Builder/LeftPanel.js
[app.Builder.js] / Builder / LeftPanel.js
1 //<Script type="text/javascript">
2 Gio = imports.gi.Gio;
3 Gtk = imports.gi.Gtk;
4 Gdk = imports.gi.Gdk;
5 GLib = imports.gi.GLib;
6 GObject = imports.gi.GObject;
7 Pango = imports.gi.Pango ;
8
9 XObject = imports.XObject.XObject;
10 console = imports.console;
11
12
13 LeftPanelPopup  = imports.Builder.LeftPanelPopup.LeftPanelPopup;
14 RightEditor     = imports.Builder.RightEditor.RightEditor;
15 /**
16  * 
17  * really the properties..
18  */
19
20
21 LeftPanel = new XObject({
22         
23         xtype: Gtk.ScrolledWindow,
24         smooth_scroll : true,
25         pack : [ 'pack_end', true, true, 0 ],
26         shadow_type : Gtk.ShadowType.IN,
27         
28         editing : false,
29         
30         init : function () {
31             XObject.prototype.init.call(this); 
32             this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
33         },
34         
35           
36     
37         
38         items : [
39             {
40                 id : 'view',
41                 
42                 xtype : Gtk.TreeView,
43                 
44                 tooltip_column : 1,
45                 headers_visible :   false ,
46                 enable_tree_lines :  true ,
47                      
48                 init : function () {
49                     XObject.prototype.init.call(this); 
50                        
51                     this.selection = this.el.get_selection();
52                     this.selection.set_mode( Gtk.SelectionMode.SINGLE);
53                  
54                     
55                     var description = new Pango.FontDescription.c_new();
56                     description.set_size(8000);
57                     this.el.modify_font(description);
58                 },     
59                 listeners : {
60                     
61                   
62                     'button-press-event' : function(tv, ev) {
63                         
64                         
65                         
66                         
67                         var res = { }; 
68                         if (!this.el.get_path_at_pos(ev.button.x,ev.button.y, res)) {
69                             return false; //not on a element.
70                         }
71                         
72                         
73                         if (ev.type != Gdk.EventType.BUTTON_PRESS  || ev.button.button != 3) {
74                             
75                             if (res.column.title != 'value') {
76                                 return false; // ignore..
77                             }
78                             if (  LeftPanel.editing) {
79                                 return false;
80                             }
81                             var renderer = LeftPanel.editableColumn.items[0].el; // set has_entry..
82                             LeftPanel.editableColumn.items[0].el.stop_editing();
83                             var type = LeftPanel.get('model').getType(res.path.to_string());
84                             
85                              
86                             var LeftTree = imports.Builder.LeftTree.LeftTree;
87                             var provider = LeftTree.getPaleteProvider();
88                             
89                             var opts = provider.findOptions(type);
90                             
91                             if (opts === false) {
92                                 LeftPanel.editableColumn.setOptions([]);
93                                 renderer.has_entry = true;
94                             } else {
95                                 LeftPanel.editableColumn.setOptions(opts);
96                                 renderer.has_entry = false;
97                             }
98                             
99                             
100                             Seed.print("click" + ev.type);
101                             //console.dump(res);
102                             return false;
103                         }
104                       
105                     
106                        
107                         if (res.column.title == 'value') {
108                             return false;
109                         }
110                         if (!LeftPanelPopup.el) LeftPanelPopup.init();
111                         LeftPanelPopup.el.set_screen(Gdk.Screen.get_default());
112                         LeftPanelPopup.el.show_all();
113                         LeftPanelPopup.el.popup(null, null, null, null, 3, ev.button.time);
114                         Seed.print("click:" + res.column.title);
115                         
116                         
117                         return false;
118                         
119                     },
120                     'row-activated' : function() 
121                     {
122                         console.print('row activated');  
123                           // always set the cmobo entry to not ediable..
124                         
125                       
126                     }
127
128                     
129                     
130                 },
131                 items : [
132                 
133                     {
134                         id : 'model',
135                         pack : [ 'set_model' ],
136                         xtype : Gtk.ListStore,
137                         
138                         init : function ()
139                         {
140                             XObject.prototype.init.call(this); 
141                             this.el.set_column_types ( 5, [
142                                 GObject.TYPE_STRING,  // 0 real key
143                                 GObject.TYPE_STRING, // 1 real value 
144                                  GObject.TYPE_STRING,  // 2 visable key
145                                  GObject.TYPE_STRING, // 3 visable value
146                                  GObject.TYPE_STRING, // 4 need to store type of!!!
147                               
148                             ]);
149                                     
150                             
151                          
152                         },
153                         toShort: function(str) {
154                             var a = typeof(str) == 'string' ? str.split("\n") : [];
155                             return a.length > 1 ? a[0] + '....' : '' + str;
156                         },
157                         load : function (ar)
158                         {
159                             this.el.clear();
160                             
161                             RightEditor.el.hide();
162                             if (ar === false) {
163                                 return ;
164                             }
165                             var ret = {}; 
166                             
167                             var LeftTree = imports.Builder.LeftTree.LeftTree;
168                             var provider = LeftTree.getPaleteProvider();
169                             
170                             // sort!!!?
171                             var iter = new Gtk.TreeIter();
172                             for (var i in ar) {
173                                 if (typeof(ar[i]) == 'object') {
174                                     continue;
175                                 }
176                                 
177                                 var type = provider.findType(ar, i, ar[i]);
178                                 
179                                 this.el.append(iter);
180                                 var p = this.el.get_path(iter).to_string();
181                                 ret[i] = p;
182                                 this.el.set_value(iter, 0, i);
183                                 this.el.set_value(iter, 1, '' + ar[i]);
184                                 this.el.set_value(iter, 2, i);
185                                 this.el.set_value(iter, 3, this.toShort(ar[i]));
186                                 this.el.set_value(iter, 4, type);
187                             }
188                             ar.listeners = ar.listeners || {};
189                             for (var i in ar.listeners ) {
190                                 this.el.append(iter);
191                                 var p = this.el.get_path(iter).to_string();
192                                 ret['!' + i] = p;
193                                 
194                                 this.el.set_value(iter, 0, '!'+  i  );
195                                 this.el.set_value(iter, 1, '' + ar.listeners[i]);
196                                 this.el.set_value(iter, 2, '<b>'+ i + '</b>');
197                                 
198                                 this.el.set_value(iter, 3, '' + this.toShort(ar.listeners[i]));
199                                 this.el.set_value(iter, 4, 'function');
200                             }
201                             return ret;
202                         },
203                         
204                         
205                         
206                         add : function( info ) {
207                             // info includes key, val, skel, etype..
208                              console.dump(info);
209                             type = info.type.toLowerCase();
210                             var data = this.toJS();
211                             
212                             if (info.etype == 'events') {
213                                 data.listeners = data.listeners || { };
214                                 if (typeof(data.listeners[info.key]) != 'undefined') {
215                                     return; //already set!
216                                 }
217                             } else {
218                                 if (typeof(data[info.key]) != 'undefined') {
219                                     return;
220                                 }
221                             }
222                             
223                             if (typeof(info.val) == 'undefined') {
224                                     
225                                 info.val = '';
226                                 if (info.type == 'boolean') {
227                                     info.val = true;
228                                 }
229                                 if (type == 'number') {
230                                     info.val = 0;
231                                 }
232                                 // utf8 == string..
233                                 
234                                 
235                             }
236                             var k = info.key;
237                             if (info.etype == 'events') {
238                              
239                                 data.listeners[info.key] = info.val;
240                                 k = '!' + info.key;
241                             } else {
242                                 data[info.key] = info.val;
243                             }
244                             
245                             
246                             var map = this.load(data);
247                             
248                             var LeftTree        = imports.Builder.LeftTree.LeftTree;
249                             
250                             LeftTree.get('model').changed(data, true); 
251                             
252                             var type = LeftPanel.get('model').getType(map[k]);
253                             
254                              
255                             var LeftTree = imports.Builder.LeftTree.LeftTree;
256                             var provider = LeftTree.getPaleteProvider();
257                             
258                             var opts = provider.findOptions(type);
259                             var renderer = LeftPanel.editableColumn.items[0].el;
260                             
261                             if (opts === false) {
262                                 LeftPanel.editableColumn.setOptions([]);
263                                 renderer.has_entry = true; /// probably does not have any effect.
264                             } else {
265                                 LeftPanel.editableColumn.setOptions(opts);
266                                 renderer.has_entry = false;
267                             }
268                             
269                             
270                             this.startEditing(map[k]);
271                              
272                             /*
273                             LeftPanel.get('view').el.row_activated(
274                                 new Gtk.TreePath.from_string(map[k]), 
275                                 LeftPanel.editableColumn.el
276                             );
277                             */
278                             
279                             
280                         },
281                         /**
282                          * start editing path (or selected if not set..)
283                          * @param {String|false} path  (optional) treepath to edit - selected tree gets
284                          *     edited by default.
285                          * @param {Number} 0 or 1 (optional)- column to edit. 
286                          */
287                         startEditing : function(path, col)
288                         {
289                             // fix tp (treepath) and path string..
290                             var tp;
291                             if (typeof(path) == 'string') {
292                                 tp = new Gtk.TreePath.from_string(path);
293                             } else {
294                                 var iter = new Gtk.TreeIter();
295                                 var s = LeftPanel.get('view').selection;
296                                 s.get_selected(this.el, iter);
297                                 tp = this.el.get_path(iter);
298                                 path = tp.to_string();
299                             }
300                             
301                             // which colum is to be edited..
302                             var colObj = false;
303                             if (typeof(col) == 'undefined') {
304                                 colObj = (!k.length || k == '|') ? 
305                                     LeftPanel.propertyColumn : LeftPanel.editableColumn;
306                             } else {
307                                 colObj = col ? LeftPanel.propertyColumn : LeftPanel.editableColumn;
308                             }
309                             
310                             // make sure the pulldown is set correctly..
311                             // not really needed for second col...
312                             var type = LeftPanel.get('model').getType(path);
313                             var opts = provider.findOptions(type);
314                             var renderer = LeftPanel.editableColumn.items[0].el;
315                             
316                             if (opts === false) {
317                                 LeftPanel.editableColumn.setOptions([]);
318                                 renderer.has_entry = true; /// probably does not have any effect.
319                             } else {
320                                 LeftPanel.editableColumn.setOptions(opts);
321                                 renderer.has_entry = false;
322                             }
323                             
324                             
325                             // iter now has row...
326                             GLib.timeout_add(0, 100, function() {
327                                 
328                                 colObj.items[0].el.editable = true; // esp. need for col 0..
329                                 LeftPanel.get('view').el.set_cursor_on_cell(
330                                     tp,
331                                     col.el,
332                                     col.items[0].el,
333                                     true
334                                 );
335                             });
336                             
337                           
338                           
339                         },
340                         deleteSelected : function()
341                         {
342                             var data = this.toJS();
343                             var iter = new Gtk.TreeIter();
344                             var s = LeftPanel.get('view').selection;
345                             s.get_selected(this.el, iter);
346                                  
347                                
348                             var gval = new GObject.Value('');
349                             LeftPanel.get('model').el.get_value(iter, 0 ,gval);
350                             
351                             var val = gval.value;
352                             if (val[0] == '!') {
353                                 // listener..
354                                 if (!data.listeners || typeof(data.listeners[  val.substring(1)]) == 'undefined') {
355                                     return;
356                                 }
357                                 delete data.listeners[  val.substring(1)];
358                                 if (!XObject.keys(data.listeners).length) {
359                                     delete data.listeners;
360                                 }
361                                 
362                             } else {
363                                 if (typeof(data[val]) == 'undefined') {
364                                     return;
365                                 }
366                                 delete data[val];
367                             }
368                             
369                             
370                             this.load(data);
371                             var LeftTree        = imports.Builder.LeftTree.LeftTree;
372                             LeftTree.get('model').changed(data, true);
373                             
374                         },
375                         
376                         
377                         
378                         activePath : false,
379                         changed : function(str, doRefresh)
380                         {
381                             if (!this.activePath) {
382                                 return;
383                             }
384                             var iter = new Gtk.TreeIter();
385                             this.el.get_iter(iter, new Gtk.TreePath.from_string(this.activePath));
386                             
387                             this.el.set_value(iter, 1, '' +str);
388                             this.el.set_value(iter, 3, '' + this.toShort(str));
389                             // update the tree...
390                             var LeftTree        = imports.Builder.LeftTree.LeftTree;
391                             LeftTree.get('model').changed(this.toJS(), doRefresh); 
392                         },
393                         toJS: function()
394                         {
395                             var iter = new Gtk.TreeIter();
396                             LeftPanel.get('model').el.get_iter_first(iter);
397                             var ar = {};
398                                
399                             while (true) {
400                                 
401                                 var k = this.getValue(iter, 0);
402                                // Seed.print(k);
403                                 if (k[0] == '!') {
404                                     ar.listeners = ar.listeners || {};
405                                     ar.listeners[  k.substring(1)] = this.getValue(iter, 1);
406                                     
407                                 } else {
408                                     ar[ k ] = this.getValue(iter, 1);
409                                 }
410                                 
411                                 if (! LeftPanel.get('model').el.iter_next(iter)) {
412                                     break;
413                                 }
414                             }
415                             
416                             
417                             Seed.print(JSON.stringify(ar));
418                             return ar;
419                             // convert the list into a json string..
420                         
421                             
422                         },
423                         getType :function(treepath_str)
424                         {
425                             var iter = new Gtk.TreeIter();
426                             this.el.get_iter(iter, new Gtk.TreePath.from_string(treepath_str));
427                             
428                             var gval = new GObject.Value('');
429                             LeftPanel.get('model').el.get_value(iter,4  ,gval);
430                             return gval.value + '';
431                         },
432                         
433                         /** get's a value, and tries to use type column to work out what type */
434                         getValue: function (iter, col) {
435                             
436                             var gval = new GObject.Value('');
437                             LeftPanel.get('model').el.get_value(iter, col ,gval);
438                             var val = '' + gval.value;
439                             if (col != 1) {
440                                 return val;
441                             }
442                             var type = this.getType(this.el.get_path(iter).to_string());
443                             //print("TYPE: " +type + " -  val:" + val);
444                             switch(type.toLowerCase()) {
445                                 case 'number':
446                                 case 'uint':
447                                 case 'int':
448                                     return parseFloat(val); // Nan ?? invalid!!?
449                                 case 'boolean':
450                                     return val == 'true' ? true : false;
451                                 default: 
452                                     return val;
453                             }
454                             
455                         },
456                         
457                         editSelected: function( e)
458                         {
459                             print("EDIT SELECTED?");
460                             var iter = new Gtk.TreeIter();
461                             var s = LeftPanel.get('view').selection;
462                             s.get_selected(LeftPanel.get('model').el, iter);
463                             var m = LeftPanel.get('model');
464                            
465                             var gval = new GObject.Value('');
466                             this.el.get_value(iter, 0 ,gval);
467                             var val = '' + gval.value;
468                             
469                             gval = new GObject.Value('');
470                             this.el.get_value(iter, 1 ,gval);
471                             var rval = gval.value;
472                             var activePath = this.el.get_path(iter).to_string(); 
473                             this.activePath = activePath ;
474                             // was activeIter...
475                             //  not listener...
476                             
477                             var showEditor = false;
478                             
479                             if (val[0] == '!') {
480                                 showEditor = true;
481                             }
482                             if (val[0] == '|') {
483                                 if (rval.match(/function/g) || rval.match(/\n/g)) {
484                                     showEditor = true;
485                                 }
486                             }
487                             
488                             if (showEditor) {
489                                 var _this = this;
490                                 this.activePath = false;
491                                 GLib.timeout_add(0, 1, function() {
492                                     //   Gdk.threads_enter();
493                                     RightEditor.el.show();
494                                     RightEditor.get('view').load( rval );
495                                     
496                                     e.editing_done();
497                                     e.remove_widget();
498                                     _this.activePath = activePath ;
499                                     
500                              //       Gdk.threads_leave();
501                                     return false;
502                                 });
503                                 return;
504                             }
505                              
506                             RightEditor.el.hide();
507
508                             var type = this.getValue(iter,4);
509                             print("type = " + type);
510                             // toggle boolean
511                             if (type == 'boolean') {
512                                 // let's show a pulldown..
513                                 //LeftPanel.editableColumn.setOptions([ 'true' , 'false']);
514                                 
515                                 return;
516                                 val = ! this.getValue(iter,1);
517                                 
518                                 this.activePath = false;
519                                 var _this = this;
520                                 GLib.timeout_add(0, 1, function() {
521                                     //   Gdk.threads_enter();
522                                      
523                                     e.editing_done();
524                                     e.remove_widget();
525                                     _this.activePath = activePath ;
526                                     _this.changed(''+val,true);
527                                     
528                              
529                                     return false;
530                                 });
531                             }
532                             //LeftPanel.editableColumn.el.has_entry = true; // alwo editing?
533                              // otherwise we are going to show the text editor..   
534                              
535                             
536                             
537                        
538                         }
539                           
540                         
541                     },
542
543                     {
544                         
545                         xtype: Gtk.TreeViewColumn,
546                         pack : ['append_column'],
547                         title : 'key',
548                         init : function ()
549                         {
550                             XObject.prototype.init.call(this); 
551                             this.el.add_attribute(this.items[0].el , 'markup', 2 );
552                             LeftPanel.propertyColumn= this;
553                         },
554                         items : [
555                             {
556                                 xtype : Gtk.CellRendererText,
557                                 editable : false,
558                                 pack : ['pack_start'],
559                             
560                                 listeners : {
561                                     'editing-started' : function(r, e, p) {
562                                         LeftPanel.get('model').activePath  = p;
563                                         this.editEvent = e;
564                                     },
565                                     edited : function(r,p, t) {
566
567                                         // since our visiable col is differnt from the editable one..
568                                         var model = LeftPanel.get('model');
569                                         var path = LeftPanel.get('model').activePath;
570                                         var iter = new Gtk.TreeIter();
571                                         model.el.get_iter(iter, new Gtk.TreePath.from_string(path));
572                                         model.el.set_value(iter, 0, t);
573                                         model.el.set_value(iter, 2, t);
574                                         
575                                         LeftPanel.get('model').activePath = false;
576                                         var LeftTree        = imports.Builder.LeftTree.LeftTree;
577                                         LeftTree.get('model').changed(LeftPanel.get('model').toJS(), true); 
578                                         this.el.editable = false;
579                                         
580                                             //this.el.has_entry = false;
581                                     }
582                                 }
583                             }
584                         ]
585                     },
586                             
587                     {
588                         
589                         xtype: Gtk.TreeViewColumn,
590                         pack : ['append_column'],
591                         title : 'value',
592                         init : function ()
593                         {
594                             XObject.prototype.init.call(this); 
595                             this.el.add_attribute(this.items[0].el , 'text', 3 );
596                             this.el.add_attribute(this.items[0].el , 'sensitive', 3 );
597                             this.el.add_attribute(this.items[0].el , 'editable', 3 );
598                            // this.el.set_cell_data_func(cell, age_cell_data_func, NULL, NULL);
599
600                             LeftPanel.editableColumn= this;
601                         },
602                         setOptions : function(ar)
603                         {
604                             //this.items[0].el.has_entry = false; // stop editable.
605                            //this.items[0].el.editable = false;
606                             var m = this.items[0].el.model;
607                             m.clear();
608                             var iter = new Gtk.TreeIter();
609                             ar.forEach(function(i) {
610                                    // sort!!!?
611                                 m.append(iter);
612                                 m.set_value(iter, 0, i);
613                             });
614                             
615                             
616                           
617                         },
618                         
619                         items : [
620                          
621                             {
622                                 
623                                 xtype : function() {
624                                     var  ret = new Gtk.CellRendererCombo();
625                                     ret.model = new Gtk.ListStore();
626                                     ret.model.set_column_types ( 1, [
627                                         GObject.TYPE_STRING,  // 0 real key
628                                         
629                                     ]);
630                                     
631                                     return  ret;
632                                 },
633                                 pack : ['pack_start'],
634                                 editable : true,
635                                 has_entry : false,
636                                 text_column : 0,
637                                 listeners : {
638  
639                                     edited : function(r,p, t) {
640                                         LeftPanel.editing = false;
641                                         print("EDITED? p:" + p + " t:" + t);
642                                         LeftPanel.get('model').changed(t, true);
643                                         LeftPanel.get('model').activePath = false;
644                                         //this.el.has_entry = false;
645                                     },
646                                     
647                                     'editing-started' : function(r, e, p) {
648                                         LeftPanel.editing  = true;
649                                       //  console.log('editing started');
650                                        // r.has_entry = false;
651                                         LeftPanel.get('model').editSelected(e);
652                                     }    
653                                 },
654                                 
655                                 
656                             }
657                         ]
658                     }
659                 
660                 ]
661             }
662         ]    
663             
664     }
665 );
666     
667      
668