UNPKG

@itwin/core-frontend

Version:
565 lines • 33.4 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module SelectionSet */ Object.defineProperty(exports, "__esModule", { value: true }); exports.SelectionTool = exports.SelectionProcessing = exports.SelectionMode = exports.SelectionMethod = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); const appui_abstract_1 = require("@itwin/appui-abstract"); const ElementLocateManager_1 = require("../ElementLocateManager"); const IModelApp_1 = require("../IModelApp"); const PrimitiveTool_1 = require("./PrimitiveTool"); const Tool_1 = require("./Tool"); const ToolAdmin_1 = require("./ToolAdmin"); const ToolAssistance_1 = require("./ToolAssistance"); const ElementSetTool_1 = require("./ElementSetTool"); // cSpell:ignore buttongroup /** The method for choosing elements with the [[SelectionTool]] * @public * @extensions */ var SelectionMethod; (function (SelectionMethod) { /** Identify element(s) by picking for drag selection (inside/overlap for drag box selection determined by point direction and shift key) */ SelectionMethod[SelectionMethod["Pick"] = 0] = "Pick"; /** Identify elements by overlap with crossing line */ SelectionMethod[SelectionMethod["Line"] = 1] = "Line"; /** Identify elements by box selection (inside/overlap for box selection determined by point direction and shift key) */ SelectionMethod[SelectionMethod["Box"] = 2] = "Box"; })(SelectionMethod || (exports.SelectionMethod = SelectionMethod = {})); /** The mode for choosing elements with the [[SelectionTool]] * @public * @extensions */ var SelectionMode; (function (SelectionMode) { /** Identified elements replace the current selection set (use control key to add or remove) */ SelectionMode[SelectionMode["Replace"] = 0] = "Replace"; /** Identified elements are added to the current selection set */ SelectionMode[SelectionMode["Add"] = 1] = "Add"; /** Identified elements are removed from the current selection set */ SelectionMode[SelectionMode["Remove"] = 2] = "Remove"; })(SelectionMode || (exports.SelectionMode = SelectionMode = {})); /** The processing method to use to update the current selection. * @public * @extensions */ var SelectionProcessing; (function (SelectionProcessing) { /** Add element to selection. */ SelectionProcessing[SelectionProcessing["AddElementToSelection"] = 0] = "AddElementToSelection"; /** Remove element from selection. */ SelectionProcessing[SelectionProcessing["RemoveElementFromSelection"] = 1] = "RemoveElementFromSelection"; /** If element is in selection remove it, else add it. */ SelectionProcessing[SelectionProcessing["InvertElementInSelection"] = 2] = "InvertElementInSelection"; /** Replace current selection with element. */ SelectionProcessing[SelectionProcessing["ReplaceSelectionWithElement"] = 3] = "ReplaceSelectionWithElement"; })(SelectionProcessing || (exports.SelectionProcessing = SelectionProcessing = {})); /** Tool for picking a set of elements of interest, selected by the user. * @public */ class SelectionTool extends PrimitiveTool_1.PrimitiveTool { static hidden = false; static toolId = "Select"; static iconSpec = "icon-cursor"; _isSelectByPoints = false; _isSuspended = false; _points = []; _selectionMethodValue = { value: SelectionMethod.Pick }; _selectionModeValue = { value: SelectionMode.Replace }; requireWriteableTarget() { return false; } autoLockTarget() { } // NOTE: For selecting elements we only care about iModel, so don't lock target model automatically. wantSelectionClearOnMiss(_ev) { return SelectionMode.Replace === this.selectionMode; } wantEditManipulators() { return SelectionMethod.Pick === this.selectionMethod; } wantPickableDecorations() { return this.wantEditManipulators(); } // Allow pickable decorations selection to be independent of manipulators... wantToolSettings() { return true; } get selectionMethod() { return this._selectionMethodValue.value; } set selectionMethod(method) { this._selectionMethodValue.value = method; } get selectionMode() { return this._selectionModeValue.value; } set selectionMode(mode) { this._selectionModeValue.value = mode; } static methodsMessage(str) { return Tool_1.CoreTools.translate(`ElementSet.SelectionMethods.${str}`); } static _methodsName = "selectionMethods"; /* The property descriptions used to generate ToolSettings UI. */ static _getMethodsDescription() { return { name: SelectionTool._methodsName, displayLabel: "", typename: "enum", editor: { name: "enum-buttongroup", params: [{ type: appui_abstract_1.PropertyEditorParamTypes.ButtonGroupData, buttons: [ { iconSpec: "icon-select-single" }, { iconSpec: "icon-select-line" }, { iconSpec: "icon-select-box" }, ], }, { type: appui_abstract_1.PropertyEditorParamTypes.SuppressEditorLabel, suppressLabelPlaceholder: true, }, ], }, enum: { choices: [ { label: SelectionTool.methodsMessage("Pick"), value: SelectionMethod.Pick }, { label: SelectionTool.methodsMessage("Line"), value: SelectionMethod.Line }, { label: SelectionTool.methodsMessage("Box"), value: SelectionMethod.Box }, ], }, }; } static modesMessage(str) { return Tool_1.CoreTools.translate(`ElementSet.SelectionModes.${str}`); } static _modesName = "selectionModes"; /* The property descriptions used to generate ToolSettings UI. */ static _getModesDescription() { return { name: SelectionTool._modesName, displayLabel: "", typename: "enum", editor: { name: "enum-buttongroup", params: [{ type: appui_abstract_1.PropertyEditorParamTypes.ButtonGroupData, buttons: [ { iconSpec: "icon-replace" }, { iconSpec: "icon-select-plus" }, { iconSpec: "icon-select-minus", isEnabledFunction: () => { const tool = IModelApp_1.IModelApp.toolAdmin.activeTool; return tool instanceof PrimitiveTool_1.PrimitiveTool ? tool.iModel.selectionSet.isActive : false; }, }, ], }, { type: appui_abstract_1.PropertyEditorParamTypes.SuppressEditorLabel, suppressLabelPlaceholder: true, }, ], }, enum: { choices: [ { label: SelectionTool.modesMessage("Replace"), value: SelectionMode.Replace }, { label: SelectionTool.modesMessage("Add"), value: SelectionMode.Add }, { label: SelectionTool.modesMessage("Remove"), value: SelectionMode.Remove }, ], }, }; } showPrompt(mode, method) { let mainMsg = "ElementSet.Prompts."; switch (method) { case SelectionMethod.Pick: mainMsg += "IdentifyElement"; break; case SelectionMethod.Line: mainMsg += (0 === this._points.length ? "StartPoint" : "EndPoint"); break; case SelectionMethod.Box: mainMsg += (0 === this._points.length ? "StartCorner" : "OppositeCorner"); break; } const mainInstruction = ToolAssistance_1.ToolAssistance.createInstruction(this.iconSpec, Tool_1.CoreTools.translate(mainMsg)); const sections = []; switch (method) { case SelectionMethod.Pick: const mousePickInstructions = []; mousePickInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.LeftClick, Tool_1.CoreTools.translate("ElementSet.Inputs.AcceptElement"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); mousePickInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.LeftClickDrag, Tool_1.CoreTools.translate("ElementSet.Inputs.BoxCorners"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); mousePickInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.RightClickDrag, Tool_1.CoreTools.translate("ElementSet.Inputs.CrossingLine"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); mousePickInstructions.push(ToolAssistance_1.ToolAssistance.createModifierKeyInstruction(ToolAssistance_1.ToolAssistance.shiftKey, ToolAssistance_1.ToolAssistanceImage.LeftClickDrag, Tool_1.CoreTools.translate("ElementSet.Inputs.OverlapSelection"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); if (SelectionMode.Replace === mode) { mousePickInstructions.push(ToolAssistance_1.ToolAssistance.createKeyboardInstruction(ToolAssistance_1.ToolAssistance.ctrlKeyboardInfo, Tool_1.CoreTools.translate("ElementSet.Inputs.InvertSelection"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); mousePickInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.CursorClick, Tool_1.CoreTools.translate("ElementSet.Inputs.ClearSelection"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); } sections.push(ToolAssistance_1.ToolAssistance.createSection(mousePickInstructions, ToolAssistance_1.ToolAssistance.inputsLabel)); const touchPickInstructions = []; if (!ToolAssistance_1.ToolAssistance.createTouchCursorInstructions(touchPickInstructions)) touchPickInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.OneTouchTap, Tool_1.CoreTools.translate("ElementSet.Inputs.AcceptElement"), false, ToolAssistance_1.ToolAssistanceInputMethod.Touch)); sections.push(ToolAssistance_1.ToolAssistance.createSection(touchPickInstructions, ToolAssistance_1.ToolAssistance.inputsLabel)); break; case SelectionMethod.Line: const mouseLineInstructions = []; mouseLineInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.LeftClick, Tool_1.CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); if (SelectionMode.Replace === mode) mouseLineInstructions.push(ToolAssistance_1.ToolAssistance.createModifierKeyInstruction(ToolAssistance_1.ToolAssistance.ctrlKey, ToolAssistance_1.ToolAssistanceImage.LeftClick, Tool_1.CoreTools.translate("ElementSet.Inputs.InvertSelection"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); sections.push(ToolAssistance_1.ToolAssistance.createSection(mouseLineInstructions, ToolAssistance_1.ToolAssistance.inputsLabel)); const touchLineInstructions = []; touchLineInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.OneTouchDrag, Tool_1.CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistance_1.ToolAssistanceInputMethod.Touch)); sections.push(ToolAssistance_1.ToolAssistance.createSection(touchLineInstructions, ToolAssistance_1.ToolAssistance.inputsLabel)); break; case SelectionMethod.Box: const mouseBoxInstructions = []; mouseBoxInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.LeftClick, Tool_1.CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); mouseBoxInstructions.push(ToolAssistance_1.ToolAssistance.createModifierKeyInstruction(ToolAssistance_1.ToolAssistance.shiftKey, ToolAssistance_1.ToolAssistanceImage.LeftClick, Tool_1.CoreTools.translate("ElementSet.Inputs.OverlapSelection"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); if (SelectionMode.Replace === mode) mouseBoxInstructions.push(ToolAssistance_1.ToolAssistance.createModifierKeyInstruction(ToolAssistance_1.ToolAssistance.ctrlKey, ToolAssistance_1.ToolAssistanceImage.LeftClick, Tool_1.CoreTools.translate("ElementSet.Inputs.InvertSelection"), false, ToolAssistance_1.ToolAssistanceInputMethod.Mouse)); sections.push(ToolAssistance_1.ToolAssistance.createSection(mouseBoxInstructions, ToolAssistance_1.ToolAssistance.inputsLabel)); const touchBoxInstructions = []; touchBoxInstructions.push(ToolAssistance_1.ToolAssistance.createInstruction(ToolAssistance_1.ToolAssistanceImage.OneTouchDrag, Tool_1.CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistance_1.ToolAssistanceInputMethod.Touch)); sections.push(ToolAssistance_1.ToolAssistance.createSection(touchBoxInstructions, ToolAssistance_1.ToolAssistance.inputsLabel)); break; } const instructions = ToolAssistance_1.ToolAssistance.createInstructions(mainInstruction, sections); IModelApp_1.IModelApp.notifications.setToolAssistance(instructions); } initSelectTool() { const method = this.selectionMethod; const mode = this.selectionMode; const enableLocate = SelectionMethod.Pick === method; this._isSelectByPoints = false; this._points.length = 0; this.initLocateElements(enableLocate, false, enableLocate ? "default" : IModelApp_1.IModelApp.viewManager.crossHairCursor, Tool_1.CoordinateLockOverrides.All); IModelApp_1.IModelApp.locateManager.options.allowDecorations = true; // Always locate to display tool tip even if we reject for adding to selection set... this.showPrompt(mode, method); } processMiss(_ev) { if (!this.iModel.selectionSet.isActive) return false; this.iModel.selectionSet.emptyAll(); return true; } updateSelection(elementId, process) { let returnValue = false; switch (process) { case SelectionProcessing.AddElementToSelection: returnValue = this.iModel.selectionSet.add(elementId); break; case SelectionProcessing.RemoveElementFromSelection: returnValue = this.iModel.selectionSet.remove(elementId); break; case SelectionProcessing.InvertElementInSelection: // (if element is in selection remove it else add it.) returnValue = this.iModel.selectionSet.invert(elementId); break; case SelectionProcessing.ReplaceSelectionWithElement: this.iModel.selectionSet.replace(elementId); returnValue = true; break; default: return false; } // always force UI to sync display of options since the select option of Remove should only be enabled if the selection set has elements. if (returnValue) this.syncSelectionMode(); return returnValue; } async processSelection(elementId, process) { return this.updateSelection(elementId, process); } useOverlapSelection(ev) { if (undefined === ev.viewport) return false; const pt1 = ev.viewport.worldToView(this._points[0]); const pt2 = ev.viewport.worldToView(ev.point); const overlapMode = (pt1.x > pt2.x); return (ev.isShiftKey ? !overlapMode : overlapMode); // Shift inverts inside/overlap selection... } selectByPointsDecorate(context) { if (!this._isSelectByPoints) return; const ev = new Tool_1.BeButtonEvent(); IModelApp_1.IModelApp.toolAdmin.fillEventFromCursorLocation(ev); if (undefined === ev.viewport) return; const vp = context.viewport; const bestContrastIsBlack = (core_common_1.ColorDef.black === vp.getContrastToBackgroundColor()); const crossingLine = (SelectionMethod.Line === this.selectionMethod || (SelectionMethod.Pick === this.selectionMethod && Tool_1.BeButton.Reset === ev.button)); const overlapSelection = (crossingLine || this.useOverlapSelection(ev)); const position = vp.worldToView(this._points[0]); position.x = Math.floor(position.x) + 0.5; position.y = Math.floor(position.y) + 0.5; const position2 = vp.worldToView(ev.point); position2.x = Math.floor(position2.x) + 0.5; position2.y = Math.floor(position2.y) + 0.5; const offset = position2.minus(position); const drawDecoration = (ctx) => { ctx.strokeStyle = bestContrastIsBlack ? "black" : "white"; ctx.lineWidth = 1; if (overlapSelection) ctx.setLineDash([5, 5]); if (crossingLine) { ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(offset.x, offset.y); ctx.stroke(); } else { ctx.strokeRect(0, 0, offset.x, offset.y); ctx.fillStyle = bestContrastIsBlack ? "rgba(0,0,0,.06)" : "rgba(255,255,255,.06)"; ctx.fillRect(0, 0, offset.x, offset.y); } }; context.addCanvasDecoration({ position, drawDecoration }); } async selectByPointsProcess(origin, corner, ev, method, overlap) { const vp = ev.viewport; if (!vp) return false; const filter = (id) => { return !core_bentley_1.Id64.isTransient(id); }; const contents = await ElementSetTool_1.ElementSetTool.getAreaOrVolumeSelectionCandidates(vp, origin, corner, method, overlap, this.wantPickableDecorations() ? undefined : filter, this.wantPickableDecorations()); if (0 === contents.size) { if (!ev.isControlKey && this.wantSelectionClearOnMiss(ev) && this.processMiss(ev)) { this.syncSelectionMode(); return true; } return false; } switch (this.selectionMode) { case SelectionMode.Replace: if (!ev.isControlKey) return this.processSelection(contents, SelectionProcessing.ReplaceSelectionWithElement); return this.processSelection(contents, SelectionProcessing.InvertElementInSelection); case SelectionMode.Add: return this.processSelection(contents, SelectionProcessing.AddElementToSelection); case SelectionMode.Remove: return this.processSelection(contents, SelectionProcessing.RemoveElementFromSelection); } } selectByPointsStart(ev) { if (Tool_1.BeButton.Data !== ev.button && Tool_1.BeButton.Reset !== ev.button) return false; this._points.length = 0; this._points.push(ev.point.clone()); this._isSelectByPoints = true; IModelApp_1.IModelApp.accuSnap.enableLocate(false); IModelApp_1.IModelApp.toolAdmin.setLocateCircleOn(false); this.showPrompt(this.selectionMode, this.selectionMethod); return true; } async selectByPointsEnd(ev) { if (!this._isSelectByPoints) return false; const vp = ev.viewport; if (vp === undefined) { this.initSelectTool(); return false; } const origin = vp.worldToView(this._points[0]); const corner = vp.worldToView(ev.point); if (SelectionMethod.Line === this.selectionMethod || (SelectionMethod.Pick === this.selectionMethod && Tool_1.BeButton.Reset === ev.button)) await this.selectByPointsProcess(origin, corner, ev, SelectionMethod.Line, true); else await this.selectByPointsProcess(origin, corner, ev, SelectionMethod.Box, this.useOverlapSelection(ev)); this.initSelectTool(); vp.invalidateDecorations(); return true; } async onMouseMotion(ev) { if (undefined !== ev.viewport && this._isSelectByPoints) ev.viewport.invalidateDecorations(); } async selectDecoration(ev, currHit) { if (undefined === currHit) currHit = await IModelApp_1.IModelApp.locateManager.doLocate(new ElementLocateManager_1.LocateResponse(), true, ev.point, ev.viewport, ev.inputSource); if (undefined !== currHit) return (currHit.isElementHit ? IModelApp_1.IModelApp.viewManager.overrideElementButtonEvent(currHit, ev) : IModelApp_1.IModelApp.viewManager.onDecorationButtonEvent(currHit, ev)); return Tool_1.EventHandled.No; } async processHit(ev, hit) { if (hit.isModelHit || hit.isMapHit) return Tool_1.EventHandled.No; // model hit = terrain, reality models, background maps, etc - not selectable switch (this.selectionMode) { case SelectionMode.Replace: await this.processSelection(hit.sourceId, ev.isControlKey ? SelectionProcessing.InvertElementInSelection : SelectionProcessing.ReplaceSelectionWithElement); break; case SelectionMode.Add: await this.processSelection(hit.sourceId, SelectionProcessing.AddElementToSelection); break; case SelectionMode.Remove: await this.processSelection(hit.sourceId, SelectionProcessing.RemoveElementFromSelection); break; } return Tool_1.EventHandled.Yes; } async onMouseStartDrag(ev) { IModelApp_1.IModelApp.accuSnap.clear(); // Need to test hit at start drag location, not current AccuSnap... if (Tool_1.EventHandled.Yes === await this.selectDecoration(ev)) return Tool_1.EventHandled.Yes; if (Tool_1.InputSource.Touch === ev.inputSource && SelectionMethod.Pick === this.selectionMethod) return Tool_1.EventHandled.No; // Require method change for line/box selection...allow IdleTool to handle touch move... return this.selectByPointsStart(ev) ? Tool_1.EventHandled.Yes : Tool_1.EventHandled.No; } async onMouseEndDrag(ev) { return await this.selectByPointsEnd(ev) ? Tool_1.EventHandled.Yes : Tool_1.EventHandled.No; } async onDataButtonUp(ev) { if (undefined === ev.viewport) return Tool_1.EventHandled.No; if (await this.selectByPointsEnd(ev)) return Tool_1.EventHandled.Yes; if (SelectionMethod.Pick !== this.selectionMethod) { if (!ev.isControlKey && this.wantSelectionClearOnMiss(ev) && this.processMiss(ev)) this.syncSelectionMode(); if (Tool_1.InputSource.Touch !== ev.inputSource) this.selectByPointsStart(ev); // Require touch move and not tap to start crossing line/box selection... return Tool_1.EventHandled.Yes; } const hit = await IModelApp_1.IModelApp.locateManager.doLocate(new ElementLocateManager_1.LocateResponse(), true, ev.point, ev.viewport, ev.inputSource); if (hit !== undefined) { if (Tool_1.EventHandled.Yes === await this.selectDecoration(ev, hit)) return Tool_1.EventHandled.Yes; if (Tool_1.EventHandled.Yes === await this.processHit(ev, hit)) return Tool_1.EventHandled.Yes; } if (!ev.isControlKey && this.wantSelectionClearOnMiss(ev) && this.processMiss(ev)) this.syncSelectionMode(); return Tool_1.EventHandled.Yes; } async onResetButtonUp(ev) { if (this._isSelectByPoints) { if (undefined !== ev.viewport) ev.viewport.invalidateDecorations(); this.initSelectTool(); return Tool_1.EventHandled.Yes; } // Check for overlapping hits... const lastHit = SelectionMode.Remove === this.selectionMode ? undefined : IModelApp_1.IModelApp.locateManager.currHit; if (lastHit && this.iModel.selectionSet.elements.has(lastHit.sourceId)) { const autoHit = IModelApp_1.IModelApp.accuSnap.currHit; // Play nice w/auto-locate, only remove previous hit if not currently auto-locating or over previous hit if (undefined === autoHit || autoHit.isSameHit(lastHit)) { const response = new ElementLocateManager_1.LocateResponse(); let nextHit; do { nextHit = await IModelApp_1.IModelApp.locateManager.doLocate(response, false, ev.point, ev.viewport, ev.inputSource); } while (undefined !== nextHit && (nextHit.isModelHit || nextHit.isMapHit)); // Ignore reality models, terrain, maps, etc. // remove element(s) previously selected if in replace mode, or if we have a next element in add mode if (SelectionMode.Replace === this.selectionMode || undefined !== nextHit) await this.processSelection(lastHit.sourceId, SelectionProcessing.RemoveElementFromSelection); // add element(s) located via reset button if (undefined !== nextHit) await this.processSelection(nextHit.sourceId, SelectionProcessing.AddElementToSelection); return Tool_1.EventHandled.Yes; } } if (Tool_1.EventHandled.Yes === await this.selectDecoration(ev, IModelApp_1.IModelApp.accuSnap.currHit)) return Tool_1.EventHandled.Yes; await IModelApp_1.IModelApp.accuSnap.resetButton(); return Tool_1.EventHandled.Yes; } async onSuspend() { this._isSuspended = true; if (this.wantEditManipulators()) IModelApp_1.IModelApp.toolAdmin.manipulatorToolEvent.raiseEvent(this, ToolAdmin_1.ManipulatorToolEvent.Suspend); } async onUnsuspend() { this._isSuspended = false; if (this.wantEditManipulators()) IModelApp_1.IModelApp.toolAdmin.manipulatorToolEvent.raiseEvent(this, ToolAdmin_1.ManipulatorToolEvent.Unsuspend); this.showPrompt(this.selectionMode, this.selectionMethod); } async onTouchMoveStart(ev, startEv) { if (startEv.isSingleTouch && !this._isSelectByPoints) await IModelApp_1.IModelApp.toolAdmin.convertTouchMoveStartToButtonDownAndMotion(startEv, ev); return (this._isSuspended || this._isSelectByPoints) ? Tool_1.EventHandled.Yes : Tool_1.EventHandled.No; } async onTouchMove(ev) { if (this._isSelectByPoints) return IModelApp_1.IModelApp.toolAdmin.convertTouchMoveToMotion(ev); } async onTouchComplete(ev) { if (this._isSelectByPoints) return IModelApp_1.IModelApp.toolAdmin.convertTouchEndToButtonUp(ev); } async onTouchCancel(ev) { if (this._isSelectByPoints) return IModelApp_1.IModelApp.toolAdmin.convertTouchEndToButtonUp(ev, Tool_1.BeButton.Reset); } decorate(context) { this.selectByPointsDecorate(context); } async onModifierKeyTransition(_wentDown, modifier, _event) { return (modifier === Tool_1.BeModifierKeys.Shift && this._isSelectByPoints) ? Tool_1.EventHandled.Yes : Tool_1.EventHandled.No; } async filterHit(hit, out) { if (!this.wantPickableDecorations() && !hit.isElementHit) return ElementLocateManager_1.LocateFilterStatus.Reject; const mode = this.selectionMode; if (SelectionMode.Replace === mode) return ElementLocateManager_1.LocateFilterStatus.Accept; const isSelected = this.iModel.selectionSet.elements.has(hit.sourceId); const status = ((SelectionMode.Add === mode ? !isSelected : isSelected) ? ElementLocateManager_1.LocateFilterStatus.Accept : ElementLocateManager_1.LocateFilterStatus.Reject); if (out && ElementLocateManager_1.LocateFilterStatus.Reject === status) out.explanation = Tool_1.CoreTools.translate(`ElementSet.Error.${isSelected ? "AlreadySelected" : "NotSelected"}`); return status; } async onRestartTool() { return this.exitTool(); } async onCleanup() { if (this.wantEditManipulators()) IModelApp_1.IModelApp.toolAdmin.manipulatorToolEvent.raiseEvent(this, ToolAdmin_1.ManipulatorToolEvent.Stop); } async onPostInstall() { await super.onPostInstall(); if (!this.targetView) return; if (this.wantEditManipulators()) IModelApp_1.IModelApp.toolAdmin.manipulatorToolEvent.raiseEvent(this, ToolAdmin_1.ManipulatorToolEvent.Start); this.initSelectTool(); } static async startTool() { return new SelectionTool().run(); } syncSelectionMode() { if (SelectionMode.Remove === this.selectionMode && !this.iModel.selectionSet.isActive) { // No selection active resetting selection mode since there is nothing to Remove this.selectionMode = SelectionMode.Replace; this.initSelectTool(); } if (this.wantToolSettings()) { const syncMode = { value: this._selectionModeValue, propertyName: SelectionTool._modesName }; IModelApp_1.IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, syncMode); this.syncToolSettingsProperties([syncMode]); } } /** Used to supply DefaultToolSettingProvider with a list of properties to use to generate ToolSettings. If undefined then no ToolSettings will be displayed * @beta */ supplyToolSettingsProperties() { if (!this.wantToolSettings()) return undefined; // load latest values from session IModelApp_1.IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [SelectionTool._modesName])?.forEach((value) => { if (value.propertyName === SelectionTool._modesName) this._selectionModeValue = value.value; }); // Make sure a mode of SelectionMode.Remove is valid if (SelectionMode.Remove === this.selectionMode && !this.iModel.selectionSet.isActive) { this.selectionMode = SelectionMode.Replace; IModelApp_1.IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { propertyName: SelectionTool._modesName, value: this._selectionModeValue }); } const toolSettings = new Array(); // generate 3 columns - label will be placed in column 0 and button group editors in columns 1 and 2. toolSettings.push({ value: this._selectionMethodValue, property: SelectionTool._getMethodsDescription(), editorPosition: { rowPriority: 0, columnIndex: 1 } }); toolSettings.push({ value: this._selectionModeValue, property: SelectionTool._getModesDescription(), editorPosition: { rowPriority: 0, columnIndex: 2 } }); return toolSettings; } /** Used to send changes from UI back to Tool * @beta */ async applyToolSettingPropertyChange(updatedValue) { let changed = false; if (updatedValue.propertyName === SelectionTool._methodsName) { const saveWantManipulators = this.wantEditManipulators(); this._selectionMethodValue = updatedValue.value; if (this._selectionMethodValue) { const currWantManipulators = this.wantEditManipulators(); if (saveWantManipulators !== currWantManipulators) IModelApp_1.IModelApp.toolAdmin.manipulatorToolEvent.raiseEvent(this, currWantManipulators ? ToolAdmin_1.ManipulatorToolEvent.Start : ToolAdmin_1.ManipulatorToolEvent.Stop); changed = true; } } if (updatedValue.propertyName === SelectionTool._modesName) { this._selectionModeValue = updatedValue.value; if (this._selectionModeValue) { if (this.wantToolSettings()) IModelApp_1.IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { propertyName: SelectionTool._modesName, value: this._selectionModeValue }); changed = true; } } if (changed) this.initSelectTool(); return true; // return true if change is valid } } exports.SelectionTool = SelectionTool; //# sourceMappingURL=SelectTool.js.map