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