Fix #8062 - fix new file node selection issue
[roobuilder] / src / Builder4 / WindowLeftTree.bjs
index e1e1a17..9bf6162 100644 (file)
@@ -3,7 +3,9 @@
  "gen_extended" : false,
  "items" : [
   {
-   "# Xcls_MainWindow main_window" : "null",
+   "# Gee.ArrayList<Gtk.Widget>? error_widgets" : "null",
+   "# Xcls_MainWindow? main_window" : "null",
+   "# int last_error_counter" : "-1",
    "$ xns" : "Gtk",
    "@ bool before_node_change" : "()",
    "@ void changed" : "()",
     },
     {
      "$ xns" : "Gtk",
-     "* init" : [
-      " this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);",
-      " "
-     ],
+     "Gtk.PolicyType hscrollbar_policy" : "Gtk.PolicyType.AUTOMATIC",
+     "Gtk.PolicyType vscrollbar_policy" : "Gtk.PolicyType.AUTOMATIC",
      "bool has_frame" : true,
      "bool hexpand" : true,
      "bool vexpand" : true,
      "items" : [
       {
        "# bool blockChanges" : false,
+       "$ JsRender.Node? dragNode" : "null",
        "$ string lastEventSource" : "\"\"",
        "$ xns" : "Gtk",
        "* init" : [
         "{",
-        " ",
+        " /*",
         "  this.css = new Gtk.CssProvider();",
         "//\ttry {",
         "\t\tthis.css.load_from_string(\"",
         " border-top-style: solid;",
         " border-top-color: #88a3bc;",
         "}",
+        ".node-err  {",
+        " border-top-width: 5px;",
+        " border-top-style: solid;",
+        " border-top-color: red;",
+        " border-bottom-width: 5px; ",
+        " border-bottom-style: solid;",
+        " border-bottom-color: red;",
+        "}",
+        ".node-warn  {",
+        " border-top-width: 5px;",
+        " border-top-style: solid;",
+        " border-top-color: #ABF4EB;",
+        " border-bottom-width: 5px; ",
+        " border-bottom-style: solid;",
+        " border-bottom-color: #ABF4EB;",
+        "}",
+        ".node-depr  {",
+        " border-top-width: 5px;",
+        " border-top-style: solid;",
+        " border-top-color: #EEA9FF;",
+        " border-bottom-width: 5px; ",
+        " border-bottom-style: solid;",
+        " border-bottom-color: #EEA9FF;",
+        "}",
+        "",
         "#left-tree-view indent {",
         "-gtk-icon-size : 2px;",
         "}",
+        "#left-tree-view indent:nth-last-child(2)  {",
+        "min-width: 24px;",
+        "}",
         "\");",
         "",
         "\tGtk.StyleContext.add_provider_for_display(",
@@ -67,7 +96,7 @@
         "\t\tthis.css,",
         "\t\tGtk.STYLE_PROVIDER_PRIORITY_APPLICATION",
         "\t);",
-        "\t",
+        "\t*/",
         "\t  ",
         "}",
         ""
            "    \tGLib.warning(\"No node found at row %d\", row);",
            "    \treturn;",
            "\t}",
+           "\t",
+           "\t",
            "\t_this.model.selectNode(node);",
            "     ",
            "     ",
            "\tGLib.debug(\"SOURCE: drag-begin\");",
            "\t ",
            "    // find what is selected in our tree...",
-           "   var data = _this.selmodel.getSelectedNode();",
+           "    var data = _this.selmodel.getSelectedNode();",
            "\tif (data == null) {",
            "\t\treturn  ;",
            "\t}",
-           "\t ",
+           "\t_this.view.dragNode = data;",
            "    var xname = data.fqn();",
            "    GLib.debug (\"XNAME  IS %s\", xname);",
            "",
            " ",
            "}"
           ],
+          "drag_cancel" : [
+           "(drag, reason) => {",
+           "",
+           "\t_this.view.dragNode = null;",
+           "\treturn true;",
+           "}",
+           ""
+          ],
+          "drag_end" : [
+           "(drag, delete_data) => {",
+           "",
+           "_this.view.dragNode = null;",
+           "}",
+           ""
+          ],
           "prepare" : [
            "(x, y) => {",
            "",
          },
          "xtype" : "EventControllerKey"
         },
+        {
+         "$ xns" : "Gtk",
+         "id" : "keystate",
+         "int is_shift" : 0,
+         "listeners" : {
+          "key_pressed" : [
+           "(keyval, keycode, state) => {",
+           "",
+           " \tif (keyval == Gdk.Key.Shift_L || keyval == Gdk.Key.Shift_R) {",
+           " \t\tthis.is_shift = 1;",
+           "\t}",
+           "\treturn true;",
+           "}",
+           ""
+          ],
+          "key_released" : [
+           "(keyval, keycode, state) => {",
+           "\tGLib.debug(\"key release %d, %d, %d\" , (int) keyval, (int)  keycode, state);",
+           " \tif (keyval == Gdk.Key.Shift_L || keyval == Gdk.Key.Shift_R) {",
+           " \t\tthis.is_shift = 0;",
+           "\t}",
+           "\t//GLib.debug(\"set state %d , shift = %d\", (int)this.el.get_current_event_state(), Gdk.ModifierType.SHIFT_MASK);",
+           "",
+           "",
+           " ",
+           "}"
+          ]
+         },
+         "xtype" : "EventControllerKey"
+        },
         {
          "$ xns" : "Gtk",
          "* ctor" : [
           "drop" : [
            "(v, x, y) => {",
            "\t",
+           "\t// must get the pos before we clear the hightlihg.",
+           " \tvar pos = \"\";",
+           " \tvar row = _this.view.getRowAt(x,y, out pos);",
            "\tthis.addHighlight(null,\"\");",
            " ",
+           " \tvar is_shift = _this.keystate.is_shift > 0;",
            " ",
-           " ",
-           " \tvar pos = \"\";",
+           "",
            " \t// -- get position..",
            " \tif (this.lastDragString != v.get_string() || this.lastDragNode == null) {",
            "\t\t// still dragging same node",
            " \t     ",
            "       ",
            "    var dropNode = new JsRender.Node(); ",
-           "\tdropNode.loadFromJsonString(v.get_string(), 1);",
+           "\tdropNode.loadFromJsonString(v.get_string(), 2);",
+           "\tGLib.debug(\"dropped node %s\", dropNode.toJsonString());",
+           "\t",
+           "\t",
            "\tvar drop_on_to = _this.main_window.windowstate.file.palete().getDropList(dropNode.fqn());",
            "   ",
            "    // if there are not items in the tree.. the we have to set isOver to true for anything..",
            "\t\t\treturn false;\t",
            "\t\t}",
            "\t\t// add new node to top..",
-           "\t\t",
+           "\t\tGLib.debug(\"adding to top\");",
            "\t\t",
            "\t\t var m = (GLib.ListStore) _this.model.el.model;",
            "     \t_this.main_window.windowstate.file.tree = dropNode;  ",
-           "    ",
+           "    \tdropNode.updated_count++;",
            "   ",
            "\t\tm.append(dropNode);",
            "\t\t_this.model.selectNode(dropNode); \t",
            "\t\t_this.changed();",
+           "\t\t_this.node_selected(dropNode);",
            "\t\treturn true; // no need to highlight?",
            "     ",
            "    }",
            "",
            "",
            "",
-           "\tvar row = _this.view.getRowAt(x,y, out pos);",
+           "",
            "\tif (row < 0) {",
+           "\t\tGLib.debug(\"could not get row %d,%d, %s\", (int)x,(int)y,pos);",
            "\t\treturn   false; //Gdk.DragAction.COPY;",
            "\t}",
            "\tvar tr = (Gtk.TreeListRow)_this.view.el.model.get_object(row);",
            "\t\t\t\tpos = \"over\";",
            " \t\t\t} else {",
            "\t\t\t\tGLib.debug(\"drop  contains %s - using %s\" , node.parent.fqn(), pos);",
+           "\t\t\t\tif (_this.view.dragNode  != null && is_shift) {",
+           "\t\t \t\t\tif (node.parent.oid == _this.view.dragNode.oid || node.parent.has_parent(_this.view.dragNode)) {",
+           "\t\t\t \t\t\tGLib.debug(\"shift drop not self not allowed\");",
+           "  \t\t\t\t\t\treturn false;\t",
+           "\t\t \t\t\t}",
+           "\t\t \t\t\t",
+           "\t\t \t\t}",
+           "\t\t\t\t",
+           "\t\t\t\t",
            "\t\t\t}",
            " \t\t}",
            " \t\t",
            "\t\t\treturn false;",
            "",
            "\t\t}",
+           "\t\tif (node.oid == _this.view.dragNode.oid || node.has_parent(_this.view.dragNode)) {",
+           " \t\t\tGLib.debug(\"shift drop not self not allowed\");",
+           "\t\t\treturn false;\t",
+           "\t\t}",
            "\t}",
            " \t",
            " \tswitch(pos) {",
            " \t\tcase \"over\":",
-           "\t \t\tnode.appendChild(dropNode);",
+           "",
+           "\t \t\tif (is_shift && _this.view.dragNode != null) {",
+           "\t\t \t\t_this.model.selectNode(null); ",
+           "\t\t \t\t_this.view.dragNode.remove();",
+           "\t \t\t}",
+           " \t \t\tnode.appendChild(dropNode);\t\t\t",
+           "\t \t\tdropNode.updated_count++;",
            " \t\t\t_this.model.selectNode(dropNode); ",
+           " \t\t\t",
            " \t\t\t_this.changed();\t\t\t\t \t\t",
            "\t \t\treturn true;",
            "\t \t\t",
            " \t\tcase \"above\":",
            " \t\t\tGLib.debug(\"Above - insertBefore\");",
            " \t\t",
-           " \t\t\tnode.parent.insertBefore(dropNode, node);",
+           "",
+           "\t \t\tif (is_shift && _this.view.dragNode != null) {",
+           "\t\t \t\t_this.model.selectNode(null); \t \t\t",
+           "\t\t \t\t_this.view.dragNode.remove();",
+           "\t \t\t}",
+           "\t\t\tnode.parent.insertBefore(dropNode, node);\t \t\t",
+           "\t\t\tdropNode.updated_count++;",
            " \t\t\t_this.model.selectNode(dropNode); \t\t\t",
            " \t\t\t_this.changed();",
            " \t\t\treturn true;",
            " \t\t\t",
            " \t\tcase \"below\":",
            " \t\t\tGLib.debug(\"Below - insertAfter\"); \t\t",
+           "\t \t\tif (is_shift && _this.view.dragNode != null) {",
+           "\t\t \t\t_this.model.selectNode(null); \t \t\t",
+           "\t\t \t\t_this.view.dragNode.remove();",
+           "\t \t\t}",
+           "\t",
+           " \t\t\t",
            " \t\t\tnode.parent.insertAfter(dropNode, node);",
+           " \t\t\tdropNode.updated_count++;",
            " \t\t\t_this.model.selectNode(dropNode);\t",
            " \t\t\t_this.changed();",
            " \t\t\t// select it",
           "motion" : [
            "(  x, y) => {",
            " ",
+           "\tvar is_shift = _this.keystate.is_shift > 0;",
+           "\t",
+           "\t//GLib.debug(\"shift is    %s\", _this.keystate.is_shift > 0 ? \"SHIFT\" : \"-\");",
            "\tstring pos; // over / before / after..",
            "",
-           "    GLib.debug(\"got drag motion\");",
+           "    //GLib.debug(\"got drag motion\");",
            "",
            "    GLib.Value v = GLib.Value(typeof(string));",
            "   \t//var str = drop.read_text( [ \"text/plain\" ] 0);",
            "   \ttry {",
            "  \t\tcont.get_value(ref v);",
            "\t} catch (GLib.Error e) {",
-           "\t    GLib.debug(\"failed to get drag value\");",
+           "\t   // GLib.debug(\"failed to get drag value\");",
            "\t\treturn Gdk.DragAction.COPY;\t ",
            "\t",
            "\t}",
-           "",
-           "\tGLib.debug(\"got %s\", v.get_string());",
+           " ",
+           "\t//GLib.debug(\"got %s\", v.get_string());",
            "\t  ",
            "\tif (this.lastDragString != v.get_string() || this.lastDragNode == null) {",
            "\t\t// still dragging same node",
            "     foreach(var dp in drop_on_to) {",
            "     \tstr += dp;",
            " \t}",
-           " \tGLib.debug(\"droplist: %s\", string.joinv(\", \", str));",
+           " \t//GLib.debug(\"droplist: %s\", string.joinv(\", \", str));",
            "     ",
            "     ",
            "    // if there are not items in the tree.. the we have to set isOver to true for anything..",
            "    }",
            "    ",
            "    ",
-           " \tGLib.debug(\"check is over\");",
+           "",
            " \t ",
            "    // if path of source and dest are inside each other..",
            "    // need to add source info to drag?",
            "    // the fail();",
            " \tvar row = _this.view.getRowAt(x,y, out pos);",
-           " \t",
+           " \t//GLib.debug(\"check is over %d, %d, %s\", (int)x,(int)y, pos);",
+           "",
            " \tif (row < 0) {",
            "\t\tthis.addHighlight(null, \"\");\t",
            "\t \treturn Gdk.DragAction.COPY;",
            "\t",
            "\tvar node =  (JsRender.Node)tr.get_item();",
            "\t",
-           "\tGLib.debug(\"Drop over node: %s\", node.fqn());",
+           "\t//GLib.debug(\"Drop over node: %s\", node.fqn());",
            "\t",
            "",
            " \tif (pos == \"above\" || pos == \"below\") {",
            "\t\tif (node.parent == null) {",
-           "\t\t\tGLib.debug(\"no parent try center\");",
+           "\t\t\t//GLib.debug(\"no parent try center\");",
            "\t\t\tpos = \"over\";",
            "\t\t} else {",
            "\t \t\t ",
            "\t \t\tif (!drop_on_to.contains(node.parent.fqn())) {",
-           "\t\t\t\tGLib.debug(\"drop on does not contain %s - try center\" , node.parent.fqn());",
+           "\t\t\t\t//GLib.debug(\"drop on does not contain %s - try center\" , node.parent.fqn());",
            "\t \t\t\tpos = \"over\";",
            " \t\t\t} else {",
-           "\t\t\t\tGLib.debug(\"drop  contains %s - using %s\" , node.parent.fqn(), pos);",
+           "\t\t\t\t//GLib.debug(\"drop  contains %s - using %s\" , node.parent.fqn(), pos);",
+           "\t\t\t\tif (_this.view.dragNode  != null && is_shift) {",
+           "\t\t \t\t\tif (node.parent.oid == _this.view.dragNode.oid || node.parent.has_parent(_this.view.dragNode)) {",
+           "\t\t\t \t\t\tGLib.debug(\"shift drop not self not allowed\");",
+           "\t\t \t\t\t\tthis.addHighlight(null, \"\");",
+           "\t\t \t\t\t\treturn Gdk.DragAction.COPY;\t",
+           "\t\t \t\t\t}",
+           "\t\t \t\t\t",
+           "\t\t \t\t}",
+           "\t\t\t\t",
            "\t\t\t}",
+           "\t\t\t",
+           "\t\t\t",
+           "\t\t\t",
            " \t\t}",
            " \t\t",
+           " \t\t",
            " \t}",
            " \tif (pos == \"over\") {",
            "\t \tif (!drop_on_to.contains(node.fqn())) {",
-           "\t\t\tGLib.debug(\"drop on does not contain %s - try center\" , node.fqn());",
+           "\t\t\t//GLib.debug(\"drop on does not contain %s - try center\" , node.fqn());",
            "\t\t\tthis.addHighlight(null, \"\"); ",
-           "\t\t\treturn Gdk.DragAction.COPY;\t\t",
+           "\t\t\treturn is_shift ?  Gdk.DragAction.MOVE :  Gdk.DragAction.COPY;\t\t",
            "\t\t}",
+           "\t\tif (_this.view.dragNode  != null && is_shift) {",
+           " \t\t\tif (node.oid == _this.view.dragNode.oid || node.has_parent(_this.view.dragNode)) {",
+           "\t \t\t\t//GLib.debug(\"shift drop not self not allowed\");",
+           " \t\t\t\tthis.addHighlight(null, \"\");",
+           " \t\t\t\treturn Gdk.DragAction.COPY;\t",
+           " \t\t\t}",
+           "\t\t}",
+           " \t\t\t",
            "\t}",
            " \t",
            " \t",
            " \t    // _this.view.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);",
            "\tvar w = _this.view.getWidgetAt(x,y);",
            "\tthis.addHighlight(w, pos); ",
-           "    return Gdk.DragAction.COPY;\t\t\t",
+           "\treturn is_shift ?  Gdk.DragAction.MOVE :  Gdk.DragAction.COPY;\t\t",
            "}"
           ]
          },
           "(Gtk.Widget? w, string hl) {",
           "\tif (this.highlightWidget != null) {",
           "\t\tvar ww  = this.highlightWidget;",
-          "\t\tGLib.debug(\"clear drag from previous highlight\");",
+          "\t\t//GLib.debug(\"clear drag from previous highlight\");",
           "\t\tif (ww.has_css_class(\"drag-below\")) {",
           "\t\t\t ww.remove_css_class(\"drag-below\");",
           "\t\t}",
           "\t\t}",
           "\t}",
           "\tif (w != null) {",
-          "\t\tGLib.debug(\"add drag=%s to widget\", hl);\t",
+          "\t\t//GLib.debug(\"add drag=%s to widget\", hl);\t",
           "\t\tif (!w.has_css_class(\"drag-\" + hl)) {",
           "\t\t\tw.add_css_class(\"drag-\" + hl);",
           "\t\t}",
         {
          "$ xns" : "Gtk",
          "* prop" : "model",
+         "bool can_unselect" : true,
          "id" : "selmodel",
          "items" : [
           {
             "\t\t",
             "\t\t}",
             "\t);",
+            "\tif (_this.selmodel.el == null) {",
+            "\t\treturn this.el;",
+            "\t}",
             "\t_this.selmodel.el.set_model(this.el);",
             "\treturn this.el;",
             "}"
            ],
+           "| int nodeToRow" : [
+            "(JsRender.Node node) ",
+            "{",
+            " ",
+            "\tvar s = _this.view.el.model as Gtk.SingleSelection;",
+            "\tfor (var i = 0; i < s.n_items; i++) {",
+            "\t\t//GLib.debug(\"check node %s\", s.get_item(i).get_type().name());",
+            "\t\tvar lr = s.get_item(i) as Gtk.TreeListRow;",
+            "\t\t//GLib.debug(\"check node %s\", lr.get_item().get_type().name());",
+            "\t\tvar nn = (lr.get_item() as JsRender.Node);",
+            "\t\tif (nn != null && nn.oid == node.oid) {",
+            "\t\t\treturn i;",
+            "\t\t\t",
+            "\t\t}",
+            "\t}",
+            "\treturn -1;\t\t\t",
+            "\t",
+            "",
+            "}"
+           ],
            "| void deleteSelected" : [
             "() {",
             "",
             "\t     return;",
             "     }",
             "    _this.selmodel.el.unselect_all();",
-            "    ",
-            "    node.remove();",
-            " \tGLib.debug(\"delete Selected - done\");",
-            "    _this.changed();",
+            "    if (node.parent != null) {",
+            "\t\tnode.remove();",
+            "\t \tGLib.debug(\"delete Selected - done\");",
+            "\t\t_this.changed();",
+            "\t\treturn;",
+            "\t}",
+            "\tthis.updateModel(null);",
+            "\t_this.main_window.windowstate.file.tree = null;",
+            "\t_this.changed();",
+            "\t_this.node_selected(null);",
             "/*    ",
             "    print(\"DELETE SELECTED?\");",
             "    //_this.view.blockChanges = true;",
             "    _this.main_window.windowstate.leftTreeNodeSelected(null);",
             "    // needed???",
             "    _this.main_window.windowstate.file = f;",
-            "    ",
+            "    _this.last_error_counter = -1;",
             "   ",
             "    if (f.tree == null) {",
             "\t    try {",
             "    // if it's still null?",
             "    if (f.tree == null) {",
             "\t\t_this.main_window.windowstate.showAddObject(_this.view.el, null);",
-            "    ",
+            "    \t_this.updateErrors();",
             "        return;",
             "    }",
             "  \tm.append(f.tree);",
-            "  \t// expand???",
-            "",
-            "/*",
-            "    if (f.tree.readItems().size < 1) {",
-            "        // single item..",
-            "        ",
-            "        //this.get('/Window.leftvpaned').el.set_position(80);",
-            "        // select first...",
-            "        _this.view.el.set_cursor( ",
-            "            new  Gtk.TreePath.from_string(\"0\"), null, false);",
-            "        ",
-            "        ",
-            "    } else {",
-            "          //this.get('/Window.leftvpaned').el.set_position(200);",
-            "    }",
-            "  */  ",
-            "    ",
-            "    ",
-            "",
-            "    //_this.maincol.el.set_max_width(_this.viewwin.el.get_allocated_width() - 32);",
+            "\t_this.updateErrors();",
             " ",
             "    _this.selmodel.el.set_selected(Gtk.INVALID_LIST_POSITION);",
             "   ",
             ""
            ],
            "| void selectNode" : [
-            "(JsRender.Node node) ",
+            "(JsRender.Node node) ",
             "{",
-            "\tvar row = -1;",
-            "\tvar s = (Gtk.SingleSelection)_this.view.el.model;",
-            "\tfor (var i = 0; i < s.n_items; i++) {",
-            "\t\t//GLib.debug(\"check node %s\", s.get_item(i).get_type().name());",
-            "\t\tvar lr = (Gtk.TreeListRow)s.get_item(i);",
-            "\t\tGLib.debug(\"check node %s\", lr.get_item().get_type().name());",
-            "\t\tif (((JsRender.Node)lr.get_item()).oid == node.oid) {",
-            "\t\t\trow  = i;",
-            "\t\t\tbreak;",
-            "\t\t}",
+            "\tvar s = _this.view.el.model as Gtk.SingleSelection;",
+            "\tif (node == null) {",
+            "\t\ts.selected=Gtk.INVALID_LIST_POSITION;",
+            "\t\treturn;",
             "\t}",
+            "\tvar row = this.nodeToRow(node);",
+            "",
+            "\t ",
             "\tif (row < 0) {",
             "\t\t// select none?",
             "\t\tGLib.debug(\"Could not find node\");",
+            "\t\ts.selected=Gtk.INVALID_LIST_POSITION;",
             "\t\treturn;",
             "\t}",
             "\tGLib.debug(\"Select %d\", row);",
             "\ts.set_selected(row);",
-            "\t_this.node_selected(node);\t\t\t",
+            "\t_this.view.el.scroll_to(row, null, Gtk.ListScrollFlags.SELECT, null);",
+            "\t//_this.node_selected(node);\t\t\t",
             "\t",
             "",
             "}"
            "\t    // why dup_?",
            "\t    ",
            "",
-           "\t    GLib.debug (\"calling left_tree.node_selected\");",
+           "\t    GLib.debug (\"calling left_tree.node_selected %s\", snode.toJsonString());",
            "\t    _this.node_selected(snode);",
            "\t   ",
            "\t     ",
           "() {",
           "  if (this.el.selected_item == null) {",
           "\t\treturn null;",
-          "  }\t\t\t        ",
+          "  }\t",
+          "   ",
+          "  ",
           "   var tr = (Gtk.TreeListRow)this.el.selected_item;",
+          "  ",
           "   return (JsRender.Node)tr.get_item();",
           "\t ",
           "}"
            "listeners" : {
             "bind" : [
              "(listitem) => {",
-             "\t GLib.debug(\"listitme is is %s\", ((Gtk.ListItem)listitem).get_type().name());",
+             "\t// GLib.debug(\"listitme is is %s\", ((Gtk.ListItem)listitem).get_type().name());",
              "\t",
              "\t//var expand = (Gtk.TreeExpander) ((Gtk.ListItem)listitem).get_child();",
              "\tvar expand = (Gtk.TreeExpander)  ((Gtk.ListItem)listitem).get_child();",
              "\t",
              "\tvar lr = (Gtk.TreeListRow)((Gtk.ListItem)listitem).get_item();",
              "\tvar node = (JsRender.Node) lr.get_item();",
-             "\t",
-             "   GLib.debug(\"node is %s\", node.get_type().name());",
+             "\tif (node == null || node.fqn() == \"\") {",
+             "\t\treturn;",
+             "\t}",
+             "   //GLib.debug(\"node is %s\", node.get_type().name());",
              "// was item (1) in old layout",
              "",
              "\t",
              "    expand.set_hide_expander( !node.hasChildren() );",
              " \texpand.set_list_row(lr);",
              " \t",
-             " \tnode.bind_property(\"iconFilename\",",
-             "                    img, \"file\",",
+             " \tnode.bind_property(\"iconResourceName\",",
+             "                    img, \"resource\",",
              "                   GLib.BindingFlags.SYNC_CREATE);",
              " \t",
              " \tnode.bind_property(\"nodeTitleProp\",",
        "string name" : "left-tree-view",
        "xtype" : "ColumnView",
        "| Gtk.Widget? getWidgetAt" : [
-        "(double x,  double in_y) {",
-        "/*",
-        "    \t",
-        "from    \thttps://discourse.gnome.org/t/gtk4-finding-a-row-data-on-gtkcolumnview/8465",
-        "    \tvar colview = gesture.widget;",
-        "    \tvar line_no = check_list_widget(colview, x,y);",
-        "         if (line_no > -1) {",
-        "    \t\tvar item = colview.model.get_item(line_no);",
-        "    \t\t ",
-        "    \t}",
-        "    \t*/",
-        "    \tvar y = in_y + _this.viewwin.el.vadjustment.value; ",
-        "        var  child = this.el.get_first_child(); ",
-        "    \t//Gtk.Allocation alloc = { 0, 0, 0, 0 };",
-        "    \tvar line_no = -1; ",
-        "    \tvar reading_header = true;",
-        "    \tvar curr_y = 0;",
-        "    \tvar header_height  = 0;",
-        "    \tvar h = 0;",
-        "    \twhile (child != null) {",
-        "\t\t\t//GLib.debug(\"Got %s\", child.get_type().name());",
-        "\t        if (reading_header) {",
-        "\t\t\t\t",
-        "",
-        "\t\t\t\tif (child.get_type().name() != \"GtkColumnListView\") {",
-        "\t\t\t        h += child.get_height();",
-        "\t\t\t\t\tchild = child.get_next_sibling();",
-        "\t\t\t\t\tcontinue;",
-        "\t\t\t\t}",
-        "\t\t\t\t// should be columnlistview",
-        "\t\t\t\tchild = child.get_first_child(); ",
-        "\t\t\t    GLib.debug(\"header height=%d\", h);",
-        "\t\t\t\theader_height =  h;",
-        "\t\t\t\t",
-        "\t\t\t\treading_header = false;",
-        "\t\t\t\t",
-        "\t        }",
-        "\t\t    line_no++;",
+        "(double x,  double  y) {",
         "",
-        "\t\t\tif (y < header_height) {",
-        "\t\t    \treturn null;",
-        "\t    \t}",
-        "",
-        "\t\t\tvar hh = child.get_height();",
-        "\t\t\t//GLib.debug(\"got cell xy = %d,%d  w,h= %d,%d\", alloc.x, alloc.y, alloc.width, alloc.height);",
-        "",
-        "\t\t    if (y > curr_y && y <= header_height + hh + curr_y ) {",
-        "\t\t\t    return (Gtk.Widget)child;",
-        "\t\t    }",
-        "\t\t    curr_y +=  hh ;",
-        "",
-        "\t\t    if (curr_y > y) {",
-        "\t\t        return null;",
-        "\t        }",
-        "\t        child = child.get_next_sibling(); ",
-        "    \t}",
-        "        return null;",
+        "\tvar w = this.el.pick(x, y, Gtk.PickFlags.DEFAULT);",
+        "\t//GLib.debug(\"got widget %s\", w == null ? \"nothing\" : w.get_type().name());",
+        "\tif (w == null) {",
+        "\t\treturn null;",
+        "\t}",
+        "\t",
+        "\tvar row= w.get_ancestor(GLib.Type.from_name(\"GtkColumnViewRowWidget\"));",
+        "\tif (row == null) {",
+        "\t\treturn null;",
+        "\t}",
+        "\treturn row;",
+        " ",
         "",
         " }"
        ],
         "    \tvar reading_header = true;",
         "\t ",
         "    \twhile (child != null) {",
-        "\t\t\tGLib.debug(\"Got %s\", child.get_type().name());",
+        "\t\t\t//GLib.debug(\"Got %s\", child.get_type().name());",
         "    \t   ",
         "    \t   if (reading_header) {",
         "\t\t\t\t",
         "\t\t\t ",
         "\t\t\t\t",
         "\t\t\t\treading_header = false;",
-        "\t\t\t\t ",
+        "\t\t\t\tcontinue;",
         "\t\t    }",
         "\t\t    ",
         "\t\t  ",
        ],
        "| int getColAt" : [
         "(double x,  double y) {",
-        "/*",
-        "    \t",
-        "from    \thttps://discourse.gnome.org/t/gtk4-finding-a-row-data-on-gtkcolumnview/8465",
-        "    \t  ",
-        "    \t*/",
-        "\t\t//Gtk.Allocation alloc = { 0, 0, 0, 0 };",
-        "\t\t//GLib.debug(\"Cehck %d, %d\", x,y);",
-        "        var  child = this.el.get_first_child(); ",
-        "    \t ",
-        "    \tvar col = 0;",
-        "    \tvar offx = 0;",
-        "    \twhile (child != null) {",
-        "\t\t\t",
-        "\t\t\tif (child.get_type().name() == \"GtkColumnViewRowWidget\") {",
-        "\t\t\t\tchild = child.get_first_child();",
-        "\t\t\t\tcontinue;",
-        "\t\t\t}",
+        "\t/*",
         "\t\t\t",
-        "\t\t\t//child.get_allocation(out alloc);",
-        "\t\t\tif (x <  (child.get_width() + offx)) {",
-        "\t\t\t\treturn col;",
-        "\t\t\t}",
-        "\t\t\treturn 1;",
-        "\t\t\t//offx += child.get_width();",
-        "\t\t\t//col++;",
-        "\t\t\t//child = child.get_next_sibling();",
+        "\tfrom    \thttps://discourse.gnome.org/t/gtk4-finding-a-row-data-on-gtkcolumnview/8465",
+        "    \t  ",
+        "\t*/",
+        "\t//Gtk.Allocation alloc = { 0, 0, 0, 0 };",
+        "\t//GLib.debug(\"Cehck %d, %d\", x,y);",
+        "    var  child = this.el.get_first_child(); ",
+        "\t ",
+        "\tvar col = 0;",
+        "\tvar offx = 0;",
+        "\twhile (child != null) {",
+        "\t\t",
+        "\t\tif (child.get_type().name() == \"GtkColumnViewRowWidget\") {",
+        "\t\t\tchild = child.get_first_child();",
+        "\t\t\tcontinue;",
         "\t\t}",
-        "    \t     ",
-        "\t\t\t  ",
-        "        return -1;",
+        "\t\t",
+        "\t\t//child.get_allocation(out alloc);",
+        "\t\tif (x <  (child.get_width() + offx)) {",
+        "\t\t\treturn col;",
+        "\t\t}",
+        "\t\treturn 1;",
+        "\t\t//offx += child.get_width();",
+        "\t\t//col++;",
+        "\t\t//child = child.get_next_sibling();",
+        "\t}",
+        "\t     ",
+        "\t\t  ",
+        "    return -1;",
         "",
         " }"
        ],
        "| int getRowAt" : [
-        "(double x,  double in_y, out string pos) {",
-        "",
+        "(double x,  double  y, out string pos) {",
         "",
+        "\tpos = \"\";",
+        "\tvar w = this.el.pick(x, y, Gtk.PickFlags.DEFAULT);",
+        "\t//GLib.debug(\"got widget %s\", w == null ? \"nothing\" : w.get_type().name());",
+        "\tif (w == null) {",
+        "\t\treturn -1;",
+        "\t}",
+        "\t",
+        "\tvar row= w.get_ancestor(GLib.Type.from_name(\"GtkColumnViewRowWidget\"));",
+        "\tif (row == null) {",
+        "\t\treturn -1;",
+        "\t}",
+        "\t",
+        "\t//GLib.debug(\"got colview %s\", row == null ? \"nothing\" : row.get_type().name());",
         "\t ",
-        "",
-        "/*",
-        "    \t",
-        "from    \thttps://discourse.gnome.org/t/gtk4-finding-a-row-data-on-gtkcolumnview/8465",
-        "    \tvar colview = gesture.widget;",
-        "    \tvar line_no = check_list_widget(colview, x,y);",
-        "         if (line_no > -1) {",
-        "    \t\tvar item = colview.model.get_item(line_no);",
-        "    \t\t ",
-        "    \t}",
-        "    \t*/",
-        " \t\t ",
-        " \t\t",
-        " \t\t//GLib.debug(\"offset = %d  y = %d\", (int) voff, (int) in_y);",
-        "    \tvar y = in_y + _this.viewwin.el.vadjustment.value; ",
-        "        var  child = this.el.get_first_child(); ",
-        "    \t//Gtk.Allocation alloc = { 0, 0, 0, 0 };",
-        "    \tvar line_no = -1; ",
-        "    \tvar reading_header = true;",
-        "    \tvar real_y = 0;",
-        "    \tvar header_height  = 0;",
-        "    \tpos = \"none\";",
-        "    \tvar h = 0;",
-        "    \twhile (child != null) {",
-        "\t\t\t//GLib.debug(\"Got %s\", child.get_type().name());",
-        "    \t    if (reading_header) {",
-        "\t\t\t\t",
-        "",
-        "\t\t\t\tif (child.get_type().name() != \"GtkColumnListView\") {",
-        "\t\t\t        h += child.get_height();",
-        "\t\t\t\t\tchild = child.get_next_sibling();",
-        "\t\t\t\t\tcontinue;",
-        "\t\t\t\t}",
-        "\t\t\t\t// should be columnlistview",
-        "\t\t\t\tchild = child.get_first_child(); ",
-        "\t\t\t    GLib.debug(\"header height=%d\", h);",
-        "\t\t\t\theader_height =  h;",
-        "\t\t\t\t",
-        "\t\t\t\treading_header = false;",
-        "\t\t\t\t",
-        "\t        }",
-        "\t        ",
-        "\t\t    if (child.get_type().name() != \"GtkColumnViewRowWidget\") {",
-        "    \t\t    child = child.get_next_sibling();",
-        "    \t\t    continue;",
-        "\t\t    }",
-        "\t\t    ",
-        "\t\t \tif (y < header_height) {",
-        "\t\t    \treturn -1;",
-        "\t    \t}",
-        "\t\t    ",
-        "\t\t    line_no++;",
-        "\t\t\tvar hh = child.get_height();",
-        "\t\t\t//child.get_allocation(out alloc);",
-        "\t\t\t//GLib.debug(\"got cell xy = %d,%d  w,h= %d,%d\", alloc.x, alloc.y, alloc.width, alloc.height);",
-        "\t\t\t//GLib.debug(\"row %d y= %d %s\", line_no, (int) (header_height + alloc.y),",
-        "\t\t\t",
-        "\t\t\t//\tchild.visible ? \"VIS\" : \"hidden\");",
-        "",
-        "\t\t    if (y >  (header_height + real_y) && y <= (header_height +  real_y + hh) ) {",
-        "\t\t    \tif (y > ( header_height + real_y + (hh * 0.8))) {",
-        "\t\t    \t\tpos = \"below\";",
-        "\t    \t\t} else if (y > ( header_height + real_y + (hh * 0.2))) {",
-        "\t    \t\t\tpos = \"over\";",
-        "    \t\t\t} else {",
-        "    \t\t\t\tpos = \"above\";",
-        "\t\t\t\t}",
-        "\t\t    \t GLib.debug(\"getRowAt return : %d, %s\", line_no, pos);",
-        "\t\t\t    return line_no;",
-        "\t\t    }",
-        " ",
-        "",
-        "\t\t    if (real_y + hh > y) {",
-        "\t\t        return -1;",
-        "\t        }",
-        "\t        real_y += hh;",
-        "\t        child = child.get_next_sibling(); ",
-        "    \t}",
-        "        return -1;",
-        "",
+        "\tvar rn = 0;",
+        "\tvar cr = row;",
+        "\t ",
+        "\twhile (cr.get_prev_sibling() != null) {",
+        "\t\trn++;",
+        "\t\tcr = cr.get_prev_sibling();",
+        "\t}",
+        "\t",
+        "\t//GLib.debug(\"row number is %d\", rn);",
+        "\t//GLib.debug(\"click %d, %d\", (int)x, (int)y);",
+        "\t// above or belw",
+        "\tGraphene.Rect  bounds;",
+        "\trow.compute_bounds(this.el, out bounds);",
+        "\t//GLib.debug(\"click x=%d, y=%d, w=%d, h=%d\", ",
+        "\t//\t(int)bounds.get_x(), (int)bounds.get_y(),",
+        "\t//\t(int)bounds.get_width(), (int)bounds.get_height()",
+        "\t//\t);",
+        "\tvar ypos = y - bounds.get_y();",
+        "\t//GLib.debug(\"rel ypos = %d\", (int)ypos);\t",
+        "\tvar rpos = 100.0 * (ypos / bounds.get_height());",
+        "\t//GLib.debug(\"rel pos = %d %%\", (int)rpos);",
+        "\tpos = \"over\";",
+        "\t",
+        "\tif (rpos > 80) {",
+        "\t\tpos = \"below\";",
+        "\t} else if (rpos < 20) {",
+        "\t\tpos = \"above\";",
+        "\t} ",
+        "\treturn rn;",
         " }"
        ]
       },
          "items" : [
           {
            "$ xns" : "Gtk",
+           "bool has_frame" : false,
            "label" : "Delete Element",
            "listeners" : {
             "clicked" : [
-             "  ( ) => {",
-             "    ",
-             "    print(\"ACTIVATE?\");",
-             "    ",
-             "  \t_this.LeftTreeMenu.el.hide();",
-             "     _this.model.deleteSelected();",
+             " ( ) => {",
+             "_this.LeftTreeMenu.el.hide();",
+             " _this.model.deleteSelected();",
+             "_this.changed();",
              "}"
             ]
            },
           },
           {
            "$ xns" : "Gtk",
+           "bool has_frame" : false,
            "label" : "Save as Template",
            "listeners" : {
             "clicked" : [
           },
           {
            "$ xns" : "Gtk",
+           "bool has_frame" : false,
            "label" : "Save as Module",
            "listeners" : {
             "clicked" : [
    "| JsRender.JsRender getActiveFile" : [
     "() {",
     "    return this.main_window.windowstate.file;",
+    "    ",
     "}",
     ""
    ],
     "}",
     "",
     ""
+   ],
+   "| void removeErrors" : [
+    "() {",
+    "\tif (this.error_widgets == null || this.error_widgets.size < 1) {",
+    " \t\treturn;",
+    "\t}",
+    "\tforeach(var child in this.error_widgets) {",
+    "\t",
+    "\t\tif (child.has_css_class(\"node-err\")) {",
+    "\t\t\tchild.remove_css_class(\"node-err\");",
+    "\t\t}",
+    "\t\tif (child.has_css_class(\"node-warn\")) {",
+    "\t\t\tchild.remove_css_class(\"node-warn\");",
+    "\t\t}",
+    "\t\t",
+    "\t\tif (child.has_css_class(\"node-depr\")) {",
+    "\t\t\tchild.remove_css_class(\"node-depr\");",
+    "\t\t}",
+    "\t}",
+    "\tthis.error_widgets  = null;",
+    "\treturn;",
+    "\t",
+    "\t/*",
+    "\tvar  child = this.view.el.get_first_child(); ",
+    " ",
+    "\tvar reading_header = true;",
+    " ",
+    "\twhile (child != null) {",
+    "\t\t//GLib.debug(\"Got %s\", child.get_type().name());",
+    "\t   ",
+    "\t   if (reading_header) {",
+    "\t\t\t",
+    "",
+    "\t\t\tif (child.get_type().name() != \"GtkColumnListView\") {",
+    "\t\t\t   ",
+    "\t\t\t\tchild = child.get_next_sibling();",
+    "\t\t\t\tcontinue;",
+    "\t\t\t}",
+    "\t\t\t// should be columnlistview",
+    "\t\t\tchild = child.get_first_child(); ",
+    "\t\t ",
+    "\t\t ",
+    "\t\t\t",
+    "\t\t\treading_header = false;",
+    "\t\t\t continue;",
+    "\t    }",
+    "\t    ",
+    "\t  \tif (child.has_css_class(\"node-err\")) {",
+    "\t\t\tchild.remove_css_class(\"node-err\");",
+    "\t\t}",
+    "\t\tif (child.has_css_class(\"node-warn\")) {",
+    "\t\t\tchild.remove_css_class(\"node-warn\");",
+    "\t\t}",
+    "\t\t",
+    "\t\tif (child.has_css_class(\"node-depr\")) {",
+    "\t\t\tchild.remove_css_class(\"node-depr\");",
+    "\t\t}",
+    "\t\t",
+    "        child = child.get_next_sibling(); ",
+    "\t}",
+    "\t//GLib.debug(\"Rturning null\");",
+    "\t*/",
+    "     ",
+    "}"
+   ],
+   "| void updateErrors" : [
+    "() {",
+    "\tvar file = this.getActiveFile();",
+    "\tif (file == null) {",
+    "\t\treturn;",
+    "\t}",
+    "\t",
+    "\tvar ar = file.getErrors();",
+    "\tif (ar == null || ar.size < 1) {",
+    "\t\tif (this.last_error_counter != file.error_counter) {",
+    "\t\t\tthis.removeErrors();",
+    "\t\t}",
+    "\t",
+    "\t\tthis.last_error_counter = file.error_counter ;",
+    "",
+    "\t\treturn;",
+    "\t}",
+    " \tif (this.last_error_counter == file.error_counter) {",
+    "\t\treturn;",
+    "\t}",
+    "\tthis.removeErrors();",
+    "\tthis.error_widgets = new Gee.ArrayList<Gtk.Widget>();",
+    "\tforeach(var diag in ar) { ",
+    "\t",
+    "\t\t ",
+    "//        print(\"get inter\\n\");",
+    "\t    var node= file.lineToNode( (int)diag.range.start.line) ;",
+    "\t    if (node == null) {",
+    "\t    \tcontinue;",
+    "    \t}",
+    "    \tvar row = _this.model.nodeToRow(node);",
+    "    \tif (row < 0) {",
+    "    \t\tcontinue;",
+    "\t\t}",
+    "    \tvar w = this.view.getWidgetAtRow(row);",
+    "    \tif (w == null) {",
+    "    \t\treturn;",
+    "\t\t}",
+    "\t\tthis.error_widgets.add(w);",
+    "\t\t// always show errors.",
+    "\t\tvar ed = diag.category.down();",
+    "\t\tif (ed != \"err\" && w.has_css_class(\"node-err\")) {",
+    "\t\t\tcontinue;",
+    "\t\t}",
+    "\t\tif (ed == \"err\" && w.has_css_class(\"node-warn\")) {",
+    "\t\t\tw.remove_css_class(\"node-warn\");",
+    "\t\t}",
+    "\t\tif (ed == \"err\" && w.has_css_class(\"node-depr\")) {",
+    "\t\t\tw.remove_css_class(\"node-depr\");",
+    "\t\t}",
+    "\t\tif (!w.has_css_class(\"node-\"+ ed)) {",
+    "\t\t\tw.add_css_class(\"node-\" + ed);",
+    "\t\t}",
+    "\t\t",
+    "\t}",
+    "\t",
+    "}"
    ]
   }
  ],