Path: blob/main/src/vs/workbench/contrib/browserView/electron-browser/browserFindWidget.ts
5232 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { SimpleFindWidget } from '../../codeEditor/browser/find/simpleFindWidget.js';6import { IContextViewService } from '../../../../platform/contextview/browser/contextView.js';7import { IContextKey, IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';8import { IHoverService } from '../../../../platform/hover/browser/hover.js';9import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';10import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';11import { IAccessibilityService } from '../../../../platform/accessibility/common/accessibility.js';12import { IBrowserViewModel } from '../common/browserView.js';13import { localize } from '../../../../nls.js';14import { DisposableStore } from '../../../../base/common/lifecycle.js';1516export const CONTEXT_BROWSER_FIND_WIDGET_VISIBLE = new RawContextKey<boolean>('browserFindWidgetVisible', false, localize('browser.findWidgetVisible', "Whether the browser find widget is visible"));17export const CONTEXT_BROWSER_FIND_WIDGET_FOCUSED = new RawContextKey<boolean>('browserFindWidgetFocused', false, localize('browser.findWidgetFocused', "Whether the browser find widget is focused"));1819/**20* Find widget for the integrated browser view.21* Uses the SimpleFindWidget base class and communicates with the browser view model22* to perform find operations in the rendered web page.23*/24export class BrowserFindWidget extends SimpleFindWidget {25private _model: IBrowserViewModel | undefined;26private readonly _modelDisposables = this._register(new DisposableStore());27private readonly _findWidgetVisible: IContextKey<boolean>;28private readonly _findWidgetFocused: IContextKey<boolean>;29private _lastFindResult: { resultIndex: number; resultCount: number } | undefined;30private _hasFoundMatch = false;3132constructor(33private readonly container: HTMLElement,34@IContextViewService contextViewService: IContextViewService,35@IContextKeyService contextKeyService: IContextKeyService,36@IHoverService hoverService: IHoverService,37@IKeybindingService keybindingService: IKeybindingService,38@IConfigurationService configurationService: IConfigurationService,39@IAccessibilityService accessibilityService: IAccessibilityService40) {41super({42showCommonFindToggles: true,43checkImeCompletionState: true,44showResultCount: true,45enableSash: true,46initialWidth: 350,47previousMatchActionId: 'workbench.action.browser.findPrevious',48nextMatchActionId: 'workbench.action.browser.findNext',49closeWidgetActionId: 'workbench.action.browser.hideFind'50}, contextViewService, contextKeyService, hoverService, keybindingService, configurationService, accessibilityService);5152this._findWidgetVisible = CONTEXT_BROWSER_FIND_WIDGET_VISIBLE.bindTo(contextKeyService);53this._findWidgetFocused = CONTEXT_BROWSER_FIND_WIDGET_FOCUSED.bindTo(contextKeyService);5455container.appendChild(this.getDomNode());56}5758/**59* Set the browser view model to use for find operations.60* This should be called whenever the editor input changes.61*/62setModel(model: IBrowserViewModel | undefined): void {63this._modelDisposables.clear();64this._model = model;65this._lastFindResult = undefined;66this._hasFoundMatch = false;6768if (model) {69this._modelDisposables.add(model.onDidFindInPage(result => {70this._lastFindResult = {71resultIndex: result.activeMatchOrdinal - 1, // Convert to 0-based index72resultCount: result.matches73};74this._hasFoundMatch = result.matches > 0;75this.updateButtons(this._hasFoundMatch);76this.updateResultCount();77}));7879this._modelDisposables.add(model.onWillDispose(() => {80this.setModel(undefined);81}));82}83}8485override reveal(initialInput?: string): void {86const wasVisible = this.isVisible();87super.reveal(initialInput);88this._findWidgetVisible.set(true);89this.container.classList.toggle('find-visible', true);9091// Focus the find input92this.focusFindBox();9394// If there's existing input and the widget wasn't already visible, trigger a search95if (this.inputValue && !wasVisible) {96this._onInputChanged();97}98}99100override hide(): void {101super.hide(false);102this._findWidgetVisible.reset();103this.container.classList.toggle('find-visible', false);104105// Stop find and clear highlights in the browser view106this._model?.stopFindInPage(true);107this._lastFindResult = undefined;108this._hasFoundMatch = false;109}110111find(previous: boolean): void {112const value = this.inputValue;113if (value && this._model) {114this._model.findInPage(value, {115forward: !previous,116recompute: false,117matchCase: this._getCaseSensitiveValue()118});119}120}121122findFirst(): void {123const value = this.inputValue;124if (value && this._model) {125this._model.findInPage(value, {126forward: true,127recompute: true,128matchCase: this._getCaseSensitiveValue()129});130}131}132133clear(): void {134if (this._model) {135this._model.stopFindInPage(false);136this._lastFindResult = undefined;137this._hasFoundMatch = false;138}139}140141protected _onInputChanged(): boolean {142if (this.inputValue) {143this.findFirst();144} else if (this._model) {145this.clear();146}147return false;148}149150protected async _getResultCount(): Promise<{ resultIndex: number; resultCount: number } | undefined> {151return this._lastFindResult;152}153154protected _onFocusTrackerFocus(): void {155this._findWidgetFocused.set(true);156}157158protected _onFocusTrackerBlur(): void {159this._findWidgetFocused.reset();160}161162protected _onFindInputFocusTrackerFocus(): void {163// No-op164}165166protected _onFindInputFocusTrackerBlur(): void {167// No-op168}169}170171172