edb5e176942fffe94b7f434fca82b736a780eb6a
[roobuilder] / src / JsRender / NodeProp.vala
1 /**
2
3 This is a replacement for our key/value 
4 events and properties
5
6  
7 */ 
8 public enum JsRender.NodePropType 
9 {
10         
11         NONE, // fake value - used in popoveraddprop.
12         CTOR, // not used exetp getProperties for?
13         
14         
15         // these are all stored as properties, and should not overlap.
16         PROP,
17         
18         RAW,
19         METHOD,
20         SIGNAL,
21                 
22         // in theory we could have user defined properties that overlap - but probably not a good idea.
23         USER,
24
25
26         
27         // specials - these should be in a seperate list?
28         SPECIAL,
29
30
31         
32         // listerens can definatly overlap as they are stored in a seperate list. << no need to use this for listeners?
33         LISTENER;
34         
35
36         
37         public static string to_abbr(NodePropType intype)
38         {
39                 switch(intype) {
40                         case PROP: return  "";
41                         case RAW: return "$";
42                         case METHOD : return  "|";      
43                         case SIGNAL : return  "@"; // vala signal
44                         case USER : return  "#"; // user defined.
45                         case SPECIAL : return  "*"; // * prop| args | ctor | init
46                         case LISTENER : return  "";  // always raw...
47                         // not used
48                         case NONE:
49                         case CTOR:
50                                  return "";
51                         
52                 }
53                 return "??";
54         }
55         
56         // only usefull for reall values.
57         public static NodePropType from_string(string str)
58         {
59                 switch(str) {
60                         //case "" : return PROP;
61                         case "$": return  RAW;
62                         case "|": return METHOD;
63                         case "@": return  SIGNAL;
64                         case "#": return USER;
65                         case "*": return SPECIAL;
66                         //case "": return case LISTENER : return  ""  // always raw...
67                 }
68                 return PROP;
69         
70         }
71         public string to_name()
72         {
73                 switch (this) {
74                         case RAW:               return "Raw Property (not quoted or escaped)";
75                         case METHOD :   return "User Defined Method";   
76                         case SIGNAL :   return  "Vala Signal"; // vala signal
77                         case USER :     return  "User Defined Property"; // user defined.
78                         case SPECIAL : return  "Special Property (eg. prop / arg / ctor / init)"; // * prop| args | ctor | init
79                         case LISTENER : return  "Listener / Signal Handler";  // always raw...
80                         // not used
81                         case NONE:  return "None??";
82                         case CTOR:  return "Constructor?";
83                         case PROP:  return "Gtk/Roo Property";
84                         default: return "oops";
85                 
86                 }
87         }
88         
89         public static NodePropType[] alltypes()
90         {
91                 return {
92                         PROP,
93                         USER,
94                         RAW,                    
95                         METHOD,
96                         SIGNAL,
97
98                         SPECIAL,
99                         LISTENER
100                 //      CTOR,
101                         
102                 };
103         }
104         public static NodePropType nameToType(string str)
105         {
106                 foreach(var np in alltypes()) {
107                         if (np.to_name() == str) {
108                                 return np;
109                         }
110                 }
111                 return NONE;
112         
113         }
114         public static string[] get_pulldown_list()
115         {
116                 // eventually it needs to be smarter.... - but i did not have internet so could not use listmodels for the dropdown
117                  
118                 string[] ret = {};
119                 foreach(var np in alltypes()) {
120                         ret += np.to_name();
121                 }
122                 return ret;
123         
124         }
125         
126         
127 }
128
129
130
131 public class JsRender.NodeProp : Object {
132
133
134
135
136
137
138         private string _name = "";
139         public string name { 
140                 get {
141                         return this._name;  
142                 }
143                 set {
144                         if (this._name == value) {
145                                 return;
146                         }
147                         this._name = value;
148                  
149                         this.updated_count++;
150                         if (this.parent != null) {
151                                 // causes props/ listeners array to get updated.
152                                 this.parent.updated_count++;
153                         }
154                 }
155          }  // can not be updated... ?? you have to remove / replace?
156         private NodePropType  _ptype;
157          
158         public NodePropType  ptype {            
159                 get {
160                         return this._ptype;  
161                 }
162                 set {
163                         if (this._ptype == value) {
164                                 return;
165                         }
166                         this._ptype = value;
167                         if (this.parent != null) {
168                                 // causes props/ listeners array to get updated.
169                                 this.parent.updated_count++;
170                         }
171                 }
172         }
173         private string _rtype = "";
174         public string rtype { 
175                 get { 
176                         return this._rtype; 
177                 }
178                 set { 
179                         if (this._rtype == value) {
180                                 return;
181                         }
182                         this._rtype = value; 
183                         if (this.parent != null) {
184                                 this.parent.updated_count++;
185                         }
186                          
187                         this.updated_count++;
188                 }
189          } // return or type
190         
191         private string _val = "";
192         public string val { 
193                 get {
194                         return this._val;
195                 }
196                 set {
197                         if (this._val == value) {
198                                 return;
199                         }
200                         this._val = value;
201                         
202                         if (this.parent != null) {
203                                 this.parent.updated_count++;
204                         }
205                         this.updated_count++;
206                 }
207         }
208
209
210         private int _updated_count = 0;
211         public int updated_count { 
212                 get {
213                         return this._updated_count; 
214                 }
215                 set  {
216  
217                         // set things that are used to display values.
218                         this.to_display_name_prop = value.to_string();
219                         this.to_tooltip_name_prop = value.to_string();
220                                         
221                         this.val_short =  value.to_string();
222                         this.val_tooltip =  value.to_string();  
223                         this._updated_count = value;
224                 }
225  
226         } // changes to this trigger updates on the tree..
227         
228         public string sort_name {
229                 owned get {
230                         if (this.add_node == null) {
231                                 return this.name;
232                         }
233                         return this.name + " " + this.add_node.fqn();
234                 }
235                 set {}
236         
237         }
238         
239         
240         public Node? parent; // the parent node.
241
242         
243         public int start_line = 0;
244         public int end_line = 0;
245         
246         // used by display list..
247         public GLib.ListStore  childstore; // WILL BE USED FOR properties with mutliple types 
248         public Node? add_node = null; // used when we list potentional nodes for properties in add list.
249
250         public string propertyof { get;   set; }
251         
252         
253         public NodeProp(string name, NodePropType ptype, string rtype, string val) {
254                 this.name = name;
255                 this.ptype = ptype;
256                 this.rtype = rtype;
257                 this.val = val;
258                 this.childstore = new GLib.ListStore( typeof(NodeProp));
259                  
260         }
261         public string ptype_as_string {
262                 get { return this.ptype.to_string(); }
263                 private set {}
264         }
265         
266         
267         public bool equals(NodeProp p) 
268         {
269                 return this.name == p.name 
270                                 && 
271                                 this.ptype == p.ptype 
272                                 && 
273                                 this.rtype == p.rtype 
274                                 && 
275                                 this.val == p.val;
276         }
277         
278         public NodeProp dupe()
279         {
280                 return new NodeProp(this.name, this.ptype, this.rtype,  this.val);
281         }
282         
283         
284         public NodeProp.from_json(string key, string inval)
285         {
286                 this.val = inval;
287                 var kkv = key.strip().split(" ");
288                 string[] kk = {};
289                 for (var i = 0; i < kkv.length; i++) {
290                         if (kkv[i].length > 0 ) {
291                                 kk += kkv[i];
292                         }
293                 }
294                 
295                 switch(kk.length) {
296                         case 1: 
297                                 this.name = kk[0];
298                                 this.ptype = NodePropType.PROP;
299                                 this.rtype = "";                
300                                 return;
301                         case 2: 
302                                 this.name = kk[1];
303                                 if (kk[0].length > 1) {
304                                         // void fred (no type)
305                                         this.rtype = kk[0];
306                                         this.ptype = NodePropType.PROP;
307                                 } else {
308                                         // has a ptype.
309                                         
310                                         this.rtype = ""; // no return type, only a ptype indicator.
311                                         this.ptype = NodePropType.from_string(kk[0]);
312                                 }
313                                 return;
314                         default: // 3 or more... (ignores spaces..)
315                         case 3:
316                                 this.name =  kk[2];
317                                 this.ptype = NodePropType.from_string(kk[0]);
318                                 this.rtype = kk[1];
319                                 return;
320                         
321                 }
322                 
323         }
324         public string  to_json_key()
325         {
326                 
327                 if (this.rtype == null) { // not sure why this happens.!?
328                         this.rtype = "";
329                 }
330                 var ortype = this.rtype +  (this.rtype.length > 0 ? " " : "");
331                 var oabbr = NodePropType.to_abbr(this.ptype);
332                 if (oabbr.length > 0) {
333                         oabbr += " ";
334                 }
335                 switch(this.ptype) {
336                         
337
338                         case NodePropType.LISTENER : 
339                                 return this.name; 
340                                 
341                         case NodePropType.PROP:
342                                 return ortype + this.name;                      
343                         
344                         case NodePropType.RAW:
345                         case NodePropType.METHOD:
346                         case NodePropType.SIGNAL:                       
347                         case NodePropType.USER :                        
348                                 return oabbr + ortype + this.name;                      
349                                 
350
351
352                         case NodePropType.SPECIAL:                      
353                                 return oabbr +   this.name;
354                         case NodePropType.NONE: // not used
355                         case NodePropType.CTOR:
356                                  return "";
357                          
358                 }
359                 return this.name;
360         }
361          
362         
363         public string  to_index_key()
364         {
365                 switch(this.ptype) {
366                         case NodePropType.PROP:
367                         case NodePropType.RAW:
368                         case NodePropType.METHOD :
369                         case NodePropType.SIGNAL :
370                         case NodePropType.USER : 
371                                 return this.name;
372                         
373                         case NodePropType.SPECIAL : 
374                                 return "* " + this.name;
375                                 
376                         // in seperate list..
377                         case NodePropType.LISTENER : 
378                                 return  this.name;
379                                 
380                         case NodePropType.NONE: // not used
381                         case NodePropType.CTOR:
382                                  return "";
383
384                                 
385                 }
386                 return this.name;
387         
388         }
389         // how it appears on the property list. -
390         
391         
392  
393         public string val_short { 
394                 set {
395                         // NOOp ??? should 
396                 }
397                 owned get {
398                         
399                          if (this._val.index_of("\n") < 0) {
400                                 return this._val;
401                          }
402                          var vals = this._val.split("\n");
403                          return vals[0]  + (vals.length > 1 ? " ..." : "");
404                 } 
405         }
406  
407     public string val_tooltip { 
408         set {
409                         // NOOp ??? should 
410                 }
411                 owned get {
412                         
413                                 return "<tt>" + GLib.Markup.escape_text(this.val) + "</tt>";
414                 } 
415     
416     
417     }
418     
419     public string to_display_name_prop { 
420                 set {
421                         // NOOp ??? should 
422                 }
423                 owned get {
424                          return  this.to_display_name();
425                 } 
426         }
427         
428         
429     
430         public string to_display_name()
431         {
432                 
433                 //return (this.rtype.length > 0 ? this.rtype + " " : "") +  this.name;
434                 // before we showed "@" for signals
435                 switch(this.ptype) {
436                         case NodePropType.PROP:
437                                 return   GLib.Markup.escape_text(this.name);
438                                 
439                         case NodePropType.RAW:
440                                 return "<span style=\"italic\">" + GLib.Markup.escape_text(this.name) + "</span>";
441                                 
442                         case NodePropType.METHOD :
443                                 return "<i>" + GLib.Markup.escape_text(this.rtype)  + "</i> <span color=\"#008000\" font_weight=\"bold\">" + GLib.Markup.escape_text( this.name) + "</span>";
444                                 
445                         case NodePropType.SIGNAL : // purpley
446                                 return "<span   color=\"#ea00d6\" font_weight=\"bold\">" + GLib.Markup.escape_text(this.name)+ "</span>";
447                                 
448                         case NodePropType.USER : 
449                                 return  "<i>" + GLib.Markup.escape_text(this.rtype)  + "</i> <span  font_weight=\"bold\">" + GLib.Markup.escape_text(this.name) + "</span>";
450                         
451                         case NodePropType.SPECIAL : 
452                                 return "<span   color=\"#0000CC\" font_weight=\"bold\">" + GLib.Markup.escape_text(this.name) + "</span>";       
453                                 
454                         // in seperate list..
455                         case NodePropType.LISTENER : 
456                                 return  "<b>" + this.name + "</b>";
457                                 
458                         case NodePropType.NONE: // not used
459                         case NodePropType.CTOR:
460                                  return "";
461                 
462                                 
463                 }
464                 return this.name;
465         }
466         
467         public string to_tooltip_name_prop { 
468                 set {
469                         // NOOp ??? should 
470                 }
471                 owned get {
472                          return  this.to_tooltip_name();
473                 } 
474         }
475         
476         public string to_tooltip_name()
477         {
478                 
479                 //return (this.rtype.length > 0 ? this.rtype + " " : "") +  this.name;
480                 // before we showed "@" for signals
481                 switch(this.ptype) {
482                         case NodePropType.PROP:
483                         case NodePropType.SIGNAL:
484                         case NodePropType.RAW:
485                         case NodePropType.SPECIAL : 
486                         case NodePropType.LISTENER :
487                                 return GLib.Markup.escape_text(this.name) ;
488                                 
489                         case NodePropType.METHOD :
490                         case NodePropType.USER :                        
491                                 return  GLib.Markup.escape_text(this.rtype)  + " " + GLib.Markup.escape_text( this.name) ;
492                                 
493                         
494                                 
495                         case NodePropType.NONE: // not used
496                         case NodePropType.CTOR:
497                                  return "";
498                 
499                                 
500                 }
501                 return this.name;
502         }
503         // used ot sort the dispaly list of properties.
504         public string to_sort_key()
505         {
506                 var n = this.name;
507                  
508                 //return (this.rtype.length > 0 ? this.rtype + " " : "") +  this.name;
509                 // before we showed "@" for signals
510                 switch(this.ptype) {
511                         case NodePropType.PROP:
512                                 return "5" +  n;
513                                 
514                         case NodePropType.RAW:
515                                 return "5" +  n;
516                                 
517                         case NodePropType.METHOD :
518                                 return "2" +  n;
519                                 
520                         case NodePropType.SIGNAL :
521                                 return "3" +  n;
522                                 
523                         case NodePropType.USER : 
524                                 return "4" +  n;
525                         
526                         case NodePropType.SPECIAL : 
527                                 return "1" +  n;
528                                 
529                         // in seperate list..
530                         case NodePropType.LISTENER : 
531                                 return  "0" + this.name;
532                         
533                         case NodePropType.NONE: // not used
534                         case NodePropType.CTOR:
535                                  return "";
536                                 
537                 }
538                 return this.name;
539         }
540         // this is really only used for stuct ctors at present  
541         // which are only props (although RAW might be valid)
542         public string value_to_code()
543         {
544                 switch (this.ptype) {
545                         case NodePropType.PROP:
546                                 break;
547                                 
548                         case NodePropType.METHOD :                       
549                         case NodePropType.RAW:
550                         case NodePropType.SIGNAL :                      
551                         case NodePropType.USER : 
552                         case NodePropType.SPECIAL : 
553                         case NodePropType.LISTENER : 
554                         case NodePropType.NONE: // not used
555                         case NodePropType.CTOR:                 
556                                 return this.val;
557                 }
558                 if (this.rtype.contains(".")) {
559                         // probalby an enum
560                         return this.val;
561                 }
562                 
563                 
564                 switch (this.rtype) {
565                         case "string":
566                                 return "\"" + this.rtype.escape() + "\"";
567                         case "bool":
568                                 return this.val.down();
569                         case "float":
570                         case "double":
571                         default:
572                                 break;
573                                 
574                         
575                 
576                 }
577                 return this.val;
578         }
579         
580         
581         
582         public string to_tooltip()
583         {
584                  
585                 switch(this.ptype) {
586                         case NodePropType.PROP:
587                                 return this.rtype + " " + this.name + " = \"" + this.val + "\"";
588                         case NodePropType.LISTENER : 
589                                 // thsi might look a bit odd on javascript?
590                                 return "on " + this.name + " " + this.val;
591                                 
592                         case NodePropType.RAW:
593                                 return  this.rtype + " " + this.name + " = " + this.val;
594                         case NodePropType.METHOD :
595                                 // functions - js    FRED  function () { }  <<< could probably be cleaner..
596                                 // functions - vala    FRED () { }
597                                 return  this.rtype + " " + this.name  + " "  + this.val;
598                         case NodePropType.SIGNAL :
599                                 return  "signal: "  + this.rtype + " " + this.name  +  " " + this.val;
600                         case NodePropType.USER : 
601                                 return  "user defined: "  + this.rtype + " " + this.name  + " = "  + this.val;
602                         
603                         case NodePropType.SPECIAL:                      
604                                 return  "special property: "  + this.rtype + " " + this.name  + " = " +   this.val;                     
605
606                         case NodePropType.NONE: // not used
607                         case NodePropType.CTOR:
608                                  return "";
609                 }
610                 return this.name;
611                  
612         }
613         
614          
615         public string to_property_option_markup(bool isbold)
616         {
617                 return isbold ?  "<b>" + this.name + "</b>" : this.name;
618         }
619         
620         public string to_property_option_tooltip()
621         {
622                 return this.to_property_option_markup( false ); // fixme will probaly want help info (possibly by havinga  reference to the GirObject that its created from
623         }
624         
625         
626         public bool is(NodeProp comp) {
627                 if (comp.ptype == NodePropType.LISTENER || this.ptype == NodePropType.LISTENER ) { 
628                         return comp.ptype == this.ptype && comp.name == this.name;
629                 }
630                 return comp.to_index_key() == this.to_index_key();
631         
632         }
633         
634         
635         /*
636         public NodeProp.listenerfromjson(string str, string inval)
637         {
638                 this.val = inval;
639                 this.name = str;
640                 this.ptype = NodePropType.LISTENER;
641                 this.rtype = "";
642                 
643         }
644         */
645         // regular addition - should work for properties  
646         public NodeProp.prop(string name, string rtype = "", string val = "")
647         {
648                 this(name, NodePropType.PROP, rtype, val);
649         }
650         public NodeProp.raw(string name, string rtype = "", string val = "")
651         {
652                 this(name, NodePropType.RAW, rtype, val);
653         }
654         
655         public NodeProp.valamethod(string name, string rtype = "void", string val = "() {\n\n}")
656         {
657                 this(name, NodePropType.METHOD, rtype, val);
658         }
659         public NodeProp.jsmethod(string name,  string val = "function() {\n\n}")
660         {
661                 this(name, NodePropType.METHOD, "", val);
662         }
663         
664         // vala (and js) specials.. props etc.. - they only have name/value (not type) - type is in xns/xtype
665         public NodeProp.special(string name, string val = "")
666         {
667                 this(name, NodePropType.SPECIAL, "", val);
668         }
669          
670         public NodeProp.listener(string name,   string val = "")
671         {
672                 this(name, NodePropType.LISTENER, "", val);
673         }
674          
675         public NodeProp.user(string name, string rtype = "", string val = "")
676         {
677                 this(name, NodePropType.USER, rtype, val);
678         }
679         public NodeProp.sig(string name, string rtype = "void", string val = "()")
680         {
681                 this(name, NodePropType.SIGNAL, rtype, val);
682         }
683         public void appendChild(NodeProp child)
684         {
685                 this.childstore.append(child);
686
687         }
688          
689         
690         /**
691         could use enums.. but basically.
692         0 - > inline text editor
693         1  -> pulldown
694         2  -> full editor
695         */
696         public bool useTextArea()
697         {
698         
699                 var use_textarea = false;
700
701                 //------------ things that require the text editor...
702                 
703                 if (this.ptype == NodePropType.LISTENER) {
704                     use_textarea = true;
705                 }
706                 if (this.ptype == NodePropType.METHOD) { 
707                     use_textarea = true;
708                 }
709                     
710                 if ( this.name == "init" && this.ptype == NodePropType.SPECIAL) {
711                     use_textarea = true;
712                 }
713                 if (this.val.length > 40 || this.val.index_of("\n") > -1) { // long value...
714                     use_textarea = true;
715                 }
716                 
717                 return use_textarea;
718         
719         }
720         
721         
722         
723         
724 }
725         
726