UNPKG

monaco-editor-core

Version:

A browser based code editor

294 lines (293 loc) • 12.1 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as dom from '../../dom.js'; import { CaseSensitiveToggle, RegexToggle, WholeWordsToggle } from './findInputToggles.js'; import { HistoryInputBox } from '../inputbox/inputBox.js'; import { Widget } from '../widget.js'; import { Emitter } from '../../../common/event.js'; import './findInput.css'; import * as nls from '../../../../nls.js'; import { DisposableStore, MutableDisposable } from '../../../common/lifecycle.js'; import { createInstantHoverDelegate } from '../hover/hoverDelegateFactory.js'; const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input"); export class FindInput extends Widget { constructor(parent, contextViewProvider, options) { super(); this.fixFocusOnOptionClickEnabled = true; this.imeSessionInProgress = false; this.additionalTogglesDisposables = this._register(new MutableDisposable()); this.additionalToggles = []; this._onDidOptionChange = this._register(new Emitter()); this.onDidOptionChange = this._onDidOptionChange.event; this._onKeyDown = this._register(new Emitter()); this.onKeyDown = this._onKeyDown.event; this._onMouseDown = this._register(new Emitter()); this.onMouseDown = this._onMouseDown.event; this._onInput = this._register(new Emitter()); this._onKeyUp = this._register(new Emitter()); this._onCaseSensitiveKeyDown = this._register(new Emitter()); this.onCaseSensitiveKeyDown = this._onCaseSensitiveKeyDown.event; this._onRegexKeyDown = this._register(new Emitter()); this.onRegexKeyDown = this._onRegexKeyDown.event; this._lastHighlightFindOptions = 0; this.placeholder = options.placeholder || ''; this.validation = options.validation; this.label = options.label || NLS_DEFAULT_LABEL; this.showCommonFindToggles = !!options.showCommonFindToggles; const appendCaseSensitiveLabel = options.appendCaseSensitiveLabel || ''; const appendWholeWordsLabel = options.appendWholeWordsLabel || ''; const appendRegexLabel = options.appendRegexLabel || ''; const history = options.history || []; const flexibleHeight = !!options.flexibleHeight; const flexibleWidth = !!options.flexibleWidth; const flexibleMaxHeight = options.flexibleMaxHeight; this.domNode = document.createElement('div'); this.domNode.classList.add('monaco-findInput'); this.inputBox = this._register(new HistoryInputBox(this.domNode, contextViewProvider, { placeholder: this.placeholder || '', ariaLabel: this.label || '', validationOptions: { validation: this.validation }, history, showHistoryHint: options.showHistoryHint, flexibleHeight, flexibleWidth, flexibleMaxHeight, inputBoxStyles: options.inputBoxStyles, })); const hoverDelegate = this._register(createInstantHoverDelegate()); if (this.showCommonFindToggles) { this.regex = this._register(new RegexToggle({ appendTitle: appendRegexLabel, isChecked: false, hoverDelegate, ...options.toggleStyles })); this._register(this.regex.onChange(viaKeyboard => { this._onDidOptionChange.fire(viaKeyboard); if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { this.inputBox.focus(); } this.validate(); })); this._register(this.regex.onKeyDown(e => { this._onRegexKeyDown.fire(e); })); this.wholeWords = this._register(new WholeWordsToggle({ appendTitle: appendWholeWordsLabel, isChecked: false, hoverDelegate, ...options.toggleStyles })); this._register(this.wholeWords.onChange(viaKeyboard => { this._onDidOptionChange.fire(viaKeyboard); if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { this.inputBox.focus(); } this.validate(); })); this.caseSensitive = this._register(new CaseSensitiveToggle({ appendTitle: appendCaseSensitiveLabel, isChecked: false, hoverDelegate, ...options.toggleStyles })); this._register(this.caseSensitive.onChange(viaKeyboard => { this._onDidOptionChange.fire(viaKeyboard); if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { this.inputBox.focus(); } this.validate(); })); this._register(this.caseSensitive.onKeyDown(e => { this._onCaseSensitiveKeyDown.fire(e); })); // Arrow-Key support to navigate between options const indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.domNode]; this.onkeydown(this.domNode, (event) => { if (event.equals(15 /* KeyCode.LeftArrow */) || event.equals(17 /* KeyCode.RightArrow */) || event.equals(9 /* KeyCode.Escape */)) { const index = indexes.indexOf(this.domNode.ownerDocument.activeElement); if (index >= 0) { let newIndex = -1; if (event.equals(17 /* KeyCode.RightArrow */)) { newIndex = (index + 1) % indexes.length; } else if (event.equals(15 /* KeyCode.LeftArrow */)) { if (index === 0) { newIndex = indexes.length - 1; } else { newIndex = index - 1; } } if (event.equals(9 /* KeyCode.Escape */)) { indexes[index].blur(); this.inputBox.focus(); } else if (newIndex >= 0) { indexes[newIndex].focus(); } dom.EventHelper.stop(event, true); } } }); } this.controls = document.createElement('div'); this.controls.className = 'controls'; this.controls.style.display = this.showCommonFindToggles ? '' : 'none'; if (this.caseSensitive) { this.controls.append(this.caseSensitive.domNode); } if (this.wholeWords) { this.controls.appendChild(this.wholeWords.domNode); } if (this.regex) { this.controls.appendChild(this.regex.domNode); } this.setAdditionalToggles(options?.additionalToggles); if (this.controls) { this.domNode.appendChild(this.controls); } parent?.appendChild(this.domNode); this._register(dom.addDisposableListener(this.inputBox.inputElement, 'compositionstart', (e) => { this.imeSessionInProgress = true; })); this._register(dom.addDisposableListener(this.inputBox.inputElement, 'compositionend', (e) => { this.imeSessionInProgress = false; this._onInput.fire(); })); this.onkeydown(this.inputBox.inputElement, (e) => this._onKeyDown.fire(e)); this.onkeyup(this.inputBox.inputElement, (e) => this._onKeyUp.fire(e)); this.oninput(this.inputBox.inputElement, (e) => this._onInput.fire()); this.onmousedown(this.inputBox.inputElement, (e) => this._onMouseDown.fire(e)); } get onDidChange() { return this.inputBox.onDidChange; } layout(style) { this.inputBox.layout(); this.updateInputBoxPadding(style.collapsedFindWidget); } enable() { this.domNode.classList.remove('disabled'); this.inputBox.enable(); this.regex?.enable(); this.wholeWords?.enable(); this.caseSensitive?.enable(); for (const toggle of this.additionalToggles) { toggle.enable(); } } disable() { this.domNode.classList.add('disabled'); this.inputBox.disable(); this.regex?.disable(); this.wholeWords?.disable(); this.caseSensitive?.disable(); for (const toggle of this.additionalToggles) { toggle.disable(); } } setFocusInputOnOptionClick(value) { this.fixFocusOnOptionClickEnabled = value; } setEnabled(enabled) { if (enabled) { this.enable(); } else { this.disable(); } } setAdditionalToggles(toggles) { for (const currentToggle of this.additionalToggles) { currentToggle.domNode.remove(); } this.additionalToggles = []; this.additionalTogglesDisposables.value = new DisposableStore(); for (const toggle of toggles ?? []) { this.additionalTogglesDisposables.value.add(toggle); this.controls.appendChild(toggle.domNode); this.additionalTogglesDisposables.value.add(toggle.onChange(viaKeyboard => { this._onDidOptionChange.fire(viaKeyboard); if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) { this.inputBox.focus(); } })); this.additionalToggles.push(toggle); } if (this.additionalToggles.length > 0) { this.controls.style.display = ''; } this.updateInputBoxPadding(); } updateInputBoxPadding(controlsHidden = false) { if (controlsHidden) { this.inputBox.paddingRight = 0; } else { this.inputBox.paddingRight = ((this.caseSensitive?.width() ?? 0) + (this.wholeWords?.width() ?? 0) + (this.regex?.width() ?? 0)) + this.additionalToggles.reduce((r, t) => r + t.width(), 0); } } getValue() { return this.inputBox.value; } setValue(value) { if (this.inputBox.value !== value) { this.inputBox.value = value; } } select() { this.inputBox.select(); } focus() { this.inputBox.focus(); } getCaseSensitive() { return this.caseSensitive?.checked ?? false; } setCaseSensitive(value) { if (this.caseSensitive) { this.caseSensitive.checked = value; } } getWholeWords() { return this.wholeWords?.checked ?? false; } setWholeWords(value) { if (this.wholeWords) { this.wholeWords.checked = value; } } getRegex() { return this.regex?.checked ?? false; } setRegex(value) { if (this.regex) { this.regex.checked = value; this.validate(); } } focusOnCaseSensitive() { this.caseSensitive?.focus(); } highlightFindOptions() { this.domNode.classList.remove('highlight-' + (this._lastHighlightFindOptions)); this._lastHighlightFindOptions = 1 - this._lastHighlightFindOptions; this.domNode.classList.add('highlight-' + (this._lastHighlightFindOptions)); } validate() { this.inputBox.validate(); } showMessage(message) { this.inputBox.showMessage(message); } clearMessage() { this.inputBox.hideMessage(); } }