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                 
174                 
175                 
176                 
177                 // -------------  handle various child types.. -----------
178                 // our overrides
179                 if (cls == "GtkMenu") {
180                         this.packMenu();
181                         return;
182                 }
183
184                 if (cls == "GtkTreeStore") { // other stores?
185                         // tree store is buildable??? --- 
186                         this.packTreeStore();
187                         return;
188                 }
189                 if (cls =="GtkTreeViewColumn") { // other stores?
190                         //?? treeview column is actually buildable -- but we do not use the builder???
191                         this.packTreeViewColumn();
192                         return;
193                 }
194                 if (cls_gtype.is_a(typeof(global::Gtk.CellRenderer))) { // other stores?
195                         this.packCellRenderer();
196                         return;
197                 }
198
199
200                 
201                 // -- handle buildable add_child..
202                 if (    cls_gtype.is_a(typeof(global::Gtk.Buildable))
203                      && 
204                         parent.get_type().is_a(typeof(global::Gtk.Buildable))
205                 )
206                 {
207                         ((global::Gtk.Buildable)parent).add_child(gtkbuilder, 
208                                                   this.wrapped_object, null);
209                         return;
210                 }
211                 // other packing?
212
213                 
214
215         }
216
217         public void packMenu()
218         {
219
220
221                 var parent = this.parentObj.wrapped_object;
222                 if (!parent.get_type().is_a(typeof(global::Gtk.Widget))) {
223                         print("skip menu pack - parent is not a widget");
224                         return;
225                 }
226                 
227                 var p = (global::Gtk.Menu)this.wrapped_object;
228                 ((global::Gtk.Widget)parent).button_press_event.connect((s, ev) => { 
229                         p.set_screen(Gdk.Screen.get_default());
230                         p.show_all();
231                         p.popup(null, null, null, ev.button, ev.time);
232                         return true;
233                 });
234         }
235
236         public void packTreeStore()
237         {
238                 var parent = this.parentObj.wrapped_object;
239                 if (!parent.get_type().is_a(typeof(global::Gtk.TreeView))) {
240                         print("skip treestore pack - parent is not a treeview");
241                         return;
242                 }
243                 ((global::Gtk.TreeView)parent).set_model((global::Gtk.TreeModel)this.wrapped_object);
244                 
245         }
246         public void packTreeViewColumn()
247         {
248                 var parent = this.parentObj.wrapped_object;
249                 if (!parent.get_type().is_a(typeof(global::Gtk.TreeView))) {
250                         print("skip packGtkViewColumn pack - parent is not a treeview");
251                         return;
252                 }
253                 ((global::Gtk.TreeView)parent).append_column((global::Gtk.TreeViewColumn)this.wrapped_object);
254                 // init contains the add_attribute for what to render...
255                 
256         }       
257
258
259         public void packCellRenderer()
260         {
261                 var parent = this.parentObj.wrapped_object;
262                 if (!parent.get_type().is_a(typeof(global::Gtk.TreeViewColumn))) {
263                         print("skip packGtkViewColumn pack - parent is not a treeview");
264                         return;
265                 }
266                 ((global::Gtk.TreeViewColumn)parent).pack_start((global::Gtk.CellRenderer)this.wrapped_object, false);
267                 // init contains the add_attribute for what to render...
268                 
269         }       
270
271
272         public void packContainerParams()
273         {
274          
275                 if (this.parentObj == null) {
276                         return;
277                 }
278                 // child must be a widget..
279                 if (!this.wrapped_object.get_type().is_a(typeof(global::Gtk.Widget))) {
280                         return;
281                 }
282                 
283                 var parent_gir = Palete.Gir.factoryFqn(this.parentObj.node.fqn());
284
285                 var parent = this.parentObj.wrapped_object;
286                 
287                 if (parent_gir == null) {
288                         return;
289                 }
290                 
291                 // let's test just setting expand to false...
292                 var cls_methods = parent_gir.methods;
293                 if (cls_methods == null) {
294                         return;
295                 }
296         
297                 if (!this.node.props.has_key("* pack")) {
298                         return;
299                 }
300                 
301                 var ns = this.parentObj.node.fqn().split(".")[0];
302                  
303                 var pack = this.node.props.get("* pack").split(",");
304
305         
306                 if (cls_methods.has_key(pack[0])) {
307                         var mparams = cls_methods.get(pack[0]).paramset.params;
308                         for (var i = 1; i < mparams.size; i++ ) {
309                                 if (i > (pack.length -1)) {
310                                         continue;
311                                 }
312                         
313                                 var k = mparams.get(i).name;
314
315                                 Value cur_val;
316                                  
317                                 var type = mparams.get(i).type;
318                                 type = Palete.Gir.fqtypeLookup(type, ns);
319
320                                 var val = this.toValue(pack[i].strip(), type);
321                                 if (val == null) {
322                                         print("skip (failed to transform value %s type = %s from %s\n", 
323                                                 this.parentObj.node.fqn()  + "." + k, type, pack[i].strip());
324                                         continue;
325                                 }
326                                 print ("pack:set_property ( %s , %s / %s)\n", k, pack[i].strip(), val.strdup_contents());
327         
328                                 ((global::Gtk.Container)parent).child_set_property(
329                                         (global::Gtk.Widget)this.wrapped_object , k, val);
330                                  
331                         }
332                 
333                 }
334         
335
336
337                         
338         }
339                    
340
341         public GLib.Value? toValue(string val, string type) {
342
343                 var gtkbuilder = new global::Gtk.Builder();
344
345                 if (type == "utf8") {
346                         var qret = GLib.Value(typeof(string));
347                         qret.set_string(val);
348                         return qret;
349                 }
350                 
351                 var prop_gtype = gtkbuilder.get_type_from_name(type);
352                 
353
354                 if (prop_gtype == GLib.Type.INVALID) {
355                          
356                         return null;
357                 }
358                 
359                 
360                 var ret = GLib.Value(prop_gtype);
361
362
363                 switch(type) {
364                         case "gboolean":
365                                 ret.set_boolean(val.down() == "false" ? false : true);
366                                 return ret;
367                         case "guint":
368                                 ret.set_uint(int.parse(val));
369                                 return ret;
370                                 
371                         case "gint":
372                                 ret.set_int(int.parse(val));
373                                 return ret;
374
375                         case "gfloat":
376                                 ret.set_float(long.parse(val));
377                                 return ret;
378                                 
379                         case "utf8":
380                                 ret.set_string(val);
381                                 return ret;
382
383                         default:
384
385                                 var sval =  GLib.Value(typeof(string));
386                                 sval.set_string(val);
387                         
388                                 if (!sval.transform(ref ret)) {
389                                 
390                                         return null;
391                                 }
392                                 return ret;
393                 }
394         }
395         
396          
397           
398                 
399 }