bc862486349e24a440a1883ac222e0fcd815df8b
[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                 var is_top = false;
79                 if (this.parent == null) {
80                         is_top = true;
81                         this.doc = new Xml.Doc("1.0");
82
83                         var inf = this.create_element("interface");
84                         this.doc->set_root_element(inf);
85                         var req = this.create_element("requires");
86                         req->set_prop("lib", "gtk+");
87                         req->set_prop("version", "4.1");
88                         inf->add_child(req);
89                         this.parent = inf;
90                 } 
91                 
92                 var cls = this.node.fqn().replace(".", "");
93                 
94                 var gdata = Palete.Gir.factoryFqn(this.project, this.node.fqn());
95                 if (gdata == null || !gdata.inherits.contains("Gtk.Buildable")) {
96                         switch(cls) {
97                         //exception to the rule.. (must be buildable to work with glade?
98                                 
99                                 case "GtkNotebookPage": 
100                                         if (this.node.childstore.get_n_items() < 1) {
101                                                 return null;
102                                         }
103                                         break;
104                                 
105                                 case "GtkColumnViewColumn": 
106                                         break;
107                                 
108                                 default:
109                                         GLib.debug("Skip %s - is not buildable / no data", cls);
110                                         return null;
111                         }
112                 }
113                 if (gdata.inherits.contains("Gtk.Native")&& !is_top) {
114                         return null;
115                 }
116                 // what namespaces are supported
117                 switch(this.node.NS) {
118                         case "Gtk":
119                         case "WebKit": //??
120                         case "Adw": // works if you call adw.init() in main!
121                                 break;
122                         default:
123                                 GLib.debug("Skip %s - NS is not available", cls);
124                                 return null;
125                 }
126                 
127                 // other problems!!!
128                 
129                 if (gdata.fqn() == ("Gtk.ListStore")) {
130                         return null;
131                 }
132                  
133                  // <object class="GtkNotebookPage">
134         //         <property name="tab-expand">1</property>
135          //       <property name="child">
136                  //      <property name="label">
137                 // should really use GXml... 
138                 var obj = this.create_element("object");
139                 //var id = this.node.uid();
140                 var skip_props = false;
141                 if (gdata.inherits.contains("Gtk.Native")) {
142                          
143                         obj->set_prop("class", "GtkFrame");
144                         skip_props = true;
145                 } else {
146                         switch(cls) {
147                                 case  "GtkHeaderBar":
148                                         obj->set_prop("class", "GtkBox");
149                                         this.addProperty(obj, "orientation", "horizontal");
150                                         skip_props = true;
151                                         break;
152                         
153                                 default:
154                                         obj->set_prop("class", cls);
155                                         break;
156                         }       
157                 }
158                 
159                 obj->set_prop("id", "w" + this.node.oid.to_string());
160                 this.parent->add_child(obj);
161                 // properties..
162                 var props = Palete.Gir.factoryFqn(this.project, this.node.fqn()).props;
163  
164               
165                 var pviter = props.map_iterator();
166                 while (!skip_props && pviter.next()) {
167                         
168                         //GLib.debug ("Check: " +cls + "::(" + pviter.get_value().propertyof + ")" + pviter.get_key() + " " );
169                         
170                 // skip items we have already handled..
171                 if  (!this.node.has(pviter.get_key())) {
172                                 continue;
173                         }
174                         var k = pviter.get_key();       
175                         var prop = props.get(k);
176                         var val = this.node.get(pviter.get_key()).strip();      
177                         // for Enums - we change it to lowercase, and remove all the previous bits.. hopefully might work.
178                         if (prop.type.contains(".") && val.contains(".")) {
179                                 var typ =  Palete.Gir.factoryFqn(this.project, prop.type);
180                                 if (typ.nodetype == "Enum") {
181                                          var bits = val.split(".");
182                                          val = bits[bits.length-1].down();
183                                 }
184                         }
185                         
186                         //  value for model seems to cause problems...(it's ok as a property?)
187                         if (k == "model") {
188                                 continue;
189                         }
190                         this.addProperty(obj, k, val);
191
192                          
193         }
194                 // packing???
195 /*
196                 var pack = "";
197                 
198                 if (with_packing   ) {
199  
200                         pack = this.packString();
201                         
202
203                 
204                 }       */
205                 // children..
206                 var left = 0, top = 0, cols = 1;
207                 if (cls == "GtkGrid") { 
208                 var colval = this.node.get_prop("* columns");
209                         GLib.debug("Columns %s", colval == null ? "no columns" : colval.val);
210                         if (colval != null) {
211                                 cols = int.parse(colval.val);
212                         }
213                 }
214                 var items = this.node.readItems();
215                 for (var i = 0; i < items.size; i++ ) {
216                         var cn = items.get(i);
217                         
218                         var childname = "child";
219                         var pname = "";
220                         if (cn.has("* prop")) { // && cn.get_prop("* prop").val == "child") {
221                                 childname = "property";
222                                 pname = cn.get_prop("* prop").val;
223                         }
224                         
225                         var child  = this.create_element(childname);
226                         if (pname != "") {
227                                 child->set_prop("name", pname);
228                         }
229                         
230                         if ((cls == "GtkWindow" || cls == "GtkApplicationWindow") && cn.fqn() == "Gtk.HeaderBar") {
231                                 child->set_prop("type", "label");
232                         }
233                         
234                         
235                         var sub_obj = this.mungeChild(cn, child);
236                         if (sub_obj == null) {
237                                 continue;
238                         }
239                         if (cls == "GtkGrid") {
240                                 this.addGridAttach(sub_obj, left, top);
241                                 left++;
242                                 if (left == cols) {
243                                         left = 0;
244                                         top++;
245                                 }
246                         
247                         
248                         }
249                         
250                         
251                         
252                         
253                         if (child->child_element_count()  < 1) {
254                                 continue;
255                         }
256                         obj->add_child(child);
257                          
258                 }
259                 return obj;
260
261                  
262
263         }
264         void addProperty(Xml.Node* obj, string k, string val) 
265         {
266                 var domprop = this.create_element("property");
267                 domprop->set_prop("name", k);
268                 domprop->add_child(new Xml.Node.text(val));
269                 obj->add_child(domprop); 
270         }
271          void addGridAttach(Xml.Node* obj, int left, int top) 
272         {
273                 var layout = this.create_element("layout");
274                 this.addProperty(layout, "column", left.to_string());
275                 this.addProperty(layout, "row", top.to_string());
276                 obj->add_child(layout); 
277                 
278         }
279
280
281                 
282 }