XObject.js
[gitlive] / XObject.js
1 //<script type="text/javascript">
2
3 /**
4  * XObject
5  * Yet another attempt to create a usable object construction library for seed..
6  *
7  * Extend this.. to use it's wonderful features..
8  * 
9  * 
10  * @arg xtype {String|Function} constructor or string.
11  * @arg xid {String}  (optional) id for registry
12  * @arg xns {String|Object}   (optional) namespace eg. Gtk or 'Gtk' - used with xtype.
13  * @arg items {Array}   (optional) list of child elements which will be constructed.. using XObject
14  * @arg listeners {Object}   (optional) map Gobject signals to functions
15  * @arg pack {Function|String|Array}   (optional) how this object gets added to it's parent
16  * @arg el {Object}   (optional) premade GObject
17  */
18
19 function XObject (cfg) {
20     // first apply cfg if set.
21     o =  {};
22     o.pack = o.pack || 'add';
23        
24     XObject.extend(o, cfg); // copy everything into o.
25     XObject.extend(this, o);
26     
27     // remove items.
28     this.items = [];
29     this.listeners = this.listeners || {}; 
30     
31     
32     // remove objects/functions from o, so they can be sent to the contructor.
33     for (var i in o) {
34         if ((typeof(o[i]) == 'object') || 
35             (typeof(o[i]) == 'function') || 
36             i == 'pack'
37         ) {
38             delete o[i];
39         }
40     }
41     
42     // do we need to call 'beforeInit here?'
43      
44     // handle include?
45     //if ((this.xtype == 'Include')) {
46     //    o = this.pre_registry[cls];
47     //}
48     var isSeed = typeof(Seed) != 'undefined';
49      
50     // xtype= Gtk.Menu ?? what about c_new stuff?
51     if (typeof(this.xtype) == 'function') {
52         this.el = this.el ||  new this.xtype(o);
53     }
54     
55     if (!this.el && o.xns) 
56         var NS = imports.gi[o.xns];
57         if (!NS) {
58             Seed.print('Invalid xns: ' + o.xns);
59         }
60         constructor = NS[o.xtype];
61         if (!constructor) {
62             Seed.print('Invalid xtype: ' + o.xns + '.' + o.xtype);
63         }
64         this.el  =   isSeed ? new constructor(o) : new constructor();
65     }
66     
67     
68     // register it!
69     if (o.xnsid  && o.xid) {
70         XObject.registry = XObject.registry || { };
71         XObject.registry[o.xnsid] = XObject.registry[o.xnsid] || {}; 
72         XObject.registry[o.xnsid][o.xid] = this;
73     }
74     
75     cfg.items.forEach(this.addItem, this);
76     
77     for (var i in this.listeners) {
78         this.addListener(i, this.listeners[i]);
79     }
80     // delete this.listeners ?
81     
82     
83     // do we need to call 'init here?'
84     
85 }
86
87
88
89 XObject.prototype = {
90     /**
91      * @property el {GObject} the Gtk / etc. element.
92      */
93     el : false, 
94     /*
95      * @property items {Array} list of sub elements
96      */
97     /**
98      * @property parent {XObject} parent Element
99      */
100      /**
101       * @method addItem
102       * Adds an item to the object using a new XObject
103       * uses pack property to determine how to add it.
104       * @arg cfg {Object} same as XObject constructor.
105       */
106     addItem : function(o) {
107         var item = new XObject(o);
108         
109         this.items.push(item);
110         
111          
112         if (typeof(item.pack) == 'function') {
113             // parent, child
114             item.pack.apply(o, [ o , o.items[i] ]);
115             item.parent = this;
116             return;
117         }
118         
119         
120         var pack_m = typeof(item.pack) == 'string' ?  item.pack :  item.pack.shift();
121         
122         // handle error.
123         if (pack_m && typeof(o.el[pack_m]) == 'undefined') {
124             Seed.print('pack method not available : ' + o.xtype + '.' +  pack_m);
125             return;
126         }
127         
128         
129         //Seed.print('Pack ' + o.xtype + '.'+ pack_m + '(' + o.items[i].xtype + ')');
130         // copy.
131         var args = Array.prototype.slice.call(typeof(item.pack) == 'string' ? [] : item.pack);
132         item.pack.unshift(item.el);
133         //Seed.print('args: ' + args.length);
134         if (pack_m) {
135             this.el[pack_m].apply(item.el, args);
136         }
137         
138         item.parent = this;
139         
140     },
141     /**
142       * @method addListener
143       * Connects a method to a signal. (gjs/Seed aware)
144       * 
145       * @arg sig  {String} name of signal
146       * @arg fn  {Function} handler.
147       */
148     addListener  : function(sig, fn) {
149               
150         var _li = XObject.createDelegate(fn,this);
151         // private listeners that are not copied to GTk.
152         
153         if (typeof(Seed) != 'undefined') {
154           //   Seed.print(typeof(_li));
155             this.el.signal[sig].connect(_li);
156         } else {
157             this.el.connect( sig, _li);
158         }
159              
160         
161     }
162     
163
164          
165         
166 /**
167  * Copies all the properties of config to obj.
168  *
169  * Pretty much the same as JQuery/Prototype..
170  * @param {Object} obj The receiver of the properties
171  * @param {Object} config The source of the properties
172  * @param {Object} defaults A different object that will also be applied for default values
173  * @return {Object} returns obj
174  * @member XObject extend
175  */
176
177
178 XObject.extend : function(o, c, defaults){
179     if(defaults){
180         // no "this" reference for friendly out of scope calls
181         XObject.extend(o, defaults);
182     }
183     if(o && c && typeof c == 'object'){
184         for(var p in c){
185             o[p] = c[p];
186         }
187     }
188     return o;
189 };
190
191 XObject.extend(XObject,
192 {
193     /**
194      * Copies all the properties of config to obj, if the do not exist.
195      * @param {Object} obj The receiver of the properties
196      * @param {Object} config The source of the properties
197      * @return {Object} returns obj
198      * @member Object extendIf
199      */
200
201
202     extendIf : function(o, c){
203
204         if(!o || !c || typeof c != 'object'){
205             return o;
206         }
207         for(var p in c){
208             if (typeof(o[p]) != 'undefined') {
209                 continue;
210             }
211             o[p] = c[p];
212         }
213         return o;
214     },
215
216  
217
218     /**
219      * Extends one class with another class and optionally overrides members with the passed literal. This class
220      * also adds the function "override()" to the class that can be used to override
221      * members on an instance.
222      *
223      * usage:
224      * MyObject = Object.define(
225      *     function(...) {
226      *          ....
227      *     },
228      *     parentClass, // or Object
229      *     {
230      *        ... methods and properties.
231      *     }
232      * });
233      * @param {Function} constructor The class inheriting the functionality
234      * @param {Object} superclass The class being extended
235      * @param {Object} overrides (optional) A literal with members
236      * @return {Function} constructor (eg. class
237      * @method define
238      */
239     define : function(){
240         // inline overrides
241         var io = function(o){
242             for(var m in o){
243                 this[m] = o[m];
244             }
245         };
246         return function(sb, sp, overrides) {
247             if (typeof(sp) == 'undefined') {
248                 // error condition - try and dump..
249                 throw "Missing superclass: when applying: " + sb
250             }
251
252             var F = function(){}, sbp, spp = sp.prototype;
253             F.prototype = spp;
254             sbp = sb.prototype = new F();
255             sbp.constructor=sb;
256             sb.superclass=spp;
257
258             // extends Object.
259             if(spp.constructor == Object.prototype.constructor){
260                 spp.constructor=sp;
261             }
262
263             sb.override = function(o){
264                 Object.extend(sb.prototype, o);
265             };
266             sbp.override = io;
267             Object.extend(sb.prototype, overrides);
268             return sb;
269         };
270     }(),
271
272          
273     /**
274      * returns a list of keys of the object.
275      * @param {Object} obj object to inspect
276      * @return {Array} returns list of kyes
277      * @member Object keys
278      */
279     keys : function(o)
280     {
281         var ret = [];
282         for(var i in o) {
283             ret.push[i];
284         }
285         return ret;
286     }
287 });