Fix #7367 - only show add child on addable objects
[roobuilder] / src / Builder4 / WindowLeftTree.vala
1 static Xcls_WindowLeftTree  _WindowLeftTree;
2
3 public class Xcls_WindowLeftTree : Object
4 {
5     public Gtk.Box el;
6     private Xcls_WindowLeftTree  _this;
7
8     public static Xcls_WindowLeftTree singleton()
9     {
10         if (_WindowLeftTree == null) {
11             _WindowLeftTree= new Xcls_WindowLeftTree();
12         }
13         return _WindowLeftTree;
14     }
15     public Xcls_viewwin viewwin;
16     public Xcls_view view;
17     public Xcls_model model;
18     public Xcls_maincol maincol;
19     public Xcls_iconrender iconrender;
20     public Xcls_renderer renderer;
21     public Xcls_addiconrender addiconrender;
22     public Xcls_LeftTreeMenu LeftTreeMenu;
23
24         // my vars (def)
25     public signal bool before_node_change ();
26     public Xcls_MainWindow main_window;
27     public signal void changed ();
28     public signal void node_selected (JsRender.Node? node, string source);
29
30     // ctor
31     public Xcls_WindowLeftTree()
32     {
33         _this = this;
34         this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 );
35
36         // my vars (dec)
37         this.main_window = null;
38
39         // set gobject values
40         var child_0 = new Xcls_viewwin( _this );
41         child_0.ref();
42         this.el.add (  child_0.el  );
43     }
44
45     // user defined functions
46     public string getActivePath () {
47         
48         var view = this.view.el;
49         if (view.get_selection().count_selected_rows() < 1) {
50             return "";
51         }
52         Gtk.TreeIter iter;
53         Gtk.TreeModel mod;
54         view.get_selection().get_selected(out mod, out iter);
55         return mod.get_path(iter).to_string();
56     }
57     public JsRender.Node? getActiveElement () { // return path to actie node.
58     
59          var path = this.getActivePath();
60          if (path.length < 1) {
61             return null;
62          }
63          return _this.model.pathToNode(path);
64          
65     }
66     public JsRender.JsRender getActiveFile () {
67         return this.main_window.windowstate.file;
68     }
69     public class Xcls_viewwin : Object
70     {
71         public Gtk.ScrolledWindow el;
72         private Xcls_WindowLeftTree  _this;
73
74
75             // my vars (def)
76
77         // ctor
78         public Xcls_viewwin(Xcls_WindowLeftTree _owner )
79         {
80             _this = _owner;
81             _this.viewwin = this;
82             this.el = new Gtk.ScrolledWindow( null, null );
83
84             // my vars (dec)
85
86             // set gobject values
87             this.el.shadow_type = Gtk.ShadowType.IN;
88             var child_0 = new Xcls_view( _this );
89             child_0.ref();
90             this.el.add (  child_0.el  );
91             var child_1 = new Xcls_LeftTreeMenu( _this );
92             child_1.ref();
93
94             // init method
95
96             this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
97
98             //listeners
99             this.el.size_allocate.connect( (allocation) => {
100             
101                  
102                 //GLib.debug("Got allocation width of scrolled view %d", allocation.width );
103                 _this.maincol.el.set_max_width(allocation.width - 32);
104             });
105         }
106
107         // user defined functions
108     }
109     public class Xcls_view : Object
110     {
111         public Gtk.TreeView el;
112         private Xcls_WindowLeftTree  _this;
113
114
115             // my vars (def)
116         public bool blockChanges;
117         public bool drag_in_motion;
118         public string lastEventSource;
119         public string dragData;
120         public bool button_is_pressed;
121         public bool key_is_pressed;
122         public int drag_x;
123         public int drag_y;
124         public string[] dropList;
125
126         // ctor
127         public Xcls_view(Xcls_WindowLeftTree _owner )
128         {
129             _this = _owner;
130             _this.view = this;
131             this.el = new Gtk.TreeView();
132
133             // my vars (dec)
134             this.blockChanges = false;
135             this.lastEventSource = "";
136             this.button_is_pressed = false;
137             this.key_is_pressed = false;
138
139             // set gobject values
140             this.el.expand = true;
141             this.el.tooltip_column = 1;
142             this.el.enable_tree_lines = true;
143             this.el.headers_visible = false;
144             var child_0 = new Xcls_model( _this );
145             child_0.ref();
146             this.el.set_model (  child_0.el  );
147             var child_1 = new Xcls_maincol( _this );
148             child_1.ref();
149             this.el.append_column (  child_1.el  );
150             var child_2 = new Xcls_TreeViewColumn8( _this );
151             child_2.ref();
152             this.el.append_column (  child_2.el  );
153
154             // init method
155
156             {
157                 var description = new Pango.FontDescription();
158                 description.set_size(8000);
159                 this.el.override_font(description);
160             
161                 var selection = this.el.get_selection();
162                 selection.set_mode( Gtk.SelectionMode.SINGLE);
163             
164             
165                 // is this really needed??
166                 /*
167                 this.selection.signal['changed'].connect(function() {
168                     _this.get('/LeftTree.view').listeners.cursor_changed.apply(
169                         _this.get('/LeftTree.view'), [ _this.get('/LeftTree.view'), '']
170                     );
171                 });
172                 */
173                 Gtk.drag_source_set (
174                     this.el,            /* widget will be drag-able */
175                     Gdk.ModifierType.BUTTON1_MASK,       /* modifier that will start a drag */
176                     BuilderApplication.targetList,            /* lists of target to support */
177                     Gdk.DragAction.COPY   | Gdk.DragAction.MOVE    |  Gdk.DragAction.LINK           /* what to do with data after dropped */
178                 );
179             
180                 // ?? needed??
181                 //Gtk.drag_source_add_text_targets(this.el); 
182             
183                 Gtk.drag_dest_set
184                 (
185                     this.el,              /* widget that will accept a drop */
186                     Gtk.DestDefaults.MOTION  | Gtk.DestDefaults.HIGHLIGHT,
187                     BuilderApplication.targetList,            /* lists of target to support */
188                     Gdk.DragAction.COPY   | Gdk.DragAction.MOVE   | Gdk.DragAction.LINK     /* what to do with data after dropped */
189                 );
190             
191                 //Gtk.drag_dest_set_target_list(this.el, Builder.Application.targetList);
192                 //Gtk.drag_dest_add_text_targets(this.el);
193                 
194                 
195                
196                 
197             }
198
199             //listeners
200             this.el.button_release_event.connect( (ev) => { 
201                 this.button_is_pressed = false;
202               return false;
203             });
204             this.el.button_press_event.connect( ( ev) => {
205                 //console.log("button press?");
206                 this.button_is_pressed = true;
207                 print("BUTTON DOWN\n");
208                 
209                 this.lastEventSource = "tree";
210                 if (! _this.before_node_change() ) {
211                 
212                    return true;
213                 }
214                 
215                 if (ev.type != Gdk.EventType.BUTTON_PRESS) {
216                         return false;
217                 }
218                 if (_this.model.el.iter_n_children(null) < 1) {
219                     _this.main_window.windowstate.showAddObject(_this.view.el);
220                     return true;
221                 }
222                 
223                
224                 Gtk.TreePath res;
225                 Gtk.TreeViewColumn col;
226                 if (!_this.view.el.get_path_at_pos((int)ev.x,(int)ev.y, out res, out col, null, null) ) {
227                     return true;
228                 }
229                 
230                 if (col.title == "Add") {
231                         GLib.Value value;
232                         Gtk.TreeIter iter;
233             
234                         _this.model.el.get_iter (out  iter, res);
235                     _this.model.el.get_value(iter, 2, out value);               
236                         // why dup_ - gets and and inc's ref count (which in theory should be freed at the end.?
237                         
238                     var node = (JsRender.Node)value.dup_object();
239                     var fqn = node.fqn();
240                         var cn = _this.main_window.windowstate.project.palete.getChildList(fqn);
241                         if (cn.length < 1) {
242                                 return true;
243                         }
244                 
245                      _this.main_window.windowstate.leftTreeBeforeChange();
246                      this.el.get_selection().select_path(res);
247                         _this.main_window.windowstate.showAddObject(this.el);
248                         return true;
249                  }
250                 
251                 if (  ev.button != 3) {
252                     //print("click" + ev.type);
253                     return false;
254                  }
255                 _this.main_window.windowstate.leftTreeBeforeChange();
256             
257                 
258                  
259                 this.el.get_selection().select_path(res);
260                  
261                   
262                  
263                   //if (!this.get('/LeftTreeMenu').el)  { 
264                   //      this.get('/LeftTreeMenu').init(); 
265                   //  }
266                     
267                  _this.LeftTreeMenu.el.set_screen(Gdk.Screen.get_default());
268                  _this.LeftTreeMenu.el.show_all();
269                   _this.LeftTreeMenu.el.popup(null, null, null,  3, ev.time);
270                  //   print("click:" + res.path.to_string());
271                   return true;
272             });
273             this.el.cursor_changed.connect( ( ) => {
274                 print("LEFT TREE Cursor Changed\n");
275                 if (!this.button_is_pressed && !this.key_is_pressed) {
276                         // then event was started by some other action
277                         // which should manually trigger all the events..
278                         print("SKIPPING select - no button or key pressed\n");
279                         return;
280                 }
281             
282             
283                  if (this.blockChanges) { // probably not needed.. 
284                         print("SKIPPING select - blockchanges set..\n");     
285                    return  ;
286                  }
287                   if (!_this.before_node_change( ) ) {
288                      this.blockChanges = true;
289                      this.el.get_selection().unselect_all();
290                      this.blockChanges = false;
291                      
292                      return;
293                  }
294                  if (_this.main_window.windowstate.file == null) {
295                         print("SKIPPING select windowstate file is not set...\n");     
296                      return;
297                  } 
298                  
299                  //var render = this.get('/LeftTree').getRenderer();                
300                 print("LEFT TREE -> view -> selection changed called\n");
301                 
302                 
303                 // -- it appears that the selection is not updated.
304                   
305                 GLib.Timeout.add_full(GLib.Priority.DEFAULT,10 , () => {
306                      print("LEFT TREE -> view -> selection changed TIMEOUT CALLED\n");
307             
308                         if (this.el.get_selection().count_selected_rows() < 1) {
309             
310                             print("selected rows < 1\n");
311                             //??this.model.load( false);
312                             _this.node_selected(null, this.lastEventSource);
313                             
314                             return false ;
315                         }
316                             
317                             //console.log('changed');
318                         var s = this.el.get_selection();
319                          Gtk.TreeIter iter;
320                          Gtk.TreeModel mod;
321                         s.get_selected(out mod, out iter);
322                         
323                         
324                         // var val = "";
325                         GLib.Value value;
326                         _this.model.el.get_value(iter, 2, out value);
327                         _this.model.activePath = mod.get_path(iter).to_string();
328                         
329                         // why dup_?
330                         
331                         var node = (JsRender.Node)value.dup_object();
332                         print ("calling left_tree.node_selected\n");
333                         _this.node_selected(node, this.lastEventSource);
334                         while (Gtk.events_pending()) {
335                             Gtk.main_iteration();
336                        }
337                         var cp = mod.get_path(iter);
338                         Gtk.TreePath sp, ep;
339                         this.el.get_visible_range(out sp, out ep);
340                         // if sp is before cp then retuns 1.
341                         // if cp is before ep then retuns 1.
342                         if (cp.compare(sp) >= 0 && ep.compare(cp) >=1) {
343                             return false;
344                         }
345                         
346                          
347                         
348                         this.el.scroll_to_cell(new Gtk.TreePath.from_string(_this.model.activePath), null, true, 0.1f,0.0f);
349                         
350                         return false;
351                   });  
352                 //_this.after_node_change(node);
353             
354             //        _this.model.file.changed(node, "tree");
355                
356                 //Seed.print( value.get_string());
357                 return  ;
358                             
359             });
360             this.el.drag_begin.connect( ( ctx)  => {
361                 //print('SOURCE: drag-begin');
362                     
363                     
364                     //this.targetData = "";
365                     
366                     // find what is selected in our tree...
367                     
368                     var s = _this.view.el.get_selection();
369                     if (s.count_selected_rows() < 1) {
370                         return;
371                     }
372                     Gtk.TreeIter iter;
373                     Gtk.TreeModel mod;
374                     s.get_selected(out mod, out iter);
375             
376                     
377             
378                     // set some properties of the tree for use by the dropped element.
379                     GLib.Value value;
380                     _this.model.el.get_value(iter, 2, out value);
381                     var tp = mod.get_path(iter).to_string();
382                     var data = (JsRender.Node)(value.dup_object());
383                     var xname = data.fqn();
384                     print ("XNAME  IS " + xname+ "\n");
385                     this.dragData = tp;
386                     this.dropList = _this.main_window.windowstate.file.palete().getDropList(xname);
387                     
388                     print ("DROP LIST IS " + string.joinv(", ", this.dropList) + "\n");
389                     
390             
391                     // make the drag icon a picture of the node that was selected
392                 
393                     
394                 // by default returns the path..
395                    var path = _this.model.el.get_path(iter);
396             
397                      
398                     var pix = this.el.create_row_drag_icon ( path);
399                     
400                     Gtk.drag_set_icon_surface (ctx, pix) ;
401                     
402                     return;
403             });
404             this.el.drag_data_get.connect( ( drag_context, data, info, time) => {
405                         
406             
407                 //print("drag-data-get");
408                 var s = this.el.get_selection();
409                 if (s.count_selected_rows() < 1) {
410                         data.set_text("",0);     
411                          print("return empty string - no selection..");
412                         return;
413                 }
414             
415                 Gtk.TreeIter iter;
416                 Gtk.TreeModel mod;
417             
418                 s.get_selected(out mod, out iter);
419             
420             
421             
422                 GLib.Value value;
423                 _this.model.el.get_value(iter, 2, out value);
424                 var ndata = (JsRender.Node)(value.dup_object());
425             
426             
427             
428                 var tp = mod.get_path(iter).to_string();
429                 // by default returns the path..
430             
431                 if ( info != Gdk.Atom.intern("STRING",true) ) {
432                         tp = ndata.toJsonString();
433                 }   
434             
435                 //data.set_text(tp,tp.length);   
436             
437                 data.set (data.get_target (), 8, (uchar[]) tp.to_utf8 ());
438             
439             
440                 //  print("return " + tp);
441                 });
442             this.el.drag_end.connect( (drag_context) => {
443                 //Seed.print('LEFT-TREE: drag-end');
444                     this.dragData = "";
445                     this.dropList = null;
446             //        this.targetData = "";
447                     this.highlightDropPath("",0);
448             //        return true;
449             });
450             this.el.drag_motion.connect( ( ctx, x, y, time)  => {
451                print("got drag motion\n");
452                 var src = Gtk.drag_get_source_widget(ctx);
453                this.drag_x = x;
454                this.drag_y = y;     
455             
456                if (src != this.el) {
457                
458              
459              
460                 // the point of this is to detect where an item could be dropped..
461                     print("requesting drag data\n");
462                    this.drag_in_motion = true;
463                    
464                         // request data that will be recieved by the recieve...              
465                     Gtk.drag_get_data
466                     (
467                             this.el,         // will receive 'drag-data-received' signal 
468                             ctx,        // represents the current state of the DnD 
469                             Gdk.Atom.intern("STRING",true),    // the target type we want 
470                             time            // time stamp 
471                     );
472                     return true;
473               }    
474             
475             
476               print("action: %d\n", ctx.get_actions());
477              //print("GETTING POS");
478                 var  targetData = "";
479             
480                 Gtk.TreePath path;
481                 Gtk.TreeViewDropPosition pos;
482                 var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);
483             
484                 // if there are not items in the tree.. the we have to set isOver to true for anything..
485                 var isEmpty = false;
486                 if (_this.model.el.iter_n_children(null) < 1) {
487                     print("got NO children?\n");
488                     isOver = true; //??? 
489                     isEmpty = true;
490                     pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;
491                 }
492             
493             
494                 // ------------- a drag from self..
495             
496             
497                 //var action = Gdk.DragAction.COPY;
498                     // unless we are copying!!! ctl button..
499                 
500                 var action = (ctx.get_actions() & Gdk.DragAction.MOVE) > 0 ?
501                              Gdk.DragAction.COPY  : Gdk.DragAction.MOVE ;
502                             // Gdk.DragAction.MOVE : Gdk.DragAction.COPY ;
503             
504             
505                 if (_this.model.el.iter_n_children(null) < 1) {
506                     // no children.. -- asume it's ok..
507                     
508                     targetData = "|%d|".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);
509                        
510                     this.highlightDropPath("", (Gtk.TreeViewDropPosition)0);        
511                     Gdk.drag_status(ctx, action ,time);
512                     return true;
513                     
514                     // continue through to allow drop...
515             
516                 } 
517                     
518                     
519             
520                 
521                 
522                 //print("ISOVER? " + isOver);
523                 if (!isOver) {
524               
525                     Gdk.drag_status(ctx, 0 ,time);
526                      this.highlightDropPath("", (Gtk.TreeViewDropPosition)0);                    
527                      return false;
528             
529                 }
530                         
531                 // drag node is parent of child..
532                 //console.log("SRC TREEPATH: " + src.treepath);
533                 //console.log("TARGET TREEPATH: " + data.path.to_string());
534                 
535                 // nned to check a  few here..
536                 //Gtk.TreeViewDropPosition.INTO_OR_AFTER
537                 //Gtk.TreeViewDropPosition.INTO_OR_BEFORE
538                 //Gtk.TreeViewDropPosition.AFTER
539                 //Gtk.TreeViewDropPosition.BEFORE
540                 
541                 // locally dragged items to not really use the 
542                 var selection_text = this.dragData;
543                 
544                         
545                         
546                 if (selection_text == null || selection_text.length < 1) {
547                             //print("Error  - drag selection text returned NULL");
548                          Gdk.drag_status(ctx, 0 ,time);
549                         this.highlightDropPath("", (Gtk.TreeViewDropPosition)0);
550                          return false;
551                  }
552                                    
553                         
554                         // see if we are dragging into ourself?
555                 var target_path = path.to_string();            
556                 print ("Drag  %s onto %s--%d\n ", selection_text, target_path, pos);
557                 
558                 // pos : 3 = ontop - 0 = after, 1 = before
559                 //print("target_path="+target_path);
560             
561                 // 
562                 if (selection_text  == target_path) {
563                     print("self drag ?? == we should perhaps allow copy onto self..\n");
564                             
565                      Gdk.drag_status(ctx, 0 ,time);
566                       this.highlightDropPath("", (Gtk.TreeViewDropPosition)0);
567                       return false;
568             //                 -- fixme -- this is not really correct..
569             
570                 }
571                         
572                 // check that 
573                 //print("DUMPING DATA");
574                 //console.dump(data);
575                 // path, pos
576                 
577                 //print(data.path.to_string() +' => '+  data.pos);
578                 
579                 // dropList is a list of xtypes that this node could be dropped on.
580                 // it is set up when we start to drag..
581                 
582                 
583                 targetData = _this.model.findDropNodeByPath( path.to_string(), this.dropList, pos);
584                     
585                 print("targetDAta: " + targetData +"\n");
586                 
587                 if (targetData.length < 1) {
588                     //print("Can not find drop node path");
589                    
590                     Gdk.drag_status(ctx, 0, time);
591                     this.highlightDropPath("", (Gtk.TreeViewDropPosition)0);
592                     return false;
593                 }
594                 
595                 var td_ar = targetData.split("|");
596                   
597                 
598             
599                 Gdk.drag_status(ctx, action ,time);
600                 this.highlightDropPath(td_ar[0], (Gtk.TreeViewDropPosition)int.parse(td_ar[1]));
601                 return true;
602                    
603                    
604             });
605             this.el.key_press_event.connect( (ev) => {
606                this.key_is_pressed = true;
607                 return false;
608             });
609             this.el.key_release_event.connect( (ev) => {
610                    this.key_is_pressed = false;
611                   return false;
612             });
613             this.el.drag_data_received.connect( (ctx, x, y, sel, info, time)  => {
614             
615                 // THIS CODE ONLY RELATES TO drag  or drop of "NEW" elements or "FROM another tree.."
616             
617             
618                 //  print("Tree: drag-data-received\n");
619                 var selection_text = (string)sel.get_data();
620                 //print("selection_text= %s\n",selection_text);
621             
622                 var is_drag = this.drag_in_motion;
623             
624             
625             
626                 GLib.debug("Is Drag %s\n", is_drag ? "Y": "N");
627                 var  targetData = "";
628             
629                 Gtk.TreePath path;
630                 Gtk.TreeViewDropPosition pos;
631                 var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);
632             
633                 // if there are not items in the tree.. the we have to set isOver to true for anything..
634                 var isEmpty = false;
635                 if (_this.model.el.iter_n_children(null) < 1) {
636                         GLib.debug("got NO children?\n");
637                         isOver = true; //??? 
638                         isEmpty = true;
639                         pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;
640                 }
641             
642             
643                 //console.log("LEFT-TREE: drag-motion");
644                 var src = Gtk.drag_get_source_widget(ctx);
645             
646                 // a drag from self - this should be handled by drop and motion.
647                 if (src == this.el) {
648                         GLib.debug("Source == this element should not happen.. ? \n");
649                         return;
650                 }
651                 //print("drag_data_recieved from another element");
652             
653                  
654             
655             
656                 if (selection_text == null || selection_text.length < 1 || !isOver) {
657                         // nothing valid foudn to drop...
658                            GLib.debug("empty sel text or not over");
659                         if (is_drag) {
660                             Gdk.drag_status(ctx, 0, time);
661                             this.highlightDropPath("", (Gtk.TreeViewDropPosition)0);
662                             return;
663                         }
664                         Gtk.drag_finish (ctx, false, false, time);        // drop failed..
665                         // no drop action...
666                         return;            
667             
668                 }
669                 var dropNode = new JsRender.Node(); 
670             
671                 var dropNodeType  = selection_text;
672                 var show_templates = true;
673                 // for drop
674                 if (dropNodeType[0] == '{') {
675                         var pa = new Json.Parser();
676                         try {
677                             pa.load_from_data(dropNodeType);
678                         } catch (Error e) {
679                             Gtk.drag_finish (ctx, false, false, time);        // drop failed..
680                             // no drop action...
681                             return;   
682                         }
683                          
684                         dropNode.loadFromJson( pa.get_root().get_object(), 2);
685                         dropNodeType = dropNode.fqn();
686                         show_templates = false;
687                         
688                         
689                 } else {
690                         // drop with property.
691                         if (selection_text.contains(":")) {
692                                 var bits = selection_text.split(":");
693                             dropNode.setFqn(bits[0]);
694                             dropNode.set_prop(new JsRender.NodeProp.special("prop", bits[1]));
695                             
696                             
697                             
698                         } else {
699                             dropNode.setFqn(selection_text);
700                         }
701                 }
702             
703                  
704                 // dropList --- need to gather this ... 
705                 GLib.debug("get dropList for : %s\n",dropNodeType);            
706                 var dropList = _this.main_window.windowstate.file.palete().getDropList(dropNodeType);
707             
708                 GLib.debug("dropList: %s\n", string.joinv(" , ", dropList));
709             
710                 // if drag action is link ... then we can drop it anywahere...
711                  if ((ctx.get_actions() & Gdk.DragAction.LINK) > 0) {
712                          // if path is null?? dragging into an empty tree?
713                          targetData = (path == null ? "" :  path.to_string()) + "|%d".printf((int)pos);
714                  } else {
715             
716             
717                         targetData = _this.model.findDropNodeByPath( isEmpty ? "" : path.to_string(), dropList, pos);
718                  }
719             
720             
721                         
722                 GLib.debug("targetDAta: %s", targetData );
723             
724                 if (targetData.length < 1) {
725                  
726                         // invalid drop path..
727                         if (this.drag_in_motion) {
728                             Gdk.drag_status(ctx, 0, time);
729                             this.highlightDropPath("", (Gtk.TreeViewDropPosition)0);
730                             return;
731                         }
732                         Gtk.drag_finish (ctx, false, false, time);        // drop failed..
733                         // no drop action...
734                         return;
735                 }
736             
737             
738             
739                  var td_ar = targetData.split("|");
740                   
741             
742                 if (this.drag_in_motion) { 
743                         Gdk.drag_status(ctx, Gdk.DragAction.COPY ,time);
744             
745                         this.highlightDropPath(  td_ar[0]  , (Gtk.TreeViewDropPosition)int.parse(td_ar[1]));
746                         return;
747                 }
748                 // continue on to allow drop..
749             
750             
751                 // at this point, drag is not in motion... -- as checked above... - so it's a real drop event..
752                 //targetData
753                 //   {parent}|{pos}|{prop}
754             
755             
756                _this.model.dropNode(targetData, dropNode, show_templates);
757                 
758                 GLib.debug("ADD new node!!!\n");
759                         
760                 ///Xcls_DialogTemplateSelect.singleton().show( _this.model.file.palete(), node);
761             
762                 Gtk.drag_finish (ctx, false, false,time);
763             
764             
765                         
766                         
767             
768             });
769             this.el.drag_drop.connect( (  ctx, x, y, time)  => {
770                   //Seed.print("TARGET: drag-drop");
771                
772                
773                 var src = Gtk.drag_get_source_widget(ctx);
774                  
775                if (src != this.el) {
776                
777                 
778                    
779                    this.drag_in_motion = false;   
780                         // request data that will be recieved by the recieve...              
781                     Gtk.drag_get_data
782                     (
783                             this.el,         // will receive 'drag-data-received' signal 
784                             ctx,        // represents the current state of the DnD 
785                             Gdk.Atom.intern("application/json",true),    // the target type we want 
786                             time            // time stamp 
787                     );
788             
789                      
790                     // No target offered by source => error
791                
792             
793                      return  false;
794                  }
795                  
796                  // handle drop around self..
797                  
798                               
799                         
800                 //print("GETTING POS");
801                 var  targetData = "";
802                 
803                 Gtk.TreePath path;
804                 Gtk.TreeViewDropPosition pos;
805                 var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);
806                 
807                 // if there are not items in the tree.. the we have to set isOver to true for anything..
808                 var isEmpty = false;
809                 if (_this.model.el.iter_n_children(null) < 1) {
810                     print("got NO children?\n");
811                     isOver = true; //??? 
812                     isEmpty = true;
813                     pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;
814                 }
815                 
816                  
817                  
818                 //var action = Gdk.DragAction.COPY;
819                     // unless we are copying!!! ctl button..
820                 
821                 var action = (ctx.get_actions() & Gdk.DragAction.MOVE) > 0 ?
822                              Gdk.DragAction.COPY  : Gdk.DragAction.MOVE ;
823                             // Gdk.DragAction.MOVE : Gdk.DragAction.COPY ;
824             
825                   
826                 if (_this.model.el.iter_n_children(null) < 1) {
827                     // no children.. -- asume it's ok..
828                     
829                     targetData = "|%d|".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);
830                      
831                     // continue through to allow drop...
832             
833                 } else {
834                             
835                             
836                 
837                             
838                             
839                             //print("ISOVER? " + isOver);
840                     if (!isOver) {
841                         
842                         Gtk.drag_finish (ctx, false, false, time);        // drop failed..
843                         return true; // not over apoint!?! - no action on drop or motion..
844                     }
845                             
846                     // drag node is parent of child..
847                     //console.log("SRC TREEPATH: " + src.treepath);
848                     //console.log("TARGET TREEPATH: " + data.path.to_string());
849                     
850                     // nned to check a  few here..
851                     //Gtk.TreeViewDropPosition.INTO_OR_AFTER
852                     //Gtk.TreeViewDropPosition.INTO_OR_BEFORE
853                     //Gtk.TreeViewDropPosition.AFTER
854                     //Gtk.TreeViewDropPosition.BEFORE
855                     
856                     // locally dragged items to not really use the 
857                     var selection_text = this.dragData;
858                     
859                     
860                     
861                     if (selection_text == null || selection_text.length < 1) {
862                         //print("Error  - drag selection text returned NULL");
863                       
864                          Gtk.drag_finish (ctx, false, false, time);        // drop failed..
865                          return true; /// -- fixme -- this is not really correct..
866                     }                
867                             
868                             // see if we are dragging into ourself?
869                             print ("got selection text of  " + selection_text);
870                     
871                     var target_path = path.to_string();
872                     //print("target_path="+target_path);
873             
874                     // 
875                     if (selection_text  == target_path) {
876                         print("self drag ?? == we should perhaps allow copy onto self..\n");
877                         
878                          Gtk.drag_finish (ctx, false, false, time);        // drop failed..
879             
880                          return true; /// -- fixme -- this is not really correct..
881             
882                     }
883                             
884                     // check that 
885                     //print("DUMPING DATA");
886                     //console.dump(data);
887                     // path, pos
888                     
889                     //print(data.path.to_string() +' => '+  data.pos);
890                     
891                     // dropList is a list of xtypes that this node could be dropped on.
892                     // it is set up when we start to drag..
893                     
894                     
895                     targetData = _this.model.findDropNodeByPath( path.to_string(), this.dropList, pos);
896                         
897                     print("targetDAta: " + targetData +"\n");
898                     
899                     if (targetData.length < 1) {
900                         //print("Can not find drop node path");
901                          
902                         Gtk.drag_finish (ctx, false, false, time);        // drop failed..
903                         return true;
904                     }
905                                 
906                             
907                             
908                             // continue on to allow drop..
909               }
910                     // at this point, drag is not in motion... -- as checked above... - so it's a real drop event..
911             
912             
913                  var delete_selection_data = false;
914                     
915                 if (action == Gdk.DragAction.ASK)  {
916                     /* Ask the user to move or copy, then set the ctx action. */
917                 }
918             
919                 if (action == Gdk.DragAction.MOVE) {
920                     delete_selection_data = true;
921                 }
922                   
923                             // drag around.. - reorder..
924                 _this.model.moveNode(targetData, action);
925                     
926                    
927                     
928                     
929                     
930                     // we can send stuff to souce here...
931             
932             
933             // do we always say failure, so we handle the reall drop?
934                 Gtk.drag_finish (ctx, false, false,time); //delete_selection_data, time);
935             
936                 return true;
937              
938              
939              
940              
941              
942              
943             });
944         }
945
946         // user defined functions
947         public void highlightDropPath ( string treepath, Gtk.TreeViewDropPosition pos) {
948         
949                 // highlighting for drag/drop
950                 if (treepath.length > 0) {
951                     this.el.set_drag_dest_row(  new  Gtk.TreePath.from_string( treepath ), pos);
952                   } else {
953                     this.el.set_drag_dest_row(null, Gtk.TreeViewDropPosition.INTO_OR_AFTER);
954                  }
955                      
956         }
957         public void selectNode (string treepath_str, string source) {
958                 this.lastEventSource = source;
959             //this.selection.select_path(new  Gtk.TreePath.from_string( treepath_str));
960              var tp = new Gtk.TreePath.from_string(treepath_str);
961              
962              this.el.set_cursor(tp, null, false);  
963              this.el.scroll_to_cell(tp, null, false, 0,0);
964         }
965         public void setCursor (string treepath, string sourceEvent)   {
966                 this.lastEventSource = sourceEvent;
967                 //this.blockChanges = true; << block changes prevents loading of 'node data' and firing of node_selected..
968             this.el.set_cursor(new Gtk.TreePath.from_string(treepath), null, false); 
969             // fire node_selected..
970             //this.blockChanges = false;
971                 this.lastEventSource = "";
972         }
973     }
974     public class Xcls_model : Object
975     {
976         public Gtk.TreeStore el;
977         private Xcls_WindowLeftTree  _this;
978
979
980             // my vars (def)
981         public DialogTemplateSelect template_select;
982         public string activePath;
983
984         // ctor
985         public Xcls_model(Xcls_WindowLeftTree _owner )
986         {
987             _this = _owner;
988             _this.model = this;
989             this.el = new Gtk.TreeStore.newv(  { typeof(string),
990 typeof(string),
991 typeof(Object),
992 typeof(Gdk.Pixbuf),
993 typeof(Gdk.Pixbuf) }  );
994
995             // my vars (dec)
996             this.template_select = null;
997             this.activePath = "";
998
999             // set gobject values
1000
1001             // init method
1002
1003             print("model initialized");
1004         }
1005
1006         // user defined functions
1007         public void loadFile (JsRender.JsRender f) {
1008             //console.dump(f);
1009             this.el.clear();
1010             _this.main_window.windowstate.leftTreeNodeSelected(null, "");
1011             // needed???
1012             _this.main_window.windowstate.file = f;
1013             
1014            
1015             if (f.tree == null) {
1016                     try {
1017                         f.loadItems( );
1018                 } catch (Error e) {
1019                         return;
1020                 }
1021             }
1022             // if it's still null?
1023             if (f.tree == null) {
1024                         _this.main_window.windowstate.showAddObject(_this.view.el);
1025             
1026                 return;
1027             }
1028           
1029             var o = new Gee.ArrayList<JsRender.Node>();
1030             o.add(f.tree);
1031             this.load(o,null);
1032             
1033             _this.view.el.expand_all();
1034         
1035             if (f.tree.items.size < 1) {
1036                 // single item..
1037                 
1038                 //this.get('/Window.leftvpaned').el.set_position(80);
1039                 // select first...
1040                 _this.view.el.set_cursor( 
1041                     new  Gtk.TreePath.from_string("0"), null, false);
1042                 
1043                 
1044             } else {
1045                   //this.get('/Window.leftvpaned').el.set_position(200);
1046             }
1047             
1048             
1049             while (Gtk.events_pending()) {
1050                 Gtk.main_iteration();
1051            }
1052         
1053             _this.maincol.el.set_max_width(_this.viewwin.el.get_allocated_width() - 32);
1054          
1055             
1056            
1057             return;
1058          
1059                     
1060         }
1061         public string findDropNodeByPath (string treepath_str, string[] targets, int in_pref = -1) {
1062         
1063             var path = treepath_str; // dupe it..
1064             
1065             
1066             // pref : 3 = ontop - 0 = after, 1 = before
1067             int pref = in_pref < 0  ?  Gtk.TreeViewDropPosition.INTO_OR_AFTER : in_pref;
1068             
1069             var last = "";
1070             
1071             //console.dump(this.treemap);
1072             
1073             print("findDropNodeByPath : got path length %d / %s\n", path.length, path);
1074             
1075             if (path.length == 0) {
1076                 // top drop. // just return empty..
1077                 return "|%d".printf((int)pref) ;
1078                 
1079             }
1080             
1081             
1082             while (path.length > 0) {
1083             
1084                 if (path.length == treepath_str.length && pref != Gtk.TreeViewDropPosition.INTO_OR_AFTER) {
1085                     if (path.last_index_of(":") < 0 ) {
1086                         return "";
1087                     }
1088                     path = path.substring(0, path.last_index_of(":"));
1089                     last = treepath_str;
1090                     print("DROP  before or after : using %s\n",path);
1091                     continue;
1092                 }
1093             
1094                 //print("LOOKING FOR PATH: " + path);
1095                 var node_data = this.pathToNode(path);
1096                 
1097                 if (node_data == null) {
1098                     print("node not found");
1099                     return "";
1100                 }
1101                 
1102                 var xname = node_data.fqn();
1103                 var match = "";
1104                 var prop = "";
1105                 
1106                 for (var i =0; i < targets.length; i++)  {
1107                     var tg = targets[i];
1108                     if ((tg == xname)  ) {
1109                         match = tg;
1110                         break;
1111                     }
1112                     // if target is "xxxx:name"
1113                     if (tg.contains(xname +":")) {
1114                         match = tg;
1115                         var ar = tg.split(":");
1116                         prop = ar[1];
1117                         break;
1118                     }
1119                 }
1120                 
1121                 if (match.length > 0) {
1122                     if (last.length > 0) { // pref is after/before..
1123                         // then it's after last
1124                         //if (pref > 1) {
1125                         //    return "";
1126                         //}
1127                         return last + "|%d".printf((int)pref) + "|" + prop;
1128         
1129                         
1130                     }
1131                     // we need to add prop - as :store -> needs to bee added when dropping onto.
1132                     return path + "|%d".printf( (int) Gtk.TreeViewDropPosition.INTO_OR_AFTER)  + "|" + prop;
1133                 }
1134                 /*
1135                 last = "" + path;
1136                 var par = path.split(":");
1137                 string [] ppar = {};
1138                 for (var i = 0; i < par.length-1; i++) {
1139                     ppar += par[i];
1140                 }
1141                 
1142                 path = string.joinv(":", ppar);
1143                 */
1144                 break;
1145         
1146             }
1147             
1148             return "";
1149                     
1150         }
1151         public void iterSetValues (Gtk.TreeIter iter, JsRender.Node node)   {
1152                 var ic = Gtk.IconTheme.get_default();
1153             Gdk.Pixbuf pix;
1154             
1155             var o =   GLib.Value(typeof(Object));
1156             o.set_object((Object)node);
1157             var clsname = node.fqn();
1158             
1159             var clsb = clsname.split(".");
1160             var sub = clsb.length > 1 ? clsb[1].down()  : "";
1161             
1162             var addi =  ic.load_icon("list-add", 16,0);
1163             var fn = "/usr/share/glade/pixmaps/hicolor/16x16/actions/widget-gtk-" + sub + ".png";
1164             if (FileUtils.test (fn, FileTest.IS_REGULAR)) {
1165                 pix = new Gdk.Pixbuf.from_file (fn);
1166             } else {
1167                 pix = ic.load_icon("emblem-new", 16,0);
1168             }
1169             
1170             var fqn = node.fqn();
1171             var cn = _this.main_window.windowstate.project.palete.getChildList(fqn);
1172             
1173             this.el.set(
1174                         iter, 
1175                         0, node.nodeTitle(),
1176                     1, node.nodeTip(), 
1177                     -1
1178             );
1179             this.el.set_value(iter, 2,o);
1180             this.el.set_value(iter, 3,pix);    
1181                 this.el.set_value(iter, 4, cn.length > 0 ? addi : null);   
1182             
1183         
1184         }
1185         public string treePathFromNode (JsRender.Node node) {
1186             // iterate through the tree and find the node
1187             var ret = "";
1188             
1189             this.el.foreach((mod, pth, iter) => {
1190                 // get the node..
1191               
1192              
1193                  GLib.Value value;
1194                  _this.model.el.get_value(iter, 2, out value);
1195                  
1196         
1197                  
1198                  var n = (JsRender.Node)value;
1199         
1200                  print("compare %s to %s\n", n.fqn(), node.fqn());
1201                 if (node == n) {
1202                     ret = pth.to_string();
1203                     return true;
1204                 }
1205                 return false;
1206             });
1207             return ret;
1208         
1209         }
1210         public void deleteSelected () {
1211             
1212             print("DELETE SELECTED?");
1213             //_this.view.blockChanges = true;
1214             print("GET SELECTION?");
1215         
1216             var s = _this.view.el.get_selection();
1217             
1218             print("GET  SELECTED?");
1219            Gtk.TreeIter iter;
1220             Gtk.TreeModel mod;
1221         
1222             
1223             if (!s.get_selected(out mod, out iter)) {
1224                 return; // nothing seleted..
1225             }
1226               
1227         
1228         
1229             this.activePath= "";      
1230             print("GET  vnode value?");
1231         
1232             GLib.Value value;
1233             this.el.get_value(iter, 2, out value);
1234             var data = (JsRender.Node)(value.get_object());
1235             print("removing node from Render\n");
1236             if (data.parent == null) {
1237                _this.main_window.windowstate.file.tree = null;
1238             } else {
1239                 data.remove();
1240             }
1241             print("removing node from Tree\n");    
1242             s.unselect_all();
1243             this.el.remove(ref iter);
1244         
1245             
1246             
1247             
1248             // 
1249             
1250             
1251         
1252         
1253             this.activePath= ""; // again!?!?      
1254             //this.changed(null,true);
1255             
1256             _this.changed();
1257             
1258             _this.view.blockChanges = false;
1259         }
1260         public void dropNode (string target_data_str, JsRender.Node node, bool show_templates) {
1261         //         print("drop Node");
1262              // console.dump(node);
1263           //    console.dump(target_data);
1264           
1265                         //target_data_str
1266                         //   {parent}|{pos}|{prop}
1267           
1268           
1269                 // 0 = before , 1=after 2/3 onto
1270           
1271                         GLib.debug("dropNode %s", target_data_str);
1272                 
1273                 var target_data= target_data_str.split("|");
1274           
1275                 var parent_str = target_data[0].length > 0 ? target_data[0] : "";
1276                 var pos = target_data.length > 1 ? int.parse(target_data[1]) : 2; // ontop..
1277           
1278           
1279                 Gtk.TreePath tree_path  =   parent_str.length > 0 ? new  Gtk.TreePath.from_string( parent_str ) : null;
1280                 
1281                 
1282                 
1283                 //print("add " + tp + "@" + target_data[1]  );
1284                 
1285                 JsRender.Node parentNode = null;
1286                 
1287                 Gtk.TreeIter iter_after;
1288                 Gtk.TreeIter iter_par ;
1289                 
1290                 // this appears to be done in drag_ddata_recieved as well.
1291                  if (target_data.length == 3 && target_data[2].length > 0) {
1292                          node.set_prop(new JsRender.NodeProp.special("prop", target_data[2]));
1293         
1294                 }
1295         
1296                 Gtk.TreePath expand_parent = null;
1297                 
1298                 // we only need to show the template if it's come from else where?
1299                  if (show_templates) {
1300                  
1301                      var ts = _this.main_window.windowstate.template_select;
1302                  
1303                      var new_node = ts.show(
1304                           _this.main_window, // (Gtk.Window) _this.el.get_toplevel (),
1305                          _this.main_window.windowstate.file.palete(),
1306                             node,
1307                             _this.main_window.windowstate.project);
1308                            
1309                      if (new_node == null) {
1310                          return; // do not add?
1311                      }
1312                      node = new_node;
1313                 }        
1314                 
1315                  //print("pos is %d  \n".printf(pos));
1316                 
1317                  Gtk.TreeIter n_iter; 
1318                  
1319                  if ( parent_str.length < 1) {
1320                       this.el.append(out n_iter, null); // drop at top level..
1321                       node.parent = null;
1322                       _this.main_window.windowstate.file.tree = node;
1323                       
1324                       
1325                 } else   if (pos  < 2) {
1326                     //print(target_data[1]  > 0 ? 'insert_after' : 'insert_before');
1327                     
1328                     this.el.get_iter(out iter_after, tree_path );            
1329                     this.el.iter_parent(out iter_par, iter_after);
1330                     expand_parent = this.el.get_path(iter_par);
1331                     
1332                     
1333                     // not sure why all the 'dup_object()' stuff? did it crash before?
1334                     GLib.Value value;
1335                     this.el.get_value( iter_par, 2, out value);
1336                     parentNode =  (JsRender.Node)value.dup_object();
1337                     
1338                     
1339                     this.el.get_value( iter_after, 2, out value);
1340                     var relNode =  (JsRender.Node)value.dup_object();
1341                     
1342                     if ( pos  > 0 ) {
1343                      
1344                         this.el.insert_after(out n_iter,    iter_par  , iter_after);
1345                         var ix = parentNode.items.index_of(relNode);
1346                         parentNode.items.insert(ix+1, node);
1347                         
1348                     } else {
1349                         this.el.insert_before(out n_iter,  iter_par  , iter_after);
1350                         var ix = parentNode.items.index_of(relNode);
1351                         parentNode.items.insert(ix, node);
1352          
1353                     }
1354                     node.parent = parentNode;
1355                     
1356                     
1357                     
1358                 } else {
1359                    //  print("appending to  " + parent_str);
1360                     this.el.get_iter(out iter_par, tree_path);
1361                     this.el.append(out n_iter,   iter_par );
1362                     expand_parent = this.el.get_path(iter_par);
1363                     
1364                     GLib.Value value;
1365                     this.el.get_value( iter_par, 2, out value);
1366                     parentNode =  (JsRender.Node)value.dup_object();
1367                     node.parent = parentNode;
1368                     parentNode.items.add(node);
1369                 }
1370                 
1371                 
1372                 
1373                 
1374                 // work out what kind of packing to use.. -- should be in 
1375                
1376                     
1377                     //_this.main_window.windowstate.file.palete().fillPack(node,parentNode);
1378                 _this.main_window.windowstate.file.palete().on_child_added(parentNode,node);
1379                     
1380                   
1381                 this.iterSetValues(n_iter, node);
1382                 // add the node...
1383                  
1384                 
1385                 
1386                         // load children - if it has any..
1387               
1388                 if (node.items.size > 0) {
1389                     this.load(node.items, n_iter);
1390                     _this.view.el.expand_row(this.el.get_path(n_iter), true);
1391                 } else if (expand_parent != null && !_this.view.el.is_row_expanded(expand_parent)) {
1392                    _this.view.el.expand_row(expand_parent,true);
1393                 }
1394         
1395                 //if (tp != null && (node.items.length() > 0 || pos > 1)) {
1396                 //    _this.view.el.expand_row(this.el.get_path(iter_par), true);
1397                // }
1398                 // wee need to get the empty proptypes from somewhere..
1399                 
1400                 //var olditer = this.activeIter;
1401                 this.activePath = this.el.get_path(n_iter).to_string();
1402         
1403         
1404                 // pretend button was pressed, so that we can trigger select node...
1405                 _this.view.button_is_pressed = true;
1406                 _this.view.lastEventSource = "";
1407                 _this.view.el.set_cursor(this.el.get_path(n_iter), null, false);
1408                 _this.view.button_is_pressed = false;
1409                 _this.changed();
1410              
1411                 
1412                     
1413         }
1414         public void moveNode (string target_data, Gdk.DragAction action) 
1415         {
1416            
1417            /// target_data = "path|pos");
1418            
1419            
1420             //print("MOVE NODE");
1421             // console.dump(target_data);
1422             Gtk.TreeIter old_iter;
1423             Gtk.TreeModel mod;
1424             
1425             var s = _this.view.el.get_selection();
1426             s.get_selected(out mod , out old_iter);
1427             mod.get_path(old_iter);
1428             
1429             var node = this.pathToNode(mod.get_path(old_iter).to_string());
1430             //console.dump(node);
1431             if (node == null) {
1432                 GLib.debug("moveNode: ERROR - node is null?");
1433             }
1434             
1435             
1436         
1437             // needs to drop first, otherwise the target_data 
1438             // treepath will be invalid.
1439         
1440             
1441             if ((action & Gdk.DragAction.MOVE) > 0) {
1442                     GLib.debug("REMOVING OLD NODE : " + target_data + "\n");
1443                     node.remove();
1444                     this.dropNode(target_data, node, false);
1445                     this.el.remove(ref old_iter);
1446                     
1447                     
1448                                  
1449             } else {
1450                 GLib.debug("DROPPING NODE // copy: " + target_data + "\n");
1451                 node = node.deepClone();
1452                 this.dropNode(target_data, node, false);
1453             }
1454             _this.changed();
1455             this.activePath= "";
1456             //this.updateNode(false,true);
1457         }
1458         public void updateSelected () {
1459           
1460            
1461             var s = _this.view.el.get_selection();
1462             
1463              Gtk.TreeIter iter;
1464             Gtk.TreeModel mod;
1465             
1466             
1467             
1468             if (!s.get_selected(out mod, out iter)) {
1469                 return; // nothing seleted..
1470             }
1471           
1472           GLib.Value value;
1473             this.el.get_value(iter, 2, out value);
1474             var node = (JsRender.Node)(value.get_object());
1475             
1476               this.el.set(iter, 0, node.nodeTitle(),
1477                         1, node.nodeTip(), -1
1478                 );
1479         }
1480         public string findDropNode (string treepath_str, string[] targets) {
1481         
1482             // this is used by the dragdrop code in the roo version AFAIR..
1483         
1484             //var path = treepath_str.replace(/^builder-/, '');
1485             // treemap is depreciated... - should really check if model has any entries..
1486         
1487             if (this.el.iter_n_children(null) < 1) {
1488                 //print("NO KEYS");
1489                 return "|%d".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);
1490             }
1491             //print("FIND treepath: " + path);
1492             //console.dump(this.treemap);
1493             
1494             //if (!treepath_str.match(/^builder-/)) {
1495             //    return []; // nothing!
1496             //}
1497             if (targets.length > 0 && targets[0] == "*") {
1498                 return  treepath_str;
1499             }
1500             return this.findDropNodeByPath(treepath_str,targets, -1);
1501         }
1502         public void load (Gee.ArrayList<JsRender.Node> tr, Gtk.TreeIter? iter) 
1503         {
1504             
1505                 
1506             Gtk.TreeIter citer;
1507             //this.insert(citer,iter,0);
1508            
1509             
1510             for(var i =0 ; i < tr.size; i++) {
1511                 if (iter != null) {
1512                     this.el.insert(out citer,iter,-1); // why not append?
1513                 } else {
1514                     this.el.append(out citer,null);
1515                 }
1516                 this.iterSetValues(citer, tr.get(i));
1517                 
1518          
1519                  
1520                 if (tr.get(i).items.size > 0) {
1521                     this.load(tr.get(i).items, citer);
1522                 }
1523              
1524             }
1525         
1526             
1527         }
1528         public JsRender.Node pathToNode (string path) {
1529          
1530              
1531              Gtk.TreeIter   iter;
1532              _this.model.el.get_iter_from_string(out iter, path);
1533              
1534              GLib.Value value;
1535              _this.model.el.get_value(iter, 2, out value);
1536              
1537              return (JsRender.Node)value.dup_object();
1538         
1539         }
1540     }
1541
1542     public class Xcls_maincol : Object
1543     {
1544         public Gtk.TreeViewColumn el;
1545         private Xcls_WindowLeftTree  _this;
1546
1547
1548             // my vars (def)
1549
1550         // ctor
1551         public Xcls_maincol(Xcls_WindowLeftTree _owner )
1552         {
1553             _this = _owner;
1554             _this.maincol = this;
1555             this.el = new Gtk.TreeViewColumn();
1556
1557             // my vars (dec)
1558
1559             // set gobject values
1560             this.el.title = "Node";
1561             this.el.sizing = Gtk.TreeViewColumnSizing.FIXED;
1562             this.el.expand = true;
1563             this.el.resizable = true;
1564             var child_0 = new Xcls_iconrender( _this );
1565             child_0.ref();
1566             this.el.pack_start (  child_0.el , false );
1567             var child_1 = new Xcls_renderer( _this );
1568             child_1.ref();
1569             this.el.pack_start (  child_1.el , true );
1570
1571             // init method
1572
1573             this.el.add_attribute(_this.renderer.el , "markup", 0 );
1574               this.el.add_attribute(_this.iconrender.el , "pixbuf",  3 );
1575         }
1576
1577         // user defined functions
1578     }
1579     public class Xcls_iconrender : Object
1580     {
1581         public Gtk.CellRendererPixbuf el;
1582         private Xcls_WindowLeftTree  _this;
1583
1584
1585             // my vars (def)
1586
1587         // ctor
1588         public Xcls_iconrender(Xcls_WindowLeftTree _owner )
1589         {
1590             _this = _owner;
1591             _this.iconrender = this;
1592             this.el = new Gtk.CellRendererPixbuf();
1593
1594             // my vars (dec)
1595
1596             // set gobject values
1597             this.el.width = 16;
1598         }
1599
1600         // user defined functions
1601     }
1602
1603     public class Xcls_renderer : Object
1604     {
1605         public Gtk.CellRendererText el;
1606         private Xcls_WindowLeftTree  _this;
1607
1608
1609             // my vars (def)
1610
1611         // ctor
1612         public Xcls_renderer(Xcls_WindowLeftTree _owner )
1613         {
1614             _this = _owner;
1615             _this.renderer = this;
1616             this.el = new Gtk.CellRendererText();
1617
1618             // my vars (dec)
1619
1620             // set gobject values
1621         }
1622
1623         // user defined functions
1624     }
1625
1626
1627     public class Xcls_TreeViewColumn8 : Object
1628     {
1629         public Gtk.TreeViewColumn el;
1630         private Xcls_WindowLeftTree  _this;
1631
1632
1633             // my vars (def)
1634
1635         // ctor
1636         public Xcls_TreeViewColumn8(Xcls_WindowLeftTree _owner )
1637         {
1638             _this = _owner;
1639             this.el = new Gtk.TreeViewColumn();
1640
1641             // my vars (dec)
1642
1643             // set gobject values
1644             this.el.max_width = 24;
1645             this.el.title = "Add";
1646             this.el.sizing = Gtk.TreeViewColumnSizing.FIXED;
1647             this.el.expand = false;
1648             var child_0 = new Xcls_addiconrender( _this );
1649             child_0.ref();
1650             this.el.pack_start (  child_0.el , true );
1651
1652             // init method
1653
1654             this.el.add_attribute(_this.addiconrender.el , "pixbuf",  4 );
1655         }
1656
1657         // user defined functions
1658     }
1659     public class Xcls_addiconrender : Object
1660     {
1661         public Gtk.CellRendererPixbuf el;
1662         private Xcls_WindowLeftTree  _this;
1663
1664
1665             // my vars (def)
1666
1667         // ctor
1668         public Xcls_addiconrender(Xcls_WindowLeftTree _owner )
1669         {
1670             _this = _owner;
1671             _this.addiconrender = this;
1672             this.el = new Gtk.CellRendererPixbuf();
1673
1674             // my vars (dec)
1675
1676             // set gobject values
1677             this.el.width = 16;
1678         }
1679
1680         // user defined functions
1681     }
1682
1683
1684
1685     public class Xcls_LeftTreeMenu : Object
1686     {
1687         public Gtk.Menu el;
1688         private Xcls_WindowLeftTree  _this;
1689
1690
1691             // my vars (def)
1692
1693         // ctor
1694         public Xcls_LeftTreeMenu(Xcls_WindowLeftTree _owner )
1695         {
1696             _this = _owner;
1697             _this.LeftTreeMenu = this;
1698             this.el = new Gtk.Menu();
1699
1700             // my vars (dec)
1701
1702             // set gobject values
1703             var child_0 = new Xcls_MenuItem11( _this );
1704             child_0.ref();
1705             this.el.add (  child_0.el  );
1706             var child_1 = new Xcls_MenuItem12( _this );
1707             child_1.ref();
1708             this.el.add (  child_1.el  );
1709             var child_2 = new Xcls_MenuItem13( _this );
1710             child_2.ref();
1711             this.el.add (  child_2.el  );
1712         }
1713
1714         // user defined functions
1715     }
1716     public class Xcls_MenuItem11 : Object
1717     {
1718         public Gtk.MenuItem el;
1719         private Xcls_WindowLeftTree  _this;
1720
1721
1722             // my vars (def)
1723
1724         // ctor
1725         public Xcls_MenuItem11(Xcls_WindowLeftTree _owner )
1726         {
1727             _this = _owner;
1728             this.el = new Gtk.MenuItem();
1729
1730             // my vars (dec)
1731
1732             // set gobject values
1733             this.el.label = "Delete Element";
1734
1735             //listeners
1736             this.el.activate.connect( ( ) => {
1737                 
1738                 print("ACTIVATE?");
1739                 
1740               
1741                  _this.model.deleteSelected();
1742             });
1743         }
1744
1745         // user defined functions
1746     }
1747
1748     public class Xcls_MenuItem12 : Object
1749     {
1750         public Gtk.MenuItem el;
1751         private Xcls_WindowLeftTree  _this;
1752
1753
1754             // my vars (def)
1755
1756         // ctor
1757         public Xcls_MenuItem12(Xcls_WindowLeftTree _owner )
1758         {
1759             _this = _owner;
1760             this.el = new Gtk.MenuItem();
1761
1762             // my vars (dec)
1763
1764             // set gobject values
1765             this.el.label = "Save as Template";
1766
1767             //listeners
1768             this.el.activate.connect( () => {
1769             
1770                  DialogSaveTemplate.singleton().show(
1771                         (Gtk.Window) _this.el.get_toplevel (), 
1772                         _this.main_window.windowstate.file.palete(), 
1773                         _this.getActiveElement()
1774                 );
1775                  
1776                 
1777             });
1778         }
1779
1780         // user defined functions
1781     }
1782
1783     public class Xcls_MenuItem13 : Object
1784     {
1785         public Gtk.MenuItem el;
1786         private Xcls_WindowLeftTree  _this;
1787
1788
1789             // my vars (def)
1790
1791         // ctor
1792         public Xcls_MenuItem13(Xcls_WindowLeftTree _owner )
1793         {
1794             _this = _owner;
1795             this.el = new Gtk.MenuItem();
1796
1797             // my vars (dec)
1798
1799             // set gobject values
1800             this.el.label = "Save as Module";
1801
1802             //listeners
1803             this.el.activate.connect( () => {
1804                 var node = _this.getActiveElement();
1805                  var name = DialogSaveModule.singleton().show(
1806                         (Gtk.Window) _this.el.get_toplevel (), 
1807                         _this.main_window.windowstate.project, 
1808                         node
1809                  );
1810                  if (name.length < 1) {
1811                         return;
1812               
1813                  }
1814                  node.set_prop( new JsRender.NodeProp.special("xinclude", name));
1815                  node.items.clear();
1816             
1817             
1818                 var s = _this.view.el.get_selection();
1819                 
1820                 print("GET  SELECTED?");
1821                 Gtk.TreeIter iter;
1822                 Gtk.TreeModel mod;
1823             
1824                 
1825                 if (!s.get_selected(out mod, out iter)) {
1826                     return; // nothing seleted..
1827                 }
1828                 Gtk.TreeIter citer;
1829                 var n_cn = mod.iter_n_children(iter) -1;
1830                 for (var i = n_cn; i > -1; i--) {
1831                     mod.iter_nth_child(out citer, iter, i);
1832                     
1833             
1834                     print("removing node from Tree\n");    
1835                 
1836                     _this.model.el.remove(ref citer);
1837                 }
1838                 _this.changed();
1839                 _this.node_selected(node, "tree");
1840                  
1841                 
1842             });
1843         }
1844
1845         // user defined functions
1846     }
1847
1848
1849
1850 }