diff --git a/extensions/git/package.json b/extensions/git/package.json index 08ef635454d..ecca4d76e17 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -11,7 +11,7 @@ "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", "enabledApiProposals": [ "diffCommand", - "contribMergeEditorToolbar", + "contribEditorContentMenu", "contribViewsWelcome", "editSessionIdentityProvider", "scmActionButton", @@ -1514,11 +1514,6 @@ "group": "navigation", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && !isInDiffEditor && !isMergeEditor && resourceScheme == file && scmActiveResourceHasChanges" }, - { - "command": "git.openMergeEditor", - "group": "navigation@-10", - "when": "config.git.enabled && !git.missing && !isInDiffEditor && !isMergeEditor && resource in git.mergeChanges" - }, { "command": "git.commitMessageAccept", "group": "navigation", @@ -1562,10 +1557,15 @@ "when": "isInDiffRightEditor && !isInEmbeddedDiffEditor && config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/" } ], - "merge/toolbar": [ + "editor/content": [ { "command": "git.acceptMerge", - "when": "isMergeEditor && mergeEditorBaseUri =~ /^(git|file):/ && mergeEditorResultUri in git.mergeChanges" + "when": "isMergeResultEditor && mergeEditorBaseUri =~ /^(git|file):/ && mergeEditorResultUri in git.mergeChanges" + }, + { + "command": "git.openMergeEditor", + "group": "navigation@-10", + "when": "config.git.enabled && !git.missing && !isInDiffEditor && !isMergeEditor && resource in git.mergeChanges" } ], "scm/change/title": [ diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 3baa6e7a735..e9fca5f288b 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -57,6 +57,7 @@ export class MenuId { static readonly DebugToolBarStop = new MenuId('DebugToolBarStop'); static readonly EditorContext = new MenuId('EditorContext'); static readonly SimpleEditorContext = new MenuId('SimpleEditorContext'); + static readonly EditorContent = new MenuId('EditorContent'); static readonly EditorContextCopy = new MenuId('EditorContextCopy'); static readonly EditorContextPeek = new MenuId('EditorContextPeek'); static readonly EditorContextShare = new MenuId('EditorContextShare'); @@ -165,7 +166,6 @@ export class MenuId { static readonly WebviewContext = new MenuId('WebviewContext'); static readonly InlineCompletionsActions = new MenuId('InlineCompletionsActions'); static readonly NewFile = new MenuId('NewFile'); - static readonly MergeToolbar = new MenuId('MergeToolbar'); static readonly MergeInput1Toolbar = new MenuId('MergeToolbar1Toolbar'); static readonly MergeInput2Toolbar = new MenuId('MergeToolbar2Toolbar'); diff --git a/src/vs/workbench/browser/codeeditor.ts b/src/vs/workbench/browser/codeeditor.ts index 6be99930f65..3c4353efa91 100644 --- a/src/vs/workbench/browser/codeeditor.ts +++ b/src/vs/workbench/browser/codeeditor.ts @@ -26,6 +26,10 @@ import { CursorChangeReason, ICursorPositionChangedEvent } from 'vs/editor/commo import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { TrackedRangeStickiness, IModelDecorationsChangeAccessor } from 'vs/editor/common/model'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { IMenuService, MenuId } from 'vs/platform/actions/common/actions'; +import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IAction } from 'vs/base/common/actions'; export interface IRangeHighlightDecoration { resource: URI; @@ -212,6 +216,44 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget { } } +export class FloatingClickMenu extends Disposable implements IEditorContribution { + + static readonly ID = 'editor.contrib.floatingClickMenu'; + + constructor( + editor: ICodeEditor, + @IInstantiationService instantiationService: IInstantiationService, + @IMenuService menuService: IMenuService, + @IContextKeyService contextKeyService: IContextKeyService + ) { + super(); + + const menu = menuService.createMenu(MenuId.EditorContent, contextKeyService); + const menuDisposables = new DisposableStore(); + const renderMenuAsFloatingClickBtn = () => { + menuDisposables.clear(); + if (!editor.hasModel() || editor.getOption(EditorOption.inDiffEditor)) { + return; + } + const actions: IAction[] = []; + createAndFillInActionBarActions(menu, { renderShortTitle: true, shouldForwardArgs: true }, actions); + if (actions.length === 0) { + return; + } + // todo@jrieken find a way to handle N actions, like showing a context menu + const [first] = actions; + const widget = instantiationService.createInstance(FloatingClickWidget, editor, first.label, first.id); + menuDisposables.add(widget); + menuDisposables.add(widget.onClick(() => first.run(editor.getModel().uri))); + widget.render(); + }; + this._store.add(menu); + this._store.add(menuDisposables); + this._store.add(menu.onDidChange(renderMenuAsFloatingClickBtn)); + renderMenuAsFloatingClickBtn(); + } +} + export class OpenWorkspaceButtonContribution extends Disposable implements IEditorContribution { static get(editor: ICodeEditor): OpenWorkspaceButtonContribution | null { diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 399f58c4f6a..18a0cbd3b36 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -54,7 +54,7 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; import { isMacintosh } from 'vs/base/common/platform'; import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; -import { OpenWorkspaceButtonContribution } from 'vs/workbench/browser/codeeditor'; +import { FloatingClickMenu, OpenWorkspaceButtonContribution } from 'vs/workbench/browser/codeeditor'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { EditorAutoSave } from 'vs/workbench/browser/parts/editor/editorAutoSave'; @@ -127,6 +127,7 @@ Registry.as(WorkbenchExtensions.Workbench).regi Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(UntitledTextEditorWorkingCopyEditorHandler, LifecyclePhase.Ready); Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DynamicEditorResolverConfigurations, LifecyclePhase.Ready); +registerEditorContribution(FloatingClickMenu.ID, FloatingClickMenu); registerEditorContribution(OpenWorkspaceButtonContribution.ID, OpenWorkspaceButtonContribution); //#endregion diff --git a/src/vs/workbench/contrib/mergeEditor/browser/view/editors/resultCodeEditorView.ts b/src/vs/workbench/contrib/mergeEditor/browser/view/editors/resultCodeEditorView.ts index 31614f7069c..f092cc5bad7 100644 --- a/src/vs/workbench/contrib/mergeEditor/browser/view/editors/resultCodeEditorView.ts +++ b/src/vs/workbench/contrib/mergeEditor/browser/view/editors/resultCodeEditorView.ts @@ -5,15 +5,18 @@ import { CompareResult } from 'vs/base/common/arrays'; import { BugIndicatingError } from 'vs/base/common/errors'; +import { toDisposable } from 'vs/base/common/lifecycle'; import { autorun, derived } from 'vs/base/common/observable'; import { IModelDeltaDecoration, MinimapPosition, OverviewRulerLane } from 'vs/editor/common/model'; import { localize } from 'vs/nls'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { MergeMarkersController } from 'vs/workbench/contrib/mergeEditor/browser/mergeMarkers/mergeMarkersController'; import { LineRange } from 'vs/workbench/contrib/mergeEditor/browser/model/lineRange'; import { applyObservableDecorations, join } from 'vs/workbench/contrib/mergeEditor/browser/utils'; import { handledConflictMinimapOverViewRulerColor, unhandledConflictMinimapOverViewRulerColor } from 'vs/workbench/contrib/mergeEditor/browser/view/colors'; import { EditorGutter } from 'vs/workbench/contrib/mergeEditor/browser/view/editorGutter'; +import { ctxIsMergeResultEditor } from 'vs/workbench/contrib/mergeEditor/common/mergeEditor'; import { CodeEditorView } from './codeEditorView'; export class ResultCodeEditorView extends CodeEditorView { @@ -110,6 +113,13 @@ export class ResultCodeEditorView extends CodeEditorView { ) { super(instantiationService); + this.editor.invokeWithinContext(accessor => { + const contextKeyService = accessor.get(IContextKeyService); + const isMergeResultEditor = ctxIsMergeResultEditor.bindTo(contextKeyService); + isMergeResultEditor.set(true); + this._register(toDisposable(() => isMergeResultEditor.reset())); + }); + this._register(applyObservableDecorations(this.editor, this.decorations)); this._register(new MergeMarkersController(this.editor, this.viewModel)); diff --git a/src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.ts b/src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.ts index 9be28f9a2f9..758d2966ae1 100644 --- a/src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.ts +++ b/src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.ts @@ -6,7 +6,6 @@ import { $, Dimension, reset } from 'vs/base/browser/dom'; import { Direction, Grid, IView, SerializableGrid } from 'vs/base/browser/ui/grid/grid'; import { Orientation, Sizing } from 'vs/base/browser/ui/splitview/splitview'; -import { IAction } from 'vs/base/common/actions'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Color } from 'vs/base/common/color'; import { BugIndicatingError } from 'vs/base/common/errors'; @@ -23,8 +22,7 @@ import { IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/ed import { ICodeEditorViewState, ScrollType } from 'vs/editor/common/editorCommon'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; import { localize } from 'vs/nls'; -import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { IMenuService, MenuId } from 'vs/platform/actions/common/actions'; +import { MenuId } from 'vs/platform/actions/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IEditorOptions, ITextEditorOptions, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; @@ -34,7 +32,6 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { FloatingClickWidget } from 'vs/workbench/browser/codeeditor'; import { AbstractTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; import { DEFAULT_EDITOR_ASSOCIATION, EditorInputWithOptions, IEditorOpenContext, IResourceMergeEditorInput } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; @@ -108,8 +105,7 @@ export class MergeEditor extends AbstractTextEditor { constructor( @IInstantiationService instantiation: IInstantiationService, @ILabelService private readonly _labelService: ILabelService, - @IMenuService private readonly _menuService: IMenuService, - @IContextKeyService private readonly _contextKeyService: IContextKeyService, + @IContextKeyService contextKeyService: IContextKeyService, @ITelemetryService telemetryService: ITelemetryService, @IStorageService storageService: IStorageService, @IThemeService themeService: IThemeService, @@ -122,10 +118,10 @@ export class MergeEditor extends AbstractTextEditor { ) { super(MergeEditor.ID, telemetryService, instantiation, storageService, textResourceConfigurationService, themeService, editorService, editorGroupService, fileService); - this._ctxIsMergeEditor = ctxIsMergeEditor.bindTo(_contextKeyService); - this._ctxUsesColumnLayout = ctxMergeEditorLayout.bindTo(_contextKeyService); - this._ctxBaseUri = ctxMergeBaseUri.bindTo(_contextKeyService); - this._ctxResultUri = ctxMergeResultUri.bindTo(_contextKeyService); + this._ctxIsMergeEditor = ctxIsMergeEditor.bindTo(contextKeyService); + this._ctxUsesColumnLayout = ctxMergeEditorLayout.bindTo(contextKeyService); + this._ctxBaseUri = ctxMergeBaseUri.bindTo(contextKeyService); + this._ctxResultUri = ctxMergeResultUri.bindTo(contextKeyService); this._layoutMode = instantiation.createInstance(MergeEditorLayout); this._ctxUsesColumnLayout.set(this._layoutMode.value); @@ -169,27 +165,6 @@ export class MergeEditor extends AbstractTextEditor { }) ) ); - - // TODO@jrieken make this proper: add menu id and allow extensions to contribute - const toolbarMenu = this._menuService.createMenu(MenuId.MergeToolbar, this._contextKeyService); - const toolbarMenuDisposables = new DisposableStore(); - const toolbarMenuRender = () => { - toolbarMenuDisposables.clear(); - - const actions: IAction[] = []; - createAndFillInActionBarActions(toolbarMenu, { renderShortTitle: true, shouldForwardArgs: true }, actions); - if (actions.length > 0) { - const [first] = actions; - const acceptBtn = this.instantiationService.createInstance(FloatingClickWidget, this.inputResultView.editor, first.label, first.id); - toolbarMenuDisposables.add(acceptBtn.onClick(() => first.run(this.inputResultView.editor.getModel()?.uri))); - toolbarMenuDisposables.add(acceptBtn); - acceptBtn.render(); - } - }; - this._store.add(toolbarMenu); - this._store.add(toolbarMenuDisposables); - this._store.add(toolbarMenu.onDidChange(toolbarMenuRender)); - toolbarMenuRender(); } private updateResultScrolling(scrollTopChanged: boolean, scrollLeftChanged: boolean): void { diff --git a/src/vs/workbench/contrib/mergeEditor/common/mergeEditor.ts b/src/vs/workbench/contrib/mergeEditor/common/mergeEditor.ts index e5757fcc8fa..56da17d7333 100644 --- a/src/vs/workbench/contrib/mergeEditor/common/mergeEditor.ts +++ b/src/vs/workbench/contrib/mergeEditor/common/mergeEditor.ts @@ -9,6 +9,7 @@ import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; export type MergeEditorLayoutTypes = 'mixed' | 'columns'; export const ctxIsMergeEditor = new RawContextKey('isMergeEditor', false, { type: 'boolean', description: localize('is', 'The editor is a merge editor') }); +export const ctxIsMergeResultEditor = new RawContextKey('isMergeResultEditor', false, { type: 'boolean', description: localize('isr', 'The editor is a the result editor of a merge editor.') }); export const ctxMergeEditorLayout = new RawContextKey('mergeEditorLayout', 'mixed', { type: 'string', description: localize('editorLayout', 'The layout mode of a merge editor') }); export const ctxMergeBaseUri = new RawContextKey('mergeEditorBaseUri', '', { type: 'string', description: localize('baseUri', 'The uri of the baser of a merge editor') }); export const ctxMergeResultUri = new RawContextKey('mergeEditorResultUri', '', { type: 'string', description: localize('resultUri', 'The uri of the result of a merge editor') }); diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 3860e67251b..70bdd5252f1 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -58,7 +58,7 @@ import { MarkdownString } from 'vs/base/common/htmlContent'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { ctxIsMergeEditor, ctxMergeBaseUri } from 'vs/workbench/contrib/mergeEditor/common/mergeEditor'; +import { ctxIsMergeResultEditor, ctxMergeBaseUri } from 'vs/workbench/contrib/mergeEditor/common/mergeEditor'; const CONTEXT_CONFLICTS_SOURCES = new RawContextKey('conflictsSources', ''); @@ -1287,8 +1287,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo id: 'workbench.userDataSync.actions.acceptMerges', title: localize('accept merges title', "Accept Merge"), menu: [{ - id: MenuId.MergeToolbar, - when: ContextKeyExpr.and(ctxIsMergeEditor, ContextKeyExpr.regex(ctxMergeBaseUri.key, new RegExp(`^${USER_DATA_SYNC_SCHEME}:`))), + id: MenuId.EditorContent, + when: ContextKeyExpr.and(ctxIsMergeResultEditor, ContextKeyExpr.regex(ctxMergeBaseUri.key, new RegExp(`^${USER_DATA_SYNC_SCHEME}:`))), }], }); } diff --git a/src/vs/workbench/services/actions/common/menusExtensionPoint.ts b/src/vs/workbench/services/actions/common/menusExtensionPoint.ts index a2c43c5301f..40eea48969a 100644 --- a/src/vs/workbench/services/actions/common/menusExtensionPoint.ts +++ b/src/vs/workbench/services/actions/common/menusExtensionPoint.ts @@ -280,10 +280,10 @@ const apiMenus: IAPIMenu[] = [ proposed: 'inlineCompletionsAdditions' }, { - key: 'merge/toolbar', - id: MenuId.MergeToolbar, - description: localize('merge.toolbar', "The prominent botton in the merge editor"), - proposed: 'contribMergeEditorToolbar' + key: 'editor/content', + id: MenuId.EditorContent, + description: localize('merge.toolbar', "The prominent button in an editor, overlays its content"), + proposed: 'contribEditorContentMenu' }, { key: 'webview/context', diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 6eaf48ed34e..85ccd21e919 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -11,9 +11,9 @@ export const allApiProposals = Object.freeze({ commentsResolvedState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.commentsResolvedState.d.ts', contribCommentPeekContext: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribCommentPeekContext.d.ts', contribEditSessions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribEditSessions.d.ts', + contribEditorContentMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribEditorContentMenu.d.ts', contribLabelFormatterWorkspaceTooltip: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribLabelFormatterWorkspaceTooltip.d.ts', contribMenuBarHome: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribMenuBarHome.d.ts', - contribMergeEditorToolbar: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribMergeEditorToolbar.d.ts', contribRemoteHelp: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribRemoteHelp.d.ts', contribShareMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribShareMenu.d.ts', contribViewSize: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribViewSize.d.ts', diff --git a/src/vscode-dts/vscode.proposed.contribMergeEditorToolbar.d.ts b/src/vscode-dts/vscode.proposed.contribEditorContentMenu.d.ts similarity index 83% rename from src/vscode-dts/vscode.proposed.contribMergeEditorToolbar.d.ts rename to src/vscode-dts/vscode.proposed.contribEditorContentMenu.d.ts index 323ff90cecb..6b45f3468bd 100644 --- a/src/vscode-dts/vscode.proposed.contribMergeEditorToolbar.d.ts +++ b/src/vscode-dts/vscode.proposed.contribEditorContentMenu.d.ts @@ -3,4 +3,4 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// empty placeholder declaration for the `mergeEditor/toolbar` menu +// empty placeholder declaration for the `editor/content` menu