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