JsRender/Roo.js
[app.Builder.js] / Palete / Gtk.js
1 //<Script type="text/javascript">
2  
3 Gio = imports.gi.Gio;
4 GIRepository  = imports.gi.GIRepository;
5 GObject= imports.gi.GObject;
6 xml     = imports.libxml;
7 console = imports.console;
8 XObject = imports.XObject.XObject;
9
10 Base = imports.Palete.Base.Base;
11 File = imports.File.File;
12 //----------------------- our roo verison
13
14
15
16
17 Gtk = XObject.define(
18     function(cfg) {
19         
20        
21         // various loader methods..
22           this.map = [];
23         this.load();
24         this.proplist = {};
25         this.comments = { }; 
26         // no parent...
27         
28        
29     },
30     Base,
31     {
32         name : 'Gtk',
33         
34         load: function () {
35                 
36          
37         
38             var data = File.read(__script_path__ +'/GtkUsage.txt');
39           // print(data);
40             data  = data.split(/\n/g);
41             var state = 0;
42             var cfg = [];
43             var left = [];
44             var right = [];
45             
46             data.forEach( function(d) {
47                 if (!d.length || d.match(/^\s+$/) || d.match(/^\s*\//)) { //empty
48                     return;
49                 }
50                 if (d.match(/^left:/)) { 
51                     state = 1;
52                     if (left.length ){
53                         
54                         cfg.push({
55                             left : left,
56                             right: right
57                         });
58                         }
59                     left = [];
60                     right = [];
61                     return;
62                 }
63                 if (d.match(/^right:/)) { 
64                     state = 2;
65                     return;
66                 }
67                 if (state == 1) {
68                     left.push(d.replace(/\s+/g, ''));
69                     return;
70                 }
71                 right.push(d.replace(/\s+/g, ''));
72                 //Seed.quit();
73                
74             }); 
75             if (left.length ){
76                         
77                 cfg.push({
78                     left : left,
79                     right: right
80                 });
81             }
82             this.map = cfg;
83              
84         },
85         
86         
87         commentLoad : function(ns)
88         {
89              
90             if (typeof(this.comments[ns]) != 'undefined') {
91                 return;
92             }
93
94             console.log("LOAD DOCS: " + ns);
95             var gi = GIRepository.Repository.get_default();
96             var ver = gi.get_version(ns);
97             if (!ver) {
98                 this.comments[ns] = {};
99                 return;
100             }
101             var ret = { };
102
103             // no idea why this is broken on my build system.
104             function getAttribute(n, name){
105                 var properties = n.properties;
106                 while (properties){
107                     if (properties.name == name)
108                          return properties.children.content;
109                      properties = properties.next
110                 }
111                 return null;
112             }
113                  
114          
115             function walk(element, path) {
116                  
117                  
118                 if (!element) {
119                     return;
120                 }
121                 
122                 var n =  getAttribute(element, 'name') ;
123                 //console.log("WALK" + n);
124                 if (element.name == 'signal') {
125                     path += '.signal';
126                 } 
127                 if (n) {
128                     path += path.length ? '.' : '';
129                     path += n;
130                 }
131                 if (element.name == 'return-value') {
132                     path += '.return-value';
133                 }
134                 
135                 
136              
137                 var d =   getAttribute(element,'doc');
138                 if (d) {
139                  //   Seed.print(path + ':' + d);
140                     ret[path] = d;
141                 }
142                 
143                 var child = element.children;
144
145                 while (child){
146                     //console.log(child.tag);
147                     if (child.type == "element"){
148                         walk (child, path);
149                     }
150                     child = child.next;
151                 }
152             }
153             
154             var pth = GIRepository.Repository.get_search_path ();
155             
156             
157             var gir_path = pth[0].replace(/lib\/girepository-1.0/, 'share\/gir-1.0');
158            
159             
160             //console.log(fn);
161             var  fn = gir_path + '/'+ ns + '-' + ver + '.gir';
162            // console.log(fn);
163             
164             if (!File.exists(fn)) {
165                 console.log('missing docc file ' + fn);
166                 this.comments[ns] = {};
167                 
168                 return;
169             }
170             var doc = xml.parseFile(fn);
171             //console.log("xmldoc?" + doc);
172             walk (doc.root, '');
173             //console.dump(ret);
174             this.comments[ns] = ret;
175             //console.dump(ret);
176
177         },
178        
179         
180         doc : function(what) {
181             var ns = what.split('.').shift();
182             this.commentLoad(ns);
183             return typeof(this.comments[ns][what]) == 'undefined' ?  '' : this.comments[ns][what];
184         },
185   
186         getPropertiesFor: function(ename, type)
187         {
188             //print("Loading for " + ename);
189             
190             if (typeof(this.proplist[ename]) != 'undefined') {
191                 //print("using cache");
192                 return this.proplist[ename][type];
193             }
194             // use introspection to get lists..
195             var gi = GIRepository.Repository.get_default();
196             var es = ename.split('.');
197             
198             imports.gi[es[0]];
199             var bi = gi.find_by_name(es[0], es[1]);
200             
201             if (!bi) {
202                 print("COULND NOT FIND BY NAME");
203                 return [];
204             }
205             var etype = bi.get_type();;
206             var meth = etype == GIRepository.InfoType.INTERFACE ?
207                 [ 
208                     'interface_info_get_n_properties',
209                     'interface_info_get_property',
210                     'interface_info_get_n_signals',
211                     'interface_info_get_signal',
212                     'interface_info_get_n_methods',
213                     'interface_info_get_method'
214                 ] : [ 
215                     'object_info_get_n_properties',
216                     'object_info_get_property',
217                     'object_info_get_n_signals',
218                     'object_info_get_signal',
219                     'object_info_get_n_methods',
220                     'object_info_get_method'
221                 ]; 
222             
223             
224             this.proplist[ename] = {}
225             this.proplist[ename]['props'] = [];
226             this.proplist[ename]['events'] = [];
227             this.proplist[ename]['methods'] = [];
228             this.proplist[ename]['inherits']= [];
229             
230             var plist = this.proplist[ename]['props'] ;
231             var elist = this.proplist[ename]['events'];
232             var mlist = this.proplist[ename]['methods'];
233             var ilist = this.proplist[ename]['inherits'];
234              /*
235              we need...
236              p.name
237             p.type
238             p.desc
239             p.sig */
240             
241             // properties.. -- and parent ones...!!!
242             for (var i =0;i <  GIRepository[meth[0]](bi); i++) {
243                 var prop = GIRepository[meth[1]](bi,i);  
244                 var n_original =  prop.get_name();
245                 
246                 var flags =  GIRepository.property_info_get_flags(prop); // check for readonly..
247                 
248                 
249                 var ty = this.typeToName(GIRepository.property_info_get_type(prop));
250                 var flags = GIRepository.property_info_get_flags(prop);
251                 print (n_original +":"+ ty);
252                 if (ty === false) {
253                     continue;
254                 }
255                 var add = {
256                      name :  n_original.replace(/\-/g, '_'),
257                      type :  ty,
258                      desc : this.doc(ename + '.' + n_original),
259                      sig : '',
260                      ctor_only : (flags  & GObject.ParamFlags.CONSTRUCT_ONLY) > 0
261                 }
262                 plist.push(add)
263             }
264            
265            
266            
267            
268            
269             // signals..
270             
271             for (var i =0;i <  GIRepository[meth[2]](bi); i++) {
272                 var prop =GIRepository[meth[3]](bi,i);  
273                 var n_original =  prop.get_name();
274                 // print ('signal: ' + n_original); 
275                 var add = {
276                     name :  n_original.replace(/\-/g, '_'),
277                     type : 'function', //???
278                     desc : this.doc(ename + '.signal.' + n_original),
279                     sig  : this.genSkel(prop) // fixme..
280                 }
281                 elist.push(add);
282             }
283             // methods
284             
285             for (var i =0;i <  GIRepository[meth[4]](bi); i++) {
286                 var prop = GIRepository[meth[5]](bi,i);  
287                 var n_original =  prop.get_name();
288                 print(ename +": ADD method: " + n_original );
289                 var flags = GIRepository.property_info_get_flags(prop);
290                 
291                 if (flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR) {
292                     var add = {
293                         name :  n_original.replace(/\-/g, '_'),
294                         type : 'ctor', //???
295                         desc : this.doc(ename + '.signal.' + n_original)
296                     };
297                     this.genParams(prop,add);
298                     mlist.push(add);
299                     continue;
300                 }
301                 if (!(flags & GIRepository.FunctionInfoFlags.IS_METHOD)) {
302                     continue;
303                 }
304                 // print ('signal: ' + n_original); 
305                 var add = {
306                     name :  n_original.replace(/\-/g, '_'),
307                     type : 'function', //???
308                     desc : this.doc(ename + '.signal.' + n_original)
309                 };
310                 this.genParams(prop,add);
311                 mlist.push(add);
312             }
313             
314             
315             
316             
317             
318             
319             if (etype == GIRepository.InfoType.INTERFACE ) {
320                // print("SKIPPING PARENT - it's an interface?!?!");
321                   return;
322             }
323             
324             // parent!!?!!?
325             var pi = GIRepository.object_info_get_parent(bi);
326             
327             if (pi) {
328                 
329                    
330                 var pname = pi.get_namespace() + '.' + pi.get_name();
331                 this.getPropertiesFor(pname, 'props');
332                 
333                 
334                 elist.push.apply(elist,this.proplist[pname]['events']);
335                 plist.push.apply(plist,this.proplist[pname]['props']);
336                 ilist.push(pname);
337                 ilist.push.apply(ilist,this.proplist[pname]['inherits']);
338                 
339                 this.overrides(mlist, this.proplist[pname]['methods']);
340                 
341                 
342             } else {
343                 print("NO PARENT FOUND?");
344             }
345             
346             // implements needs to be more carefull as it could add dupes..
347             // use the parent implements list to ensure no dupes..
348             for(var i =0; i < GIRepository.object_info_get_n_interfaces(bi); i++) {
349                  
350                 var prop = GIRepository.object_info_get_interface(bi,i);
351                 var iface = prop.get_namespace() +'.'+ prop.get_name();
352                 if ( ilist.indexOf(iface) > -1) {
353                     continue;
354                 }
355                 this.getPropertiesFor(iface, 'props'); // just load one of them..
356                 ilist.push(iface);
357                 
358                 elist.push.apply(elist,this.proplist[iface]['events']);
359                 plist.push.apply(plist,this.proplist[iface]['props']);
360                 this.overrides(mlist, this.proplist[pname]['methods']);
361             }
362             function sfunc(a,b) {
363                 if (a.name == b.name) return 0;
364                 return a.name > b.name ? 1 : -1
365             }
366             plist.sort(sfunc);
367             elist.sort(sfunc);
368             mlist.sort(sfunc);
369             
370             return this.proplist[ename][type];
371             
372         },
373         genParams: function(sig, meth)
374         {
375             var args = ['self'];
376             var ret = "\n";
377             meth.ret_type = this.typeToName(GIRepository.callable_info_get_return_type(sig));
378             // might be a numbeR??
379             meth.params = [];
380             for(var a_i  =0; a_i   < GIRepository.callable_info_get_n_args(sig); a_i++) {
381                 var arg = GIRepository.callable_info_get_arg(sig, a_i);
382                  
383                 meth.params.push({
384                     name  : arg.get_name(),
385                     type : this.typeToName(arg.get_type(), true)
386                 });
387             }
388             
389                 
390             
391             
392         },
393         genSkel: function(sig) // should really use genParams...
394         {
395             var args = ['self'];
396             var ret = "\n";
397             var ret_type = this.typeToName(GIRepository.callable_info_get_return_type(sig));
398             // might be a numbeR??
399             if (ret_type == 'boolean') {
400                 ret = "    return false;\n";
401             }
402             for(var a_i  =0; a_i   < GIRepository.callable_info_get_n_args(sig); a_i++) {
403                 var arg = GIRepository.callable_info_get_arg(sig, a_i);
404                 
405                 args.push(arg.get_name());
406             }
407             return 'function (' + args.join(', ') + ") {\n" + ret + "}"; 
408                 
409             
410             
411         },
412         typeToName  : function (type_info, allow_iface) // find type for properties or arguments.
413         {
414            var ty = GIRepository.type_tag_to_string( GIRepository.type_info_get_tag(type_info));
415            
416             if ((ty == 'void') && GIRepository.type_info_is_pointer(type_info)) {
417                 return false;
418             }
419             if (ty == 'array') {
420                 return false; // unspported   
421             }
422             if (ty != 'interface') {
423                 return ty;
424             }
425             // we can accept enum types here..
426             var interface_info = GIRepository.type_info_get_interface(type_info);
427             var interface_type = interface_info.get_type();
428             
429             if (!allow_iface && interface_type != GIRepository.InfoType.ENUM) {
430                 return false;
431             }
432             return interface_info.get_namespace() + '.' + interface_info.get_name();
433             
434         },
435         /**
436          * merge two proprety arrays' ignoring what's overrriden.
437          * 
438          */
439         
440         
441         overrides : function (top, bottom)
442         {
443             function inTop(b)
444             {
445                 return !top.every(function(t) {
446                     if (t.name == b.name) {
447                         return false;
448                     }
449                     return true;
450                 });
451             }
452             bottom.forEach(function(e) {
453                 if (!inTop(e)) {
454                     top.push(e);
455                 }
456             });
457             
458         },
459         
460         /**
461          * guess type..
462          * 
463          */
464         findType : function (data, prop, value)
465         {
466             // specials??
467             if ((prop == '|xns') || (prop == 'xtype'))  {
468                 return 'string';
469             }
470             
471             var qname = this.guessName(data);
472             if (prop[0] == '|') {
473                 prop= prop.substring(1);
474             }
475             
476             var prs = this.getPropertiesFor(qname, 'props');
477             var ret = false;
478             prs.forEach(function(e) {
479                 if (ret !== false) {
480                     return; // got it.
481                 }
482                 if (e.name == prop) {
483                     ret = e;
484                 }
485                 
486             });
487             if (!ret) {
488                 return Base.prototype.findType(data, prop,value);
489             }
490              
491             // got the type
492             return ret.type;
493         },
494         
495         findOptions : function(ename)
496         {
497             
498             var es = ename.split('.');
499             if (es.length !=2) {
500                 return Base.prototype.findOptions(ename);
501             }
502             var gi = GIRepository.Repository.get_default();
503             var bi = gi.find_by_name(es[0], es[1]);
504             var etype = GIRepository.object_info_get_type(bi);
505             if (etype != GIRepository.InfoType.ENUM) {
506                 console.log("Options not handled yet!!!");
507                 return false;
508             }
509             var ret = [];
510             // got an enum.. let's return the values..
511             for(var i =0; i < bi.get_n_values(); i++) {
512                  
513                   var prop = bi.get_value(i);
514                    
515                 
516                   ret.push( ename + '.' + prop.get_name().toUpperCase() ) 
517             }
518             return ret;
519         },
520         /**
521          * determine the packing types..
522          */
523         getDefaultPack: function(pname, cname) {
524             var list = this.getPackingList(pname,cname);
525            // console.dump(list);
526             
527             
528             if (!list.every(function(e) { return e.name != 'add'; })) {
529                 return 'add'; // add is in our list..?? what about args..?!?
530             }
531             function toRet(e) {
532                 var ret = [e.name];
533                 e.params.forEach(function(p,i) {
534                     if (ret === false) { return; } // skip broken..
535                     if (i==0) { return; } // skip first..
536                     if (p.type == 'boolean') {
537                         ret.push('false');
538                         return;
539                     }
540                     if (p.type == 'number') {
541                         ret.push('0');
542                         return;
543                     }
544                     if (p.type == 'uint') {
545                         ret.push('0');
546                         return;
547                     }
548                     ret = false; // invalid!
549                 });
550                 return ret === false ? false : ret.join(',');
551             };
552             var packret = false;
553             list.every(function(e) {
554                 
555                 packret = toRet(e);
556                 //print("DEFAULT PACK TEST : " + e.name + " : " +packret);
557                 if (packret !== false) {
558                     return false;
559                 }
560                 return true; // continue
561             });
562             //print("DEFAULT PACK: " + packret);
563             // should we do best match..?
564             return packret;
565         },
566         /**
567          * get packing list..
568          */
569         getPackingList :function (pname, cname)
570         {
571             var funcs = this.getPropertiesFor(pname,'methods');
572             //print("getPackingList : ALL FUNCS");
573             //console.dump(funcs);
574             var ret = [];
575             var _this = this;
576             // let's assume top down...
577             var inherits = [ cname ];
578             inherits.push.apply(inherits, this.getPropertiesFor(cname,'inherits'));
579             funcs.forEach(function(m) {
580                 if (m.params.length && (typeof(m.params[0].type) == 'string') &&
581                     inherits.indexOf(m.params[0].type) > -1) {
582                     ret.push(m);
583                 }
584             });
585             return ret; 
586         }
587         
588         
589     }
590 );
591