src/Palete/Palete.vala
[app.Builder.js] / src / Palete / Roo.vala
index 1fbdb44..37d2d99 100644 (file)
@@ -1,3 +1,5 @@
+using Gtk;
+
 namespace Palete {
 
        
@@ -31,153 +33,388 @@ namespace Palete {
                          
         }
 
-       Gee.HashMap<string,GirObject> propsFromJSONArray(string type, Json.Array ar)
-       {
+               Gee.HashMap<string,GirObject> propsFromJSONArray(string type, Json.Array ar, GirObject cls)
+               {
 
-               var ret = new Gee.HashMap<string,GirObject>();
-               
-               for (var i =0 ; i < ar.get_length(); i++) {
-                       var o = ar.get_object_element(i);
-                       var name = o.get_string_member("name"); 
-                       var prop = new GirObject(type, name );  
-                    
-                       prop.type        = o.get_string_member("type");
-                       prop.doctxt  = o.get_string_member("desc");
-                       prop.propertyof = o.has_member("memberOf") ? o.get_string_member("memberOf") : "";
-                       prop.sig = o.has_member("sig") ? o.get_string_member("sig") : "";
-                       //print(type + ":" + name +"\n");
-                       ret.set(name,prop);
+                       var ret = new Gee.HashMap<string,GirObject>();
+                       
+                       for (var i =0 ; i < ar.get_length(); i++) {
+                               var o = ar.get_object_element(i);
+                               var name = o.get_string_member("name"); 
+                               var prop = new GirObject(type, name );  
+                                
+                               prop.type        = o.get_string_member("type");
+                               prop.doctxt  = o.get_string_member("desc");
+                               prop.propertyof = o.has_member("memberOf") ? o.get_string_member("memberOf") : "";
+                               if (prop.propertyof.length < 1)  {
+                                       prop.propertyof = cls.name;
+                               }
+                               prop.sig = o.has_member("sig") ? o.get_string_member("sig") : "";
+                               
+                               if (o.has_member("optvals")  ) {
+                                       var oar = o.get_array_member("optvals");
+                                       
+                                       for (var oi = 0; oi < oar.get_length(); oi++) {
+                                               prop.optvalues.add(oar.get_string_element(oi));
+                                       }
+                                       
+                               }       
+                               
+                               
+                               
+                               //print(type + ":" + name +"\n");
+                               ret.set(name,prop);
+                       }
+                       return ret;
                }
-               return ret;
-       }
-        Gee.HashMap<string,GirObject> classes; 
-        public override void  load () {
+        
+               public override void  load () {
 
-               if (this.classes != null) {
-                       return;
-               }
-               this.loadUsageFile(BuilderApplication.configDirectory() + "/resources/RooUsage.txt");
-               this.classes = new Gee.HashMap<string,GirObject>();
+                       if (this.classes != null) {
+                               return;
+                       }
+                       this.loadUsageFile(BuilderApplication.configDirectory() + "/resources/RooUsage.txt");
+                       this.classes = new Gee.HashMap<string,GirObject>();
 
-            
-               var pa = new Json.Parser();
-               pa.load_from_file(BuilderApplication.configDirectory() + "/resources/roodata.json");
-               var node = pa.get_root();
+                               
+                       var pa = new Json.Parser();
+                       pa.load_from_file(BuilderApplication.configDirectory() + "/resources/roodata.json");
+                       var node = pa.get_root();
 
-               var clist =  node.get_object().get_object_member("data");
-               clist.foreach_member((o , key, value) => {
-                       //print("cls:" + key+"\n");
-                
-                       var cls = new GirObject("class", key);  
-                       cls.props = this.propsFromJSONArray("prop", value.get_object().get_array_member("props"));
-                       cls.signals = this.propsFromJSONArray("signal", value.get_object().get_array_member("events"));
-                       this.classes.set(key, cls);
-               });
+                       var clist =  node.get_object().get_object_member("data");
+                               clist.foreach_member((o , key, value) => {
+                               //print("cls:" + key+"\n");
+                        
+                               var cls = new GirObject("class", key);  
+                               cls.props = this.propsFromJSONArray("prop", value.get_object().get_array_member("props"),cls);
+                               cls.signals = this.propsFromJSONArray("signal", value.get_object().get_array_member("events"),cls);
+                               if (value.get_object().has_member("methods")) {
+                                       cls.methods = this.propsFromJSONArray("method", value.get_object().get_array_member("methods"),cls);
+                               }
+                               
+                               this.classes.set(key, cls);
+                       });
+                               
+                               
                        
-               
-               
-             
-        }
-         
-        
-        public string doc(string what) {
-               return "";
-               /*var ns = what.split(".")[0];
+                                
+               }
+                 
+                       
+               public string doc(string what) {
+                       return "";
+                       /*var ns = what.split(".")[0];
 
 
-               
-               
-            var gir =  Gir.factory(ns);
-                       return   gir.doc(what);
-                       */
                        
-            //return typeof(this.comments[ns][what]) == 'undefined' ?  '' : this.comments[ns][what];
-        }
+                       
+                               var gir =  Gir.factory(ns);
+                               return   gir.doc(what);
+                               */
+                               
+                       //return typeof(this.comments[ns][what]) == 'undefined' ?  '' : this.comments[ns][what];
+               }
 
                // does not handle implements...
-       public override GirObject? getClass(string ename)
-       {
-               this.load();
-               return this.classes.get(ename);
-               
-       }
-           
-        public override Gee.HashMap<string,GirObject> getPropertiesFor(string ename, string type)
-        {
-                   //print("Loading for " + ename);
-                   
-
-               this.load();
-                               // if (typeof(this.proplist[ename]) != 'undefined') {
-                       //print("using cache");
-                    //   return this.proplist[ename][type];
-                   //}
-                   // use introspection to get lists..
-        
-               
-               var cls = this.classes.get(ename);
-               var ret = new Gee.HashMap<string,GirObject>();
-               if (cls == null) {
-                       print("could not find class: %s\n", ename);
-                       return ret;
-                       //throw new Error.INVALID_VALUE( "Could not find class: " + ename);
-       
+               public override GirObject? getClass(string ename)
+               {
+                       this.load();
+                       return this.classes.get(ename);
+                       
                }
-
-               //cls.parseProps();
-               //cls.parseSignals(); // ?? needed for add handler..
-               //cls.parseMethods(); // ?? needed for ??..
-               //cls.parseConstructors(); // ?? needed for ??..
-
-               //cls.overlayParent();
-
-               switch  (type) {
+               
+               public override Gee.HashMap<string,GirObject> getPropertiesFor(string ename, string type)
+               {
+                       //print("Loading for " + ename);
                        
+
+                       this.load();
+                                       // if (typeof(this.proplist[ename]) != 'undefined') {
+                                       //print("using cache");
+                                //   return this.proplist[ename][type];
+                               //}
+                               // use introspection to get lists..
+                
                        
-                       case "props":
-                               return cls.props;
-                       case "signals":
-                               return cls.signals;
-                       case "methods":
-                               return ret;
-                       case "ctors":
+                       var cls = this.classes.get(ename);
+                       var ret = new Gee.HashMap<string,GirObject>();
+                       if (cls == null) {
+                               print("could not find class: %s\n", ename);
                                return ret;
-                       default:
-                               throw new Error.INVALID_VALUE( "getPropertiesFor called with: " + type);
-                               //var ret = new Gee.HashMap<string,GirObject>();
-                               //return ret;
+                               //throw new Error.INVALID_VALUE( "Could not find class: " + ename);
                
-               }
+                       }
+
+                       //cls.parseProps();
+                       //cls.parseSignals(); // ?? needed for add handler..
+                       //cls.parseMethods(); // ?? needed for ??..
+                       //cls.parseConstructors(); // ?? needed for ??..
+
+                       //cls.overlayParent();
+
+                       switch  (type) {
+                               
+                               
+                               case "props":
+                                       return cls.props;
+                               case "signals":
+                                       return cls.signals;
+                               case "methods":
+                                       return ret;
+                               case "ctors":
+                                       return ret;
+                               default:
+                                       throw new Error.INVALID_VALUE( "getPropertiesFor called with: " + type);
+                                       //var ret = new Gee.HashMap<string,GirObject>();
+                                       //return ret;
+                       
+                       }
                
        
                //cls.overlayInterfaces(gir);
 
 
-             
-        }
-       public string[] getInheritsFor(string ename)
-       {
-               string[] ret = {};
-               var es = ename.split(".");
-               var gir = Gir.factory(es[0]);
-               
-               var cls = gir.classes.get(es[1]);
-               if (cls == null) {
-                       return ret;
+                        
                }
-               return cls.inheritsToStringArray();
-               
+               public string[] getInheritsFor(string ename)
+               {
+                       string[] ret = {};
+                       var es = ename.split(".");
+                       var gir = Gir.factory(es[0]);
+                       
+                       var cls = gir.classes.get(es[1]);
+                       if (cls == null) {
+                               return ret;
+                       }
+                       return cls.inheritsToStringArray();
+                       
 
-       }
+               }
 
 
-       public override void fillPack(JsRender.Node node,JsRender.Node parent)
-       {   
+               public override void fillPack(JsRender.Node node,JsRender.Node parent)
+               {   
 
-                return;
-       }
-       
+                        return;
+               }
+               /*
+                *  Pulldown options for type
+                */
+               public override bool typeOptions(string fqn, string key, string type, out string[] opts) 
+               {
+                       opts = {};
+                       print("get typeOptions %s (%s)%s", fqn, type, key);
+                       if (type.up() == "BOOL" || type.up() == "BOOLEAN") {
+                               opts = { "true", "false" };
+                               return true;
+                        }
+                        
+                        var props = this.getPropertiesFor(fqn, "props");
+                        if (!props.has_key(key)) {
+                                print("prop %s does not have key %s\n", fqn, key);
+                                return false;
+                        }
+                        var pr = props.get(key);
+                        if (pr.optvalues.size < 1) {
+                                print("prop %s no optvalues for %s\n", fqn, key);
+                                return false;
+                        }
+                        string[] ret = {};
+                        for(var i = 0; i < pr.optvalues.size; i++) {
+                                ret += pr.optvalues.get(i);
+                        }
+                        opts = ret;
+                        print("prop %s returning optvalues for %s\n", fqn, key);
+                        return true;
+                        
+               }
+               public override  List<SourceCompletionItem> suggestComplete(
+                               JsRender.JsRender file,
+                               JsRender.Node? node,
+                               string proptype, 
+                               string key,
+                               string complete_string
+               ) { 
+                       
+                       var ret =  new List<SourceCompletionItem>();
+                       // completion rules??
+                       
+                       // Roo......
+                       
+                       // this. (based on the node type)
+                       // this.xxx // Node and any determination...
+                       
+                       if (complete_string.index_of(".",0) < 0) {
+                               // string does not have a '.'
+                               // offer up this / Roo / javascript keywords... / look for var string = .. in the code..
+                               for(var i = 0; i <  JsRender.Lang.match_strings.size ; i++) {
+                                       var str = JsRender.Lang.match_strings.get(i);
+                                       if (complete_string != str && str.index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
+                                               ret.append(new SourceCompletionItem (str, str, null, "javascript : " + str));
+                                       }
+                                       
+                                       
+                               }
+                               if (complete_string != "Roo" && "Roo".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
+                                       ret.append(new SourceCompletionItem ("Roo - A Roo class", "Roo", null, "Roo library"));
+                               }
+                               if (complete_string != "_this" && "_this".index_of(complete_string,0) == 0 ) { // should we ignore exact matches... ???
+                                       ret.append(new SourceCompletionItem ("_this - the top level element", "_this", null, "Top level element"));
+                               }
+                               return ret;
+                       }
+                       // got at least one ".".
+                       var parts = complete_string.split(".");
+                       var curtype = "";
+                       var cur_instance = false;
+                       if (parts[0] == "this") {
+                               // work out from the node, what the type is...
+                               if (node == null) {
+                                       print("node is empty - no return\n");
+                                       return ret; // no idea..
+                               }
+                               curtype = node.fqn();
+                               cur_instance = true;
+                       }
+                       if (parts[0] == "Roo") {        
+                               curtype = "Roo";
+                               cur_instance = false;
+                       }
+                       
+                       var prevbits = parts[0] + ".";
+                       for(var i =1; i < parts.length; i++) {
+                               print("matching %d/%d\n", i, parts.length);
+                               var is_last = i == parts.length -1;
+                               
+                               // look up all the properties of the type...
+                               var cls = this.getClass(curtype);
+                               if (cls == null) {
+                                       print("could not get class of curtype %s\n", curtype);
+                                       return ret;
+                               }
+
+                               if (!is_last) {
+                               
+                                       // only exact matches from here on...
+                                       if (cur_instance) {
+                                               if (cls.props.has_key(parts[i])) {
+                                                       var prop = cls.props.get(parts[i]);
+                                                       if (prop.type.index_of(".",0) > -1) {
+                                                               // type is another roo object..
+                                                               curtype = prop.type;
+                                                               prevbits += parts[i] + ".";
+                                                               continue;
+                                                       }
+                                                       return ret;
+                                               }
+                                               
+                                               
+                                               
+                                               // check methods?? - we do not export that at present..
+                                               return ret;      //no idea...
+                                       }
+                               
+                                       // not a instance..
+                                       //look for child classes.
+                                       var citer = this.classes.map_iterator();
+                                       var foundit = false;
+                                       while (citer.next()) {
+                                               var scls = citer.get_key();
+                                               var look = prevbits + parts[i];
+                                               if (scls.index_of(look,0) != 0) {
+                                                       continue;
+                                               }
+                                               // got a starting match..
+                                               curtype = look;
+                                               cur_instance = false;
+                                               foundit =true;
+                                               break;
+                                       }
+                                       if (!foundit) {
+                                               return ret;
+                                       }
+                                       prevbits += parts[i] + ".";
+                                       continue;
+                               }
+                               // got to the last element..
+                               print("Got last element\n");
+                               if (curtype == "") { // should not happen.. we would have returned already..
+                                       return ret;
+                               }
+                               print("Got last element type %s\n",curtype);
+                               if (!cur_instance) {
+                                       print("matching instance");
+                                       // it's a static reference..
+                                       var citer = this.classes.map_iterator();
+                                       while (citer.next()) {
+                                               var scls = citer.get_key();
+                                               var look = prevbits + parts[i];
+                                               if (parts[i].length > 0 && scls.index_of(look,0) != 0) {
+                                                       continue;
+                                               }
+                                               // got a starting match..
+                                               ret.append(new SourceCompletionItem (
+                                                       scls,
+                                                       scls, 
+                                                       null, 
+                                                       scls));
+                                       }
+                                       return ret;
+                               }
+                               print("matching property");
+                               
+                               
+                               
+                               var citer = cls.methods.map_iterator();
+                               while (citer.next()) {
+                                       var prop = citer.get_value();
+                                       // does the name start with ...
+                                       if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
+                                               continue;
+                                       }
+                                       // got a matching property...
+                                       // return type?
+                                       ret.append(new SourceCompletionItem (
+                                                        prop.name + prop.sig + " :  ("+ prop.propertyof + ")", 
+                                                       prevbits + prop.name + "(", 
+                                                       null, 
+                                                       prop.doctxt));
+                               }
+                               
+                               // get the properties / methods and subclasses.. of cls..
+                               // we have cls.. - see if the string matches any of the properties..
+                               citer = cls.props.map_iterator();
+                               while (citer.next()) {
+                                       var prop = citer.get_value();
+                                       // does the name start with ...
+                                       if (parts[i].length > 0 && prop.name.index_of(parts[i],0) != 0) {
+                                               continue;
+                                       }
+                                       // got a matching property...
+                                       
+                                       ret.append(new SourceCompletionItem (
+                                                        prop.name + " : " + prop.type + " ("+ prop.propertyof + ")", 
+                                                       prevbits + prop.name, 
+                                                       null, 
+                                                       prop.doctxt));
+                               }
+                                        
+                                       
+                               return ret;     
+                                       
+                                       
+                               
+                                       
+                               
+                       }
+                       
+                        
+                       
+                       
+                       
+                       
+                       return ret;
+               }
     }
 }