UNPKG

@itwin/measure-tools-react

Version:
242 lines 9.75 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { BeDuration, BeUiEvent } from "@itwin/core-bentley"; import { EventHandled, IModelApp, NotifyMessageDetails, OutputMessageAlert, OutputMessagePriority, OutputMessageType, PrimitiveTool, ToolAssistance, ToolAssistanceInputMethod, } from "@itwin/core-frontend"; import { MeasureTools } from "../MeasureTools.js"; import { FeatureTracking } from "./FeatureTracking.js"; import { SheetMeasurementsHelper } from "./SheetMeasurementHelper.js"; /** Namespace for functions relating to the MeasurementTool interface. */ export var MeasurementTool; (function (MeasurementTool) { /** Event for when a tool creates a new measurement. */ MeasurementTool.onNewMeasurement = new BeUiEvent(); /** Event when the tool's dynamic measurement has changed. */ MeasurementTool.onDynamicMeasurementChanged = new BeUiEvent(); /** Gets the active measurement tool, if it exists. * @returns the measurement tool, or undefined if the current tool is not one. */ function getActiveMeasurementTool() { const tool = IModelApp.toolAdmin.currentTool; if (tool === undefined || !("measurements" in tool) || !("persistMeasurements" in tool) || !("clearMeasurements" in tool)) return undefined; return tool; } MeasurementTool.getActiveMeasurementTool = getActiveMeasurementTool; })(MeasurementTool || (MeasurementTool = {})); /** * Helper class to hold the selection state during the operation of a tool. Call saveSelection on install and restoreSelection on cleanup. */ export class SelectionHolder { constructor() { this._selectedIds = new Set(); } saveSelection(imodel, clearSelectionAfter) { this._imodel = imodel; this._selectedIds.clear(); imodel.selectionSet.elements.forEach((id) => this._selectedIds.add(id)); if (clearSelectionAfter) imodel.selectionSet.emptyAll(); } restoreSelection() { if (!this._imodel) return; this._imodel.selectionSet.replace(this._selectedIds); this._imodel = undefined; this._selectedIds.clear(); } } /** Useful base class for tools */ export class PrimitiveToolBase extends PrimitiveTool { get feature() { return undefined; } async onPostInstall() { await super.onPostInstall(); const feature = this.feature; if (feature) FeatureTracking.notifyFeature(feature); } // Recommended way to show feedback to the user in a consistant manor showMessage(priority, briefMessage, detailedMessage) { const msg = new NotifyMessageDetails(priority, briefMessage, detailedMessage, OutputMessageType.Toast, OutputMessageAlert.Balloon); msg.displayTime = BeDuration.fromSeconds(5.0); IModelApp.notifications.outputMessage(msg); } async showException(err) { const priority = OutputMessagePriority.Error; const msg = err.message || err.name || typeof err; this.showMessage(priority, msg); } createMouseUndoInstruction(textOverride) { const text = textOverride || MeasureTools.localization.getLocalizedString("MeasureTools:Generic.undoMeasurement"); return ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), text, false, ToolAssistanceInputMethod.Mouse); } createMouseRedoInstruction(textOverride) { const text = textOverride || MeasureTools.localization.getLocalizedString("MeasureTools:Generic.redoMeasurement"); return ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Y"]), text, false, ToolAssistanceInputMethod.Mouse); } // For most of our cases we expect to draw our decorations when suspended also decorateSuspended(context) { this.decorate(context); } } /** Useful base class for measurement tools which maintains a tool model that a subclass will instantiate as well as save the current selection/restore on exit. * Generally a measurement tool model contains all the logic to create and manage measurements dynamically, while the tool is responsible * for sending input events to the model. */ export class MeasurementToolBase extends PrimitiveToolBase { get measurements() { return this._toolModel.measurements; } get dynamicMeasurement() { return this._toolModel.dynamicMeasurement; } get toolModel() { return this._toolModel; } get selectionHolder() { return this._selectionHolder; } get saveRestoreSelection() { return true; } get allowedDrawingTypes() { return []; } constructor(allowedViewportCallback = (() => true)) { super(); this._allowedViewportCallback = allowedViewportCallback; this._enableSheetMeasurements = false; this._toolModel = this.createToolModel(); this._toolModel.synchMeasurementsWithSelectionSet = true; // Sync by default this._selectionHolder = new SelectionHolder(); this.setupEvents(); } requireWriteableTarget() { return false; } isValidLocation(ev, _isButtonEvent) { if (ev.viewport) return this._allowedViewportCallback(ev.viewport); return true; } async onPostInstall() { await super.onPostInstall(); if (this.saveRestoreSelection) this._selectionHolder.saveSelection(this.iModel, true); this._toolModel.initialize(); this.updateAccuSnap(); this.updateToolAssistance(); } async onCleanup() { await super.onCleanup(); if (this.saveRestoreSelection) this._selectionHolder.restoreSelection(); // Persist measurements when the tool exits this._toolModel.persistMeasurements(); this._toolModel.cleanup(); } async onReinitialize() { this.toolModel.reset(false); this.updateAccuSnap(); this.updateToolAssistance(); } async onUndoPreviousStep() { // If we have an active measurement, reset to initial state if (undefined !== this._toolModel.dynamicMeasurement) { await this.onReinitialize(); return true; } // Start undoing existing measurements if (this._toolModel.canUndo) { const result = this._toolModel.undoMeasurement(); this.updateToolAssistance(); return result; } const message = MeasureTools.localization.getLocalizedString("MeasureTools:Generic.nothingToUndo"); this.showMessage(OutputMessagePriority.Info, message); return false; } async onRedoPreviousStep() { // Probably not a good idea if there are ongoing measurements if (undefined !== this._toolModel.dynamicMeasurement) return false; if (this._toolModel.canRedo) { const result = this._toolModel.redoMeasurement(); this.updateToolAssistance(); return result; } const message = MeasureTools.localization.getLocalizedString("MeasureTools:Generic.nothingToRedo"); this.showMessage(OutputMessagePriority.Info, message); return false; } async onResetButtonDown(_ev) { if (undefined !== this.toolModel.dynamicMeasurement) await this.onReinitialize(); else await this.onRestartTool(); return EventHandled.Yes; } async onKeyTransition(wentDown, keyEvent) { if (EventHandled.Yes === (await super.onKeyTransition(wentDown, keyEvent))) return EventHandled.Yes; if (wentDown && "escape" === keyEvent.key.toLowerCase()) { await this.exitTool(); return EventHandled.Yes; } return EventHandled.No; } testDecorationHit(id) { return this._toolModel.testDecorationHit(id); } getDecorationGeometry(hit) { return this._toolModel.getDecorationGeometry(hit); } async getToolTip(hit) { const defaultToolTip = async (hit) => { const toolTip = await this._toolModel.getToolTip(hit); if (toolTip === "") return super.getToolTip(hit); return toolTip; }; if (!this._enableSheetMeasurements) { return defaultToolTip(hit); } else { return SheetMeasurementsHelper.getSheetToolTipText(hit, this.allowedDrawingTypes, defaultToolTip); } } decorate(context) { this._toolModel.decorate(context); } async onUnsuspend() { this.updateAccuSnap(); this.updateToolAssistance(); } persistMeasurements() { return this._toolModel.persistMeasurements(); } clearMeasurements(viewportType) { this._toolModel.clearMeasurements(viewportType); } updateAccuSnap() { IModelApp.accuSnap.enableSnap(true); } updateToolAssistance() { } setupEvents() { this._toolModel.onNewMeasurement.addListener((args) => { MeasurementTool.onNewMeasurement.emit(args); }); this._toolModel.onDynamicMeasurementChanged.addListener((args) => { MeasurementTool.onDynamicMeasurementChanged.emit(args); }); } } //# sourceMappingURL=MeasurementTool.js.map