src/Palete/Roo.vala
[app.Builder.js] / src / Palete / Roo.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 Roo : Palete {
24                 
25                 
26         public Roo()
27         {
28
29
30             
31             base();
32             this.name = "Roo";
33                           
34         }
35
36                 Gee.HashMap<string,GirObject> propsFromJSONArray(string type, Json.Array ar, GirObject cls)
37                 {
38
39                         var ret = new Gee.HashMap<string,GirObject>();
40                         
41                         for (var i =0 ; i < ar.get_length(); i++) {
42                                 var o = ar.get_object_element(i);
43                                 var name = o.get_string_member("name"); 
44                                 var prop = new GirObject(type, name );  
45                                  
46                                 prop.type        = o.get_string_member("type");
47                                 prop.doctxt  = o.get_string_member("desc");
48                                 prop.propertyof = o.has_member("memberOf") ? o.get_string_member("memberOf") : "";
49                                 if (prop.propertyof.length < 1)  {
50                                         prop.propertyof = cls.name;
51                                 }
52                                 prop.sig = o.has_member("sig") ? o.get_string_member("sig") : "";
53                                 
54                                 if (o.has_member("optvals")  ) {
55                                         var oar = o.get_array_member("optvals");
56                                         
57                                         for (var oi = 0; oi < oar.get_length(); oi++) {
58                                                 prop.optvalues.add(oar.get_string_element(oi));
59                                         }
60                                         
61                                 }       
62                                 
63                                 
64                                 
65                                 //print(type + ":" + name +"\n");
66                                 ret.set(name,prop);
67                         }
68                         return ret;
69                 }
70          
71                 public override void  load () {
72
73                         if (this.classes != null) {
74                                 return;
75                         }
76                         this.loadUsageFile(BuilderApplication.configDirectory() + "/resources/RooUsage.txt");
77                         this.classes = new Gee.HashMap<string,GirObject>();
78
79                                 
80                         var pa = new Json.Parser();
81                         pa.load_from_file(BuilderApplication.configDirectory() + "/resources/roodata.json");
82                         var node = pa.get_root();
83
84                         var clist =  node.get_object().get_object_member("data");
85                                 clist.foreach_member((o , key, value) => {
86                                 //print("cls:" + key+"\n");
87                          
88                                 var cls = new GirObject("class", key);  
89                                 cls.props = this.propsFromJSONArray("prop", value.get_object().get_array_member("props"),cls);
90                                 cls.signals = this.propsFromJSONArray("signal", value.get_object().get_array_member("events"),cls);
91                                 
92                                 this.classes.set(key, cls);
93                         });
94                                 
95                                 
96                         
97                                  
98                 }
99                   
100                         
101                 public string doc(string what) {
102                         return "";
103                         /*var ns = what.split(".")[0];
104
105
106                         
107                         
108                                 var gir =  Gir.factory(ns);
109                                 return   gir.doc(what);
110                                 */
111                                 
112                         //return typeof(this.comments[ns][what]) == 'undefined' ?  '' : this.comments[ns][what];
113                 }
114
115                 // does not handle implements...
116                 public override GirObject? getClass(string ename)
117                 {
118                         this.load();
119                         return this.classes.get(ename);
120                         
121                 }
122                 
123                 public override Gee.HashMap<string,GirObject> getPropertiesFor(string ename, string type)
124                 {
125                         //print("Loading for " + ename);
126                         
127
128                         this.load();
129                                         // if (typeof(this.proplist[ename]) != 'undefined') {
130                                         //print("using cache");
131                                  //   return this.proplist[ename][type];
132                                 //}
133                                 // use introspection to get lists..
134                  
135                         
136                         var cls = this.classes.get(ename);
137                         var ret = new Gee.HashMap<string,GirObject>();
138                         if (cls == null) {
139                                 print("could not find class: %s\n", ename);
140                                 return ret;
141                                 //throw new Error.INVALID_VALUE( "Could not find class: " + ename);
142                 
143                         }
144
145                         //cls.parseProps();
146                         //cls.parseSignals(); // ?? needed for add handler..
147                         //cls.parseMethods(); // ?? needed for ??..
148                         //cls.parseConstructors(); // ?? needed for ??..
149
150                         //cls.overlayParent();
151
152                         switch  (type) {
153                                 
154                                 
155                                 case "props":
156                                         return cls.props;
157                                 case "signals":
158                                         return cls.signals;
159                                 case "methods":
160                                         return ret;
161                                 case "ctors":
162                                         return ret;
163                                 default:
164                                         throw new Error.INVALID_VALUE( "getPropertiesFor called with: " + type);
165                                         //var ret = new Gee.HashMap<string,GirObject>();
166                                         //return ret;
167                         
168                         }
169                 
170         
171                 //cls.overlayInterfaces(gir);
172
173
174                          
175                 }
176                 public string[] getInheritsFor(string ename)
177                 {
178                         string[] ret = {};
179                         var es = ename.split(".");
180                         var gir = Gir.factory(es[0]);
181                         
182                         var cls = gir.classes.get(es[1]);
183                         if (cls == null) {
184                                 return ret;
185                         }
186                         return cls.inheritsToStringArray();
187                         
188
189                 }
190
191
192                 public override void fillPack(JsRender.Node node,JsRender.Node parent)
193                 {   
194
195                          return;
196                 }
197                 /*
198                  *  Pulldown options for type
199                  */
200                 public override bool typeOptions(string fqn, string key, string type, out string[] opts) 
201                 {
202                         opts = {};
203                         print("get typeOptions %s (%s)%s", fqn, type, key);
204                         if (type.up() == "BOOL" || type.up() == "BOOLEAN") {
205                                 opts = { "true", "false" };
206                                 return true;
207                          }
208                          
209                          var props = this.getPropertiesFor(fqn, "props");
210                          if (!props.has_key(key)) {
211                                  print("prop %s does not have key %s\n", fqn, key);
212                                  return false;
213                          }
214                          var pr = props.get(key);
215                          if (pr.optvalues.size < 1) {
216                                  print("prop %s no optvalues for %s\n", fqn, key);
217                                  return false;
218                          }
219                          string[] ret = {};
220                          for(var i = 0; i < pr.optvalues.size; i++) {
221                                  ret += pr.optvalues.get(i);
222                          }
223                          opts = ret;
224                          print("prop %s returning optvalues for %s\n", fqn, key);
225                          return true;
226                          
227                 }
228                 public override  List<SourceCompletionItem> suggestComplete(
229                                 JsRender.JsRender file,
230                                 JsRender.Node node,
231                                 string proptype, 
232                                 string key,
233                                 string complete_string
234                 ) { 
235                         
236                         var ret =  new List<SourceCompletionItem>();
237                         // completion rules??
238                         
239                         // Roo......
240                         
241                         // this. (based on the node type)
242                         // this.xxx // Node and any determination...
243                         
244                         if (complete_string.index_of(".",0) < 0) {
245                                 // string does not have a '.'
246                                 // offer up this / Roo / javascript keywords... / look for var string = .. in the code..
247                                 for(var i = 0; i <  JsRender.Lang.match_strings.size ; i++) {
248                                         var str = JsRender.Lang.match_strings.get(i);
249                                         if (complete_string != str && str.index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
250                                                 ret.append(new SourceCompletionItem (str, str, null, "javascript : " + str));
251                                         }
252                                         
253                                         
254                                 }
255                                 if (complete_string != "Roo" && "Roo".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
256                                         ret.append(new SourceCompletionItem ("Roo - A Roo class", "Roo", null, "Roo library"));
257                                 }
258                                 if (complete_string != "_this" && "_this".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
259                                         ret.append(new SourceCompletionItem ("_this (the top level element", "_this", null, "Top level element"));
260                                 }
261                                 return ret;
262                         }
263                         // got at least one ".".
264                         var parts = complete_string.split(".");
265                         var curtype = "";
266                         var cur_instance = false;
267                         if (parts[0] == "this") {
268                                 // work out from the node, what the type is...
269                                 if (node == null) {
270                                         print("node is empty - no return\n");
271                                         return ret; // no idea..
272                                 }
273                                 curtype = node.fqn();
274                                 cur_instance = true;
275                         }
276                         if (parts[0] == "Roo") {        
277                                 curtype = "Roo";
278                                 cur_instance = false;
279                         }
280                         
281                         var prevbits = parts[0] + ".";
282                         for(var i =1; i < parts.length; i++) {
283                                 print("matching %d/%d\n", i, parts.length);
284                                 var is_last = i == parts.length -1;
285                                 
286                                 // look up all the properties of the type...
287                                 var cls = this.getClass(curtype);
288                                 if (cls == null) {
289                                         print("could not get class of curtype %s\n", curtype);
290                                         return ret;
291                                 }
292
293                                 if (!is_last) {
294                                 
295                                         // only exact matches from here on...
296                                         if (cur_instance) {
297                                                 if (cls.props.has_key(parts[i])) {
298                                                         var prop = cls.props.get(parts[i]);
299                                                         if (prop.type.index_of(".",0) > -1) {
300                                                                 // type is another roo object..
301                                                                 curtype = prop.type;
302                                                                 prevbits += parts[i] + ".";
303                                                                 continue;
304                                                         }
305                                                         return ret;
306                                                 }
307                                                 // check methods?? - we do not export that at present..
308                                                 return ret;      //no idea...
309                                         }
310                                 
311                                         // not a instance..
312                                         //look for child classes.
313                                         var citer = this.classes.map_iterator();
314                                         var foundit = false;
315                                         while (citer.next()) {
316                                                 var scls = citer.get_key();
317                                                 var look = prevbits + parts[i];
318                                                 if (scls.index_of(look,0) != 0) {
319                                                         continue;
320                                                 }
321                                                 // got a starting match..
322                                                 curtype = look;
323                                                 cur_instance = false;
324                                                 foundit =true;
325                                                 break;
326                                         }
327                                         if (!foundit) {
328                                                 return ret;
329                                         }
330                                         prevbits += parts[i] + ".";
331                                         continue;
332                                 }
333                                 // got to the last element..
334                                 print("Got last element\n");
335                                 if (curtype == "") { // should not happen.. we would have returned already..
336                                         return ret;
337                                 }
338                                 print("Got last element type %s\n",curtype);
339                                 if (!cur_instance) {
340                                         print("matching instance");
341                                         // it's a static reference..
342                                         var citer = this.classes.map_iterator();
343                                         while (citer.next()) {
344                                                 var scls = citer.get_key();
345                                                 var look = prevbits + parts[i];
346                                                 if (parts[i].length > 0 && scls.index_of(look,0) != 0) {
347                                                         continue;
348                                                 }
349                                                 // got a starting match..
350                                                 ret.append(new SourceCompletionItem (
351                                                         scls,
352                                                         scls, 
353                                                         null, 
354                                                         scls));
355                                         }
356                                         return ret;
357                                 }
358                                 print("matching property");
359                                 
360                                 // get the properties / methods and subclasses.. of cls..
361                                 // we have cls.. - see if the string matches any of the properties..
362                                 var citer = cls.props.map_iterator();
363                                 while (citer.next()) {
364                                         var prop = citer.get_value();
365                                         // does the name start with ...
366                                         if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
367                                                 continue;
368                                         }
369                                         // got a matching property...
370                                         
371                                         ret.append(new SourceCompletionItem (
372                                                          prop.name + " : " + prop.type + " ("+ prop.propertyof + ")", 
373                                                         prevbits + prop.name, 
374                                                         null, 
375                                                         prop.doctxt));
376                                 }
377                                          
378                                         
379                                 return ret;     
380                                         
381                                         
382                                 
383                                         
384                                 
385                         }
386                         
387                          
388                         
389                         
390                         
391                         
392                         return ret;
393                 }
394     }
395 }
396