Fix #8102 - glade view include gtksource
[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                         case "GtkSource":
122                                 break;
123                         default:
124                                 GLib.debug("Skip %s - NS is not available", cls);
125                                 return null;
126                 }
127                 
128                 // other problems!!!
129                 
130                 if (gdata.fqn() == ("Gtk.ListStore")) {
131                         return null;
132                 }
133                  
134                  // <object class="GtkNotebookPage">
135         //         <property name="tab-expand">1</property>
136          //       <property name="child">
137                  //      <property name="label">
138                 // should really use GXml... 
139                 var obj = this.create_element("object");
140                 //var id = this.node.uid();
141                 var skip_props = false;
142                 if (gdata.inherits.contains("Gtk.Native")) {
143                          
144                         obj->set_prop("class", "GtkFrame");
145                         skip_props = true;
146                 } else {
147                         switch(cls) {
148                                 case  "GtkHeaderBar":
149                                         obj->set_prop("class", "GtkBox");
150                                         this.addProperty(obj, "orientation", "horizontal");
151                                         skip_props = true;
152                                         break;
153                         
154                                 default:
155                                         obj->set_prop("class", cls);
156                                         break;
157                         }       
158                 }
159                 
160                 obj->set_prop("id", "w" + this.node.oid.to_string());
161                 this.parent->add_child(obj);
162                 // properties..
163                 var props = Palete.Gir.factoryFqn(this.project, this.node.fqn()).props;
164  
165               
166                 var pviter = props.map_iterator();
167                 while (!skip_props && pviter.next()) {
168                         
169                         //GLib.debug ("Check: " +cls + "::(" + pviter.get_value().propertyof + ")" + pviter.get_key() + " " );
170                         
171                 // skip items we have already handled..
172                 if  (!this.node.has(pviter.get_key())) {
173                                 continue;
174                         }
175                         var k = pviter.get_key();       
176                         var prop = props.get(k);
177                         var val = this.node.get(pviter.get_key()).strip();      
178                         // for Enums - we change it to lowercase, and remove all the previous bits.. hopefully might work.
179                         if (prop.type.contains(".") && val.contains(".")) {
180                                 var typ =  Palete.Gir.factoryFqn(this.project, prop.type);
181                                 if (typ.nodetype == "Enum") {
182                                          var bits = val.split(".");
183                                          val = bits[bits.length-1].down();
184                                 }
185                         }
186                         
187                         //  value for model seems to cause problems...(it's ok as a property?)
188                         if (k == "model") {
189                                 continue;
190                         }
191                         this.addProperty(obj, k, val);
192
193                          
194         }
195                 // packing???
196 /*
197                 var pack = "";
198                 
199                 if (with_packing   ) {
200  
201                         pack = this.packString();
202                         
203
204                 
205                 }       */
206                 // children..
207                 var left = 0, top = 0, cols = 1;
208                 if (cls == "GtkGrid") { 
209                 var colval = this.node.get_prop("* columns");
210                         GLib.debug("Columns %s", colval == null ? "no columns" : colval.val);
211                         if (colval != null) {
212                                 cols = int.parse(colval.val);
213                         }
214                 }
215                 var items = this.node.readItems();
216                 for (var i = 0; i < items.size; i++ ) {
217                         var cn = items.get(i);
218                         
219                         var childname = "child";
220                         var pname = "";
221                         if (cn.has("* prop")) { // && cn.get_prop("* prop").val == "child") {
222                                 childname = "property";
223                                 pname = cn.get_prop("* prop").val;
224                         }
225                         
226                         var child  = this.create_element(childname);
227                         if (pname != "") {
228                                 child->set_prop("name", pname);
229                         }
230                         
231                         if ((cls == "GtkWindow" || cls == "GtkApplicationWindow") && cn.fqn() == "Gtk.HeaderBar") {
232                                 child->set_prop("type", "label");
233                         }
234                         
235                         
236                         var sub_obj = this.mungeChild(cn, child);
237                         if (sub_obj == null) {
238                                 continue;
239                         }
240                         if (cls == "GtkGrid") {
241                                 this.addGridAttach(sub_obj, left, top);
242                                 left++;
243                                 if (left == cols) {
244                                         left = 0;
245                                         top++;
246                                 }
247                         
248                         
249                         }
250                         
251                         
252                         
253                         
254                         if (child->child_element_count()  < 1) {
255                                 continue;
256                         }
257                         obj->add_child(child);
258                          
259                 }
260                 return obj;
261
262                  
263
264         }
265         void addProperty(Xml.Node* obj, string k, string val) 
266         {
267                 var domprop = this.create_element("property");
268                 domprop->set_prop("name", k);
269                 domprop->add_child(new Xml.Node.text(val));
270                 obj->add_child(domprop); 
271         }
272          void addGridAttach(Xml.Node* obj, int left, int top) 
273         {
274                 var layout = this.create_element("layout");
275                 this.addProperty(layout, "column", left.to_string());
276                 this.addProperty(layout, "row", top.to_string());
277                 obj->add_child(layout); 
278                 
279         }
280
281
282                 
283 }