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...
24 public class JsRender.NodeToGtk : Object {
27 Object wrapped_object;
30 Gee.ArrayList<NodeToGtk> children;
32 Gee.ArrayList<string> els;
33 //Gee.ArrayList<string> skip;
34 Gee.HashMap<string,string> ar_props;
35 public static int vcnt = 0;
37 public NodeToGtk( Node node)
40 this.els = new Gee.ArrayList<string>();
41 this.children = new Gee.ArrayList<NodeToGtk>();
42 //this.skip = new Gee.ArrayList<string>();
43 this.ar_props = new Gee.HashMap<string,string>();
44 this.parentObj = null;
47 public Object? munge ( )
49 var ret = this.mungeNode();
54 return ret.wrapped_object;
57 public NodeToGtk? mungeChild( Node cnode)
59 var x = new NodeToGtk(cnode);
65 public NodeToGtk? mungeNode()
68 var parent = this.parentObj != null ? this.parentObj.wrapped_object : null;
69 var cls = this.node.fqn().replace(".", "");
70 var ns = this.node.fqn().split(".")[0];
71 var gtkbuilder = new global::Gtk.Builder();
73 var cls_gtype = gtkbuilder.get_type_from_name(cls);
74 print("Type: %s ?= %s\n", this.node.fqn(), cls_gtype.name());
76 if (cls_gtype == GLib.Type.INVALID) {
77 print("SKIP - gtype is invalid\n");
80 // if it's a window...
82 if (cls_gtype.is_a(typeof(global::Gtk.Window))) {
83 // what if it has none...
84 if (this.node.items.size < 1) {
87 return this.mungeChild(this.node.items.get(0));
90 var ret = Object.new(cls_gtype);
91 ret.ref(); //??? problematic?
92 this.wrapped_object = ret;
97 //case "GtkTreeStore": // top level.. - named and referenced
98 case "GtkListStore": // top level.. - named and referenced
99 //case "GtkTreeViewColumn": // part of liststore?!?!
100 //case "GtkMenu": // top level..
101 //case "GtkCellRendererText":
102 case "GtkSourceBuffer":
103 case "GtkClutterActor"://fixme..
104 case "GtkClutterEmbed"://fixme.. -- we can not nest embedded.. need to solve..
115 if (parent != null && parent.get_type().is_a(typeof(global::Gtk.Container))) {
116 this.packContainerParams();
119 var cls_gir =Palete.Gir.factoryFqn(this.node.fqn());
120 if (cls_gir == null) {
123 //var id = this.node.uid();
124 //var ret = @"$pad<object class=\"$cls\" id=\"$id\">\n";
126 var props = cls_gir.props;
129 var pviter = props.map_iterator();
130 while (pviter.next()) {
132 // print("Check: " +cls + "::(" + pviter.get_value().propertyof + ")" + pviter.get_key() + " " );
133 var k = pviter.get_key();
134 // skip items we have already handled..
135 if (!this.node.has(k)) {
138 // find out the type of the property...
139 var type = pviter.get_value().type;
140 type = Palete.Gir.fqtypeLookup(type, ns);
142 var val = this.toValue(this.node.get(k).strip(), type);
144 print("skip (failed to transform value %s type = %s from %s\n",
145 cls + "." + k, type, this.node.get(k).strip());
148 print ("set_property ( %s , %s / %s)\n", k, this.node.get(k).strip(), val.strdup_contents());
151 ret.set_property(k, val);
156 // for now... - just try the builder style packing
160 if (this.node.items.size < 1) {
164 for (var i = 0; i < this.node.items.size; i++ ) {
166 var ch = this.mungeChild(this.node.items.get(i));
168 this.children.add(ch);
173 this.afterChildren();
182 public void afterChildren()
184 // things like GtkNotebook - we have to pack children after they have been created..
185 var cls = this.node.fqn().replace(".", "");
187 if (cls == "GtkNotebook") {
188 this.afterChildrenGtkNotebook();
195 public void afterChildrenGtkNotebook()
197 // we have a number of children..
198 // some are labels - this might need to be more complex...
199 // perhaps labels should be a special property labels[] of the notebook..
200 var labels = new Gee.ArrayList<NodeToGtk>();
201 var bodies = new Gee.ArrayList<NodeToGtk>();
202 for (var i = 0; i < this.children.size; i++) {
203 var cn = this.children.get(i).node.fqn().replace(".", "");
204 if (cn != "GtkLabel") {
205 bodies.add(this.children.get(i));
208 labels.add(this.children.get(i));
210 for (var i = 0; i < bodies.size; i++) {
211 ((global::Gtk.Notebook)this.wrapped_object).append_page(
212 (global::Gtk.Notebook) bodies.get(i).wrapped_object,
213 (labels.size > i - 1) ?
214 (global::Gtk.Notebook) labels.get(i).wrapped_object :
227 * called after the this.object has been created
228 * and it needs to be packed onto parent.
230 public void packParent()
232 var cls = this.node.fqn().replace(".", "");
234 var gtkbuilder = new global::Gtk.Builder();
235 var cls_gtype = gtkbuilder.get_type_from_name(cls);
237 if (this.parentObj == null) {
242 var parent = this.parentObj.wrapped_object;
246 if (parent == null) { // no parent.. can not pack.
249 // ------------- handle various special parents .. -----------
251 var par_type = this.parentObj.node.fqn().replace(".", "");
253 if (par_type == "GtkNotebook") {
254 // do not pack - it's done afterwards...
258 // ------------- handle various child types.. -----------
260 if (cls == "GtkMenu") {
265 if (cls == "GtkTreeStore") { // other stores?
266 // tree store is buildable??? ---
267 this.packTreeStore();
270 if (cls =="GtkTreeViewColumn") { // other stores?
271 //?? treeview column is actually buildable -- but we do not use the builder???
272 this.packTreeViewColumn();
275 if (cls_gtype.is_a(typeof(global::Gtk.CellRenderer))) { // other stores?
276 this.packCellRenderer();
282 // -- handle buildable add_child..
283 if ( cls_gtype.is_a(typeof(global::Gtk.Buildable))
285 parent.get_type().is_a(typeof(global::Gtk.Buildable))
288 ((global::Gtk.Buildable)parent).add_child(gtkbuilder,
289 this.wrapped_object, null);
298 public void packMenu()
302 var parent = this.parentObj.wrapped_object;
303 if (!parent.get_type().is_a(typeof(global::Gtk.Widget))) {
304 print("skip menu pack - parent is not a widget");
308 var p = (global::Gtk.Menu)this.wrapped_object;
309 ((global::Gtk.Widget)parent).button_press_event.connect((s, ev) => {
310 p.set_screen(Gdk.Screen.get_default());
312 p.popup(null, null, null, ev.button, ev.time);
317 public void packTreeStore()
319 var parent = this.parentObj.wrapped_object;
320 if (!parent.get_type().is_a(typeof(global::Gtk.TreeView))) {
321 print("skip treestore pack - parent is not a treeview");
324 ((global::Gtk.TreeView)parent).set_model((global::Gtk.TreeModel)this.wrapped_object);
327 public void packTreeViewColumn()
329 var parent = this.parentObj.wrapped_object;
330 if (!parent.get_type().is_a(typeof(global::Gtk.TreeView))) {
331 print("skip packGtkViewColumn pack - parent is not a treeview");
334 ((global::Gtk.TreeView)parent).append_column((global::Gtk.TreeViewColumn)this.wrapped_object);
335 // init contains the add_attribute for what to render...
340 public void packCellRenderer()
342 var parent = this.parentObj.wrapped_object;
343 if (!parent.get_type().is_a(typeof(global::Gtk.TreeViewColumn))) {
344 print("skip packGtkViewColumn pack - parent is not a treeview");
347 ((global::Gtk.TreeViewColumn)parent).pack_start((global::Gtk.CellRenderer)this.wrapped_object, false);
348 // init contains the add_attribute for what to render...
353 public void packContainerParams()
356 if (this.parentObj == null) {
359 // child must be a widget..
360 if (!this.wrapped_object.get_type().is_a(typeof(global::Gtk.Widget))) {
364 var parent_gir = Palete.Gir.factoryFqn(this.parentObj.node.fqn());
366 var parent = this.parentObj.wrapped_object;
368 if (parent_gir == null) {
372 // let's test just setting expand to false...
373 var cls_methods = parent_gir.methods;
374 if (cls_methods == null) {
378 if (!this.node.props.has_key("* pack") ||
379 this.node.props.get("* pack").length < 1) {
383 var ns = this.parentObj.node.fqn().split(".")[0];
385 var pack = this.node.props.get("* pack").split(",");
388 if (cls_methods.has_key(pack[0])) {
389 var mparams = cls_methods.get(pack[0]).paramset.params;
390 for (var i = 1; i < mparams.size; i++ ) {
391 if (i > (pack.length -1)) {
395 var k = mparams.get(i).name;
399 var type = mparams.get(i).type;
400 type = Palete.Gir.fqtypeLookup(type, ns);
402 var val = this.toValue(pack[i].strip(), type);
404 print("skip (failed to transform value %s type = %s from %s\n",
405 this.parentObj.node.fqn() + "." + k, type, pack[i].strip());
408 print ("pack:set_property ( %s , %s / %s)\n", k, pack[i].strip(), val.strdup_contents());
410 ((global::Gtk.Container)parent).child_set_property(
411 (global::Gtk.Widget)this.wrapped_object , k, val);
423 public GLib.Value? toValue(string val, string type) {
425 var gtkbuilder = new global::Gtk.Builder();
427 if (type == "utf8") {
428 var qret = GLib.Value(typeof(string));
429 qret.set_string(val);
433 var prop_gtype = gtkbuilder.get_type_from_name(type);
436 if (prop_gtype == GLib.Type.INVALID) {
442 var ret = GLib.Value(prop_gtype);
447 ret.set_boolean(val.down() == "false" ? false : true);
450 ret.set_uint(int.parse(val));
454 ret.set_int(int.parse(val));
458 ret.set_float(long.parse(val));
467 var sval = GLib.Value(typeof(string));
468 sval.set_string(val);
470 if (!sval.transform(ref ret)) {