Skip to content

Commit

Permalink
Scoped context keys for editor part (#197010)
Browse files Browse the repository at this point in the history
* scoped context key service for editor part

* Refactor editor part context keys

* Remove conext keys changes for none maximize

* safer access to potential `undefined` context keys

* Fix MockScopableContextKeyService

---------

Co-authored-by: Benjamin Pasero <[email protected]>
  • Loading branch information
benibenj and bpasero authored Oct 31, 2023
1 parent 8e991e7 commit 7df50fe
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export class MockScopableContextKeyService extends MockContextKeyService {
* Don't implement this for all tests since we rarely depend on this behavior and it isn't implemented fully
*/
public override createScoped(domNote: HTMLElement): IScopedContextKeyService {
return new MockContextKeyService();
return new MockScopableContextKeyService();
}
}

Expand Down
6 changes: 1 addition & 5 deletions src/vs/workbench/browser/contextkeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ 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, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext, TitleBarStyleContext } from 'vs/workbench/common/contextkeys';
import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, TitleBarVisibleContext, TitleBarStyleContext, MultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
Expand Down Expand Up @@ -45,7 +45,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
private activeEditorGroupLast: IContextKey<boolean>;
private activeEditorGroupLocked: IContextKey<boolean>;
private multipleEditorGroupsContext: IContextKey<boolean>;
private maximizedEditorGroupContext: IContextKey<boolean>;

private editorsVisibleContext: IContextKey<boolean>;

Expand Down Expand Up @@ -139,7 +138,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
this.activeEditorGroupLast = ActiveEditorGroupLastContext.bindTo(this.contextKeyService);
this.activeEditorGroupLocked = ActiveEditorGroupLockedContext.bindTo(this.contextKeyService);
this.multipleEditorGroupsContext = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
this.maximizedEditorGroupContext = MaximizedEditorGroupContext.bindTo(this.contextKeyService);

// Working Copies
this.dirtyWorkingCopiesContext = DirtyWorkingCopiesContext.bindTo(this.contextKeyService);
Expand Down Expand Up @@ -238,8 +236,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
this._register(this.editorGroupService.onDidChangeActiveGroup(() => this.updateEditorGroupContextKeys()));
this._register(this.editorGroupService.onDidChangeGroupLocked(() => this.updateEditorGroupContextKeys()));

this._register(this.editorGroupService.onDidChangeGroupMaximized((maximized) => this.maximizedEditorGroupContext.set(maximized)));

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, disposables: this._store }));
Expand Down
8 changes: 4 additions & 4 deletions src/vs/workbench/browser/parts/editor/editor.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/
import { IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor';
import {
TextCompareEditorActiveContext, ActiveEditorPinnedContext, EditorGroupEditorsCountContext, ActiveEditorStickyContext, ActiveEditorAvailableEditorIdsContext,
MultipleEditorGroupsContext, ActiveEditorDirtyContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext,
EditorTabsVisibleContext, ActiveEditorLastInGroupContext, MaximizedEditorGroupContext
EditorPartMultipleEditorGroupsContext, ActiveEditorDirtyContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext,
EditorTabsVisibleContext, ActiveEditorLastInGroupContext, EditorPartMaximizedEditorGroupContext, MultipleEditorGroupsContext
} from 'vs/workbench/common/contextkeys';
import { SideBySideEditorInput, SideBySideEditorInputSerializer } from 'vs/workbench/common/editor/sideBySideEditorInput';
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
Expand Down Expand Up @@ -384,8 +384,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: SHOW_EDITORS_IN
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: localize('closeAll', "Close All") }, group: '5_close', order: 10 });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CLOSE_SAVED_EDITORS_COMMAND_ID, title: localize('closeAllSaved', "Close Saved") }, group: '5_close', order: 20 });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_KEEP_EDITORS_COMMAND_ID, title: localize('togglePreviewMode', "Enable Preview Editors"), toggled: ContextKeyExpr.has('config.workbench.editor.enablePreview') }, group: '7_settings', order: 10 });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('maximizeGroup', "Maximize Group") }, group: '8_group_operations', order: 5, when: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext) });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('unmaximizeGroup', "Unmaximize Group") }, group: '8_group_operations', order: 5, when: MaximizedEditorGroupContext });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('maximizeGroup', "Maximize Group") }, group: '8_group_operations', order: 5, when: ContextKeyExpr.and(EditorPartMaximizedEditorGroupContext.negate(), EditorPartMultipleEditorGroupsContext) });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('unmaximizeGroup', "Unmaximize Group") }, group: '8_group_operations', order: 5, when: EditorPartMaximizedEditorGroupContext });
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_LOCK_GROUP_COMMAND_ID, title: localize('lockGroup', "Lock Group"), toggled: ActiveEditorGroupLockedContext }, group: '8_group_operations', order: 10, when: MultipleEditorGroupsContext });

function appendEditorToolItem(primary: ICommandAction, when: ContextKeyExpression | undefined, order: number, alternative?: ICommandAction, precondition?: ContextKeyExpression | undefined): void {
Expand Down
12 changes: 6 additions & 6 deletions src/vs/workbench/browser/parts/editor/editorActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ILogService } from 'vs/platform/log/common/log';
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ActiveEditorAvailableEditorIdsContext, ActiveEditorContext, ActiveEditorGroupEmptyContext, MaximizedEditorGroupContext, MultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
import { ActiveEditorAvailableEditorIdsContext, ActiveEditorContext, ActiveEditorGroupEmptyContext, EditorPartMaximizedEditorGroupContext, EditorPartMultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
import { URI } from 'vs/base/common/uri';
import { getActiveDocument } from 'vs/base/browser/dom';

Expand Down Expand Up @@ -1073,7 +1073,7 @@ export class MaximizeGroupHideSidebarAction extends Action2 {
title: { value: localize('maximizeEditorHideSidebar', "Maximize Editor Group and Hide Side Bars"), original: 'Maximize Editor Group and Hide Side Bars' },
f1: true,
category: Categories.View,
precondition: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext)
precondition: ContextKeyExpr.and(EditorPartMaximizedEditorGroupContext.negate(), EditorPartMultipleEditorGroupsContext)
});
}

Expand All @@ -1098,7 +1098,7 @@ export class ToggleMaximizeEditorGroupAction extends Action2 {
title: { value: localize('toggleMaximizeEditorGroup', "Toggle Maximize Editor Group"), original: 'Toggle Maximize Editor Group' },
f1: true,
category: Categories.View,
precondition: ContextKeyExpr.or(MultipleEditorGroupsContext, MaximizedEditorGroupContext),
precondition: ContextKeyExpr.or(EditorPartMultipleEditorGroupsContext, EditorPartMaximizedEditorGroupContext),
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyM),
Expand All @@ -1107,16 +1107,16 @@ export class ToggleMaximizeEditorGroupAction extends Action2 {
id: MenuId.EditorTitle,
order: -10000, // towards the front
group: 'navigation',
when: MaximizedEditorGroupContext
when: EditorPartMaximizedEditorGroupContext
},
{
id: MenuId.EmptyEditorGroup,
order: -10000, // towards the front
group: 'navigation',
when: MaximizedEditorGroupContext
when: EditorPartMaximizedEditorGroupContext
}],
icon: Codicon.screenFull,
toggled: MaximizedEditorGroupContext,
toggled: EditorPartMaximizedEditorGroupContext,
});
}

Expand Down
63 changes: 53 additions & 10 deletions src/vs/workbench/browser/parts/editor/editorPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ import { findGroup } from 'vs/workbench/services/editor/common/editorGroupFinder
import { SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { EditorPartMaximizedEditorGroupContext, EditorPartMultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';

interface IEditorPartUIState {
readonly serializedGrid: ISerializedGrid;
Expand Down Expand Up @@ -140,6 +143,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {

private container: HTMLElement | undefined;

private scopedInstantiationService!: IInstantiationService;

private centeredLayoutWidget!: CenteredViewLayout;

private gridWidget!: SerializableGrid<IEditorGroupView>;
Expand All @@ -156,7 +161,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
@IConfigurationService private readonly configurationService: IConfigurationService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IHostService private readonly hostService: IHostService
@IHostService private readonly hostService: IHostService,
@IContextKeyService private readonly contextKeyService: IContextKeyService
) {
super(id, { hasTitle: false }, themeService, storageService, layoutService);

Expand Down Expand Up @@ -214,7 +220,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {

readonly sideGroup: IEditorSideGroup = {
openEditor: (editor, options) => {
const [group] = this.instantiationService.invokeFunction(accessor => findGroup(accessor, { editor, options }, SIDE_GROUP));
const [group] = this.scopedInstantiationService.invokeFunction(accessor => findGroup(accessor, { editor, options }, SIDE_GROUP));

return group.openEditor(editor, options);
}
Expand Down Expand Up @@ -624,11 +630,11 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
// Create group view
let groupView: IEditorGroupView;
if (from instanceof EditorGroupView) {
groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService,);
} else if (isSerializedEditorGroupModel(from)) {
groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService);
} else {
groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService);
}

// Keep in map
Expand Down Expand Up @@ -930,7 +936,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
createEditorDropTarget(container: unknown, delegate: IEditorDropTargetDelegate): IDisposable {
assertType(container instanceof HTMLElement);

return this.instantiationService.createInstance(EditorDropTarget, container, delegate);
return this.scopedInstantiationService.createInstance(EditorDropTarget, container, delegate);
}

//#region Part
Expand Down Expand Up @@ -967,6 +973,12 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
this.container.classList.add('content');
parent.appendChild(this.container);

// Scoped instantiation service
const scopedContextKeyService = this._register(this.contextKeyService.createScoped(this.container));
this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection(
[IContextKeyService, scopedContextKeyService]
));

// Grid control
this.doCreateGridControl(options);

Expand All @@ -977,6 +989,9 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
// Drag & Drop support
this.setupDragAndDropSupport(parent, this.container);

// Context keys
this.handleContextKeys(scopedContextKeyService);

// Signal ready
this.whenReadyPromise.complete();
this._isReady = true;
Expand All @@ -989,6 +1004,32 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
return this.container;
}

private handleContextKeys(contextKeyService: IContextKeyService): void {
const multipleEditorGroupsContext = EditorPartMultipleEditorGroupsContext.bindTo(contextKeyService);
const maximizedEditorGroupContext = EditorPartMaximizedEditorGroupContext.bindTo(contextKeyService);

const updateContextKeys = () => {
const groupCount = this.count;
if (groupCount > 1) {
multipleEditorGroupsContext.set(true);
} else {
multipleEditorGroupsContext.reset();
}

if (this.hasMaximizedGroup()) {
maximizedEditorGroupContext.set(true);
} else {
maximizedEditorGroupContext.reset();
}
};

updateContextKeys();

this._register(this.onDidAddGroup(() => updateContextKeys()));
this._register(this.onDidRemoveGroup(() => updateContextKeys()));
this._register(this.onDidChangeGroupMaximized(() => updateContextKeys()));
}

private setupDragAndDropSupport(parent: HTMLElement, container: HTMLElement): void {

// Editor drop target
Expand Down Expand Up @@ -1335,9 +1376,10 @@ export class MainEditorPart extends EditorPart {
@IConfigurationService configurationService: IConfigurationService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IHostService hostService: IHostService
@IHostService hostService: IHostService,
@IContextKeyService contextKeyService: IContextKeyService
) {
super(editorPartsView, Parts.EDITOR_PART, '', false, instantiationService, themeService, configurationService, storageService, layoutService, hostService);
super(editorPartsView, Parts.EDITOR_PART, '', false, instantiationService, themeService, configurationService, storageService, layoutService, hostService, contextKeyService);
}
}

Expand All @@ -1356,10 +1398,11 @@ export class AuxiliaryEditorPart extends EditorPart implements IAuxiliaryEditorP
@IConfigurationService configurationService: IConfigurationService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IHostService hostService: IHostService
@IHostService hostService: IHostService,
@IContextKeyService contextKeyService: IContextKeyService
) {
const id = AuxiliaryEditorPart.COUNTER++;
super(editorPartsView, `workbench.parts.auxiliaryEditor.${id}`, groupsLabel, true, instantiationService, themeService, configurationService, storageService, layoutService, hostService);
super(editorPartsView, `workbench.parts.auxiliaryEditor.${id}`, groupsLabel, true, instantiationService, themeService, configurationService, storageService, layoutService, hostService, contextKeyService);
}

protected override saveState(): void {
Expand Down
Loading

0 comments on commit 7df50fe

Please sign in to comment.