UNPKG

js-draw

Version:

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

239 lines (238 loc) 10.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const math_1 = require("@js-draw/math"); const PanZoom_1 = __importStar(require("../../tools/PanZoom")); const types_1 = require("../../types"); const Viewport_1 = __importDefault(require("../../Viewport")); const constants_1 = require("../constants"); const BaseToolWidget_1 = __importDefault(require("./BaseToolWidget")); const BaseWidget_1 = __importDefault(require("./BaseWidget")); const makeSeparator_1 = __importDefault(require("./components/makeSeparator")); const makeZoomControl = (localizationTable, editor, helpDisplay) => { const zoomLevelRow = document.createElement('div'); const increaseButton = document.createElement('button'); const decreaseButton = document.createElement('button'); const resetViewButton = document.createElement('button'); const zoomLevelDisplay = document.createElement('span'); increaseButton.innerText = '+'; decreaseButton.innerText = '-'; resetViewButton.innerText = localizationTable.resetView; zoomLevelRow.replaceChildren(zoomLevelDisplay, increaseButton, decreaseButton, resetViewButton); zoomLevelRow.classList.add(`${constants_1.toolbarCSSPrefix}zoomLevelEditor`); zoomLevelDisplay.classList.add('zoomDisplay'); let lastZoom; const updateZoomDisplay = () => { let zoomLevel = editor.viewport.getScaleFactor() * 100; if (zoomLevel > 0.1) { zoomLevel = Math.round(zoomLevel * 10) / 10; } else { zoomLevel = Math.round(zoomLevel * 1000) / 1000; } if (zoomLevel !== lastZoom) { zoomLevelDisplay.textContent = localizationTable.zoomLevel(zoomLevel); lastZoom = zoomLevel; } }; updateZoomDisplay(); editor.notifier.on(types_1.EditorEventType.ViewportChanged, (event) => { if (event.kind === types_1.EditorEventType.ViewportChanged) { updateZoomDisplay(); // Can't reset if already reset. resetViewButton.disabled = event.newTransform.eq(math_1.Mat33.identity); } }); const zoomBy = (factor) => { const screenCenter = editor.viewport.visibleRect.center; const transformUpdate = math_1.Mat33.scaling2D(factor, screenCenter); editor.dispatch(Viewport_1.default.transformBy(transformUpdate), false); }; increaseButton.onclick = () => { zoomBy(5.0 / 4); }; decreaseButton.onclick = () => { zoomBy(4.0 / 5); }; resetViewButton.onclick = () => { const addToHistory = false; editor.dispatch(Viewport_1.default.transformBy(editor.viewport.canvasToScreenTransform.inverse()), addToHistory); }; helpDisplay?.registerTextHelpForElement(increaseButton, localizationTable.handDropdown__zoomInHelpText); helpDisplay?.registerTextHelpForElement(decreaseButton, localizationTable.handDropdown__zoomOutHelpText); helpDisplay?.registerTextHelpForElement(resetViewButton, localizationTable.handDropdown__resetViewHelpText); helpDisplay?.registerTextHelpForElement(zoomLevelDisplay, localizationTable.handDropdown__zoomDisplayHelpText); return zoomLevelRow; }; class HandModeWidget extends BaseWidget_1.default { constructor(editor, tool, flag, makeIcon, title, helpText, localizationTable) { super(editor, `pan-mode-${flag}`, localizationTable); this.tool = tool; this.flag = flag; this.makeIcon = makeIcon; this.title = title; this.helpText = helpText; editor.notifier.on(types_1.EditorEventType.ToolUpdated, (toolEvt) => { if (toolEvt.kind === types_1.EditorEventType.ToolUpdated && toolEvt.tool === tool) { const allEnabled = !!(tool.getMode() & PanZoom_1.PanZoomMode.SinglePointerGestures); this.setSelected(!!(tool.getMode() & flag) || allEnabled); // Unless this widget toggles all single pointer gestures, toggling while // single pointer gestures are enabled should have no effect this.setDisabled(allEnabled && flag !== PanZoom_1.PanZoomMode.SinglePointerGestures); } }); this.setSelected(false); } shouldAutoDisableInReadOnlyEditor() { return false; } setModeFlag(enabled) { this.tool.setModeEnabled(this.flag, enabled); } handleClick() { this.setModeFlag(!this.isSelected()); } getTitle() { return this.title; } createIcon() { return this.makeIcon(); } fillDropdown(_dropdown) { return false; } getHelpText() { return this.helpText; } } /** This toolbar widget allows controlling the editor's {@link PanZoom} tool(s). */ class HandToolWidget extends BaseToolWidget_1.default { constructor(editor, // Can either be the primary pan/zoom tool (in the primary tools list) or // the override pan/zoom tool. // If the override pan/zoom tool, the primary will be gotten from the editor's // tool controller. // If the primary, the override will be gotten from the editor's tool controller. tool, localizationTable) { const isGivenToolPrimary = editor.toolController.getPrimaryTools().includes(tool); const primaryTool = (isGivenToolPrimary ? tool : HandToolWidget.getPrimaryHandTool(editor.toolController)) ?? tool; super(editor, primaryTool, 'hand-tool-widget', localizationTable); this.overridePanZoomTool = (isGivenToolPrimary ? HandToolWidget.getOverrideHandTool(editor.toolController) : tool) ?? tool; // Only allow toggling a hand tool if we're using the primary hand tool and not the override // hand tool for this button. this.allowTogglingBaseTool = primaryTool !== null; // Allow showing/hiding the dropdown, even if `overridePanZoomTool` isn't enabled. if (!this.allowTogglingBaseTool) { this.container.classList.add('dropdownShowable'); } // Controls for the overriding hand tool. const touchPanningWidget = new HandModeWidget(editor, this.overridePanZoomTool, PanZoom_1.PanZoomMode.OneFingerTouchGestures, () => this.editor.icons.makeTouchPanningIcon(), localizationTable.touchPanning, localizationTable.handDropdown__touchPanningHelpText, localizationTable); const rotationLockWidget = new HandModeWidget(editor, this.overridePanZoomTool, PanZoom_1.PanZoomMode.RotationLocked, () => this.editor.icons.makeRotationLockIcon(), localizationTable.lockRotation, localizationTable.handDropdown__lockRotationHelpText, localizationTable); this.addSubWidget(touchPanningWidget); this.addSubWidget(rotationLockWidget); } static getPrimaryHandTool(toolController) { const primaryPanZoomToolList = toolController .getPrimaryTools() .filter((tool) => tool instanceof PanZoom_1.default); const primaryPanZoomTool = primaryPanZoomToolList[0]; return primaryPanZoomTool; } static getOverrideHandTool(toolController) { const panZoomToolList = toolController.getMatchingTools(PanZoom_1.default); const panZoomTool = panZoomToolList[0]; return panZoomTool; } shouldAutoDisableInReadOnlyEditor() { return false; } getTitle() { return this.localizationTable.handTool; } createIcon() { return this.editor.icons.makeHandToolIcon(); } handleClick() { if (this.allowTogglingBaseTool) { super.handleClick(); } else { this.setDropdownVisible(!this.isDropdownVisible()); } } getHelpText() { return this.localizationTable.handDropdown__baseHelpText; } fillDropdown(dropdown, helpDisplay) { super.fillDropdown(dropdown, helpDisplay); // The container for all actions that come after the toolbar buttons. const nonbuttonActionContainer = document.createElement('div'); nonbuttonActionContainer.classList.add(`${constants_1.toolbarCSSPrefix}nonbutton-controls-main-list`); (0, makeSeparator_1.default)().addTo(nonbuttonActionContainer); const zoomControl = makeZoomControl(this.localizationTable, this.editor, helpDisplay); nonbuttonActionContainer.appendChild(zoomControl); dropdown.appendChild(nonbuttonActionContainer); return true; } setSelected(selected) { if (this.allowTogglingBaseTool) { super.setSelected(selected); } } serializeState() { const toolMode = this.overridePanZoomTool.getMode(); return { ...super.serializeState(), touchPanning: toolMode & PanZoom_1.PanZoomMode.OneFingerTouchGestures, rotationLocked: toolMode & PanZoom_1.PanZoomMode.RotationLocked, }; } deserializeFrom(state) { if (state.touchPanning !== undefined) { this.overridePanZoomTool.setModeEnabled(PanZoom_1.PanZoomMode.OneFingerTouchGestures, !!state.touchPanning); } if (state.rotationLocked !== undefined) { this.overridePanZoomTool.setModeEnabled(PanZoom_1.PanZoomMode.RotationLocked, !!state.rotationLocked); } super.deserializeFrom(state); } } exports.default = HandToolWidget;