disable gtksource klugde
[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.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                         foreach(var impl in gir.implementations) {
630                                 menuitem_children.add(impl);
631                         }
632                 }
633
634                 if (menuitem_children.contains(this.node.fqn())) {
635                         this.addLine(this.ipad + "this.el.show();");
636                 
637                 }
638         }
639
640         void addInitMyVars()
641         {
642                         //var meths = this.palete.getPropertiesFor(item['|xns'] + '.' + item.xtype, 'methods');
643                         //print(JSON.stringify(meths,null,4));Seed.quit();
644                         
645                         
646                         
647                         // initialize.. my vars..
648                 this.addLine();
649                 this.addLine( this.ipad + "// my vars (dec)");
650                 
651                 var iter = this.myvars.list_iterator();
652                 while(iter.next()) {
653                         
654                         var k = iter.get();
655                         
656                          
657                         var prop = this.node.props.get(k);
658                         
659                         var v = prop.val.strip();                       
660                         
661                         if (v.length < 1) {
662                                 continue; 
663                         }
664                         // at this point start using 
665
666                         if (v == "FALSE" || v == "TRUE") {
667                                 v= v.down();
668                         }
669                         //FIXME -- check for raw string.. "string XXXX"
670                         
671                         // if it's a string...
672                         
673                         prop.start_line = this.cur_line;
674                         this.addLine(this.ipad + "this." + prop.name + " = " +   v +";");
675                         prop.end_line = this.cur_line;
676                 }
677         }
678
679         
680
681
682         
683         void addWrappedProperties()
684         {
685                 var cls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn());
686                 if (cls == null) {
687                         GLib.debug("Skipping wrapped properties - could not find class  %s" , this.node.fqn());
688                         return;
689                 }
690                         // what are the properties of this class???
691                 this.addLine();
692                 this.addLine(this.ipad + "// set gobject values");
693                 
694
695                 var iter = cls.props.map_iterator();
696                 while (iter.next()) {
697                         var p = iter.get_key();
698                         //print("Check Write %s\n", p);
699                         if (!this.node.has(p)) {
700                                 continue;
701                         }
702                         if (this.shouldIgnoreWrapped(p)) {
703                                 continue;
704                         }
705                         
706                         this.ignore(p);
707
708
709                         var prop = this.node.get_prop(p);
710                         var v = prop.val;
711                         
712                         // user defined properties.
713                         if (prop.ptype == NodePropType.USER) {
714                                 continue;
715                         }
716                                 
717
718                         
719                         var is_raw = prop.ptype == NodePropType.RAW;
720                         
721                         // what's the type.. - if it's a string.. then we quote it..
722                         if (iter.get_value().type == "string" && !is_raw) {
723                                  v = "\"" +  v.escape("") + "\"";
724                         }
725                         if (v == "TRUE" || v == "FALSE") {
726                                 v = v.down();
727                         }
728                         if (iter.get_value().type == "float" && v[v.length-1] != 'f') {
729                                 v += "f";
730                         }
731                         
732                         prop.start_line = this.cur_line;
733                         this.addLine("%sthis.el.%s = %s;".printf(ipad,p,v)); // // %s,  iter.get_value().type);
734                         prop.end_line = this.cur_line;          
735                            // got a property..
736                            
737
738                 }
739                 
740         }
741         /**
742          *  pack the children into the parent.
743          * 
744          * if the child's id starts with '*' then it is not packed...
745          * - this allows you to define children and add them manually..
746          */
747
748         void addChildren()
749         {
750                                 //code
751                 if (this.node.items.size < 1) {
752                         return;
753                 }
754                 this.pane_number = 0;
755                 var cols = this.node.has("* columns") ? int.parse(this.node.get_prop("* columns").val) : 1;
756                 var colpos = 0;
757                 
758                 var iter = this.node.items.list_iterator();
759                 var i = -1;
760                 while (iter.next()) {
761                         i++;
762                                 
763                         var child = iter.get();
764
765                         if (child.xvala_id[0] == '*') {
766                                 continue; // skip generation of children?
767                         }
768                                         
769                         var xargs = "";
770                         if (child.has("* args")) {
771                                 
772                                 var ar = child.get_prop("* args").val.split(",");
773                                 for (var ari = 0 ; ari < ar.length; ari++ ) {
774                                         var arg = ar[ari].split(" ");
775                                         xargs += "," + arg[arg.length -1];
776                                 }
777                         }
778                         // create the element..
779                         this.addLine(this.ipad + "var child_" + "%d".printf(i) + " = new " + child.xvala_xcls +
780                                         "( _this " + xargs + ");" );
781                         
782                         // this is only needed if it does not have an ID???
783                         
784                         
785                         if (child.has("* prop")) {
786                                 // fixme special packing!??!?!
787                                 if (child.get_prop("* prop").val.contains("[]")) {
788                                         // currently these 'child props
789                                         // used for label[]  on Notebook
790                                         // used for button[]  on Dialog?
791                                         // columns[] ?
792                                          this.packChild(child, i, 0, 0, child.get_prop("* prop").val);  /// fixme - this is a bit speciall...
793                                         continue;
794                                 }
795                                 // add a ref... (if 'id' is not set... to a '+' ?? what does that mean? - fake ids?
796                                 if (child.xvala_id.length < 1 || child.xvala_id[0] != '+') {
797                                         this.addLine(this.ipad + "child_" + "%d".printf(i) +".ref();"); // we need to reference increase unnamed children...
798                                 } else {
799                                         //this.addLine(this.ipad + "// no ref as xvala_id is %s".printf(child.xvala_id));
800                                 }                       
801                                 
802                                 
803                                 this.addLine(ipad + "this.el." + child.get_prop("* prop").val + " = child_" + "%d".printf(i) + ".el;");
804                                 continue;
805                         } 
806                         
807                         if (child.xvala_id.length < 1 || child.xvala_id[0] != '+') {
808                                 this.addLine(this.ipad + "child_" + "%d".printf(i) +".ref();"); // we need to reference increase unnamed children...
809                         } else {
810                                 //this.addLine(this.ipad + "// no ref as xvala_id is %s".printf(child.xvala_id));
811                         }
812                         
813                         
814                         this.packChild(child, i, cols, colpos);
815                         if (child.has("colspan")) {
816                                 colpos += int.parse(child.get_prop("colspan").val);
817                         } else {
818                                 colpos += 1;
819                         }
820                                           
821                         if (child.xvala_id[0] != '+') {
822                                 continue; // skip generation of children?
823                                                 
824                         }
825                         // this.{id - without the '+'} = the element...
826                         this.addLine(this.ipad + "this." + child.xvala_id.substring(1) + " =  child_" + "%d".printf(i) +  ";");
827                                   
828                 }
829         }
830         
831
832         
833         void packChild(Node child, int i, int cols, int colpos, string propname= "")
834         {
835                 
836                 GLib.debug("packChild %s=>%s", this.node.fqn(), child.fqn());
837                 // forcing no packing? - true or false? -should we just accept false?
838                 if (child.has("* pack") && child.get("* pack").down() == "false") {
839                         return; // force no packing
840                 }
841                 if (child.has("* pack") && child.get("* pack").down() == "true") {
842                         return; // force no packing
843                 }
844                 
845                 // BC really - don't want to support this anymore.
846                 if (child.has("* pack")) {
847                         
848                         string[]  packing =  { "add" };
849                         if (child.has("* pack")) {
850                                 packing = child.get("* pack").split(",");
851                         }
852                         
853                         var pack = packing[0];
854                         this.addLine(this.ipad + "this.el." + pack.strip() + " (  child_" + "%d".printf(i) + ".el " +
855                                    (packing.length > 1 ? 
856                                                 (", " + string.joinv(",", packing).substring(pack.length+1))
857                                         :
858                                                         ""
859                                                 ) + " );");
860                         return;  
861                 }
862                 switch (this.node.fqn()) {
863                         
864                                 
865                 
866                         case "Gtk.Fixed":
867                         case "Gtk.Layout":
868                                 var x = child.has("x") ?  child.get_prop("x").val  : "0";
869                                 var y = child.has("y") ?  child.get_prop("y").val  : "0";
870                                 this.addLine(this.ipad + "this.el.put(  child_%d.el, %s, %s );".printf(i,x,y) );
871                                 return;
872                                 
873                         case "Gtk.Grid":
874                                 var x = "%d".printf(colpos % cols);
875                                 var y = "%d".printf(( colpos - (colpos % cols) ) / cols);
876                                 var w = child.has("colspan") ? child.get_prop("colspan").val : "1";
877                                 var h = "1";
878                                 this.addLine(this.ipad + "this.el.attach(  child_%d.el, %s, %s, %s, %s );".printf(i,x,y, w, h) );
879                                 return;
880
881                         case "Gtk.Stack":
882                                 var named = child.has("stack_name") ?  child.get_prop("stack_name").val.escape() : "";
883                                 var title = child.has("stack_title") ?  child.get_prop("stack_title").val.escape()  : "";
884                                 if (title.length > 0) {
885                                         this.addLine(this.ipad + "this.el.add_titled(  child_%d.el, \"%s\", \"%s\" );".printf(i,named,title));  
886                                 } else {
887                                         this.addLine(this.ipad + "this.el.add_named(  child_%d.el, \"%s\" );".printf(i,named));
888                                 }
889                                 return;
890                                 
891                         case "Gtk.Notebook": // use label
892                                 var label = child.has("notebook_label") ?  child.get_prop("notebook_label").val.escape() : "";
893                                 this.addLine(this.ipad + "this.el.append_page( child_%d.el, new Gtk.Label(\"%s\"));".printf(i, label)); 
894                                 return;
895                                 
896                          
897                         case "Gtk.TreeView": // adding TreeViewColumns
898                                 this.addLine(this.ipad + "this.el.append_column(  child_" + "%d".printf(i) + ".el );");
899                                 return;
900                         
901                         case "Gtk.TreeViewColumn": //adding Renderers - I think these are all proprerties of the renderer used...
902                                 if (child.has("markup_column") && int.parse(child.get_prop("markup_column").val) > -1) {
903                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"markup\", %s );".printf(i, child.get_prop("markup_column").val));
904                                 }
905                                 if (child.has("text_column") && int.parse(child.get_prop("text_column").val) > -1) {
906                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"text\", %s );".printf(i, child.get_prop("text_column").val));
907                                 }
908                                 if (child.has("pixbuf_column") && int.parse(child.get_prop("pixbuf_column").val) > -1) {
909                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"pixbuf\", %s );".printf(i, child.get_prop("pixbuf_column").val));
910                                 }
911                                 if (child.has("pixbuf_column") && int.parse(child.get_prop("active_column").val) > -1) {
912                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"active\", %s );".printf(i, child.get_prop("active_column").val));
913                                 }
914                                 if (child.has("background_column") && int.parse(child.get_prop("background_column").val) > -1) {
915                                         this.addLine(this.ipad + "this.el.add_attribute(  child_%d.el, \"background-rgba\", %s );".printf(i, child.get_prop("background_column").val));
916                                 }
917                                 this.addLine(this.ipad + "this.el.add(  child_" + "%d".printf(i) + ".el );");
918                                 // any more!?
919                                 return;
920                         
921                         case "Gtk.Dialog":
922                                 if (propname == "buttons[]") {
923                                         var resp_id = i;
924                                         if (child.has("* response_id")) { 
925                                                 resp_id = int.parse(child.get_prop("* response_id").val);
926                                         }
927                                         this.addLine(this.ipad + "this.el.add_action_widget( child_%d.el, %d);".printf(i,resp_id) );
928                                         return;
929                                 }
930                         
931                                 
932                                 this.addLine(this.ipad + "this.el.get_content_area().add( child_" + "%d".printf(i) + ".el );");
933                                 return;
934
935                         case "Gtk.Paned":
936                                 this.pane_number++;
937                                 switch(this.pane_number) {
938                                         case 1:
939                                         case 2:                                 
940                                                 this.addLine(this.ipad + "this.el.pack%d( child_%d".printf(this.pane_number,i) + ".el );");
941                                                 return;
942                                         default:
943                                                 // do nothing
944                                                 break;
945                                 }
946                                 return;
947                                 
948                         case "Gtk.Menu":
949                                 this.addLine(this.ipad + "this.el.append(  child_" + "%d".printf(i) + ".el );");
950                                 return;
951                         
952                         default:
953                                 this.addLine(this.ipad + "this.el.add(  child_" + "%d".printf(i) + ".el );");
954                                 return;
955                 
956                 
957                 }
958                 
959                 
960         }
961         
962         // fixme GtkDialog?!? buttons[]
963         
964         // fixme ... add case "Gtk.RadioButton":  // group_id ??
965
966                         
967
968         void addInit()
969         {
970
971                 
972                 if (!this.node.has("* init")) {
973                                 return;
974                 }
975                 this.addLine();
976                 this.addLine(ipad + "// init method");
977                 this.addLine();
978                 this.node.setLine(this.cur_line, "p", "init");
979                 
980                 var init =  this.node.get_prop("* init");
981                 init.start_line = this.cur_line;
982                 this.addMultiLine(ipad + this.padMultiline(ipad, init.val) );
983                 init.end_line = this.cur_line;
984          }
985          void addListeners()
986          {
987                 if (this.node.listeners.size < 1) {
988                         return;
989                 }
990                                 
991                 this.addLine();
992                 this.addLine(ipad + "//listeners");
993                         
994                          
995
996                 var iter = this.node.listeners.map_iterator();
997                 while (iter.next()) {
998                         var k = iter.get_key();
999                         var prop = iter.get_value();
1000                         var v = prop.val;
1001                         
1002                         prop.start_line = this.cur_line;
1003                         this.node.setLine(this.cur_line, "l", k);
1004                         this.addMultiLine(this.ipad + "this.el." + k + ".connect( " + 
1005                                         this.padMultiline(this.ipad,v) +");"); 
1006                         prop.end_line = this.cur_line;
1007                 }
1008         }    
1009         void addEndCtor()
1010         {
1011                          
1012                         // end ctor..
1013                         this.addLine(this.pad + "}");
1014         }
1015
1016
1017         /*
1018  * Standardize this crap...
1019  * 
1020  * standard properties (use to set)
1021  *          If they are long values show the dialog..
1022  *
1023  * someprop : ....
1024  * bool is_xxx  :: can show a pulldown.. (true/false)
1025  * string html  
1026  * $ string html  = string with value interpolated eg. baseURL + ".." 
1027  *  Clutter.ActorAlign x_align  (typed)  -- shows pulldowns if type is ENUM? 
1028  * $ untypedvalue = javascript untyped value...  
1029  * _ string html ... = translatable..
1030
1031  * 
1032  * object properties (not part of the GOjbect being wrapped?
1033  * # Gee.ArrayList<Xcls_fileitem> fileitems
1034  * 
1035  * signals
1036  * @ void open 
1037  * 
1038  * methods -- always text editor..
1039  * | void clearFiles
1040  * | someJSmethod
1041  * 
1042  * specials
1043  * * prop -- string
1044  * * args  -- string
1045  * * ctor -- string
1046  * * init -- big string?
1047  * 
1048  * event handlers (listeners)
1049  *   just shown 
1050  * 
1051  * -----------------
1052  * special ID values
1053  *  +XXXX -- indicates it's a instance property / not glob...
1054  *  *XXXX -- skip writing glob property (used as classes that can be created...)
1055  * 
1056  * 
1057  */
1058          
1059         void addUserMethods()
1060         {
1061                 this.addLine();
1062                 this.addLine(this.pad + "// user defined functions");
1063                         
1064                         // user defined functions...
1065                 var iter = this.node.props.map_iterator();
1066                 while(iter.next()) {
1067                         var prop = iter.get_value();
1068                         if (this.shouldIgnore(prop.name)) {
1069                                 continue;
1070                         }
1071                         // HOW TO DETERIME if its a method?            
1072                         if (prop.ptype != NodePropType.METHOD) {
1073                                         //strbuilder("\n" + pad + "// skip " + k + " - not pipe \n"); 
1074                                         continue;
1075                         }
1076                         
1077                         // function in the format of {type} (args) { .... }
1078
1079
1080
1081                         prop.start_line = this.cur_line;
1082                         this.node.setLine(this.cur_line, "p", prop.name);
1083                         this.addMultiLine(this.pad + "public " + prop.rtype + " " +  prop.name + " " + this.padMultiline(this.pad, prop.val));;
1084                         prop.end_line = this.cur_line;
1085                                 
1086                 }
1087         }
1088
1089         void iterChildren()
1090         {
1091                 this.node.line_end = this.cur_line;
1092                 this.node.sortLines();
1093                 
1094                         
1095                 if (this.depth > 0) {
1096                         this.addLine(this.inpad + "}");
1097                 }
1098                 
1099                 var iter = this.node.items.list_iterator();
1100                  
1101                 while (iter.next()) {
1102                         this.addMultiLine(this.mungeChild(iter.get()));
1103                 }
1104                          
1105                 if (this.depth < 1) {
1106                         this.addLine(this.inpad + "}");
1107                 }
1108                         
1109         }
1110
1111         string padMultiline(string pad, string str)
1112         {
1113                 var ar = str.strip().split("\n");
1114                 return string.joinv("\n" + pad , ar);
1115         }
1116         
1117         void ignore(string i) {
1118                 this.ignoreList.add(i);
1119                 
1120         }
1121         void ignoreWrapped(string i) {
1122                 this.ignoreWrappedList.add(i);
1123                 
1124         }
1125         bool shouldIgnore(string i)
1126         {
1127                 return ignoreList.contains(i);
1128         }
1129         bool shouldIgnoreWrapped(string i)
1130         {
1131                 return ignoreWrappedList.contains(i);
1132         }
1133         
1134 }
1135         
1136          
1137         
1138         
1139
1140