Fix #8034 - structs as ctor properties - need adding as default properties.
[roobuilder] / src / Palete / Gtk.vala
1 using Gtk;
2
3
4 /**
5
6 This basically provides all the data needed to add stuff to gtk objects 
7   
8
9 */
10
11
12
13 namespace Palete {
14
15         
16         
17         
18         
19          
20
21         public class Gtk : Palete {
22                 
23                 public Gee.ArrayList<string> package_cache;
24                 
25                 public Gtk(Project.Project project)
26                 {
27
28                     aconstruct(project);
29                     this.name = "Gtk";
30                     var context = new Vala.CodeContext ();
31                          
32                     this.package_cache = this.loadPackages(Path.get_dirname (context.get_vapi_path("glib-2.0")));
33                     this.package_cache.add_all(
34                             this.loadPackages(Path.get_dirname (context.get_vapi_path("gee-0.8")))
35                     );
36                      
37                    
38                     
39                 }
40                 
41                 
42         // a) build a list of all widgets that can be added generically.
43                 // b) build child list for all containers.
44                 // c) build child list for all widgets (based on properties)
45                 // d) handle oddities?
46                 
47                 public bool loaded = false; // set to false to force a reload
48
49                 public override void  load () 
50                 {
51                         if (this.loaded) {
52                                 return;
53                         }
54                         Gir.factory(this.project, "Gtk"); // triggers a load...
55                          
56                         this.init_node_defaults();
57                         this.add_node_default_from_ctor_all();
58                     this.init_child_defaults();  
59                     
60                     this.loaded = true;
61                          
62                         
63                 }
64                 
65                 
66                 
67           
68                 
69                 public string doc(string what) 
70                 {
71                 var ns = what.split(".")[0];
72                 var gir =  Gir.factory(this.project,ns);
73                         return  ((Gir) gir).doc(what);
74                         
75                     //return typeof(this.comments[ns][what]) == 'undefined' ?  '' : this.comments[ns][what];
76                 }
77
78                 public GirObject? loadGir (string ename) {
79                         var es = ename.split(".");
80                         if (es.length < 2) {
81                                 return null;
82                         }
83                         var gir = Gir.factory(this.project,es[0]);
84                         if (gir == null) {
85                                 return null;
86                         }
87                         return gir;
88                         
89                 }
90
91                         // does not handle implements...
92                 public override GirObject? getClass(string ename)
93                 {
94                         var es = ename.split(".");
95                         var gir = this.loadGir(ename);
96                         return gir  == null ? null : gir.classes.get(es[1]);
97                 
98                 }
99                  
100                 public  GirObject? getDelegate(string ename) 
101                 {
102                         var es = ename.split(".");
103                         var gir = this.loadGir(ename);
104                         return gir  == null ? null : gir.delegates.get(es[1]);
105                 }
106                 
107                 public  GirObject? getClassOrEnum(string ename)
108                 {
109                         var es = ename.split(".");
110                         var gir = this.loadGir(ename);
111                         return gir  == null ? null : 
112                                         (gir.classes.has_key(es[1]) ?  gir.classes.get(es[1]) : gir.consts.get(es[1]) );
113                  
114                 }
115
116
117                 public override Gee.HashMap<string,GirObject> getPropertiesFor( string ename, JsRender.NodePropType ptype) 
118                 {
119                         //print("Loading for " + ename);
120                     
121
122                         this.load();
123                                 // if (typeof(this.proplist[ename]) != 'undefined') {
124                         //print("using cache");
125                         //   return this.proplist[ename][type];
126                         //}
127                         // use introspection to get lists..
128          
129                         var es = ename.split(".");
130                         var gir = Gir.factory(this.project,es[0]);
131                         if (gir == null) {
132                                 print("WARNING = could not load vapi for %s  (%s)\n", ename , es[0]);
133                                 return new Gee.HashMap<string,GirObject>();
134                         }
135                         var cls = gir.classes.get(es[1]);
136                         if (cls == null) {
137                                 var ret = new Gee.HashMap<string,GirObject>();
138                                 return ret;
139                                 //throw new Error.INVALID_VALUE( "Could not find class: " + ename);
140                         
141                         }
142
143                         //cls.parseProps();
144                         //cls.parseSignals(); // ?? needed for add handler..
145                         //cls.parseMethods(); // ?? needed for ??..
146                         //cls.parseConstructors(); // ?? needed for ??..
147
148                         cls.overlayParent(this.project);
149
150                         switch  (ptype) {
151                                 case JsRender.NodePropType.PROP:
152                                         var ret =  this.filterProps(cls.props);
153                                         // add ctor
154                                         this.add_props_from_ctors(cls, ret);
155                                         return ret;
156                                 case JsRender.NodePropType.LISTENER:
157                                         return this.filterSignals(cls.signals);
158                                 case JsRender.NodePropType.METHOD:
159                                         return cls.methods;
160                                 case JsRender.NodePropType.CTOR:  // needed to query the arguments of a ctor.
161                                         return cls.ctors;
162                                 default:
163                                         GLib.error( "getPropertiesFor called with: " + ptype.to_string());
164                                         //var ret = new Gee.HashMap<string,GirObject>();
165                                         //return ret;
166                                 
167                         }
168                                 
169                         
170                         //cls.overlayInterfaces(gir);
171                      
172                      
173                 }
174                 // get rid of objecst from props list..
175                 public Gee.HashMap<string,GirObject>  filterProps(Gee.HashMap<string,GirObject> props)
176                 {
177                         // we shold probably cache this??
178                         
179                         var outprops = new Gee.HashMap<string,GirObject>(); 
180                         
181                         foreach(var k in props.keys) {
182                                 var val = props.get(k);
183 //                              GLib.debug("FilterProp: %s", k);
184                                 // properties that dont make any sense to display.
185                                 if (
186                                         k == "___" ||
187                                         k == "parent" ||
188                                         k == "default_widget" ||
189                                         k == "root" ||
190                                         k == "layout_manager" || // ??
191                                         k == "widget"  // gestures..
192                                 ) {
193                                         continue;
194                                 }
195                                 
196                                 if (val.is_deprecated) {
197                                         continue;
198                                 }
199                                 if (!val.is_writable && !val.ctor_only ) { // if it's ctor we accept it.
200                                         continue;
201                                 }
202                                 
203                                 if (val.type == "GLib.Object") { /// this is practually everything? ?? shoud we display it as a property?
204                                         continue;
205                                 }
206                                 if (!val.type.contains(".")) {
207                                         outprops.set(k,val);
208                                         continue;
209                                 }
210                                 var cls = this.getClassOrEnum(val.type);
211                                 
212                                 // if cls == null - it's probably a struct? I don't think we handle thses
213                                 if ( cls != null ) { // cls.nodetype == "Enum") {
214                                         // assume it's ok
215                                         outprops.set(k,val);
216                                         continue;
217                                 }
218                                 // do nothing? - classes not allowed?
219                                 
220                         }
221                         
222                         
223                         return outprops;
224                 
225                 
226                 }
227                 
228                 private void add_props_from_ctors(GirObject cls, Gee.HashMap<string,GirObject> props)
229                 {
230                         if (cls.ctors.has_key("new")) {
231                                 this.add_props_from_ctor(cls.ctors.get("new"), props);  
232                                 return;
233                         }
234                         // does not have new ?? needed?
235                         foreach(var ctor in cls.ctors.values) {
236                                 this.add_props_from_ctor(ctor, props);
237                                 break;
238                         
239                         }
240                 }
241                 
242                 private void add_props_from_ctor(GirObject ctor,  Gee.HashMap<string,GirObject> props)
243                 {
244                         var cname = ctor.gparent.fqn();
245                         GLib.debug("Add node from ctor %s:%s", ctor.gparent.fqn(), ctor.name);
246                          
247                         if (ctor.paramset == null) {
248                                 return;
249                         }
250                         
251                          
252                         // assume we are calling this for a reason...
253                         // get the first value params.
254                          
255                                 //gtk box failing
256                         //GLib.debug("No. of parmas %s %d", cls, ctor.params.size);
257                           
258                     foreach (var prop in ctor.paramset.params) {
259  
260                             
261                             if (props.has_key(prop.name)) { // overlap (we assume it's the same..)
262                                 continue;
263                         }
264                         prop.propertyof = cname + "." + ctor.name; // as it's probably not filled in..
265                             
266                             GLib.debug("adding proprty from ctor : %s, %s, %s", cname , prop.name, prop.type);
267
268                              props.set(prop.name, prop);
269                     
270                             
271                              
272                     }
273                 }
274                 
275                 
276                 
277                                 // get rid of depricated from signal list..
278                 public Gee.HashMap<string,GirObject>  filterSignals(Gee.HashMap<string,GirObject> props)
279                 {
280                         // we shold probably cache this??
281                         
282                         var outprops = new Gee.HashMap<string,GirObject>(); 
283                         
284                         foreach(var k in props.keys) {
285                                 var val = props.get(k);
286                                  
287                                 if (val.is_deprecated) {
288                                         continue;
289                                 }
290                                 
291                                 outprops.set(k,val);
292                                         
293                                 // do nothing? - classes not allowed?
294                                 
295                         }
296                         
297                         
298                         return outprops;
299                 
300                 
301                 }
302                 
303                 public string[] getInheritsFor(string ename)
304                 {
305                         string[] ret = {};
306                          
307                         var cls = this.getClass(ename);
308                          
309                         if (cls == null || cls.nodetype != "Class") {
310                                 print("getInheritsFor:could not find cls: %s\n", ename);
311                                 return ret;
312                         }
313                         
314                         return cls.inheritsToStringArray();
315                         
316
317                 }
318                 Gee.HashMap<string,Gee.HashMap<string,JsRender.NodeProp>> node_defaults;
319                 Gee.HashMap<string,Gee.ArrayList<JsRender.NodeProp>> child_defaults;
320                 
321                 public void init_node_defaults()
322                 {
323                         this.node_defaults = new Gee.HashMap<string,Gee.HashMap<string,JsRender.NodeProp>>();
324                         
325                         // this lot could probably be configured?
326                         
327                         // does this need to add properties to methods?
328                         // these are fake methods.
329                         
330                         
331                         
332                    
333                         this.add_node_default("Gtk.ComboBox", "has_entry", "false");
334                         this.add_node_default("Gtk.Expander", "label", "Label"); 
335                          
336                         this.add_node_default("Gtk.Frame", "label", "Label"); 
337                         
338                         this.add_node_default("Gtk.Grid", "columns", "2"); // special properties (is special as it's not part of the standard?!)
339                         //this.add_node_default("Gtk.Grid", "rows", "2");  << this is not really that important..
340                  
341                         this.add_node_default("Gtk.HeaderBar", "title", "Window Title");
342                         this.add_node_default("Gtk.Label", "label", "Label"); // althought the ctor asks for string.. - we can use label after ctor.
343                  
344                         this.add_node_default("Gtk.Scale", "orientation");
345                          
346                         this.add_node_default("Gtk.ToggleButton", "label", "Label");  
347                         this.add_node_default("Gtk.MenuItem", "label", "Label");
348                         this.add_node_default("Gtk.CheckItem", "label", "Label");                       
349                         this.add_node_default("Gtk.RadioMenuItem", "label", "Label");
350                         this.add_node_default("Gtk.TearoffMenuItem", "label", "Label");
351                         
352                         // not sure how many of these 'attributes' there are - documenation is a bit thin on the ground
353                         this.add_node_default("Gtk.CellRendererText",    "markup_column", "-1");
354                         this.add_node_default("Gtk.CellRendererText",           "text_column","-1");
355                         this.add_node_default("Gtk.CellRendererPixBuf",  "pixbuf_column", "-1");
356                         this.add_node_default("Gtk.CellRendererToggle",  "active_column", "-1");                        
357
358                         //foreground
359                         //foreground-gdk
360                         
361                         
362                          
363                         // treeviewcolumn
364                         
365                 }
366                 
367                 
368                 
369                 
370                 private void add_node_default_from_ctor_all()
371         {
372
373                         var pr = (Project.Gtk) this.project;
374                         
375                          
376                          
377                         foreach(var key in   pr.gir_cache.keys) {
378                                 var gir = pr.gir_cache.get(key);
379                                 GLib.debug("building drop list for package %s", key);
380                                 this.add_node_default_from_ctor_package(gir.classes);
381                         }       
382                 }
383
384                 private void add_node_default_from_ctor_package(Gee.HashMap<string,GirObject> classes)
385                 {
386                         
387
388                         
389                         foreach(var cls in classes.values) {
390                                 GLib.debug("building drop list for class %s.%s", cls.package, cls.name);
391                                 this.add_node_default_from_ctor_classes(cls);
392                         }
393                  
394                 }
395                 
396                 private void add_node_default_from_ctor_classes(GirObject cls)
397                 {
398                         if (cls.ctors.has_key("new")) {
399                                 this.add_node_default_from_ctor(cls.ctors.get("new"));
400                                 return; // and no more.
401                         }
402                         // does not have new ?? needed?
403                         foreach(var ctor in cls.ctors.values) {
404                                 this.add_node_default_from_ctor(ctor);
405                                 break;
406                         
407                         }
408                 }
409                 
410                 
411                 
412                 
413                 
414                 
415                 private void add_node_default_from_ctor(GirObject ctor )
416                 {
417                         var cname = ctor.gparent.fqn();
418                         GLib.debug("Add node from ctor %s:%s", ctor.gparent.fqn(), ctor.name);
419                         if (!this.node_defaults.has_key(cname)) {
420                                 this.node_defaults.set(cname, new Gee.HashMap<string,JsRender.NodeProp>());
421                         }
422                         
423                         if (ctor.paramset == null) {
424                                 return;
425                         }
426                         
427                         var defs=  this.node_defaults.get(cname);
428                         
429                         
430                          
431                         GLib.debug("ctor: %s: %s", cname , ctor.name);
432                          
433                         
434                         // assume we are calling this for a reason...
435                         // get the first value params.
436                          
437                                 //gtk box failing
438                         //GLib.debug("No. of parmas %s %d", cls, ctor.params.size);
439                           
440                     foreach (var prop in ctor.paramset.params) {
441                             string[] opts;
442                             
443                             if (defs.has_key(prop.name)) {
444                                 continue;
445                         }
446                         var sub = this.getClass(prop.type);
447                             
448                            // GLib.debug("adding property from ctor : %s, %s, %s  [%s]", cname , prop.name, prop.type, sub == null ? "-" : sub.nodetype);
449  
450                             if (sub != null) { // can't add child classes here...
451                                 if (sub.nodetype == "Struct") {
452                                         this.node_defaults.get(cname).set(prop.name, new JsRender.NodeProp.raw(prop.name, prop.type, ""));
453                                                 continue;
454                                 }
455                                     GLib.debug("skipping ctor argument proprty is an object");
456                                     continue;
457                             }
458                              
459                             sub = this.getDelegate(prop.type);
460                              if (sub != null) { // can't add child classes here...
461                                 this.node_defaults.get(cname).set(prop.name, new JsRender.NodeProp.raw(prop.name, prop.type, sub.sig));
462                                 continue;
463                             }
464                             
465                             // FIXME!!! - what about functions
466                             
467                             var dval = "";
468                             switch (prop.type) {
469                                     case "int":
470                                             dval = "0";break;
471                                     case "string": 
472                                             dval = ""; break;
473                                     // anything else?
474                                     
475                                     default: // enam? or bool?
476                                             this.typeOptions(cname, prop.name, prop.type, out opts);
477                                             dval = opts.length > 0 ? opts[0] : "";
478                                             break;
479                             }
480                             
481                             this.node_defaults.get(cname).set(prop.name, new JsRender.NodeProp.prop( prop.name, prop.type, dval));
482                     
483                             
484                              
485                     }
486                 }
487                 
488                 private void add_node_default(string cname, string propname, string val = "")
489                 {
490                         if (!this.node_defaults.has_key(cname)) {
491                                 var add = new Gee.HashMap<string, JsRender.NodeProp>();
492                                 this.node_defaults.set(cname, add);
493                         }
494                         // this recurses...
495                         var cls = this.getClass(cname);
496                         if (cls == null) {
497                                 GLib.debug("invalid class name %s", cname);
498                                 return;
499                         }
500                         var ar = cls.props;
501                         
502                         // liststore.columns - exists as a property but does not have a type (it's an array of typeofs()....
503                         if (ar.has_key(propname) && ar.get(propname).type != "") { // must have  type (otherwise special)
504                                 //GLib.debug("Class %s has property %s from %s - adding normal property", cls, propname, ar.get(propname).asJSONString());
505                                 var add = ar.get(propname).toNodeProp(this, cname); // our nodes dont have default values.
506                                 add.val = val;
507                                 this.node_defaults.get(cname).set(propname, add);
508                                 return;
509                                 
510                         } 
511                         //GLib.debug("Class %s has property %s - adding special property", cls, propname);                      
512                         this.node_defaults.get(cname).set(propname,
513                                 new  JsRender.NodeProp.special( propname, val) 
514                         );
515
516                         
517
518                 
519                 }
520                 private void init_child_defaults()
521                 {
522                         this.child_defaults = new Gee.HashMap<string,Gee.ArrayList<JsRender.NodeProp>>();
523                         
524                         this.add_child_default("Gtk.Fixed", "x", "int", "0");
525                         this.add_child_default("Gtk.Fixed", "y", "int", "0");
526                         this.add_child_default("Gtk.Layout", "x", "int", "0");
527                         this.add_child_default("Gtk.Layout", "y", "int", "0");
528                         this.add_child_default("Gtk.Grid", "colspan", "int", "1");
529                         //this.add_child_default("Gtk.Grid", "height", "int", "1");                     
530                         this.add_child_default("Gtk.Stack", "stack_name", "string", "name");
531                         this.add_child_default("Gtk.Stack", "stack_title", "string", "title");  
532                         
533                         
534                 }
535                 private void add_child_default(string cls, string propname, string type, string val)
536                 {
537                         if (!this.child_defaults.has_key(cls)) {
538                                 this.child_defaults.set(cls, new Gee.ArrayList<JsRender.NodeProp>());
539                         }
540                         
541                         
542                         this.child_defaults.get(cls).add( new JsRender.NodeProp.prop(propname, type, val));
543                 
544                 }
545                  
546                 public Gee.ArrayList<string> packages(Project.Gtk gproject)
547                 {
548                         var vapidirs = gproject.vapidirs();
549                         var ret =  new Gee.ArrayList<string>();
550                         ret.add_all(this.package_cache);
551                         for(var i = 0; i < vapidirs.length;i++) {
552                                 var add = this.loadPackages(vapidirs[i]);
553                                 for (var j=0; j < add.size; j++) {
554                                         if (ret.contains(add.get(j))) {
555                                                 continue;
556                                         }
557                                         ret.add(add.get(j));
558                                 }
559                                 
560                         }
561                         
562                         return ret;
563                 }
564                 // get a list of available vapi files...
565                 
566                 public  Gee.ArrayList<string>  loadPackages(string dirname)
567                 {
568
569                         var ret = new  Gee.ArrayList<string>();
570                         //this.package_cache = new Gee.ArrayList<string>();
571                         
572                         if (!GLib.FileUtils.test(dirname,  FileTest.IS_DIR)) {
573                                 print("opps package directory %s does not exist", dirname);
574                                 return ret;
575                         }
576                          
577                         var dir = File.new_for_path(dirname);
578                         
579                         
580                         try {
581                                 var file_enum = dir.enumerate_children(
582                                         GLib.FileAttribute.STANDARD_DISPLAY_NAME, 
583                                         GLib.FileQueryInfoFlags.NONE, 
584                                         null
585                                 );
586                         
587                          
588                                 FileInfo next_file; 
589                                 while ((next_file = file_enum.next_file(null)) != null) {
590                                         var fn = next_file.get_display_name();
591                                         if (!Regex.match_simple("\\.vapi$", fn)) {
592                                                 continue;
593                                         }
594                                         ret.add(Path.get_basename(fn).replace(".vapi", ""));
595                                 }       
596                         } catch(GLib.Error e) {
597                                 print("oops - something went wrong scanning the packages\n");
598                         }
599                         return ret;
600                         
601                          
602                 }
603                 public override bool  typeOptions(string fqn, string key, string type, out string[] opts) 
604                 {
605                         opts = {};
606                         if (type == ""  ) { // empty type   dont try and fill in options
607                                 return false;
608                         }
609                         GLib.debug("get typeOptions %s (%s)%s", fqn, type, key);
610                         if (type.up() == "BOOL" || type.up() == "BOOLEAN") {
611                                 opts = { "true", "false" };
612                                 return true;
613                         }
614  
615                         var gir= Gir.factoryFqn(this.project,type) ;  // not get class as we are finding Enums.
616                         if (gir == null) {
617                                 GLib.debug("could not find Gir data for %s\n", key);
618                                 return false;
619                         }
620                         //print ("Got type %s", gir.asJSONString());
621                         if (gir.nodetype != "Enum") {
622                                 return false;
623                         }
624                         string[] ret = {};
625                         var iter = gir.consts.map_iterator();
626                         while(iter.next()) {
627                                 
628                                 ret  += (type + "." + iter.get_value().name);
629                         }
630                         
631                         if (ret.length > 0) {
632                                 opts = ret;
633                                 return true;
634                         }
635                         
636                          
637                         return false;
638                          
639                 }
640                 
641                  
642                 
643                 
644                 void add_classes_from_method(GirObject cls, string method , Gee.ArrayList<string> ret)
645                 {
646                         
647                         //GLib.debug("add_classes_from_method %s, %s", cls.fqn(), method);
648                         // does class have this method?
649                         if (!cls.methods.has_key(method)) {
650                                 GLib.debug("skip  %s does not have method %s", cls.fqn(), method);
651                                 return;
652                         }
653                         // add all the possible classes to ret based on first arguemnt?
654                         var m = cls.methods.get(method);
655                         
656                         if (m.paramset.params.size < 1) {
657                                 GLib.debug("%s: %s does not have any params?", cls.fqn(), method);
658                                 return;
659                         }
660                                 
661                         
662                         
663                         var ty = m.paramset.params.get(0).type;
664                         GLib.debug("add  %s   method %s arg0 = %s", cls.fqn(), method, ty);
665                         this.addRealClasses(ret, ty);
666                         // skip dupe // skip depricated
667                         // skip not object // skip GLib.Object (base)
668                         
669                         
670                         //if (cls.fqn() == "GLib.Menu" && method == "append_submenu") {
671                         //      ty = m.paramset.params.get(1).type;
672                         //      GLib.debug("add  %s   method %s arg1 = %s", cls.fqn(), method, ty);
673                         //      this.addRealClasses(ret, ty);
674                         //}
675                          
676                 }
677                 
678                 void addRealClasses(Gee.ArrayList<string>  ret, string cn, bool allow_root = false)
679                 {
680                         if (!cn.contains(".")) {
681                                 return;
682                         }
683                         
684                         var w = this.getClass(cn);
685                         if (w == null) {
686                                 return;
687                         }
688                         
689                         if (w.nodetype != "Class" && w.nodetype != "Interface" ) {
690                                 return;
691                         }
692                         if (ret.contains(cn)) {
693                                 return;
694                         }
695                         
696                         if (!allow_root && w.implements.contains("Gtk.Native")) { // removes popover + window
697                                 return;
698                         }
699                         
700                         if (!w.is_deprecated &&  !w.is_abstract && w.nodetype == "Class" ) {
701                         ret.add(cn);
702                         }
703                         
704                         
705                         
706                         
707                 foreach (var str in w.implementations) {
708                         var c = this.getClass(str);
709                         if (c.is_deprecated || c.is_abstract) {
710                                 continue;
711                                 }
712                                 if (ret.contains(str)) {
713                                         continue;
714                                 }
715                                 if (!allow_root && c.implements.contains("Gtk.Native")) { // removes popover + window
716                                         continue;
717                                 }
718                                 
719                                 
720                                 
721                                 ret.add(str);
722                 }
723                 }
724                         
725                 
726                 /**
727                   this is the real list of objects that appear in the add object pulldown
728                   @param in_rval "*top" || "Gtk.Widget"
729                   
730                 */
731                 public override Gee.ArrayList<string> getChildList(string in_rval, bool with_props)
732         {
733                 
734                 GLib.debug("getChildList %s %s", in_rval, with_props ? "(with props)" : "");
735                 
736                 //return this.original_getChildList(  in_rval, with_props);
737                 var pr = (Project.Gtk) this.project;
738                 if (with_props && pr.child_list_cache_props.has_key(in_rval)) {
739                         return pr.child_list_cache_props.get(in_rval);
740                 }
741                 if (!with_props && pr.child_list_cache.has_key(in_rval)) {
742                                 return pr.child_list_cache.get(in_rval);
743                 }
744                 
745                 // CACHE ?      
746                 var ret = new Gee.ArrayList<string>();
747                 
748                 if (in_rval == "*top") {
749                         // everythign that's not depricated and extends Gtk.Widget
750                         // even a gtk window and about dialog are widgets
751                         this.addRealClasses(ret, "Gtk.Widget", true);
752                         
753                         return ret;
754                         
755                 
756                 
757                 }
758                 var cls = this.getClass(in_rval);
759                 if (cls == null) {
760                         GLib.debug("could not get class for %s", in_rval);
761                         return ret;
762                         }
763                 
764                 // look through methods of in_rval
765                 // set_X << ignore
766                 // probably methods:
767                 this.add_classes_from_method(cls, "add_controller", ret);
768                 this.add_classes_from_method(cls, "add_shortcut", ret);
769                 this.add_classes_from_method(cls, "add_tick_callback", ret); // wtf does this do.
770                 this.add_classes_from_method(cls, "append", ret);
771                 this.add_classes_from_method(cls, "append_column", ret); // columnview column
772                 this.add_classes_from_method(cls, "append_item", ret); // GLib.Menu 
773                 //this.add_classes_from_method(cls, "append_submenu", ret); // GLib.Menu - complicated to support
774                 this.add_classes_from_method(cls, "attach", ret); // grid column                
775                 this.add_classes_from_method(cls, "pack_start", ret); // headerbar (also has pack end?)
776                 
777                   // add_controller 1st arge = ??
778                   // add_menomic_label ??? << no ???
779                   // add_shortcut? 
780                  // add_tick_callback ?
781                  // append << core one to add stuff..
782                  
783                 if (!with_props) {
784                         
785                         pr.child_list_cache.set(in_rval, ret);
786                         return ret; 
787                 }
788                 foreach(var pn in cls.props.values) {
789
790                         if (!pn.is_writable ) {
791                                 GLib.debug("Skip (not write)  %s : (%s) %s", cls.fqn(), pn.type , pn.name);
792                                 continue;
793                         }
794                         // if (&& !pn.ctor_only << we add these?
795                         // are they really available ?
796                         GLib.debug("Add %s : (%s) %s", cls.fqn(), pn.type , pn.name);                   
797                         this.addRealClasses(ret, pn.type);
798                 }
799                 
800                 pr.child_list_cache_props.set(in_rval, ret);            
801                 
802                 return ret;
803                 
804                 
805         }
806         
807         public void buildChildListForDroppingProject()
808         {
809
810                         this.load();
811                         var pr = (Project.Gtk) this.project;
812                         
813                         if (pr.dropList != null) {
814                                 GLib.debug("Drop list alreayd loaded");
815                                 return;
816                         }
817                          
818                         pr.dropList = new Gee.HashMap<string,Gee.ArrayList<string>>();
819                         foreach(var key in   pr.gir_cache.keys) {
820                                 var gir = pr.gir_cache.get(key);
821                                 GLib.debug("building drop list for package %s", key);
822                                 this.buildChildListForDropping(key, gir.classes);
823                         }       
824                 }
825
826                 public void buildChildListForDropping(string pkg, Gee.HashMap<string,GirObject> classes)
827                 {
828                         
829
830                         
831                         foreach(var cls in classes.keys) {
832                                 GLib.debug("building drop list for class %s.%s", pkg, cls);
833                                 this.buildDropList(pkg + "." + cls, this.getChildList(pkg + "." + cls, true));
834                         }
835                         this.buildDropList("*top", this.getChildList("*top", true));
836                 }
837                 
838                  
839         
840         public void buildDropList(string parent, Gee.ArrayList<string> children) 
841         {
842                 
843                 var pr = (Project.Gtk) this.project;
844                 foreach(var c in children) {
845                         if (!pr.dropList.has_key(c)) {
846
847                                 pr.dropList.set(c, new Gee.ArrayList<string>());
848                                 }
849                         var dl = pr.dropList.get(c);
850                         if (dl.contains(parent)) {
851                                 continue;
852                         }
853                         GLib.debug("%s[] = %s", c, parent);
854                         dl.add(parent);
855                 }
856         
857         
858         }
859         
860                 public override Gee.ArrayList<string> getDropList(string rval)
861                 {
862                         this.buildChildListForDroppingProject();
863                         var pr = (Project.Gtk) this.project;
864                         if (!pr.dropList.has_key(rval)) {
865                                 GLib.debug("returning empty drop list for  %s", rval);
866                                 return new Gee.ArrayList<string>();
867                         }
868                         GLib.debug("returning %d items in drop list  %s", pr.dropList.get(rval).size, rval);                    
869                         return  pr.dropList.get(rval);
870
871                         
872                 }
873                  
874                  
875                 public override JsRender.Node fqnToNode(string fqn) 
876                 {
877                         this.load();    
878                         var ret = new JsRender.Node();
879                         ret.setFqn(fqn);
880                         if (!this.node_defaults.has_key(fqn)) {
881                                 return ret;
882                         }
883
884                         foreach (var nv in this.node_defaults.get(fqn).values) {
885                                 ret.add_prop(nv.dupe());
886                         }
887                         return ret;
888                         
889                         
890                         
891                 }
892                 
893                 
894                 
895     }
896 }
897