1 static Xcls_WindowLeftTree _WindowLeftTree;
3 public class Xcls_WindowLeftTree : Object
6 private Xcls_WindowLeftTree _this;
8 public static Xcls_WindowLeftTree singleton()
10 if (_WindowLeftTree == null) {
11 _WindowLeftTree= new Xcls_WindowLeftTree();
13 return _WindowLeftTree;
15 public Xcls_viewwin viewwin;
16 public Xcls_view view;
17 public Xcls_keystate keystate;
18 public Xcls_drop drop;
19 public Xcls_selmodel selmodel;
20 public Xcls_model model;
21 public Xcls_maincol maincol;
22 public Xcls_LeftTreeMenu LeftTreeMenu;
25 public signal bool before_node_change ();
26 public Xcls_MainWindow? main_window;
27 public int last_error_counter;
28 public signal void changed ();
29 public signal void node_selected (JsRender.Node? node);
30 public Gee.ArrayList<Gtk.Widget>? error_widgets;
33 public Xcls_WindowLeftTree()
36 this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 );
39 this.main_window = null;
40 this.last_error_counter = -1;
41 this.error_widgets = null;
44 this.el.hexpand = true;
45 this.el.vexpand = true;
46 var child_1 = new Xcls_ListView1( _this );
48 this.el.append( child_1.el );
49 new Xcls_viewwin( _this );
50 this.el.append( _this.viewwin.el );
53 // user defined functions
54 public void updateErrors () {
55 var file = this.getActiveFile();
60 var ar = file.getErrors();
61 if (ar == null || ar.size < 1) {
62 if (this.last_error_counter != file.error_counter) {
66 this.last_error_counter = file.error_counter ;
70 if (this.last_error_counter == file.error_counter) {
74 this.error_widgets = new Gee.ArrayList<Gtk.Widget>();
75 foreach(var diag in ar) {
77 // print("get inter\n");
78 var node= file.lineToNode( (int)diag.range.start.line) ;
82 var w = node.get_data<Gtk.Widget>("tree-row");
86 this.error_widgets.add(w);
87 // always show errors.
88 var ed = diag.category.down();
89 if (ed != "err" && w.has_css_class("node-err")) {
92 if (ed == "err" && w.has_css_class("node-warn")) {
93 w.remove_css_class("node-warn");
95 if (ed == "err" && w.has_css_class("node-depr")) {
96 w.remove_css_class("node-depr");
98 if (!w.has_css_class("node-"+ ed)) {
99 w.add_css_class("node-" + ed);
105 public void onresize () {
108 //GLib.debug("Got allocation width of scrolled view %d", allocation.width );
109 // _this.maincol.el.set_max_width( _this.viewwin.el.get_width() - 32 );
111 public void removeErrors () {
112 if (this.error_widgets == null || this.error_widgets.size < 1) {
115 foreach(var child in this.error_widgets) {
117 if (child.has_css_class("node-err")) {
118 child.remove_css_class("node-err");
120 if (child.has_css_class("node-warn")) {
121 child.remove_css_class("node-warn");
124 if (child.has_css_class("node-depr")) {
125 child.remove_css_class("node-depr");
128 this.error_widgets = null;
132 var child = this.view.el.get_first_child();
134 var reading_header = true;
136 while (child != null) {
137 //GLib.debug("Got %s", child.get_type().name());
139 if (reading_header) {
142 if (child.get_type().name() != "GtkColumnListView") {
144 child = child.get_next_sibling();
147 // should be columnlistview
148 child = child.get_first_child();
152 reading_header = false;
156 if (child.has_css_class("node-err")) {
157 child.remove_css_class("node-err");
159 if (child.has_css_class("node-warn")) {
160 child.remove_css_class("node-warn");
163 if (child.has_css_class("node-depr")) {
164 child.remove_css_class("node-depr");
167 child = child.get_next_sibling();
169 //GLib.debug("Rturning null");
173 public JsRender.Node? getActiveElement () { // return path to actie node.
176 return _this.selmodel.getSelectedNode();
180 public JsRender.JsRender getActiveFile () {
181 return this.main_window.windowstate.file;
184 public class Xcls_ListView1 : Object
186 public Gtk.ListView el;
187 private Xcls_WindowLeftTree _this;
193 public Xcls_ListView1(Xcls_WindowLeftTree _owner )
196 var child_1 = new Xcls_SignalListItemFactory2( _this );
198 this.el = new Gtk.ListView( null, child_1.el );
202 // set gobject values
205 // user defined functions
207 public class Xcls_SignalListItemFactory2 : Object
209 public Gtk.SignalListItemFactory el;
210 private Xcls_WindowLeftTree _this;
216 public Xcls_SignalListItemFactory2(Xcls_WindowLeftTree _owner )
219 this.el = new Gtk.SignalListItemFactory();
223 // set gobject values
226 // user defined functions
230 public class Xcls_viewwin : Object
232 public Gtk.ScrolledWindow el;
233 private Xcls_WindowLeftTree _this;
239 public Xcls_viewwin(Xcls_WindowLeftTree _owner )
242 _this.viewwin = this;
243 this.el = new Gtk.ScrolledWindow();
247 // set gobject values
248 this.el.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC;
249 this.el.has_frame = true;
250 this.el.hexpand = true;
251 this.el.vexpand = true;
252 this.el.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC;
253 new Xcls_view( _this );
254 this.el.child = _this.view.el;
255 new Xcls_LeftTreeMenu( _this );
258 // user defined functions
260 public class Xcls_view : Object
262 public Gtk.ColumnView el;
263 private Xcls_WindowLeftTree _this;
267 public bool blockChanges;
268 public bool headers_visible;
269 public string lastEventSource;
270 public bool button_is_pressed;
271 public Gtk.CssProvider css;
272 public JsRender.Node? dragNode;
275 public Xcls_view(Xcls_WindowLeftTree _owner )
279 new Xcls_selmodel( _this );
280 this.el = new Gtk.ColumnView( _this.selmodel.el );
283 this.blockChanges = false;
284 this.headers_visible = false;
285 this.lastEventSource = "";
286 this.button_is_pressed = false;
287 this.dragNode = null;
289 // set gobject values
290 this.el.name = "left-tree-view";
291 this.el.hexpand = false;
292 this.el.vexpand = true;
293 var child_2 = new Xcls_GestureClick5( _this );
295 this.el.add_controller( child_2.el );
296 var child_3 = new Xcls_GestureClick6( _this );
298 this.el.add_controller( child_3.el );
299 var child_4 = new Xcls_DragSource7( _this );
301 this.el.add_controller( child_4.el );
302 var child_5 = new Xcls_EventControllerKey8( _this );
304 this.el.add_controller( child_5.el );
305 new Xcls_keystate( _this );
306 this.el.add_controller( _this.keystate.el );
307 new Xcls_drop( _this );
308 this.el.add_controller( _this.drop.el );
309 new Xcls_maincol( _this );
310 this.el.append_column ( _this.maincol.el );
311 var child_9 = new Xcls_ColumnViewColumn15( _this );
313 this.el.append_column ( child_9.el );
319 this.css = new Gtk.CssProvider();
321 this.css.load_from_string("
322 #left-tree-view { font-size: 12px;}
323 .drag-over { background-color:#88a3bc; }
325 border-bottom-width: 5px;
326 border-bottom-style: solid;
327 border-bottom-color: #88a3bc;
330 border-top-width: 5px;
331 border-top-style: solid;
332 border-top-color: #88a3bc;
335 border-top-width: 5px;
336 border-top-style: solid;
337 border-top-color: red;
338 border-bottom-width: 5px;
339 border-bottom-style: solid;
340 border-bottom-color: red;
343 border-top-width: 5px;
344 border-top-style: solid;
345 border-top-color: #ABF4EB;
346 border-bottom-width: 5px;
347 border-bottom-style: solid;
348 border-bottom-color: #ABF4EB;
351 border-top-width: 5px;
352 border-top-style: solid;
353 border-top-color: #EEA9FF;
354 border-bottom-width: 5px;
355 border-bottom-style: solid;
356 border-bottom-color: #EEA9FF;
359 #left-tree-view indent {
360 -gtk-icon-size : 2px;
362 #left-tree-view indent:nth-last-child(2) {
367 Gtk.StyleContext.add_provider_for_display(
368 this.el.get_display(),
370 Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
377 // user defined functions
378 public Gtk.Widget? getRowWidgetAt (double x, double y, out string pos) {
381 var w = this.el.pick(x, y, Gtk.PickFlags.DEFAULT);
382 //GLib.debug("got widget %s", w == null ? "nothing" : w.get_type().name());
387 var row = w.get_ancestor(GLib.Type.from_name("GtkColumnViewRowWidget"));
392 //GLib.debug("got colview %s", row == null ? "nothing" : row.get_type().name());
396 //GLib.debug("row number is %d", rn);
397 //GLib.debug("click %d, %d", (int)x, (int)y);
399 Graphene.Rect bounds;
400 row.compute_bounds(this.el, out bounds);
401 //GLib.debug("click x=%d, y=%d, w=%d, h=%d",
402 // (int)bounds.get_x(), (int)bounds.get_y(),
403 // (int)bounds.get_width(), (int)bounds.get_height()
405 var ypos = y - bounds.get_y();
406 //GLib.debug("rel ypos = %d", (int)ypos);
407 var rpos = 100.0 * (ypos / bounds.get_height());
408 //GLib.debug("rel pos = %d %%", (int)rpos);
413 } else if (rpos < 20) {
418 public int getColAt (double x, double y) {
421 from https://discourse.gnome.org/t/gtk4-finding-a-row-data-on-gtkcolumnview/8465
424 //Gtk.Allocation alloc = { 0, 0, 0, 0 };
425 //GLib.debug("Cehck %d, %d", x,y);
426 var child = this.el.get_first_child();
430 while (child != null) {
432 if (child.get_type().name() == "GtkColumnViewRowWidget") {
433 child = child.get_first_child();
437 //child.get_allocation(out alloc);
438 if (x < (child.get_width() + offx)) {
442 //offx += child.get_width();
444 //child = child.get_next_sibling();
451 public int getRowAtOLD (double x, double y, out string pos) {
454 var w = this.el.pick(x, y, Gtk.PickFlags.DEFAULT);
455 //GLib.debug("got widget %s", w == null ? "nothing" : w.get_type().name());
460 var row= w.get_ancestor(GLib.Type.from_name("GtkColumnViewRowWidget"));
465 //GLib.debug("got colview %s", row == null ? "nothing" : row.get_type().name());
470 while (cr.get_prev_sibling() != null) {
472 cr = cr.get_prev_sibling();
475 //GLib.debug("row number is %d", rn);
476 //GLib.debug("click %d, %d", (int)x, (int)y);
478 Graphene.Rect bounds;
479 row.compute_bounds(this.el, out bounds);
480 //GLib.debug("click x=%d, y=%d, w=%d, h=%d",
481 // (int)bounds.get_x(), (int)bounds.get_y(),
482 // (int)bounds.get_width(), (int)bounds.get_height()
484 var ypos = y - bounds.get_y();
485 //GLib.debug("rel ypos = %d", (int)ypos);
486 var rpos = 100.0 * (ypos / bounds.get_height());
487 //GLib.debug("rel pos = %d %%", (int)rpos);
492 } else if (rpos < 20) {
497 public Gtk.Widget? getWidgetAtRowBROKE (uint row) {
500 from https://discourse.gnome.org/t/gtk4-finding-a-row-data-on-gtkcolumnview/8465
501 var colview = gesture.widget;
502 var line_no = check_list_widget(colview, x,y);
504 var item = colview.model.get_item(line_no);
508 //GLib.debug("Get Widget At Row %d", (int)row);
509 var child = this.el.get_first_child();
511 var reading_header = true;
513 while (child != null) {
514 //GLib.debug("Got %s", child.get_type().name());
516 if (reading_header) {
519 if (child.get_type().name() != "GtkColumnListView") {
521 child = child.get_next_sibling();
524 // should be columnlistview
525 child = child.get_first_child();
529 reading_header = false;
536 if (line_no == row) {
537 //GLib.debug("Returning widget %s", child.get_type().name());
538 return (Gtk.Widget)child;
540 child = child.get_next_sibling();
542 //GLib.debug("Rturning null");
547 public class Xcls_GestureClick5 : Object
549 public Gtk.GestureClick el;
550 private Xcls_WindowLeftTree _this;
556 public Xcls_GestureClick5(Xcls_WindowLeftTree _owner )
559 this.el = new Gtk.GestureClick();
563 // set gobject values
566 this.el.released.connect( (n_press, x, y) => {
568 _this.view.button_is_pressed = false;
572 this.el.pressed.connect( (n_press, x, y) => {
574 //console.log("button press?");
576 //this.el.set_state(Gtk.EventSequenceState.CLAIMED);
580 _this.view.button_is_pressed = true;
582 _this.view.lastEventSource = "tree";
583 if (! _this.before_node_change() ) {
584 GLib.debug("before_node_change return false");
588 // nothing there -show dialog
589 if (_this.model.el.get_n_items() < 1) {
590 _this.main_window.windowstate.showAddObject(_this.view.el, null);
591 GLib.debug("no items");
595 var row_widget = _this.view.getRowWidgetAt(x,y, out pos );
596 if (row_widget == null) {
597 GLib.debug("no row selected items");
601 var node = row_widget.get_data<JsRender.Node>("node");
603 GLib.warning("No node found bound to widget");
609 if (_this.view.getColAt(x,y) > 0 ) {
610 GLib.debug("add colum clicked.");
611 var fqn = node.fqn();
612 var cn = _this.main_window.windowstate.project.palete.getChildList(fqn, false);
617 _this.main_window.windowstate.leftTreeBeforeChange();
618 //_this.view.el.get_selection().select_path(res);
619 GLib.debug("Button Pressed - start show window");
620 _this.main_window.windowstate.showAddObject(_this.view.el, node);
621 GLib.debug("Button Pressed - finsihed show window");
630 // user defined functions
633 public class Xcls_GestureClick6 : Object
635 public Gtk.GestureClick el;
636 private Xcls_WindowLeftTree _this;
642 public Xcls_GestureClick6(Xcls_WindowLeftTree _owner )
645 this.el = new Gtk.GestureClick();
649 // set gobject values
653 this.el.pressed.connect( (n_press, x, y) => {
658 if (_this.model.el.get_n_items() < 1) {
660 GLib.debug("no items");
664 var row_widget = _this.view.getRowWidgetAt(x,y, out pos );
665 if (row_widget == null) {
666 GLib.debug("no row selected items");
670 var node = row_widget.get_data<JsRender.Node>("node");
672 GLib.warning("No node found from widget");
677 _this.model.selectNode(node);
681 GLib.debug("Prssed %d", (int) this.el.get_current_button());
682 //_this.deletemenu.el.set_parent(_this.view.el);
683 _this.LeftTreeMenu.el.set_parent(_this.view.el);
686 //Gtk.Allocation rect;
687 //_this.view.el.get_allocation(out rect);
688 //_this.deletemenu.el.set_has_arrow(false);
689 _this.LeftTreeMenu.el.set_position(Gtk.PositionType.BOTTOM);
692 _this.LeftTreeMenu.el.set_offset(
694 (int)y - (int)_this.view.el.get_height());
696 _this.LeftTreeMenu.el.popup();
701 // user defined functions
704 public class Xcls_DragSource7 : Object
706 public Gtk.DragSource el;
707 private Xcls_WindowLeftTree _this;
713 public Xcls_DragSource7(Xcls_WindowLeftTree _owner )
716 this.el = new Gtk.DragSource();
720 // set gobject values
721 this.el.actions = Gdk.DragAction.COPY | Gdk.DragAction.MOVE ;
724 this.el.drag_cancel.connect( (drag, reason) => {
726 _this.view.dragNode = null;
729 this.el.prepare.connect( (x, y) => {
733 /// ( drag_context, data, info, time) => {
736 //print("drag-data-get");
737 var ndata = _this.selmodel.getSelectedNode();
739 GLib.debug("return empty string - no selection..");
745 //data.set_text(tp,tp.length);
747 var str = ndata.toJsonString();
748 GLib.debug("prepare store: %s", str);
749 GLib.Value ov = GLib.Value(typeof(string));
751 var cont = new Gdk.ContentProvider.for_value(ov);
753 GLib.Value v = GLib.Value(typeof(string));
754 //var str = drop.read_text( [ "text/plain" ] 0);
756 cont.get_value(ref v);
759 GLib.debug("set %s", v.get_string());
765 this.el.drag_begin.connect( ( drag ) => {
766 GLib.debug("SOURCE: drag-begin");
768 // find what is selected in our tree...
769 var data = _this.selmodel.getSelectedNode();
773 _this.view.dragNode = data;
774 var xname = data.fqn();
775 GLib.debug ("XNAME IS %s", xname);
777 var widget = data.get_data<Gtk.Widget>("tree-row");
780 var paintable = new Gtk.WidgetPaintable(widget);
781 this.el.set_icon(paintable, 0,0);
785 this.el.drag_end.connect( (drag, delete_data) => {
787 _this.view.dragNode = null;
791 // user defined functions
794 public class Xcls_EventControllerKey8 : Object
796 public Gtk.EventControllerKey el;
797 private Xcls_WindowLeftTree _this;
803 public Xcls_EventControllerKey8(Xcls_WindowLeftTree _owner )
806 this.el = new Gtk.EventControllerKey();
810 // set gobject values
813 this.el.key_pressed.connect( (keyval, keycode, state) => {
817 if (keyval != Gdk.Key.Delete && keyval != Gdk.Key.BackSpace) {
821 _this.model.deleteSelected();
827 // user defined functions
830 public class Xcls_keystate : Object
832 public Gtk.EventControllerKey el;
833 private Xcls_WindowLeftTree _this;
840 public Xcls_keystate(Xcls_WindowLeftTree _owner )
843 _this.keystate = this;
844 this.el = new Gtk.EventControllerKey();
849 // set gobject values
852 this.el.key_released.connect( (keyval, keycode, state) => {
853 GLib.debug("key release %d, %d, %d" , (int) keyval, (int) keycode, state);
854 if (keyval == Gdk.Key.Shift_L || keyval == Gdk.Key.Shift_R) {
857 //GLib.debug("set state %d , shift = %d", (int)this.el.get_current_event_state(), Gdk.ModifierType.SHIFT_MASK);
862 this.el.key_pressed.connect( (keyval, keycode, state) => {
864 if (keyval == Gdk.Key.Shift_L || keyval == Gdk.Key.Shift_R) {
871 // user defined functions
874 public class Xcls_drop : Object
876 public Gtk.DropTarget el;
877 private Xcls_WindowLeftTree _this;
881 public Gtk.Widget? highlightWidget;
882 public JsRender.Node? lastDragNode;
883 public string lastDragString;
886 public Xcls_drop(Xcls_WindowLeftTree _owner )
890 this.el = new Gtk.DropTarget ( typeof(string) ,
891 Gdk.DragAction.COPY | Gdk.DragAction.MOVE );
894 this.highlightWidget = null;
895 this.lastDragNode = null;
896 this.lastDragString = "\"\"";
898 // set gobject values
901 this.el.accept.connect( (drop) => {
903 GLib.debug("got DropTarget:accept");
905 // NOT REALLY NEEDED? = put stuff in drop?
908 /* ( ctx, x, y, time) => {
909 //Seed.print("TARGET: drag-drop");
912 var src = Gtk.drag_get_source_widget(ctx);
914 if (src != this.el) {
918 this.drag_in_motion = false;
919 // request data that will be recieved by the recieve...
922 this.el, // will receive 'drag-data-received' signal
923 ctx, // represents the current state of the DnD
924 Gdk.Atom.intern("application/json",true), // the target type we want
929 // No target offered by source => error
935 // handle drop around self..
939 //print("GETTING POS");
943 Gtk.TreeViewDropPosition pos;
944 var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);
946 // if there are not items in the tree.. the we have to set isOver to true for anything..
948 if (_this.model.el.iter_n_children(null) < 1) {
949 print("got NO children?\n");
952 pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;
957 //var action = Gdk.DragAction.COPY;
958 // unless we are copying!!! ctl button..
960 var action = (ctx.get_actions() & Gdk.DragAction.MOVE) > 0 ?
961 Gdk.DragAction.COPY : Gdk.DragAction.MOVE ;
962 // Gdk.DragAction.MOVE : Gdk.DragAction.COPY ;
965 if (_this.model.el.iter_n_children(null) < 1) {
966 // no children.. -- asume it's ok..
968 targetData = "|%d|".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);
970 // continue through to allow drop...
978 //print("ISOVER? " + isOver);
981 Gtk.drag_finish (ctx, false, false, time); // drop failed..
982 return true; // not over apoint!?! - no action on drop or motion..
985 // drag node is parent of child..
986 //console.log("SRC TREEPATH: " + src.treepath);
987 //console.log("TARGET TREEPATH: " + data.path.to_string());
989 // nned to check a few here..
990 //Gtk.TreeViewDropPosition.INTO_OR_AFTER
991 //Gtk.TreeViewDropPosition.INTO_OR_BEFORE
992 //Gtk.TreeViewDropPosition.AFTER
993 //Gtk.TreeViewDropPosition.BEFORE
995 // locally dragged items to not really use the
996 var selection_text = this.dragData;
1000 if (selection_text == null || selection_text.length < 1) {
1001 //print("Error - drag selection text returned NULL");
1003 Gtk.drag_finish (ctx, false, false, time); // drop failed..
1004 return true; /// -- fixme -- this is not really correct..
1007 // see if we are dragging into ourself?
1008 print ("got selection text of " + selection_text);
1010 var target_path = path.to_string();
1011 //print("target_path="+target_path);
1014 if (selection_text == target_path) {
1015 print("self drag ?? == we should perhaps allow copy onto self..\n");
1017 Gtk.drag_finish (ctx, false, false, time); // drop failed..
1019 return true; /// -- fixme -- this is not really correct..
1024 //print("DUMPING DATA");
1025 //console.dump(data);
1028 //print(data.path.to_string() +' => '+ data.pos);
1030 // dropList is a list of xtypes that this node could be dropped on.
1031 // it is set up when we start to drag..
1034 targetData = _this.model.findDropNodeByPath( path.to_string(), this.dropList, pos);
1036 print("targetDAta: " + targetData +"\n");
1038 if (targetData.length < 1) {
1039 //print("Can not find drop node path");
1041 Gtk.drag_finish (ctx, false, false, time); // drop failed..
1047 // continue on to allow drop..
1049 // at this point, drag is not in motion... -- as checked above... - so it's a real drop event..
1052 var delete_selection_data = false;
1054 if (action == Gdk.DragAction.ASK) {
1055 // Ask the user to move or copy, then set the ctx action.
1058 if (action == Gdk.DragAction.MOVE) {
1059 delete_selection_data = true;
1062 // drag around.. - reorder..
1063 _this.model.moveNode(targetData, action);
1069 // we can send stuff to souce here...
1072 // do we always say failure, so we handle the reall drop?
1073 Gtk.drag_finish (ctx, false, false,time); //delete_selection_data, time);
1086 this.el.motion.connect( ( x, y) => {
1088 var is_shift = _this.keystate.is_shift > 0;
1090 //GLib.debug("shift is %s", _this.keystate.is_shift > 0 ? "SHIFT" : "-");
1091 string pos; // over / before / after..
1093 //GLib.debug("got drag motion");
1095 GLib.Value v = GLib.Value(typeof(string));
1096 //var str = drop.read_text( [ "text/plain" ] 0);
1097 var cont = this.el.current_drop.get_drag().content ;
1099 cont.get_value(ref v);
1100 } catch (GLib.Error e) {
1101 // GLib.debug("failed to get drag value");
1102 return Gdk.DragAction.COPY;
1106 //GLib.debug("got %s", v.get_string());
1108 if (this.lastDragString != v.get_string() || this.lastDragNode == null) {
1109 // still dragging same node
1111 this.lastDragNode = new JsRender.Node();
1112 this.lastDragNode.loadFromJsonString(v.get_string(), 1);
1116 var drop_on_to = _this.main_window.windowstate.file.palete().getDropList(
1117 this.lastDragNode.fqn());
1120 foreach(var dp in drop_on_to) {
1123 //GLib.debug("droplist: %s", string.joinv(", ", str));
1126 // if there are not items in the tree.. the we have to set isOver to true for anything..
1128 if (_this.model.el.n_items < 1) {
1129 // FIXME check valid drop types?
1130 if (drop_on_to.contains("*top")) {
1131 this.addHighlight(_this.view.el, "over");
1133 this.addHighlight(null, "");
1136 return Gdk.DragAction.COPY; // no need to highlight?
1143 // if path of source and dest are inside each other..
1144 // need to add source info to drag?
1146 var row_widget = _this.view.getRowWidgetAt( x,y, out pos);
1147 // var row = _this.view.getRowAt(x,y, out pos);
1148 //GLib.debug("check is over %d, %d, %s", (int)x,(int)y, pos);
1150 if (row_widget == null) {
1151 this.addHighlight(null, "");
1152 return Gdk.DragAction.COPY;
1154 var node = row_widget.get_data<JsRender.Node>("node");
1156 //GLib.debug("Drop over node: %s", node.fqn());
1159 if (pos == "above" || pos == "below") {
1160 if (node.parent == null) {
1161 //GLib.debug("no parent try center");
1165 if (!drop_on_to.contains(node.parent.fqn())) {
1166 //GLib.debug("drop on does not contain %s - try center" , node.parent.fqn());
1169 //GLib.debug("drop contains %s - using %s" , node.parent.fqn(), pos);
1170 if (_this.view.dragNode != null && is_shift) {
1171 if (node.parent.oid == _this.view.dragNode.oid || node.parent.has_parent(_this.view.dragNode)) {
1172 GLib.debug("shift drop not self not allowed");
1173 this.addHighlight(null, "");
1174 return Gdk.DragAction.COPY;
1187 if (pos == "over") {
1188 if (!drop_on_to.contains(node.fqn())) {
1189 //GLib.debug("drop on does not contain %s - try center" , node.fqn());
1190 this.addHighlight(null, "");
1191 return is_shift ? Gdk.DragAction.MOVE : Gdk.DragAction.COPY;
1193 if (_this.view.dragNode != null && is_shift) {
1194 if (node.oid == _this.view.dragNode.oid || node.has_parent(_this.view.dragNode)) {
1195 //GLib.debug("shift drop not self not allowed");
1196 this.addHighlight(null, "");
1197 return Gdk.DragAction.COPY;
1204 // _this.view.highlightDropPath("", (Gtk.TreeViewDropPosition)0);
1206 this.addHighlight(row_widget, pos);
1207 return is_shift ? Gdk.DragAction.MOVE : Gdk.DragAction.COPY;
1209 this.el.leave.connect( ( ) => {
1210 this.addHighlight(null,"");
1213 this.el.drop.connect( (v, x, y) => {
1215 // must get the pos before we clear the hightlihg.
1217 var row_widget = _this.view.getRowWidgetAt(x,y, out pos);
1218 this.addHighlight(null,"");
1220 var is_shift = _this.keystate.is_shift > 0;
1223 // -- get position..
1224 if (this.lastDragString != v.get_string() || this.lastDragNode == null) {
1225 // still dragging same node
1227 this.lastDragNode = new JsRender.Node();
1228 this.lastDragNode.loadFromJsonString(v.get_string(), 1);
1233 var dropNode = new JsRender.Node();
1234 dropNode.loadFromJsonString(v.get_string(), 2);
1235 GLib.debug("dropped node %s", dropNode.toJsonString());
1238 var drop_on_to = _this.main_window.windowstate.file.palete().getDropList(dropNode.fqn());
1240 // if there are not items in the tree.. the we have to set isOver to true for anything..
1242 if (_this.model.el.n_items < 1) {
1243 // FIXME check valid drop types?
1244 if (!drop_on_to.contains("*top")) {
1245 GLib.debug("drop on to list does not contain top?");
1248 // add new node to top..
1249 GLib.debug("adding to top");
1251 var m = (GLib.ListStore) _this.model.el.model;
1252 _this.main_window.windowstate.file.tree = dropNode;
1253 dropNode.updated_count++;
1256 _this.model.selectNode(dropNode);
1258 _this.node_selected(dropNode);
1259 return true; // no need to highlight?
1266 if (row_widget == null) {
1267 GLib.debug("could not get row %d,%d, %s", (int)x,(int)y,pos);
1268 return false; //Gdk.DragAction.COPY;
1271 var node = row_widget.get_data<JsRender.Node>("node");
1273 if (pos == "above" || pos == "below") {
1274 if (node.parent == null) {
1277 if (!drop_on_to.contains(node.parent.fqn())) {
1280 GLib.debug("drop contains %s - using %s" , node.parent.fqn(), pos);
1281 if (_this.view.dragNode != null && is_shift) {
1282 if (node.parent.oid == _this.view.dragNode.oid || node.parent.has_parent(_this.view.dragNode)) {
1283 GLib.debug("shift drop not self not allowed");
1294 if (pos == "over") {
1295 if (!drop_on_to.contains(node.fqn())) {
1296 GLib.debug("drop on does not contain %s - try center" , node.fqn());
1300 if (node.oid == _this.view.dragNode.oid || node.has_parent(_this.view.dragNode)) {
1301 GLib.debug("shift drop not self not allowed");
1309 if (is_shift && _this.view.dragNode != null) {
1310 _this.model.selectNode(null);
1311 _this.view.dragNode.remove();
1313 node.appendChild(dropNode);
1314 dropNode.updated_count++;
1315 _this.model.selectNode(dropNode);
1321 GLib.debug("Above - insertBefore");
1324 if (is_shift && _this.view.dragNode != null) {
1325 _this.model.selectNode(null);
1326 _this.view.dragNode.remove();
1328 node.parent.insertBefore(dropNode, node);
1329 dropNode.updated_count++;
1330 _this.model.selectNode(dropNode);
1335 GLib.debug("Below - insertAfter");
1336 if (is_shift && _this.view.dragNode != null) {
1337 _this.model.selectNode(null);
1338 _this.view.dragNode.remove();
1342 node.parent.insertAfter(dropNode, node);
1343 dropNode.updated_count++;
1344 _this.model.selectNode(dropNode);
1350 // should not happen
1362 // user defined functions
1363 public void addHighlight (Gtk.Widget? w, string hl) {
1364 if (this.highlightWidget != null) {
1365 var ww = this.highlightWidget;
1366 //GLib.debug("clear drag from previous highlight");
1367 if (ww.has_css_class("drag-below")) {
1368 ww.remove_css_class("drag-below");
1370 if (ww.has_css_class("drag-above")) {
1371 ww.remove_css_class("drag-above");
1373 if (ww.has_css_class("drag-over")) {
1374 ww.remove_css_class("drag-over");
1378 //GLib.debug("add drag=%s to widget", hl);
1379 if (!w.has_css_class("drag-" + hl)) {
1380 w.add_css_class("drag-" + hl);
1383 this.highlightWidget = w;
1387 public class Xcls_selmodel : Object
1389 public Gtk.SingleSelection el;
1390 private Xcls_WindowLeftTree _this;
1396 public Xcls_selmodel(Xcls_WindowLeftTree _owner )
1399 _this.selmodel = this;
1400 new Xcls_model( _this );
1401 this.el = new Gtk.SingleSelection( _this.model.el );
1405 // set gobject values
1406 this.el.can_unselect = true;
1409 this.el.selection_changed.connect( (position, n_items) => {
1413 //if (!this.button_is_pressed && !this.key_is_pressed) {
1414 // then event was started by some other action
1415 // which should manually trigger all the events..
1416 // print("SKIPPING select - no button or key pressed\n");
1421 if (_this.view.blockChanges) { // probably not needed..
1422 GLib.debug("SKIPPING select - blockchanges set..");
1426 if (!_this.before_node_change( ) ) {
1427 _this.view.blockChanges = true;
1428 _this.selmodel.el.unselect_all();
1429 _this.view.blockChanges = false;
1433 if (_this.main_window.windowstate.file == null) {
1434 GLib.debug("SKIPPING select windowstate file is not set...");
1438 //var render = this.get('/LeftTree').getRenderer();
1439 GLib.debug("LEFT TREE -> view -> selection changed called");
1442 // -- it appears that the selection is not updated.
1443 // select the node...
1444 //_this.selmodel.el.set_selected(row);
1446 GLib.debug("LEFT TREE -> view -> selection changed TIMEOUT CALLED");
1448 var snode = _this.selmodel.getSelectedNode();
1449 if (snode == null) {
1451 GLib.debug("selected rows < 1");
1452 //??this.model.load( false);
1453 _this.node_selected(null);
1461 GLib.debug ("calling left_tree.node_selected %s", snode.toJsonString());
1462 _this.node_selected(snode);
1467 // no need to scroll. it's in the view as we clicked on it.
1468 // _this.view.el.scroll_to_cell(new Gtk.TreePath.from_string(_this.model.activePath), null, true, 0.1f,0.0f);
1474 // user defined functions
1475 public JsRender.Node? getSelectedNode () {
1476 if (this.el.selected_item == null) {
1481 var tr = (Gtk.TreeListRow)this.el.selected_item;
1483 return (JsRender.Node)tr.get_item();
1486 public JsRender.Node getNodeAt (uint row) {
1488 var tr = (Gtk.TreeListRow)this.el.get_item(row);
1490 var a = tr.get_item();;
1491 GLib.debug("get_item (2) = %s", a.get_type().name());
1494 return (JsRender.Node)tr.get_item();
1498 public class Xcls_model : Object
1500 public Gtk.TreeListModel el;
1501 private Xcls_WindowLeftTree _this;
1507 public Xcls_model(Xcls_WindowLeftTree _owner )
1511 this.el = this.updateModel(null);
1515 // set gobject values
1518 // user defined functions
1519 public void loadFile (JsRender.JsRender f) {
1522 _this.drop.highlightWidget = null;
1524 var m = (GLib.ListStore) this.el.model;
1526 _this.main_window.windowstate.leftTreeNodeSelected(null);
1528 _this.main_window.windowstate.file = f;
1529 _this.last_error_counter = -1;
1531 if (f.tree == null) {
1538 // if it's still null?
1539 if (f.tree == null) {
1540 _this.main_window.windowstate.showAddObject(_this.view.el, null);
1541 _this.updateErrors();
1545 _this.updateErrors();
1547 _this.selmodel.el.set_selected(Gtk.INVALID_LIST_POSITION);
1553 public int nodeToRow (JsRender.Node node)
1556 var s = _this.view.el.model as Gtk.SingleSelection;
1557 for (var i = 0; i < s.n_items; i++) {
1558 //GLib.debug("check node %s", s.get_item(i).get_type().name());
1559 var lr = s.get_item(i) as Gtk.TreeListRow;
1560 //GLib.debug("check node %s", lr.get_item().get_type().name());
1561 var nn = (lr.get_item() as JsRender.Node);
1562 if (nn != null && nn.oid == node.oid) {
1571 public void deleteSelected () {
1575 var node = _this.selmodel.getSelectedNode();
1579 GLib.debug("delete Selected - no node slected?");
1582 _this.selmodel.el.unselect_all();
1583 if (node.parent != null) {
1585 GLib.debug("delete Selected - done");
1589 this.updateModel(null);
1590 _this.main_window.windowstate.file.tree = null;
1592 _this.node_selected(null);
1594 print("DELETE SELECTED?");
1595 //_this.view.blockChanges = true;
1596 print("GET SELECTION?");
1598 var s = _this.view.el.get_selection();
1600 print("GET SELECTED?");
1605 if (!s.get_selected(out mod, out iter)) {
1606 return; // nothing seleted..
1611 this.activePath= "";
1612 print("GET vnode value?");
1615 this.el.get_value(iter, 2, out value);
1616 var data = (JsRender.Node)(value.get_object());
1617 print("removing node from Render\n");
1618 if (data.parent == null) {
1619 _this.main_window.windowstate.file.tree = null;
1623 print("removing node from Tree\n");
1625 this.el.remove(ref iter);
1635 this.activePath= ""; // again!?!?
1636 //this.changed(null,true);
1640 _this.view.blockChanges = false;
1643 public Gtk.TreeListModel updateModel (GLib.ListStore? m) {
1644 this.el = new Gtk.TreeListModel(
1645 m != null ? m : new GLib.ListStore(typeof(JsRender.Node)), //..... << that's our store..
1649 return ((JsRender.Node)item).childstore;
1653 if (_this.selmodel.el == null) {
1656 _this.selmodel.el.set_model(this.el);
1659 public void selectNode (JsRender.Node? node)
1661 var s = _this.view.el.model as Gtk.SingleSelection;
1663 s.selected=Gtk.INVALID_LIST_POSITION;
1666 var row = this.nodeToRow(node);
1671 GLib.debug("Could not find node");
1672 s.selected=Gtk.INVALID_LIST_POSITION;
1675 GLib.debug("Select %d", row);
1676 s.set_selected(row);
1677 _this.view.el.scroll_to(row, null, Gtk.ListScrollFlags.SELECT, null);
1678 //_this.node_selected(node);
1685 public class Xcls_maincol : Object
1687 public Gtk.ColumnViewColumn el;
1688 private Xcls_WindowLeftTree _this;
1694 public Xcls_maincol(Xcls_WindowLeftTree _owner )
1697 _this.maincol = this;
1698 var child_1 = new Xcls_SignalListItemFactory14( _this );
1700 this.el = new Gtk.ColumnViewColumn( "Property", child_1.el );
1704 // set gobject values
1705 this.el.id = "maincol";
1706 this.el.expand = true;
1707 this.el.resizable = true;
1710 // user defined functions
1712 public class Xcls_SignalListItemFactory14 : Object
1714 public Gtk.SignalListItemFactory el;
1715 private Xcls_WindowLeftTree _this;
1721 public Xcls_SignalListItemFactory14(Xcls_WindowLeftTree _owner )
1724 this.el = new Gtk.SignalListItemFactory();
1728 // set gobject values
1731 this.el.setup.connect( (listitem) => {
1733 var expand = new Gtk.TreeExpander();
1735 expand.set_indent_for_depth(true);
1736 expand.set_indent_for_icon(true);
1737 var hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL,0);
1738 var icon = new Gtk.Image();
1739 var lbl = new Gtk.Label("");
1740 lbl.use_markup = true;
1741 lbl.ellipsize = Pango.EllipsizeMode.END;
1743 icon.margin_end = 4;
1744 lbl.justify = Gtk.Justification.LEFT;
1747 // listitem.activatable = true; ??
1751 expand.set_child(hbox);
1752 ((Gtk.ListItem)listitem).set_child(expand);
1755 this.el.bind.connect( (listitem) => {
1756 // GLib.debug("listitme is is %s", ((Gtk.ListItem)listitem).get_type().name());
1758 //var expand = (Gtk.TreeExpander) ((Gtk.ListItem)listitem).get_child();
1759 var expand = (Gtk.TreeExpander) ((Gtk.ListItem)listitem).get_child();
1762 var hbox = (Gtk.Box) expand.child;
1765 var img = (Gtk.Image) hbox.get_first_child();
1766 var lbl = (Gtk.Label) img.get_next_sibling();
1768 var lr = (Gtk.TreeListRow)((Gtk.ListItem)listitem).get_item();
1769 var node = (JsRender.Node) lr.get_item();
1770 if (node == null || node.fqn() == "") {
1774 node.set_data<Gtk.Widget>("tree-row", expand.get_parent().get_parent());
1775 expand.get_parent().get_parent().set_data<JsRender.Node>("node", node);
1777 //GLib.debug("node is %s", node.get_type().name());
1778 // was item (1) in old layout
1783 var ic = Gtk.IconTheme.get_for_display(_this.el.get_display());
1784 var clsname = node.fqn();
1786 var clsb = clsname.split(".");
1787 var sub = clsb.length > 1 ? clsb[1].down() : "";
1789 var fn = "/usr/share/glade/pixmaps/hicolor/16x16/actions/widget-gtk-" + sub + ".png";
1793 if (FileUtils.test (fn, FileTest.IS_REGULAR)) {
1794 img.set_from_file(fn);
1797 img.set_from_paintable(
1799 "media-playback-stop", null, 16,1,
1800 Gtk.TextDirection.NONE, 0
1804 } catch (GLib.Error e) {}
1806 expand.set_hide_expander( !node.hasChildren() );
1807 expand.set_list_row(lr);
1809 node.bind_property("iconResourceName",
1811 GLib.BindingFlags.SYNC_CREATE);
1813 node.bind_property("nodeTitleProp",
1815 GLib.BindingFlags.SYNC_CREATE);
1816 node.bind_property("nodeTipProp",
1817 lbl, "tooltip_markup",
1818 GLib.BindingFlags.SYNC_CREATE);
1824 // user defined functions
1828 public class Xcls_ColumnViewColumn15 : Object
1830 public Gtk.ColumnViewColumn el;
1831 private Xcls_WindowLeftTree _this;
1837 public Xcls_ColumnViewColumn15(Xcls_WindowLeftTree _owner )
1840 var child_1 = new Xcls_SignalListItemFactory16( _this );
1842 this.el = new Gtk.ColumnViewColumn( "Add", child_1.el );
1846 // set gobject values
1847 this.el.fixed_width = 25;
1850 // user defined functions
1852 public class Xcls_SignalListItemFactory16 : Object
1854 public Gtk.SignalListItemFactory el;
1855 private Xcls_WindowLeftTree _this;
1861 public Xcls_SignalListItemFactory16(Xcls_WindowLeftTree _owner )
1864 this.el = new Gtk.SignalListItemFactory();
1868 // set gobject values
1871 this.el.setup.connect( (listitem) => {
1874 var icon = new Gtk.Image();
1876 ((Gtk.ListItem)listitem).set_child(icon);
1878 this.el.bind.connect( (listitem) => {
1880 var img = (Gtk.Image) ((Gtk.ListItem)listitem).get_child();
1881 var lr = (Gtk.TreeListRow)((Gtk.ListItem)listitem).get_item();
1882 var node = (JsRender.Node) lr.get_item();
1885 var ic = Gtk.IconTheme.get_for_display(_this.el.get_display());
1886 img.set_from_paintable(
1888 "list-add", null, 16,1,
1889 Gtk.TextDirection.NONE, 0
1893 var fqn = node.fqn();
1894 var cn = _this.main_window.windowstate.project.palete.getChildList(fqn, false);
1896 img.set_visible(cn.size > 0 ? true : false);
1901 // user defined functions
1906 public class Xcls_LeftTreeMenu : Object
1908 public Gtk.Popover el;
1909 private Xcls_WindowLeftTree _this;
1915 public Xcls_LeftTreeMenu(Xcls_WindowLeftTree _owner )
1918 _this.LeftTreeMenu = this;
1919 this.el = new Gtk.Popover();
1923 // set gobject values
1924 var child_1 = new Xcls_Box18( _this );
1926 this.el.child = child_1.el;
1929 // user defined functions
1931 public class Xcls_Box18 : Object
1934 private Xcls_WindowLeftTree _this;
1940 public Xcls_Box18(Xcls_WindowLeftTree _owner )
1943 this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 );
1947 // set gobject values
1948 var child_1 = new Xcls_Button19( _this );
1950 this.el.append( child_1.el );
1951 var child_2 = new Xcls_Button20( _this );
1953 this.el.append( child_2.el );
1954 var child_3 = new Xcls_Button21( _this );
1956 this.el.append( child_3.el );
1959 // user defined functions
1961 public class Xcls_Button19 : Object
1963 public Gtk.Button el;
1964 private Xcls_WindowLeftTree _this;
1970 public Xcls_Button19(Xcls_WindowLeftTree _owner )
1973 this.el = new Gtk.Button();
1977 // set gobject values
1978 this.el.has_frame = false;
1979 this.el.label = "Delete Element";
1982 this.el.clicked.connect( ( ) => {
1983 _this.LeftTreeMenu.el.hide();
1984 _this.model.deleteSelected();
1989 // user defined functions
1992 public class Xcls_Button20 : Object
1994 public Gtk.Button el;
1995 private Xcls_WindowLeftTree _this;
2001 public Xcls_Button20(Xcls_WindowLeftTree _owner )
2004 this.el = new Gtk.Button();
2008 // set gobject values
2009 this.el.has_frame = false;
2010 this.el.label = "Save as Template";
2013 this.el.clicked.connect( () => {
2014 _this.LeftTreeMenu.el.hide();
2015 DialogSaveTemplate.singleton().showIt(
2016 (Gtk.Window) _this.el.get_root (),
2017 _this.main_window.windowstate.file.palete(),
2018 _this.getActiveElement()
2025 // user defined functions
2028 public class Xcls_Button21 : Object
2030 public Gtk.Button el;
2031 private Xcls_WindowLeftTree _this;
2037 public Xcls_Button21(Xcls_WindowLeftTree _owner )
2040 this.el = new Gtk.Button();
2044 // set gobject values
2045 this.el.has_frame = false;
2046 this.el.label = "Save as Module";
2049 this.el.clicked.connect( () => {
2051 _this.LeftTreeMenu.el.hide();
2052 var node = _this.getActiveElement();
2055 var sm = DialogSaveModule.singleton();
2059 (Gtk.Window) _this.el.get_root (),
2060 _this.main_window.windowstate.project,
2064 gtk4 migration - disabled this part.. probably not used muchanyway
2067 if (name.length < 1) {
2071 node.set_prop( new JsRender.NodeProp.special("xinclude", name));
2075 var s = _this.view.el.get_selection();
2077 print("GET SELECTED?");
2082 if (!s.get_selected(out mod, out iter)) {
2083 return; // nothing seleted..
2086 var n_cn = mod.iter_n_children(iter) -1;
2087 for (var i = n_cn; i > -1; i--) {
2088 mod.iter_nth_child(out citer, iter, i);
2091 print("removing node from Tree\n");
2093 _this.model.el.remove(ref citer);
2096 _this.node_selected(node, "tree");
2102 // user defined functions