Fix #8063 - see if we can improve glade dump
[roobuilder] / src / JsRender / NodeToGlade.vala
1 /*
2  This kind of works - however there are issues with embedding gladeui that do not seem fixable.
3  - rendering is borked for windows - they detach for some reason.
4  - selecting stuff and drag etc. would probably be complicated...
5  
6  
7 */
8 public class JsRender.NodeToGlade : Object {
9
10         Node node;
11         Project.Gtk project;
12         Xml.Node* parent;
13         Xml.Doc* doc;
14         
15         public NodeToGlade( Project.Gtk project, Node node, Xml.Node* parent) 
16         {
17                 
18                 this.parent = parent;
19                 this.project = project;
20                 this.node = node;
21                 
22         }
23         
24         public static string mungeFile(JsRender file) 
25         {
26                 if (file.tree == null) {
27                         return "";
28                 }
29
30                 var n = new NodeToGlade(  (Project.Gtk) file.project, file.tree,  null);
31         
32                 ///n.toValaName(file.tree);
33                 
34                 
35                 //GLib.debug("top cls %s / xlcs %s ",file.tree.xvala_cls,file.tree.xvala_cls); 
36                 //n.cls = file.tree.xvala_cls;
37                 //n.xcls = file.tree.xvala_xcls;
38                 return n.munge();
39                 
40
41         }
42         
43         public string munge ( )
44         {
45
46
47                 this.mungeNode ();
48                 string ret;
49                 int len;
50         this.doc->dump_memory_format (out ret, out len, true);
51
52                 return ret;
53         
54           
55                      
56         }
57         public Xml.Node* mungeChild( Node cnode , Xml.Node* cdom)
58         {
59                 var x = new  NodeToGlade(this.project, cnode,  cdom);
60                 return x.mungeNode();
61         }
62         public static Xml.Ns* ns = null;
63         
64         
65         public  Xml.Node* create_element(string n)
66         {
67                 if (NodeToGlade.ns == null) {
68                         Xml.Ns* ns = new Xml.Ns (null, "", "");
69                 ns->type = Xml.ElementType.ELEMENT_NODE;
70                 }
71                 Xml.Node* nn =  new Xml.Node (ns, n);
72        return nn;
73         
74         }
75         
76         public Xml.Node* mungeNode()
77         {
78                  
79                 var is_top = false;
80                 if (this.parent == null) {
81                         is_top = true;
82                         this.doc = new Xml.Doc("1.0");
83
84                         var inf = this.create_element("interface");
85                         this.doc->set_root_element(inf);
86                         var req = this.create_element("requires");
87                         req->set_prop("lib", "gtk+");
88                         req->set_prop("version", "4.1");
89                         inf->add_child(req);
90                         this.parent = inf;
91                 } 
92                 
93                 var cls = this.node.fqn().replace(".", "");
94                 
95                 var gdata = Palete.Gir.factoryFqn(this.project, this.node.fqn());
96                 if (gdata == null || !gdata.inherits.contains("Gtk.Buildable")) {
97                         switch(cls) {
98                                 case "GtkColumnViewColumn": //exception to the rule..
99                                         break;
100                                 default:
101                                         return null;
102                         }
103                 }
104                 if (gdata.inherits.contains("Gtk.Native")&& !is_top) {
105                         return null;
106                 }
107                 // what namespaces are supported
108                 switch(this.node.NS) {
109                         case "Gtk":
110                         case "Webkit": //??
111                         case "Adw": // works if you call adw.init() in main!
112                                 break;
113                         default:
114                                 return null;
115                 }
116                 
117                 // other problems!!!
118                 
119                 if (gdata.fqn() == ("Gtk.ListStore")) {
120                         return null;
121                 }
122                  
123                  // <object class="GtkNotebookPage">
124         //         <property name="tab-expand">1</property>
125          //       <property name="child">
126                  //      <property name="label">
127                 // should really use GXml... 
128                 var obj = this.create_element("object");
129                 //var id = this.node.uid();
130                 var skip_props = false;
131                 if (gdata.inherits.contains("Gtk.Native")) {
132                          
133                         obj->set_prop("class", "GtkFrame");
134                         skip_props = true;
135                 } else {
136                         switch(cls) {
137                                 case  "GtkHeaderBar":
138                                         obj->set_prop("class", "GtkBox");
139                                         this.addProperty(obj, "orientation", "horizontal");
140                                         skip_props = true;
141                                         break;
142                         
143                                 default:
144                                         obj->set_prop("class", cls);
145                                         break;
146                         }       
147                 }
148                 
149                 obj->set_prop("id", "w" + this.node.oid.to_string());
150                 this.parent->add_child(obj);
151                 // properties..
152                 var props = Palete.Gir.factoryFqn(this.project, this.node.fqn()).props;
153  
154               
155                 var pviter = props.map_iterator();
156                 while (!skip_props && pviter.next()) {
157                         
158                         //GLib.debug ("Check: " +cls + "::(" + pviter.get_value().propertyof + ")" + pviter.get_key() + " " );
159                         
160                 // skip items we have already handled..
161                 if  (!this.node.has(pviter.get_key())) {
162                                 continue;
163                         }
164                         var k = pviter.get_key();       
165                         var prop = props.get(k);
166                         var val = this.node.get(pviter.get_key()).strip();      
167                         // for Enums - we change it to lowercase, and remove all the previous bits.. hopefully might work.
168                         if (prop.type.contains(".") && val.contains(".")) {
169                                 var typ =  Palete.Gir.factoryFqn(this.project, prop.type);
170                                 if (typ.nodetype == "Enum") {
171                                          var bits = val.split(".");
172                                          val = bits[bits.length-1].down();
173                                 }
174                         }
175                         
176                         //  value for model seems to cause problems...(it's ok as a property?)
177                         if (k == "model") {
178                                 continue;
179                         }
180                         this.addProperty(obj, k, val);
181
182                          
183         }
184                 // packing???
185 /*
186                 var pack = "";
187                 
188                 if (with_packing   ) {
189  
190                         pack = this.packString();
191                         
192
193                 
194                 }       */
195                 // children..
196                 var left = 0, top = 0, cols = 1;
197                 if (cls == "GtkGrid") { 
198                 var colval = this.node.get_prop("* columns");
199                         GLib.debug("Columns %s", colval == null ? "no columns" : colval.val);
200                         if (colval != null) {
201                                 cols = int.parse(colval.val);
202                         }
203                 }
204                 var items = this.node.readItems();
205                 for (var i = 0; i < items.size; i++ ) {
206                         var cn = items.get(i);
207                         var child  = this.create_element("child");
208                         if ((cls == "GtkWindow" || cls == "GtkApplicationWindow") && cn.fqn() == "Gtk.HeaderBar") {
209                                 child->set_prop("type", "label");
210                         }
211                         
212                         
213                         var sub_obj = this.mungeChild(cn, child);
214                         if (sub_obj == null) {
215                                 continue;
216                         }
217                         if (cls == "GtkGrid") {
218                                 this.addGridAttach(sub_obj, left, top);
219                                 left++;
220                                 if (left == cols) {
221                                         left = 0;
222                                         top++;
223                                 }
224                         
225                         
226                         }
227                         
228                         
229                         
230                         
231                         if (child->child_element_count()  < 1) {
232                                 continue;
233                         }
234                         obj->add_child(child);
235                          
236                 }
237                 return obj;
238
239                  
240
241         }
242         void addProperty(Xml.Node* obj, string k, string val) 
243         {
244                 var domprop = this.create_element("property");
245                 domprop->set_prop("name", k);
246                 domprop->add_child(new Xml.Node.text(val));
247                 obj->add_child(domprop); 
248         }
249          void addGridAttach(Xml.Node* obj, int left, int top) 
250         {
251                 var layout = this.create_element("layout");
252                 this.addProperty(layout, "column", left.to_string());
253                 this.addProperty(layout, "row", top.to_string());
254                 obj->add_child(layout); 
255                 
256         }
257
258
259                 
260 }