UNPKG

js-draw

Version:

Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.

98 lines (97 loc) 4.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const math_1 = require("@js-draw/math"); const SelectionTool_1 = require("./SelectionTool"); const verticalOffset = 40; class SelectionMenuShortcut { constructor(parent, viewport, icon, showContextMenu, localization) { this.parent = parent; this.viewport = viewport; this.icon = icon; this.localization = localization; this.lastDragPointer = null; this.element = document.createElement('div'); this.element.classList.add(`${SelectionTool_1.cssPrefix}handle`, `${SelectionTool_1.cssPrefix}selection-menu`); this.element.style.setProperty('--vertical-offset', `${verticalOffset}px`); this.onClick = () => { this.button?.focus({ preventScroll: true }); const anchor = this.getBBoxCanvasCoords().center; showContextMenu(anchor); }; this.initUI(); this.updatePosition(); } initUI() { const button = document.createElement('button'); this.icon.classList.add('icon'); button.replaceChildren(this.icon); button.ariaLabel = this.localization.selectionMenu__show; button.title = button.ariaLabel; this.button = button; // To prevent editor event handlers from conflicting with those for the button, // don't register a [click] handler. An onclick handler can be fired incorrectly // in this case (in Chrome) after onClick is fired in onDragEnd, leading to a double // on-click action. button.onkeydown = (event) => { if (event.key === 'Enter') { // .preventDefault prevents [Enter] from activating the first item in the // selection menu. event.preventDefault(); this.onClick(); } }; this.element.appendChild(button); // Update the bounding box of this in response to the new button. requestAnimationFrame(() => { this.updatePosition(); }); } addTo(container) { container.appendChild(this.element); } remove() { this.element.remove(); } getElementScreenSize() { return math_1.Vec2.of(this.element.clientWidth, this.element.clientHeight); } /** Gets this menu's bounding box relative to the top left of its parent. */ getBBoxParentCoords() { const topLeft = math_1.Vec2.of(0, -verticalOffset); const screenSize = this.getElementScreenSize(); return new math_1.Rect2(topLeft.x, topLeft.y, screenSize.x, screenSize.y); } getBBoxCanvasCoords() { const parentCanvasRect = this.parent.region; const toCanvasScale = this.viewport.getSizeOfPixelOnCanvas(); // Don't apply rotation -- rotation is handled by the selection container const contentCanvasSize = this.getElementScreenSize().times(toCanvasScale); const handleSizeCanvas = verticalOffset / this.viewport.getScaleFactor(); const topLeft = math_1.Vec2.of(parentCanvasRect.x, parentCanvasRect.y - handleSizeCanvas); const minSize = math_1.Vec2.of(48, 48).times(toCanvasScale); return new math_1.Rect2(topLeft.x, topLeft.y, contentCanvasSize.x, contentCanvasSize.y).grownToSize(minSize); } updatePosition() { const bbox = this.getBBoxParentCoords(); // Position within the selection box. this.element.style.marginLeft = `${bbox.topLeft.x}px`; this.element.style.marginTop = `${bbox.topLeft.y}px`; } containsPoint(canvasPoint) { return this.getBBoxCanvasCoords().containsPoint(canvasPoint); } handleDragStart(pointer) { this.lastDragPointer = pointer; return true; } handleDragUpdate(pointer) { this.lastDragPointer = pointer; } handleDragEnd() { if (this.lastDragPointer && this.containsPoint(this.lastDragPointer.canvasPos)) { this.onClick(); } this.lastDragPointer = null; } } exports.default = SelectionMenuShortcut;