From 27659805f68fff7cf6e38e950e72cf2618dfe9e5 Mon Sep 17 00:00:00 2001 From: zadam Date: Mon, 10 Jun 2019 21:47:08 +0200 Subject: [PATCH] redesign of drag & drop, separation of active, focused and active notes in the tree, fixes #565 --- .../javascripts/services/drag_and_drop.js | 17 +++--------- .../javascripts/services/note_detail.js | 1 - .../services/note_detail_relation_map.js | 24 ++++++++++++----- src/public/javascripts/services/tree.js | 8 +----- .../javascripts/services/tree_keybindings.js | 16 ++++++++++++ src/public/stylesheets/style.css | 26 +++++++------------ 6 files changed, 48 insertions(+), 44 deletions(-) diff --git a/src/public/javascripts/services/drag_and_drop.js b/src/public/javascripts/services/drag_and_drop.js index b1333c228..520f60d88 100644 --- a/src/public/javascripts/services/drag_and_drop.js +++ b/src/public/javascripts/services/drag_and_drop.js @@ -10,23 +10,14 @@ const dragAndDropSetup = { return false; } - if (!data.originalEvent.shiftKey) { - // keep existing selection only if CTRL key is pressed - for (const selectedNode of treeService.getSelectedNodes()) { - selectedNode.setSelected(false); - selectedNode.renderTitle(); - } - } - node.setSelected(true); - // this is for dragging notes into relation map - // we allow to drag only one note at a time because it multi-drag conflicts with multiple single drags - // in UX and single drag is probably more useful - data.dataTransfer.setData("text", JSON.stringify({ + const notes = treeService.getSelectedNodes().map(node => { return { noteId: node.data.noteId, title: node.title - })); + }}); + + data.dataTransfer.setData("text", JSON.stringify(notes)); // This function MUST be defined to enable dragging for the tree. // Return false to cancel dragging of node. diff --git a/src/public/javascripts/services/note_detail.js b/src/public/javascripts/services/note_detail.js index be198d30f..5d9315cb2 100644 --- a/src/public/javascripts/services/note_detail.js +++ b/src/public/javascripts/services/note_detail.js @@ -154,7 +154,6 @@ async function showTab(tabId) { if (newActiveNode && newActiveNode.isVisible()) { newActiveNode.setActive(true, {noEvents: true}); - newActiveNode.setSelected(true); } } } diff --git a/src/public/javascripts/services/note_detail_relation_map.js b/src/public/javascripts/services/note_detail_relation_map.js index 3220466be..bd69a6d6c 100644 --- a/src/public/javascripts/services/note_detail_relation_map.js +++ b/src/public/javascripts/services/note_detail_relation_map.js @@ -567,20 +567,30 @@ class NoteDetailRelationMap { async dropNoteOntoRelationMapHandler(ev) { ev.preventDefault(); - const note = JSON.parse(ev.originalEvent.dataTransfer.getData("text")); + const notes = JSON.parse(ev.originalEvent.dataTransfer.getData("text")); let {x, y} = this.getMousePosition(ev); - const exists = this.mapData.notes.some(n => n.noteId === note.noteId); + for (const note of notes) { + const exists = this.mapData.notes.some(n => n.noteId === note.noteId); - if (exists) { - await infoDialog.info(`Note "${note.title}" is already placed into the diagram`); + if (exists) { + infoService.showError(`Note "${note.title}" is already in the diagram.`); - return; + continue; + } + + this.mapData.notes.push({noteId: note.noteId, x, y}); + + if (x > 1000) { + y += 100; + x = 0; + } + else { + x += 200; + } } - this.mapData.notes.push({noteId: note.noteId, x, y}); - this.saveData(); await this.refresh(); diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index e0daf47b2..29376c470 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -309,12 +309,6 @@ function clearSelectedNodes() { for (const selectedNode of getSelectedNodes()) { selectedNode.setSelected(false); } - - const currentNode = getActiveNode(); - - if (currentNode) { - currentNode.setSelected(true); - } } async function treeInitialized() { @@ -388,13 +382,13 @@ function initFancyTree(tree) { if (targetType === 'title' || targetType === 'icon') { if (event.shiftKey) { node.setSelected(!node.isSelected()); + node.setFocus(true); } else if (event.ctrlKey) { noteDetailService.loadNoteDetail(node.data.noteId, { newTab: true }); } else { node.setActive(); - node.setSelected(true); clearSelectedNodes(); } diff --git a/src/public/javascripts/services/tree_keybindings.js b/src/public/javascripts/services/tree_keybindings.js index 6f288d632..8236051dc 100644 --- a/src/public/javascripts/services/tree_keybindings.js +++ b/src/public/javascripts/services/tree_keybindings.js @@ -43,6 +43,14 @@ const keyBindings = { "shift+up": () => { const node = treeService.getFocusedNode(); + if (!node) { + return; + } + + if (node.isActive()) { + node.setSelected(true); + } + node.navigate($.ui.keyCode.UP, false).then(() => { const currentNode = treeService.getFocusedNode(); @@ -58,6 +66,14 @@ const keyBindings = { "shift+down": () => { const node = treeService.getFocusedNode(); + if (!node) { + return; + } + + if (node.isActive()) { + node.setSelected(true); + } + node.navigate($.ui.keyCode.DOWN, false).then(() => { const currentNode = treeService.getFocusedNode(); diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index 2200206df..36c54ec64 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -188,33 +188,27 @@ span.fancytree-node.fancytree-active-clone:not(.fancytree-active) .fancytree-tit padding-left: 5px; } -span.fancytree-active.fancytree-focused .fancytree-title { +span.fancytree-active .fancytree-title { + font-weight: bold; + border-color: var(--main-background-color) !important; /* invisible border */ +} + +span.fancytree-focused .fancytree-title, span.fancytree-focused.fancytree-selected .fancytree-title { color: var(--active-item-text-color) !important; background-color: var(--active-item-background-color) !important; - border-color: var(--main-border-color) !important; + border-color: var(--main-background-color) !important; /* invisible border */ border-radius: 3px; - font-weight: bold; } -span.fancytree-active:not(.fancytree-focused) .fancytree-title { +span.fancytree-selected .fancytree-title { color: var(--hover-item-text-color) !important; background-color: var(--hover-item-background-color) !important; - border-color: var(--main-border-color) !important; - border-radius: 3px; - font-weight: bold; -} - -span.fancytree-selected:not(.fancytree-active) .fancytree-title { - color: var(--hover-item-text-color) !important; - background-color: var(--hover-item-background-color) !important; - border-color: var(--main-border-color) !important; + border-color: var(--main-background-color) !important; /* invisible border */ border-radius: 3px; font-style: italic; } -span.fancytree-node:not(.fancytree-active):hover span.fancytree-title { - color: var(--hover-item-text-color) !important; - background-color: var(--hover-item-background-color) !important; +span.fancytree-node:hover span.fancytree-title { border-color: var(--main-border-color) !important; border-radius: 3px; }