UNPKG

monaco-editor

Version:
687 lines (686 loc) • 33.6 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); } return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); import './quickopen.css'; import * as nls from '../../../../nls.js'; import * as platform from '../../../common/platform.js'; import * as types from '../../../common/types.js'; import { Filter, Renderer, DataSource, AccessibilityProvider } from './quickOpenViewer.js'; import { InputBox } from '../../../browser/ui/inputbox/inputBox.js'; import { Tree } from '../../tree/browser/treeImpl.js'; import { ProgressBar } from '../../../browser/ui/progressbar/progressbar.js'; import { StandardKeyboardEvent } from '../../../browser/keyboardEvent.js'; import { DefaultController } from '../../tree/browser/treeDefaults.js'; import * as DOM from '../../../browser/dom.js'; import { Disposable } from '../../../common/lifecycle.js'; import { Color } from '../../../common/color.js'; import { mixin } from '../../../common/objects.js'; import { StandardMouseEvent } from '../../../browser/mouseEvent.js'; var QuickOpenController = /** @class */ (function (_super) { __extends(QuickOpenController, _super); function QuickOpenController() { return _super !== null && _super.apply(this, arguments) || this; } QuickOpenController.prototype.onContextMenu = function (tree, element, event) { if (platform.isMacintosh) { return this.onLeftClick(tree, element, event); // https://github.com/Microsoft/vscode/issues/1011 } return _super.prototype.onContextMenu.call(this, tree, element, event); }; return QuickOpenController; }(DefaultController)); export { QuickOpenController }; var defaultStyles = { background: Color.fromHex('#1E1E1E'), foreground: Color.fromHex('#CCCCCC'), pickerGroupForeground: Color.fromHex('#0097FB'), pickerGroupBorder: Color.fromHex('#3F3F46'), widgetShadow: Color.fromHex('#000000'), progressBarBackground: Color.fromHex('#0E70C0') }; var DEFAULT_INPUT_ARIA_LABEL = nls.localize('quickOpenAriaLabel', "Quick picker. Type to narrow down results."); var QuickOpenWidget = /** @class */ (function (_super) { __extends(QuickOpenWidget, _super); function QuickOpenWidget(container, callbacks, options) { var _this = _super.call(this) || this; _this.isDisposed = false; _this.container = container; _this.callbacks = callbacks; _this.options = options; _this.styles = options || Object.create(null); mixin(_this.styles, defaultStyles, false); _this.model = null; return _this; } QuickOpenWidget.prototype.getModel = function () { return this.model; }; QuickOpenWidget.prototype.create = function () { var _this = this; // Container this.element = document.createElement('div'); DOM.addClass(this.element, 'monaco-quick-open-widget'); this.container.appendChild(this.element); this._register(DOM.addDisposableListener(this.element, DOM.EventType.CONTEXT_MENU, function (e) { return DOM.EventHelper.stop(e, true); })); // Do this to fix an issue on Mac where the menu goes into the way this._register(DOM.addDisposableListener(this.element, DOM.EventType.FOCUS, function (e) { return _this.gainingFocus(); }, true)); this._register(DOM.addDisposableListener(this.element, DOM.EventType.BLUR, function (e) { return _this.loosingFocus(e); }, true)); this._register(DOM.addDisposableListener(this.element, DOM.EventType.KEY_DOWN, function (e) { var keyboardEvent = new StandardKeyboardEvent(e); if (keyboardEvent.keyCode === 9 /* Escape */) { DOM.EventHelper.stop(e, true); _this.hide(2 /* CANCELED */); } else if (keyboardEvent.keyCode === 2 /* Tab */ && !keyboardEvent.altKey && !keyboardEvent.ctrlKey && !keyboardEvent.metaKey) { var stops = e.currentTarget.querySelectorAll('input, .monaco-tree, .monaco-tree-row.focused .action-label.icon'); if (keyboardEvent.shiftKey && keyboardEvent.target === stops[0]) { DOM.EventHelper.stop(e, true); stops[stops.length - 1].focus(); } else if (!keyboardEvent.shiftKey && keyboardEvent.target === stops[stops.length - 1]) { DOM.EventHelper.stop(e, true); stops[0].focus(); } } })); // Progress Bar this.progressBar = this._register(new ProgressBar(this.element, { progressBarBackground: this.styles.progressBarBackground })); this.progressBar.hide(); // Input Field this.inputContainer = document.createElement('div'); DOM.addClass(this.inputContainer, 'quick-open-input'); this.element.appendChild(this.inputContainer); this.inputBox = this._register(new InputBox(this.inputContainer, null, { placeholder: this.options.inputPlaceHolder || '', ariaLabel: DEFAULT_INPUT_ARIA_LABEL, inputBackground: this.styles.inputBackground, inputForeground: this.styles.inputForeground, inputBorder: this.styles.inputBorder, inputValidationInfoBackground: this.styles.inputValidationInfoBackground, inputValidationInfoForeground: this.styles.inputValidationInfoForeground, inputValidationInfoBorder: this.styles.inputValidationInfoBorder, inputValidationWarningBackground: this.styles.inputValidationWarningBackground, inputValidationWarningForeground: this.styles.inputValidationWarningForeground, inputValidationWarningBorder: this.styles.inputValidationWarningBorder, inputValidationErrorBackground: this.styles.inputValidationErrorBackground, inputValidationErrorForeground: this.styles.inputValidationErrorForeground, inputValidationErrorBorder: this.styles.inputValidationErrorBorder })); this.inputElement = this.inputBox.inputElement; this.inputElement.setAttribute('role', 'combobox'); this.inputElement.setAttribute('aria-haspopup', 'false'); this.inputElement.setAttribute('aria-autocomplete', 'list'); this._register(DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.INPUT, function (e) { return _this.onType(); })); this._register(DOM.addDisposableListener(this.inputBox.inputElement, DOM.EventType.KEY_DOWN, function (e) { var keyboardEvent = new StandardKeyboardEvent(e); var shouldOpenInBackground = _this.shouldOpenInBackground(keyboardEvent); // Do not handle Tab: It is used to navigate between elements without mouse if (keyboardEvent.keyCode === 2 /* Tab */) { return; } // Pass tree navigation keys to the tree but leave focus in input field else if (keyboardEvent.keyCode === 18 /* DownArrow */ || keyboardEvent.keyCode === 16 /* UpArrow */ || keyboardEvent.keyCode === 12 /* PageDown */ || keyboardEvent.keyCode === 11 /* PageUp */) { DOM.EventHelper.stop(e, true); _this.navigateInTree(keyboardEvent.keyCode, keyboardEvent.shiftKey); // Position cursor at the end of input to allow right arrow (open in background) // to function immediately unless the user has made a selection if (_this.inputBox.inputElement.selectionStart === _this.inputBox.inputElement.selectionEnd) { _this.inputBox.inputElement.selectionStart = _this.inputBox.value.length; } } // Select element on Enter or on Arrow-Right if we are at the end of the input else if (keyboardEvent.keyCode === 3 /* Enter */ || shouldOpenInBackground) { DOM.EventHelper.stop(e, true); var focus_1 = _this.tree.getFocus(); if (focus_1) { _this.elementSelected(focus_1, e, shouldOpenInBackground ? 2 /* OPEN_IN_BACKGROUND */ : 1 /* OPEN */); } } })); // Result count for screen readers this.resultCount = document.createElement('div'); DOM.addClass(this.resultCount, 'quick-open-result-count'); this.resultCount.setAttribute('aria-live', 'polite'); this.resultCount.setAttribute('aria-atomic', 'true'); this.element.appendChild(this.resultCount); // Tree this.treeContainer = document.createElement('div'); DOM.addClass(this.treeContainer, 'quick-open-tree'); this.element.appendChild(this.treeContainer); var createTree = this.options.treeCreator || (function (container, config, opts) { return new Tree(container, config, opts); }); this.tree = this._register(createTree(this.treeContainer, { dataSource: new DataSource(this), controller: new QuickOpenController({ clickBehavior: 1 /* ON_MOUSE_UP */, keyboardSupport: this.options.keyboardSupport }), renderer: (this.renderer = new Renderer(this, this.styles)), filter: new Filter(this), accessibilityProvider: new AccessibilityProvider(this) }, { twistiePixels: 11, indentPixels: 0, alwaysFocused: true, verticalScrollMode: 3 /* Visible */, horizontalScrollMode: 2 /* Hidden */, ariaLabel: nls.localize('treeAriaLabel', "Quick Picker"), keyboardSupport: this.options.keyboardSupport, preventRootFocus: false })); this.treeElement = this.tree.getHTMLElement(); // Handle Focus and Selection event this._register(this.tree.onDidChangeFocus(function (event) { _this.elementFocused(event.focus, event); })); this._register(this.tree.onDidChangeSelection(function (event) { if (event.selection && event.selection.length > 0) { var mouseEvent = event.payload && event.payload.originalEvent instanceof StandardMouseEvent ? event.payload.originalEvent : void 0; var shouldOpenInBackground = mouseEvent ? _this.shouldOpenInBackground(mouseEvent) : false; _this.elementSelected(event.selection[0], event, shouldOpenInBackground ? 2 /* OPEN_IN_BACKGROUND */ : 1 /* OPEN */); } })); this._register(DOM.addDisposableListener(this.treeContainer, DOM.EventType.KEY_DOWN, function (e) { var keyboardEvent = new StandardKeyboardEvent(e); // Only handle when in quick navigation mode if (!_this.quickNavigateConfiguration) { return; } // Support keyboard navigation in quick navigation mode if (keyboardEvent.keyCode === 18 /* DownArrow */ || keyboardEvent.keyCode === 16 /* UpArrow */ || keyboardEvent.keyCode === 12 /* PageDown */ || keyboardEvent.keyCode === 11 /* PageUp */) { DOM.EventHelper.stop(e, true); _this.navigateInTree(keyboardEvent.keyCode); } })); this._register(DOM.addDisposableListener(this.treeContainer, DOM.EventType.KEY_UP, function (e) { var keyboardEvent = new StandardKeyboardEvent(e); var keyCode = keyboardEvent.keyCode; // Only handle when in quick navigation mode if (!_this.quickNavigateConfiguration) { return; } // Select element when keys are pressed that signal it var quickNavKeys = _this.quickNavigateConfiguration.keybindings; var wasTriggerKeyPressed = keyCode === 3 /* Enter */ || quickNavKeys.some(function (k) { var _a = k.getParts(), firstPart = _a[0], chordPart = _a[1]; if (chordPart) { return false; } if (firstPart.shiftKey && keyCode === 4 /* Shift */) { if (keyboardEvent.ctrlKey || keyboardEvent.altKey || keyboardEvent.metaKey) { return false; // this is an optimistic check for the shift key being used to navigate back in quick open } return true; } if (firstPart.altKey && keyCode === 6 /* Alt */) { return true; } if (firstPart.ctrlKey && keyCode === 5 /* Ctrl */) { return true; } if (firstPart.metaKey && keyCode === 57 /* Meta */) { return true; } return false; }); if (wasTriggerKeyPressed) { var focus_2 = _this.tree.getFocus(); if (focus_2) { _this.elementSelected(focus_2, e); } } })); // Support layout if (this.layoutDimensions) { this.layout(this.layoutDimensions); } this.applyStyles(); // Allows focus to switch to next/previous entry after tab into an actionbar item this._register(DOM.addDisposableListener(this.treeContainer, DOM.EventType.KEY_DOWN, function (e) { var keyboardEvent = new StandardKeyboardEvent(e); // Only handle when not in quick navigation mode if (_this.quickNavigateConfiguration) { return; } if (keyboardEvent.keyCode === 18 /* DownArrow */ || keyboardEvent.keyCode === 16 /* UpArrow */ || keyboardEvent.keyCode === 12 /* PageDown */ || keyboardEvent.keyCode === 11 /* PageUp */) { DOM.EventHelper.stop(e, true); _this.navigateInTree(keyboardEvent.keyCode, keyboardEvent.shiftKey); _this.treeElement.focus(); } })); return this.element; }; QuickOpenWidget.prototype.style = function (styles) { this.styles = styles; this.applyStyles(); }; QuickOpenWidget.prototype.applyStyles = function () { if (this.element) { var foreground = this.styles.foreground ? this.styles.foreground.toString() : null; var background = this.styles.background ? this.styles.background.toString() : null; var borderColor = this.styles.borderColor ? this.styles.borderColor.toString() : null; var widgetShadow = this.styles.widgetShadow ? this.styles.widgetShadow.toString() : null; this.element.style.color = foreground; this.element.style.backgroundColor = background; this.element.style.borderColor = borderColor; this.element.style.borderWidth = borderColor ? '1px' : null; this.element.style.borderStyle = borderColor ? 'solid' : null; this.element.style.boxShadow = widgetShadow ? "0 5px 8px " + widgetShadow : null; } if (this.progressBar) { this.progressBar.style({ progressBarBackground: this.styles.progressBarBackground }); } if (this.inputBox) { this.inputBox.style({ inputBackground: this.styles.inputBackground, inputForeground: this.styles.inputForeground, inputBorder: this.styles.inputBorder, inputValidationInfoBackground: this.styles.inputValidationInfoBackground, inputValidationInfoForeground: this.styles.inputValidationInfoForeground, inputValidationInfoBorder: this.styles.inputValidationInfoBorder, inputValidationWarningBackground: this.styles.inputValidationWarningBackground, inputValidationWarningForeground: this.styles.inputValidationWarningForeground, inputValidationWarningBorder: this.styles.inputValidationWarningBorder, inputValidationErrorBackground: this.styles.inputValidationErrorBackground, inputValidationErrorForeground: this.styles.inputValidationErrorForeground, inputValidationErrorBorder: this.styles.inputValidationErrorBorder }); } if (this.tree && !this.options.treeCreator) { this.tree.style(this.styles); } if (this.renderer) { this.renderer.updateStyles(this.styles); } }; QuickOpenWidget.prototype.shouldOpenInBackground = function (e) { // Keyboard if (e instanceof StandardKeyboardEvent) { if (e.keyCode !== 17 /* RightArrow */) { return false; // only for right arrow } if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) { return false; // no modifiers allowed } // validate the cursor is at the end of the input and there is no selection, // and if not prevent opening in the background such as the selection can be changed var element = this.inputBox.inputElement; return element.selectionEnd === this.inputBox.value.length && element.selectionStart === element.selectionEnd; } // Mouse return e.middleButton; }; QuickOpenWidget.prototype.onType = function () { var value = this.inputBox.value; // Adjust help text as needed if present if (this.helpText) { if (value) { DOM.hide(this.helpText); } else { DOM.show(this.helpText); } } // Send to callbacks this.callbacks.onType(value); }; QuickOpenWidget.prototype.navigateInTree = function (keyCode, isShift) { var model = this.tree.getInput(); var entries = model ? model.entries : []; var oldFocus = this.tree.getFocus(); // Normal Navigation switch (keyCode) { case 18 /* DownArrow */: this.tree.focusNext(); break; case 16 /* UpArrow */: this.tree.focusPrevious(); break; case 12 /* PageDown */: this.tree.focusNextPage(); break; case 11 /* PageUp */: this.tree.focusPreviousPage(); break; case 2 /* Tab */: if (isShift) { this.tree.focusPrevious(); } else { this.tree.focusNext(); } break; } var newFocus = this.tree.getFocus(); // Support cycle-through navigation if focus did not change if (entries.length > 1 && oldFocus === newFocus) { // Up from no entry or first entry goes down to last if (keyCode === 16 /* UpArrow */ || (keyCode === 2 /* Tab */ && isShift)) { this.tree.focusLast(); } // Down from last entry goes to up to first else if (keyCode === 18 /* DownArrow */ || keyCode === 2 /* Tab */ && !isShift) { this.tree.focusFirst(); } } // Reveal newFocus = this.tree.getFocus(); if (newFocus) { this.tree.reveal(newFocus); } }; QuickOpenWidget.prototype.elementFocused = function (value, event) { if (!value || !this.isVisible()) { return; } // ARIA this.inputElement.setAttribute('aria-activedescendant', this.treeElement.getAttribute('aria-activedescendant')); var context = { event: event, keymods: this.extractKeyMods(event), quickNavigateConfiguration: this.quickNavigateConfiguration }; this.model.runner.run(value, 0 /* PREVIEW */, context); }; QuickOpenWidget.prototype.elementSelected = function (value, event, preferredMode) { var hide = true; // Trigger open of element on selection if (this.isVisible()) { var mode = preferredMode || 1 /* OPEN */; var context_1 = { event: event, keymods: this.extractKeyMods(event), quickNavigateConfiguration: this.quickNavigateConfiguration }; hide = this.model.runner.run(value, mode, context_1); } // Hide if command was run successfully if (hide) { this.hide(0 /* ELEMENT_SELECTED */); } }; QuickOpenWidget.prototype.extractKeyMods = function (event) { return { ctrlCmd: event && (event.ctrlKey || event.metaKey || (event.payload && event.payload.originalEvent && (event.payload.originalEvent.ctrlKey || event.payload.originalEvent.metaKey))), alt: event && (event.altKey || (event.payload && event.payload.originalEvent && event.payload.originalEvent.altKey)) }; }; QuickOpenWidget.prototype.show = function (param, options) { this.visible = true; this.isLoosingFocus = false; this.quickNavigateConfiguration = options ? options.quickNavigateConfiguration : void 0; // Adjust UI for quick navigate mode if (this.quickNavigateConfiguration) { DOM.hide(this.inputContainer); DOM.show(this.element); this.tree.domFocus(); } // Otherwise use normal UI else { DOM.show(this.inputContainer); DOM.show(this.element); this.inputBox.focus(); } // Adjust Help text for IE if (this.helpText) { if (this.quickNavigateConfiguration || types.isString(param)) { DOM.hide(this.helpText); } else { DOM.show(this.helpText); } } // Show based on param if (types.isString(param)) { this.doShowWithPrefix(param); } else { if (options.value) { this.restoreLastInput(options.value); } this.doShowWithInput(param, options && options.autoFocus ? options.autoFocus : {}); } // Respect selectAll option if (options && options.inputSelection && !this.quickNavigateConfiguration) { this.inputBox.select(options.inputSelection); } if (this.callbacks.onShow) { this.callbacks.onShow(); } }; QuickOpenWidget.prototype.restoreLastInput = function (lastInput) { this.inputBox.value = lastInput; this.inputBox.select(); this.callbacks.onType(lastInput); }; QuickOpenWidget.prototype.doShowWithPrefix = function (prefix) { this.inputBox.value = prefix; this.callbacks.onType(prefix); }; QuickOpenWidget.prototype.doShowWithInput = function (input, autoFocus) { this.setInput(input, autoFocus); }; QuickOpenWidget.prototype.setInputAndLayout = function (input, autoFocus) { var _this = this; this.treeContainer.style.height = this.getHeight(input) + "px"; this.tree.setInput(null).then(function () { _this.model = input; // ARIA _this.inputElement.setAttribute('aria-haspopup', String(input && input.entries && input.entries.length > 0)); return _this.tree.setInput(input); }).then(function () { // Indicate entries to tree _this.tree.layout(); var entries = input ? input.entries.filter(function (e) { return _this.isElementVisible(input, e); }) : []; _this.updateResultCount(entries.length); // Handle auto focus if (entries.length) { _this.autoFocus(input, entries, autoFocus); } }); }; QuickOpenWidget.prototype.isElementVisible = function (input, e) { if (!input.filter) { return true; } return input.filter.isVisible(e); }; QuickOpenWidget.prototype.autoFocus = function (input, entries, autoFocus) { if (autoFocus === void 0) { autoFocus = {}; } // First check for auto focus of prefix matches if (autoFocus.autoFocusPrefixMatch) { var caseSensitiveMatch = void 0; var caseInsensitiveMatch = void 0; var prefix = autoFocus.autoFocusPrefixMatch; var lowerCasePrefix = prefix.toLowerCase(); for (var i = 0; i < entries.length; i++) { var entry = entries[i]; var label = input.dataSource.getLabel(entry); if (!caseSensitiveMatch && label.indexOf(prefix) === 0) { caseSensitiveMatch = entry; } else if (!caseInsensitiveMatch && label.toLowerCase().indexOf(lowerCasePrefix) === 0) { caseInsensitiveMatch = entry; } if (caseSensitiveMatch && caseInsensitiveMatch) { break; } } var entryToFocus = caseSensitiveMatch || caseInsensitiveMatch; if (entryToFocus) { this.tree.setFocus(entryToFocus); this.tree.reveal(entryToFocus, 0.5); return; } } // Second check for auto focus of first entry if (autoFocus.autoFocusFirstEntry) { this.tree.focusFirst(); this.tree.reveal(this.tree.getFocus()); } // Third check for specific index option else if (typeof autoFocus.autoFocusIndex === 'number') { if (entries.length > autoFocus.autoFocusIndex) { this.tree.focusNth(autoFocus.autoFocusIndex); this.tree.reveal(this.tree.getFocus()); } } // Check for auto focus of second entry else if (autoFocus.autoFocusSecondEntry) { if (entries.length > 1) { this.tree.focusNth(1); } } // Finally check for auto focus of last entry else if (autoFocus.autoFocusLastEntry) { if (entries.length > 1) { this.tree.focusLast(); } } }; QuickOpenWidget.prototype.getHeight = function (input) { var _this = this; var renderer = input.renderer; if (!input) { var itemHeight = renderer.getHeight(null); return this.options.minItemsToShow ? this.options.minItemsToShow * itemHeight : 0; } var height = 0; var preferredItemsHeight; if (this.layoutDimensions && this.layoutDimensions.height) { preferredItemsHeight = (this.layoutDimensions.height - 50 /* subtract height of input field (30px) and some spacing (drop shadow) to fit */) * 0.40 /* max 40% of screen */; } if (!preferredItemsHeight || preferredItemsHeight > QuickOpenWidget.MAX_ITEMS_HEIGHT) { preferredItemsHeight = QuickOpenWidget.MAX_ITEMS_HEIGHT; } var entries = input.entries.filter(function (e) { return _this.isElementVisible(input, e); }); var maxEntries = this.options.maxItemsToShow || entries.length; for (var i = 0; i < maxEntries && i < entries.length; i++) { var entryHeight = renderer.getHeight(entries[i]); if (height + entryHeight <= preferredItemsHeight) { height += entryHeight; } else { break; } } return height; }; QuickOpenWidget.prototype.updateResultCount = function (count) { this.resultCount.textContent = nls.localize({ key: 'quickInput.visibleCount', comment: ['This tells the user how many items are shown in a list of items to select from. The items can be anything. Currently not visible, but read by screen readers.'] }, "{0} Results", count); }; QuickOpenWidget.prototype.hide = function (reason) { if (!this.isVisible()) { return; } this.visible = false; DOM.hide(this.element); this.element.blur(); // Clear input field and clear tree this.inputBox.value = ''; this.tree.setInput(null); // ARIA this.inputElement.setAttribute('aria-haspopup', 'false'); // Reset Tree Height this.treeContainer.style.height = (this.options.minItemsToShow ? this.options.minItemsToShow * 22 : 0) + "px"; // Clear any running Progress this.progressBar.stop().hide(); // Clear Focus if (this.tree.isDOMFocused()) { this.tree.domBlur(); } else if (this.inputBox.hasFocus()) { this.inputBox.blur(); } // Callbacks if (reason === 0 /* ELEMENT_SELECTED */) { this.callbacks.onOk(); } else { this.callbacks.onCancel(); } if (this.callbacks.onHide) { this.callbacks.onHide(reason); } }; QuickOpenWidget.prototype.setInput = function (input, autoFocus, ariaLabel) { if (!this.isVisible()) { return; } // If the input changes, indicate this to the tree if (!!this.getInput()) { this.onInputChanging(); } // Adapt tree height to entries and apply input this.setInputAndLayout(input, autoFocus); // Apply ARIA if (this.inputBox) { this.inputBox.setAriaLabel(ariaLabel || DEFAULT_INPUT_ARIA_LABEL); } }; QuickOpenWidget.prototype.onInputChanging = function () { var _this = this; if (this.inputChangingTimeoutHandle) { clearTimeout(this.inputChangingTimeoutHandle); this.inputChangingTimeoutHandle = null; } // when the input is changing in quick open, we indicate this as CSS class to the widget // for a certain timeout. this helps reducing some hectic UI updates when input changes quickly DOM.addClass(this.element, 'content-changing'); this.inputChangingTimeoutHandle = setTimeout(function () { DOM.removeClass(_this.element, 'content-changing'); }, 500); }; QuickOpenWidget.prototype.getInput = function () { return this.tree.getInput(); }; QuickOpenWidget.prototype.isVisible = function () { return this.visible; }; QuickOpenWidget.prototype.layout = function (dimension) { this.layoutDimensions = dimension; // Apply to quick open width (height is dynamic by number of items to show) var quickOpenWidth = Math.min(this.layoutDimensions.width * 0.62 /* golden cut */, QuickOpenWidget.MAX_WIDTH); if (this.element) { // quick open this.element.style.width = quickOpenWidth + "px"; this.element.style.marginLeft = "-" + quickOpenWidth / 2 + "px"; // input field this.inputContainer.style.width = quickOpenWidth - 12 + "px"; } }; QuickOpenWidget.prototype.gainingFocus = function () { this.isLoosingFocus = false; }; QuickOpenWidget.prototype.loosingFocus = function (e) { var _this = this; if (!this.isVisible()) { return; } var relatedTarget = e.relatedTarget; if (!this.quickNavigateConfiguration && DOM.isAncestor(relatedTarget, this.element)) { return; // user clicked somewhere into quick open widget, do not close thereby } this.isLoosingFocus = true; setTimeout(function () { if (!_this.isLoosingFocus || _this.isDisposed) { return; } var veto = _this.callbacks.onFocusLost && _this.callbacks.onFocusLost(); if (!veto) { _this.hide(1 /* FOCUS_LOST */); } }, 0); }; QuickOpenWidget.prototype.dispose = function () { _super.prototype.dispose.call(this); this.isDisposed = true; }; QuickOpenWidget.MAX_WIDTH = 600; // Max total width of quick open widget QuickOpenWidget.MAX_ITEMS_HEIGHT = 20 * 22; // Max height of item list below input field return QuickOpenWidget; }(Disposable)); export { QuickOpenWidget };