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