fix #7989 - add support for extended classes (partial)
[roobuilder] / src / JsRender / NodeToValaWrapped.vala
1 /**
2         this is the code to write the 'classic' node to vala output
3         */
4         /**
5  * 
6  * Code to convert node tree to Vala...
7  * 
8  * usage : x = (new JsRender.NodeToVala(node)).munge();
9  * 
10  * Fixmes?
11  *
12  *  pack - can we come up with a replacement?
13      - parent.child == child_widget -- actually uses getters and effectively does 'add'?
14        (works on most)?
15     
16      
17  * args  -- vala constructor args (should really only be used at top level - we did use it for clutter originally(
18  * ctor  -- different ctor argument
19  
20  * 
21  
22  * 
23  * 
24 */
25
26  
27 public class JsRender.NodeToValaWrapped : NodeToVala {
28
29
30         
31
32         public NodeToValaWrapped( JsRender file,  Node node,  int depth, NodeToVala? parent) 
33         {
34                 base (file, node, depth, parent);
35                 this.this_el = "this.el.";
36         }
37         
38         /**
39          *  Main entry point to convert a file into a string..
40          */
41         public static string mungeFile(JsRender file) 
42         {
43                 if (file.tree == null) {
44                         return "";
45                 }
46
47                 var n = new NodeToValaWrapped(file, file.tree, 0, null);
48                 n.toValaName(file.tree);
49                  
50                 GLib.debug("top cls %s / xlcs %s\n ",file.tree.xvala_cls,file.tree.xvala_cls); 
51                 n.initCls();
52                 return n.munge();
53                 
54
55         }
56         public override string munge ( )
57         {
58                 //return this.mungeToString(this.node);
59                 
60         
61                 
62                 this.namespaceHeader();
63                 this.globalVars();
64                 this.classHeader();
65                 this.addSingleton();
66                 this.addTopProperties();
67                 this.addMyVars();
68                 this.addPlusProperties(); // (this is child properties whos 'id' starts with '+' ??? not sure..
69                 this.addValaCtor();
70                 this.addUnderThis();
71                 this.addWrappedCtor();  // var this.el = new XXXXX()
72
73                 this.addInitMyVars();
74                 this.addWrappedProperties();
75                 this.addChildren();
76                 //this.addAutoShow(); // not needed gtk4 autoshow menuitems
77                 
78                 this.addInit();
79                 this.addListeners();
80                 this.addEndCtor();
81                 this.addUserMethods();
82                 this.iterChildren();
83                 this.namespaceFooter();
84                 
85                 return this.ret;
86                  
87                          
88         }
89         public override string mungeChild(  Node cnode)
90         {
91                 var x = new  NodeToValaWrapped(this.file, cnode,  this.depth+1, this);
92                 return x.munge();
93         }
94         
95         protected override void classHeader()
96         {
97                 var top = this.top as NodeToVala;
98                 if (top == null) {
99                          
100                         return;
101                 }
102                 // class header..
103                 // class xxx {   WrappedGtk  el; }
104                 this.node.line_start = this.cur_line;
105                 
106                 this.top.node.setNodeLine(this.cur_line, this.node);
107                 
108                 this.addLine(this.inpad + "public class " + this.xcls + " : Object");
109                 this.addLine(this.inpad + "{");
110                 
111                  
112                 this.addLine(this.pad + "public " + this.cls + " el;");
113  
114                 this.addLine(this.pad + "private " + top.xcls + "  _this;");
115                 this.addLine();
116                         
117                         
118                         
119                         // singleton
120         }
121         public void globalVars()
122         {
123                 if (this.depth > 0) {
124                         return;
125                 }
126                 // Global Vars..??? when did this get removed..?
127                 //this.ret += this.inpad + "public static " + this.xcls + "  " + this.node.xvala_id+ ";\n\n";
128
129                 this.addLine(this.inpad + "static " + this.xcls + "  _" + this.node.xvala_id+ ";");
130                 this.addLine();
131                    
132         }
133         protected void addSingleton() 
134         {
135                 if (depth > 0) {
136                         return;
137                 }
138                 this.addLine(pad + "public static " + xcls + " singleton()");
139                 this.addLine(this.pad + "{");
140                 this.addLine(this.ipad +    "if (_" + this.node.xvala_id  + " == null) {");
141                 this.addLine(this.ipad +    "    _" + this.node.xvala_id + "= new "+ this.xcls + "();");  // what about args?
142                 this.addLine(this.ipad +    "}");
143                 this.addLine(this.ipad +    "return _" + this.node.xvala_id +";");
144                 this.addLine(this.pad + "}");
145         }
146         /**
147          * add the constructor definition..
148          */
149         protected override void addValaCtor()
150         {
151                         
152                 
153                 // .vala props.. 
154                 
155  
156                 var cargs_str = "";
157                 // ctor..
158                 this.addLine();
159                 this.addLine(this.pad + "// ctor");
160                 
161                 if (this.node.has("* args")) {
162                         // not sure what this is supposed to be ding..
163                 
164                         cargs_str =  this.node.get("* args");
165                         //var ar = this.node.get("* args");.split(",");
166                         //for (var ari =0; ari < ar.length; ari++) {
167                                 //      cargs +=  (ar[ari].trim().split(" ").pop();
168                                   // }
169                         }
170         
171                 if (this.depth < 1) {
172                  
173                         // top level - does not pass the top level element..
174                         this.addLine(this.pad + "public " + this.xcls + "(" +  cargs_str +")");
175                         this.addLine(this.pad + "{");
176                 } else {
177                         if (cargs_str.length > 0) {
178                                 cargs_str = ", " + cargs_str;
179                         }
180                         var top = this.top as NodeToVala;
181                         var tcls = top == null ? "???" : top.xcls;
182                         // for sub classes = we passs the top level as _owner
183                         this.addLine(this.pad + "public " + this.xcls + "(" +  tcls + " _owner " + cargs_str + ")");
184                         this.addLine(this.pad + "{");
185                 }
186                 
187
188         }
189         /**
190          * Initialize this.el to point to the wrapped element.
191          * 
192          * 
193          */
194
195         void addWrappedCtor()
196         {
197                 // wrapped ctor..
198                 // this may need to look up properties to fill in the arguments..
199                 // introspection does not workk..... - as things like gtkmessagedialog
200                 /*
201                 if (cls == 'Gtk.Table') {
202
203                 var methods = this.palete.getPropertiesFor(cls, 'methods');
204
205                 print(JSON.stringify(this.palete.proplist[cls], null,4));
206                 Seed.quit();
207                 }
208                 */
209                 
210                 // ctor can still override.
211                 if (this.node.has("* ctor")) {
212                         this.node.setLine(this.cur_line, "p", "* ctor");
213                         this.addLine(this.ipad + "this.el = " + this.node.get("* ctor")+ ";");
214                         return;
215                 }
216                 
217                 this.node.setLine(this.cur_line, "p", "* xtype");;
218                 
219                 // is the wrapped element a struct?
220                 
221                 var ncls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn());
222                 if (ncls != null && ncls.nodetype == "Struct") {
223                         // we can use regular setters to apply the values.
224                         this.addLine(this.ipad + "this.el = " + this.node.fqn() + "();");
225                         return;
226                 
227                 
228                 }
229
230                 var ctor = ".new";
231                 var args_str = "";
232                 switch(this.node.fqn()) {
233                 
234                 // FIXME -- these are all GTK3 - can be removed when I get rid of them..
235                         case "Gtk.ComboBox":
236                                 var is_entry = this.node.has("has_entry") && this.node.get_prop("has_entry").val.down() == "true";
237                                 if (!is_entry) { 
238                                         break; // regular ctor.
239                                 }
240                                 this.ignoreWrapped("has_entry");
241                                 ctor = ".with_entry";
242                                 break;
243                                 
244                 
245                         case "Gtk.ListStore":
246                         case "Gtk.TreeStore":
247
248                                 // not sure if this works.. otherwise we have to go with varargs and count + vals...
249                                 if (this.node.has("* types")) {
250                                         args_str = this.node.get_prop("* types").val;
251                                 }
252                                 if (this.node.has("n_columns") && this.node.has("columns")) { // old value?
253                                         args_str = " { " + this.node.get_prop("columns").val + " } ";
254                                         this.ignoreWrapped("columns");
255                                         this.ignoreWrapped("n_columns");
256                                 }
257                                 
258                                 this.addLine(this.ipad + "this.el = new " + this.node.fqn() + ".newv( " + args_str + " );");
259                                 return;
260  
261                                 
262                         case "Gtk.LinkButton": // args filled with values.
263                                 if (this.node.has("label")) {
264                                         ctor = ".with_label";    
265                                 }
266                                 break;
267                                 
268                         default:
269                                 break;
270                 }
271                 var default_ctor = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn() + ctor);              
272                  
273                 
274                 // use the default ctor - with arguments (from properties)
275                 
276                 if (default_ctor != null && default_ctor.paramset != null && default_ctor.paramset.params.size > 0) {
277                         string[] args  = {};
278                         foreach(var param in default_ctor.paramset.params) {
279                                  
280                                 var n = param.name;
281                             GLib.debug("building CTOR ARGS: %s, %s", n, param.is_varargs ? "VARARGS": "");
282                                 if (n == "___") { // for some reason our varargs are converted to '___' ...
283                                         continue;
284                                 }
285                                 
286                                 if (this.node.has(n)) {  // node does not have a value
287                                         
288                                         this.ignoreWrapped(n);
289                                         this.ignore(n);
290                                         
291                                         var v = this.node.get(n);
292
293                                         if (param.type == "string") {
294                                                 v = "\"" +  v.escape("") + "\"";
295                                         }
296                                         if (v == "TRUE" || v == "FALSE") {
297                                                 v = v.down();
298                                         }
299
300                                         
301                                         args += v;
302                                         continue;
303                                 }
304                                 var propnode = this.node.findProp(n);
305                                 if (propnode != null) {
306                                         // assume it's ok..
307                                         
308                                         var pname = this.addPropSet(propnode, propnode.has("id") ? propnode.get_prop("id").val : "");
309                                         args += (pname + ".el") ;
310                                         if (!propnode.has("id")) {
311                                                 this.addLine(this.ipad + pname +".ref();"); 
312                                         }
313                                         
314                                         
315                                         
316                                         this.ignoreWrapped(n);
317                                         
318                                         continue;
319                                 }
320                                         
321                                          
322                                         
323                                         
324                                  
325                                 if (param.type.contains("int")) {
326                                         args += "0";
327                                         continue;
328                                 }
329                                 if (param.type.contains("float")) {
330                                         args += "0f";
331                                         continue;
332                                 }
333                                 if (param.type.contains("bool")) {
334                                         args += "true"; // always default to true?
335                                         continue;
336                                 }
337                                 // any other types???
338                                 
339                                 
340                                 
341                                 
342                                 args += "null";
343                                  
344                                 
345
346                         }
347                         this.node.setLine(this.cur_line, "p", "* xtype");
348                         this.addLine(this.ipad + "this.el = new " + this.node.fqn() + "( "+ string.joinv(", ",args) + " );") ;
349                         return;
350                         
351                 }
352                 // default ctor with no params..
353                  if (default_ctor != null && ctor != ".new" ) {
354                         this.node.setLine(this.cur_line, "p", "* xtype");
355                         
356                         this.addLine(this.ipad + "this.el = new " + this.node.fqn() + ctor + "(  );") ;
357                         return;
358                  }
359                 
360                 
361                 this.addLine(this.ipad + "this.el = new " + this.node.fqn() + "(" + args_str + ");");
362                         
363         }
364          
365                  
366
367 }