forked from microsoft/vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
contextmenuService.ts
104 lines (83 loc) · 3.42 KB
/
contextmenuService.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {TPromise} from 'vs/base/common/winjs.base';
import severity from 'vs/base/common/severity';
import actions = require('vs/base/common/actions');
import {Separator} from 'vs/base/browser/ui/actionbar/actionbar';
import dom = require('vs/base/browser/dom');
import {$} from 'vs/base/browser/builder';
import {IContextMenuService, IContextMenuDelegate} from 'vs/platform/contextview/browser/contextView';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IMessageService} from 'vs/platform/message/common/message';
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {remote, webFrame} from 'electron';
export class ContextMenuService implements IContextMenuService {
public serviceId = IContextMenuService;
private telemetryService: ITelemetryService;
private messageService: IMessageService;
private keybindingService: IKeybindingService;
constructor(messageService: IMessageService, telemetryService: ITelemetryService, keybindingService: IKeybindingService) {
this.messageService = messageService;
this.telemetryService = telemetryService;
this.keybindingService = keybindingService;
}
public showContextMenu(delegate: IContextMenuDelegate): void {
delegate.getActions().then(actions => {
if (!actions.length) {
return TPromise.as(null);
}
return TPromise.timeout(0).then(() => { // https://github.com/Microsoft/vscode/issues/3638
let menu = new remote.Menu();
let actionToRun: actions.IAction = null;
actions.forEach(a => {
if (a instanceof Separator) {
menu.append(new remote.MenuItem({ type: 'separator' }));
} else {
const keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(a) : undefined;
const accelerator = keybinding && this.keybindingService.getElectronAcceleratorFor(keybinding);
const item = new remote.MenuItem({
label: a.label,
checked: a.checked,
accelerator,
enabled: a.enabled,
click: () => {
actionToRun = a;
}
});
menu.append(item);
}
});
const anchor = delegate.getAnchor();
let x: number, y: number;
if (dom.isHTMLElement(anchor)) {
const $anchor = $(<HTMLElement>anchor);
const elementPosition = $anchor.getPosition();
const elementSize = $anchor.getTotalSize();
x = elementPosition.left;
y = elementPosition.top + elementSize.height;
} else {
const pos = <{ x: number; y: number; }>anchor;
x = pos.x;
y = pos.y;
}
let zoom = webFrame.getZoomFactor();
x *= zoom;
y *= zoom;
menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y));
if (delegate.onHide) {
delegate.onHide(false);
}
if (!actionToRun) {
return;
}
this.telemetryService.publicLog('workbenchActionExecuted', { id: actionToRun.id, from: 'contextMenu' });
const context = delegate.getActionsContext ? delegate.getActionsContext() : null;
return actionToRun.run(context) || TPromise.as(null);
});
})
.done(null, e => this.messageService.show(severity.Error, e));
}
}