3 * This code renders the Gtk tree into a set of Gtk elements.
4 * principle = one NodeToGtk wraps around the original 'node'
6 * it's called by the view element with
7 * var x = new JsRender.NodeToGtk(file.tree);
8 var obj = x.munge() as Gtk.Widget;
12 * The idea behind the Javascript tools stuff is that we can
13 * transform what is actually being requested to be rendered
14 * -- eg. an AboutBox, and turn that into load of real widgets..
15 * that could be displayed..
17 * we could go on the theory that we send the whole tree to the 'plugin'
18 * and that would do all the transformations before rendering..
19 * -- this would make more sense...
20 * -- otherwise we would call it on each element, and might get really confused
26 public class JsRender.NodeToGtk : Object {
29 Object wrapped_object;
32 Gee.ArrayList<NodeToGtk> children;
34 Gee.ArrayList<string> els;
35 //Gee.ArrayList<string> skip;
36 Gee.HashMap<string,string> ar_props;
37 public static int vcnt = 0;
41 public NodeToGtk( Project.Gtk project, Node node , NodeToGtk? parent_obj = null)
44 this.project = project;
46 this.els = new Gee.ArrayList<string>();
47 this.children = new Gee.ArrayList<NodeToGtk>();
48 //this.skip = new Gee.ArrayList<string>();
49 this.ar_props = new Gee.HashMap<string,string>();
50 this.parentObj = parent_obj;
52 if (parent_obj == null) {
53 // then serialize up the node,
54 // send it to javascript for processsing,
55 // then rebuild node from return value..
57 var ret = Palete.Javascript.singleton().executeFile(
58 BuilderApplication.configDirectory() + "/resources/node_to_gtk.js",
62 var new_node = new Node();
63 var pa = new Json.Parser();
64 pa.load_from_data(ret);
65 var rnode = pa.get_root();
68 new_node.loadFromJson(rnode.get_object(), 2);
71 } catch (Palete.JavascriptError e) {
72 print("Error: %s\n", e.message);
80 public Object? munge ( )
82 var ret = this.mungeNode( );
87 return ret.wrapped_object;
90 public NodeToGtk? mungeChild ( Node cnode)
92 var x = new NodeToGtk( this.project, cnode, this);
98 public NodeToGtk? mungeNode()
101 var parent = this.parentObj != null ? this.parentObj.wrapped_object : null;
102 var cls = this.node.fqn().replace(".", "");
103 var ns = this.node.fqn().split(".")[0];
104 var gtkbuilder = new global::Gtk.Builder();
106 var cls_gtype = gtkbuilder.get_type_from_name(cls);
107 print("Type: %s ?= %s\n", this.node.fqn(), cls_gtype.name());
109 if (cls_gtype == GLib.Type.INVALID) {
110 print("SKIP - gtype is invalid\n");
113 // if it's a window... -- things we can not render....
115 if (cls_gtype.is_a(typeof(global::Gtk.Window))) {
116 // what if it has none...
117 if (this.node.items.size < 1) {
120 return this.mungeChild(this.node.items.get(0));
122 if (cls_gtype.is_a(typeof(global::Gtk.Popover))) {
123 // what if it has none...
124 if (this.node.items.size < 1) {
127 return this.mungeChild(this.node.items.get(0));
130 var ret = Object.new(cls_gtype);
131 ret.ref(); //??? problematic?
132 this.wrapped_object = ret;
137 //case "GtkTreeStore": // top level.. - named and referenced
138 case "GtkListStore": // top level.. - named and referenced
139 //case "GtkTreeViewColumn": // part of liststore?!?!
140 //case "GtkMenu": // top level..
141 //case "GtkCellRendererText":
142 case "GtkSourceBuffer":
143 case "GtkClutterActor"://fixme..
144 case "GtkClutterEmbed"://fixme.. -- we can not nest embedded.. need to solve..
155 if (parent != null && parent.get_type().is_a(typeof(global::Gtk.Container))) {
156 this.packContainerParams();
159 var cls_gir =Palete.Gir.factoryFqn(this.project, this.node.fqn());
160 if (cls_gir == null) {
163 //var id = this.node.uid();
164 //var ret = @"$pad<object class=\"$cls\" id=\"$id\">\n";
166 var props = cls_gir.props;
169 var pviter = props.map_iterator();
170 while (pviter.next()) {
172 // print("Check: " +cls + "::(" + pviter.get_value().propertyof + ")" + pviter.get_key() + " " );
173 var k = pviter.get_key();
174 // skip items we have already handled..
175 if (!this.node.has(k)) {
178 // find out the type of the property...
179 var type = pviter.get_value().type;
180 type = Palete.Gir.fqtypeLookup(this.project, type, ns);
182 var ocl = (ObjectClass) cls_gtype.class_ref ();
183 var ps = ocl.find_property(k);
185 // attempt to read property type and enum...
188 var vt = ps.value_type;
191 var raw_val = this.node.get(k).strip();
192 var rv_s = raw_val.split(".");
193 if (rv_s.length > 0) {
194 raw_val = rv_s[rv_s.length-1];
195 EnumClass ec = (EnumClass) vt.class_ref ();
197 for (var i =0;i< ec.n_values; i++) {
198 var ev = ec.values[i].value_name;
199 var ev_s= ev.split("_");
200 if (raw_val == ev_s[ev_s.length-1]) {
201 var sval = GLib.Value(typeof(int));
202 sval.set_int(ec.values[i].value);
203 ret.set_property(k, sval);
219 var val = this.toValue(this.node.get(k).strip(), type);
221 print("skip (failed to transform value %s type = %s from %s\n",
222 cls + "." + k, type, this.node.get(k).strip());
225 print ("set_property ( %s , %s / %s)\n", k, this.node.get(k).strip(), val.strdup_contents());
228 ret.set_property(k, val);
233 // for now... - just try the builder style packing
237 if (this.node.items.size < 1) {
241 for (var i = 0; i < this.node.items.size; i++ ) {
243 var ch = this.mungeChild(this.node.items.get(i));
245 this.children.add(ch);
250 this.afterChildren();
259 public void afterChildren()
261 // things like GtkNotebook - we have to pack children after they have been created..
262 var cls = this.node.fqn().replace(".", "");
264 if (cls == "GtkNotebook") {
265 this.afterChildrenGtkNotebook();
272 public void afterChildrenGtkNotebook()
274 // we have a number of children..
275 // some are labels - this might need to be more complex...
276 // perhaps labels should be a special property labels[] of the notebook..
277 var labels = new Gee.ArrayList<NodeToGtk>();
278 var bodies = new Gee.ArrayList<NodeToGtk>();
279 for (var i = 0; i < this.children.size; i++) {
280 var cn = this.children.get(i).node.fqn().replace(".", "");
281 if (cn != "GtkLabel") {
282 bodies.add(this.children.get(i));
285 labels.add(this.children.get(i));
287 for (var i = 0; i < bodies.size; i++) {
288 var lbl = (i > (labels.size -1)) ? null : labels.get(i);
290 ((global::Gtk.Notebook)this.wrapped_object).append_page(
291 (global::Gtk.Notebook) bodies.get(i).wrapped_object,
292 lbl != null ? (global::Gtk.Notebook) lbl.wrapped_object : null
303 * called after the this.object has been created
304 * and it needs to be packed onto parent.
306 public void packParent()
308 var cls = this.node.fqn().replace(".", "");
310 var gtkbuilder = new global::Gtk.Builder();
311 var cls_gtype = gtkbuilder.get_type_from_name(cls);
313 if (this.parentObj == null) {
318 var parent = this.parentObj.wrapped_object;
322 if (parent == null) { // no parent.. can not pack.
325 // ------------- handle various special parents .. -----------
327 var par_type = this.parentObj.node.fqn().replace(".", "");
329 if (par_type == "GtkNotebook") {
330 // do not pack - it's done afterwards...
334 // ------------- handle various child types.. -----------
336 if (cls == "GtkMenu") {
341 if (cls == "GtkTreeStore") { // other stores?
342 // tree store is buildable??? ---
343 this.packTreeStore();
346 if (cls =="GtkTreeViewColumn") { // other stores?
347 //?? treeview column is actually buildable -- but we do not use the builder???
348 this.packTreeViewColumn();
351 if (cls_gtype.is_a(typeof(global::Gtk.CellRenderer))) { // other stores?
352 this.packCellRenderer();
358 // -- handle buildable add_child..
359 if ( cls_gtype.is_a(typeof(global::Gtk.Buildable))
361 parent.get_type().is_a(typeof(global::Gtk.Buildable))
364 ((global::Gtk.Buildable)parent).add_child(gtkbuilder,
365 this.wrapped_object, null);
374 public void packMenu()
378 var parent = this.parentObj.wrapped_object;
379 if (!parent.get_type().is_a(typeof(global::Gtk.Widget))) {
380 print("skip menu pack - parent is not a widget");
384 var p = (global::Gtk.Menu)this.wrapped_object;
385 ((global::Gtk.Widget)parent).button_press_event.connect((s, ev) => {
386 p.set_screen(Gdk.Screen.get_default());
388 p.popup(null, null, null, ev.button, ev.time);
393 public void packTreeStore()
395 var parent = this.parentObj.wrapped_object;
396 if (!parent.get_type().is_a(typeof(global::Gtk.TreeView))) {
397 print("skip treestore pack - parent is not a treeview");
400 ((global::Gtk.TreeView)parent).set_model((global::Gtk.TreeModel)this.wrapped_object);
403 public void packTreeViewColumn()
405 var parent = this.parentObj.wrapped_object;
406 if (!parent.get_type().is_a(typeof(global::Gtk.TreeView))) {
407 print("skip packGtkViewColumn pack - parent is not a treeview");
410 ((global::Gtk.TreeView)parent).append_column((global::Gtk.TreeViewColumn)this.wrapped_object);
411 // init contains the add_attribute for what to render...
416 public void packCellRenderer()
418 var parent = this.parentObj.wrapped_object;
419 if (!parent.get_type().is_a(typeof(global::Gtk.TreeViewColumn))) {
420 print("skip packGtkViewColumn pack - parent is not a treeview");
423 ((global::Gtk.TreeViewColumn)parent).pack_start((global::Gtk.CellRenderer)this.wrapped_object, false);
424 // init contains the add_attribute for what to render...
429 public void packContainerParams()
432 if (this.parentObj == null) {
435 // child must be a widget..
436 if (!this.wrapped_object.get_type().is_a(typeof(global::Gtk.Widget))) {
440 var parent_gir = Palete.Gir.factoryFqn(this.project, this.parentObj.node.fqn());
442 var parent = this.parentObj.wrapped_object;
444 if (parent_gir == null) {
448 // let's test just setting expand to false...
449 var cls_methods = parent_gir.methods;
450 if (cls_methods == null) {
454 if (!this.node.props.has_key("* pack") ||
455 this.node.props.get("* pack").val.length < 1) {
459 var ns = this.parentObj.node.fqn().split(".")[0];
461 var pack = this.node.props.get("* pack").val.split(",");
463 // this tries to use the parameter names from the '*pack' function as properties in child_set_property.
464 // for a grid it's trying to do left/top/width/height.
467 if (cls_methods.has_key(pack[0])) {
468 var mparams = cls_methods.get(pack[0]).paramset.params;
469 for (var i = 1; i < mparams.size; i++ ) {
470 if (i > (pack.length -1)) {
473 Palete.Gir.checkParamOverride(mparams.get(i));
474 var k = mparams.get(i).name;
478 var type = mparams.get(i).type;
479 type = Palete.Gir.fqtypeLookup(this.project, type, ns);
481 var val = this.toValue(pack[i].strip(), type);
483 print("skip (failed to transform value %s type = %s from %s\n",
484 this.parentObj.node.fqn() + "." + k, type, pack[i].strip());
487 print ("pack:set_property ( %s , %s / %s)\n", k, pack[i].strip(), val.strdup_contents());
489 ((global::Gtk.Container)parent).child_set_property(
490 (global::Gtk.Widget)this.wrapped_object , k, val);
502 public GLib.Value? toValue(string val, string type) {
506 if (type == "string") {
507 var qret = GLib.Value(typeof(string));
508 qret.set_string(val);
514 * var gtkbuilder = new global::Gtk.Builder();
515 var prop_gtype = gtkbuilder.get_type_from_name(type);
518 if (prop_gtype == GLib.Type.INVALID) {
529 var ret = GLib.Value(typeof(bool));
530 ret.set_boolean(val.down() == "false" ? false : true);
534 var ret = GLib.Value(typeof(uint));
535 ret.set_uint(int.parse(val));
539 var ret = GLib.Value(typeof(int));
540 ret.set_int(int.parse(val));
546 var ret = GLib.Value(typeof(long));
547 ret.set_long((long)int64.parse(val));
551 var ret = GLib.Value(typeof(ulong));
552 ret.set_ulong((ulong) uint64.parse(val));
556 var ret = GLib.Value(typeof(float));
557 ret.set_float((float)double.parse(val));
561 var ret = GLib.Value(typeof(string));
568 var sval = GLib.Value(typeof(string));
569 sval.set_string(val);
571 if (!sval.transform(ref ret)) {
578 // should not get here..