From 76d03e3eaca991427c87e6d474999d81580a12fb Mon Sep 17 00:00:00 2001 From: CTomlyn Date: Tue, 26 Nov 2024 18:42:08 -0800 Subject: [PATCH] Text area shortcuts Signed-off-by: CTomlyn --- .../src/common-canvas/keyboard-utils.js | 80 +++++++++++++++++-- .../src/common-canvas/svg-canvas-renderer.js | 25 +++++- .../svg-canvas-utils-textarea.js | 55 ++++++------- 3 files changed, 120 insertions(+), 40 deletions(-) diff --git a/canvas_modules/common-canvas/src/common-canvas/keyboard-utils.js b/canvas_modules/common-canvas/src/common-canvas/keyboard-utils.js index dd41bddbe..ee33a2a98 100644 --- a/canvas_modules/common-canvas/src/common-canvas/keyboard-utils.js +++ b/canvas_modules/common-canvas/src/common-canvas/keyboard-utils.js @@ -22,6 +22,8 @@ const LEFT_ARROW_KEY = "ArrowLeft"; const RIGHT_ARROW_KEY = "ArrowRight"; const UP_ARROW_KEY = "ArrowUp"; const DOWN_ARROW_KEY = "ArrowDown"; +const LAB_KEY = "Comma"; // Left angle bracket +const RAB_KEY = "Period"; // Right angle bracket const ESC_KEY = "Escape"; const PERIOD_KEY = "Period"; const SLASH_KEY = "Slash"; @@ -30,13 +32,21 @@ const MINUS_KEY = "Minus"; const TAB_KEY = "Tab"; const BACKSPACE_KEY = "Backspace"; const DELETE_KEY = "Delete"; + const A_KEY = "KeyA"; +const B_KEY = "KeyB"; const C_KEY = "KeyC"; +const E_KEY = "KeyE"; +const I_KEY = "KeyI"; +const K_KEY = "KeyK"; const P_KEY = "KeyP"; const V_KEY = "KeyV"; const X_KEY = "KeyX"; const Y_KEY = "KeyY"; const Z_KEY = "KeyZ"; + +const SEVEN_KEY = "Digit7"; +const EIGHT_KEY = "Digit8"; const ZERO_KEY = "Digit0"; export default class KeyboardUtils { @@ -133,10 +143,16 @@ export default class KeyboardUtils { return !this.isMetaKey(d3Event) && !d3Event.shiftKey && d3Event.code === LEFT_ARROW_KEY; } - // The calling code will differentiate between a single select - // or an 'extra' select that adds to the set of selected objects. static selectObject(d3Event) { - return d3Event.code === RETURN_KEY; + return !this.isMetaKey(d3Event) && !d3Event.shiftKey && d3Event.code === RETURN_KEY; + } + + static selectObjectAugment(d3Event) { + return this.isMetaKey(d3Event) && !d3Event.shiftKey && d3Event.code === RETURN_KEY; + } + + static selectObjectRange(d3Event) { + return !this.isMetaKey(d3Event) && d3Event.shiftKey && d3Event.code === RETURN_KEY; } static nextSiblingLink(d3Event) { @@ -150,10 +166,6 @@ export default class KeyboardUtils { // Shortcut to display either a context menu or context // toolbar, depending on which is enabled, for the // canvas or objects on the canvas. - // Note: We don't use a augmentation key (Cmnd or Ctrl or Shift) - // for this shortcut because displaying context options - // involves auto-select which uses augmentation keys for - // adding selections to the set of selections. static displayContextOptions(evt) { return this.isMetaKey(evt) && evt.code === SLASH_KEY; } @@ -202,6 +214,60 @@ export default class KeyboardUtils { return this.isMetaKey(d3Event) && d3Event.shiftKey && d3Event.code === PERIOD_KEY; } + /* ----------------------------------------- */ + /* Comment Text Entry */ + /* ----------------------------------------- */ + + static cancelTextEntry(d3Event) { + return d3Event.code === ESC_KEY; + } + + // During text entry this might either complete the text entry OR + // add a new line. + static returnCommand(d3Event) { + return d3Event.code === RETURN_KEY; + } + + static boldCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.code === B_KEY; + } + + static italicsCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.code === I_KEY; + } + + static strikethroughCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.shiftKey && d3Event.code === X_KEY; + } + + static numberedListCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.shiftKey && d3Event.code === SEVEN_KEY; + } + + static bulletedListCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.shiftKey && d3Event.code === EIGHT_KEY; + } + + static codeCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.code === E_KEY; + } + + static linkCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.code === K_KEY; + } + + static quoteCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.shiftKey && d3Event.code === RAB_KEY; + } + + static incHashesCommand(d3Event) { + return this.isMetaKey(d3Event) && !d3Event.shiftKey && d3Event.code === RAB_KEY; + } + + static decHashesCommand(d3Event) { + return this.isMetaKey(d3Event) && d3Event.code === LAB_KEY; + } + /* ----------------------------------------- */ /* Color Picker */ /* ----------------------------------------- */ diff --git a/canvas_modules/common-canvas/src/common-canvas/svg-canvas-renderer.js b/canvas_modules/common-canvas/src/common-canvas/svg-canvas-renderer.js index ed784110d..1a5d35536 100644 --- a/canvas_modules/common-canvas/src/common-canvas/svg-canvas-renderer.js +++ b/canvas_modules/common-canvas/src/common-canvas/svg-canvas-renderer.js @@ -2064,7 +2064,15 @@ export default class SVGCanvasRenderer { } else if (KeyboardUtils.selectObject(d3Event)) { CanvasUtils.stopPropagationAndPreventDefault(d3Event); - this.selectObjectD3Event(d3Event, d, "node"); + this.selectObject(d3Event, d, "node", false, false); + + } else if (KeyboardUtils.selectObjectAugment(d3Event)) { + CanvasUtils.stopPropagationAndPreventDefault(d3Event); + this.selectObject(d3Event, d, "node", false, true); + + } else if (KeyboardUtils.selectObjectRange(d3Event)) { + CanvasUtils.stopPropagationAndPreventDefault(d3Event); + this.selectObject(d3Event, d, "node", true, false); } else if (KeyboardUtils.sizeObjectUp(d3Event)) { if (CanvasUtils.isNodeResizable(d, this.config)) { @@ -4046,7 +4054,12 @@ export default class SVGCanvasRenderer { CanvasUtils.stopPropagationAndPreventDefault(d3Event); } else if (KeyboardUtils.selectObject(d3Event)) { - this.selectObjectD3Event(d3Event, d, "comment"); + CanvasUtils.stopPropagationAndPreventDefault(d3Event); + this.selectObject(d3Event, d, "comment", false, false); + + } else if (KeyboardUtils.selectObjectAugment(d3Event)) { + CanvasUtils.stopPropagationAndPreventDefault(d3Event); + this.selectObject(d3Event, d, "comment", false, true); } else if (KeyboardUtils.displayContextOptions(d3Event)) { // Don't let keypress go through to the Canvas otherwise the @@ -4519,7 +4532,13 @@ export default class SVGCanvasRenderer { CanvasUtils.stopPropagationAndPreventDefault(d3Event); } else if (KeyboardUtils.selectObject(d3Event)) { - this.selectObjectD3Event(d3Event, d, "link"); + CanvasUtils.stopPropagationAndPreventDefault(d3Event); + this.selectObject(d3Event, d, "link", false, false); + + } else if (KeyboardUtils.selectObjectAugment(d3Event)) { + CanvasUtils.stopPropagationAndPreventDefault(d3Event); + this.selectObject(d3Event, d, "link", false, true); + } else if (KeyboardUtils.displayContextOptions(d3Event)) { // Don't let keypress go through to the Canvas otherwise the diff --git a/canvas_modules/common-canvas/src/common-canvas/svg-canvas-utils-textarea.js b/canvas_modules/common-canvas/src/common-canvas/svg-canvas-utils-textarea.js index 4c85e597b..ec2356235 100644 --- a/canvas_modules/common-canvas/src/common-canvas/svg-canvas-utils-textarea.js +++ b/canvas_modules/common-canvas/src/common-canvas/svg-canvas-utils-textarea.js @@ -30,23 +30,12 @@ import { } from "./constants/canvas-constants.js"; const BACKSPACE_KEY = 8; -const RETURN_KEY = 13; -const ESC_KEY = 27; const LEFT_ARROW_KEY = 37; const UP_ARROW_KEY = 38; const RIGHT_ARROW_KEY = 39; const DOWN_ARROW_KEY = 40; const DELETE_KEY = 46; const A_KEY = 65; -const B_KEY = 66; -const E_KEY = 69; -const I_KEY = 73; -const K_KEY = 75; -const X_KEY = 88; -const LAB_KEY = 188; // Left angle bracket < -const RAB_KEY = 190; // Right angle bracket > -const SEVEN_KEY = 55; -const EIGHT_KEY = 56; const SCROLL_PADDING_COMMENT = 2; const SCROLL_PADDING_LABEL = 12; @@ -181,26 +170,32 @@ export default class SvgCanvasTextArea { this.completeEditing(evt); } - // Applies a markdown action to the comment text being edited using - // the same commands as the toolbar. + // Returns a markdown action to the comment text being edited, based + // on keyboard input. Returns the same commands as the toolbar buttons. getMarkdownAction(d3Event) { - if (KeyboardUtils.isMetaKey(d3Event)) { - switch (d3Event.keyCode) { - case B_KEY: return "bold"; - case I_KEY: return "italics"; - case X_KEY: return d3Event.shiftKey ? "strikethrough" : null; - case SEVEN_KEY: return d3Event.shiftKey ? "numberedList" : null; - case EIGHT_KEY: return d3Event.shiftKey ? "bulletedList" : null; - case E_KEY: return "code"; - case K_KEY: return "link"; - case LAB_KEY: return "decreaseHashes"; - case RAB_KEY: return d3Event.shiftKey ? "quote" : "increaseHashes"; - default: - } - } else if (d3Event.keyCode === RETURN_KEY) { + if (KeyboardUtils.boldCommand(d3Event)) { + return "bold"; + } else if (KeyboardUtils.italicsCommand(d3Event)) { + return "italics"; + } else if (KeyboardUtils.strikethroughCommand(d3Event)) { + return "strikethrough"; + } else if (KeyboardUtils.numberedListCommand(d3Event)) { + return "numberedList"; + } else if (KeyboardUtils.bulletedListCommand(d3Event)) { + return "bulletedList"; + } else if (KeyboardUtils.codeCommand(d3Event)) { + return "code"; + } else if (KeyboardUtils.linkCommand(d3Event)) { + return "link"; + } else if (KeyboardUtils.quoteCommand(d3Event)) { + return "quote"; + } else if (KeyboardUtils.incHashesCommand(d3Event)) { + return "increaseHashes"; + } else if (KeyboardUtils.decHashesCommand(d3Event)) { + return "decreaseHashes"; + } else if (KeyboardUtils.returnCommand(d3Event)) { return "return"; } - return null; } @@ -811,7 +806,7 @@ export default class SvgCanvasTextArea { textEntrySel .on("keydown", (d3Event) => { // If user hits return/enter - if (d3Event.keyCode === RETURN_KEY) { + if (KeyboardUtils.returnCommand(d3Event)) { if (data.allowReturnKey === "save" || d3Event.shiftKey) { this.textContentSaved = true; this.saveAndCloseTextArea(data, d3Event.target, d3Event); @@ -825,7 +820,7 @@ export default class SvgCanvasTextArea { } // If user presses ESC key revert back to original text by just // closing the text area. - if (d3Event.keyCode === ESC_KEY) { + if (KeyboardUtils.cancelTextEntry(d3Event)) { CanvasUtils.stopPropagationAndPreventDefault(d3Event); this.textAreaEscKeyPressed = true; this.closeTextArea(data);