ffe8a79d5ffa299a1a6ca5aaa451bf0e97c90d32
[roobuilder] / src / JsRender / NodeToVala.vala
1 /**
2  * 
3  * Code to convert node tree to Vala...
4  * 
5  * usage : x = (new JsRender.NodeToVala(node)).munge();
6  * 
7  * Fixmes?
8  *
9  *  pack - can we come up with a replacement?
10      - parent.child == child_widget -- actually uses getters and effectively does 'add'?
11        (works on most)?
12     
13      
14  * args  -- vala constructor args (should really only be used at top level - we did use it for clutter originally(
15  * ctor  -- different ctor argument
16  
17  * 
18  
19  * 
20  * 
21 */
22
23
24
25
26 public class JsRender.NodeToVala : Object {
27
28         Node node;
29
30         int depth;
31         string inpad;
32         string pad;
33         string ipad;
34         string cls;  // node fqn()
35         string xcls;
36         
37         string ret;
38         
39         int cur_line;
40
41         Gee.ArrayList<string> ignoreList;
42         Gee.ArrayList<string> ignoreWrappedList; 
43         Gee.ArrayList<string> myvars;
44         Gee.ArrayList<Node> vitems; // top level items
45         NodeToVala top;
46         JsRender file;
47         int pane_number = 0;
48         
49         /* 
50          * ctor - just initializes things
51          * - wraps a render node 
52          */
53         public NodeToVala( JsRender file,  Node node,  int depth, NodeToVala? parent) 
54         {
55
56                 
57                 this.node = node;
58                 this.depth = depth;
59                 this.inpad = string.nfill(depth > 0 ? 4 : 0, ' ');
60                 this.pad = this.inpad + "    ";
61                 this.ipad = this.inpad + "        ";
62                 this.cls = node.xvala_cls;
63                 this.xcls = node.xvala_xcls;
64                 this.ret = "";
65                 this.cur_line = parent == null ? 0 : parent.cur_line;
66                 
67                 
68                 this.top = parent == null ? this : parent.top;
69                 this.ignoreList = new Gee.ArrayList<string>();
70                 this.ignoreWrappedList  = new Gee.ArrayList<string>();
71                 this.myvars = new Gee.ArrayList<string>();
72                 this.vitems = new Gee.ArrayList<Node>();
73                 this.file = file;
74                 
75                 // initialize line data..
76                 node.line_start = this.cur_line;
77                 node.line_end  = this.cur_line;
78                 node.lines = new Gee.ArrayList<int>();
79                 node.line_map = new Gee.HashMap<int,string>();
80                 if (parent == null) {
81                         node.node_lines = new Gee.ArrayList<int>();
82                         node.node_lines_map = new Gee.HashMap<int,Node>();
83                  }
84                 
85         }
86
87         public int vcnt = 0;
88         string toValaNS(Node item)
89         {
90                 var ns = item.get("xns") ;
91                 //if (ns == "GtkSource") {  technically on Gtk3?
92                 //      return "Gtk.Source";
93                 //}
94                 return ns + ".";
95         }
96         public void  toValaName(Node item, int depth =0) 
97         {
98                 this.vcnt++;
99
100                 var ns =  this.toValaNS(item) ;
101                 var cls = ns + item.get("xtype");
102                 
103                 
104                 item.xvala_cls = cls;
105                 
106                 
107                 string id = item.get("id").length > 0 ?
108                         item.get("id") :  "%s%d".printf(item.get("xtype"), this.vcnt);
109
110                 
111                 
112                 
113                 if (id[0] == '*' || id[0] == '+') {
114                         item.xvala_xcls = "Xcls_" + id.substring(1);
115                 } else {
116                         item.xvala_xcls = "Xcls_" + id;
117                 }
118                         
119                 
120                 item.xvala_id =  id;
121                 if (depth > 0) {                        
122                         this.vitems.add(item);
123                         
124                 // setting id on top level class changes it classname..                 
125                 // oddly enough we havent really thought about namespacing here.
126                 
127                 } else if (!item.props.has_key("id")) { 
128                         // use the file name..
129                         item.xvala_xcls =  this.file.name;
130                         // is id used?
131                         item.xvala_id = this.file.name;
132
133                 }
134                 // loop children..
135                                                                                                                            
136                 if (item.items.size < 1) {
137                         return;
138                 }
139                 for(var i =0;i<item.items.size;i++) {
140                         this.toValaName(item.items.get(i), depth+1);
141                 }
142                                           
143         }
144         /**
145          *  Main entry point to convert a file into a string..
146          */
147         public static string mungeFile(JsRender file) 
148         {
149                 if (file.tree == null) {
150                         return "";
151                 }
152
153                 var n = new NodeToVala(file, file.tree, 0, null);
154                 n.file = file;
155                 n.vcnt = 0;
156                 
157                 n.toValaName(file.tree);
158                 
159                 
160                 GLib.debug("top cls %s / xlcs %s\n ",file.tree.xvala_cls,file.tree.xvala_cls); 
161                 n.cls = file.tree.xvala_cls;
162                 n.xcls = file.tree.xvala_xcls;
163                 return n.munge();
164                 
165
166         }
167         
168         public string munge ( )
169         {
170                 //return this.mungeToString(this.node);
171
172                 this.ignore("pack");
173                 this.ignore("init");
174                 this.ignore("xns");
175                 this.ignore("xtype");
176                 this.ignore("id");
177                 
178                 this.globalVars();
179                 this.classHeader();
180                 this.addSingleton();
181                 this.addTopProperties();
182                 this.addMyVars();
183                 this.addPlusProperties();
184                 this.addValaCtor();
185                 this.addUnderThis();
186                 this.addWrappedCtor();
187
188                 this.addInitMyVars();
189                 this.addWrappedProperties();
190                 this.addChildren();
191                 this.addAutoShow(); // autoshow menuitems
192                 
193                 this.addInit();
194                 this.addListeners();
195                 this.addEndCtor();
196                 this.addUserMethods();
197                 this.iterChildren();
198                 
199                 return this.ret;
200                  
201                          
202         } 
203         public string mungeChild(  Node cnode)
204         {
205                 var x = new  NodeToVala(this.file, cnode,  this.depth+1, this);
206                 return x.munge();
207         }
208         public void addLine(string str= "")
209         {
210                 this.cur_line++;
211                 //this.ret += "/*%d*/ ".printf(this.cur_line-1) + str + "\n";
212                 this.ret += str + "\n";
213         }
214         public void addMultiLine(string str= "")
215         {
216                  
217                 this.cur_line += str.split("\n").length;
218                 //this.ret +=  "/*%d*/ ".printf(l) + str + "\n";
219                 this.ret +=   str + "\n";
220         }
221          
222         
223         public void globalVars()
224         {
225                 if (this.depth > 0) {
226                         return;
227                 }
228                 // Global Vars..??? when did this get removed..?
229                 //this.ret += this.inpad + "public static " + this.xcls + "  " + this.node.xvala_id+ ";\n\n";
230
231                 this.addLine(this.inpad + "static " + this.xcls + "  _" + this.node.xvala_id+ ";");
232                 this.addLine();
233                    
234         }
235
236         void classHeader()
237         {
238                            
239                 // class header..
240                 // class xxx {   WrappedGtk  el; }
241                 this.node.line_start = this.cur_line;
242                 
243                 this.top.node.setNodeLine(this.cur_line, this.node);
244                 
245                 this.addLine(inpad + "public class " + this.xcls + " : Object");
246                 this.addLine(this.inpad + "{");
247                 
248                  
249                 this.addLine(this.pad + "public " + this.cls + " el;");
250  
251                 this.addLine(this.pad + "private " + this.top.xcls + "  _this;");
252                 this.addLine();
253                         
254                         
255                         
256                         // singleton
257         }
258         void addSingleton() 
259         {
260                 if (depth > 0) {
261                         return;
262                 }
263                 this.addLine(pad + "public static " + xcls + " singleton()");
264                 this.addLine(this.pad + "{");
265                 this.addLine(this.ipad +    "if (_" + this.node.xvala_id  + " == null) {");
266                 this.addLine(this.ipad +    "    _" + this.node.xvala_id + "= new "+ this.xcls + "();");  // what about args?
267                 this.addLine(this.ipad +    "}");
268                 this.addLine(this.ipad +    "return _" + this.node.xvala_id +";");
269                 this.addLine(this.pad + "}");
270         }
271                         
272         /**
273          * when ID is used... on an element, it registeres a property on the top level...
274          * so that _this.ID always works..
275          * 
276          */
277         void addTopProperties()
278         {
279                 if (this.depth > 0) {
280                         return;
281                 }
282                 // properties - global..??
283
284                 var iter = this.vitems.list_iterator();
285                 while(iter.next()) {
286                         var n = iter.get();
287
288                          
289                         if (!n.props.has_key("id") || n.xvala_id.length < 0) {
290                                 continue;
291                                 
292                         }
293                         if (n.xvala_id[0] == '*') {
294                                 continue;
295                         }
296                         if (n.xvala_id[0] == '+') {
297                                 continue;
298                         }
299                         this.addLine(this.pad + "public " + n.xvala_xcls + " " + n.xvala_id + ";");
300                         
301                 }
302                                 
303         }
304         /**
305          * create properties that are not 'part of the wrapped element.
306          * 
307          * 
308          */
309  
310         void addMyVars()
311         {
312                 GLib.debug("callinged addMhyVars");
313                 
314                 this.addLine();
315                 this.addLine(this.ipad + "// my vars (def)");
316                         
317
318  
319                 var cls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn());
320                    
321                 if (cls == null) {
322                         GLib.debug("Gir factory failed to find class %s", this.node.fqn());
323                         
324                         //return;
325                 }
326           
327                 
328                         // Key = TYPE:name
329                 var iter = this.node.props.map_iterator();
330                 while (iter.next()) {
331                          
332                         var prop = iter.get_value();
333                         
334                         if (this.shouldIgnore(prop.name)) {
335                                 continue;
336                         }
337
338                         // user defined method
339                         if (prop.ptype == NodePropType.METHOD) {
340                                 continue;
341                         }
342                         if (prop.ptype == NodePropType.SPECIAL) {
343                                 continue;
344                         }
345                                 
346                         if (prop.ptype == NodePropType.SIGNAL) {
347                                 this.node.setLine(this.cur_line, "p", prop.name);
348                                 this.addLine(this.pad + "public signal " + prop.rtype + " " + prop.name  + " "  + prop.val + ";");
349                                 
350                                 this.ignore(prop.name);
351                                 continue;
352                         }
353                         
354                         GLib.debug("Got myvars: %s", prop.name.strip());
355                         
356                         if (prop.rtype.strip().length < 1) {
357                                 continue;
358                         }
359                         
360                         // is it a class property...
361                         if (cls != null && cls.props.has_key(prop.name) && prop.ptype != NodePropType.USER) {
362                                 continue;
363                         }
364                         
365                         this.myvars.add(prop.name);
366                         prop.start_line = this.cur_line;
367                         
368                         this.node.setLine(this.cur_line, "p", prop.name);
369                         
370                         this.addLine(this.pad + "public " + prop.rtype + " " + prop.name + ";"); // definer - does not include value.
371
372
373                         prop.end_line = this.cur_line;                          
374                         this.ignore(prop.name);
375                         
376                                 
377                 }
378         }
379         
380         // if id of child is '+' then it's a property of this..
381         void addPlusProperties()
382         {
383                 if (this.node.items.size < 1) {
384                         return;
385                 }
386                 var iter = this.node.items.list_iterator();
387                 while (iter.next()) {
388                         var ci = iter.get();
389                                 
390                         if (ci.xvala_id[0] != '+') {
391                                 continue; // skip generation of children?
392                                 
393                         }
394                          
395                         this.addLine(this.pad + "public " + ci.xvala_xcls + " " + ci.xvala_id.substring(1) + ";");
396                                            
397                         
398                 }
399         }
400         /**
401          * add the constructor definition..
402          */
403         void addValaCtor()
404         {
405                         
406                 
407                 // .vala props.. 
408                 
409  
410                 var cargs_str = "";
411                 // ctor..
412                 this.addLine();
413                 this.addLine(this.pad + "// ctor");
414                 
415                 if (this.node.has("* args")) {
416                         // not sure what this is supposed to be ding..
417                 
418                         cargs_str =  this.node.get("* args");
419                         //var ar = this.node.get("* args");.split(",");
420                         //for (var ari =0; ari < ar.length; ari++) {
421                                 //      cargs +=  (ar[ari].trim().split(" ").pop();
422                                   // }
423                         }
424         
425                 if (this.depth < 1) {
426                  
427                         // top level - does not pass the top level element..
428                         this.addLine(this.pad + "public " + this.xcls + "(" +  cargs_str +")");
429                         this.addLine(this.pad + "{");
430                 } else {
431                         if (cargs_str.length > 0) {
432                                 cargs_str = ", " + cargs_str;
433                         }
434                         // for sub classes = we passs the top level as _owner
435                         this.addLine(this.pad + "public " + this.xcls + "(" +  this.top.xcls + " _owner " + cargs_str + ")");
436                         this.addLine(this.pad + "{");
437                 }
438                 
439
440         }
441         /**
442          *  make sure _this is defined..
443          */
444         void addUnderThis() 
445         {
446                 // public static?
447                 if (depth < 1) {
448                         this.addLine( this.ipad + "_this = this;");
449                         return;
450                 }
451                 // for non top level = _this point to owner, and _this.ID is set
452                 
453                 this.addLine( this.ipad + "_this = _owner;");
454
455                 if (this.node.props.has_key("id")
456                         &&
457                         this.node.xvala_id != "" 
458                         && 
459                         this.node.xvala_id[0] != '*' 
460                         && 
461                         this.node.xvala_id[0] != '+' 
462                         ) {
463                                 this.addLine( this.ipad + "_this." + node.xvala_id  + " = this;");
464                    
465                 }
466                          
467         }
468         /**
469          * Initialize this.el to point to the wrapped element.
470          * 
471          * 
472          */
473
474         void addWrappedCtor()
475         {
476                 // wrapped ctor..
477                 // this may need to look up properties to fill in the arguments..
478                 // introspection does not workk..... - as things like gtkmessagedialog
479                 /*
480                 if (cls == 'Gtk.Table') {
481
482                 var methods = this.palete.getPropertiesFor(cls, 'methods');
483
484                 print(JSON.stringify(this.palete.proplist[cls], null,4));
485                 Seed.quit();
486                 }
487                 */
488                 
489                 // ctor can still override.
490                 if (this.node.has("* ctor")) {
491                         this.node.setLine(this.cur_line, "p", "* ctor");
492                         this.addLine(this.ipad + "this.el = " + this.node.get("* ctor")+ ";");
493                         return;
494                 }
495                 
496                 this.node.setLine(this.cur_line, "p", "* xtype");;
497                 
498                 // is the wrapped element a struct?
499                 
500                 var ncls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn());
501                 if (ncls != null && ncls.nodetype == "Struct") {
502                         // we can use regular setters to apply the values.
503                         this.addLine(this.ipad + "this.el = " + this.node.fqn() + "();");
504                         return;
505                 
506                 
507                 }
508
509                 var ctor = ".new";
510                 var args_str = "";
511                 switch(this.node.fqn()) {
512                 
513                         case "Gtk.ComboBox":
514                                 var is_entry = this.node.has("has_entry") && this.node.get_prop("has_entry").val.down() == "true";
515                                 if (!is_entry) { 
516                                         break; // regular ctor.
517                                 }
518                                 this.ignoreWrapped("has_entry");
519                                 ctor = ".with_entry";
520                                 break;
521                                 
522                 
523                         case "Gtk.ListStore":
524                         case "Gtk.TreeStore":
525
526                                 // not sure if this works.. otherwise we have to go with varargs and count + vals...
527                                 if (this.node.has("* types")) {
528                                         args_str = this.node.get_prop("* types").val;
529                                 }
530                                 if (this.node.has("n_columns") && this.node.has("columns")) { // old value?
531                                         args_str = " { " + this.node.get_prop("columns").val + " } ";
532                                         this.ignoreWrapped("columns");
533                                         this.ignoreWrapped("n_columns");
534                                 }
535                                 
536                                 this.addLine(this.ipad + "this.el = new " + this.node.fqn() + ".newv( " + args_str + " );");
537                                 return;
538  
539                                 
540                         case "Gtk.LinkButton": // args filled with values.
541                                 if (this.node.has("label")) {
542                                         ctor = ".with_label";    
543                                 }
544                                 break;
545                                 
546                         default:
547                                 break;
548                 }
549                 var default_ctor = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn() + ctor);              
550                  
551                 
552                 // use the default ctor - with arguments (from properties)
553                 
554                 if (default_ctor != null && default_ctor.paramset != null && default_ctor.paramset.params.size > 0) {
555                         string[] args  = {};
556                         var iter = default_ctor.paramset.params.list_iterator();
557                         while (iter.next()) {
558                                 var n = iter.get().name;
559                             GLib.debug("building CTOR ARGS: %s, %s", n, iter.get().is_varargs ? "VARARGS": "");
560                                 if (n == "___") { // for some reason our varargs are converted to '___' ...
561                                         continue;
562                                 }
563                                 
564                                 if (!this.node.has(n)) {  // node does not have a value
565                                         
566                                          
567                                         if (iter.get().type.contains("int")) {
568                                                 args += "0";
569                                                 continue;
570                                         }
571                                         if (iter.get().type.contains("float")) {
572                                                 args += "0f";
573                                                 continue;
574                                         }
575                                         if (iter.get().type.contains("bool")) {
576                                                 args += "true"; // always default to true?
577                                                 continue;
578                                         }
579                                         // any other types???
580                                         
581                                         args += "null";
582                                         continue;
583                                 }
584                                 this.ignoreWrapped(n);
585                                 this.ignore(n);
586                                 
587                                 var v = this.node.get(n);
588
589                                 if (iter.get().type == "string") {
590                                         v = "\"" +  v.escape("") + "\"";
591                                 }
592                                 if (v == "TRUE" || v == "FALSE") {
593                                         v = v.down();
594                                 }
595
596                                 
597                                 args += v;
598
599                         }
600                         this.node.setLine(this.cur_line, "p", "* xtype");
601                         
602                         this.addLine(this.ipad + "this.el = new " + this.node.fqn() + "( "+ string.joinv(", ",args) + " );") ;
603                         return;
604                         
605                 }
606                 // default ctor with no params..
607                  if (default_ctor != null && ctor != ".new" ) {
608                         this.node.setLine(this.cur_line, "p", "* xtype");
609                         
610                         this.addLine(this.ipad + "this.el = new " + this.node.fqn() + ctor + "(  );") ;
611                         return;
612                  }
613                 
614                 
615                 this.addLine(this.ipad + "this.el = new " + this.node.fqn() + "(" + args_str + ");");
616                 
617                 
618
619                         
620         }
621         public static Gee.ArrayList<string> menuitem_children = null;
622         
623         void addAutoShow()
624         {
625                 if (menuitem_children == null) {
626                         menuitem_children = new Gee.ArrayList<string>();
627                         menuitem_children.add("Gtk.MenuItem");
628                         var gir = this.file.project.palete.getClass("Gtk.MenuItem");
629                         if (gir != null) {
630                             foreach(var impl in gir.implementations) {
631                                     menuitem_children.add(impl);
632                             }
633                     }
634                 }
635
636                 if (menuitem_children.contains(this.node.fqn())) {
637                         this.addLine(this.ipad + "this.el.show();");
638                 
639                 }
640         }
641
642         void addInitMyVars()
643         {
644                         //var meths = this.palete.getPropertiesFor(item['|xns'] + '.' + item.xtype, 'methods');
645                         //print(JSON.stringify(meths,null,4));Seed.quit();
646                         
647                         
648                         
649                         // initialize.. my vars..
650                 this.addLine();
651                 this.addLine( this.ipad + "// my vars (dec)");
652                 
653                 var iter = this.myvars.list_iterator();
654                 while(iter.next()) {
655                         
656                         var k = iter.get();
657                         
658                          
659                         var prop = this.node.props.get(k);
660                         
661                         var v = prop.val.strip();                       
662                         
663                         if (v.length < 1) {
664                                 continue; 
665                         }
666                         // at this point start using 
667
668                         if (v == "FALSE" || v == "TRUE") {
669                                 v= v.down();
670                         }
671                         //FIXME -- check for raw string.. "string XXXX"
672                         
673                         // if it's a string...
674                         
675                         prop.start_line = this.cur_line;
676                         this.addLine(this.ipad + "this." + prop.name + " = " +   v +";");
677                         prop.end_line = this.cur_line;
678                 }
679         }
680
681         
682
683
684         
685         void addWrappedProperties()
686         {
687                 var cls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn());
688                 if (cls == null) {
689                         GLib.debug("Skipping wrapped properties - could not find class  %s" , this.node.fqn());
690                         return;
691                 }
692                         // what are the properties of this class???
693                 this.addLine();
694                 this.addLine(this.ipad + "// set gobject values");
695                 
696
697                 var iter = cls.props.map_iterator();
698                 while (iter.next()) {
699                         var p = iter.get_key();
700                         //print("Check Write %s\n", p);
701                         if (!this.node.has(p)) {
702                                 continue;
703                         }
704                         if (this.shouldIgnoreWrapped(p)) {
705                                 continue;
706                         }
707                         
708                         this.ignore(p);
709
710
711                         var prop = this.node.get_prop(p);
712                         var v = prop.val;
713                         
714                         // user defined properties.
715                         if (prop.ptype == NodePropType.USER) {
716                                 continue;
717                         }
718                                 
719
720                         
721                         var is_raw = prop.ptype == NodePropType.RAW;
722                         
723                         // what's the type.. - if it's a string.. then we quote it..
724                         if (iter.get_value().type == "string" && !is_raw) {
725                                  v = "\"" +  v.escape("") + "\"";
726                         }
727                         if (v == "TRUE" || v == "FALSE") {
728                                 v = v.down();
729                         }
730                         if (iter.get_value().type == "float" && v[v.length-1] != 'f') {
731                                 v += "f";
732                         }
733                         
734                         prop.start_line = this.cur_line;
735                         this.addLine("%sthis.el.%s = %s;".printf(ipad,p,v)); // // %s,  iter.get_value().type);
736                         prop.end_line = this.cur_line;          
737                            // got a property..
738                            
739
740                 }
741                 
742         }
743         /**
744          *  pack the children into the parent.
745          * 
746          * if the child's id starts with '*' then it is not packed...
747          * - this allows you to define children and add them manually..
748          */
749
750         void addChildren()
751         {
752                                 //code
753                 if (this.node.items.size < 1) {
754                         return;
755                 }
756                 this.pane_number = 0;
757                 var cols = this.node.has("* columns") ? int.parse(this.node.get_prop("* columns").val) : 1;
758                 var colpos = 0;
759                 
760                 var iter = this.node.items.list_iterator();
761                 var i = -1;
762                 while (iter.next()) {
763                         i++;
764                                 
765                         var child = iter.get();
766
767                         if (child.xvala_id[0] == '*') {
768                                 continue; // skip generation of children?
769                         }
770                                         
771                         var xargs = "";
772                         if (child.has("* args")) {
773                                 
774                                 var ar = child.get_prop("* args").val.split(",");
775                                 for (var ari = 0 ; ari < ar.length; ari++ ) {
776                                         var arg = ar[ari].split(" ");
777                                         xargs += "," + arg[arg.length -1];
778                                 }
779                         }
780                         // create the element..
781                         this.addLine(this.ipad + "var child_" + "%d".printf(i) + " = new " + child.xvala_xcls +
782                                         "( _this " + xargs + ");" );
783                         
784                         // this is only needed if it does not have an ID???
785                         
786                         
787                         if (child.has("* prop")) {
788                                 // fixme special packing!??!?!
789                                 if (child.get_prop("* prop").val.contains("[]")) {
790                                         // currently these 'child props
791                                         // used for label[]  on Notebook
792                                         // used for button[]  on Dialog?
793                                         // columns[] ?
794                                         this.packChild(child, i, 0, 0, child.get_prop("* prop").val);  /// fixme - this is a bit speciall...
795                                         continue;
796                                 }
797                                 // add a ref... (if 'id' is not set... to a '+' ?? what does that mean? - fake ids?
798                                 if (child.xvala_id.length < 1 || child.xvala_id[0] != '+') {
799                                         this.addLine(this.ipad + "child_" + "%d".printf(i) +".ref();"); // we need to reference increase unnamed children...
800                                 } else {
801                                         //this.addLine(this.ipad + "// no ref as xvala_id is %s".printf(child.xvala_id));
802                                 }                       
803                                 
804                                 
805                                 this.addLine(ipad + "this.el." + child.get_prop("* prop").val + " = child_" + "%d".printf(i) + ".el;");
806                                 continue;
807                         } 
808                         
809                         if (child.xvala_id.length < 1 || child.xvala_id[0] != '+') {
810                                 this.addLine(this.ipad + "child_" + "%d".printf(i) +".ref();"); // we need to reference increase unnamed children...
811                         } else {
812                                 //this.addLine(this.ipad + "// no ref as xvala_id is %s".printf(child.xvala_id));
813                         }
814                         
815                         
816                         this.packChild(child, i, cols, colpos);
817                         if (child.has("colspan")) {
818                                 colpos += int.parse(child.get_prop("colspan").val);
819                         } else {
820                                 colpos += 1;
821                         }
822                                           
823                         if (child.xvala_id[0] != '+') {
824                                 continue; // skip generation of children?
825                                                 
826                         }
827                         // this.{id - without the '+'} = the element...
828                         this.addLine(this.ipad + "this." + child.xvala_id.substring(1) + " =  child_" + "%d".printf(i) +  ";");
829                                   
830                 }
831         }
832         
833
834         
835         void packChild(Node child, int i, int cols, int colpos, string propname= "")
836         {
837                 
838                 GLib.debug("packChild %s=>%s", this.node.fqn(), child.fqn());
839                 // forcing no packing? - true or false? -should we just accept false?
840                 if (child.has("* pack") && child.get("* pack").down() == "false") {
841                         return; // force no packing
842                 }
843                 if (child.has("* pack") && child.get("* pack").down() == "true") {
844                         return; // force no packing
845                 }
846                 
847                 // BC really - don't want to support this anymore.
848                 if (child.has("* pack")) {
849                         
850                         string[]  packing =  { "add" };
851                         if (child.has("* pack")) {
852                                 packing = child.get("* pack").split(",");
853                         }
854                         
855                         var pack = packing[0];
856                         this.addLine(this.ipad + "this.el." + pack.strip() + " (  child_" + "%d".printf(i) + ".el " +
857                                    (packing.length > 1 ? 
858                                                 (", " + string.joinv(",", packing).substring(pack.length+1))
859                                         :
860                                                         ""
861                                                 ) + " );");
862                         return;  
863                 }
864                 var childcls =  this.file.project.palete.getClass(child.fqn()); // very trusting..
865                 var is_event = childcls.inherits.contains("Gtk.EventController") || childcls.implements.contains("Gtk.EventController");
866                 if (is_event) {
867                     this.addLine(this.ipad + "this.el.add_controller(  child_%d.el );".printf(i) );
868                     return;
869                 }
870                 
871                 
872                 switch (this.node.fqn()) {
873                         
874                                 
875                 
876                         case "Gtk.Fixed":
877                         case "Gtk.Layout":
878                                 var x = child.has("x") ?  child.get_prop("x").val  : "0";
879                                 var y = child.has("y") ?  child.get_prop("y").val  : "0";
880                                 this.addLine(this.ipad + "this.el.put(  child_%d.el, %s, %s );".printf(i,x,y) );
881                                 return;
882                                 
883                         case "Gtk.Grid":
884                                 var x = "%d".printf(colpos % cols);
885                                 var y = "%d".printf(( colpos - (colpos % cols) ) / cols);
886                                 var w = child.has("colspan") ? child.get_prop("colspan").val : "1";
887                                 var h = "1";
888                                 this.addLine(this.ipad + "this.el.attach(  child_%d.el, %s, %s, %s, %s );".printf(i,x,y, w, h) );
889                                 return;
890
891                         case "Gtk.Stack":
892                                 var named = child.has("stack_name") ?  child.get_prop("stack_name").val.escape() : "";
893                                 var title = child.has("stack_title") ?  child.get_prop("stack_title").val.escape()  : "";
894                                 if (title.length > 0) {
895                                         this.addLine(this.ipad + "this.el.add_titled(  child_%d.el, \"%s\", \"%s\" );".printf(i,named,title));  
896                                 } else {
897                                         this.addLine(this.ipad + "this.el.add_named(  child_%d.el, \"%s\" );".printf(i,named));
898                                 }
899                                 return;
900                                 
901                         case "Gtk.Notebook": // use label
902                                 var label = child.has("notebook_label") ?  child.get_prop("notebook_label").val.escape() : "";
903                                 this.addLine(this.ipad + "this.el.append_page( child_%d.el, new Gtk.Label(\"%s\"));".printf(i, label)); 
904                                 return;
905                                 
906                          
907                         case "Gtk.TreeView": // adding TreeViewColumns
908                                 this.addLine(this.ipad + "this.el.append_column(  child_" + "%d".printf(i) + ".el );");
909                                 return;
910                         
911                         case "Gtk.TreeViewColumn": //adding Renderers - I think these are all proprerties of the renderer used...
912                                 if (child.has("markup_column") && int.parse(child.get_prop("markup_column").val) > -1) {
913                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"markup\", %s );".printf(i, child.get_prop("markup_column").val));
914                                 }
915                                 if (child.has("text_column") && int.parse(child.get_prop("text_column").val) > -1) {
916                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"text\", %s );".printf(i, child.get_prop("text_column").val));
917                                 }
918                                 if (child.has("pixbuf_column") && int.parse(child.get_prop("pixbuf_column").val) > -1) {
919                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"pixbuf\", %s );".printf(i, child.get_prop("pixbuf_column").val));
920                                 }
921                                 if (child.has("pixbuf_column") && int.parse(child.get_prop("active_column").val) > -1) {
922                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"active\", %s );".printf(i, child.get_prop("active_column").val));
923                                 }
924                                 if (child.has("background_column") && int.parse(child.get_prop("background_column").val) > -1) {
925                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"background-rgba\", %s );".printf(i, child.get_prop("background_column").val));
926                                 }
927                                 this.addLine(this.ipad + "this.el.add(  child_" + "%d".printf(i) + ".el );");
928                                 // any more!?
929                                 return;
930                         
931                         case "Gtk.Dialog":
932                                 if (propname == "buttons[]") {
933                                         var resp_id = i;
934                                         if (child.has("* response_id")) { 
935                                                 resp_id = int.parse(child.get_prop("* response_id").val);
936                                         }
937                                         this.addLine(this.ipad + "this.el.add_action_widget( child_%d.el, %d);".printf(i,resp_id) );
938                                         return;
939                                 }
940                         
941                                 
942                                 this.addLine(this.ipad + "this.el.get_content_area().add( child_" + "%d".printf(i) + ".el );");
943                                 return;
944
945                         case "Gtk.Paned":
946                                 this.pane_number++;
947                                 switch(this.pane_number) {
948                                         case 1:
949                                         case 2:                                 
950                                                 this.addLine(this.ipad + "this.el.pack%d( child_%d".printf(this.pane_number,i) + ".el );");
951                                                 return;
952                                         default:
953                                                 // do nothing
954                                                 break;
955                                 }
956                                 return;
957                                 
958                         case "Gtk.Menu":
959                                 this.addLine(this.ipad + "this.el.append(  child_" + "%d".printf(i) + ".el );");
960                                 return;
961                         
962                         default:
963                             // gtk4 uses append!!!! - gtk3 - uses add..
964                                 this.addLine(this.ipad + "this.el.append(  child_" + "%d".printf(i) + ".el );");
965                                 return;
966                 
967                 
968                 }
969                 
970                 
971         }
972         
973         // fixme GtkDialog?!? buttons[]
974         
975         // fixme ... add case "Gtk.RadioButton":  // group_id ??
976
977                         
978
979         void addInit()
980         {
981
982                 
983                 if (!this.node.has("* init")) {
984                                 return;
985                 }
986                 this.addLine();
987                 this.addLine(ipad + "// init method");
988                 this.addLine();
989                 this.node.setLine(this.cur_line, "p", "init");
990                 
991                 var init =  this.node.get_prop("* init");
992                 init.start_line = this.cur_line;
993                 this.addMultiLine(ipad + this.padMultiline(ipad, init.val) );
994                 init.end_line = this.cur_line;
995          }
996          void addListeners()
997          {
998                 if (this.node.listeners.size < 1) {
999                         return;
1000                 }
1001                                 
1002                 this.addLine();
1003                 this.addLine(ipad + "//listeners");
1004                         
1005                          
1006
1007                 var iter = this.node.listeners.map_iterator();
1008                 while (iter.next()) {
1009                         var k = iter.get_key();
1010                         var prop = iter.get_value();
1011                         var v = prop.val;
1012                         
1013                         prop.start_line = this.cur_line;
1014                         this.node.setLine(this.cur_line, "l", k);
1015                         this.addMultiLine(this.ipad + "this.el." + k + ".connect( " + 
1016                                         this.padMultiline(this.ipad,v) +");"); 
1017                         prop.end_line = this.cur_line;
1018                 }
1019         }    
1020         void addEndCtor()
1021         {
1022                          
1023                         // end ctor..
1024                         this.addLine(this.pad + "}");
1025         }
1026
1027
1028         /*
1029  * Standardize this crap...
1030  * 
1031  * standard properties (use to set)
1032  *          If they are long values show the dialog..
1033  *
1034  * someprop : ....
1035  * bool is_xxx  :: can show a pulldown.. (true/false)
1036  * string html  
1037  * $ string html  = string with value interpolated eg. baseURL + ".." 
1038  *  Clutter.ActorAlign x_align  (typed)  -- shows pulldowns if type is ENUM? 
1039  * $ untypedvalue = javascript untyped value...  
1040  * _ string html ... = translatable..
1041
1042  * 
1043  * object properties (not part of the GOjbect being wrapped?
1044  * # Gee.ArrayList<Xcls_fileitem> fileitems
1045  * 
1046  * signals
1047  * @ void open 
1048  * 
1049  * methods -- always text editor..
1050  * | void clearFiles
1051  * | someJSmethod
1052  * 
1053  * specials
1054  * * prop -- string
1055  * * args  -- string
1056  * * ctor -- string
1057  * * init -- big string?
1058  * 
1059  * event handlers (listeners)
1060  *   just shown 
1061  * 
1062  * -----------------
1063  * special ID values
1064  *  +XXXX -- indicates it's a instance property / not glob...
1065  *  *XXXX -- skip writing glob property (used as classes that can be created...)
1066  * 
1067  * 
1068  */
1069          
1070         void addUserMethods()
1071         {
1072                 this.addLine();
1073                 this.addLine(this.pad + "// user defined functions");
1074                         
1075                         // user defined functions...
1076                 var iter = this.node.props.map_iterator();
1077                 while(iter.next()) {
1078                         var prop = iter.get_value();
1079                         if (this.shouldIgnore(prop.name)) {
1080                                 continue;
1081                         }
1082                         // HOW TO DETERIME if its a method?            
1083                         if (prop.ptype != NodePropType.METHOD) {
1084                                         //strbuilder("\n" + pad + "// skip " + k + " - not pipe \n"); 
1085                                         continue;
1086                         }
1087                         
1088                         // function in the format of {type} (args) { .... }
1089
1090
1091
1092                         prop.start_line = this.cur_line;
1093                         this.node.setLine(this.cur_line, "p", prop.name);
1094                         this.addMultiLine(this.pad + "public " + prop.rtype + " " +  prop.name + " " + this.padMultiline(this.pad, prop.val));;
1095                         prop.end_line = this.cur_line;
1096                                 
1097                 }
1098         }
1099
1100         void iterChildren()
1101         {
1102                 this.node.line_end = this.cur_line;
1103                 this.node.sortLines();
1104                 
1105                         
1106                 if (this.depth > 0) {
1107                         this.addLine(this.inpad + "}");
1108                 }
1109                 
1110                 var iter = this.node.items.list_iterator();
1111                  
1112                 while (iter.next()) {
1113                         this.addMultiLine(this.mungeChild(iter.get()));
1114                 }
1115                          
1116                 if (this.depth < 1) {
1117                         this.addLine(this.inpad + "}");
1118                 }
1119                         
1120         }
1121
1122         string padMultiline(string pad, string str)
1123         {
1124                 var ar = str.strip().split("\n");
1125                 return string.joinv("\n" + pad , ar);
1126         }
1127         
1128         void ignore(string i) {
1129                 this.ignoreList.add(i);
1130                 
1131         }
1132         void ignoreWrapped(string i) {
1133                 this.ignoreWrappedList.add(i);
1134                 
1135         }
1136         bool shouldIgnore(string i)
1137         {
1138                 return ignoreList.contains(i);
1139         }
1140         bool shouldIgnoreWrapped(string i)
1141         {
1142                 return ignoreWrappedList.contains(i);
1143         }
1144         
1145 }
1146         
1147          
1148         
1149         
1150
1151