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