@itwin/core-frontend
Version:
iTwin.js frontend components
565 lines • 33.4 kB
JavaScript
"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