3 * Code to convert node tree to Javascript...
5 * usage : x = (new JsRender.NodeToJs(node)).munge();
12 public class JsRender.NodeToJs : Object {
14 static uint indent = 1;
15 static string indent_str = " ";
18 Gee.ArrayList<string> doubleStringProps; // need to think if this is a good idea like this
21 Gee.ArrayList<string> els;
22 //Gee.ArrayList<string> skip;
23 Gee.HashMap<string,string> ar_props;
25 Gee.HashMap<string,string> out_props;
26 Gee.HashMap<string,string> out_listeners;
27 Gee.HashMap<string,Node> out_nodeprops;
28 Gee.ArrayList<Node> out_children;
29 Gee.HashMap<string,Gee.ArrayList<Node>> out_props_array;
37 public NodeToJs( Node node, Gee.ArrayList<string> doubleStringProps, string pad, NodeToJs? parent)
40 this.doubleStringProps = doubleStringProps;
43 this.els = new Gee.ArrayList<string>();
44 this.ar_props = new Gee.HashMap<string,string>();
47 this.out_props = new Gee.HashMap<string,string>();
48 this.out_listeners = new Gee.HashMap<string,string>();
49 this.out_nodeprops = new Gee.HashMap<string,Node>() ;
50 this.out_children = new Gee.ArrayList<Node> ();
51 this.out_props_array = new Gee.HashMap<string,Gee.ArrayList<Node>>() ;
57 this.cur_line = parent == null ? 0 : parent.cur_line;
59 this.top = parent == null ? this : parent.top;
68 public string munge ( )
70 //return this.mungeToString(this.node);
72 this.node.line_start = this.cur_line;
76 this.readArrayProps();
79 if (!this.node.props.has_key("* xinclude")) {
86 if (this.els.size < 1) {
91 var spad = pad.substring(0, this.pad.length-indent);
94 var str_props = gLibStringListJoin(",\n" + this.pad , this.els) ;
95 //print ("STR PROPS: " + str_props);
99 if (!this.node.props.has_key("* xinclude")) {
101 this.pad + str_props +
107 return "Roo.apply(" + this.node.props.get("* xinclude") + "._tree(), "+
109 this.pad + str_props +
115 This currently works by creating a key/value array of this.els, which is just an array of properties..
116 this is so that join() works...
120 b) output plan properties.
121 c) output listeners..
123 g) output prop_arrays..
132 public string mungeOut()
134 if (this.node.props.has_key("* xinclude")) {
135 this.addLine("Roo.apply(" + this.node.props.get("* xinclude") + "._tree(), {");
141 // output the items...
142 // work out remaining items...
143 var total_nodes = this.out_props.size +
144 (this.out_listeners.size > 0 ? 1 : 0) +
145 this.out_nodeprops.size +
146 this.out_props_array.size +
147 (this.out_children.size > 0 ? 1 : 0);
150 var iter = this.out_props.map_iterator();
153 suffix = total_nodes > 0 ? "," : "";
154 this.addLine(this.pad + iter.get_key() + " : " + iter.get_value() + suffix);
158 if (this.out_listeners.size > 0 ) {
160 this.addLine(this.pad + "listeners : {");
161 iter = this.out_listeners.map_iterator();
162 var sz = this.out_listeners.size;
165 suffix = sz > 0 ? "," : "";
166 this.addMultiLine(this.pad + indent_str + iter.get_key() + " : " + iter.get_value() + suffix);
168 suffix = total_nodes > 0 ? "," : "";
169 this.addLine(this.pad + "}" + suffix);
173 if (this.out_nodeprops.size > 0 ) {
175 this.addLine(this.pad + "listeners : {");
176 iter = this.out_nodeprops.map_iterator();
177 var sz = this.out_listeners.size;
180 var suffix = sz > 0 ? "," : "";
181 this.addMultiLine(this.pad + iter.get_key() + " : " + iter.get_value() + suffix);
197 public void addLine(string str= "")
200 this.ret += str+ "\n";
206 public void addMultiLine(string str= "")
209 this.cur_line += str.split("\n").length;
210 //this.ret += "/*%d*/ ".printf(l) + str + "\n";
211 this.ret += str + "\n";
214 string gLibStringListJoin( string sep, Gee.ArrayList<string> ar)
217 for (var i = 0; i < ar.size; i++) {
218 ret += i>0 ? sep : "";
224 public string mungeChild(string pad , Node cnode)
226 var x = new NodeToJs(cnode, this.doubleStringProps, pad, this);
233 public void checkChildren ()
237 // look throught he chilren == looking for * prop.. -- fixme might not work..
240 if (!this.node.hasChildren()) {
245 for (var ii =0; ii< this.node.items.size; ii++) {
246 var pl = this.node.items.get(ii);
247 if (!pl.props.has_key("* prop")) {
252 //print(JSON.stringify(pl,null,4));
254 //var prop = pl['*prop'] + '';
255 //delete pl['*prop'];
256 var prop = pl.get("* prop");
257 print("got prop "+ prop + "\n");
260 if (! Regex.match_simple("\\[\\]$", prop)) {
261 // it's a standard prop..
263 // munge property..??
265 this.out_nodeprops.set(prop, pl);
267 this.els.add( prop + " : " + this.mungeChild ( this.pad + indent_str, pl));
277 var sprop = prop.replace("[]", "");
278 print("sprop is : " + sprop + "\n");
280 // it's an array type..
282 if (!this.ar_props.has_key(sprop)) {
284 this.ar_props.set(sprop, "");
285 this.out_props_array.set(sprop, new Gee.ArrayList<Node>());
287 old = this.ar_props.get(sprop);
289 var nstr = old += old.length > 0 ? ",\n" : "";
290 nstr += this.mungeChild( this.pad + indent_str + indent_str + indent_str , pl);
291 this.out_props_array.get(sprop).add( pl);
292 this.ar_props.set(sprop, nstr);
299 * Standardize this crap...
301 * standard properties (use to set)
302 * If they are long values show the dialog..
305 * bool is_xxx :: can show a pulldown.. (true/false)
307 * $ string html = string with value interpolated eg. baseURL + ".."
308 * Clutter.ActorAlign x_align (typed) -- shows pulldowns if type is ENUM?
309 * $ untypedvalue = javascript untyped value...
310 * _ string html ... = translatable..
313 * object properties (not part of the GOjbect being wrapped?
314 * # Gee.ArrayList<Xcls_fileitem> fileitems
319 * methods -- always text editor..
327 * * init -- big string?
329 * event handlers (listeners)
334 * +XXXX -- indicates it's a instance property / not glob...
335 * *XXXX -- skip writing glob property (used as classes that can be created...)
339 public void readProps()
344 if (this.node.props.has_key("$ xns")) {
345 this.out_props.set("'|xns'", this.node.props.get("$ xns") );
347 this.els.add("'|xns' : '" + this.node.props.get("$ xns") + "'");
353 func_regex = new Regex("^\\s+|\\s+$");
355 print("failed to build regex");
358 // sort the key's so they always get rendered in the same order..
360 var keys = new Gee.ArrayList<string>();
361 var piter = this.node.props.map_iterator();
362 while (piter.next() ) {
366 this.node.normalize_key(piter.get_key(), out k, out kflag, out ktype);
371 keys.sort(( a, b) => {
372 return ((string)a).collate((string)b);
373 //if (a == b) return 0;
374 //return a < b ? -1 : 1;
379 for (var i = 0; i< keys.size; i++) {
380 var key = this.node.get_key(keys.get(i));
381 print("ADD KEY %s\n", key);
386 this.node.normalize_key(key, out k, out kflag, out ktype);
389 var v = this.node.get(key);
392 //if (this.skip.contains(k) ) {
395 if ( Regex.match_simple("\\[\\]$", k)) {
396 // array .. not supported... here?
402 // skip builder stuff. prefixed with '.' .. just like unix fs..
403 if (kflag == ".") { // |. or . -- do not output..
407 // ignore '* prop'; ???
412 if (Lang.isKeyword(leftv) || Lang.isBuiltin(leftv)) {
413 left = "'" + leftv + "'";
414 } else if (Regex.match_simple("[^A-Za-z_]+",leftv)) { // not plain a-z... - quoted.
415 var val = this.node.quoteString(leftv);
417 left = "'" + val.substring(1, val.length-2).replace("'", "\\'") + "'";
425 // next.. is it a function.. or a raw string..
433 // ??? any others that are raw output..
435 // does not hapepnd with arrays..
436 if (v.length < 1) { //if (typeof(el) == 'string' && !obj[i].length) { //skip empty.
443 str = func_regex.replace(v,v.length, 0, "");
445 print("regex failed");
451 var lines = str.split("\n");
453 if (lines.length > 0) {
454 nstr = string.joinv("\n" + this.pad, lines);
455 //nstr = string.joinv("\n", lines);
457 //print("==> " + str + "\n");
458 this.els.add(left + nstr);
469 ktype.down() == "boolean"
471 ktype.down() == "bool"
473 ktype.down() == "number"
475 ktype.down() == "int"
476 ) { // boolean or number...?
477 this.els.add(left + v.down() );
481 // is it a translated string?
487 //if (this.doubleStringProps.size < 1) {
488 // this.els.add(left + this.node.quoteString(v));
492 if (this.doubleStringProps.index_of(k) > -1) {
493 // then use the translated version...
495 els.add(left + "_this._strings['" +
496 GLib.Checksum.compute_for_string (ChecksumType.MD5, v) +
501 if (ktype.down() == "string" && k[0] == '_') {
502 els.add(left + "_this._strings['" +
503 GLib.Checksum.compute_for_string (ChecksumType.MD5, v) +
508 // otherwise it needs to be encapsulated.. as single quotes..
510 var vv = this.node.quoteString(v);
511 // single quote.. v.substring(1, v.length-1).replace("'", "\\'") + "'";
512 this.els.add(left + "'" + vv.substring(1, vv.length-2).replace("'", "\\'") + "'");
520 public void readArrayProps()
523 // handle the childitems that are arrays.. eg. button[] = { }...
527 var iter = this.ar_props.map_iterator();
528 while (iter.next()) {
529 var k = iter.get_key();
530 var right = iter.get_value();
532 string leftv = k[0] == '|' ? k.substring(1) : k;
533 if (Lang.isKeyword(leftv) || Lang.isBuiltin(leftv)) {
534 left = "'" + leftv + "'";
535 } else if (Regex.match_simple("[^A-Za-z_]+",leftv)) { // not plain a-z... - quoted.
536 var val = this.node.quoteString(leftv);
538 left = "'" + val.substring(1, val.length-2).replace("'", "\\'") + "'";
547 if (right.length > 0){
548 this.els.add(left + "[\n" + this.pad + indent_str + indent_str +
549 right + "\n" + this.pad + "]");
556 public void readListeners()
559 if (this.node.listeners.size < 1) {
562 // munge the listeners.
563 //print("ADDING listeners?");
565 var liter = this.node.listeners.map_iterator();
569 var keys = new Gee.ArrayList<string>();
570 var piter = this.node.listeners.map_iterator();
571 while (piter.next() ) {
573 keys.add(piter.get_key());
575 keys.sort(( a, b) => {
576 return ((string)a).collate((string)b);
577 //if (a == b) return 0;
578 //return a < b ? -1 : 1;
581 var itms = "listeners : {\n";
583 for (var i = 0; i< keys.size; i++) {
584 var key = keys.get(i);
585 var val = this.node.listeners.get(key);
588 itms += i >0 ? ",\n" : "";
590 var str = val.strip();
591 var lines = str.split("\n");
592 if (lines.length > 0) {
593 //str = string.joinv("\n" + this.pad + " ", lines);
594 str = string.joinv("\n" + this.pad + indent_str + indent_str , lines);
597 itms += this.pad + indent_str + key.replace("|", "") + " : " + str;
602 itms += "\n" + this.pad + "}";
603 //print ( "ADD " + itms);
608 public void iterChildren()
612 // finally munge the children...
613 if (this.node.items.size < 1) {
616 var itms = "items : [\n";
618 for(var i = 0; i < this.node.items.size;i++) {
619 var ele = this.node.items.get(i);
620 if (ele.props.has_key("* prop")) {
627 itms += this.pad + indent_str +
628 this.mungeChild( this.pad + indent_str + indent_str , ele);
632 itms += "\n"+ this.pad + "]" + "\n";
636 // finally output listeners...
638 public void xIncludeToString()