{
- "name" : "WindowLeftTree",
- "parent" : "",
- "title" : "",
- "path" : "/home/alan/gitlive/roobuilder/src/Builder4/WindowLeftTree.bjs",
- "permname" : "",
- "modOrder" : "",
"build_module" : "builder",
"items" : [
{
- "| JsRender.Node? getActiveElement" : " () { // return path to actie node.\n\n var path = this.getActivePath();\n if (path.length < 1) {\n return null;\n }\n return _this.model.pathToNode(path);\n \n}\n",
- "@ bool before_node_change" : "()",
- "id" : "WindowLeftTree",
- "$ shadow_type" : "Gtk.ShadowType.IN",
- "* init" : " this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);\n \n",
- "| JsRender.JsRender getActiveFile" : "() {\n return this.main_window.windowstate.file;\n}\n",
+ "# Xcls_MainWindow main_window" : "null",
+ "$ xns" : "Gtk",
"* pack" : "add",
- "xtype" : "ScrolledWindow",
+ "@ bool before_node_change" : "()",
"@ void changed" : "()",
- "$ xns" : "Gtk",
"@ void node_selected" : "(JsRender.Node? node, string source)",
- "# Xcls_MainWindow main_window" : "null",
- "| string getActivePath" : " () {\n \n var view = this.view.el;\n if (view.get_selection().count_selected_rows() < 1) {\n return \"\";\n }\n Gtk.TreeIter iter;\n Gtk.TreeModel mod;\n view.get_selection().get_selected(out mod, out iter);\n return mod.get_path(iter).to_string();\n}\n ",
+ "Gtk.Orientation orientation" : "Gtk.Orientation.VERTICAL",
+ "id" : "WindowLeftTree",
"items" : [
{
- "listeners" : {
- "button_release_event" : "(ev) => { \n this.button_is_pressed = false;\n return false;\n}",
- "button_press_event" : " ( ev) => {\n //console.log(\"button press?\");\n this.button_is_pressed = true;\n print(\"BUTTON DOWN\\n\");\n \n this.lastEventSource = \"tree\";\n if (! _this.before_node_change() ) {\n \n return true;\n }\n \n\n \n if (ev.type != Gdk.EventType.BUTTON_PRESS || ev.button != 3) {\n //print(\"click\" + ev.type);\n return false;\n }\n Gtk.TreePath res;\n if (!_this.view.el.get_path_at_pos((int)ev.x,(int)ev.y, out res, null, null, null) ) {\n return true;\n }\n \n this.el.get_selection().select_path(res);\n \n //if (!this.get('/LeftTreeMenu').el) { \n // this.get('/LeftTreeMenu').init(); \n // }\n \n _this.LeftTreeMenu.el.set_screen(Gdk.Screen.get_default());\n _this.LeftTreeMenu.el.show_all();\n _this.LeftTreeMenu.el.popup(null, null, null, 3, ev.time);\n // print(\"click:\" + res.path.to_string());\n return true;\n}",
- "cursor_changed" : " ( ) => {\n print(\"LEFT TREE Cursor Changed\\n\");\n\tif (!this.button_is_pressed && !this.key_is_pressed) {\n\t\t// then event was started by some other action\n\t\t// which should manually trigger all the events..\n\t\tprint(\"SKIPPING select - no button or key pressed\\n\");\n\t\treturn;\n\t}\n\n\n if (this.blockChanges) { // probably not needed.. \n\t\tprint(\"SKIPPING select - blockchanges set..\\n\"); \n return ;\n }\n if (!_this.before_node_change( ) ) {\n\t this.blockChanges = true;\n\t this.el.get_selection().unselect_all();\n\t this.blockChanges = false;\n\t \n\t return;\n }\n if (_this.main_window.windowstate.file == null) {\n \t\tprint(\"SKIPPING select windowstate file is not set...\\n\"); \n return;\n } \n \n //var render = this.get('/LeftTree').getRenderer(); \n print(\"LEFT TREE -> view -> selection changed called\\n\");\n \n \n // -- it appears that the selection is not updated.\n \n GLib.Timeout.add_full(GLib.Priority.DEFAULT,10 , () => {\n print(\"LEFT TREE -> view -> selection changed TIMEOUT CALLED\\n\");\n\n if (this.el.get_selection().count_selected_rows() < 1) {\n\n print(\"selected rows < 1\\n\");\n //??this.model.load( false);\n _this.node_selected(null, this.lastEventSource);\n \n return false ;\n }\n \n //console.log('changed');\n var s = this.el.get_selection();\n Gtk.TreeIter iter;\n Gtk.TreeModel mod;\n s.get_selected(out mod, out iter);\n \n \n // var val = \"\";\n GLib.Value value;\n _this.model.el.get_value(iter, 2, out value);\n _this.model.activePath = mod.get_path(iter).to_string();\n \n var node = (JsRender.Node)value.dup_object();\n print (\"calling left_tree.node_selected\\n\");\n _this.node_selected(node, this.lastEventSource);\n while (Gtk.events_pending()) {\n Gtk.main_iteration();\n }\n var cp = mod.get_path(iter);\n Gtk.TreePath sp, ep;\n this.el.get_visible_range(out sp, out ep);\n // if sp is before cp then retuns 1.\n // if cp is before ep then retuns 1.\n if (cp.compare(sp) >= 0 && ep.compare(cp) >=1) {\n return false;\n }\n \n \n \n this.el.scroll_to_cell(new Gtk.TreePath.from_string(_this.model.activePath), null, true, 0.1f,0.0f);\n \n return false;\n }); \n //_this.after_node_change(node);\n\n// _this.model.file.changed(node, \"tree\");\n \n //Seed.print( value.get_string());\n return ;\n \n}",
- "drag_begin" : "( ctx) => {\n\t//print('SOURCE: drag-begin');\n \n \n //this.targetData = \"\";\n \n // find what is selected in our tree...\n \n var s = _this.view.el.get_selection();\n if (s.count_selected_rows() < 1) {\n return;\n }\n Gtk.TreeIter iter;\n Gtk.TreeModel mod;\n s.get_selected(out mod, out iter);\n\n \n\n // set some properties of the tree for use by the dropped element.\n GLib.Value value;\n _this.model.el.get_value(iter, 2, out value);\n var tp = mod.get_path(iter).to_string();\n var data = (JsRender.Node)(value.dup_object());\n var xname = data.fqn();\n print (\"XNAME IS \" + xname+ \"\\n\");\n this.dragData = tp;\n this.dropList = _this.main_window.windowstate.file.palete().getDropList(xname);\n \n print (\"DROP LIST IS \" + string.joinv(\", \", this.dropList) + \"\\n\");\n \n\n // make the drag icon a picture of the node that was selected\n \n \n // by default returns the path..\n var path = _this.model.el.get_path(iter);\n\n \n var pix = this.el.create_row_drag_icon ( path);\n \n Gtk.drag_set_icon_surface (ctx, pix) ;\n \n return;\n}",
- "drag_end" : " (drag_context) => {\n\t//Seed.print('LEFT-TREE: drag-end');\n this.dragData = \"\";\n this.dropList = null;\n// this.targetData = \"\";\n this.highlightDropPath(\"\",0);\n// return true;\n}",
- "drag_motion" : " ( ctx, x, y, time) => {\n print(\"got drag motion\\n\");\n var src = Gtk.drag_get_source_widget(ctx);\n this.drag_x = x;\n this.drag_y = y; \n\n if (src != this.el) {\n \n \n \n // the point of this is to detect where an item could be dropped..\n print(\"requesting drag data\\n\");\n this.drag_in_motion = true;\n \n // request data that will be recieved by the recieve... \n Gtk.drag_get_data\n (\n this.el, // will receive 'drag-data-received' signal \n ctx, // represents the current state of the DnD \n Gdk.Atom.intern(\"STRING\",true), // the target type we want \n time // time stamp \n );\n return true;\n } \n\n\n print(\"action: %d\\n\", ctx.get_actions());\n //print(\"GETTING POS\");\n var targetData = \"\";\n\n Gtk.TreePath path;\n Gtk.TreeViewDropPosition pos;\n var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);\n\n // if there are not items in the tree.. the we have to set isOver to true for anything..\n var isEmpty = false;\n if (_this.model.el.iter_n_children(null) < 1) {\n print(\"got NO children?\\n\");\n isOver = true; //??? \n isEmpty = true;\n pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;\n }\n\n\n // ------------- a drag from self..\n\n\n //var action = Gdk.DragAction.COPY;\n // unless we are copying!!! ctl button..\n \n var action = (ctx.get_actions() & Gdk.DragAction.MOVE) > 0 ?\n Gdk.DragAction.COPY : Gdk.DragAction.MOVE ;\n // Gdk.DragAction.MOVE : Gdk.DragAction.COPY ;\n\n\n if (_this.model.el.iter_n_children(null) < 1) {\n // no children.. -- asume it's ok..\n \n targetData = \"|%d|\".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);\n \n this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0); \n Gdk.drag_status(ctx, action ,time);\n return true;\n \n // continue through to allow drop...\n\n } \n \n \n\n \n \n //print(\"ISOVER? \" + isOver);\n if (!isOver) {\n \n Gdk.drag_status(ctx, 0 ,time);\n this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0); \n return false;\n\n }\n \n // drag node is parent of child..\n //console.log(\"SRC TREEPATH: \" + src.treepath);\n //console.log(\"TARGET TREEPATH: \" + data.path.to_string());\n \n // nned to check a few here..\n //Gtk.TreeViewDropPosition.INTO_OR_AFTER\n //Gtk.TreeViewDropPosition.INTO_OR_BEFORE\n //Gtk.TreeViewDropPosition.AFTER\n //Gtk.TreeViewDropPosition.BEFORE\n \n // locally dragged items to not really use the \n var selection_text = this.dragData;\n \n \n \n if (selection_text == null || selection_text.length < 1) {\n //print(\"Error - drag selection text returned NULL\");\n Gdk.drag_status(ctx, 0 ,time);\n this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);\n return false;\n }\n \n \n // see if we are dragging into ourself?\n var target_path = path.to_string(); \n print (\"Drag %s onto %s--%d\\n \", selection_text, target_path, pos);\n \n // pos : 3 = ontop - 0 = after, 1 = before\n //print(\"target_path=\"+target_path);\n\n // \n if (selection_text == target_path) {\n print(\"self drag ?? == we should perhaps allow copy onto self..\\n\");\n \n Gdk.drag_status(ctx, 0 ,time);\n this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);\n return false;\n// -- fixme -- this is not really correct..\n\n }\n \n // check that \n //print(\"DUMPING DATA\");\n //console.dump(data);\n // path, pos\n \n //print(data.path.to_string() +' => '+ data.pos);\n \n // dropList is a list of xtypes that this node could be dropped on.\n // it is set up when we start to drag..\n \n \n targetData = _this.model.findDropNodeByPath( path.to_string(), this.dropList, pos);\n \n print(\"targetDAta: \" + targetData +\"\\n\");\n \n if (targetData.length < 1) {\n //print(\"Can not find drop node path\");\n \n Gdk.drag_status(ctx, 0, time);\n this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);\n return false;\n }\n \n var td_ar = targetData.split(\"|\");\n \n \n\n Gdk.drag_status(ctx, action ,time);\n this.highlightDropPath(td_ar[0], (Gtk.TreeViewDropPosition)int.parse(td_ar[1]));\n return true;\n \n \n}",
- "drag_data_get" : "( drag_context, data, info, time) => {\n \n \n //print(\"drag-data-get\");\n var s = this.el.get_selection();\n if (s.count_selected_rows() < 1) {\n data.set_text(\"\",0); \n print(\"return empty string - no selection..\");\n return;\n }\n \n Gtk.TreeIter iter;\n Gtk.TreeModel mod;\n \n s.get_selected(out mod, out iter);\n \n \n \n GLib.Value value;\n _this.model.el.get_value(iter, 2, out value);\n var ndata = (JsRender.Node)(value.dup_object());\n \n \n \n var tp = mod.get_path(iter).to_string();\n // by default returns the path..\n \n if ( info != Gdk.Atom.intern(\"STRING\",true) ) {\n tp = ndata.toJsonString();\n } \n \n //data.set_text(tp,tp.length); \n \n data.set (data.get_target (), 8, (uchar[]) tp.to_utf8 ());\n \n \n // print(\"return \" + tp);\n }",
- "key_press_event" : "(ev) => {\n this.key_is_pressed = true;\n return false;\n}",
- "key_release_event" : "(ev) => {\n this.key_is_pressed = false;\n return false;\n}\n",
- "drag_data_received" : " (ctx, x, y, sel, info, time) => {\n \n // THIS CODE ONLY RELATES TO drag or drop of \"NEW\" elements or \"FROM another tree..\"\n \n \n // print(\"Tree: drag-data-received\\n\");\n var selection_text = (string)sel.get_data();\n //print(\"selection_text= %s\\n\",selection_text);\n\n var is_drag = this.drag_in_motion;\n \n \n\n\t\tGLib.debug(\"Is Drag %s\\n\", is_drag ? \"Y\": \"N\");\n var targetData = \"\";\n \n Gtk.TreePath path;\n Gtk.TreeViewDropPosition pos;\n var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);\n \n // if there are not items in the tree.. the we have to set isOver to true for anything..\n var isEmpty = false;\n if (_this.model.el.iter_n_children(null) < 1) {\n GLib.debug(\"got NO children?\\n\");\n isOver = true; //??? \n isEmpty = true;\n pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;\n }\n \n \n //console.log(\"LEFT-TREE: drag-motion\");\n var src = Gtk.drag_get_source_widget(ctx);\n \n // a drag from self - this should be handled by drop and motion.\n if (src == this.el) {\n GLib.debug(\"Source == this element should not happen.. ? \\n\");\n return;\n }\n //print(\"drag_data_recieved from another element\");\n \n \n \n \n if (selection_text == null || selection_text.length < 1 || !isOver) {\n // nothing valid foudn to drop...\n GLib.debug(\"empty sel text or not over\");\n if (is_drag) {\n Gdk.drag_status(ctx, 0, time);\n this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);\n return;\n }\n Gtk.drag_finish (ctx, false, false, time); // drop failed..\n // no drop action...\n return; \n \n }\n var dropNode = new JsRender.Node(); \n \n var dropNodeType = selection_text;\n var show_templates = true;\n // for drop\n if (dropNodeType[0] == '{') {\n var pa = new Json.Parser();\n try {\n pa.load_from_data(dropNodeType);\n } catch (Error e) {\n Gtk.drag_finish (ctx, false, false, time); // drop failed..\n // no drop action...\n return; \n }\n \n dropNode.loadFromJson( pa.get_root().get_object(), 2);\n dropNodeType = dropNode.fqn();\n show_templates = false;\n \n \n } else {\n \tif (selection_text.contains(\":\")) {\n\t \tvar bits = selection_text.split(\":\");\n\t dropNode.setFqn(bits[0]);\n\t dropNode.props.set(\"* prop\", bits[1]);\n \t} else {\n\n\t dropNode.setFqn(selection_text);\n }\n }\n\n \n // dropList --- need to gather this ... \n GLib.debug(\"get dropList for : %s\\n\",dropNodeType); \n var dropList = _this.main_window.windowstate.file.palete().getDropList(dropNodeType);\n \n GLib.debug(\"dropList: %s\\n\", string.joinv(\" , \", dropList));\n \n // if drag action is link ... then we can drop it anywahere...\n if ((ctx.get_actions() & Gdk.DragAction.LINK) > 0) {\n // if path is null?? dragging into an empty tree?\n targetData = (path == null ? \"\" : path.to_string()) + \"|%d\".printf((int)pos);\n } else {\n \n \n targetData = _this.model.findDropNodeByPath( isEmpty ? \"\" : path.to_string(), dropList, pos);\n }\n \n \n \n GLib.debug(\"targetDAta: %s\", targetData );\n \n if (targetData.length < 1) {\n \n // invalid drop path..\n if (this.drag_in_motion) {\n Gdk.drag_status(ctx, 0, time);\n this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);\n return;\n }\n Gtk.drag_finish (ctx, false, false, time); // drop failed..\n // no drop action...\n return;\n }\n \n \n \n var td_ar = targetData.split(\"|\");\n \n \n if (this.drag_in_motion) { \n Gdk.drag_status(ctx, Gdk.DragAction.COPY ,time);\n\n this.highlightDropPath( td_ar[0] , (Gtk.TreeViewDropPosition)int.parse(td_ar[1]));\n return;\n }\n // continue on to allow drop..\n \n\n // at this point, drag is not in motion... -- as checked above... - so it's a real drop event..\n //targetData\n \t\t// {parent}|{pos}|{prop}\n \n\n _this.model.dropNode(targetData, dropNode, show_templates);\n GLib.debug(\"ADD new node!!!\\n\");\n \n ///Xcls_DialogTemplateSelect.singleton().show( _this.model.file.palete(), node);\n \n Gtk.drag_finish (ctx, false, false,time);\n \n \n \n \n \n}",
- "drag_drop" : " ( ctx, x, y, time) => {\n //Seed.print(\"TARGET: drag-drop\");\n \n \n var src = Gtk.drag_get_source_widget(ctx);\n \n if (src != this.el) {\n \n \n \n this.drag_in_motion = false; \n // request data that will be recieved by the recieve... \n Gtk.drag_get_data\n (\n this.el, // will receive 'drag-data-received' signal \n ctx, // represents the current state of the DnD \n Gdk.Atom.intern(\"application/json\",true), // the target type we want \n time // time stamp \n );\n\n \n // No target offered by source => error\n \n\n return false;\n }\n \n // handle drop around self..\n \n \n \n //print(\"GETTING POS\");\n var targetData = \"\";\n \n Gtk.TreePath path;\n Gtk.TreeViewDropPosition pos;\n var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);\n \n // if there are not items in the tree.. the we have to set isOver to true for anything..\n var isEmpty = false;\n if (_this.model.el.iter_n_children(null) < 1) {\n print(\"got NO children?\\n\");\n isOver = true; //??? \n isEmpty = true;\n pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;\n }\n \n \n \n //var action = Gdk.DragAction.COPY;\n // unless we are copying!!! ctl button..\n \n var action = (ctx.get_actions() & Gdk.DragAction.MOVE) > 0 ?\n Gdk.DragAction.COPY : Gdk.DragAction.MOVE ;\n // Gdk.DragAction.MOVE : Gdk.DragAction.COPY ;\n\n \n if (_this.model.el.iter_n_children(null) < 1) {\n // no children.. -- asume it's ok..\n \n targetData = \"|%d|\".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);\n \n // continue through to allow drop...\n\n } else {\n \n \n \n \n \n //print(\"ISOVER? \" + isOver);\n if (!isOver) {\n \n Gtk.drag_finish (ctx, false, false, time); // drop failed..\n return true; // not over apoint!?! - no action on drop or motion..\n }\n \n // drag node is parent of child..\n //console.log(\"SRC TREEPATH: \" + src.treepath);\n //console.log(\"TARGET TREEPATH: \" + data.path.to_string());\n \n // nned to check a few here..\n //Gtk.TreeViewDropPosition.INTO_OR_AFTER\n //Gtk.TreeViewDropPosition.INTO_OR_BEFORE\n //Gtk.TreeViewDropPosition.AFTER\n //Gtk.TreeViewDropPosition.BEFORE\n \n // locally dragged items to not really use the \n var selection_text = this.dragData;\n \n \n \n if (selection_text == null || selection_text.length < 1) {\n //print(\"Error - drag selection text returned NULL\");\n \n Gtk.drag_finish (ctx, false, false, time); // drop failed..\n return true; /// -- fixme -- this is not really correct..\n } \n \n // see if we are dragging into ourself?\n print (\"got selection text of \" + selection_text);\n \n var target_path = path.to_string();\n //print(\"target_path=\"+target_path);\n\n // \n if (selection_text == target_path) {\n print(\"self drag ?? == we should perhaps allow copy onto self..\\n\");\n \n Gtk.drag_finish (ctx, false, false, time); // drop failed..\n\n return true; /// -- fixme -- this is not really correct..\n\n }\n \n // check that \n //print(\"DUMPING DATA\");\n //console.dump(data);\n // path, pos\n \n //print(data.path.to_string() +' => '+ data.pos);\n \n // dropList is a list of xtypes that this node could be dropped on.\n // it is set up when we start to drag..\n \n \n targetData = _this.model.findDropNodeByPath( path.to_string(), this.dropList, pos);\n \n print(\"targetDAta: \" + targetData +\"\\n\");\n \n if (targetData.length < 1) {\n //print(\"Can not find drop node path\");\n \n Gtk.drag_finish (ctx, false, false, time); // drop failed..\n return true;\n }\n \n \n \n // continue on to allow drop..\n }\n // at this point, drag is not in motion... -- as checked above... - so it's a real drop event..\n\n\n var delete_selection_data = false;\n \n if (action == Gdk.DragAction.ASK) {\n /* Ask the user to move or copy, then set the ctx action. */\n }\n\n if (action == Gdk.DragAction.MOVE) {\n delete_selection_data = true;\n }\n \n // drag around.. - reorder..\n _this.model.moveNode(targetData, action);\n \n \n \n \n \n // we can send stuff to souce here...\n\n\n// do we always say failure, so we handle the reall drop?\n Gtk.drag_finish (ctx, false, false,time); //delete_selection_data, time);\n\n return true;\n \n \n \n \n \n \n}"
- },
- "# string dragData" : "",
- "# string[] dropList" : "",
- "# int drag_x" : "",
- "id" : "view",
- "gboolean headers_visible" : true,
- "# int drag_y" : "",
- "* init" : "{\n var description = new Pango.FontDescription();\n description.set_size(8000);\n this.el.override_font(description);\n\n var selection = this.el.get_selection();\n selection.set_mode( Gtk.SelectionMode.SINGLE);\n\n\n // is this really needed??\n /*\n this.selection.signal['changed'].connect(function() {\n\t _this.get('/LeftTree.view').listeners.cursor_changed.apply(\n\t _this.get('/LeftTree.view'), [ _this.get('/LeftTree.view'), '']\n\t );\n });\n */\n Gtk.drag_source_set (\n\t this.el, /* widget will be drag-able */\n\t Gdk.ModifierType.BUTTON1_MASK, /* modifier that will start a drag */\n\t BuilderApplication.targetList, /* lists of target to support */\n\t Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK /* what to do with data after dropped */\n );\n\n // ?? needed??\n //Gtk.drag_source_add_text_targets(this.el); \n\n Gtk.drag_dest_set\n (\n this.el, /* widget that will accept a drop */\n Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT,\n BuilderApplication.targetList, /* lists of target to support */\n Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK /* what to do with data after dropped */\n );\n\n //Gtk.drag_dest_set_target_list(this.el, Builder.Application.targetList);\n //Gtk.drag_dest_add_text_targets(this.el);\n}\n",
- "tooltip_column" : 1,
- "bool expand" : true,
- "* pack" : "add",
- "xtype" : "TreeView",
- "$ enable_tree_lines" : true,
- "$ headers_visible" : false,
- "bool button_is_pressed" : false,
- "| void highlightDropPath" : " ( string treepath, Gtk.TreeViewDropPosition pos) {\n\n // highlighting for drag/drop\n if (treepath.length > 0) {\n this.el.set_drag_dest_row( new Gtk.TreePath.from_string( treepath ), pos);\n } else {\n this.el.set_drag_dest_row(null, Gtk.TreeViewDropPosition.INTO_OR_AFTER);\n }\n \n}",
- "$ string lastEventSource" : "\"\"",
- "bool key_is_pressed" : false,
- "# bool drag_in_motion" : "",
- "# bool blockChanges" : false,
"$ xns" : "Gtk",
- "| void setCursor" : "(string treepath, string sourceEvent) {\n\tthis.lastEventSource = sourceEvent;\n\t//this.blockChanges = true; << block changes prevents loading of 'node data' and firing of node_selected..\n this.el.set_cursor(new Gtk.TreePath.from_string(treepath), null, false); \n // fire node_selected..\n //this.blockChanges = false;\n\tthis.lastEventSource = \"\";\n}\n",
- "| void selectNode" : "(string treepath_str, string source) {\n\tthis.lastEventSource = source;\n //this.selection.select_path(new Gtk.TreePath.from_string( treepath_str));\n var tp = new Gtk.TreePath.from_string(treepath_str);\n \n this.el.set_cursor(tp, null, false); \n this.el.scroll_to_cell(tp, null, false, 0,0);\n}\n",
+ "* pack" : "add",
+ "bool always_show_image" : true,
+ "bool hexpand" : true,
"items" : [
{
- "| string findDropNode" : " (string treepath_str, string[] targets) {\n\n // this is used by the dragdrop code in the roo version AFAIR..\n\n //var path = treepath_str.replace(/^builder-/, '');\n // treemap is depreciated... - should really check if model has any entries..\n\n if (this.el.iter_n_children(null) < 1) {\n //print(\"NO KEYS\");\n return \"|%d\".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);\n }\n //print(\"FIND treepath: \" + path);\n //console.dump(this.treemap);\n \n //if (!treepath_str.match(/^builder-/)) {\n // return []; // nothing!\n //}\n if (targets.length > 0 && targets[0] == \"*\") {\n return treepath_str;\n }\n return this.findDropNodeByPath(treepath_str,targets, -1);\n}\n",
- "id" : "model",
- "currentTree" : false,
- "# DialogTemplateSelect template_select" : "null",
- "* init" : "print(\"model initialized\");\n\n",
- "| void loadFile" : "(JsRender.JsRender f) {\n //console.dump(f);\n this.el.clear();\n \n // needed???\n _this.main_window.windowstate.file = f;\n \n \n if (f.tree == null) {\n\t try {\n\t f.loadItems( );\n } catch (Error e) {\n \t\treturn;\n }\n }\n // if it's still null?\n if (f.tree == null) {\n return;\n }\n \n var o = new Gee.ArrayList<JsRender.Node>();\n o.add(f.tree);\n this.load(o,null);\n \n _this.view.el.expand_all();\n\n if (f.tree.items.size < 1) {\n // single item..\n \n //this.get('/Window.leftvpaned').el.set_position(80);\n // select first...\n _this.view.el.set_cursor( \n new Gtk.TreePath.from_string(\"0\"), null, false);\n \n \n } else {\n //this.get('/Window.leftvpaned').el.set_position(200);\n }\n \n return;\n \n \n}\n",
- "| void updateSelected" : "() {\n \n \n var s = _this.view.el.get_selection();\n \n Gtk.TreeIter iter;\n Gtk.TreeModel mod;\n \n \n \n if (!s.get_selected(out mod, out iter)) {\n return; // nothing seleted..\n }\n \n GLib.Value value;\n this.el.get_value(iter, 2, out value);\n var node = (JsRender.Node)(value.get_object());\n \n this.el.set(iter, 0, node.nodeTitle(),\n 1, node.nodeTip(), -1\n );\n}\n",
- "* pack" : "set_model",
- "xtype" : "TreeStore",
- "| string findDropNodeByPath" : " (string treepath_str, string[] targets, int in_pref = -1) {\n\n var path = treepath_str; // dupe it..\n \n \n // pref : 3 = ontop - 0 = after, 1 = before\n int pref = in_pref < 0 ? Gtk.TreeViewDropPosition.INTO_OR_AFTER : in_pref;\n \n var last = \"\";\n \n //console.dump(this.treemap);\n \n print(\"findDropNodeByPath : got path length %d / %s\\n\", path.length, path);\n \n if (path.length == 0) {\n // top drop. // just return empty..\n return \"|%d\".printf((int)pref) ;\n \n }\n \n \n while (path.length > 0) {\n \n if (path.length == treepath_str.length && pref != Gtk.TreeViewDropPosition.INTO_OR_AFTER) {\n if (path.last_index_of(\":\") < 0 ) {\n return \"\";\n }\n path = path.substring(0, path.last_index_of(\":\"));\n last = treepath_str;\n print(\"DROP before or after : using %s\\n\",path);\n continue;\n }\n \n //print(\"LOOKING FOR PATH: \" + path);\n var node_data = this.pathToNode(path);\n \n if (node_data == null) {\n print(\"node not found\");\n return \"\";\n }\n \n var xname = node_data.fqn();\n var match = \"\";\n var prop = \"\";\n \n for (var i =0; i < targets.length; i++) {\n var tg = targets[i];\n if ((tg == xname) ) {\n match = tg;\n break;\n }\n // if target is \"xxxx:name\"\n if (tg.contains(xname +\":\")) {\n match = tg;\n var ar = tg.split(\":\");\n prop = ar[1];\n break;\n }\n }\n \n if (match.length > 0) {\n if (last.length > 0) { // pref is after/before..\n // then it's after last\n //if (pref > 1) {\n // return \"\";\n //}\n return last + \"|%d\".printf((int)pref) + \"|\" + prop;\n\n \n }\n // we need to add prop - as :store -> needs to bee added when dropping onto.\n return path + \"|%d\".printf( (int) Gtk.TreeViewDropPosition.INTO_OR_AFTER) + \"|\" + prop;\n }\n /*\n last = \"\" + path;\n var par = path.split(\":\");\n string [] ppar = {};\n for (var i = 0; i < par.length-1; i++) {\n ppar += par[i];\n }\n \n path = string.joinv(\":\", ppar);\n */\n break;\n\n }\n \n return \"\";\n \n}\n",
- "| void moveNode" : "(string target_data, Gdk.DragAction action) \n{\n \n /// target_data = \"path|pos\");\n \n \n //print(\"MOVE NODE\");\n // console.dump(target_data);\n Gtk.TreeIter old_iter;\n Gtk.TreeModel mod;\n \n var s = _this.view.el.get_selection();\n s.get_selected(out mod , out old_iter);\n mod.get_path(old_iter);\n \n var node = this.pathToNode(mod.get_path(old_iter).to_string());\n //console.dump(node);\n if (node == null) {\n print(\"moveNode: ERROR - node is null?\");\n }\n \n \n\n // needs to drop first, otherwise the target_data \n // treepath will be invalid.\n\n \n if ((action & Gdk.DragAction.MOVE) > 0) {\n print(\"REMOVING OLD NODE : \" + target_data + \"\\n\");\n node.remove();\n this.dropNode(target_data, node, false);\n this.el.remove(ref old_iter);\n \n \n \n } else {\n print(\"DROPPING NODE // copy: \" + target_data + \"\\n\");\n node = node.deepClone();\n this.dropNode(target_data, node, false);\n }\n _this.changed();\n this.activePath= \"\";\n //this.updateNode(false,true);\n}\n",
- "# string activePath" : "\"\"",
- "$ columns" : "typeof(string),typeof(string),typeof(Object)",
- "| void load" : "(Gee.ArrayList<JsRender.Node> tr, Gtk.TreeIter? iter) \n{\n Gtk.TreeIter citer;\n //this.insert(citer,iter,0);\n for(var i =0 ; i < tr.size; i++) {\n if (iter != null) {\n this.el.insert(out citer,iter,-1); // why not append?\n } else {\n this.el.append(out citer,null);\n }\n \n this.el.set(citer, 0, tr.get(i).nodeTitle(),\n 1, tr.get(i).nodeTip(), -1\n );\n var o = GLib.Value(typeof(Object));\n o.set_object((Object)tr.get(i));\n \n this.el.set_value(citer, 2, o);\n \n if (tr.get(i).items.size > 0) {\n this.load(tr.get(i).items, citer);\n }\n \n }\n\n \n}",
- "| void deleteSelected" : "() {\n \n print(\"DELETE SELECTED?\");\n //_this.view.blockChanges = true;\n print(\"GET SELECTION?\");\n\n var s = _this.view.el.get_selection();\n \n print(\"GET SELECTED?\");\n Gtk.TreeIter iter;\n Gtk.TreeModel mod;\n\n \n if (!s.get_selected(out mod, out iter)) {\n return; // nothing seleted..\n }\n \n\n\n this.activePath= \"\"; \n print(\"GET vnode value?\");\n\n GLib.Value value;\n this.el.get_value(iter, 2, out value);\n var data = (JsRender.Node)(value.get_object());\n print(\"removing node from Render\\n\");\n if (data.parent == null) {\n _this.main_window.windowstate.file.tree = null;\n } else {\n data.remove();\n }\n print(\"removing node from Tree\\n\"); \n s.unselect_all();\n this.el.remove(ref iter);\n\n \n \n \n // \n \n \n\n\n this.activePath= \"\"; // again!?!? \n //this.changed(null,true);\n \n _this.changed();\n \n _this.view.blockChanges = false;\n}\n",
- "n_columns" : 3,
- "$ xns" : "Gtk",
- "| JsRender.Node pathToNode" : "(string path) {\n \n \n Gtk.TreeIter iter;\n _this.model.el.get_iter_from_string(out iter, path);\n \n GLib.Value value;\n _this.model.el.get_value(iter, 2, out value);\n \n return (JsRender.Node)value.dup_object();\n\n}",
- "| void dropNode" : "(string target_data_str, JsRender.Node node, bool show_templates) {\n// print(\"drop Node\");\n // console.dump(node);\n // console.dump(target_data);\n \n \t\t//target_data_str\n \t\t// {parent}|{pos}|{prop}\n \n \n // 0 = before , 1=after 2/3 onto\n \n \t\tGLib.debug(\"dropNode %s\", target_data_str);\n var target_data= target_data_str.split(\"|\");\n \n var parent_str = target_data[0].length > 0 ? target_data[0] : \"\";\n var pos = target_data.length > 1 ? int.parse(target_data[1]) : 2; // ontop..\n \n \n Gtk.TreePath tree_path = parent_str.length > 0 ? new Gtk.TreePath.from_string( parent_str ) : null;\n \n \n \n //print(\"add \" + tp + \"@\" + target_data[1] );\n \n JsRender.Node parentNode = null;\n \n Gtk.TreeIter iter_after;\n Gtk.TreeIter iter_par ;\n \n \n if (target_data.length == 3 && target_data[2].length > 0) {\n node.props.set(\"* prop\", target_data[2]);\n }\n\n Gtk.TreePath expand_parent = null;\n \n // we only need to show the template if it's come from else where?\n if (show_templates) {\n \n var ts = _this.main_window.windowstate.template_select;\n \n var new_node = ts.show(\n _this.main_window, // (Gtk.Window) _this.el.get_toplevel (),\n _this.main_window.windowstate.file.palete(),\n node,\n _this.main_window.windowstate.project);\n \n if (new_node == null) {\n return; // do not add?\n }\n node = new_node;\n } \n \n //print(\"pos is %d \\n\".printf(pos));\n \n Gtk.TreeIter n_iter; \n \n if ( parent_str.length < 1) {\n this.el.append(out n_iter, null); // drop at top level..\n node.parent = null;\n _this.main_window.windowstate.file.tree = node;\n \n \n } else if (pos < 2) {\n //print(target_data[1] > 0 ? 'insert_after' : 'insert_before');\n \n this.el.get_iter(out iter_after, tree_path ); \n this.el.iter_parent(out iter_par, iter_after);\n expand_parent = this.el.get_path(iter_par);\n \n GLib.Value value;\n this.el.get_value( iter_par, 2, out value);\n parentNode = (JsRender.Node)value.dup_object();\n \n \n this.el.get_value( iter_after, 2, out value);\n var relNode = (JsRender.Node)value.dup_object();\n \n if ( pos > 0 ) {\n \n this.el.insert_after(out n_iter, iter_par , iter_after);\n var ix = parentNode.items.index_of(relNode);\n parentNode.items.insert(ix+1, node);\n \n } else {\n this.el.insert_before(out n_iter, iter_par , iter_after);\n var ix = parentNode.items.index_of(relNode);\n parentNode.items.insert(ix, node);\n \n }\n node.parent = parentNode;\n \n \n \n } else {\n // print(\"appending to \" + parent_str);\n this.el.get_iter(out iter_par, tree_path);\n this.el.append(out n_iter, iter_par );\n expand_parent = this.el.get_path(iter_par);\n \n GLib.Value value;\n this.el.get_value( iter_par, 2, out value);\n parentNode = (JsRender.Node)value.dup_object();\n node.parent = parentNode;\n parentNode.items.add(node);\n }\n \n // reparent node in tree...\n \n \n // why only on no parent???\n \n //if (node.parent = null) {\n \n \n \n //}\n \n \n // work out what kind of packing to use.. -- should be in \n if (!node.has(\"pack\") && parent_str.length > 1) {\n \n _this.main_window.windowstate.file.palete().fillPack(node,parentNode);\n \n \n }\n \n // add the node...\n \n this.el.set(n_iter, 0, node.nodeTitle(), 1, node.nodeTip(), -1 );\n var o = GLib.Value(typeof(Object));\n o.set_object((Object)node);\n \n this.el.set_value(n_iter, 2, o);\n \n \n \n \n// load children - if it has any..\n \n if (node.items.size > 0) {\n this.load(node.items, n_iter);\n _this.view.el.expand_row(this.el.get_path(n_iter), true);\n } else if (expand_parent != null && !_this.view.el.is_row_expanded(expand_parent)) {\n _this.view.el.expand_row(expand_parent,true);\n }\n\n //if (tp != null && (node.items.length() > 0 || pos > 1)) {\n // _this.view.el.expand_row(this.el.get_path(iter_par), true);\n // }\n // wee need to get the empty proptypes from somewhere..\n \n //var olditer = this.activeIter;\n this.activePath = this.el.get_path(n_iter).to_string();\n\n\n // pretend button was pressed, so that we can trigger select node...\n _this.view.button_is_pressed = true;\n _this.view.lastEventSource = \"\";\n _this.view.el.set_cursor(this.el.get_path(n_iter), null, false);\n _this.view.button_is_pressed = false;\n _this.changed();\n \n \n \n}\n",
- "$ listAllTypes" : "function() {\n var s = this.get('/LeftTree.view').selection;\n print (\"LIST ALL TYPES: \" + s.count_selected_rows() );\n \n if (s.count_selected_rows() > 0) {\n var iter = new Gtk.TreeIter(); \n s.get_selected(this.el, iter);\n\n // set some properties of the tree for use by the dropped element.\n var value = new GObject.Value('');\n this.el.get_value(iter, 2, value);\n var data = JSON.parse(value.value);\n \n \n var xname = this.get('/LeftTree.model').file.guessName(data);\n console.log('selected:' + xname);\n if (xname.length) {\n return [ xname ];\n }\n return []; // could not find it..\n }\n \n var ret = [ ];\n \n var _this = this;\n function addall(li)\n {\n li.forEach(function(el) {\n // this is specific to roo!!!?\n if (!el) { // skip empty?\n return;\n }\n var fullpath = _this.file.guessName(el);\n if (fullpath.length && ret.indexOf(fullpath) < 0) {\n ret.push(fullpath);\n }\n \n \n if (el.items && el.items.length) {\n addall(el.items);\n }\n \n });\n \n \n }\n \n addall([this.currentTree]);\n \n // only if we have nothing, should we add '*top'\n if (!ret.length) {\n ret = [ '*top' ];\n }\n //console.log('all types in tree');\n //console.dump(ret);\n \n return ret;\n \n}\n",
- "| string treePathFromNode" : "(JsRender.Node node) {\n // iterate through the tree and find the node\n var ret = \"\";\n \n this.el.foreach((mod, pth, iter) => {\n // get the node..\n \n \n GLib.Value value;\n _this.model.el.get_value(iter, 2, out value);\n \n\n \n var n = (JsRender.Node)value;\n\n print(\"compare %s to %s\\n\", n.fqn(), node.fqn());\n if (node == n) {\n ret = pth.to_string();\n return true;\n }\n return false;\n });\n return ret;\n\n}\n"
- },
- {
- "utf8 title" : "test",
- "* init" : " this.el.add_attribute(_this.renderer.el , \"markup\", 0 );\n ",
- "xtype" : "TreeViewColumn",
- "* pack" : "append_column",
"$ xns" : "Gtk",
- "items" : [
- {
- "id" : "renderer",
- "* pack" : "pack_start,true",
- "xtype" : "CellRendererText",
- "$ xns" : "Gtk"
- }
- ]
+ "* pack" : "set_image",
+ "utf8 icon_name" : "list-add",
+ "xtype" : "Image"
}
- ]
+ ],
+ "listeners" : {
+ "clicked" : [
+ " ( ) => {",
+ " ",
+ "",
+ " \t_this.main_window.windowstate.showAddObject(this.el);",
+ " ",
+ "}"
+ ]
+ },
+ "string label" : "Add Child Element",
+ "xtype" : "Button"
},
{
- "id" : "LeftTreeMenu",
- "* pack" : false,
- "xtype" : "Menu",
"$ xns" : "Gtk",
+ "* init" : [
+ " this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);",
+ " ",
+ ""
+ ],
+ "* pack" : "add",
+ "Gtk.ShadowType shadow_type" : "Gtk.ShadowType.IN",
"items" : [
{
- "listeners" : {
- "activate" : " ( ) => {\n \n print(\"ACTIVATE?\");\n \n \n _this.model.deleteSelected();\n}"
- },
- "label" : "Delete Element",
+ "# bool blockChanges" : false,
+ "# bool drag_in_motion" : "",
+ "# int drag_x" : "",
+ "# int drag_y" : "",
+ "# string dragData" : "",
+ "# string[] dropList" : "",
+ "$ enable_tree_lines" : true,
+ "$ headers_visible" : false,
+ "$ string lastEventSource" : "\"\"",
+ "$ xns" : "Gtk",
+ "* init" : [
+ "{",
+ " var description = new Pango.FontDescription();",
+ " description.set_size(8000);",
+ " this.el.override_font(description);",
+ "",
+ " var selection = this.el.get_selection();",
+ " selection.set_mode( Gtk.SelectionMode.SINGLE);",
+ "",
+ "",
+ " // is this really needed??",
+ " /*",
+ " this.selection.signal['changed'].connect(function() {",
+ "\t _this.get('/LeftTree.view').listeners.cursor_changed.apply(",
+ "\t _this.get('/LeftTree.view'), [ _this.get('/LeftTree.view'), '']",
+ "\t );",
+ " });",
+ " */",
+ " Gtk.drag_source_set (",
+ "\t this.el, /* widget will be drag-able */",
+ "\t Gdk.ModifierType.BUTTON1_MASK, /* modifier that will start a drag */",
+ "\t BuilderApplication.targetList, /* lists of target to support */",
+ "\t Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK /* what to do with data after dropped */",
+ " );",
+ "",
+ " // ?? needed??",
+ " //Gtk.drag_source_add_text_targets(this.el); ",
+ "",
+ " Gtk.drag_dest_set",
+ " (",
+ " this.el, /* widget that will accept a drop */",
+ " Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT,",
+ " BuilderApplication.targetList, /* lists of target to support */",
+ " Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK /* what to do with data after dropped */",
+ " );",
+ "",
+ " //Gtk.drag_dest_set_target_list(this.el, Builder.Application.targetList);",
+ " //Gtk.drag_dest_add_text_targets(this.el);",
+ "}",
+ ""
+ ],
"* pack" : "add",
- "xtype" : "MenuItem",
- "$ xns" : "Gtk"
- },
- {
+ "bool button_is_pressed" : false,
+ "bool expand" : true,
+ "bool key_is_pressed" : false,
+ "gboolean headers_visible" : true,
+ "id" : "view",
+ "items" : [
+ {
+ "# DialogTemplateSelect template_select" : "null",
+ "# string activePath" : "\"\"",
+ "$ columns" : "typeof(string),typeof(string),typeof(Object)",
+ "$ listAllTypes" : [
+ "function() {",
+ " var s = this.get('/LeftTree.view').selection;",
+ " print (\"LIST ALL TYPES: \" + s.count_selected_rows() );",
+ " ",
+ " if (s.count_selected_rows() > 0) {",
+ " var iter = new Gtk.TreeIter(); ",
+ " s.get_selected(this.el, iter);",
+ "",
+ " // set some properties of the tree for use by the dropped element.",
+ " var value = new GObject.Value('');",
+ " this.el.get_value(iter, 2, value);",
+ " var data = JSON.parse(value.value);",
+ " ",
+ " ",
+ " var xname = this.get('/LeftTree.model').file.guessName(data);",
+ " console.log('selected:' + xname);",
+ " if (xname.length) {",
+ " return [ xname ];",
+ " }",
+ " return []; // could not find it..",
+ " }",
+ " ",
+ " var ret = [ ];",
+ " ",
+ " var _this = this;",
+ " function addall(li)",
+ " {",
+ " li.forEach(function(el) {",
+ " // this is specific to roo!!!?",
+ " if (!el) { // skip empty?",
+ " return;",
+ " }",
+ " var fullpath = _this.file.guessName(el);",
+ " if (fullpath.length && ret.indexOf(fullpath) < 0) {",
+ " ret.push(fullpath);",
+ " }",
+ " ",
+ " ",
+ " if (el.items && el.items.length) {",
+ " addall(el.items);",
+ " }",
+ " ",
+ " });",
+ " ",
+ " ",
+ " }",
+ " ",
+ " addall([this.currentTree]);",
+ " ",
+ " // only if we have nothing, should we add '*top'",
+ " if (!ret.length) {",
+ " ret = [ '*top' ];",
+ " }",
+ " //console.log('all types in tree');",
+ " //console.dump(ret);",
+ " ",
+ " return ret;",
+ " ",
+ "}",
+ ""
+ ],
+ "$ xns" : "Gtk",
+ "* init" : [
+ "print(\"model initialized\");",
+ "",
+ ""
+ ],
+ "* pack" : "set_model",
+ "currentTree" : false,
+ "id" : "model",
+ "n_columns" : 3,
+ "xtype" : "TreeStore",
+ "| JsRender.Node pathToNode" : [
+ "(string path) {",
+ " ",
+ " ",
+ " Gtk.TreeIter iter;",
+ " _this.model.el.get_iter_from_string(out iter, path);",
+ " ",
+ " GLib.Value value;",
+ " _this.model.el.get_value(iter, 2, out value);",
+ " ",
+ " return (JsRender.Node)value.dup_object();",
+ "",
+ "}"
+ ],
+ "| string findDropNode" : [
+ " (string treepath_str, string[] targets) {",
+ "",
+ " // this is used by the dragdrop code in the roo version AFAIR..",
+ "",
+ " //var path = treepath_str.replace(/^builder-/, '');",
+ " // treemap is depreciated... - should really check if model has any entries..",
+ "",
+ " if (this.el.iter_n_children(null) < 1) {",
+ " //print(\"NO KEYS\");",
+ " return \"|%d\".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);",
+ " }",
+ " //print(\"FIND treepath: \" + path);",
+ " //console.dump(this.treemap);",
+ " ",
+ " //if (!treepath_str.match(/^builder-/)) {",
+ " // return []; // nothing!",
+ " //}",
+ " if (targets.length > 0 && targets[0] == \"*\") {",
+ " return treepath_str;",
+ " }",
+ " return this.findDropNodeByPath(treepath_str,targets, -1);",
+ "}",
+ ""
+ ],
+ "| string findDropNodeByPath" : [
+ " (string treepath_str, string[] targets, int in_pref = -1) {",
+ "",
+ " var path = treepath_str; // dupe it..",
+ " ",
+ " ",
+ " // pref : 3 = ontop - 0 = after, 1 = before",
+ " int pref = in_pref < 0 ? Gtk.TreeViewDropPosition.INTO_OR_AFTER : in_pref;",
+ " ",
+ " var last = \"\";",
+ " ",
+ " //console.dump(this.treemap);",
+ " ",
+ " print(\"findDropNodeByPath : got path length %d / %s\\n\", path.length, path);",
+ " ",
+ " if (path.length == 0) {",
+ " // top drop. // just return empty..",
+ " return \"|%d\".printf((int)pref) ;",
+ " ",
+ " }",
+ " ",
+ " ",
+ " while (path.length > 0) {",
+ " ",
+ " if (path.length == treepath_str.length && pref != Gtk.TreeViewDropPosition.INTO_OR_AFTER) {",
+ " if (path.last_index_of(\":\") < 0 ) {",
+ " return \"\";",
+ " }",
+ " path = path.substring(0, path.last_index_of(\":\"));",
+ " last = treepath_str;",
+ " print(\"DROP before or after : using %s\\n\",path);",
+ " continue;",
+ " }",
+ " ",
+ " //print(\"LOOKING FOR PATH: \" + path);",
+ " var node_data = this.pathToNode(path);",
+ " ",
+ " if (node_data == null) {",
+ " print(\"node not found\");",
+ " return \"\";",
+ " }",
+ " ",
+ " var xname = node_data.fqn();",
+ " var match = \"\";",
+ " var prop = \"\";",
+ " ",
+ " for (var i =0; i < targets.length; i++) {",
+ " var tg = targets[i];",
+ " if ((tg == xname) ) {",
+ " match = tg;",
+ " break;",
+ " }",
+ " // if target is \"xxxx:name\"",
+ " if (tg.contains(xname +\":\")) {",
+ " match = tg;",
+ " var ar = tg.split(\":\");",
+ " prop = ar[1];",
+ " break;",
+ " }",
+ " }",
+ " ",
+ " if (match.length > 0) {",
+ " if (last.length > 0) { // pref is after/before..",
+ " // then it's after last",
+ " //if (pref > 1) {",
+ " // return \"\";",
+ " //}",
+ " return last + \"|%d\".printf((int)pref) + \"|\" + prop;",
+ "",
+ " ",
+ " }",
+ " // we need to add prop - as :store -> needs to bee added when dropping onto.",
+ " return path + \"|%d\".printf( (int) Gtk.TreeViewDropPosition.INTO_OR_AFTER) + \"|\" + prop;",
+ " }",
+ " /*",
+ " last = \"\" + path;",
+ " var par = path.split(\":\");",
+ " string [] ppar = {};",
+ " for (var i = 0; i < par.length-1; i++) {",
+ " ppar += par[i];",
+ " }",
+ " ",
+ " path = string.joinv(\":\", ppar);",
+ " */",
+ " break;",
+ "",
+ " }",
+ " ",
+ " return \"\";",
+ " ",
+ "}",
+ ""
+ ],
+ "| void deleteSelected" : [
+ "() {",
+ " ",
+ " print(\"DELETE SELECTED?\");",
+ " //_this.view.blockChanges = true;",
+ " print(\"GET SELECTION?\");",
+ "",
+ " var s = _this.view.el.get_selection();",
+ " ",
+ " print(\"GET SELECTED?\");",
+ " Gtk.TreeIter iter;",
+ " Gtk.TreeModel mod;",
+ "",
+ " ",
+ " if (!s.get_selected(out mod, out iter)) {",
+ " return; // nothing seleted..",
+ " }",
+ " ",
+ "",
+ "",
+ " this.activePath= \"\"; ",
+ " print(\"GET vnode value?\");",
+ "",
+ " GLib.Value value;",
+ " this.el.get_value(iter, 2, out value);",
+ " var data = (JsRender.Node)(value.get_object());",
+ " print(\"removing node from Render\\n\");",
+ " if (data.parent == null) {",
+ " _this.main_window.windowstate.file.tree = null;",
+ " } else {",
+ " data.remove();",
+ " }",
+ " print(\"removing node from Tree\\n\"); ",
+ " s.unselect_all();",
+ " this.el.remove(ref iter);",
+ "",
+ " ",
+ " ",
+ " ",
+ " // ",
+ " ",
+ " ",
+ "",
+ "",
+ " this.activePath= \"\"; // again!?!? ",
+ " //this.changed(null,true);",
+ " ",
+ " _this.changed();",
+ " ",
+ " _this.view.blockChanges = false;",
+ "}",
+ ""
+ ],
+ "| void dropNode" : [
+ "(string target_data_str, JsRender.Node node, bool show_templates) {",
+ "// print(\"drop Node\");",
+ " // console.dump(node);",
+ " // console.dump(target_data);",
+ " ",
+ " \t\t//target_data_str",
+ " \t\t// {parent}|{pos}|{prop}",
+ " ",
+ " ",
+ " // 0 = before , 1=after 2/3 onto",
+ " ",
+ " \t\tGLib.debug(\"dropNode %s\", target_data_str);",
+ " var target_data= target_data_str.split(\"|\");",
+ " ",
+ " var parent_str = target_data[0].length > 0 ? target_data[0] : \"\";",
+ " var pos = target_data.length > 1 ? int.parse(target_data[1]) : 2; // ontop..",
+ " ",
+ " ",
+ " Gtk.TreePath tree_path = parent_str.length > 0 ? new Gtk.TreePath.from_string( parent_str ) : null;",
+ " ",
+ " ",
+ " ",
+ " //print(\"add \" + tp + \"@\" + target_data[1] );",
+ " ",
+ " JsRender.Node parentNode = null;",
+ " ",
+ " Gtk.TreeIter iter_after;",
+ " Gtk.TreeIter iter_par ;",
+ " ",
+ " ",
+ " if (target_data.length == 3 && target_data[2].length > 0) {",
+ " node.props.set(\"* prop\", target_data[2]);",
+ " }",
+ "",
+ " Gtk.TreePath expand_parent = null;",
+ " ",
+ " // we only need to show the template if it's come from else where?",
+ " if (show_templates) {",
+ " ",
+ " var ts = _this.main_window.windowstate.template_select;",
+ " ",
+ " var new_node = ts.show(",
+ " _this.main_window, // (Gtk.Window) _this.el.get_toplevel (),",
+ " _this.main_window.windowstate.file.palete(),",
+ " node,",
+ " _this.main_window.windowstate.project);",
+ " ",
+ " if (new_node == null) {",
+ " return; // do not add?",
+ " }",
+ " node = new_node;",
+ " } ",
+ " ",
+ " //print(\"pos is %d \\n\".printf(pos));",
+ " ",
+ " Gtk.TreeIter n_iter; ",
+ " ",
+ " if ( parent_str.length < 1) {",
+ " this.el.append(out n_iter, null); // drop at top level..",
+ " node.parent = null;",
+ " _this.main_window.windowstate.file.tree = node;",
+ " ",
+ " ",
+ " } else if (pos < 2) {",
+ " //print(target_data[1] > 0 ? 'insert_after' : 'insert_before');",
+ " ",
+ " this.el.get_iter(out iter_after, tree_path ); ",
+ " this.el.iter_parent(out iter_par, iter_after);",
+ " expand_parent = this.el.get_path(iter_par);",
+ " ",
+ " GLib.Value value;",
+ " this.el.get_value( iter_par, 2, out value);",
+ " parentNode = (JsRender.Node)value.dup_object();",
+ " ",
+ " ",
+ " this.el.get_value( iter_after, 2, out value);",
+ " var relNode = (JsRender.Node)value.dup_object();",
+ " ",
+ " if ( pos > 0 ) {",
+ " ",
+ " this.el.insert_after(out n_iter, iter_par , iter_after);",
+ " var ix = parentNode.items.index_of(relNode);",
+ " parentNode.items.insert(ix+1, node);",
+ " ",
+ " } else {",
+ " this.el.insert_before(out n_iter, iter_par , iter_after);",
+ " var ix = parentNode.items.index_of(relNode);",
+ " parentNode.items.insert(ix, node);",
+ " ",
+ " }",
+ " node.parent = parentNode;",
+ " ",
+ " ",
+ " ",
+ " } else {",
+ " // print(\"appending to \" + parent_str);",
+ " this.el.get_iter(out iter_par, tree_path);",
+ " this.el.append(out n_iter, iter_par );",
+ " expand_parent = this.el.get_path(iter_par);",
+ " ",
+ " GLib.Value value;",
+ " this.el.get_value( iter_par, 2, out value);",
+ " parentNode = (JsRender.Node)value.dup_object();",
+ " node.parent = parentNode;",
+ " parentNode.items.add(node);",
+ " }",
+ " ",
+ " // reparent node in tree...",
+ " ",
+ " ",
+ " // why only on no parent???",
+ " ",
+ " //if (node.parent = null) {",
+ " ",
+ " ",
+ " ",
+ " //}",
+ " ",
+ " ",
+ " // work out what kind of packing to use.. -- should be in ",
+ " if (!node.has(\"pack\") && parent_str.length > 1) {",
+ " ",
+ " _this.main_window.windowstate.file.palete().fillPack(node,parentNode);",
+ " ",
+ " ",
+ " }",
+ " ",
+ " // add the node...",
+ " ",
+ " this.el.set(n_iter, 0, node.nodeTitle(), 1, node.nodeTip(), -1 );",
+ " var o = GLib.Value(typeof(Object));",
+ " o.set_object((Object)node);",
+ " ",
+ " this.el.set_value(n_iter, 2, o);",
+ " ",
+ " ",
+ " ",
+ " ",
+ "// load children - if it has any..",
+ " ",
+ " if (node.items.size > 0) {",
+ " this.load(node.items, n_iter);",
+ " _this.view.el.expand_row(this.el.get_path(n_iter), true);",
+ " } else if (expand_parent != null && !_this.view.el.is_row_expanded(expand_parent)) {",
+ " _this.view.el.expand_row(expand_parent,true);",
+ " }",
+ "",
+ " //if (tp != null && (node.items.length() > 0 || pos > 1)) {",
+ " // _this.view.el.expand_row(this.el.get_path(iter_par), true);",
+ " // }",
+ " // wee need to get the empty proptypes from somewhere..",
+ " ",
+ " //var olditer = this.activeIter;",
+ " this.activePath = this.el.get_path(n_iter).to_string();",
+ "",
+ "",
+ " // pretend button was pressed, so that we can trigger select node...",
+ " _this.view.button_is_pressed = true;",
+ " _this.view.lastEventSource = \"\";",
+ " _this.view.el.set_cursor(this.el.get_path(n_iter), null, false);",
+ " _this.view.button_is_pressed = false;",
+ " _this.changed();",
+ " ",
+ " ",
+ " ",
+ "}",
+ ""
+ ],
+ "| void load" : [
+ "(Gee.ArrayList<JsRender.Node> tr, Gtk.TreeIter? iter) ",
+ "{",
+ " Gtk.TreeIter citer;",
+ " //this.insert(citer,iter,0);",
+ " for(var i =0 ; i < tr.size; i++) {",
+ " if (iter != null) {",
+ " this.el.insert(out citer,iter,-1); // why not append?",
+ " } else {",
+ " this.el.append(out citer,null);",
+ " }",
+ " ",
+ " this.el.set(citer, 0, tr.get(i).nodeTitle(),",
+ " 1, tr.get(i).nodeTip(), -1",
+ " );",
+ " var o = GLib.Value(typeof(Object));",
+ " o.set_object((Object)tr.get(i));",
+ " ",
+ " this.el.set_value(citer, 2, o);",
+ " ",
+ " if (tr.get(i).items.size > 0) {",
+ " this.load(tr.get(i).items, citer);",
+ " }",
+ " ",
+ " }",
+ "",
+ " ",
+ "}"
+ ],
+ "| void loadFile" : [
+ "(JsRender.JsRender f) {",
+ " //console.dump(f);",
+ " this.el.clear();",
+ " _this.main_window.windowstate.leftTreeNodeSelected(null, \"\");",
+ " // needed???",
+ " _this.main_window.windowstate.file = f;",
+ " ",
+ " ",
+ " if (f.tree == null) {",
+ "\t try {",
+ "\t f.loadItems( );",
+ " } catch (Error e) {",
+ " \t\treturn;",
+ " }",
+ " }",
+ " // if it's still null?",
+ " if (f.tree == null) {",
+ " return;",
+ " }",
+ " ",
+ " var o = new Gee.ArrayList<JsRender.Node>();",
+ " o.add(f.tree);",
+ " this.load(o,null);",
+ " ",
+ " _this.view.el.expand_all();",
+ "",
+ " if (f.tree.items.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);",
+ " }",
+ " ",
+ " return;",
+ " ",
+ " ",
+ "}",
+ ""
+ ],
+ "| void moveNode" : [
+ "(string target_data, Gdk.DragAction action) ",
+ "{",
+ " ",
+ " /// target_data = \"path|pos\");",
+ " ",
+ " ",
+ " //print(\"MOVE NODE\");",
+ " // console.dump(target_data);",
+ " Gtk.TreeIter old_iter;",
+ " Gtk.TreeModel mod;",
+ " ",
+ " var s = _this.view.el.get_selection();",
+ " s.get_selected(out mod , out old_iter);",
+ " mod.get_path(old_iter);",
+ " ",
+ " var node = this.pathToNode(mod.get_path(old_iter).to_string());",
+ " //console.dump(node);",
+ " if (node == null) {",
+ " print(\"moveNode: ERROR - node is null?\");",
+ " }",
+ " ",
+ " ",
+ "",
+ " // needs to drop first, otherwise the target_data ",
+ " // treepath will be invalid.",
+ "",
+ " ",
+ " if ((action & Gdk.DragAction.MOVE) > 0) {",
+ " print(\"REMOVING OLD NODE : \" + target_data + \"\\n\");",
+ " node.remove();",
+ " this.dropNode(target_data, node, false);",
+ " this.el.remove(ref old_iter);",
+ " ",
+ " ",
+ " ",
+ " } else {",
+ " print(\"DROPPING NODE // copy: \" + target_data + \"\\n\");",
+ " node = node.deepClone();",
+ " this.dropNode(target_data, node, false);",
+ " }",
+ " _this.changed();",
+ " this.activePath= \"\";",
+ " //this.updateNode(false,true);",
+ "}",
+ ""
+ ],
+ "| void updateSelected" : [
+ "() {",
+ " ",
+ " ",
+ " var s = _this.view.el.get_selection();",
+ " ",
+ " Gtk.TreeIter iter;",
+ " Gtk.TreeModel mod;",
+ " ",
+ " ",
+ " ",
+ " if (!s.get_selected(out mod, out iter)) {",
+ " return; // nothing seleted..",
+ " }",
+ " ",
+ " GLib.Value value;",
+ " this.el.get_value(iter, 2, out value);",
+ " var node = (JsRender.Node)(value.get_object());",
+ " ",
+ " this.el.set(iter, 0, node.nodeTitle(),",
+ " 1, node.nodeTip(), -1",
+ " );",
+ "}",
+ ""
+ ],
+ "| string treePathFromNode" : [
+ "(JsRender.Node node) {",
+ " // iterate through the tree and find the node",
+ " var ret = \"\";",
+ " ",
+ " this.el.foreach((mod, pth, iter) => {",
+ " // get the node..",
+ " ",
+ " ",
+ " GLib.Value value;",
+ " _this.model.el.get_value(iter, 2, out value);",
+ " ",
+ "",
+ " ",
+ " var n = (JsRender.Node)value;",
+ "",
+ " print(\"compare %s to %s\\n\", n.fqn(), node.fqn());",
+ " if (node == n) {",
+ " ret = pth.to_string();",
+ " return true;",
+ " }",
+ " return false;",
+ " });",
+ " return ret;",
+ "",
+ "}",
+ ""
+ ]
+ },
+ {
+ "$ xns" : "Gtk",
+ "* init" : [
+ " this.el.add_attribute(_this.renderer.el , \"markup\", 0 );",
+ " "
+ ],
+ "* pack" : "append_column",
+ "items" : [
+ {
+ "$ xns" : "Gtk",
+ "* pack" : "pack_start,true",
+ "id" : "renderer",
+ "xtype" : "CellRendererText"
+ }
+ ],
+ "utf8 title" : "test",
+ "xtype" : "TreeViewColumn"
+ }
+ ],
"listeners" : {
- "activate" : " () => {\n\n DialogSaveTemplate.singleton().show(\n (Gtk.Window) _this.el.get_toplevel (), \n _this.main_window.windowstate.file.palete(), \n _this.getActiveElement()\n );\n \n \n}"
+ "button_press_event" : [
+ " ( ev) => {",
+ " //console.log(\"button press?\");",
+ " this.button_is_pressed = true;",
+ " print(\"BUTTON DOWN\\n\");",
+ " ",
+ " this.lastEventSource = \"tree\";",
+ " if (! _this.before_node_change() ) {",
+ " ",
+ " return true;",
+ " }",
+ " ",
+ "",
+ " ",
+ " if (ev.type != Gdk.EventType.BUTTON_PRESS || ev.button != 3) {",
+ " //print(\"click\" + ev.type);",
+ " return false;",
+ " }",
+ " Gtk.TreePath res;",
+ " if (!_this.view.el.get_path_at_pos((int)ev.x,(int)ev.y, out res, null, null, null) ) {",
+ " return true;",
+ " }",
+ " ",
+ " this.el.get_selection().select_path(res);",
+ " ",
+ " //if (!this.get('/LeftTreeMenu').el) { ",
+ " // this.get('/LeftTreeMenu').init(); ",
+ " // }",
+ " ",
+ " _this.LeftTreeMenu.el.set_screen(Gdk.Screen.get_default());",
+ " _this.LeftTreeMenu.el.show_all();",
+ " _this.LeftTreeMenu.el.popup(null, null, null, 3, ev.time);",
+ " // print(\"click:\" + res.path.to_string());",
+ " return true;",
+ "}"
+ ],
+ "button_release_event" : [
+ "(ev) => { ",
+ " this.button_is_pressed = false;",
+ " return false;",
+ "}"
+ ],
+ "cursor_changed" : [
+ " ( ) => {",
+ " print(\"LEFT TREE Cursor Changed\\n\");",
+ "\tif (!this.button_is_pressed && !this.key_is_pressed) {",
+ "\t\t// then event was started by some other action",
+ "\t\t// which should manually trigger all the events..",
+ "\t\tprint(\"SKIPPING select - no button or key pressed\\n\");",
+ "\t\treturn;",
+ "\t}",
+ "",
+ "",
+ " if (this.blockChanges) { // probably not needed.. ",
+ "\t\tprint(\"SKIPPING select - blockchanges set..\\n\"); ",
+ " return ;",
+ " }",
+ " if (!_this.before_node_change( ) ) {",
+ "\t this.blockChanges = true;",
+ "\t this.el.get_selection().unselect_all();",
+ "\t this.blockChanges = false;",
+ "\t ",
+ "\t return;",
+ " }",
+ " if (_this.main_window.windowstate.file == null) {",
+ " \t\tprint(\"SKIPPING select windowstate file is not set...\\n\"); ",
+ " return;",
+ " } ",
+ " ",
+ " //var render = this.get('/LeftTree').getRenderer(); ",
+ " print(\"LEFT TREE -> view -> selection changed called\\n\");",
+ " ",
+ " ",
+ " // -- it appears that the selection is not updated.",
+ " ",
+ " GLib.Timeout.add_full(GLib.Priority.DEFAULT,10 , () => {",
+ " print(\"LEFT TREE -> view -> selection changed TIMEOUT CALLED\\n\");",
+ "",
+ " if (this.el.get_selection().count_selected_rows() < 1) {",
+ "",
+ " print(\"selected rows < 1\\n\");",
+ " //??this.model.load( false);",
+ " _this.node_selected(null, this.lastEventSource);",
+ " ",
+ " return false ;",
+ " }",
+ " ",
+ " //console.log('changed');",
+ " var s = this.el.get_selection();",
+ " Gtk.TreeIter iter;",
+ " Gtk.TreeModel mod;",
+ " s.get_selected(out mod, out iter);",
+ " ",
+ " ",
+ " // var val = \"\";",
+ " GLib.Value value;",
+ " _this.model.el.get_value(iter, 2, out value);",
+ " _this.model.activePath = mod.get_path(iter).to_string();",
+ " ",
+ " var node = (JsRender.Node)value.dup_object();",
+ " print (\"calling left_tree.node_selected\\n\");",
+ " _this.node_selected(node, this.lastEventSource);",
+ " while (Gtk.events_pending()) {",
+ " Gtk.main_iteration();",
+ " }",
+ " var cp = mod.get_path(iter);",
+ " Gtk.TreePath sp, ep;",
+ " this.el.get_visible_range(out sp, out ep);",
+ " // if sp is before cp then retuns 1.",
+ " // if cp is before ep then retuns 1.",
+ " if (cp.compare(sp) >= 0 && ep.compare(cp) >=1) {",
+ " return false;",
+ " }",
+ " ",
+ " ",
+ " ",
+ " this.el.scroll_to_cell(new Gtk.TreePath.from_string(_this.model.activePath), null, true, 0.1f,0.0f);",
+ " ",
+ " return false;",
+ " }); ",
+ " //_this.after_node_change(node);",
+ "",
+ "// _this.model.file.changed(node, \"tree\");",
+ " ",
+ " //Seed.print( value.get_string());",
+ " return ;",
+ " ",
+ "}"
+ ],
+ "drag_begin" : [
+ "( ctx) => {",
+ "\t//print('SOURCE: drag-begin');",
+ " ",
+ " ",
+ " //this.targetData = \"\";",
+ " ",
+ " // find what is selected in our tree...",
+ " ",
+ " var s = _this.view.el.get_selection();",
+ " if (s.count_selected_rows() < 1) {",
+ " return;",
+ " }",
+ " Gtk.TreeIter iter;",
+ " Gtk.TreeModel mod;",
+ " s.get_selected(out mod, out iter);",
+ "",
+ " ",
+ "",
+ " // set some properties of the tree for use by the dropped element.",
+ " GLib.Value value;",
+ " _this.model.el.get_value(iter, 2, out value);",
+ " var tp = mod.get_path(iter).to_string();",
+ " var data = (JsRender.Node)(value.dup_object());",
+ " var xname = data.fqn();",
+ " print (\"XNAME IS \" + xname+ \"\\n\");",
+ " this.dragData = tp;",
+ " this.dropList = _this.main_window.windowstate.file.palete().getDropList(xname);",
+ " ",
+ " print (\"DROP LIST IS \" + string.joinv(\", \", this.dropList) + \"\\n\");",
+ " ",
+ "",
+ " // make the drag icon a picture of the node that was selected",
+ " ",
+ " ",
+ " // by default returns the path..",
+ " var path = _this.model.el.get_path(iter);",
+ "",
+ " ",
+ " var pix = this.el.create_row_drag_icon ( path);",
+ " ",
+ " Gtk.drag_set_icon_surface (ctx, pix) ;",
+ " ",
+ " return;",
+ "}"
+ ],
+ "drag_data_get" : [
+ "( drag_context, data, info, time) => {",
+ " ",
+ " ",
+ " //print(\"drag-data-get\");",
+ " var s = this.el.get_selection();",
+ " if (s.count_selected_rows() < 1) {",
+ " data.set_text(\"\",0); ",
+ " print(\"return empty string - no selection..\");",
+ " return;",
+ " }",
+ " ",
+ " Gtk.TreeIter iter;",
+ " Gtk.TreeModel mod;",
+ " ",
+ " s.get_selected(out mod, out iter);",
+ " ",
+ " ",
+ " ",
+ " GLib.Value value;",
+ " _this.model.el.get_value(iter, 2, out value);",
+ " var ndata = (JsRender.Node)(value.dup_object());",
+ " ",
+ " ",
+ " ",
+ " var tp = mod.get_path(iter).to_string();",
+ " // by default returns the path..",
+ " ",
+ " if ( info != Gdk.Atom.intern(\"STRING\",true) ) {",
+ " tp = ndata.toJsonString();",
+ " } ",
+ " ",
+ " //data.set_text(tp,tp.length); ",
+ " ",
+ " data.set (data.get_target (), 8, (uchar[]) tp.to_utf8 ());",
+ " ",
+ " ",
+ " // print(\"return \" + tp);",
+ " }"
+ ],
+ "drag_data_received" : [
+ " (ctx, x, y, sel, info, time) => {",
+ " ",
+ " // THIS CODE ONLY RELATES TO drag or drop of \"NEW\" elements or \"FROM another tree..\"",
+ " ",
+ " ",
+ " // print(\"Tree: drag-data-received\\n\");",
+ " var selection_text = (string)sel.get_data();",
+ " //print(\"selection_text= %s\\n\",selection_text);",
+ "",
+ " var is_drag = this.drag_in_motion;",
+ " ",
+ " ",
+ "",
+ "\t\tGLib.debug(\"Is Drag %s\\n\", is_drag ? \"Y\": \"N\");",
+ " var targetData = \"\";",
+ " ",
+ " Gtk.TreePath path;",
+ " Gtk.TreeViewDropPosition pos;",
+ " var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);",
+ " ",
+ " // if there are not items in the tree.. the we have to set isOver to true for anything..",
+ " var isEmpty = false;",
+ " if (_this.model.el.iter_n_children(null) < 1) {",
+ " GLib.debug(\"got NO children?\\n\");",
+ " isOver = true; //??? ",
+ " isEmpty = true;",
+ " pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;",
+ " }",
+ " ",
+ " ",
+ " //console.log(\"LEFT-TREE: drag-motion\");",
+ " var src = Gtk.drag_get_source_widget(ctx);",
+ " ",
+ " // a drag from self - this should be handled by drop and motion.",
+ " if (src == this.el) {",
+ " GLib.debug(\"Source == this element should not happen.. ? \\n\");",
+ " return;",
+ " }",
+ " //print(\"drag_data_recieved from another element\");",
+ " ",
+ " ",
+ " ",
+ " ",
+ " if (selection_text == null || selection_text.length < 1 || !isOver) {",
+ " // nothing valid foudn to drop...",
+ " GLib.debug(\"empty sel text or not over\");",
+ " if (is_drag) {",
+ " Gdk.drag_status(ctx, 0, time);",
+ " this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);",
+ " return;",
+ " }",
+ " Gtk.drag_finish (ctx, false, false, time); // drop failed..",
+ " // no drop action...",
+ " return; ",
+ " ",
+ " }",
+ " var dropNode = new JsRender.Node(); ",
+ " ",
+ " var dropNodeType = selection_text;",
+ " var show_templates = true;",
+ " // for drop",
+ " if (dropNodeType[0] == '{') {",
+ " var pa = new Json.Parser();",
+ " try {",
+ " pa.load_from_data(dropNodeType);",
+ " } catch (Error e) {",
+ " Gtk.drag_finish (ctx, false, false, time); // drop failed..",
+ " // no drop action...",
+ " return; ",
+ " }",
+ " ",
+ " dropNode.loadFromJson( pa.get_root().get_object(), 2);",
+ " dropNodeType = dropNode.fqn();",
+ " show_templates = false;",
+ " ",
+ " ",
+ " } else {",
+ " \tif (selection_text.contains(\":\")) {",
+ "\t \tvar bits = selection_text.split(\":\");",
+ "\t dropNode.setFqn(bits[0]);",
+ "\t dropNode.props.set(\"* prop\", bits[1]);",
+ " \t} else {",
+ "",
+ "\t dropNode.setFqn(selection_text);",
+ " }",
+ " }",
+ "",
+ " ",
+ " // dropList --- need to gather this ... ",
+ " GLib.debug(\"get dropList for : %s\\n\",dropNodeType); ",
+ " var dropList = _this.main_window.windowstate.file.palete().getDropList(dropNodeType);",
+ " ",
+ " GLib.debug(\"dropList: %s\\n\", string.joinv(\" , \", dropList));",
+ " ",
+ " // if drag action is link ... then we can drop it anywahere...",
+ " if ((ctx.get_actions() & Gdk.DragAction.LINK) > 0) {",
+ " // if path is null?? dragging into an empty tree?",
+ " targetData = (path == null ? \"\" : path.to_string()) + \"|%d\".printf((int)pos);",
+ " } else {",
+ " ",
+ " ",
+ " targetData = _this.model.findDropNodeByPath( isEmpty ? \"\" : path.to_string(), dropList, pos);",
+ " }",
+ " ",
+ " ",
+ " ",
+ " GLib.debug(\"targetDAta: %s\", targetData );",
+ " ",
+ " if (targetData.length < 1) {",
+ " ",
+ " // invalid drop path..",
+ " if (this.drag_in_motion) {",
+ " Gdk.drag_status(ctx, 0, time);",
+ " this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);",
+ " return;",
+ " }",
+ " Gtk.drag_finish (ctx, false, false, time); // drop failed..",
+ " // no drop action...",
+ " return;",
+ " }",
+ " ",
+ " ",
+ " ",
+ " var td_ar = targetData.split(\"|\");",
+ " ",
+ " ",
+ " if (this.drag_in_motion) { ",
+ " Gdk.drag_status(ctx, Gdk.DragAction.COPY ,time);",
+ "",
+ " this.highlightDropPath( td_ar[0] , (Gtk.TreeViewDropPosition)int.parse(td_ar[1]));",
+ " return;",
+ " }",
+ " // continue on to allow drop..",
+ " ",
+ "",
+ " // at this point, drag is not in motion... -- as checked above... - so it's a real drop event..",
+ " //targetData",
+ " \t\t// {parent}|{pos}|{prop}",
+ " ",
+ "",
+ " _this.model.dropNode(targetData, dropNode, show_templates);",
+ " GLib.debug(\"ADD new node!!!\\n\");",
+ " ",
+ " ///Xcls_DialogTemplateSelect.singleton().show( _this.model.file.palete(), node);",
+ " ",
+ " Gtk.drag_finish (ctx, false, false,time);",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ "}"
+ ],
+ "drag_drop" : [
+ " ( ctx, x, y, time) => {",
+ " //Seed.print(\"TARGET: drag-drop\");",
+ " ",
+ " ",
+ " var src = Gtk.drag_get_source_widget(ctx);",
+ " ",
+ " if (src != this.el) {",
+ " ",
+ " ",
+ " ",
+ " this.drag_in_motion = false; ",
+ " // request data that will be recieved by the recieve... ",
+ " Gtk.drag_get_data",
+ " (",
+ " this.el, // will receive 'drag-data-received' signal ",
+ " ctx, // represents the current state of the DnD ",
+ " Gdk.Atom.intern(\"application/json\",true), // the target type we want ",
+ " time // time stamp ",
+ " );",
+ "",
+ " ",
+ " // No target offered by source => error",
+ " ",
+ "",
+ " return false;",
+ " }",
+ " ",
+ " // handle drop around self..",
+ " ",
+ " ",
+ " ",
+ " //print(\"GETTING POS\");",
+ " var targetData = \"\";",
+ " ",
+ " Gtk.TreePath path;",
+ " Gtk.TreeViewDropPosition pos;",
+ " var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);",
+ " ",
+ " // if there are not items in the tree.. the we have to set isOver to true for anything..",
+ " var isEmpty = false;",
+ " if (_this.model.el.iter_n_children(null) < 1) {",
+ " print(\"got NO children?\\n\");",
+ " isOver = true; //??? ",
+ " isEmpty = true;",
+ " pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;",
+ " }",
+ " ",
+ " ",
+ " ",
+ " //var action = Gdk.DragAction.COPY;",
+ " // unless we are copying!!! ctl button..",
+ " ",
+ " var action = (ctx.get_actions() & Gdk.DragAction.MOVE) > 0 ?",
+ " Gdk.DragAction.COPY : Gdk.DragAction.MOVE ;",
+ " // Gdk.DragAction.MOVE : Gdk.DragAction.COPY ;",
+ "",
+ " ",
+ " if (_this.model.el.iter_n_children(null) < 1) {",
+ " // no children.. -- asume it's ok..",
+ " ",
+ " targetData = \"|%d|\".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);",
+ " ",
+ " // continue through to allow drop...",
+ "",
+ " } else {",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " //print(\"ISOVER? \" + isOver);",
+ " if (!isOver) {",
+ " ",
+ " Gtk.drag_finish (ctx, false, false, time); // drop failed..",
+ " return true; // not over apoint!?! - no action on drop or motion..",
+ " }",
+ " ",
+ " // drag node is parent of child..",
+ " //console.log(\"SRC TREEPATH: \" + src.treepath);",
+ " //console.log(\"TARGET TREEPATH: \" + data.path.to_string());",
+ " ",
+ " // nned to check a few here..",
+ " //Gtk.TreeViewDropPosition.INTO_OR_AFTER",
+ " //Gtk.TreeViewDropPosition.INTO_OR_BEFORE",
+ " //Gtk.TreeViewDropPosition.AFTER",
+ " //Gtk.TreeViewDropPosition.BEFORE",
+ " ",
+ " // locally dragged items to not really use the ",
+ " var selection_text = this.dragData;",
+ " ",
+ " ",
+ " ",
+ " if (selection_text == null || selection_text.length < 1) {",
+ " //print(\"Error - drag selection text returned NULL\");",
+ " ",
+ " Gtk.drag_finish (ctx, false, false, time); // drop failed..",
+ " return true; /// -- fixme -- this is not really correct..",
+ " } ",
+ " ",
+ " // see if we are dragging into ourself?",
+ " print (\"got selection text of \" + selection_text);",
+ " ",
+ " var target_path = path.to_string();",
+ " //print(\"target_path=\"+target_path);",
+ "",
+ " // ",
+ " if (selection_text == target_path) {",
+ " print(\"self drag ?? == we should perhaps allow copy onto self..\\n\");",
+ " ",
+ " Gtk.drag_finish (ctx, false, false, time); // drop failed..",
+ "",
+ " return true; /// -- fixme -- this is not really correct..",
+ "",
+ " }",
+ " ",
+ " // check that ",
+ " //print(\"DUMPING DATA\");",
+ " //console.dump(data);",
+ " // path, pos",
+ " ",
+ " //print(data.path.to_string() +' => '+ data.pos);",
+ " ",
+ " // dropList is a list of xtypes that this node could be dropped on.",
+ " // it is set up when we start to drag..",
+ " ",
+ " ",
+ " targetData = _this.model.findDropNodeByPath( path.to_string(), this.dropList, pos);",
+ " ",
+ " print(\"targetDAta: \" + targetData +\"\\n\");",
+ " ",
+ " if (targetData.length < 1) {",
+ " //print(\"Can not find drop node path\");",
+ " ",
+ " Gtk.drag_finish (ctx, false, false, time); // drop failed..",
+ " return true;",
+ " }",
+ " ",
+ " ",
+ " ",
+ " // continue on to allow drop..",
+ " }",
+ " // at this point, drag is not in motion... -- as checked above... - so it's a real drop event..",
+ "",
+ "",
+ " var delete_selection_data = false;",
+ " ",
+ " if (action == Gdk.DragAction.ASK) {",
+ " /* Ask the user to move or copy, then set the ctx action. */",
+ " }",
+ "",
+ " if (action == Gdk.DragAction.MOVE) {",
+ " delete_selection_data = true;",
+ " }",
+ " ",
+ " // drag around.. - reorder..",
+ " _this.model.moveNode(targetData, action);",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " // we can send stuff to souce here...",
+ "",
+ "",
+ "// do we always say failure, so we handle the reall drop?",
+ " Gtk.drag_finish (ctx, false, false,time); //delete_selection_data, time);",
+ "",
+ " return true;",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ "}"
+ ],
+ "drag_end" : [
+ " (drag_context) => {",
+ "\t//Seed.print('LEFT-TREE: drag-end');",
+ " this.dragData = \"\";",
+ " this.dropList = null;",
+ "// this.targetData = \"\";",
+ " this.highlightDropPath(\"\",0);",
+ "// return true;",
+ "}"
+ ],
+ "drag_motion" : [
+ " ( ctx, x, y, time) => {",
+ " print(\"got drag motion\\n\");",
+ " var src = Gtk.drag_get_source_widget(ctx);",
+ " this.drag_x = x;",
+ " this.drag_y = y; ",
+ "",
+ " if (src != this.el) {",
+ " ",
+ " ",
+ " ",
+ " // the point of this is to detect where an item could be dropped..",
+ " print(\"requesting drag data\\n\");",
+ " this.drag_in_motion = true;",
+ " ",
+ " // request data that will be recieved by the recieve... ",
+ " Gtk.drag_get_data",
+ " (",
+ " this.el, // will receive 'drag-data-received' signal ",
+ " ctx, // represents the current state of the DnD ",
+ " Gdk.Atom.intern(\"STRING\",true), // the target type we want ",
+ " time // time stamp ",
+ " );",
+ " return true;",
+ " } ",
+ "",
+ "",
+ " print(\"action: %d\\n\", ctx.get_actions());",
+ " //print(\"GETTING POS\");",
+ " var targetData = \"\";",
+ "",
+ " Gtk.TreePath path;",
+ " Gtk.TreeViewDropPosition pos;",
+ " var isOver = _this.view.el.get_dest_row_at_pos(this.drag_x,this.drag_y, out path, out pos);",
+ "",
+ " // if there are not items in the tree.. the we have to set isOver to true for anything..",
+ " var isEmpty = false;",
+ " if (_this.model.el.iter_n_children(null) < 1) {",
+ " print(\"got NO children?\\n\");",
+ " isOver = true; //??? ",
+ " isEmpty = true;",
+ " pos = Gtk.TreeViewDropPosition.INTO_OR_AFTER;",
+ " }",
+ "",
+ "",
+ " // ------------- a drag from self..",
+ "",
+ "",
+ " //var action = Gdk.DragAction.COPY;",
+ " // unless we are copying!!! ctl button..",
+ " ",
+ " var action = (ctx.get_actions() & Gdk.DragAction.MOVE) > 0 ?",
+ " Gdk.DragAction.COPY : Gdk.DragAction.MOVE ;",
+ " // Gdk.DragAction.MOVE : Gdk.DragAction.COPY ;",
+ "",
+ "",
+ " if (_this.model.el.iter_n_children(null) < 1) {",
+ " // no children.. -- asume it's ok..",
+ " ",
+ " targetData = \"|%d|\".printf((int)Gtk.TreeViewDropPosition.INTO_OR_AFTER);",
+ " ",
+ " this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0); ",
+ " Gdk.drag_status(ctx, action ,time);",
+ " return true;",
+ " ",
+ " // continue through to allow drop...",
+ "",
+ " } ",
+ " ",
+ " ",
+ "",
+ " ",
+ " ",
+ " //print(\"ISOVER? \" + isOver);",
+ " if (!isOver) {",
+ " ",
+ " Gdk.drag_status(ctx, 0 ,time);",
+ " this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0); ",
+ " return false;",
+ "",
+ " }",
+ " ",
+ " // drag node is parent of child..",
+ " //console.log(\"SRC TREEPATH: \" + src.treepath);",
+ " //console.log(\"TARGET TREEPATH: \" + data.path.to_string());",
+ " ",
+ " // nned to check a few here..",
+ " //Gtk.TreeViewDropPosition.INTO_OR_AFTER",
+ " //Gtk.TreeViewDropPosition.INTO_OR_BEFORE",
+ " //Gtk.TreeViewDropPosition.AFTER",
+ " //Gtk.TreeViewDropPosition.BEFORE",
+ " ",
+ " // locally dragged items to not really use the ",
+ " var selection_text = this.dragData;",
+ " ",
+ " ",
+ " ",
+ " if (selection_text == null || selection_text.length < 1) {",
+ " //print(\"Error - drag selection text returned NULL\");",
+ " Gdk.drag_status(ctx, 0 ,time);",
+ " this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);",
+ " return false;",
+ " }",
+ " ",
+ " ",
+ " // see if we are dragging into ourself?",
+ " var target_path = path.to_string(); ",
+ " print (\"Drag %s onto %s--%d\\n \", selection_text, target_path, pos);",
+ " ",
+ " // pos : 3 = ontop - 0 = after, 1 = before",
+ " //print(\"target_path=\"+target_path);",
+ "",
+ " // ",
+ " if (selection_text == target_path) {",
+ " print(\"self drag ?? == we should perhaps allow copy onto self..\\n\");",
+ " ",
+ " Gdk.drag_status(ctx, 0 ,time);",
+ " this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);",
+ " return false;",
+ "// -- fixme -- this is not really correct..",
+ "",
+ " }",
+ " ",
+ " // check that ",
+ " //print(\"DUMPING DATA\");",
+ " //console.dump(data);",
+ " // path, pos",
+ " ",
+ " //print(data.path.to_string() +' => '+ data.pos);",
+ " ",
+ " // dropList is a list of xtypes that this node could be dropped on.",
+ " // it is set up when we start to drag..",
+ " ",
+ " ",
+ " targetData = _this.model.findDropNodeByPath( path.to_string(), this.dropList, pos);",
+ " ",
+ " print(\"targetDAta: \" + targetData +\"\\n\");",
+ " ",
+ " if (targetData.length < 1) {",
+ " //print(\"Can not find drop node path\");",
+ " ",
+ " Gdk.drag_status(ctx, 0, time);",
+ " this.highlightDropPath(\"\", (Gtk.TreeViewDropPosition)0);",
+ " return false;",
+ " }",
+ " ",
+ " var td_ar = targetData.split(\"|\");",
+ " ",
+ " ",
+ "",
+ " Gdk.drag_status(ctx, action ,time);",
+ " this.highlightDropPath(td_ar[0], (Gtk.TreeViewDropPosition)int.parse(td_ar[1]));",
+ " return true;",
+ " ",
+ " ",
+ "}"
+ ],
+ "key_press_event" : [
+ "(ev) => {",
+ " this.key_is_pressed = true;",
+ " return false;",
+ "}"
+ ],
+ "key_release_event" : [
+ "(ev) => {",
+ " this.key_is_pressed = false;",
+ " return false;",
+ "}",
+ ""
+ ]
},
- "label" : "Save as Template",
- "* pack" : "add",
- "xtype" : "MenuItem",
- "$ xns" : "Gtk"
+ "tooltip_column" : 1,
+ "xtype" : "TreeView",
+ "| void highlightDropPath" : [
+ " ( string treepath, Gtk.TreeViewDropPosition pos) {",
+ "",
+ " // highlighting for drag/drop",
+ " if (treepath.length > 0) {",
+ " this.el.set_drag_dest_row( new Gtk.TreePath.from_string( treepath ), pos);",
+ " } else {",
+ " this.el.set_drag_dest_row(null, Gtk.TreeViewDropPosition.INTO_OR_AFTER);",
+ " }",
+ " ",
+ "}"
+ ],
+ "| void selectNode" : [
+ "(string treepath_str, string source) {",
+ "\tthis.lastEventSource = source;",
+ " //this.selection.select_path(new Gtk.TreePath.from_string( treepath_str));",
+ " var tp = new Gtk.TreePath.from_string(treepath_str);",
+ " ",
+ " this.el.set_cursor(tp, null, false); ",
+ " this.el.scroll_to_cell(tp, null, false, 0,0);",
+ "}",
+ ""
+ ],
+ "| void setCursor" : [
+ "(string treepath, string sourceEvent) {",
+ "\tthis.lastEventSource = sourceEvent;",
+ "\t//this.blockChanges = true; << block changes prevents loading of 'node data' and firing of node_selected..",
+ " this.el.set_cursor(new Gtk.TreePath.from_string(treepath), null, false); ",
+ " // fire node_selected..",
+ " //this.blockChanges = false;",
+ "\tthis.lastEventSource = \"\";",
+ "}",
+ ""
+ ]
},
{
- "listeners" : {
- "activate" : " () => {\n var node = _this.getActiveElement();\n var name = DialogSaveModule.singleton().show(\n (Gtk.Window) _this.el.get_toplevel (), \n _this.main_window.windowstate.project, \n node\n );\n if (name.length < 1) {\n return;\n \n }\n node.props.set(\"* xinclude\", name);\n node.items.clear();\n\n\n var s = _this.view.el.get_selection();\n \n print(\"GET SELECTED?\");\n Gtk.TreeIter iter;\n Gtk.TreeModel mod;\n\n \n if (!s.get_selected(out mod, out iter)) {\n return; // nothing seleted..\n }\n Gtk.TreeIter citer;\n var n_cn = mod.iter_n_children(iter) -1;\n for (var i = n_cn; i > -1; i--) {\n mod.iter_nth_child(out citer, iter, i);\n \n\n print(\"removing node from Tree\\n\"); \n \n _this.model.el.remove(ref citer);\n }\n _this.changed();\n _this.node_selected(node, \"tree\");\n \n \n}"
- },
- "label" : "Save as Module",
- "* pack" : "add",
- "xtype" : "MenuItem",
- "$ xns" : "Gtk"
+ "$ xns" : "Gtk",
+ "* pack" : false,
+ "id" : "LeftTreeMenu",
+ "items" : [
+ {
+ "$ xns" : "Gtk",
+ "* pack" : "add",
+ "label" : "Delete Element",
+ "listeners" : {
+ "activate" : [
+ " ( ) => {",
+ " ",
+ " print(\"ACTIVATE?\");",
+ " ",
+ " ",
+ " _this.model.deleteSelected();",
+ "}"
+ ]
+ },
+ "xtype" : "MenuItem"
+ },
+ {
+ "$ xns" : "Gtk",
+ "* pack" : "add",
+ "label" : "Save as Template",
+ "listeners" : {
+ "activate" : [
+ " () => {",
+ "",
+ " DialogSaveTemplate.singleton().show(",
+ " (Gtk.Window) _this.el.get_toplevel (), ",
+ " _this.main_window.windowstate.file.palete(), ",
+ " _this.getActiveElement()",
+ " );",
+ " ",
+ " ",
+ "}"
+ ]
+ },
+ "xtype" : "MenuItem"
+ },
+ {
+ "$ xns" : "Gtk",
+ "* pack" : "add",
+ "label" : "Save as Module",
+ "listeners" : {
+ "activate" : [
+ " () => {",
+ " var node = _this.getActiveElement();",
+ " var name = DialogSaveModule.singleton().show(",
+ " (Gtk.Window) _this.el.get_toplevel (), ",
+ " _this.main_window.windowstate.project, ",
+ " node",
+ " );",
+ " if (name.length < 1) {",
+ " return;",
+ " ",
+ " }",
+ " node.props.set(\"* xinclude\", name);",
+ " node.items.clear();",
+ "",
+ "",
+ " var s = _this.view.el.get_selection();",
+ " ",
+ " print(\"GET SELECTED?\");",
+ " Gtk.TreeIter iter;",
+ " Gtk.TreeModel mod;",
+ "",
+ " ",
+ " if (!s.get_selected(out mod, out iter)) {",
+ " return; // nothing seleted..",
+ " }",
+ " Gtk.TreeIter citer;",
+ " var n_cn = mod.iter_n_children(iter) -1;",
+ " for (var i = n_cn; i > -1; i--) {",
+ " mod.iter_nth_child(out citer, iter, i);",
+ " ",
+ "",
+ " print(\"removing node from Tree\\n\"); ",
+ " ",
+ " _this.model.el.remove(ref citer);",
+ " }",
+ " _this.changed();",
+ " _this.node_selected(node, \"tree\");",
+ " ",
+ " ",
+ "}"
+ ]
+ },
+ "xtype" : "MenuItem"
+ }
+ ],
+ "xtype" : "Menu"
}
- ]
+ ],
+ "xtype" : "ScrolledWindow"
}
+ ],
+ "xtype" : "Box",
+ "| JsRender.JsRender getActiveFile" : [
+ "() {",
+ " return this.main_window.windowstate.file;",
+ "}",
+ ""
+ ],
+ "| JsRender.Node? getActiveElement" : [
+ " () { // return path to actie node.",
+ "",
+ " var path = this.getActivePath();",
+ " if (path.length < 1) {",
+ " return null;",
+ " }",
+ " return _this.model.pathToNode(path);",
+ " ",
+ "}",
+ ""
+ ],
+ "| string getActivePath" : [
+ " () {",
+ " ",
+ " var view = this.view.el;",
+ " if (view.get_selection().count_selected_rows() < 1) {",
+ " return \"\";",
+ " }",
+ " Gtk.TreeIter iter;",
+ " Gtk.TreeModel mod;",
+ " view.get_selection().get_selected(out mod, out iter);",
+ " return mod.get_path(iter).to_string();",
+ "}",
+ " "
]
}
- ]
+ ],
+ "modOrder" : "",
+ "name" : "WindowLeftTree",
+ "parent" : "",
+ "path" : "/home/alan/gitlive/roobuilder/src/Builder4/WindowLeftTree.bjs",
+ "permname" : "",
+ "title" : ""
}
\ No newline at end of file