diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index a8abe040f01f273a576c5f4f1af3683a3303e533..29c0e390acbb1e3613030d8c48641e3541d2c333 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -11,7 +11,7 @@ import { IEditorQuickOpenEntry, IQuickOpenRegistry, Extensions as QuickOpenExten import { StatusbarItemDescriptor, IStatusbarRegistry, Extensions as StatusExtensions } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar'; import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; -import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext } from 'vs/workbench/common/editor'; +import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext } from 'vs/workbench/common/editor'; import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; @@ -434,11 +434,11 @@ MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroupContext, { command: { id: edi // Editor Title Context Menu MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_EDITOR_COMMAND_ID, title: nls.localize('close', "Close") }, group: '1_close', order: 10 }); -MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeOthers', "Close Others") }, group: '1_close', order: 20 }); -MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID, title: nls.localize('closeRight', "Close to the Right") }, group: '1_close', order: 30, when: ContextKeyExpr.has('config.workbench.editor.showTabs') }); +MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeOthers', "Close Others"), precondition: EditorGroupEditorsCountContext.notEqualsTo('1') }, group: '1_close', order: 20 }); +MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID, title: nls.localize('closeRight', "Close to the Right"), precondition: EditorGroupEditorsCountContext.notEqualsTo('1') }, group: '1_close', order: 30, when: ContextKeyExpr.has('config.workbench.editor.showTabs') }); MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: nls.localize('closeAllSaved', "Close Saved") }, group: '1_close', order: 40 }); MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All") }, group: '1_close', order: 50 }); -MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: nls.localize('keepOpen', "Keep Open") }, group: '3_preview', order: 10, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') }); +MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: nls.localize('keepOpen', "Keep Open"), precondition: EditorPinnedContext.toNegated() }, group: '3_preview', order: 10, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') }); MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_UP, title: nls.localize('splitUp', "Split Up") }, group: '5_split', order: 10 }); MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_DOWN, title: nls.localize('splitDown', "Split Down") }, group: '5_split', order: 20 }); MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_LEFT, title: nls.localize('splitLeft', "Split Left") }, group: '5_split', order: 30 }); diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index fd8a90600ff87a4c493e08f30bb621b9858a392f..65615a7e2d4ed372b3433b5089b5feb9b404ecb6 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup'; -import { EditorInput, EditorOptions, GroupIdentifier, ConfirmResult, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, GroupIdentifier, ConfirmResult, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor, EditorGroupEditorsCountContext } from 'vs/workbench/common/editor'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom'; @@ -214,6 +214,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { private handleGroupContextKeys(contextKeyServcie: IContextKeyService): void { const groupActiveEditorDirtyContextKey = EditorGroupActiveEditorDirtyContext.bindTo(contextKeyServcie); + const groupEditorsCountContext = EditorGroupEditorsCountContext.bindTo(contextKeyServcie); let activeEditorListener: IDisposable; @@ -229,12 +230,17 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } }; - // Track the active editor and update context key that reflects - // the dirty state of this editor + // Update group contexts based on group changes this._register(this.onDidGroupChange(e => { + + // Track the active editor and update context key that reflects + // the dirty state of this editor if (e.kind === GroupChangeKind.EDITOR_ACTIVE) { observeActiveEditor(); } + + // Group editors count context + groupEditorsCountContext.set(this.count); })); observeActiveEditor(); diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index 4d32086b4e147752a2880380b68fb9e35d7f12cb..5f2adfb21ca0a681033ca2d418f52e20a5718876 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -18,7 +18,7 @@ import { localize } from 'vs/nls'; import { createActionViewItem, fillInActionBarActions, fillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { ExecuteCommandAction, IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -33,7 +33,7 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs'; import { BreadcrumbsControl, IBreadcrumbsControlOptions } from 'vs/workbench/browser/parts/editor/breadcrumbsControl'; import { EDITOR_TITLE_HEIGHT, IEditorGroupsAccessor, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; -import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions, SideBySideEditor } from 'vs/workbench/common/editor'; +import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions, SideBySideEditor, EditorPinnedContext } from 'vs/workbench/common/editor'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { Themable } from 'vs/workbench/common/theme'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -59,6 +59,8 @@ export abstract class TitleControl extends Themable { protected editorActionsToolbar: ToolBar; private resourceContext: ResourceContextKey; + private editorPinnedContext: IContextKey; + private editorToolBarMenuDisposables: IDisposable[] = []; private contextMenu: IMenu; @@ -84,6 +86,8 @@ export abstract class TitleControl extends Themable { super(themeService); this.resourceContext = this._register(instantiationService.createInstance(ResourceContextKey)); + this.editorPinnedContext = EditorPinnedContext.bindTo(contextKeyService); + this.contextMenu = this._register(this.menuService.createMenu(MenuId.EditorTitleContext, this.contextKeyService)); this.create(parent); @@ -220,8 +224,9 @@ export abstract class TitleControl extends Themable { // Dispose previous listeners this.editorToolBarMenuDisposables = dispose(this.editorToolBarMenuDisposables); - // Update the resource context + // Update contexts this.resourceContext.set(this.group.activeEditor ? withUndefinedAsNull(toResource(this.group.activeEditor, { supportSideBySide: SideBySideEditor.MASTER })) : null); + this.editorPinnedContext.set(this.group.activeEditor ? this.group.isPinned(this.group.activeEditor) : false); // Editor actions require the editor control to be there, so we retrieve it via service const activeControl = this.group.activeControl; @@ -286,9 +291,11 @@ export abstract class TitleControl extends Themable { protected onContextMenu(editor: IEditorInput, e: Event, node: HTMLElement): void { - // Update the resource context - const currentContext = this.resourceContext.get(); + // Update contexts based on editor picked and remember previous to restore + const currentResourceContext = this.resourceContext.get(); this.resourceContext.set(withUndefinedAsNull(toResource(editor, { supportSideBySide: SideBySideEditor.MASTER }))); + const currentPinnedContext = !!this.editorPinnedContext.get(); + this.editorPinnedContext.set(this.group.isPinned(editor)); // Find target anchor let anchor: HTMLElement | { x: number, y: number } = node; @@ -309,8 +316,9 @@ export abstract class TitleControl extends Themable { getKeyBinding: (action) => this.getKeybinding(action), onHide: () => { - // restore previous context - this.resourceContext.set(currentContext || null); + // restore previous contexts + this.resourceContext.set(currentResourceContext || null); + this.editorPinnedContext.set(currentPinnedContext); // restore focus to active group this.accessor.activeGroup.focus(); diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 73b8e872b920d496fe9d2879db0aa88d0bc556ef..6915bca48904dbe54d5cf54c9bca48cd27f70a0e 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -23,7 +23,9 @@ import { coalesce } from 'vs/base/common/arrays'; export const ActiveEditorContext = new RawContextKey('activeEditor', null); export const EditorsVisibleContext = new RawContextKey('editorIsOpen', false); +export const EditorPinnedContext = new RawContextKey('editorPinned', false); export const EditorGroupActiveEditorDirtyContext = new RawContextKey('groupActiveEditorDirty', false); +export const EditorGroupEditorsCountContext = new RawContextKey('groupEditorsCount', 0); export const NoEditorsVisibleContext: ContextKeyExpr = EditorsVisibleContext.toNegated(); export const TextCompareEditorVisibleContext = new RawContextKey('textCompareEditorVisible', false); export const TextCompareEditorActiveContext = new RawContextKey('textCompareEditorActive', false);