Skip to content

Commit 3697925

Browse files
committed
Use menuService across all views for context menus. Breakpoints.
fixes microsoft#112551
1 parent a341f80 commit 3697925

File tree

6 files changed

+234
-229
lines changed

6 files changed

+234
-229
lines changed

src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { IModelDecorationOptions, IModelDeltaDecoration, TrackedRangeStickiness,
1515
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1616
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
1717
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
18-
import { RemoveBreakpointAction } from 'vs/workbench/contrib/debug/browser/debugActions';
1918
import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, BreakpointWidgetContext, IBreakpointEditorContribution, IBreakpointUpdateData, IDebugConfiguration, State, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
2019
import { IMarginData } from 'vs/editor/browser/controller/mouseTarget';
2120
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
@@ -301,7 +300,9 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi
301300
const actions: IAction[] = [];
302301
if (breakpoints.length === 1) {
303302
const breakpointType = breakpoints[0].logMessage ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint");
304-
actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService));
303+
actions.push(new Action('debug.removeBreakpoint', nls.localize('removeBreakpoint', "Remove {0}", breakpointType), undefined, true, async () => {
304+
await this.debugService.removeBreakpoints(breakpoints[0].getId());
305+
}));
305306
actions.push(new Action(
306307
'workbench.debug.action.editBreakpointAction',
307308
nls.localize('editBreakpoint', "Edit {0}...", breakpointType),

src/vs/workbench/contrib/debug/browser/breakpointsView.ts

Lines changed: 216 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55

66
import * as resources from 'vs/base/common/resources';
77
import * as dom from 'vs/base/browser/dom';
8-
import { IAction, Action, Separator } from 'vs/base/common/actions';
9-
import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINTS_FOCUSED, State, DEBUG_SCHEME, IFunctionBreakpoint, IExceptionBreakpoint, IEnablement, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, IDebugModel, IDataBreakpoint, BREAKPOINTS_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug';
8+
import { IAction } from 'vs/base/common/actions';
9+
import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINTS_FOCUSED, State, DEBUG_SCHEME, IFunctionBreakpoint, IExceptionBreakpoint, IEnablement, IDebugModel, IDataBreakpoint, BREAKPOINTS_VIEW_ID, CONTEXT_BREAKPOINT_ITEM_TYPE, CONTEXT_EXCEPTION_BREAKPOINT_SUPPORTS_CONDITION, CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_IN_DEBUG_MODE, IBaseBreakpoint, IBreakpointEditorContribution, BREAKPOINT_EDITOR_CONTRIBUTION_ID } from 'vs/workbench/contrib/debug/common/debug';
1010
import { ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, DataBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
11-
import { RemoveBreakpointAction, EnableAllBreakpointsAction, DisableAllBreakpointsAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions';
1211
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
1312
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1413
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
@@ -23,12 +22,11 @@ import { KeyCode } from 'vs/base/common/keyCodes';
2322
import { WorkbenchList, ListResourceNavigator } from 'vs/platform/list/browser/listService';
2423
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
2524
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
26-
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
2725
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2826
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
2927
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
3028
import { ILabelService } from 'vs/platform/label/common/label';
31-
import { IContextKeyService, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey';
29+
import { IContextKeyService, ContextKeyEqualsExpr, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
3230
import { Gesture } from 'vs/base/browser/touch';
3331
import { IViewDescriptorService } from 'vs/workbench/common/views';
3432
import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor';
@@ -37,9 +35,11 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
3735
import { Orientation } from 'vs/base/browser/ui/splitview/splitview';
3836
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
3937
import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons';
40-
import { registerAction2, Action2, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
38+
import { registerAction2, Action2, MenuId, IMenu, IMenuService } from 'vs/platform/actions/common/actions';
4139
import { localize } from 'vs/nls';
4240
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
41+
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
42+
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
4343

4444
const $ = dom.$;
4545

@@ -64,6 +64,9 @@ export class BreakpointsView extends ViewPane {
6464
private list!: WorkbenchList<BreakpointItem>;
6565
private needsRefresh = false;
6666
private ignoreLayout = false;
67+
private menu: IMenu;
68+
private breakpointItemType: IContextKey<string | undefined>;
69+
private exceptionBreakpointSupportsCondition: IContextKey<boolean>;
6770

6871
constructor(
6972
options: IViewletViewOptions,
@@ -80,10 +83,21 @@ export class BreakpointsView extends ViewPane {
8083
@IOpenerService openerService: IOpenerService,
8184
@ITelemetryService telemetryService: ITelemetryService,
8285
@ILabelService private readonly labelService: ILabelService,
86+
@IMenuService menuService: IMenuService
8387
) {
8488
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
8589

90+
this.menu = menuService.createMenu(MenuId.DebugBreakpointsContext, contextKeyService);
91+
this._register(this.menu);
92+
this.breakpointItemType = CONTEXT_BREAKPOINT_ITEM_TYPE.bindTo(contextKeyService);
93+
this.exceptionBreakpointSupportsCondition = CONTEXT_EXCEPTION_BREAKPOINT_SUPPORTS_CONDITION.bindTo(contextKeyService);
8694
this._register(this.debugService.getModel().onDidChangeBreakpoints(() => this.onBreakpointsChange()));
95+
this._register(this.debugService.getViewModel().onDidSelectBreakpoint(breakpoint => {
96+
if (breakpoint) {
97+
// Only react when a new breakpoint is selected - to reduce refresh, since other times a refresh is not needed
98+
this.onBreakpointsChange();
99+
}
100+
}));
87101
}
88102

89103
public renderBody(container: HTMLElement): void {
@@ -140,7 +154,6 @@ export class BreakpointsView extends ViewPane {
140154
if (e.browserEvent instanceof MouseEvent && e.browserEvent.detail === 2 && e.element instanceof FunctionBreakpoint && e.element !== this.debugService.getViewModel().getSelectedBreakpoint()) {
141155
// double click
142156
this.debugService.getViewModel().setSelectedBreakpoint(e.element);
143-
this.onBreakpointsChange();
144157
}
145158
}));
146159

@@ -183,60 +196,20 @@ export class BreakpointsView extends ViewPane {
183196
}
184197

185198
private onListContextMenu(e: IListContextMenuEvent<IEnablement>): void {
186-
if (!e.element) {
187-
return;
188-
}
189-
190-
const actions: IAction[] = [];
191199
const element = e.element;
200+
const type = element instanceof Breakpoint ? 'breakpoint' : element instanceof ExceptionBreakpoint ? 'exceptionBreakpoint' :
201+
element instanceof FunctionBreakpoint ? 'functionBreakpoint' : element instanceof DataBreakpoint ? 'dataBreakpoint' : undefined;
202+
this.breakpointItemType.set(type);
203+
this.exceptionBreakpointSupportsCondition.set(element instanceof ExceptionBreakpoint && element.supportsCondition);
192204

193-
if (element instanceof ExceptionBreakpoint) {
194-
if (element.supportsCondition) {
195-
actions.push(new Action('workbench.action.debug.editExceptionBreakpointCondition', localize('editCondition', "Edit Condition"), '', true, async () => {
196-
this.debugService.getViewModel().setSelectedBreakpoint(element);
197-
this.onBreakpointsChange();
198-
}));
199-
}
200-
} else {
201-
const breakpointType = element instanceof Breakpoint && element.logMessage ? localize('Logpoint', "Logpoint") : localize('Breakpoint', "Breakpoint");
202-
if (element instanceof Breakpoint || element instanceof FunctionBreakpoint) {
203-
actions.push(new Action('workbench.action.debug.openEditorAndEditBreakpoint', localize('editBreakpoint', "Edit {0}...", breakpointType), '', true, async () => {
204-
if (element instanceof Breakpoint) {
205-
const editor = await openBreakpointSource(element, false, false, true, this.debugService, this.editorService);
206-
if (editor) {
207-
const codeEditor = editor.getControl();
208-
if (isCodeEditor(codeEditor)) {
209-
codeEditor.getContribution<IBreakpointEditorContribution>(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(element.lineNumber, element.column);
210-
}
211-
}
212-
} else {
213-
this.debugService.getViewModel().setSelectedBreakpoint(element);
214-
this.onBreakpointsChange();
215-
}
216-
}));
217-
actions.push(new Separator());
218-
}
219-
220-
221-
actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService));
222-
223-
if (this.debugService.getModel().getBreakpoints().length + this.debugService.getModel().getFunctionBreakpoints().length >= 1) {
224-
actions.push(this.instantiationService.createInstance(MenuItemAction, removeAllBreakpointsCommand, undefined, {}));
225-
actions.push(new Separator());
226-
227-
actions.push(new EnableAllBreakpointsAction(EnableAllBreakpointsAction.ID, EnableAllBreakpointsAction.LABEL, this.debugService, this.keybindingService));
228-
actions.push(new DisableAllBreakpointsAction(DisableAllBreakpointsAction.ID, DisableAllBreakpointsAction.LABEL, this.debugService, this.keybindingService));
229-
}
230-
231-
actions.push(new Separator());
232-
actions.push(new ReapplyBreakpointsAction(ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL, this.debugService, this.keybindingService));
233-
}
205+
const actions: IAction[] = [];
206+
const actionsDisposable = createAndFillInContextMenuActions(this.menu, { arg: e.element, shouldForwardArgs: false }, actions);
234207

235208
this.contextMenuService.showContextMenu({
236209
getAnchor: () => e.anchor,
237210
getActions: () => actions,
238211
getActionsContext: () => element,
239-
onHide: () => dispose(actions)
212+
onHide: () => dispose(actionsDisposable)
240213
});
241214
}
242215

@@ -933,21 +906,60 @@ registerAction2(class extends Action2 {
933906
}
934907
});
935908

936-
export const removeAllBreakpointsCommand = {
937-
id: 'workbench.debug.viewlet.action.removeAllBreakpoints',
938-
title: localize('removeAllBreakpoints', "Remove All Breakpoints"),
939-
f1: true,
940-
icon: icons.breakpointsRemoveAll,
941-
menu: [{
942-
id: MenuId.ViewTitle,
943-
group: 'navigation',
944-
order: 30,
945-
when: ContextKeyEqualsExpr.create('view', BREAKPOINTS_VIEW_ID)
946-
}]
947-
};
948909
registerAction2(class extends Action2 {
949910
constructor() {
950-
super(removeAllBreakpointsCommand);
911+
super({
912+
id: 'workbench.debug.viewlet.action.removeBreakpoint',
913+
title: localize('removeBreakpoint', "Remove Breakpoint"),
914+
menu: [{
915+
id: MenuId.DebugBreakpointsContext,
916+
group: '3_modification',
917+
order: 10,
918+
when: CONTEXT_BREAKPOINT_ITEM_TYPE.notEqualsTo('exceptionBreakpoint')
919+
}]
920+
});
921+
}
922+
923+
async run(accessor: ServicesAccessor, breakpoint: IBaseBreakpoint): Promise<void> {
924+
const debugService = accessor.get(IDebugService);
925+
if (breakpoint instanceof Breakpoint) {
926+
await debugService.removeBreakpoints(breakpoint.getId());
927+
} else if (breakpoint instanceof FunctionBreakpoint) {
928+
await debugService.removeFunctionBreakpoints(breakpoint.getId());
929+
} else if (breakpoint instanceof DataBreakpoint) {
930+
await debugService.removeDataBreakpoints(breakpoint.getId());
931+
}
932+
}
933+
});
934+
935+
registerAction2(class extends Action2 {
936+
constructor() {
937+
super({
938+
id: 'workbench.debug.viewlet.action.removeAllBreakpoints',
939+
title: {
940+
original: 'Remove All Breakpoints',
941+
value: localize('removeAllBreakpoints', "Remove All Breakpoints"),
942+
mnemonicedTitle: localize({ key: 'miRemoveAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Remove &&All Breakpoints")
943+
},
944+
f1: true,
945+
icon: icons.breakpointsRemoveAll,
946+
menu: [{
947+
id: MenuId.ViewTitle,
948+
group: 'navigation',
949+
order: 30,
950+
when: ContextKeyEqualsExpr.create('view', BREAKPOINTS_VIEW_ID)
951+
}, {
952+
id: MenuId.DebugBreakpointsContext,
953+
group: '3_modification',
954+
order: 20,
955+
when: ContextKeyExpr.and(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_BREAKPOINT_ITEM_TYPE.notEqualsTo('exceptionBreakpoint'))
956+
}, {
957+
id: MenuId.MenubarDebugMenu,
958+
group: '5_breakpoints',
959+
order: 3,
960+
when: CONTEXT_DEBUGGERS_AVAILABLE
961+
}]
962+
});
951963
}
952964

953965
run(accessor: ServicesAccessor): void {
@@ -957,3 +969,140 @@ registerAction2(class extends Action2 {
957969
debugService.removeDataBreakpoints();
958970
}
959971
});
972+
973+
registerAction2(class extends Action2 {
974+
constructor() {
975+
super({
976+
id: 'workbench.debug.viewlet.action.enableAllBreakpoints',
977+
title: {
978+
original: '',
979+
value: localize('enableAllBreakpoints', "Enable All Breakpoints"),
980+
mnemonicedTitle: localize({ key: 'miEnableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "&&Enable All Breakpoints"),
981+
},
982+
f1: true,
983+
precondition: CONTEXT_DEBUGGERS_AVAILABLE,
984+
menu: [{
985+
id: MenuId.DebugBreakpointsContext,
986+
group: 'z_commands',
987+
order: 10,
988+
when: ContextKeyExpr.and(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_BREAKPOINT_ITEM_TYPE.notEqualsTo('exceptionBreakpoint'))
989+
}, {
990+
id: MenuId.MenubarDebugMenu,
991+
group: '5_breakpoints',
992+
order: 1,
993+
when: CONTEXT_DEBUGGERS_AVAILABLE
994+
}]
995+
});
996+
}
997+
998+
async run(accessor: ServicesAccessor): Promise<void> {
999+
const debugService = accessor.get(IDebugService);
1000+
await debugService.enableOrDisableBreakpoints(true);
1001+
}
1002+
});
1003+
1004+
registerAction2(class extends Action2 {
1005+
constructor() {
1006+
super({
1007+
id: 'workbench.debug.viewlet.action.disableAllBreakpoints',
1008+
title: {
1009+
original: 'Disable All Breakpoints',
1010+
value: localize('disableAllBreakpoints', "Disable All Breakpoints"),
1011+
mnemonicedTitle: localize({ key: 'miDisableAllBreakpoints', comment: ['&& denotes a mnemonic'] }, "Disable A&&ll Breakpoints")
1012+
},
1013+
f1: true,
1014+
precondition: CONTEXT_DEBUGGERS_AVAILABLE,
1015+
menu: [{
1016+
id: MenuId.DebugBreakpointsContext,
1017+
group: 'z_commands',
1018+
order: 20,
1019+
when: ContextKeyExpr.and(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_BREAKPOINT_ITEM_TYPE.notEqualsTo('exceptionBreakpoint'))
1020+
}, {
1021+
id: MenuId.MenubarDebugMenu,
1022+
group: '5_breakpoints',
1023+
order: 2,
1024+
1025+
when: CONTEXT_DEBUGGERS_AVAILABLE
1026+
}]
1027+
});
1028+
}
1029+
1030+
async run(accessor: ServicesAccessor): Promise<void> {
1031+
const debugService = accessor.get(IDebugService);
1032+
await debugService.enableOrDisableBreakpoints(false);
1033+
}
1034+
});
1035+
1036+
registerAction2(class extends Action2 {
1037+
constructor() {
1038+
super({
1039+
id: 'workbench.debug.viewlet.action.reapplyBreakpointsAction',
1040+
title: localize('reapplyAllBreakpoints', "Reapply All Breakpoints"),
1041+
f1: true,
1042+
precondition: CONTEXT_IN_DEBUG_MODE,
1043+
menu: [{
1044+
id: MenuId.DebugBreakpointsContext,
1045+
group: 'z_commands',
1046+
order: 30,
1047+
when: ContextKeyExpr.and(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_BREAKPOINT_ITEM_TYPE.notEqualsTo('exceptionBreakpoint'))
1048+
}]
1049+
});
1050+
}
1051+
1052+
async run(accessor: ServicesAccessor): Promise<void> {
1053+
const debugService = accessor.get(IDebugService);
1054+
await debugService.setBreakpointsActivated(true);
1055+
}
1056+
});
1057+
1058+
registerAction2(class extends Action2 {
1059+
constructor() {
1060+
super({
1061+
id: 'workbench.action.debug.editExceptionBreakpointCondition',
1062+
title: localize('editCondition', "Edit Condition"),
1063+
menu: [{
1064+
id: MenuId.DebugBreakpointsContext,
1065+
group: 'navigation',
1066+
order: 10,
1067+
when: CONTEXT_EXCEPTION_BREAKPOINT_SUPPORTS_CONDITION
1068+
}]
1069+
});
1070+
}
1071+
1072+
async run(accessor: ServicesAccessor, breakpoint: ExceptionBreakpoint): Promise<void> {
1073+
const debugService = accessor.get(IDebugService);
1074+
debugService.getViewModel().setSelectedBreakpoint(breakpoint);
1075+
}
1076+
});
1077+
1078+
1079+
registerAction2(class extends Action2 {
1080+
constructor() {
1081+
super({
1082+
id: 'debug.editBreakpoint',
1083+
title: localize('editBreakpoint', "Edit Breakpoint..."),
1084+
menu: [{
1085+
id: MenuId.DebugBreakpointsContext,
1086+
group: 'navigation',
1087+
order: 10,
1088+
when: ContextKeyExpr.or(CONTEXT_BREAKPOINT_ITEM_TYPE.isEqualTo('breakpoint'), CONTEXT_BREAKPOINT_ITEM_TYPE.isEqualTo('functionBreakpoint'))
1089+
}]
1090+
});
1091+
}
1092+
1093+
async run(accessor: ServicesAccessor, breakpoint: ExceptionBreakpoint): Promise<void> {
1094+
const debugService = accessor.get(IDebugService);
1095+
const editorService = accessor.get(IEditorService);
1096+
if (breakpoint instanceof Breakpoint) {
1097+
const editor = await openBreakpointSource(breakpoint, false, false, true, debugService, editorService);
1098+
if (editor) {
1099+
const codeEditor = editor.getControl();
1100+
if (isCodeEditor(codeEditor)) {
1101+
codeEditor.getContribution<IBreakpointEditorContribution>(BREAKPOINT_EDITOR_CONTRIBUTION_ID).showBreakpointWidget(breakpoint.lineNumber, breakpoint.column);
1102+
}
1103+
}
1104+
} else {
1105+
debugService.getViewModel().setSelectedBreakpoint(breakpoint);
1106+
}
1107+
}
1108+
});

0 commit comments

Comments
 (0)