Path: blob/main/src/vs/platform/history/browser/contextScopedHistoryWidget.ts
3296 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 { IHistoryNavigationWidget } from '../../../base/browser/history.js';6import { IContextViewProvider } from '../../../base/browser/ui/contextview/contextview.js';7import { FindInput, IFindInputOptions } from '../../../base/browser/ui/findinput/findInput.js';8import { IReplaceInputOptions, ReplaceInput } from '../../../base/browser/ui/findinput/replaceInput.js';9import { HistoryInputBox, IHistoryInputOptions } from '../../../base/browser/ui/inputbox/inputBox.js';10import { KeyCode, KeyMod } from '../../../base/common/keyCodes.js';11import { ContextKeyExpr, IContextKey, IContextKeyService, RawContextKey } from '../../contextkey/common/contextkey.js';12import { KeybindingsRegistry, KeybindingWeight } from '../../keybinding/common/keybindingsRegistry.js';13import { localize } from '../../../nls.js';14import { DisposableStore, IDisposable, toDisposable } from '../../../base/common/lifecycle.js';15import { isActiveElement } from '../../../base/browser/dom.js';1617export const historyNavigationVisible = new RawContextKey<boolean>('suggestWidgetVisible', false, localize('suggestWidgetVisible', "Whether suggestion are visible"));1819const HistoryNavigationWidgetFocusContext = 'historyNavigationWidgetFocus';20const HistoryNavigationForwardsEnablementContext = 'historyNavigationForwardsEnabled';21const HistoryNavigationBackwardsEnablementContext = 'historyNavigationBackwardsEnabled';2223export interface IHistoryNavigationContext extends IDisposable {24historyNavigationForwardsEnablement: IContextKey<boolean>;25historyNavigationBackwardsEnablement: IContextKey<boolean>;26}2728let lastFocusedWidget: IHistoryNavigationWidget | undefined = undefined;29const widgets: IHistoryNavigationWidget[] = [];3031export function registerAndCreateHistoryNavigationContext(scopedContextKeyService: IContextKeyService, widget: IHistoryNavigationWidget): IHistoryNavigationContext {32if (widgets.includes(widget)) {33throw new Error('Cannot register the same widget multiple times');34}3536widgets.push(widget);37const disposableStore = new DisposableStore();38const historyNavigationWidgetFocus = new RawContextKey<boolean>(HistoryNavigationWidgetFocusContext, false).bindTo(scopedContextKeyService);39const historyNavigationForwardsEnablement = new RawContextKey<boolean>(HistoryNavigationForwardsEnablementContext, true).bindTo(scopedContextKeyService);40const historyNavigationBackwardsEnablement = new RawContextKey<boolean>(HistoryNavigationBackwardsEnablementContext, true).bindTo(scopedContextKeyService);4142const onDidFocus = () => {43historyNavigationWidgetFocus.set(true);44lastFocusedWidget = widget;45};4647const onDidBlur = () => {48historyNavigationWidgetFocus.set(false);49if (lastFocusedWidget === widget) {50lastFocusedWidget = undefined;51}52};5354// Check for currently being focused55if (isActiveElement(widget.element)) {56onDidFocus();57}5859disposableStore.add(widget.onDidFocus(() => onDidFocus()));60disposableStore.add(widget.onDidBlur(() => onDidBlur()));61disposableStore.add(toDisposable(() => {62widgets.splice(widgets.indexOf(widget), 1);63onDidBlur();64}));6566return {67historyNavigationForwardsEnablement,68historyNavigationBackwardsEnablement,69dispose() {70disposableStore.dispose();71}72};73}7475export class ContextScopedHistoryInputBox extends HistoryInputBox {7677constructor(container: HTMLElement, contextViewProvider: IContextViewProvider | undefined, options: IHistoryInputOptions,78@IContextKeyService contextKeyService: IContextKeyService79) {80super(container, contextViewProvider, options);81const scopedContextKeyService = this._register(contextKeyService.createScoped(this.element));82this._register(registerAndCreateHistoryNavigationContext(scopedContextKeyService, this));83}8485}8687export class ContextScopedFindInput extends FindInput {8889constructor(container: HTMLElement | null, contextViewProvider: IContextViewProvider, options: IFindInputOptions,90@IContextKeyService contextKeyService: IContextKeyService91) {92super(container, contextViewProvider, options);93const scopedContextKeyService = this._register(contextKeyService.createScoped(this.inputBox.element));94this._register(registerAndCreateHistoryNavigationContext(scopedContextKeyService, this.inputBox));95}96}9798export class ContextScopedReplaceInput extends ReplaceInput {99100constructor(container: HTMLElement | null, contextViewProvider: IContextViewProvider | undefined, options: IReplaceInputOptions,101@IContextKeyService contextKeyService: IContextKeyService, showReplaceOptions: boolean = false102) {103super(container, contextViewProvider, showReplaceOptions, options);104const scopedContextKeyService = this._register(contextKeyService.createScoped(this.inputBox.element));105this._register(registerAndCreateHistoryNavigationContext(scopedContextKeyService, this.inputBox));106}107108}109110KeybindingsRegistry.registerCommandAndKeybindingRule({111id: 'history.showPrevious',112weight: KeybindingWeight.WorkbenchContrib,113when: ContextKeyExpr.and(114ContextKeyExpr.has(HistoryNavigationWidgetFocusContext),115ContextKeyExpr.equals(HistoryNavigationBackwardsEnablementContext, true),116ContextKeyExpr.not('isComposing'),117historyNavigationVisible.isEqualTo(false),118),119primary: KeyCode.UpArrow,120secondary: [KeyMod.Alt | KeyCode.UpArrow],121handler: (accessor) => {122lastFocusedWidget?.showPreviousValue();123}124});125126KeybindingsRegistry.registerCommandAndKeybindingRule({127id: 'history.showNext',128weight: KeybindingWeight.WorkbenchContrib,129when: ContextKeyExpr.and(130ContextKeyExpr.has(HistoryNavigationWidgetFocusContext),131ContextKeyExpr.equals(HistoryNavigationForwardsEnablementContext, true),132ContextKeyExpr.not('isComposing'),133historyNavigationVisible.isEqualTo(false),134),135primary: KeyCode.DownArrow,136secondary: [KeyMod.Alt | KeyCode.DownArrow],137handler: (accessor) => {138lastFocusedWidget?.showNextValue();139}140});141142143