Skip to content

Commit

Permalink
Cleanup editor group context keys (#212955)
Browse files Browse the repository at this point in the history
* cleanup editor group context keys

* Update src/vs/workbench/browser/parts/editor/editorPart.ts

Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>

* context key on parts

* Update global context keys

* remove scoped keys on group removal

* cleanup

---------

Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
  • Loading branch information
benibenj and bpasero authored May 20, 2024
1 parent 5a51456 commit aa31bfc
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 142 deletions.
119 changes: 1 addition & 118 deletions src/vs/workbench/browser/contextkeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,29 @@ import { Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, MainEditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, TitleBarVisibleContext, TitleBarStyleContext, MultipleEditorGroupsContext, IsAuxiliaryWindowFocusedContext, ActiveCompareEditorCanSwapContext } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext } from 'vs/workbench/common/contextkeys';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
import { getVirtualWorkspaceScheme } from 'vs/platform/workspace/common/virtualWorkspace';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { isNative } from 'vs/base/common/platform';
import { IEditorResolverService } from 'vs/workbench/services/editor/common/editorResolverService';
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
import { IProductService } from 'vs/platform/product/common/productService';
import { FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files';
import { getTitleBarStyle } from 'vs/platform/window/common/window';
import { mainWindow } from 'vs/base/browser/window';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { isFullscreen, onDidChangeFullscreen } from 'vs/base/browser/browser';
import { Schemas } from 'vs/base/common/network';

export class WorkbenchContextKeysHandler extends Disposable {
private inputFocusedContext: IContextKey<boolean>;

private dirtyWorkingCopiesContext: IContextKey<boolean>;

private activeEditorContext: IContextKey<string | null>;
private activeEditorCanRevert: IContextKey<boolean>;
private activeEditorCanSplitInGroup: IContextKey<boolean>;
private activeEditorAvailableEditorIds: IContextKey<string>;

private activeEditorIsReadonly: IContextKey<boolean>;
private activeCompareEditorCanSwap: IContextKey<boolean>;
private activeEditorCanToggleReadonly: IContextKey<boolean>;

private activeEditorGroupEmpty: IContextKey<boolean>;
private activeEditorGroupIndex: IContextKey<number>;
private activeEditorGroupLast: IContextKey<boolean>;
private activeEditorGroupLocked: IContextKey<boolean>;
private multipleEditorGroupsContext: IContextKey<boolean>;

private editorsVisibleContext: IContextKey<boolean>;

private textCompareEditorVisibleContext: IContextKey<boolean>;
private textCompareEditorActiveContext: IContextKey<boolean>;

private sideBySideEditorActiveContext: IContextKey<boolean>;
private splitEditorsVerticallyContext: IContextKey<boolean>;

private workbenchStateContext: IContextKey<string>;
Expand Down Expand Up @@ -90,13 +63,10 @@ export class WorkbenchContextKeysHandler extends Disposable {
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IProductService private readonly productService: IProductService,
@IEditorService private readonly editorService: IEditorService,
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@IPaneCompositePartService private readonly paneCompositeService: IPaneCompositePartService,
@IWorkingCopyService private readonly workingCopyService: IWorkingCopyService,
@IFileService private readonly fileService: IFileService
) {
super();

Expand Down Expand Up @@ -128,24 +98,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
ProductQualityContext.bindTo(this.contextKeyService).set(this.productService.quality || '');
EmbedderIdentifierContext.bindTo(this.contextKeyService).set(productService.embedderIdentifier);

// Editors
this.activeEditorContext = ActiveEditorContext.bindTo(this.contextKeyService);
this.activeEditorIsReadonly = ActiveEditorReadonlyContext.bindTo(this.contextKeyService);
this.activeCompareEditorCanSwap = ActiveCompareEditorCanSwapContext.bindTo(this.contextKeyService);
this.activeEditorCanToggleReadonly = ActiveEditorCanToggleReadonlyContext.bindTo(this.contextKeyService);
this.activeEditorCanRevert = ActiveEditorCanRevertContext.bindTo(this.contextKeyService);
this.activeEditorCanSplitInGroup = ActiveEditorCanSplitInGroupContext.bindTo(this.contextKeyService);
this.activeEditorAvailableEditorIds = ActiveEditorAvailableEditorIdsContext.bindTo(this.contextKeyService);
this.editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
this.textCompareEditorVisibleContext = TextCompareEditorVisibleContext.bindTo(this.contextKeyService);
this.textCompareEditorActiveContext = TextCompareEditorActiveContext.bindTo(this.contextKeyService);
this.sideBySideEditorActiveContext = SideBySideEditorActiveContext.bindTo(this.contextKeyService);
this.activeEditorGroupEmpty = ActiveEditorGroupEmptyContext.bindTo(this.contextKeyService);
this.activeEditorGroupIndex = ActiveEditorGroupIndexContext.bindTo(this.contextKeyService);
this.activeEditorGroupLast = ActiveEditorGroupLastContext.bindTo(this.contextKeyService);
this.activeEditorGroupLocked = ActiveEditorGroupLockedContext.bindTo(this.contextKeyService);
this.multipleEditorGroupsContext = MultipleEditorGroupsContext.bindTo(this.contextKeyService);

// Working Copies
this.dirtyWorkingCopiesContext = DirtyWorkingCopiesContext.bindTo(this.contextKeyService);
this.dirtyWorkingCopiesContext.set(this.workingCopyService.hasDirty);
Expand Down Expand Up @@ -231,19 +183,8 @@ export class WorkbenchContextKeysHandler extends Disposable {
private registerListeners(): void {
this.editorGroupService.whenReady.then(() => {
this.updateEditorAreaContextKeys();
this.updateEditorContextKeys();
});

this._register(this.editorService.onDidActiveEditorChange(() => this.updateEditorContextKeys()));
this._register(this.editorService.onDidVisibleEditorsChange(() => this.updateEditorContextKeys()));

this._register(this.editorGroupService.onDidAddGroup(() => this.updateEditorContextKeys()));
this._register(this.editorGroupService.onDidRemoveGroup(() => this.updateEditorContextKeys()));
this._register(this.editorGroupService.onDidChangeGroupIndex(() => this.updateEditorContextKeys()));

this._register(this.editorGroupService.onDidChangeActiveGroup(() => this.updateEditorGroupContextKeys()));
this._register(this.editorGroupService.onDidChangeGroupLocked(() => this.updateEditorGroupContextKeys()));

this._register(this.editorGroupService.onDidChangeEditorPartOptions(() => this.updateEditorAreaContextKeys()));

this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => disposables.add(addDisposableListener(window, EventType.FOCUS_IN, () => this.updateInputContextKeys(window.document), true)), { window: mainWindow, disposables: this._store }));
Expand Down Expand Up @@ -290,64 +231,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
this.editorTabsVisibleContext.set(this.editorGroupService.partOptions.showTabs === 'multiple');
}

private updateEditorContextKeys(): void {
const activeEditorPane = this.editorService.activeEditorPane;
const visibleEditorPanes = this.editorService.visibleEditorPanes;

this.textCompareEditorActiveContext.set(activeEditorPane?.getId() === TEXT_DIFF_EDITOR_ID);
this.textCompareEditorVisibleContext.set(visibleEditorPanes.some(editorPane => editorPane.getId() === TEXT_DIFF_EDITOR_ID));

this.sideBySideEditorActiveContext.set(activeEditorPane?.getId() === SIDE_BY_SIDE_EDITOR_ID);

if (visibleEditorPanes.length > 0) {
this.editorsVisibleContext.set(true);
} else {
this.editorsVisibleContext.reset();
}

if (!this.editorService.activeEditor) {
this.activeEditorGroupEmpty.set(true);
} else {
this.activeEditorGroupEmpty.reset();
}

this.updateEditorGroupContextKeys();

if (activeEditorPane) {
this.activeEditorContext.set(activeEditorPane.getId());
this.activeEditorCanRevert.set(!activeEditorPane.input.hasCapability(EditorInputCapabilities.Untitled));
this.activeEditorCanSplitInGroup.set(activeEditorPane.input.hasCapability(EditorInputCapabilities.CanSplitInGroup));
applyAvailableEditorIds(this.activeEditorAvailableEditorIds, activeEditorPane.input, this.editorResolverService);
this.activeEditorIsReadonly.set(!!activeEditorPane.input.isReadonly());
const primaryEditorResource = EditorResourceAccessor.getOriginalUri(activeEditorPane.input, { supportSideBySide: SideBySideEditor.PRIMARY });
const secondaryEditorResource = EditorResourceAccessor.getOriginalUri(activeEditorPane.input, { supportSideBySide: SideBySideEditor.SECONDARY });
this.activeCompareEditorCanSwap.set(activeEditorPane.input instanceof DiffEditorInput && !activeEditorPane.input.original.isReadonly() && !!primaryEditorResource && (this.fileService.hasProvider(primaryEditorResource) || primaryEditorResource.scheme === Schemas.untitled) && !!secondaryEditorResource && (this.fileService.hasProvider(secondaryEditorResource) || secondaryEditorResource.scheme === Schemas.untitled));
this.activeEditorCanToggleReadonly.set(!!primaryEditorResource && this.fileService.hasProvider(primaryEditorResource) && !this.fileService.hasCapability(primaryEditorResource, FileSystemProviderCapabilities.Readonly));
} else {
this.activeEditorContext.reset();
this.activeEditorIsReadonly.reset();
this.activeCompareEditorCanSwap.reset();
this.activeEditorCanToggleReadonly.reset();
this.activeEditorCanRevert.reset();
this.activeEditorCanSplitInGroup.reset();
this.activeEditorAvailableEditorIds.reset();
}
}

private updateEditorGroupContextKeys(): void {
const groupCount = this.editorGroupService.count;
if (groupCount > 1) {
this.multipleEditorGroupsContext.set(true);
} else {
this.multipleEditorGroupsContext.reset();
}

const activeGroup = this.editorGroupService.activeGroup;
this.activeEditorGroupIndex.set(activeGroup.index + 1); // not zero-indexed
this.activeEditorGroupLast.set(activeGroup.index === groupCount - 1);
this.activeEditorGroupLocked.set(activeGroup.isLocked);
}

private updateInputContextKeys(ownerDocument: Document): void {

function activeElementIsInput(): boolean {
Expand Down
3 changes: 3 additions & 0 deletions src/vs/workbench/browser/parts/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { IWindowsConfiguration } from 'vs/platform/window/common/window';
import { BooleanVerifier, EnumVerifier, NumberVerifier, ObjectVerifier, SetVerifier, verifyObject } from 'vs/base/common/verifier';
import { IAuxiliaryWindowOpenOptions } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService';
import { ContextKeyValue, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey';

export interface IEditorPartCreationOptions {
readonly restorePreviousState: boolean;
Expand Down Expand Up @@ -187,6 +188,8 @@ export interface IEditorPartsView {
readonly count: number;

createAuxiliaryEditorPart(options?: IAuxiliaryWindowOpenOptions): Promise<IAuxiliaryEditorPart>;

bind<T extends ContextKeyValue>(contextKey: RawContextKey<T>, group: IEditorGroupView): IContextKey<T>;
}

/**
Expand Down
43 changes: 22 additions & 21 deletions src/vs/workbench/browser/parts/editor/editorGroupView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,27 +248,28 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}

private handleGroupContextKeys(): void {
const groupActiveEditorDirtyContext = ActiveEditorDirtyContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorPinnedContext = ActiveEditorPinnedContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorFirstContext = ActiveEditorFirstInGroupContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorLastContext = ActiveEditorLastInGroupContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorStickyContext = ActiveEditorStickyContext.bindTo(this.scopedContextKeyService);
const groupEditorsCountContext = EditorGroupEditorsCountContext.bindTo(this.scopedContextKeyService);
const groupLockedContext = ActiveEditorGroupLockedContext.bindTo(this.scopedContextKeyService);
const multipleEditorsSelectedContext = MultipleEditorsSelectedContext.bindTo(this.contextKeyService);
const twoEditorsSelectedContext = TwoEditorsSelectedContext.bindTo(this.contextKeyService);

const groupActiveEditorContext = ActiveEditorContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorIsReadonly = ActiveEditorReadonlyContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorCanRevert = ActiveEditorCanRevertContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorCanToggleReadonly = ActiveEditorCanToggleReadonlyContext.bindTo(this.scopedContextKeyService);
const groupActiveCompareEditorCanSwap = ActiveCompareEditorCanSwapContext.bindTo(this.scopedContextKeyService);
const groupTextCompareEditorVisibleContext = TextCompareEditorVisibleContext.bindTo(this.scopedContextKeyService);
const groupTextCompareEditorActiveContext = TextCompareEditorActiveContext.bindTo(this.scopedContextKeyService);

const groupActiveEditorAvailableEditorIds = ActiveEditorAvailableEditorIdsContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorCanSplitInGroupContext = ActiveEditorCanSplitInGroupContext.bindTo(this.scopedContextKeyService);
const sideBySideEditorContext = SideBySideEditorActiveContext.bindTo(this.scopedContextKeyService);
const groupActiveEditorDirtyContext = this.editorPartsView.bind(ActiveEditorDirtyContext, this);
const groupActiveEditorPinnedContext = this.editorPartsView.bind(ActiveEditorPinnedContext, this);
const groupActiveEditorFirstContext = this.editorPartsView.bind(ActiveEditorFirstInGroupContext, this);
const groupActiveEditorLastContext = this.editorPartsView.bind(ActiveEditorLastInGroupContext, this);
const groupActiveEditorStickyContext = this.editorPartsView.bind(ActiveEditorStickyContext, this);
const groupEditorsCountContext = this.editorPartsView.bind(EditorGroupEditorsCountContext, this);
const groupLockedContext = this.editorPartsView.bind(ActiveEditorGroupLockedContext, this);

const multipleEditorsSelectedContext = MultipleEditorsSelectedContext.bindTo(this.scopedContextKeyService);
const twoEditorsSelectedContext = TwoEditorsSelectedContext.bindTo(this.scopedContextKeyService);

const groupActiveEditorContext = this.editorPartsView.bind(ActiveEditorContext, this);
const groupActiveEditorIsReadonly = this.editorPartsView.bind(ActiveEditorReadonlyContext, this);
const groupActiveEditorCanRevert = this.editorPartsView.bind(ActiveEditorCanRevertContext, this);
const groupActiveEditorCanToggleReadonly = this.editorPartsView.bind(ActiveEditorCanToggleReadonlyContext, this);
const groupActiveCompareEditorCanSwap = this.editorPartsView.bind(ActiveCompareEditorCanSwapContext, this);
const groupTextCompareEditorVisibleContext = this.editorPartsView.bind(TextCompareEditorVisibleContext, this);
const groupTextCompareEditorActiveContext = this.editorPartsView.bind(TextCompareEditorActiveContext, this);

const groupActiveEditorAvailableEditorIds = this.editorPartsView.bind(ActiveEditorAvailableEditorIdsContext, this);
const groupActiveEditorCanSplitInGroupContext = this.editorPartsView.bind(ActiveEditorCanSplitInGroupContext, this);
const sideBySideEditorContext = this.editorPartsView.bind(SideBySideEditorActiveContext, this);

const activeEditorListener = this._register(new MutableDisposable());

Expand Down
Loading

0 comments on commit aa31bfc

Please sign in to comment.