fix #7989 - add support for extended classes (partial)
[roobuilder] / src / JsRender / NodeToVala.vala
index 2b206c5..b96e8f9 100644 (file)
  * 
  * usage : x = (new JsRender.NodeToVala(node)).munge();
  * 
+ * Fixmes?
+ *
+ *  pack - can we come up with a replacement?
+     - parent.child == child_widget -- actually uses getters and effectively does 'add'?
+       (works on most)?
+    
+     
+ * args  -- vala constructor args (should really only be used at top level - we did use it for clutter originally(
+ * ctor  -- different ctor argument
  * 
- * 
  * 
  * 
 */
 
+public abstract class JsRender.NodeToVala : NodeWriter {
 
+       protected string this_el = "??";
+        
+       int child_count = 1; // used to number the children.
+       public string cls;  // node fqn()
+       public string xcls;
+       
 
+       Gee.ArrayList<string> ignoreWrappedList; 
+       Gee.ArrayList<string> myvars;
 
-public class JsRender.NodeToVala : Object {
-
-       Node node;
 
-       int depth;
-       string inpad;
-       string pad;
-       string ipad;
-       string cls;
-       string xcls;
+        
+       int pane_number = 0;// ?? used when generating Gtk.Pane tabs
        
-       string ret;
        
-       int cur_line;
-
-       Gee.ArrayList<string> ignoreList;
-       Gee.ArrayList<string> ignoreWrappedList; 
-       Gee.ArrayList<string> myvars;
-       Gee.ArrayList<Node> vitems; // top level items
-       NodeToVala top;
-       JsRender file;
+       static construct {
+               NodeWriter.globalIgnore("pack");
+               NodeWriter.globalIgnore("init");
+               NodeWriter.globalIgnore("xns");
+               NodeWriter.globalIgnore("xtype");
+               NodeWriter.globalIgnore("id");
        
+       }
        /* 
         * ctor - just initializes things
         * - wraps a render node 
         */
-       public NodeToVala( JsRender file,  Node node,  int depth, NodeToVala? parent) 
+       protected NodeToVala( JsRender file,  Node node,  int depth, NodeToVala? parent) 
        {
 
+               base (file, node, depth, parent);
+        
+               this.initPadding('\t', 1);
                
-               this.node = node;
-               this.depth = depth;
-               this.inpad = string.nfill(depth > 0 ? 4 : 0, ' ');
-               this.pad = this.inpad + "    ";
-               this.ipad = this.inpad + "        ";
                this.cls = node.xvala_cls;
                this.xcls = node.xvala_xcls;
-               this.ret = "";
-               this.cur_line = parent == null ? 0 : parent.cur_line;
-               
+               if (depth == 0 && this.xcls.contains(".")) {
+                       var ar = this.xcls.split(".");
+                       this.xcls = ar[ar.length-1];
+               }
                
-               this.top = parent == null ? this : parent.top;
-               this.ignoreList = new Gee.ArrayList<string>();
+
                this.ignoreWrappedList  = new Gee.ArrayList<string>();
                this.myvars = new Gee.ArrayList<string>();
-               this.vitems = new Gee.ArrayList<Node>();
-               this.file = file;
-               
-               // initialize line data..
-               node.line_start = this.cur_line;
-               node.line_end  = this.cur_line;
-               node.lines = new Gee.ArrayList<int>();
-               node.line_map = new Gee.HashMap<int,string>();
-               if (parent == null) {
-                       node.node_lines = new Gee.ArrayList<int>();
-                       node.node_lines_map = new Gee.HashMap<int,Node>();
-                }
-               
+               this.child_count = 1;
+                
        }
-
-       public int vcnt = 0;
-       string toValaNS(Node item)
+       public void initCls()
        {
-               var ns = item.get("xns") ;
-               if (ns == "GtkSource") {
-                       return "Gtk.Source";
-               }
-               return ns + ".";
+               this.cls = this.file.tree.xvala_cls;
+               this.xcls = this.file.tree.xvala_xcls;
        }
-       public void  toValaName(Node item, int depth =0) 
+       public abstract  string mungeChild(  Node cnode);
+       
+        
+       public void namespaceHeader()
        {
-               this.vcnt++;
-
-               var ns =  this.toValaNS(item) ;
-               var cls = ns + item.get("xtype");
-               
-               
-               item.xvala_cls = cls;
-               
-               
-               string id = item.get("id").length > 0 ?
-                       item.get("id") :  "%s%d".printf(item.get("xtype"), this.vcnt);
-
-               
-               
-               
-               if (id[0] == '*' || id[0] == '+') {
-                       item.xvala_xcls = "Xcls_" + id.substring(1);
-               } else {
-                       item.xvala_xcls = "Xcls_" + id;
-               }
-                       
-               
-               item.xvala_id =  id;
-               if (depth > 0) {                        
-                       this.vitems.add(item);
-               } else if (!item.props.has_key("id")) {
-                       // use the file name..
-                       item.xvala_xcls =  this.file.name;
-                       // is id used?
-                       item.xvala_id = this.file.name;
-
-               }
-               // loop children..
-                                                                                                                          
-               if (item.items.size < 1) {
+               if (this.depth > 0 || this.file.file_namespace == "") {
                        return;
-               }
-               for(var i =0;i<item.items.size;i++) {
-                       this.toValaName(item.items.get(i), depth+1);
-               }
-                                         
+               } 
+               this.addLine("namespace " + this.file.file_namespace);
+               this.addLine("{");
+       
        }
-       /**
-        *  Main entry point to convert a file into a string..
-        */
-       public static string mungeFile(JsRender file) 
+       public void namespaceFooter()
        {
-               if (file.tree == null) {
-                       return "";
+               if (this.depth > 0 || this.file.file_namespace == "") {
+                       return;
                }
-
-               var n = new NodeToVala(file, file.tree, 0, null);
-               n.file = file;
-               n.vcnt = 0;
-               
-               n.toValaName(file.tree);
-               
-               
-               GLib.debug("top cls %s / xlcs %s\n ",file.tree.xvala_cls,file.tree.xvala_cls); 
-               n.cls = file.tree.xvala_cls;
-               n.xcls = file.tree.xvala_xcls;
-               return n.munge();
-               
-
-       }
+               this.addLine("}");
        
-       public string munge ( )
-       {
-               //return this.mungeToString(this.node);
-
-               this.ignore("pack");
-               this.ignore("init");
-               this.ignore("xns");
-               this.ignore("xtype");
-               this.ignore("id");
-               
-               this.globalVars();
-               this.classHeader();
-               this.addSingleton();
-               this.addTopProperties();
-               this.addMyVars();
-               this.addPlusProperties();
-               this.addValaCtor();
-               this.addUnderThis();
-               this.addWrappedCtor();
-
-               this.addInitMyVars();
-               this.addWrappedProperties();
-               this.addChildren();
-               this.addInit();
-               this.addListeners();
-               this.addEndCtor();
-               this.addUserMethods();
-               this.iterChildren();
-               
-               return this.ret;
-                
-                        
-       } 
-       public string mungeChild(  Node cnode)
-       {
-               var x = new  NodeToVala(this.file, cnode,  this.depth+1, this);
-               return x.munge();
-       }
-       public void addLine(string str= "")
-       {
-               this.cur_line++;
-               //this.ret += "/*%d*/ ".printf(this.cur_line-1) + str + "\n";
-               this.ret += str + "\n";
        }
-       public void addMultiLine(string str= "")
-       {
-                
-               this.cur_line += str.split("\n").length;
-               //this.ret +=  "/*%d*/ ".printf(l) + str + "\n";
-               this.ret +=   str + "\n";
-       }
-        
        
-       public void globalVars()
-       {
-               if (this.depth > 0) {
-                       return;
-               }
-               // Global Vars..??? when did this get removed..?
-               //this.ret += this.inpad + "public static " + this.xcls + "  " + this.node.xvala_id+ ";\n\n";
 
-               this.addLine(this.inpad + "static " + this.xcls + "  _" + this.node.xvala_id+ ";");
-               this.addLine();
-                  
-       }
+       protected abstract void classHeader();
+        
 
-       void classHeader()
-       {
-                          
-               // class header..
-               // class xxx {   WrappedGtk  el; }
-               this.node.line_start = this.cur_line;
-               
-               this.top.node.setNodeLine(this.cur_line, this.node);
-               
-               this.addLine(inpad + "public class " + this.xcls + " : Object");
-               this.addLine(this.inpad + "{");
-               
-                
-               this.addLine(this.pad + "public " + this.cls + " el;");
-               this.addLine(this.pad + "private " + this.top.xcls + "  _this;");
-               this.addLine();
-                       
-                       
-                       
-                       // singleton
-       }
-       void addSingleton() 
-       {
-               if (depth > 0) {
-                       return;
-               }
-               this.addLine(pad + "public static " + xcls + " singleton()");
-               this.addLine(this.pad + "{");
-               this.addLine(this.ipad +    "if (_" + this.node.xvala_id  + " == null) {");
-               this.addLine(this.ipad +    "    _" + this.node.xvala_id + "= new "+ this.xcls + "();");  // what about args?
-               this.addLine(this.ipad +    "}");
-               this.addLine(this.ipad +    "return _" + this.node.xvala_id +";");
-               this.addLine(this.pad + "}");
-       }
                        
        /**
         * when ID is used... on an element, it registeres a property on the top level...
         * so that _this.ID always works..
         * 
         */
-       void addTopProperties()
+       protected void addTopProperties()
        {
                if (this.depth > 0) {
                        return;
                }
                // properties - global..??
+               foreach(var n in this.top_level_items) { 
 
-               var iter = this.vitems.list_iterator();
-               while(iter.next()) {
-                       var n = iter.get();
-
-                        
                        if (!n.props.has_key("id") || n.xvala_id.length < 0) {
                                continue;
                                
                        }
-                       if (n.xvala_id[0] == '*') {
-                               continue;
-                       }
-                       if (n.xvala_id[0] == '+') {
+                       if (n.xvala_id[0] == '*' || n.xvala_id[0] == '+') {
                                continue;
                        }
+                        
                        this.addLine(this.pad + "public " + n.xvala_xcls + " " + n.xvala_id + ";");
                        
                }
@@ -289,9 +133,11 @@ public class JsRender.NodeToVala : Object {
         * 
         * 
         */
-       
-       void addMyVars()
+       protected void addMyVars()
        {
+               GLib.debug("callinged addMhyVars");
+               
                this.addLine();
                this.addLine(this.ipad + "// my vars (def)");
                        
@@ -300,69 +146,68 @@ public class JsRender.NodeToVala : Object {
                var cls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn());
                   
                if (cls == null) {
-                       return;
+                       GLib.debug("Gir factory failed to find class %s", this.node.fqn());
+                       
+                       //return;
                }
          
                
                        // Key = TYPE:name
-               var iter = this.node.props.map_iterator();
-               while (iter.next()) {
-                       var k = iter.get_key();
-                       if (this.shouldIgnore(k)) {
+               foreach(var prop in this.node.props.values) {
+                  
+                       if (this.shouldIgnore(prop.name)) {
                                continue;
                        }
-                       var vv = k.strip().split(" ");
+
                        // user defined method
-                       if (vv[0] == "|") {
+                       if (prop.ptype == NodePropType.METHOD) {
                                continue;
                        }
-                       if (vv[0] == "*") {
+                       if (prop.ptype == NodePropType.SPECIAL) {
                                continue;
                        }
                                
-                       if (vv[0] == "@") {
-                               this.node.setLine(this.cur_line, "p", k);
-                               this.addLine(this.pad + "public signal" + k.substring(1)  + " "  + iter.get_value() + ";");
+                       if (prop.ptype == NodePropType.SIGNAL) {
+                               this.node.setLine(this.cur_line, "p", prop.name);
+                               this.addLine(this.pad + "public signal " + prop.rtype + " " + prop.name  + " "  + prop.val + ";");
                                
-                               this.ignore(k);
-                               continue;
-                       }
-                       var min = (vv[0] == "$" || vv[0] == "#") ? 3 : 2; 
-                       if (vv.length < min) {
-                               // skip 'old js style properties without a type'
+                               this.ignore(prop.name);
                                continue;
                        }
                        
-                       var kname = vv[vv.length-1];
-
-                       if (this.shouldIgnore(kname)) {
+                       GLib.debug("Got myvars: %s", prop.name.strip());
+                       
+                       if (prop.rtype.strip().length < 1) {
                                continue;
                        }
                        
                        // is it a class property...
-                       if (cls.props.has_key(kname) && vv[0] != "#") {
+                       if (cls != null && cls.props.has_key(prop.name) && prop.ptype != NodePropType.USER) {
                                continue;
                        }
                        
-                       this.myvars.add(k);
-                       this.node.setLine(this.cur_line, "p", k);
+                       this.myvars.add(prop.name);
+                       prop.start_line = this.cur_line;
                        
-                       this.addLine(this.pad + "public " + 
-                               (k[0] == '$' || k[0] == '#' ? k.substring(2) : k ) + ";");
-                               
-                       this.ignore(k);
+                       this.node.setLine(this.cur_line, "p", prop.name);
+                       
+                       this.addLine(this.pad + "public " + prop.rtype + " " + prop.name + ";"); // definer - does not include value.
+
+
+                       prop.end_line = this.cur_line;                          
+                       this.ignore(prop.name);
                        
                                
                }
        }
        
        // if id of child is '+' then it's a property of this..
-       void addPlusProperties()
+       protected void addPlusProperties()
        {
-               if (this.node.items.size < 1) {
+               if (this.node.readItems().size < 1) {
                        return;
                }
-               var iter = this.node.items.list_iterator();
+               var iter = this.node.readItems().list_iterator();
                while (iter.next()) {
                        var ci = iter.get();
                                
@@ -379,46 +224,11 @@ public class JsRender.NodeToVala : Object {
        /**
         * add the constructor definition..
         */
-       void addValaCtor()
-       {
-                       
-               
-               // .vala props.. 
-               
-               string[] cargs = {};
-               var cargs_str = "";
-               // ctor..
-               this.addLine();
-               this.addLine(this.pad + "// ctor");
-               
-               if (this.node.has("* args")) {
-                       // not sure what this is supposed to be ding..
-               
-                       cargs_str = ", " + this.node.get("* args");
-                       //var ar = this.node.get("* args");.split(",");
-                       //for (var ari =0; ari < ar.length; ari++) {
-                               //      cargs +=  (ar[ari].trim().split(" ").pop();
-                                 // }
-                       }
-       
-               if (this.depth < 1) {
-                
-                       // top level - does not pass the top level element..
-                       this.addLine(this.pad + "public " + this.xcls + "(" +  cargs_str +")");
-                       this.addLine(this.pad + "{");
-               } else {
-                               
-                       // for sub classes = we passs the top level as _owner
-                       this.addLine(this.pad + "public " + this.xcls + "(" +  this.top.xcls + " _owner " + cargs_str + ")");
-                       this.addLine(this.pad + "{");
-               }
-               
-
-       }
+       protected abstract void addValaCtor();
        /**
         *  make sure _this is defined..
         */
-       void addUnderThis() 
+       protected void addUnderThis() 
        {
                // public static?
                if (depth < 1) {
@@ -442,92 +252,10 @@ public class JsRender.NodeToVala : Object {
                }
                         
        }
-       /**
-        * Initialize this.el to point to the wrapped element.
-        * 
-        * 
-        */
-
-       void addWrappedCtor()
-       {
-               // wrapped ctor..
-               // this may need to look up properties to fill in the arguments..
-               // introspection does not workk..... - as things like gtkmessagedialog
-               /*
-               if (cls == 'Gtk.Table') {
-
-               var methods = this.palete.getPropertiesFor(cls, 'methods');
-
-               print(JSON.stringify(this.palete.proplist[cls], null,4));
-               Seed.quit();
-               }
-               */
-               if (this.node.has("* ctor")) {
-                       this.node.setLine(this.cur_line, "p", "* ctor");
-                       this.addLine(this.ipad + "this.el = " + this.node.get("* ctor")+ ";");
-                       return;
-               }
-                
-               var  default_ctor = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn() + ".new");
-
-                
-               if (default_ctor != null && default_ctor.paramset != null && default_ctor.paramset.params.size > 0) {
-                       string[] args  = {};
-                       var iter = default_ctor.paramset.params.list_iterator();
-                       while (iter.next()) {
-                               var n = iter.get().name;
-                           print("building CTOR ARGS: %s, %s", n, iter.get().is_varargs ? "VARARGS": "");
-                                
-                               
-                               if (!this.node.has(n)) {
-
-                                       if (iter.get().type.contains("int")) {
-                                               args += "0";
-                                               continue;
-                                       }
-                                       if (iter.get().type.contains("float")) {
-                                               args += "0f";
-                                               continue;
-                                       }
-                                       if (iter.get().type.contains("bool")) {
-                                               args += "true"; // always default to true?
-                                               continue;
-                                       }
-                                       // any other types???
-                                       
-                                       args += "null";
-                                       continue;
-                               }
-                               this.ignoreWrapped(n);
-                               this.ignore(n);
-                               
-                               var v = this.node.get(n);
-
-                               if (iter.get().type == "string") {
-                                       v = "\"" +  v.escape("") + "\"";
-                               }
-                               if (v == "TRUE" || v == "FALSE") {
-                                       v = v.down();
-                               }
-
-                               
-                               args += v;
-
-                       }
-                       this.node.setLine(this.cur_line, "p", "* xtype");
-                       
-                       this.addLine(this.ipad + "this.el = new " + cls + "( "+ string.joinv(", ",args) + " );") ;
-                       return;
-                       
-               }
-               this.node.setLine(this.cur_line, "p", "* xtype");;
-               
-               this.addLine(this.ipad + "this.el = new " + this.cls + "();");
-
-                       
-       }
-
-       void addInitMyVars()
+        
+       
+        
+       protected void addInitMyVars()
        {
                        //var meths = this.palete.getPropertiesFor(item['|xns'] + '.' + item.xtype, 'methods');
                        //print(JSON.stringify(meths,null,4));Seed.quit();
@@ -543,23 +271,26 @@ public class JsRender.NodeToVala : Object {
                        
                        var k = iter.get();
                        
-                       var ar  = k.strip().split(" ");
-                       var kname = ar[ar.length-1];
+                        
+                       var prop = this.node.props.get(k);
+                       
+                       var v = prop.val.strip();                       
                        
-                       var v = this.node.props.get(k);
-                       // ignore signals.. 
                        if (v.length < 1) {
                                continue; 
                        }
+                       // at this point start using 
+
                        if (v == "FALSE" || v == "TRUE") {
-                               v = v.down();
+                               v= v.down();
                        }
                        //FIXME -- check for raw string.. "string XXXX"
                        
                        // if it's a string...
                        
-                       
-                       this.addLine(this.ipad + "this." + kname + " = " +   v +";");
+                       prop.start_line = this.cur_line;
+                       this.addLine(this.ipad + "this." + prop.name + " = " +   v +";");
+                       prop.end_line = this.cur_line;
                }
        }
 
@@ -567,20 +298,19 @@ public class JsRender.NodeToVala : Object {
 
 
        
-       void addWrappedProperties()
+       protected  void addWrappedProperties()
        {
                var cls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn());
                if (cls == null) {
+                       GLib.debug("Skipping wrapped properties - could not find class  %s" , this.node.fqn());
                        return;
                }
                        // what are the properties of this class???
                this.addLine();
                this.addLine(this.ipad + "// set gobject values");
                
-
-               var iter = cls.props.map_iterator();
-               while (iter.next()) {
-                       var p = iter.get_key();
+               foreach(var p in cls.props.keys) { 
+                       var val = cls.props.get(p);
                        //print("Check Write %s\n", p);
                        if (!this.node.has(p)) {
                                continue;
@@ -589,40 +319,40 @@ public class JsRender.NodeToVala : Object {
                                continue;
                        }
                        
-                               this.ignore(p);
-                       var v = this.node.get(p);
+                       this.ignore(p);
 
-                       var nodekey = this.node.get_key(p);
 
+                       var prop = this.node.get_prop(p);
+                       var v = prop.val;
+                       
                        // user defined properties.
-                       if (nodekey[0] == '#') {
+                       if (prop.ptype == NodePropType.USER) {
                                continue;
                        }
                                
 
                        
-                       var is_raw = nodekey[0] == '$';
+                       var is_raw = prop.ptype == NodePropType.RAW;
                        
                        // what's the type.. - if it's a string.. then we quote it..
-                       if (iter.get_value().type == "string" && !is_raw) {
+                       if (val.type == "string" && !is_raw) {
                                 v = "\"" +  v.escape("") + "\"";
                        }
                        if (v == "TRUE" || v == "FALSE") {
                                v = v.down();
                        }
-                       if (iter.get_value().type == "float" && v[v.length-1] != 'f') {
+                       if (val.type == "float" && v[v.length-1] != 'f') {
                                v += "f";
                        }
                        
-                       
-                       this.addLine("%sthis.el.%s = %s;".printf(ipad,p,v)); // // %s,  iter.get_value().type);
-                                       
+                       prop.start_line = this.cur_line;
+                       this.addLine("%s%s%s = %s;".printf(ipad,this.this_el,p,v)); // // %s,  iter.get_value().type);
+                       prop.end_line = this.cur_line;          
                           // got a property..
                           
 
                }
-               
-       }
+       } 
        /**
         *  pack the children into the parent.
         * 
@@ -630,80 +360,303 @@ public class JsRender.NodeToVala : Object {
         * - this allows you to define children and add them manually..
         */
 
-       void addChildren()
+       protected  void addChildren()
        {
                                //code
-               if (this.node.items.size < 1) {
+               if (this.node.readItems().size < 1) {
                        return;
                }
+               this.pane_number = 0;
+               var cols = this.node.has("* columns") ? int.max(1, int.parse(this.node.get_prop("* columns").val)) : 1;
+               var colpos = 0;
+               
+                
+               foreach(var child in this.node.readItems()) {
+                       
+                       
                         
-               var iter = this.node.items.list_iterator();
-               var i = -1;
-               while (iter.next()) {
-                       i++;
-                               
-                       var ci = iter.get();
 
-                       if (ci.xvala_id[0] == '*') {
+                       if (child.xvala_id[0] == '*') {
                                continue; // skip generation of children?
                        }
-                                       
-                       var xargs = "";
-                       if (ci.has("* args")) {
-                               
-                               var ar = ci.get("* args").split(",");
-                               for (var ari = 0 ; ari < ar.length; ari++ ) {
-                                       var arg = ar[ari].split(" ");
-                                       xargs += "," + arg[arg.length -1];
-                               }
+
+                       // probably added in ctor..                             
+                       if (child.has("* prop") && this.shouldIgnoreWrapped(child.get_prop("* prop").val)) {
+                               continue;
                        }
                        // create the element..
-                       this.addLine(this.ipad + "var child_" + "%d".printf(i) + " = new " + ci.xvala_xcls +
-                                       "( _this " + xargs + ");" );
                        
                        // this is only needed if it does not have an ID???
-                       this.addLine(this.ipad + "child_" + "%d".printf(i) +".ref();"); // we need to reference increase unnamed children...
+                       var childname = this.addPropSet(child, child.has("id") ? child.get_prop("id").val : "") ; 
                        
-                       if (ci.has("* prop")) {
-                               this.addLine(ipad + "this.el." + ci.get("* prop") + " = child_" + "%d".printf(i) + ".el;");
-                               continue;
-                       } 
+                       if (child.has("* prop")) {
+                        
+                       
+                               // fixme special packing!??!?!
+                               if (child.get_prop("* prop").val.contains("[]")) {
+                                       // currently these 'child props
+                                       // used for label[]  on Notebook
+                                       // used for button[]  on Dialog?
+                                       // columns[] ?
+                                        
+                                       this.packChild(child, childname, 0, 0, child.get_prop("* prop").val);  /// fixme - this is a bit speciall...
+                                       continue;
+                               }
+                               
+       
+                               
+                               this.ignoreWrapped(child.get_prop("* prop").val);
+                               var el_name = this.this_el == "this.el." ? ".el" : "";
+                               this.addLine(ipad + this.this_el  + child.get_prop("* prop").val + " = " + childname + el_name +";");
                                
-
-       // not sure why we have 'true' in pack?!?
-                       if (!ci.has("pack") || ci.get("pack").down() == "false" || ci.get("pack").down() == "true") {
                                continue;
+                       } 
+                        if (!child.has("id") && this.this_el == "this.el.") {
+                               this.addLine(this.ipad +  childname +".ref();"); 
+                        } 
+                       this.packChild(child, childname, cols, colpos);
+                       
+                       if (child.has("colspan")) {
+                               colpos += int.parse(child.get_prop("colspan").val);
+                       } else {
+                               colpos += 1;
+                       }
+                                         
+                       
+                       // this.{id - without the '+'} = the element...
+                        
+                                 
+               }
+       }
+       
+       protected string addPropSet(Node child, string child_name) 
+       {
+        
+               
+               var xargs = "";
+               if (child.has("* args")) {
+                       
+                       var ar = child.get_prop("* args").val.split(",");
+                       for (var ari = 0 ; ari < ar.length; ari++ ) {
+                               var arg = ar[ari].split(" ");
+                               xargs += "," + arg[arg.length -1];
                        }
+               }
+               
+               var childname = "child_" + "%d".printf(this.child_count++);     
+               var prefix = "";
+               if (child_name == "") {
+                       prefix = "var " + childname + " = ";
+               }
+               var cls =  child.xvala_xcls;
+               /*
+               if (this.this_el == "this.") {
+                       var clsdata = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn());
+                       //if (clsdata.is_sealed) {
+                               cls = this.node.fqn(); // need ctor data...
+                               this.addLine(this.ipad + @"$(prefix)new $cls( _this $xargs);" );
+                               return child_name == "" ? childname : ("_this." + child_name);  
+                       }
+               }
+               */
+               
+               this.addLine(this.ipad + @"$(prefix)new $cls( _this $xargs);" );
+                
+               // add a ref... (if 'id' is not set... to a '+' ?? what does that mean? - fake ids?
+               // remove '+' support as I cant remember what it does!!!
+               //if (child.xvala_id.length < 1 ) {
+               //      this.addLine(this.ipad + childname +".ref();"); // we need to reference increase unnamed children...
+               //}                     
+           //if (child.xvala_id[0] == '+') {
+               //      this.addLine(this.ipad + "this." + child.xvala_id.substring(1) + " = " + childname+  ";");
+                                       
+               //}
+               
+
+               return child_name == "" ? childname : ("_this." + child_name);  
+       }               
+                       
+       
+
+       
+       protected void packChild(Node child, string childname, int cols, int colpos, string propname= "")
+       {
+               
+               GLib.debug("packChild %s=>%s", this.node.fqn(), child.fqn());
+               // forcing no packing? - true or false? -should we just accept false?
+               if (child.has("* pack") && child.get("* pack").down() == "false") {
+                       return; // force no packing
+               }
+               if (child.has("* pack") && child.get("* pack").down() == "true") {
+                       return; // force no packing
+               }
+               var el_name = this.this_el == "this.el." ? ".el" : "";
+               var this_el = this.this_el;
+               // BC really - don't want to support this anymore.
+               if (child.has("* pack")) {
                        
                        string[]  packing =  { "add" };
-                       if (ci.has("pack")) {
-                               packing = ci.get("pack").split(",");
+                       if (child.has("* pack")) {
+                               packing = child.get("* pack").split(",");
                        }
                        
                        var pack = packing[0];
-                       this.addLine(this.ipad + "this.el." + pack.strip() + " (  child_" + "%d".printf(i) + ".el " +
+                       this.addLine(this.ipad + this.this_el + pack.strip() + " ( " + childname + el_name + " " +
                                   (packing.length > 1 ? 
                                                (", " + string.joinv(",", packing).substring(pack.length+1))
-                                       :
-                                                       ""
-                                               ) + " );");
+                                       : "" ) + " );");
+                       return;  
+               }
+               var childcls =  this.file.project.palete.getClass(child.fqn()); // very trusting..
+               if (childcls == null) {
+                 return;
+               }
+               // GTK4
+               var is_event = childcls.inherits.contains("Gtk.EventController") || childcls.implements.contains("Gtk.EventController");
+               if (is_event) {
+                   this.addLine(this.ipad + this.this_el + "add_controller(  %s.el );".printf(childname) );
+                   return;
+               }
+               
+               
+               switch (this.node.fqn()) {
+                       
+                               
+               
+                       case "Gtk.Fixed":
+                       case "Gtk.Layout":
+                               var x = child.has("x") ?  child.get_prop("x").val  : "0";
+                               var y = child.has("y") ?  child.get_prop("y").val  : "0";
+                               this.addLine(@"$(ipad)$(this_el)put( $(childname)$(el_name), $(x), $(y) );");
+                               return;
+                               
+                       
+
+                       case "Gtk.Stack":
+                               var named = child.has("stack_name") ?  child.get_prop("stack_name").val.escape() : "";
+                               var title = child.has("stack_title") ?  child.get_prop("stack_title").val.escape()  : "";
+                               if (title.length > 0) {
+                                       this.addLine(@"$(ipad)$(this_el)add_titled( $(childname)$(el_name), \"$(named)\", \"$(title)\" );");
+                                       return;
+                               } 
+                               this.addLine(@"$(ipad)$(this_el)add_named( $(childname)$(el_name), \"$(named)\");");
+                               return;
+                               
+                       case "Gtk.Notebook": // use label
+                               var label = child.has("notebook_label") ?  child.get_prop("notebook_label").val.escape() : "";
+                               this.addLine(@"$(ipad)$(this_el)append_page( $(childname)$(el_name), new Gtk.Label(\"$(label)\");");
+                               
+                               return;
+                               
+                        
+                       case "Gtk.TreeView": // adding TreeViewColumns
+                               this.addLine(this.ipad + "this.el.append_column( " + childname + ".el );");
+                               return;
+                       
+                       case "Gtk.TreeViewColumn": //adding Renderers - I think these are all proprerties of the renderer used...
+                               if (child.has("markup_column") && int.parse(child.get_prop("markup_column").val) > -1) {
+                                       var val = child.get_prop("markup_column").val;
+                                       this.addLine(@"$(ipad)$(this_el)add_attribute( $(childname)$(el_name), \"markup\", $(val) );");
+                               }
+                               if (child.has("text_column") && int.parse(child.get_prop("text_column").val) > -1) {
+                                       var val = child.get_prop("text_column").val;
+                                       this.addLine(@"$(ipad)$(this_el)add_attribute( $(childname)$(el_name), \"text\", $(val) );");
+                               }
+                               if (child.has("pixbuf_column") && int.parse(child.get_prop("pixbuf_column").val) > -1) {
+                                       var val = child.get_prop("pixbuf_column").val;
+                                       this.addLine(@"$(ipad)$(this_el).add_attribute( $(childname)$(el_name), \"pixbuf\", $(val) );");
+                               }
+                               if (child.has("pixbuf_column") && int.parse(child.get_prop("active_column").val) > -1) {
+                                       var val = child.get_prop("active_column").val;
+                                       this.addLine(@"$(ipad)$(this_el).add_attribute( $(childname)$(el_name), \"active\", $(val) );");
+                               }
+                               if (child.has("background_column") && int.parse(child.get_prop("background_column").val) > -1) {
+                               var val = child.get_prop("background_column").val;
+                                       this.addLine(@"$(ipad)$(this_el).add_attribute( $(childname)$(el_name), \"background-rgba\", $(val) );");
+                               }
+                               this.addLine(this.ipad + "this.el.add( " + childname + ".el );");
+                               // any more!?
+                               return;
+               
+                       case "Gtk.Dialog":
+                               if (propname == "buttons[]") {
+                                       var resp_id = int.parse(childname.replace("child_", ""));
+                                       if (child.has("* response_id")) { 
+                                               resp_id = int.parse(child.get_prop("* response_id").val);
+                                       }
+                                       this.addLine(@"$(ipad)$(this_el).add_action_widget( $(childname)$(el_name), $(resp_id) );");
+
+                                       return;
+                               }
+                       
+                               this.addLine(@"$(ipad)$$(this_el)get_content_area().add( $(childname)$(el_name) );");
+                               return;
+
+               
+                               
+                       
        
-                                         
-                       if (ci.xvala_id[0] != '+') {
-                               continue; // skip generation of children?
-                                               
-                       }
-                       // this.{id - without the '+'} = the element...
-                       this.addLine(this.ipad + "this." + ci.xvala_id.substring(1) + " =  child_" + "%d".printf(i) +  ";");
-                                 
+       
+       // known working with GTK4 !
+                       case "Gtk.HeaderBar": // it could be end... - not sure how to hanle that other than overriding                                  this.addLine(this.ipad + "this.el.add_action_widget( %s.el, %d);".printf(childname,resp_id) ); the pack method?
+                               this.addLine(@"$(ipad)$(this_el)pack_start( $(childname)$(el_name) );");
+                               return;
+                       
+                       case "GLib.Menu":
+                               this.addLine(@"$(ipad)$(this_el)append_item( $(childname)$(el_name) );");
+                               return; 
+                       
+                       case "Gtk.Paned":
+                               this.pane_number++;
+                               switch(this.pane_number) {
+                                       case 1:
+                                               this.addLine(@"$(ipad)$(this_el)pack_start( $(childname)$(el_name) );");
+                                               return;
+                                       case 2: 
+                                               this.addLine(@"$(ipad)$(this_el)pack_end( $(childname)$(el_name) );");
+                                               return;
+                                       default:
+                                               // do nothing
+                                               break;
+                               }
+                               return;
+                       
+                       case "Gtk.ColumnView":
+                               this.addLine(@"$(ipad)$(this_el)append_column( $(childname)$(el_name) );");
+                               return;
+                       
+                       case "Gtk.Grid":
+                               var x = "%d".printf(colpos % cols);
+                               var y = "%d".printf(( colpos - (colpos % cols) ) / cols);
+                               var w = child.has("colspan") ? child.get_prop("colspan").val : "1";
+                               var h = "1";
+                               this.addLine(@"$(ipad)$(this_el)attach( $(childname)$(el_name), $x, $y, $w, $h );");
+                               return;
+                       
+                       default:
+                               this.addLine(@"$(ipad)$(this_el)append( $(childname)$(el_name) );");
+                           // gtk4 uses append!!!! - gtk3 - uses add..
+                               return;
+               
+               
                }
+               
+               
        }
+       
+       // fixme GtkDialog?!? buttons[]
+       
+       // fixme ... add case "Gtk.RadioButton":  // group_id ??
 
-       void addInit()
+                       
+
+       protected void addInit()
        {
 
                
-               if (!this.node.has("init")) {
+               if (!this.node.has("init")) {
                                return;
                }
                this.addLine();
@@ -711,10 +664,12 @@ public class JsRender.NodeToVala : Object {
                this.addLine();
                this.node.setLine(this.cur_line, "p", "init");
                
-               this.addMultiLine(ipad + this.padMultiline(ipad, this.node.get("init")) );
-
+               var init =  this.node.get_prop("* init");
+               init.start_line = this.cur_line;
+               this.addMultiLine(ipad + this.padMultiline(ipad, init.val) );
+               init.end_line = this.cur_line;
         }
-        void addListeners()
+        protected void addListeners()
         {
                if (this.node.listeners.size < 1) {
                        return;
@@ -728,15 +683,17 @@ public class JsRender.NodeToVala : Object {
                var iter = this.node.listeners.map_iterator();
                while (iter.next()) {
                        var k = iter.get_key();
-                       var v = iter.get_value();
+                       var prop = iter.get_value();
+                       var v = prop.val;
                        
+                       prop.start_line = this.cur_line;
                        this.node.setLine(this.cur_line, "l", k);
-                       this.addMultiLine(this.ipad + "this.el." + k + ".connect( " + 
+                       this.addMultiLine(this.ipad + this.this_el + k + ".connect( " + 
                                        this.padMultiline(this.ipad,v) +");"); 
-                               
+                       prop.end_line = this.cur_line;
                }
        }    
-       void addEndCtor()
+       protected void addEndCtor()
        {
                         
                        // end ctor..
@@ -786,7 +743,7 @@ public class JsRender.NodeToVala : Object {
  * 
  */
         
-       void addUserMethods()
+       protected void addUserMethods()
        {
                this.addLine();
                this.addLine(this.pad + "// user defined functions");
@@ -794,27 +751,29 @@ public class JsRender.NodeToVala : Object {
                        // user defined functions...
                var iter = this.node.props.map_iterator();
                while(iter.next()) {
-                       var k = iter.get_key();
-                       if (this.shouldIgnore(k)) {
+                       var prop = iter.get_value();
+                       if (this.shouldIgnore(prop.name)) {
                                continue;
                        }
                        // HOW TO DETERIME if its a method?            
-                       if (k[0] != '|') {
+                       if (prop.ptype != NodePropType.METHOD) {
                                        //strbuilder("\n" + pad + "// skip " + k + " - not pipe \n"); 
                                        continue;
                        }
                        
                        // function in the format of {type} (args) { .... }
-                       var kk = k.substring(2);
-                       var vv = iter.get_value();
-                       this.node.setLine(this.cur_line, "p", k);
-                       this.addMultiLine(this.pad + "public " + kk + " " + this.padMultiline(this.pad, vv));;
-                       
+
+
+
+                       prop.start_line = this.cur_line;
+                       this.node.setLine(this.cur_line, "p", prop.name);
+                       this.addMultiLine(this.pad + "public " + prop.rtype + " " +  prop.name + " " + this.padMultiline(this.pad, prop.val));;
+                       prop.end_line = this.cur_line;
                                
                }
        }
 
-       void iterChildren()
+       protected void iterChildren()
        {
                this.node.line_end = this.cur_line;
                this.node.sortLines();
@@ -824,7 +783,7 @@ public class JsRender.NodeToVala : Object {
                        this.addLine(this.inpad + "}");
                }
                
-               var iter = this.node.items.list_iterator();
+               var iter = this.node.readItems().list_iterator();
                 
                while (iter.next()) {
                        this.addMultiLine(this.mungeChild(iter.get()));
@@ -835,26 +794,15 @@ public class JsRender.NodeToVala : Object {
                }
                        
        }
 
-       string padMultiline(string pad, string str)
-       {
-               var ar = str.strip().split("\n");
-               return string.joinv("\n" + pad , ar);
-       }
        
-       void ignore(string i) {
-               this.ignoreList.add(i);
-               
-       }
-       void ignoreWrapped(string i) {
+       protected void ignoreWrapped(string i) {
                this.ignoreWrappedList.add(i);
                
        }
-       bool shouldIgnore(string i)
-       {
-               return ignoreList.contains(i);
-       }
-       bool shouldIgnoreWrapped(string i)
+       
+       protected  bool shouldIgnoreWrapped(string i)
        {
                return ignoreWrappedList.contains(i);
        }
@@ -863,6 +811,4 @@ public class JsRender.NodeToVala : Object {
        
         
        
-       
-
-
+       
\ No newline at end of file