diff --git a/src/css/tools.css b/src/css/tools.css index dca84a08..ff54cbf9 100644 --- a/src/css/tools.css +++ b/src/css/tools.css @@ -76,7 +76,7 @@ } .tool-shape-select .drawing-canvas-container:hover { - cursor: url(../img/cursors/wand.png) 15 15, pointer; + cursor: url(../img/cursors/wand.png) 10 5, pointer; } .tool-colorpicker .drawing-canvas-container:hover { diff --git a/src/js/Events.js b/src/js/Events.js index dc2b9e16..5241ce03 100644 --- a/src/js/Events.js +++ b/src/js/Events.js @@ -63,6 +63,9 @@ var Events = { SELECTION_CREATED: 'SELECTION_CREATED', SELECTION_MOVE_REQUEST: 'SELECTION_MOVE_REQUEST', SELECTION_DISMISSED: 'SELECTION_DISMISSED', + SELECTION_COPY: 'SELECTION_COPY', + SELECTION_CUT: 'SELECTION_CUT', + SELECTION_PASTE: 'SELECTION_PASTE', SHOW_NOTIFICATION: 'SHOW_NOTIFICATION', HIDE_NOTIFICATION: 'HIDE_NOTIFICATION', diff --git a/src/js/selection/SelectionManager.js b/src/js/selection/SelectionManager.js index 6df6f923..63696e12 100644 --- a/src/js/selection/SelectionManager.js +++ b/src/js/selection/SelectionManager.js @@ -17,12 +17,16 @@ $.subscribe(Events.SELECTION_CREATED, $.proxy(this.onSelectionCreated_, this)); $.subscribe(Events.SELECTION_DISMISSED, $.proxy(this.onSelectionDismissed_, this)); $.subscribe(Events.SELECTION_MOVE_REQUEST, $.proxy(this.onSelectionMoved_, this)); + $.subscribe(Events.SELECTION_COPY, this.copy.bind(this)); + $.subscribe(Events.SELECTION_CUT, this.cut.bind(this)); + $.subscribe(Events.SELECTION_PASTE, this.paste.bind(this)); var shortcuts = pskl.service.keyboard.Shortcuts; pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.PASTE, this.paste.bind(this)); pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.CUT, this.cut.bind(this)); pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.COPY, this.copy.bind(this)); pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.DELETE, this.onDeleteShortcut_.bind(this)); + pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.COMMIT, this.commit.bind(this)); $.subscribe(Events.TOOL_SELECTED, $.proxy(this.onToolSelected_, this)); }; @@ -107,6 +111,19 @@ }); }; + /** + * If the currently selected tool is a selection tool, call commitSelection handler on + * the current tool instance. + */ + ns.SelectionManager.prototype.commit = function() { + var tool = pskl.app.drawingController.currentToolBehavior; + var isSelectionTool = tool instanceof pskl.tools.drawing.selection.BaseSelect; + if (isSelectionTool) { + var overlay = pskl.app.drawingController.overlayFrame; + tool.commitSelection(overlay); + } + }; + ns.SelectionManager.prototype.replay = function (frame, replayData) { if (replayData.type === SELECTION_REPLAY.PASTE) { this.pastePixels_(frame, replayData.pixels); diff --git a/src/js/service/keyboard/KeycodeTranslator.js b/src/js/service/keyboard/KeycodeTranslator.js index b5156897..7cd8a293 100644 --- a/src/js/service/keyboard/KeycodeTranslator.js +++ b/src/js/service/keyboard/KeycodeTranslator.js @@ -1,7 +1,7 @@ (function () { var specialKeys = { - 191 : '?', 8 : 'back', + 13 : 'enter', 27 : 'esc', 37 : 'left', 38 : 'up', @@ -20,6 +20,7 @@ 61 : '+', 188 : '<', 190 : '>', + 191 : '?', 219 : '[', 221 : ']' }; diff --git a/src/js/service/keyboard/Shortcut.js b/src/js/service/keyboard/Shortcut.js index beee43c0..31b934f6 100644 --- a/src/js/service/keyboard/Shortcut.js +++ b/src/js/service/keyboard/Shortcut.js @@ -53,7 +53,18 @@ * @return {Boolean} true if the shortcut can be updated */ ns.Shortcut.prototype.isEditable = function () { - return this.getKeys().length < 2; + if (this.getKeys().length === 0) { + // No key defined: can be edited. + return true; + } + + if (this.getKeys().length === 1) { + // Only one key defined, can be edited if it is not using a forbidden key. + return ns.Shortcuts.FORBIDDEN_KEYS.indexOf(this.getKeys()[0]) === -1; + } + + // More than one key, can't be edited. + return false; }; ns.Shortcut.prototype.isCustom = function () { diff --git a/src/js/service/keyboard/Shortcuts.js b/src/js/service/keyboard/Shortcuts.js index 70151fea..c0dc7369 100644 --- a/src/js/service/keyboard/Shortcuts.js +++ b/src/js/service/keyboard/Shortcuts.js @@ -11,7 +11,7 @@ * Or really custom shortcuts such as the 1-9 for color palette shorctus */ FORBIDDEN_KEYS : ['1', '2', '3', '4', '5', '6', '7', '8', '9', '?', 'shift+?', - 'del', 'back', 'ctrl+Y', 'ctrl+shift+Z'], + 'DEL', 'BACK', 'ENTER', 'ctrl+Y', 'ctrl+shift+Z'], /** * Syntax : createShortcut(id, description, default key(s)) @@ -38,7 +38,8 @@ CUT : createShortcut('selection-cut', 'Cut selection', 'ctrl+X'), COPY : createShortcut('selection-copy', 'Copy selection', 'ctrl+C'), PASTE : createShortcut('selection-paste', 'Paste selection', 'ctrl+V'), - DELETE : createShortcut('selection-delete', 'Delete selection', ['del', 'back']) + DELETE : createShortcut('selection-delete', 'Delete selection', ['DEL', 'BACK']), + COMMIT : createShortcut('selection-commit', 'Commit selection', ['ENTER']) }, MISC : { diff --git a/src/js/tools/drawing/selection/AbstractDragSelect.js b/src/js/tools/drawing/selection/AbstractDragSelect.js index 3b9f4ead..c5671b5d 100644 --- a/src/js/tools/drawing/selection/AbstractDragSelect.js +++ b/src/js/tools/drawing/selection/AbstractDragSelect.js @@ -8,8 +8,6 @@ ns.AbstractDragSelect = function () { ns.BaseSelect.call(this); - - this.hasSelection = false; }; pskl.utils.inherit(ns.AbstractDragSelect, ns.BaseSelect); @@ -18,8 +16,7 @@ ns.AbstractDragSelect.prototype.onSelectStart_ = function (col, row, frame, overlay) { if (this.hasSelection) { this.hasSelection = false; - overlay.clear(); - $.publish(Events.SELECTION_DISMISSED); + this.commitSelection(overlay); } else { this.hasSelection = true; this.onDragSelectStart_(col, row); diff --git a/src/js/tools/drawing/selection/BaseSelect.js b/src/js/tools/drawing/selection/BaseSelect.js index 20f6d1d2..e71eda67 100644 --- a/src/js/tools/drawing/selection/BaseSelect.js +++ b/src/js/tools/drawing/selection/BaseSelect.js @@ -18,11 +18,13 @@ this.lastMoveRow = null; this.selection = null; + this.hasSelection = false; this.tooltipDescriptors = [ {description : 'Drag the selection to move it. You may switch to other layers and frames.'}, {key : 'ctrl+c', description : 'Copy the selected area'}, - {key : 'ctrl+v', description : 'Paste the copied area'} + {key : 'ctrl+v', description : 'Paste the copied area'}, + {key : 'shift', description : 'Hold to move the content'} ]; }; @@ -48,6 +50,11 @@ this.onSelectStart_(col, row, frame, overlay); } else { this.mode = 'moveSelection'; + if (event.shiftKey && !this.isMovingContent_) { + this.isMovingContent_ = true; + $.publish(Events.SELECTION_CUT); + this.drawSelectionOnOverlay_(overlay); + } this.onSelectionMoveStart_(col, row, frame, overlay); } }; @@ -91,6 +98,10 @@ this.bodyRoot.removeClass(this.secondaryToolId); } } + + if (!this.hasSelection) { + pskl.tools.drawing.BaseTool.prototype.moveUnactiveToolAt.apply(this, arguments); + } }; ns.BaseSelect.prototype.isInSelection = function (col, row) { @@ -99,8 +110,19 @@ }); }; - ns.BaseSelect.prototype.hideHighlightedPixel = function() { - // there is no highlighted pixel for selection tools, do nothing + /** + * Protected method, should be called when the selection is dismissed. + */ + ns.BaseSelect.prototype.commitSelection = function (overlay) { + if (this.isMovingContent_) { + $.publish(Events.SELECTION_PASTE); + this.isMovingContent_ = false; + } + + // Clean previous selection: + $.publish(Events.SELECTION_DISMISSED); + overlay.clear(); + this.hasSelection = false; }; /** diff --git a/src/js/tools/drawing/selection/ShapeSelect.js b/src/js/tools/drawing/selection/ShapeSelect.js index 488a2af6..7e9073ca 100644 --- a/src/js/tools/drawing/selection/ShapeSelect.js +++ b/src/js/tools/drawing/selection/ShapeSelect.js @@ -22,16 +22,18 @@ * @override */ ns.ShapeSelect.prototype.onSelectStart_ = function (col, row, frame, overlay) { - // Clean previous selection: - $.publish(Events.SELECTION_DISMISSED); - overlay.clear(); + if (this.hasSelection) { + this.hasSelection = false; + this.commitSelection(overlay); + } else { + this.hasSelection = true; + // From the pixel clicked, get shape using an algorithm similar to the paintbucket one: + var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row); + this.selection = new pskl.selection.ShapeSelection(pixels); - // From the pixel cliked, get shape using an algorithm similar to the paintbucket one: - var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row); - this.selection = new pskl.selection.ShapeSelection(pixels); - - $.publish(Events.SELECTION_CREATED, [this.selection]); - this.drawSelectionOnOverlay_(overlay); + $.publish(Events.SELECTION_CREATED, [this.selection]); + this.drawSelectionOnOverlay_(overlay); + } }; })();