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