Test.GtkWriter.vala.c
[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 (n_original.match(/^new/)) {
292                     var add = {
293                         name :  n_original.replace(/\-/g, '_'),
294                         type : 'ctor', //???
295                         desc : '',
296                         //desc : this.doc(ename + "."+ n_original)
297                     };
298                     this.genParams(prop,add);
299                     mlist.push(add);
300                     continue;
301                 }
302                 continue;
303                 // not sure why we need all the other ones...
304                 //if (!(flags & GIRepository.FunctionInfoFlags.IS_METHOD)) {
305                 //    continue;
306                 //}
307                 // print ('signal: ' + n_original); 
308                 var add = {
309                     name :  n_original.replace(/\-/g, '_'),
310                     type : 'function', //???
311                     desc : '', //this.doc(ename + '.' + n_original)
312                 };
313                 this.genParams(prop,add);
314                 mlist.push(add);
315             }
316             
317             
318             
319             
320             
321             
322             if (etype == GIRepository.InfoType.INTERFACE ) {
323                // print("SKIPPING PARENT - it's an interface?!?!");
324                   return;
325             }
326             
327             // parent!!?!!?
328             var pi = GIRepository.object_info_get_parent(bi);
329             
330             if (pi) {
331                 
332                    
333                 var pname = pi.get_namespace() + '.' + pi.get_name();
334                 this.getPropertiesFor(pname, 'props');
335                 
336                 
337                 elist.push.apply(elist,this.proplist[pname]['events']);
338                 plist.push.apply(plist,this.proplist[pname]['props']);
339                 ilist.push(pname);
340                 ilist.push.apply(ilist,this.proplist[pname]['inherits']);
341                 
342                 this.overrides(mlist, this.proplist[pname]['methods']);
343                 
344                 
345             } else {
346                 print("NO PARENT FOUND?");
347             }
348             
349             // implements needs to be more carefull as it could add dupes..
350             // use the parent implements list to ensure no dupes..
351             for(var i =0; i < GIRepository.object_info_get_n_interfaces(bi); i++) {
352                  
353                 var prop = GIRepository.object_info_get_interface(bi,i);
354                 var iface = prop.get_namespace() +'.'+ prop.get_name();
355                 if ( ilist.indexOf(iface) > -1) {
356                     continue;
357                 }
358                 this.getPropertiesFor(iface, 'props'); // just load one of them..
359                 ilist.push(iface);
360                 
361                 elist.push.apply(elist,this.proplist[iface]['events']);
362                 plist.push.apply(plist,this.proplist[iface]['props']);
363                 this.overrides(mlist, this.proplist[pname]['methods']);
364             }
365             function sfunc(a,b) {
366                 if (a.name == b.name) return 0;
367                 return a.name > b.name ? 1 : -1
368             }
369             plist.sort(sfunc);
370             elist.sort(sfunc);
371             mlist.sort(sfunc);
372             
373             return this.proplist[ename][type];
374             
375         },
376         genParams: function(sig, meth)
377         {
378             var args = ['self'];
379             var ret = "\n";
380             meth.ret_type = this.typeToName(GIRepository.callable_info_get_return_type(sig));
381             // might be a numbeR??
382             meth.params = [];
383             for(var a_i  =0; a_i   < GIRepository.callable_info_get_n_args(sig); a_i++) {
384                 var arg = GIRepository.callable_info_get_arg(sig, a_i);
385                 print(arg.get_name());
386                 print(arg.get_type());
387                 meth.params.push({
388                     name  : arg.get_name(),
389                     type : this.typeToName(arg.get_type(), true)
390                 });
391             }
392             
393                 
394             
395             
396         },
397         genSkel: function(sig) // should really use genParams...
398         {
399             var args = ['self'];
400             var ret = "\n";
401             var ret_type = this.typeToName(GIRepository.callable_info_get_return_type(sig));
402             // might be a numbeR??
403             if (ret_type == 'boolean') {
404                 ret = "    return false;\n";
405             }
406             for(var a_i  =0; a_i   < GIRepository.callable_info_get_n_args(sig); a_i++) {
407                 var arg = GIRepository.callable_info_get_arg(sig, a_i);
408                 
409                 args.push(arg.get_name());
410             }
411             return 'function (' + args.join(', ') + ") {\n" + ret + "}"; 
412                 
413             
414             
415         },
416         typeToName  : function (type_info, allow_iface) // find type for properties or arguments.
417         {
418             print(type_info);
419             if (type_info == 17) {
420                 return 'integer';
421             }
422              
423             var x = GIRepository.type_info_get_tag(type_info);
424             print(x);
425             var ty = GIRepository.type_tag_to_string( GIRepository.type_info_get_tag(type_info));
426             print(ty);
427            
428             if ((ty == 'void') && GIRepository.type_info_is_pointer(type_info)) {
429                 return false;
430             }
431             if (ty == 'array') {
432                 return false; // unspported   
433             }
434             if (ty != 'interface') {
435                 return ty;
436             }
437             // we can accept enum types here..
438             var interface_info = GIRepository.type_info_get_interface(type_info);
439             var interface_type = interface_info.get_type();
440             
441             if (!allow_iface && interface_type != GIRepository.InfoType.ENUM) {
442                 return false;
443             }
444             return interface_info.get_namespace() + '.' + interface_info.get_name();
445             
446         },
447         /**
448          * merge two proprety arrays' ignoring what's overrriden.
449          * 
450          */
451         
452         
453         overrides : function (top, bottom)
454         {
455             function inTop(b)
456             {
457                 return !top.every(function(t) {
458                     if (t.name == b.name) {
459                         return false;
460                     }
461                     return true;
462                 });
463             }
464             bottom.forEach(function(e) {
465                 if (!inTop(e)) {
466                     top.push(e);
467                 }
468             });
469             
470         },
471         
472         /**
473          * guess type..
474          * 
475          */
476         findType : function (data, prop, value)
477         {
478             // specials??
479             if ((prop == '|xns') || (prop == 'xtype'))  {
480                 return 'string';
481             }
482             
483             var qname = this.guessName(data);
484             if (prop[0] == '|') {
485                 prop= prop.substring(1);
486             }
487             
488             var prs = this.getPropertiesFor(qname, 'props');
489             var ret = false;
490             prs.forEach(function(e) {
491                 if (ret !== false) {
492                     return; // got it.
493                 }
494                 if (e.name == prop) {
495                     ret = e;
496                 }
497                 
498             });
499             if (!ret) {
500                 return Base.prototype.findType(data, prop,value);
501             }
502              
503             // got the type
504             return ret.type;
505         },
506         
507         findOptions : function(ename)
508         {
509             
510             var es = ename.split('.');
511             if (es.length !=2) {
512                 return Base.prototype.findOptions(ename);
513             }
514             var gi = GIRepository.Repository.get_default();
515             var bi = gi.find_by_name(es[0], es[1]);
516             var etype = GIRepository.object_info_get_type(bi);
517             if (etype != GIRepository.InfoType.ENUM) {
518                 console.log("Options not handled yet!!!");
519                 return false;
520             }
521             var ret = [];
522             // got an enum.. let's return the values..
523             for(var i =0; i < bi.get_n_values(); i++) {
524                  
525                   var prop = bi.get_value(i);
526                    
527                 
528                   ret.push( ename + '.' + prop.get_name().toUpperCase() ) 
529             }
530             return ret;
531         },
532         /**
533          * determine the packing types..
534          */
535         getDefaultPack: function(pname, cname) {
536             var list = this.getPackingList(pname,cname);
537            // console.dump(list);
538             
539             
540             if (!list.every(function(e) { return e.name != 'add'; })) {
541                 return 'add'; // add is in our list..?? what about args..?!?
542             }
543             function toRet(e) {
544                 var ret = [e.name];
545                 e.params.forEach(function(p,i) {
546                     if (ret === false) { return; } // skip broken..
547                     if (i==0) { return; } // skip first..
548                     if (p.type == 'boolean') {
549                         ret.push('false');
550                         return;
551                     }
552                     if (p.type == 'number') {
553                         ret.push('0');
554                         return;
555                     }
556                     if (p.type == 'uint') {
557                         ret.push('0');
558                         return;
559                     }
560                     ret = false; // invalid!
561                 });
562                 return ret === false ? false : ret.join(',');
563             };
564             var packret = false;
565             list.every(function(e) {
566                 
567                 packret = toRet(e);
568                 //print("DEFAULT PACK TEST : " + e.name + " : " +packret);
569                 if (packret !== false) {
570                     return false;
571                 }
572                 return true; // continue
573             });
574             //print("DEFAULT PACK: " + packret);
575             // should we do best match..?
576             return packret;
577         },
578         /**
579          * get packing list..
580          */
581         getPackingList :function (pname, cname)
582         {
583             var funcs = this.getPropertiesFor(pname,'methods');
584             //print("getPackingList : ALL FUNCS");
585             //console.dump(funcs);
586             var ret = [];
587             var _this = this;
588             // let's assume top down...
589             var inherits = [ cname ];
590             inherits.push.apply(inherits, this.getPropertiesFor(cname,'inherits'));
591             funcs.forEach(function(m) {
592                 if (m.params.length && (typeof(m.params[0].type) == 'string') &&
593                     inherits.indexOf(m.params[0].type) > -1) {
594                     ret.push(m);
595                 }
596             });
597             return ret; 
598         }
599         
600         
601     }
602 );
603