simpleFindWidget.ts 7.3 KB
Newer Older
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import 'vs/css!./simpleFindWidget';
import * as nls from 'vs/nls';
import { Widget } from 'vs/base/browser/ui/widget';
9
import { Delayer } from 'vs/base/common/async';
10 11 12 13 14 15
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import * as dom from 'vs/base/browser/dom';
import { FindInput } from 'vs/base/browser/ui/findinput/findInput';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { registerThemingParticipant, ITheme } from 'vs/platform/theme/common/themeService';
import { inputBackground, inputActiveOptionBorder, inputForeground, inputBorder, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationErrorBackground, inputValidationErrorBorder, editorWidgetBackground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
R
rebornix 已提交
16
import { SimpleButton } from './findWidget';
17 18 19 20 21 22 23 24

const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find");
const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find");
const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous match");
const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next match");
const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close");

export abstract class SimpleFindWidget extends Widget {
M
Matt Bierner 已提交
25 26 27 28 29 30 31
	private _findInput: FindInput;
	private _domNode: HTMLElement;
	private _innerDomNode: HTMLElement;
	private _isVisible: boolean;
	private _focusTracker: dom.IFocusTracker;
	private _findInputFocusTracker: dom.IFocusTracker;
	private _updateHistoryDelayer: Delayer<void>;
32

33
	constructor(
34
		@IContextViewService private readonly _contextViewService: IContextViewService
35 36
	) {
		super();
M
Matt Bierner 已提交
37

38 39 40 41 42
		this._findInput = this._register(new FindInput(null, this._contextViewService, {
			label: NLS_FIND_INPUT_LABEL,
			placeholder: NLS_FIND_INPUT_PLACEHOLDER,
		}));

43 44 45
		// Find History with update delayer
		this._updateHistoryDelayer = new Delayer<void>(500);

46 47
		this.oninput(this._findInput.domNode, (e) => {
			this.onInputChanged();
48
			this._delayedUpdateHistory();
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
		});

		this._register(this._findInput.onKeyDown((e) => {
			if (e.equals(KeyCode.Enter)) {
				this.find(false);
				e.preventDefault();
				return;
			}

			if (e.equals(KeyMod.Shift | KeyCode.Enter)) {
				this.find(true);
				e.preventDefault();
				return;
			}
		}));

65
		const prevBtn = new SimpleButton({
66 67 68 69
			label: NLS_PREVIOUS_MATCH_BTN_LABEL,
			className: 'previous',
			onTrigger: () => {
				this.find(true);
M
Matt Bierner 已提交
70
			}
71 72
		});

73
		const nextBtn = new SimpleButton({
74 75 76 77
			label: NLS_NEXT_MATCH_BTN_LABEL,
			className: 'next',
			onTrigger: () => {
				this.find(false);
M
Matt Bierner 已提交
78
			}
79 80
		});

81
		const closeBtn = new SimpleButton({
82 83 84 85
			label: NLS_CLOSE_BTN_LABEL,
			className: 'close-fw',
			onTrigger: () => {
				this.hide();
M
Matt Bierner 已提交
86
			}
87 88
		});

89 90 91 92 93 94 95 96
		this._innerDomNode = document.createElement('div');
		this._innerDomNode.classList.add('simple-find-part');
		this._innerDomNode.appendChild(this._findInput.domNode);
		this._innerDomNode.appendChild(prevBtn.domNode);
		this._innerDomNode.appendChild(nextBtn.domNode);
		this._innerDomNode.appendChild(closeBtn.domNode);

		// _domNode wraps _innerDomNode, ensuring that
97
		this._domNode = document.createElement('div');
98 99
		this._domNode.classList.add('simple-find-part-wrapper');
		this._domNode.appendChild(this._innerDomNode);
100

101
		this.onkeyup(this._innerDomNode, e => {
102 103 104 105 106 107 108
			if (e.equals(KeyCode.Escape)) {
				this.hide();
				e.preventDefault();
				return;
			}
		});

109
		this._focusTracker = this._register(dom.trackFocus(this._innerDomNode));
110 111
		this._register(this._focusTracker.onDidFocus(this.onFocusTrackerFocus.bind(this)));
		this._register(this._focusTracker.onDidBlur(this.onFocusTrackerBlur.bind(this)));
112

113
		this._findInputFocusTracker = this._register(dom.trackFocus(this._findInput.domNode));
114 115
		this._register(this._findInputFocusTracker.onDidFocus(this.onFindInputFocusTrackerFocus.bind(this)));
		this._register(this._findInputFocusTracker.onDidBlur(this.onFindInputFocusTrackerBlur.bind(this)));
116

117
		this._register(dom.addDisposableListener(this._innerDomNode, 'click', (event) => {
118 119 120 121
			event.stopPropagation();
		}));
	}

122 123 124 125 126 127
	protected abstract onInputChanged(): void;
	protected abstract find(previous: boolean): void;
	protected abstract onFocusTrackerFocus(): void;
	protected abstract onFocusTrackerBlur(): void;
	protected abstract onFindInputFocusTrackerFocus(): void;
	protected abstract onFindInputFocusTrackerBlur(): void;
C
cleidigh 已提交
128

129 130 131 132
	protected get inputValue() {
		return this._findInput.getValue();
	}

M
Matt Bierner 已提交
133 134
	public updateTheme(theme: ITheme): void {
		const inputStyles = {
135 136 137 138 139 140 141 142 143 144 145 146 147 148
			inputActiveOptionBorder: theme.getColor(inputActiveOptionBorder),
			inputBackground: theme.getColor(inputBackground),
			inputForeground: theme.getColor(inputForeground),
			inputBorder: theme.getColor(inputBorder),
			inputValidationInfoBackground: theme.getColor(inputValidationInfoBackground),
			inputValidationInfoBorder: theme.getColor(inputValidationInfoBorder),
			inputValidationWarningBackground: theme.getColor(inputValidationWarningBackground),
			inputValidationWarningBorder: theme.getColor(inputValidationWarningBorder),
			inputValidationErrorBackground: theme.getColor(inputValidationErrorBackground),
			inputValidationErrorBorder: theme.getColor(inputValidationErrorBorder)
		};
		this._findInput.style(inputStyles);
	}

M
Matt Bierner 已提交
149
	dispose() {
150 151 152 153 154 155 156
		super.dispose();

		if (this._domNode && this._domNode.parentElement) {
			this._domNode.parentElement.removeChild(this._domNode);
		}
	}

157 158 159 160
	public getDomNode(): HTMLElement {
		return this._domNode;
	}

161
	public reveal(initialInput?: string): void {
162 163 164 165
		if (initialInput) {
			this._findInput.setValue(initialInput);
		}

166
		if (this._isVisible) {
167 168 169 170 171 172 173
			this._findInput.select();
			return;
		}

		this._isVisible = true;

		setTimeout(() => {
174 175
			dom.addClass(this._innerDomNode, 'visible');
			this._innerDomNode.setAttribute('aria-hidden', 'false');
176
			setTimeout(() => {
177
				this._findInput.select();
178 179 180 181 182 183 184 185
			}, 200);
		}, 0);
	}

	public hide(): void {
		if (this._isVisible) {
			this._isVisible = false;

186 187
			dom.removeClass(this._innerDomNode, 'visible');
			this._innerDomNode.setAttribute('aria-hidden', 'true');
188 189
		}
	}
190 191 192 193 194 195 196

	protected _delayedUpdateHistory() {
		this._updateHistoryDelayer.trigger(this._updateHistory.bind(this));
	}

	protected _updateHistory() {
		if (this.inputValue) {
197
			this._findInput.inputBox.addToHistory(this._findInput.getValue());
198 199 200 201
		}
	}

	public showNextFindTerm() {
202
		this._findInput.inputBox.showNextValue();
203 204 205
	}

	public showPreviousFindTerm() {
206
		this._findInput.inputBox.showPreviousValue();
207
	}
208 209 210 211 212 213 214 215 216
}

// theming
registerThemingParticipant((theme, collector) => {
	const findWidgetBGColor = theme.getColor(editorWidgetBackground);
	if (findWidgetBGColor) {
		collector.addRule(`.monaco-workbench .simple-find-part { background-color: ${findWidgetBGColor} !important; }`);
	}

M
Matt Bierner 已提交
217
	const widgetShadowColor = theme.getColor(widgetShadow);
218 219 220 221
	if (widgetShadowColor) {
		collector.addRule(`.monaco-workbench .simple-find-part { box-shadow: 0 2px 8px ${widgetShadowColor}; }`);
	}
});