fix segfault on empty prop key value
[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         
72 }
73
74
75
76 public class JsRender.NodeProp : Object {
77
78
79
80         public string name  = "";
81         public NodePropType ptype;  
82         public string rtype = ""; // return or type
83         public string val = "";
84         public int start_line = 0;
85         public int end_line = 0;
86         
87         
88         
89         public NodeProp(string name, NodePropType ptype, string rtype, string val) {
90                 this.name = name;
91                 this.ptype = ptype;
92                 this.rtype = rtype;
93                 this.val = val;
94         }
95         
96         public NodeProp dupe()
97         {
98                 return new NodeProp(this.name, this.ptype, this.rtype,  this.val);
99         }
100         
101         
102         public NodeProp.from_json(string key, string inval)
103         {
104                 this.val = inval;
105                 var kkv = key.strip().split(" ");
106                 string[] kk = {};
107                 for (var i = 0; i < kkv.length; i++) {
108                         if (kkv[i].length > 0 ) {
109                                 kk += kkv[i];
110                         }
111                 }
112                 
113                 switch(kk.length) {
114                         case 1: 
115                                 this.name = kk[0];
116                                 this.ptype = NodePropType.PROP;
117                                 this.rtype = "";                
118                                 return;
119                         case 2: 
120                                 this.name = kk[1];
121                                 if (kk[0].length > 1) {
122                                         // void fred (no type)
123                                         this.rtype = kk[0];
124                                         this.ptype = NodePropType.PROP;
125                                 } else {
126                                         // has a ptype.
127                                         
128                                         this.rtype = ""; // no return type, only a ptype indicator.
129                                         this.ptype = NodePropType.from_string(kk[0]);
130                                 }
131                                 return;
132                         default: // 3 or more... (ignores spaces..)
133                         case 3:
134                                 this.name =  kk[2];
135                                 this.ptype = NodePropType.from_string(kk[0]);
136                                 this.rtype = kk[1];
137                                 return;
138                         
139                 }
140                 
141         }
142         public string  to_json_key()
143         {
144                 
145                 if (this.rtype == null) { // not sure why this happens.!?
146                         this.rtype = "";
147                 }
148                 var ortype = this.rtype +  (this.rtype.length > 0 ? " " : "");
149                 var oabbr = NodePropType.to_abbr(this.ptype);
150                 if (oabbr.length > 0) {
151                         oabbr += " ";
152                 }
153                 switch(this.ptype) {
154                         
155
156                         case NodePropType.LISTENER : 
157                                 return this.name; 
158                                 
159                         case NodePropType.PROP:
160                                 return ortype + this.name;                      
161                         
162                         case NodePropType.RAW:
163                         case NodePropType.METHOD:
164                         case NodePropType.SIGNAL:                       
165                         case NodePropType.USER :                        
166                                 return oabbr + ortype + this.name;                      
167                                 
168
169
170                         case NodePropType.SPECIAL:                      
171                                 return oabbr +   this.name;
172                         case NodePropType.NONE: // not used
173                         case NodePropType.CTOR:
174                                  return "";
175                          
176                 }
177                 return this.name;
178         }
179          
180         
181         public string  to_index_key()
182         {
183                 switch(this.ptype) {
184                         case NodePropType.PROP:
185                         case NodePropType.RAW:
186                         case NodePropType.METHOD :
187                         case NodePropType.SIGNAL :
188                         case NodePropType.USER : 
189                                 return this.name;
190                         
191                         case NodePropType.SPECIAL : 
192                                 return "* " + this.name;
193                                 
194                         // in seperate list..
195                         case NodePropType.LISTENER : 
196                                 return  this.name;
197                                 
198                         case NodePropType.NONE: // not used
199                         case NodePropType.CTOR:
200                                  return "";
201
202                                 
203                 }
204                 return this.name;
205         
206         }
207         // how it appears on the property list. -- 
208         public string to_display_name()
209         {
210                 
211                 //return (this.rtype.length > 0 ? this.rtype + " " : "") +  this.name;
212                 // before we showed "@" for signals
213                 switch(this.ptype) {
214                         case NodePropType.PROP:
215                                 return  this.name;
216                                 
217                         case NodePropType.RAW:
218                                 return "<span style=\"italic\">" + GLib.Markup.escape_text(this.name) + "</span>";
219                                 
220                         case NodePropType.METHOD :
221                                 return "<i>" + GLib.Markup.escape_text(this.rtype)  + "</i> <span color=\"#008000\" font_weight=\"bold\">" + GLib.Markup.escape_text( this.name) + "</span>";
222                                 
223                         case NodePropType.SIGNAL : // purpley
224                                 return "<span   color=\"#ea00d6\" font_weight=\"bold\">" + GLib.Markup.escape_text(this.name)+ "</span>";
225                                 
226                         case NodePropType.USER : 
227                                 return  "<i>" + GLib.Markup.escape_text(this.rtype)  + "</i> <span  font_weight=\"bold\">" + GLib.Markup.escape_text(this.name) + "</span>";
228                         
229                         case NodePropType.SPECIAL : 
230                                 return "<span   color=\"#0000CC\" font_weight=\"bold\">" + GLib.Markup.escape_text(this.name) + "</span>";       
231                                 
232                         // in seperate list..
233                         case NodePropType.LISTENER : 
234                                 return  "<b>" + this.name + "</b>";
235                                 
236                         case NodePropType.NONE: // not used
237                         case NodePropType.CTOR:
238                                  return "";
239                 
240                                 
241                 }
242                 return this.name;
243         }
244         
245         // used ot sort the dispaly list of properties.
246         public string to_sort_key()
247         {
248                 var n = this.name;
249                  
250                 //return (this.rtype.length > 0 ? this.rtype + " " : "") +  this.name;
251                 // before we showed "@" for signals
252                 switch(this.ptype) {
253                         case NodePropType.PROP:
254                                 return "5" +  n;
255                                 
256                         case NodePropType.RAW:
257                                 return "5" +  n;
258                                 
259                         case NodePropType.METHOD :
260                                 return "2" +  n;
261                                 
262                         case NodePropType.SIGNAL :
263                                 return "3" +  n;
264                                 
265                         case NodePropType.USER : 
266                                 return "4" +  n;
267                         
268                         case NodePropType.SPECIAL : 
269                                 return "1" +  n;
270                                 
271                         // in seperate list..
272                         case NodePropType.LISTENER : 
273                                 return  "0" + this.name;
274                         
275                         case NodePropType.NONE: // not used
276                         case NodePropType.CTOR:
277                                  return "";
278                                 
279                 }
280                 return this.name;
281         }
282         // this is really only used for stuct ctors at present  
283         // which are only props (although RAW might be valid)
284         public string value_to_code()
285         {
286                 switch (this.ptype) {
287                         case NodePropType.PROP:
288                                 break;
289                                 
290                         case NodePropType.METHOD :                       
291                         case NodePropType.RAW:
292                         case NodePropType.SIGNAL :                      
293                         case NodePropType.USER : 
294                         case NodePropType.SPECIAL : 
295                         case NodePropType.LISTENER : 
296                         case NodePropType.NONE: // not used
297                         case NodePropType.CTOR:                 
298                                 return this.val;
299                 }
300                 if (this.rtype.contains(".")) {
301                         // probalby an enum
302                         return this.val;
303                 }
304                 
305                 
306                 switch (this.rtype) {
307                         case "string":
308                                 return "\"" + this.rtype.escape() + "\"";
309                         case "bool":
310                                 return this.val.down();
311                         case "float":
312                         case "double":
313                         default:
314                                 return this.val;
315                                 
316                         
317                 
318                 }
319                 return this.val;
320         }
321         
322         
323         
324         public string to_tooltip()
325         {
326                  
327                 switch(this.ptype) {
328                         case NodePropType.PROP:
329                                 return this.rtype + " " + this.name + " = \"" + this.val + "\"";
330                         case NodePropType.LISTENER : 
331                                 // thsi might look a bit odd on javascript?
332                                 return "on " + this.name + " " + this.val;
333                                 
334                         case NodePropType.RAW:
335                                 return  this.rtype + " " + this.name + " = " + this.val;
336                         case NodePropType.METHOD :
337                                 // functions - js    FRED  function () { }  <<< could probably be cleaner..
338                                 // functions - vala    FRED () { }
339                                 return  this.rtype + " " + this.name  + " "  + this.val;
340                         case NodePropType.SIGNAL :
341                                 return  "signal: "  + this.rtype + " " + this.name  +  " " + this.val;
342                         case NodePropType.USER : 
343                                 return  "user defined: "  + this.rtype + " " + this.name  + " = "  + this.val;
344                         
345                         case NodePropType.SPECIAL:                      
346                                 return  "special property: "  + this.rtype + " " + this.name  + " = " +   this.val;                     
347
348                         case NodePropType.NONE: // not used
349                         case NodePropType.CTOR:
350                                  return "";
351                 }
352                 return this.name;
353                  
354         }
355         
356          
357         public string to_property_option_markup(bool isbold)
358         {
359                 return isbold ?  "<b>" + this.name + "</b>" : this.name;
360         }
361         
362         public string to_property_option_tooltip()
363         {
364                 return this.to_property_option_markup( false ); // fixme will probaly want help info (possibly by havinga  reference to the GirObject that its created from
365         }
366         
367         
368         public bool is(NodeProp comp) {
369                 if (comp.ptype == NodePropType.LISTENER || this.ptype == NodePropType.LISTENER ) { 
370                         return comp.ptype == this.ptype && comp.name == this.name;
371                 }
372                 return comp.to_index_key() == this.to_index_key();
373         
374         }
375         
376         
377         /*
378         public NodeProp.listenerfromjson(string str, string inval)
379         {
380                 this.val = inval;
381                 this.name = str;
382                 this.ptype = NodePropType.LISTENER;
383                 this.rtype = "";
384                 
385         }
386         */
387         // regular addition - should work for properties  
388         public NodeProp.prop(string name, string rtype = "", string val = "")
389         {
390                 this(name, NodePropType.PROP, rtype, val);
391         }
392         public NodeProp.raw(string name, string rtype = "", string val = "")
393         {
394                 this(name, NodePropType.RAW, rtype, val);
395         }
396         
397         public NodeProp.valamethod(string name, string rtype = "void", string val = "() {\n\n}")
398         {
399                 this(name, NodePropType.METHOD, rtype, val);
400         }
401         public NodeProp.jsmethod(string name,  string val = "function() {\n\n}")
402         {
403                 this(name, NodePropType.METHOD, "", val);
404         }
405         
406         // vala (and js) specials.. props etc.. - they only have name/value (not type) - type is in xns/xtype
407         public NodeProp.special(string name, string val = "")
408         {
409                 this(name, NodePropType.SPECIAL, "", val);
410         }
411          
412         public NodeProp.listener(string name,   string val = "")
413         {
414                 this(name, NodePropType.LISTENER, "", val);
415         }
416          
417         public NodeProp.user(string name, string rtype = "", string val = "")
418         {
419                 this(name, NodePropType.USER, rtype, val);
420         }
421         public NodeProp.sig(string name, string rtype = "void", string val = "()")
422         {
423                 this(name, NodePropType.SIGNAL, rtype, val);
424         }
425         
426 }
427