src/Palete/Gtk.vala
[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                          
232                         var dir = File.new_for_path(dirname);
233                         try {
234                                 var file_enum = dir.enumerate_children(
235                                         GLib.FileAttribute.STANDARD_DISPLAY_NAME, 
236                                         GLib.FileQueryInfoFlags.NONE, 
237                                         null
238                                 );
239                         
240                          
241                                 FileInfo next_file; 
242                                 while ((next_file = file_enum.next_file(null)) != null) {
243                                         var fn = next_file.get_display_name();
244                                         if (!Regex.match_simple("\\.vapi$", fn)) {
245                                                 continue;
246                                         }
247                                         ret.add(Path.get_basename(fn).replace(".vapi", ""));
248                                 }       
249                         } catch(Error e) {
250                                 print("oops - something went wrong scanning the packages\n");
251                         }
252                         return ret;
253                         
254                          
255                 }
256                 public override bool  typeOptions(string fqn, string key, string type, out string[] opts) 
257                 {
258                         opts = {};
259                         print("get typeOptions %s (%s)%s", fqn, type, key);
260                         if (type.up() == "BOOL" || type.up() == "BOOLEAN") {
261                                 opts = { "true", "false" };
262                                 return true;
263                         }
264                         var gir= Gir.factoryFqn(type) ;
265                         if (gir == null) {
266                                 print("could not find Gir data for %s\n", key);
267                                 return false;
268                         }
269                         print ("Got type %s", gir.asJSONString());
270                         if (gir.nodetype != "Enum") {
271                                 return false;
272                         }
273                         string[] ret = {};
274                         var iter = gir.consts.map_iterator();
275                         while(iter.next()) {
276                                 
277                                 ret  += (type + "." + iter.get_value().name);
278                         }
279                         
280                         if (ret.length > 0) {
281                                 opts = ret;
282                                 return true;
283                         }
284                         
285                          
286                         return false;
287                          
288                 }
289                 
290                 public override  List<SourceCompletionItem> suggestComplete(
291                                 JsRender.JsRender file,
292                                 JsRender.Node? node,
293                                 string proptype, 
294                                 string key,
295                                 string complete_string
296                 ) { 
297                         
298                         var ret =  new List<SourceCompletionItem>();
299                         // completion rules??
300                         
301                         // Roo......
302                         
303                         // this. (based on the node type)
304                         // this.xxx // Node and any determination...
305                         
306                         if (complete_string.index_of(".",0) < 0) {
307                                 // string does not have a '.'
308                                 // offer up this / Roo / javascript keywords... / look for var string = .. in the code..
309                                 for(var i = 0; i <  JsRender.Lang.match_strings.size ; i++) {
310                                         var str = JsRender.Lang.match_strings.get(i);
311                                         if (complete_string != str && str.index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
312                                                 ret.append(new SourceCompletionItem (str, str, null, "javascript : " + str));
313                                         }
314                                         
315                                         
316                                 }
317                                 if (complete_string != "Roo" && "Roo".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
318                                         ret.append(new SourceCompletionItem ("Roo - A Roo class", "Roo", null, "Roo library"));
319                                 }
320                                 if (complete_string != "_this" && "_this".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
321                                         ret.append(new SourceCompletionItem ("_this - the top level element", "_this", null, "Top level element"));
322                                 }
323                                 return ret;
324                         }
325                         // got at least one ".".
326                         var parts = complete_string.split(".");
327                         var curtype = "";
328                         var cur_instance = false;
329                         if (parts[0] == "this") {
330                                 // work out from the node, what the type is...
331                                 if (node == null) {
332                                         print("node is empty - no return\n");
333                                         return ret; // no idea..
334                                 }
335                                 curtype = node.fqn();
336                                 cur_instance = true;
337                         }
338                         if (parts[0] == "Roo") {        
339                                 curtype = "Roo";
340                                 cur_instance = false;
341                         }
342                         
343                         var prevbits = parts[0] + ".";
344                         for(var i =1; i < parts.length; i++) {
345                                 print("matching %d/%d\n", i, parts.length);
346                                 var is_last = i == parts.length -1;
347                                 
348                                 // look up all the properties of the type...
349                                 var cls = this.getClass(curtype);
350                                 if (cls == null) {
351                                         print("could not get class of curtype %s\n", curtype);
352                                         return ret;
353                                 }
354
355                                 if (!is_last) {
356                                 
357                                         // only exact matches from here on...
358                                         if (cur_instance) {
359                                                 if (cls.props.has_key(parts[i])) {
360                                                         var prop = cls.props.get(parts[i]);
361                                                         if (prop.type.index_of(".",0) > -1) {
362                                                                 // type is another roo object..
363                                                                 curtype = prop.type;
364                                                                 prevbits += parts[i] + ".";
365                                                                 continue;
366                                                         }
367                                                         return ret;
368                                                 }
369                                                 
370                                                 
371                                                 
372                                                 // check methods?? - we do not export that at present..
373                                                 return ret;      //no idea...
374                                         }
375                                 
376                                         // not a instance..
377                                         //look for child classes.
378                                         var citer = this.classes.map_iterator();
379                                         var foundit = false;
380                                         while (citer.next()) {
381                                                 var scls = citer.get_key();
382                                                 var look = prevbits + parts[i];
383                                                 if (scls.index_of(look,0) != 0) {
384                                                         continue;
385                                                 }
386                                                 // got a starting match..
387                                                 curtype = look;
388                                                 cur_instance = false;
389                                                 foundit =true;
390                                                 break;
391                                         }
392                                         if (!foundit) {
393                                                 return ret;
394                                         }
395                                         prevbits += parts[i] + ".";
396                                         continue;
397                                 }
398                                 // got to the last element..
399                                 print("Got last element\n");
400                                 if (curtype == "") { // should not happen.. we would have returned already..
401                                         return ret;
402                                 }
403                                 print("Got last element type %s\n",curtype);
404                                 if (!cur_instance) {
405                                         print("matching instance");
406                                         // it's a static reference..
407                                         var citer = this.classes.map_iterator();
408                                         while (citer.next()) {
409                                                 var scls = citer.get_key();
410                                                 var look = prevbits + parts[i];
411                                                 if (parts[i].length > 0 && scls.index_of(look,0) != 0) {
412                                                         continue;
413                                                 }
414                                                 // got a starting match..
415                                                 ret.append(new SourceCompletionItem (
416                                                         scls,
417                                                         scls, 
418                                                         null, 
419                                                         scls));
420                                         }
421                                         return ret;
422                                 }
423                                 print("matching property");
424                                 
425                                 
426                                 
427                                 var citer = cls.methods.map_iterator();
428                                 while (citer.next()) {
429                                         var prop = citer.get_value();
430                                         // does the name start with ...
431                                         if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
432                                                 continue;
433                                         }
434                                         // got a matching property...
435                                         // return type?
436                                         ret.append(new SourceCompletionItem (
437                                                          prop.name + prop.sig + " :  ("+ prop.propertyof + ")", 
438                                                         prevbits + prop.name + "(", 
439                                                         null, 
440                                                         prop.doctxt));
441                                 }
442                                 
443                                 // get the properties / methods and subclasses.. of cls..
444                                 // we have cls.. - see if the string matches any of the properties..
445                                 citer = cls.props.map_iterator();
446                                 while (citer.next()) {
447                                         var prop = citer.get_value();
448                                         // does the name start with ...
449                                         if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
450                                                 continue;
451                                         }
452                                         // got a matching property...
453                                         
454                                         ret.append(new SourceCompletionItem (
455                                                          prop.name + " : " + prop.type + " ("+ prop.propertyof + ")", 
456                                                         prevbits + prop.name, 
457                                                         null, 
458                                                         prop.doctxt));
459                                 }
460                                          
461                                         
462                                 return ret;     
463                                         
464                                         
465                                 
466                                         
467                                 
468                         }
469                         
470                          
471                         
472                         
473                         
474                         
475                         return ret;
476                 }
477         
478     }
479 }
480