UNPKG

@itwin/frontend-devtools

Version:

Debug menu and supporting UI widgets

190 lines 7.78 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Widgets */ import { IModelApp, MessageBoxIconType, MessageBoxType, ParseAndRunResult } from "@itwin/core-frontend"; import { createButton } from "../ui/Button"; import { appendDataListEntries, createDataList } from "../ui/DataList"; import { createTextBox } from "../ui/TextBox"; function keyinsToDataListEntries(keyins) { const entries = []; for (const keyin of keyins) { entries.push({ value: keyin }); } return entries; } /** Controls whether localized and/or non-localized key-in strings appear in a KeyinField's auto-completion list. * @beta */ export var KeyinFieldLocalization; (function (KeyinFieldLocalization) { /** Include only non-localized key-in strings. */ KeyinFieldLocalization[KeyinFieldLocalization["NonLocalized"] = 0] = "NonLocalized"; /** Include only localized key-in strings. */ KeyinFieldLocalization[KeyinFieldLocalization["Localized"] = 1] = "Localized"; /** Include localized and non-localized strings for each key-in. */ KeyinFieldLocalization[KeyinFieldLocalization["Both"] = 2] = "Both"; })(KeyinFieldLocalization || (KeyinFieldLocalization = {})); /** A textbox allowing input of key-ins (localized tool names) combined with a drop-down that lists all registered key-ins, filtered by substring match on the current input. * Press `enter` or click the Enter button to run the key-in. * @beta */ export class KeyinField { /** @alpha */ autoCompleteList; textBox; keyins; _historyIndex; _historyLength = 0; _history; _localization; constructor(props) { this._localization = props.localization ?? KeyinFieldLocalization.NonLocalized; this.keyins = this.findKeyins(); const autoCompleteListId = `${props.baseId}_autoComplete`; this.autoCompleteList = createDataList({ parent: props.parent, entries: keyinsToDataListEntries(this.keyins), id: autoCompleteListId, inline: true, }); this.textBox = createTextBox({ label: props.wantLabel ? "Key-in: " : undefined, id: `${props.baseId}_textBox`, parent: props.parent, handler: () => this.selectAll(), keypresshandler: async (_tb, ev) => { await this.handleKeyPress(ev); }, focushandler: (_tb) => { this.respondToKeyinFocus(); }, tooltip: "Type the key-in text here", inline: true, list: autoCompleteListId, }); if (props.wantButton) { createButton({ handler: async (_bt) => { await this.submitKeyin(); }, parent: props.parent, value: "Enter", inline: true, tooltip: "Click here to execute the key-in", }); } if (undefined !== props.historyLength && props.historyLength > 0) { this.textBox.textbox.onkeydown = (ev) => this.handleKeyDown(ev); // eslint-disable-line @typescript-eslint/promise-function-async this._historyLength = props.historyLength; this._history = []; } } focus() { this.textBox.textbox.focus(); } loseFocus() { this.textBox.textbox.blur(); } selectAll() { this.textBox.textbox.setSelectionRange(0, this.textBox.textbox.value.length); } async handleKeyPress(ev) { ev.stopPropagation(); if ("Enter" === ev.key) await this.submitKeyin(); } async handleKeyDown(ev) { ev.stopPropagation(); if (undefined === this._history || 0 === this._history.length) return; // NB: History list is ordered by most to least recent so moving "backwards" means incrementing the index. const direction = ev.key === "ArrowDown" ? 1 : (ev.key === "ArrowUp" ? 1 : 0); if (0 === direction) return; ev.preventDefault(); ev.stopPropagation(); if (this._historyIndex === undefined) { if (direction < 0) return; else this._historyIndex = -1; } const newIndex = this._historyIndex + direction; if (newIndex >= 0 && newIndex < this._history.length) { this._historyIndex = newIndex; if (this._historyIndex >= 0) this.textBox.textbox.value = this._history[newIndex]; } } resetHistoryIndex() { this._historyIndex = undefined; } pushHistory(keyin) { if (undefined === this._history) return; this.textBox.textbox.value = ""; this.resetHistoryIndex(); if (this._history.length === 0 || keyin.toLowerCase() !== this._history[0].toLowerCase()) { this._history.unshift(keyin); if (this._history.length > this._historyLength) this._history.pop(); } } async submitKeyin() { this.selectAll(); const textBox = this.textBox.textbox; const input = textBox.value; this.pushHistory(input); let message; try { switch (await IModelApp.tools.parseAndRun(input)) { case ParseAndRunResult.ToolNotFound: message = `Cannot find a key-in that matches: ${input}`; break; case ParseAndRunResult.BadArgumentCount: message = "Incorrect number of arguments"; break; case ParseAndRunResult.FailedToRun: message = "Key-in failed to run"; break; } } catch (ex) { message = `Key-in produced exception: ${ex}`; } if (undefined !== message) await IModelApp.notifications.openMessageBox(MessageBoxType.MediumAlert, message, MessageBoxIconType.Warning); } respondToKeyinFocus() { this.resetHistoryIndex(); // Handle case in which new tools were registered since we last populated the auto-complete list. // This can occur e.g. as a result of loading a extension, or deferred initialization of a package like markup. const keyins = this.findKeyins(); if (keyins.length > this.keyins.length) { const newKeyins = []; for (const keyin of keyins) if (!this.keyins.includes(keyin)) { newKeyins.push(keyin); this.keyins.push(keyin); } if (newKeyins.length > 0) appendDataListEntries(this.autoCompleteList, keyinsToDataListEntries(newKeyins)); } } findKeyins() { const keyins = []; const tools = IModelApp.tools.getToolList(); for (const tool of tools) { switch (this._localization) { case KeyinFieldLocalization.Localized: keyins.push(tool.keyin); break; case KeyinFieldLocalization.Both: keyins.push(tool.keyin); if (tool.keyin === tool.englishKeyin) break; /* falls through */ default: case KeyinFieldLocalization.NonLocalized: keyins.push(tool.englishKeyin); break; } } return keyins; } } //# sourceMappingURL=KeyinField.js.map