src/JsRender/NodeToGtk.vala
[app.Builder.js] / src / JsRender / NodeToGtk.vala
1 /*
2
3  
4 */
5 public class JsRender.NodeToGtk : Object {
6
7         Node node;
8         Object wrapped_object; 
9         NodeToGtk parentObj;
10         
11         Gee.ArrayList<string> els;
12         //Gee.ArrayList<string> skip;
13         Gee.HashMap<string,string> ar_props;
14         public static int vcnt = 0; 
15
16         public NodeToGtk( Node node) 
17         {
18                 this.node = node;
19                 this.els = new Gee.ArrayList<string>(); 
20                 //this.skip = new Gee.ArrayList<string>();
21                 this.ar_props = new Gee.HashMap<string,string>();
22                 this.parentObj = null;
23         }
24         
25         public Object? munge ( )
26         {
27
28                  return this.mungeNode ();
29                  
30                      
31         }
32         public Object? mungeChild(  Node cnode)
33         {
34                 var x = new  NodeToGtk(cnode);
35                 x.parentObj = this;
36                 return x.mungeNode();
37         }
38         
39         public Object? mungeNode()
40         {
41
42                 var parent = this.parentObj != null ? this.parentObj.wrapped_object : null;
43                 var cls = this.node.fqn().replace(".", "");
44                 var ns = this.node.fqn().split(".")[0];
45                 var gtkbuilder = new global::Gtk.Builder();
46
47                 var cls_gtype = gtkbuilder.get_type_from_name(cls);
48                 print("Type: %s ?= %s\n", this.node.fqn(), cls_gtype.name());
49
50                 if (cls_gtype == GLib.Type.INVALID) {
51                         print("SKIP - gtype is invalid\n");
52                         return null;
53                 }
54                 // if it's a window... 
55
56                 if (cls_gtype.is_a(typeof(global::Gtk.Window))) {
57                         // what if it has none...
58                         if (this.node.items.size < 1) {
59                                 return null;
60                         }
61                         return this.mungeChild(this.node.items.get(0));
62                 }
63
64                 var ret = Object.new(cls_gtype);
65                 ret.ref(); //??? problematic?
66                 this.wrapped_object = ret;
67                 
68                  
69                 switch(cls) {
70                         // fixme
71                         //case "GtkTreeStore": // top level.. - named and referenced
72                         case "GtkListStore": // top level.. - named and referenced
73                         //case "GtkTreeViewColumn": // part of liststore?!?!
74                         //case "GtkMenu": // top level..
75                         //case "GtkCellRendererText":
76                         case "GtkSourceBuffer":                         
77                         case "GtkClutterActor"://fixme..
78                         case "GtkClutterEmbed"://fixme.. -- we can not nest embedded.. need to solve..
79                                         
80                                 return null;
81                 }
82
83                 this.packParent();
84                 
85
86                 // pack paramenters
87
88                 
89                 if (parent != null && parent.get_type().is_a(typeof(global::Gtk.Container))) {
90                         this.packContainerParams();
91                 }
92                 
93                 var cls_gir =Palete.Gir.factoryFqn(this.node.fqn()); 
94                 if (cls_gir == null) {
95                         return null;
96                 }
97                 //var id = this.node.uid();
98                 //var ret = @"$pad<object class=\"$cls\" id=\"$id\">\n";
99                 // properties..
100                 var props = cls_gir.props;
101                 
102               
103                 var pviter = props.map_iterator();
104                 while (pviter.next()) {
105                         
106                                 // print("Check: " +cls + "::(" + pviter.get_value().propertyof + ")" + pviter.get_key() + " " );
107                         var k = pviter.get_key();
108                         // skip items we have already handled..
109                         if  (!this.node.has(k)) {
110                                 continue;
111                         }
112                         // find out the type of the property...
113                         var type = pviter.get_value().type;
114                         type = Palete.Gir.fqtypeLookup(type, ns);
115
116                         var val = this.toValue(this.node.get(k).strip(), type);
117                         if (val == null) {
118                                 print("skip (failed to transform value %s type = %s from %s\n", 
119                                         cls + "." + k, type,  this.node.get(k).strip());
120                                 continue;
121                         }
122                         print ("set_property ( %s , %s / %s)\n", k, this.node.get(k).strip(), val.strdup_contents());
123                         
124                         
125                         ret.set_property(k, val);  
126                         
127
128                 }
129                 // packing???
130                 // for now... - just try the builder style packing
131                 
132                 
133                  
134                 if (this.node.items.size < 1) {
135                         return ret;
136                 }
137                 
138                 for (var i = 0; i < this.node.items.size; i++ ) {
139
140                          this.mungeChild(this.node.items.get(i));
141                          
142                 }
143                 
144                 return ret;
145                 
146
147                  
148
149         }
150         /**
151          * called after the this.object  has been created
152          * and it needs to be packed onto parent.
153          */
154         public void packParent() 
155         {
156                 var cls = this.node.fqn().replace(".", "");
157                 
158                 var gtkbuilder = new global::Gtk.Builder();
159                 var cls_gtype = gtkbuilder.get_type_from_name(cls);
160
161                 if (this.parentObj == null) {
162                         return;
163                 }
164                                 
165                     
166                 var parent = this.parentObj.wrapped_object;
167                 
168                 var do_pack =true;
169
170                 if (parent == null) { // no parent.. can not pack.
171                         return;
172                 }
173                 // -------------  handle various special parents .. -----------
174                 
175                 var par_type = this.parentObj.node.fqn().replace(".", "");
176                 
177                 if (par_type == "GtkNotebook") {
178                         this.packIntoNotebook();
179                         return;
180                 }
181                 
182                 // -------------  handle various child types.. -----------
183                 // our overrides
184                 if (cls == "GtkMenu") {
185                         this.packMenu();
186                         return;
187                 }
188
189                 if (cls == "GtkTreeStore") { // other stores?
190                         // tree store is buildable??? --- 
191                         this.packTreeStore();
192                         return;
193                 }
194                 if (cls =="GtkTreeViewColumn") { // other stores?
195                         //?? treeview column is actually buildable -- but we do not use the builder???
196                         this.packTreeViewColumn();
197                         return;
198                 }
199                 if (cls_gtype.is_a(typeof(global::Gtk.CellRenderer))) { // other stores?
200                         this.packCellRenderer();
201                         return;
202                 }
203
204
205                 
206                 // -- handle buildable add_child..
207                 if (    cls_gtype.is_a(typeof(global::Gtk.Buildable))
208                      && 
209                         parent.get_type().is_a(typeof(global::Gtk.Buildable))
210                 )
211                 {
212                         ((global::Gtk.Buildable)parent).add_child(gtkbuilder, 
213                                                   this.wrapped_object, null);
214                         return;
215                 }
216                 // other packing?
217
218                 
219
220         }
221
222         public void packMenu()
223         {
224
225
226                 var parent = this.parentObj.wrapped_object;
227                 if (!parent.get_type().is_a(typeof(global::Gtk.Widget))) {
228                         print("skip menu pack - parent is not a widget");
229                         return;
230                 }
231                 
232                 var p = (global::Gtk.Menu)this.wrapped_object;
233                 ((global::Gtk.Widget)parent).button_press_event.connect((s, ev) => { 
234                         p.set_screen(Gdk.Screen.get_default());
235                         p.show_all();
236                         p.popup(null, null, null, ev.button, ev.time);
237                         return true;
238                 });
239         }
240
241         public void packTreeStore()
242         {
243                 var parent = this.parentObj.wrapped_object;
244                 if (!parent.get_type().is_a(typeof(global::Gtk.TreeView))) {
245                         print("skip treestore pack - parent is not a treeview");
246                         return;
247                 }
248                 ((global::Gtk.TreeView)parent).set_model((global::Gtk.TreeModel)this.wrapped_object);
249                 
250         }
251         public void packTreeViewColumn()
252         {
253                 var parent = this.parentObj.wrapped_object;
254                 if (!parent.get_type().is_a(typeof(global::Gtk.TreeView))) {
255                         print("skip packGtkViewColumn pack - parent is not a treeview");
256                         return;
257                 }
258                 ((global::Gtk.TreeView)parent).append_column((global::Gtk.TreeViewColumn)this.wrapped_object);
259                 // init contains the add_attribute for what to render...
260                 
261         }       
262
263
264         public void packCellRenderer()
265         {
266                 var parent = this.parentObj.wrapped_object;
267                 if (!parent.get_type().is_a(typeof(global::Gtk.TreeViewColumn))) {
268                         print("skip packGtkViewColumn pack - parent is not a treeview");
269                         return;
270                 }
271                 ((global::Gtk.TreeViewColumn)parent).pack_start((global::Gtk.CellRenderer)this.wrapped_object, false);
272                 // init contains the add_attribute for what to render...
273                 
274         }       
275
276
277         public void packContainerParams()
278         {
279          
280                 if (this.parentObj == null) {
281                         return;
282                 }
283                 // child must be a widget..
284                 if (!this.wrapped_object.get_type().is_a(typeof(global::Gtk.Widget))) {
285                         return;
286                 }
287                 
288                 var parent_gir = Palete.Gir.factoryFqn(this.parentObj.node.fqn());
289
290                 var parent = this.parentObj.wrapped_object;
291                 
292                 if (parent_gir == null) {
293                         return;
294                 }
295                 
296                 // let's test just setting expand to false...
297                 var cls_methods = parent_gir.methods;
298                 if (cls_methods == null) {
299                         return;
300                 }
301         
302                 if (!this.node.props.has_key("* pack")) {
303                         return;
304                 }
305                 
306                 var ns = this.parentObj.node.fqn().split(".")[0];
307                  
308                 var pack = this.node.props.get("* pack").split(",");
309
310         
311                 if (cls_methods.has_key(pack[0])) {
312                         var mparams = cls_methods.get(pack[0]).paramset.params;
313                         for (var i = 1; i < mparams.size; i++ ) {
314                                 if (i > (pack.length -1)) {
315                                         continue;
316                                 }
317                         
318                                 var k = mparams.get(i).name;
319
320                                 Value cur_val;
321                                  
322                                 var type = mparams.get(i).type;
323                                 type = Palete.Gir.fqtypeLookup(type, ns);
324
325                                 var val = this.toValue(pack[i].strip(), type);
326                                 if (val == null) {
327                                         print("skip (failed to transform value %s type = %s from %s\n", 
328                                                 this.parentObj.node.fqn()  + "." + k, type, pack[i].strip());
329                                         continue;
330                                 }
331                                 print ("pack:set_property ( %s , %s / %s)\n", k, pack[i].strip(), val.strdup_contents());
332         
333                                 ((global::Gtk.Container)parent).child_set_property(
334                                         (global::Gtk.Widget)this.wrapped_object , k, val);
335                                  
336                         }
337                 
338                 }
339         
340
341
342                         
343         }
344                    
345
346         public GLib.Value? toValue(string val, string type) {
347
348                 var gtkbuilder = new global::Gtk.Builder();
349
350                 if (type == "utf8") {
351                         var qret = GLib.Value(typeof(string));
352                         qret.set_string(val);
353                         return qret;
354                 }
355                 
356                 var prop_gtype = gtkbuilder.get_type_from_name(type);
357                 
358
359                 if (prop_gtype == GLib.Type.INVALID) {
360                          
361                         return null;
362                 }
363                 
364                 
365                 var ret = GLib.Value(prop_gtype);
366
367
368                 switch(type) {
369                         case "gboolean":
370                                 ret.set_boolean(val.down() == "false" ? false : true);
371                                 return ret;
372                         case "guint":
373                                 ret.set_uint(int.parse(val));
374                                 return ret;
375                                 
376                         case "gint":
377                                 ret.set_int(int.parse(val));
378                                 return ret;
379
380                         case "gfloat":
381                                 ret.set_float(long.parse(val));
382                                 return ret;
383                                 
384                         case "utf8":
385                                 ret.set_string(val);
386                                 return ret;
387
388                         default:
389
390                                 var sval =  GLib.Value(typeof(string));
391                                 sval.set_string(val);
392                         
393                                 if (!sval.transform(ref ret)) {
394                                 
395                                         return null;
396                                 }
397                                 return ret;
398                 }
399         }
400         
401          
402           
403                 
404 }