Fix #5829 - Messing around with flutter API
[roobuilder] / src / Palete / Gtk.vala
1 using Gtk;
2
3 namespace Palete {
4
5         
6         
7         
8         
9         public class Introspect.El : Object
10         {
11                 public enum eltype { 
12                             NS,
13                             CLASS,
14                             METHOD,
15                             PROP
16                 }
17                 
18             
19                 public eltype type;
20         }
21
22
23         public class Gtk : Palete {
24                 
25                 public Gee.ArrayList<string> package_cache;
26                 
27                 public Gtk(Project.Project project)
28                 {
29
30                     base(project);
31                     this.name = "Gtk";
32                     var context = new Vala.CodeContext ();
33                          
34                     this.package_cache = this.loadPackages(Path.get_dirname (context.get_vapi_path("glib-2.0")));
35                     this.package_cache.add_all(
36                             this.loadPackages(Path.get_dirname (context.get_vapi_path("gee-0.8")))
37                     );
38                                 //this.load();
39                     // various loader methods..
40                       //this.map = [];
41                     //this.load();
42                     //this.proplist = {};
43                     //this.comments = { }; 
44                     // no parent...
45                 }
46               
47                 public override void  load () {
48
49                         this.loadUsageFile(BuilderApplication.configDirectory() + "/resources/GtkUsage.txt");
50          
51                      
52                 }
53                 
54                 public string doc(string what) {
55                         var ns = what.split(".")[0];
56                         var gir =  Gir.factory(this.project,ns);
57                         return   gir.doc(what);
58                         
59                     //return typeof(this.comments[ns][what]) == 'undefined' ?  '' : this.comments[ns][what];
60                 }
61
62                         // does not handle implements...
63                 public override GirObject? getClass(string ename)
64                 {
65
66                         var es = ename.split(".");
67                         var gir = Gir.factory(this.project,es[0]);
68                 
69                         return gir.classes.get(es[1]);
70                 
71                 }
72
73                 public override Gee.HashMap<string,GirObject> getPropertiesFor( string ename, string type)  
74                 {
75                         //print("Loading for " + ename);
76                     
77
78
79                                 // if (typeof(this.proplist[ename]) != 'undefined') {
80                         //print("using cache");
81                         //   return this.proplist[ename][type];
82                         //}
83                         // use introspection to get lists..
84          
85                         var es = ename.split(".");
86                         var gir = Gir.factory(this.project,es[0]);
87                         if (gir == null) {
88                                 print("WARNING = could not load vapi for %s  (%s)\n", ename , es[0]);
89                                 return new Gee.HashMap<string,GirObject>();
90                         }
91                         var cls = gir.classes.get(es[1]);
92                         if (cls == null) {
93                                 var ret = new Gee.HashMap<string,GirObject>();
94                                 return ret;
95                                 //throw new Error.INVALID_VALUE( "Could not find class: " + ename);
96                         
97                         }
98
99                         //cls.parseProps();
100                         //cls.parseSignals(); // ?? needed for add handler..
101                         //cls.parseMethods(); // ?? needed for ??..
102                         //cls.parseConstructors(); // ?? needed for ??..
103
104                         cls.overlayParent(this.project);
105
106                         switch  (type) {
107                                 case "props":
108                                         return cls.props;
109                                 case "signals":
110                                         return cls.signals;
111                                 case "methods":
112                                         return cls.methods;
113                                 case "ctors":
114                                         return cls.ctors;
115                                 default:
116                                         throw new Error.INVALID_VALUE( "getPropertiesFor called with: " + type);
117                                         //var ret = new Gee.HashMap<string,GirObject>();
118                                         //return ret;
119                                 
120                         }
121                                 
122                         
123                         //cls.overlayInterfaces(gir);
124                     
125                     
126                      
127                 }
128                 public string[] getInheritsFor(string ename)
129                 {
130                         string[] ret = {};
131                          
132                         var cls = Gir.factoryFqn(this.project,ename);
133                          
134                         if (cls == null || cls.nodetype != "Class") {
135                                 print("getInheritsFor:could not find cls: %s\n", ename);
136                                 return ret;
137                         }
138                         
139                         return cls.inheritsToStringArray();
140                         
141
142                 }
143          
144                 public override void fillPack(JsRender.Node node,JsRender.Node parent)
145                 {   
146                         
147                         string inherits =  string.joinv(" ", 
148                                       this.getInheritsFor (node.fqn())) + " ";
149                         inherits += node.fqn() + " ";
150                         //print ("fillPack:Inherits : %s\n", inherits);
151                         // parent.fqn() method ( node.fqn()
152                         var methods = this.getPropertiesFor (parent.fqn(), "methods");
153                         
154                         var res = new Gee.HashMap<string,string>();
155                         var map = methods.map_iterator();
156                         while (map.next()) {
157                                 
158                                 var n = map.get_key();
159                                 //print ("fillPack:checking method %s\n", n);
160                                 
161                                 var meth = map.get_value();
162                                 if (meth.paramset == null || meth.paramset.params.size < 1) {
163                                         print ("fillPack:c -- no params\n");
164                                 
165                                         continue;
166                                 }
167                                 var fp = meth.paramset.params.get(0);
168                                 
169                                 var type = Gir.fqtypeLookup(this.project, fp.type, meth.ns);
170                                 print ("fillPack:first param type is %s\n", type);
171
172                                 
173                                 if (!inherits.contains(" " + type + " ")) {
174                                         continue;
175                                 }
176                                 
177                                 
178                                 var pack = meth.name;
179                                 for(var i =1; i < meth.paramset.params.size; i++) {
180                                         var ty = Gir.fqtypeLookup(this.project,meth.paramset.params.get(i).type, meth.ns);
181                                         pack += "," + Gir.guessDefaultValueForType(ty);
182                                 }
183
184                                 print ("fillPack:add pack:  --          %s\n",pack );
185
186                                 res.set(meth.name, pack);
187                                 
188                                 
189
190                         }
191                         if (res.size < 1) {
192                                 return ;
193                         }
194                         if (res.has_key("pack_start")) {
195                                 node.props.set("* pack", res.get("pack_start"));
196                                 return;
197                         }
198                         if (res.has_key("add")) {
199                                 node.props.set("* pack", res.get("add"));
200                                 return;
201                         }
202                         var riter = res.map_iterator();
203                         while(riter.next()) {
204                                 node.props.set("* pack", riter.get_value());
205                                 return;
206                         }
207                         
208                         
209                 }
210                 public Gee.ArrayList<string> packages(Project.Gtk gproject)
211                 {
212                         var vapidirs = gproject.vapidirs();
213                         var ret =  new Gee.ArrayList<string>();
214                         ret.add_all(this.package_cache);
215                         for(var i = 0; i < vapidirs.length;i++) {
216                                 var add = this.loadPackages(vapidirs[i]);
217                                 for (var j=0; j < add.size; j++) {
218                                         if (ret.contains(add.get(j))) {
219                                                 continue;
220                                         }
221                                         ret.add(add.get(j));
222                                 }
223                                 
224                         }
225                         
226                         return ret;
227                 }
228                 
229                 public  Gee.ArrayList<string>  loadPackages(string dirname)
230                 {
231
232                         var ret = new  Gee.ArrayList<string>();
233                         //this.package_cache = new Gee.ArrayList<string>();
234                         
235                         if (!GLib.FileUtils.test(dirname,  FileTest.IS_DIR)) {
236                                 print("opps package directory %s does not exist", dirname);
237                                 return ret;
238                         }
239                          
240                         var dir = File.new_for_path(dirname);
241                         
242                         
243                         try {
244                                 var file_enum = dir.enumerate_children(
245                                         GLib.FileAttribute.STANDARD_DISPLAY_NAME, 
246                                         GLib.FileQueryInfoFlags.NONE, 
247                                         null
248                                 );
249                         
250                          
251                                 FileInfo next_file; 
252                                 while ((next_file = file_enum.next_file(null)) != null) {
253                                         var fn = next_file.get_display_name();
254                                         if (!Regex.match_simple("\\.vapi$", fn)) {
255                                                 continue;
256                                         }
257                                         ret.add(Path.get_basename(fn).replace(".vapi", ""));
258                                 }       
259                         } catch(Error e) {
260                                 print("oops - something went wrong scanning the packages\n");
261                         }
262                         return ret;
263                         
264                          
265                 }
266                 public override bool  typeOptions(string fqn, string key, string type, out string[] opts) 
267                 {
268                         opts = {};
269                         print("get typeOptions %s (%s)%s", fqn, type, key);
270                         if (type.up() == "BOOL" || type.up() == "BOOLEAN") {
271                                 opts = { "true", "false" };
272                                 return true;
273                         }
274                         var gir= Gir.factoryFqn(this.project,type) ;
275                         if (gir == null) {
276                                 print("could not find Gir data for %s\n", key);
277                                 return false;
278                         }
279                         print ("Got type %s", gir.asJSONString());
280                         if (gir.nodetype != "Enum") {
281                                 return false;
282                         }
283                         string[] ret = {};
284                         var iter = gir.consts.map_iterator();
285                         while(iter.next()) {
286                                 
287                                 ret  += (type + "." + iter.get_value().name);
288                         }
289                         
290                         if (ret.length > 0) {
291                                 opts = ret;
292                                 return true;
293                         }
294                         
295                          
296                         return false;
297                          
298                 }
299                 
300                 public override  List<SourceCompletionItem> suggestComplete(
301                                 JsRender.JsRender file,
302                                 JsRender.Node? node,
303                                 string proptype, 
304                                 string key,
305                                 string complete_string
306                 ) { 
307                         
308                         var ret =  new List<SourceCompletionItem>();
309                         // completion rules??
310                         
311                         // make sure data is loaded
312                         Gir.factory(this.project,"Gtk");
313                         
314                         // Roo......
315                         
316                         // this. (based on the node type)
317                         // this.xxx // Node and any determination...
318                         
319                         if (complete_string.index_of(".",0) < 0) {
320                                 // string does not have a '.'
321                                 // offer up vala keywords... / _this .. / look for var string = .. in the code..
322                                 
323                                 var max = (int)Vala.TokenType.YIELD +1;
324                                 for (var i =0; i < max;i++) {
325                                         var m = (Vala.TokenType)i;
326                                         var s = m.to_string();
327                                         var ss = s.slice(1,-1);
328                                         if (s[0] == '`' && GLib.Regex.match_simple("^[a-z]+$", ss) &&
329                                                 complete_string != ss && ss.index_of(complete_string,0) == 0 ) {
330                                                 ret.append(new SourceCompletionItem (ss, ss, null, "vala : " + ss));
331                                         }
332                                 }
333                                 var miter = ((Project.Gtk)this.project).gir_cache.map_iterator();
334                                 while (miter.next()) {
335                                         var ss = miter.get_key();
336                                         
337                                         if (complete_string != ss && ss.index_of(complete_string,0) == 0 ) {
338                                                 ret.append(new SourceCompletionItem (ss, ss, null, "vala namespace : " + ss));
339                                         }
340                                 }
341                                  
342                                 
343                                 if (complete_string != "_this" && "_this".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
344                                         ret.append(new SourceCompletionItem ("_this - the top level element", "_this", null, "Top level element"));
345                                 }
346                                 // basic types..
347                                 
348                                 return ret;
349                         }
350                          
351                         
352                          // got at least one ".".
353                         var parts = complete_string.split(".");
354                         var curtype = "";
355                         var cur_instance = false;
356                         if (parts[0] == "this") {
357                                 // work out from the node, what the type is...
358                                 if (node == null) {
359                                         print("node is empty - no return\n");
360                                         return ret; // no idea..
361                                 }
362                                 curtype = "*" +  node.fqn();
363                                 cur_instance = true;
364                         } else {
365                                  if (((Project.Gtk)this.project).gir_cache.get(parts[0]) == null) {
366                                         return ret;
367                                 }
368                                 curtype = parts[0];
369                         }
370                         // all Gtk.... etc.. types...
371                         
372                         
373                         //if (parts[0] == "Roo") {      
374                         //      curtype = "Roo";
375                         //      cur_instance = false;
376                         //}
377                         
378                         var prevbits = parts[0] + ".";
379                         for(var i =1; i < parts.length; i++) {
380                                 print("matching %d/%d\n", i, parts.length);
381                                 var is_last = i == parts.length -1;
382                                 
383                                 
384                                  
385                                 // look up all the properties of the type...
386                                 var cls = Gir.factoryFqn(this.project,curtype);
387                                 if (cls == null && curtype[0] != '*') {
388                                         print("could not get class of curtype %s\n", curtype);
389                                         return ret;
390                                 }
391
392                                 if (!is_last) {
393                                         
394                                         if (curtype[0] == '*' && parts[i] == "el") {
395                                                 curtype = curtype.substring(1);
396                                                 prevbits += parts[i] + ".";
397                                                 continue;
398                                         }
399                                         
400                                         // only exact matches from here on...
401                                         if (cur_instance) {
402                                                 if (cls == null) {
403                                                         return ret;
404                                                 }
405                                                 if (cls.props.has_key(parts[i])) {
406                                                         var prop = cls.props.get(parts[i]);
407                                                         if (prop.type.index_of(".",0) > -1) {
408                                                                 // type is another roo object..
409                                                                 curtype = prop.type;
410                                                                 prevbits += parts[i] + ".";
411                                                                 continue;
412                                                         }
413                                                         return ret;
414                                                 }
415                                                  
416                                                 
417                                                 
418                                                 // check methods?? - we do not export that at present..
419                                                 return ret;      //no idea...
420                                         }
421                                         var look = prevbits + parts[i];
422                                         var scls = Gir.factoryFqn(this.project,look);
423                                         if (scls == null) {
424                                                 return ret;
425                                         }
426                                         curtype = look;
427                                         prevbits += parts[i] + ".";
428                                         continue;
429                                          
430                                 }
431                                 
432                                 // got to the last element..
433                                 print("Got last element\n");
434                                 if (curtype == "") { // should not happen.. we would have returned already..
435                                         return ret;
436                                 }
437                                 print("Got last element type %s\n",curtype);
438                                 if (!cur_instance) {
439                                         print("matching instance");
440                                         // it's a static reference..
441                                         var citer = cls.classes.map_iterator();
442                                         while (citer.next()) {
443                                                 var scls = citer.get_key();
444                                                 
445                                                 if (parts[i].length > 0 && scls.index_of(parts[i],0) != 0) {
446                                                         continue;
447                                                 }
448                                                 // got a starting match..
449                                                 ret.append(new SourceCompletionItem (
450                                                         prevbits + scls,
451                                                         prevbits + scls, 
452                                                         null, 
453                                                         scls));
454                                         }
455                                         // methods.... 
456                                         citer = cls.methods.map_iterator();
457                                         while (citer.next()) {
458                                                 var scls = citer.get_key();
459                                                 
460                                                 if (parts[i].length > 0 && scls.index_of(parts[i],0) != 0) {
461                                                         continue;
462                                                 }
463                                                 // got a starting match..
464                                                 ret.append(new SourceCompletionItem (
465                                                         prevbits + scls  + citer.get_value().sig ,
466                                                         prevbits + scls, 
467                                                         null, 
468                                                         scls));
469                                         }
470                                         
471                                         // enums.... 
472                                         citer = cls.consts.map_iterator();
473                                         while (citer.next()) {
474                                                 var scls = citer.get_key();
475                                                 
476                                                 if (parts[i].length > 0 && scls.index_of(parts[i],0) != 0) {
477                                                         continue;
478                                                 }
479                                                 // got a starting match..
480                                                 ret.append(new SourceCompletionItem (
481                                                         prevbits + scls  + citer.get_value().sig ,
482                                                         prevbits + scls, 
483                                                         null, 
484                                                         scls));
485                                         }
486                                         
487                                         
488                                         return ret;
489                                 }
490                                 print("matching property");
491                                 if (cls == null) {
492                                         return ret;
493                                 }
494                                 
495                                 
496                                 var citer = cls.methods.map_iterator();
497                                 while (citer.next()) {
498                                         var prop = citer.get_value();
499                                         // does the name start with ...
500                                         if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
501                                                 continue;
502                                         }
503                                         // got a matching property...
504                                         // return type?
505                                         ret.append(new SourceCompletionItem (
506                                                          prop.name + prop.sig + " :  ("+ prop.propertyof + ")", 
507                                                         prevbits + prop.name + "(", 
508                                                         null, 
509                                                         prop.doctxt));
510                                 }
511                                 
512                                 // get the properties / methods and subclasses.. of cls..
513                                 // we have cls.. - see if the string matches any of the properties..
514                                 citer = cls.props.map_iterator();
515                                 while (citer.next()) {
516                                         var prop = citer.get_value();
517                                         // does the name start with ...
518                                         if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
519                                                 continue;
520                                         }
521                                         // got a matching property...
522                                         
523                                         ret.append(new SourceCompletionItem (
524                                                          prop.name + " : " + prop.type + " ("+ prop.propertyof + ")", 
525                                                         prevbits + prop.name, 
526                                                         null, 
527                                                         prop.doctxt));
528                                 }
529                                          
530                                         
531                                 return ret;     
532                                         
533                                         
534                                 
535                                         
536                                 
537                         }
538                         
539                          
540                         
541                         
542                         
543                         
544                         return ret;
545                 }
546                 
547                 public override string[] getChildList(string in_rval)
548         {
549                 return this.original_getChildList(  in_rval);
550         }
551                 public override string[] getDropList(string rval)
552                 {
553                         return this.default_getDropList(rval);
554                 }       
555     }
556 }
557