actions.ts 39.7 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6 7
import 'vs/css!./media/actions';

8
import { URI } from 'vs/base/common/uri';
C
Christof Marti 已提交
9
import { Action } from 'vs/base/common/actions';
10
import { IWindowService, IWindowsService, MenuBarVisibility } from 'vs/platform/windows/common/windows';
11
import * as nls from 'vs/nls';
12
import product from 'vs/platform/node/product';
13
import * as errors from 'vs/base/common/errors';
14
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
15
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
J
Johannes Rieken 已提交
16
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
S
SteVen Batten 已提交
17
import { isMacintosh, isLinux, language } from 'vs/base/common/platform';
18
import * as browser from 'vs/base/browser/browser';
B
Benjamin Pasero 已提交
19
import { IEditorGroupsService, GroupDirection, GroupLocation, IFindGroupScope } from 'vs/workbench/services/group/common/editorGroupsService';
S
sj.hwang 已提交
20
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
21
import { IPartService, Parts, Position as PartPosition } from 'vs/workbench/services/part/common/partService';
S
sj.hwang 已提交
22
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
B
Benjamin Pasero 已提交
23
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
S
SteVen Batten 已提交
24
import { webFrame, shell } from 'electron';
25
import { getBaseLabel } from 'vs/base/common/labels';
B
Benjamin Pasero 已提交
26 27
import { IViewlet } from 'vs/workbench/common/viewlet';
import { IPanel } from 'vs/workbench/common/panel';
28
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
S
Sandeep Somavarapu 已提交
29
import { FileKind } from 'vs/platform/files/common/files';
30
import { IssueType } from 'vs/platform/issue/common/issue';
J
Joao Moreno 已提交
31 32 33 34 35 36
import { domEvent } from 'vs/base/browser/event';
import { once } from 'vs/base/common/event';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { getDomNodePagePosition, createStyleSheet, createCSSRule } from 'vs/base/browser/dom';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Context } from 'vs/platform/contextkey/browser/contextKeyService';
37
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
38
import { INotificationService } from 'vs/platform/notification/common/notification';
I
isidor 已提交
39
import { ILabelService } from 'vs/platform/label/common/label';
40
import { dirname } from 'vs/base/common/resources';
C
Christof Marti 已提交
41 42
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
C
Christof Marti 已提交
43
import { IQuickInputService, IQuickPickItem, IQuickInputButton, IQuickPickSeparator, IKeyMods } from 'vs/platform/quickinput/common/quickInput';
44
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
E
Erich Gamma 已提交
45

46 47
// --- actions

48
export class CloseCurrentWindowAction extends Action {
E
Erich Gamma 已提交
49

B
Benjamin Pasero 已提交
50 51
	static readonly ID = 'workbench.action.closeWindow';
	static readonly LABEL = nls.localize('closeWindow', "Close Window");
E
Erich Gamma 已提交
52

53
	constructor(id: string, label: string, @IWindowService private windowService: IWindowService) {
E
Erich Gamma 已提交
54 55 56
		super(id, label);
	}

B
Benjamin Pasero 已提交
57
	run(): Thenable<boolean> {
58
		this.windowService.closeWindow();
E
Erich Gamma 已提交
59

B
Benjamin Pasero 已提交
60
		return Promise.resolve(true);
E
Erich Gamma 已提交
61 62 63
	}
}

64
export class CloseWorkspaceAction extends Action {
E
Erich Gamma 已提交
65

66
	static readonly ID = 'workbench.action.closeFolder';
67
	static LABEL = nls.localize('closeWorkspace', "Close Workspace");
E
Erich Gamma 已提交
68 69 70 71 72

	constructor(
		id: string,
		label: string,
		@IWorkspaceContextService private contextService: IWorkspaceContextService,
73
		@INotificationService private notificationService: INotificationService,
J
Joao Moreno 已提交
74
		@IWindowService private windowService: IWindowService
E
Erich Gamma 已提交
75 76 77 78
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
79
	run(): Thenable<void> {
80
		if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
81
			this.notificationService.info(nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close."));
82

B
Benjamin Pasero 已提交
83
			return Promise.resolve(null);
E
Erich Gamma 已提交
84 85
		}

86
		return this.windowService.closeWorkspace();
E
Erich Gamma 已提交
87 88 89 90 91
	}
}

export class NewWindowAction extends Action {

92
	static readonly ID = 'workbench.action.newWindow';
J
Joao Moreno 已提交
93
	static LABEL = nls.localize('newWindow', "New Window");
E
Erich Gamma 已提交
94

B
Benjamin Pasero 已提交
95 96 97
	constructor(
		id: string,
		label: string,
J
Joao Moreno 已提交
98
		@IWindowsService private windowsService: IWindowsService
B
Benjamin Pasero 已提交
99
	) {
E
Erich Gamma 已提交
100 101 102
		super(id, label);
	}

B
Benjamin Pasero 已提交
103
	run(): Thenable<void> {
J
Joao Moreno 已提交
104
		return this.windowsService.openNewWindow();
E
Erich Gamma 已提交
105 106 107 108 109
	}
}

export class ToggleFullScreenAction extends Action {

110
	static readonly ID = 'workbench.action.toggleFullScreen';
J
Joao Moreno 已提交
111
	static LABEL = nls.localize('toggleFullScreen', "Toggle Full Screen");
E
Erich Gamma 已提交
112

J
Joao Moreno 已提交
113
	constructor(id: string, label: string, @IWindowService private windowService: IWindowService) {
E
Erich Gamma 已提交
114 115 116
		super(id, label);
	}

B
Benjamin Pasero 已提交
117
	run(): Thenable<void> {
J
Joao Moreno 已提交
118
		return this.windowService.toggleFullScreen();
E
Erich Gamma 已提交
119 120 121
	}
}

122 123
export class ToggleMenuBarAction extends Action {

124
	static readonly ID = 'workbench.action.toggleMenuBar';
J
Joao Moreno 已提交
125
	static LABEL = nls.localize('toggleMenuBar', "Toggle Menu Bar");
126

127
	private static readonly menuBarVisibilityKey = 'window.menuBarVisibility';
128 129 130 131

	constructor(
		id: string,
		label: string,
132
		@IConfigurationService private configurationService: IConfigurationService
133
	) {
134 135 136
		super(id, label);
	}

B
Benjamin Pasero 已提交
137
	run(): Thenable<void> {
138
		let currentVisibilityValue = this.configurationService.getValue<MenuBarVisibility>(ToggleMenuBarAction.menuBarVisibilityKey);
139 140
		if (typeof currentVisibilityValue !== 'string') {
			currentVisibilityValue = 'default';
141 142 143
		}

		let newVisibilityValue: string;
144
		if (currentVisibilityValue === 'visible' || currentVisibilityValue === 'default') {
145 146
			newVisibilityValue = 'toggle';
		} else {
147
			newVisibilityValue = 'default';
148 149
		}

150
		this.configurationService.updateValue(ToggleMenuBarAction.menuBarVisibilityKey, newVisibilityValue, ConfigurationTarget.USER);
151

B
Benjamin Pasero 已提交
152
		return Promise.resolve(null);
153 154 155
	}
}

E
Erich Gamma 已提交
156 157
export class ToggleDevToolsAction extends Action {

158
	static readonly ID = 'workbench.action.toggleDevTools';
J
Joao Moreno 已提交
159
	static LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools");
E
Erich Gamma 已提交
160

J
Joao Moreno 已提交
161
	constructor(id: string, label: string, @IWindowService private windowsService: IWindowService) {
E
Erich Gamma 已提交
162 163 164
		super(id, label);
	}

B
Benjamin Pasero 已提交
165
	run(): Thenable<void> {
J
Joao Moreno 已提交
166
		return this.windowsService.toggleDevTools();
E
Erich Gamma 已提交
167 168 169
	}
}

170
export abstract class BaseZoomAction extends Action {
171
	private static readonly SETTING_KEY = 'window.zoomLevel';
172 173 174 175

	constructor(
		id: string,
		label: string,
176
		@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService
177 178 179 180 181
	) {
		super(id, label);
	}

	protected setConfiguredZoomLevel(level: number): void {
182 183
		level = Math.round(level); // when reaching smallest zoom, prevent fractional zoom levels

B
Benjamin Pasero 已提交
184
		const applyZoom = () => {
185
			webFrame.setZoomLevel(level);
B
Benjamin Pasero 已提交
186
			browser.setZoomFactor(webFrame.getZoomFactor());
187 188 189 190
			// See https://github.com/Microsoft/vscode/issues/26151
			// Cannot be trusted because the webFrame might take some time
			// until it really applies the new zoom level
			browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false);
191 192
		};

193
		this.configurationService.updateValue(BaseZoomAction.SETTING_KEY, level).then(() => applyZoom());
194 195 196 197
	}
}

export class ZoomInAction extends BaseZoomAction {
E
Erich Gamma 已提交
198

B
Benjamin Pasero 已提交
199 200
	static readonly ID = 'workbench.action.zoomIn';
	static readonly LABEL = nls.localize('zoomIn', "Zoom In");
E
Erich Gamma 已提交
201

202 203 204
	constructor(
		id: string,
		label: string,
205
		@IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService
206
	) {
207
		super(id, label, configurationService);
E
Erich Gamma 已提交
208 209
	}

B
Benjamin Pasero 已提交
210
	run(): Thenable<boolean> {
211
		this.setConfiguredZoomLevel(webFrame.getZoomLevel() + 1);
E
Erich Gamma 已提交
212

B
Benjamin Pasero 已提交
213
		return Promise.resolve(true);
E
Erich Gamma 已提交
214 215 216
	}
}

217
export class ZoomOutAction extends BaseZoomAction {
E
Erich Gamma 已提交
218

B
Benjamin Pasero 已提交
219 220
	static readonly ID = 'workbench.action.zoomOut';
	static readonly LABEL = nls.localize('zoomOut', "Zoom Out");
E
Erich Gamma 已提交
221

222 223
	constructor(
		id: string,
224
		label: string,
225
		@IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService
226
	) {
227
		super(id, label, configurationService);
E
Erich Gamma 已提交
228 229
	}

B
Benjamin Pasero 已提交
230
	run(): Thenable<boolean> {
231
		this.setConfiguredZoomLevel(webFrame.getZoomLevel() - 1);
232

B
Benjamin Pasero 已提交
233
		return Promise.resolve(true);
E
Erich Gamma 已提交
234 235 236
	}
}

237
export class ZoomResetAction extends BaseZoomAction {
E
Erich Gamma 已提交
238

B
Benjamin Pasero 已提交
239 240
	static readonly ID = 'workbench.action.zoomReset';
	static readonly LABEL = nls.localize('zoomReset', "Reset Zoom");
E
Erich Gamma 已提交
241

242 243 244
	constructor(
		id: string,
		label: string,
245
		@IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService
246
	) {
247
		super(id, label, configurationService);
E
Erich Gamma 已提交
248 249
	}

B
Benjamin Pasero 已提交
250
	run(): Thenable<boolean> {
251
		this.setConfiguredZoomLevel(0);
252

B
Benjamin Pasero 已提交
253
		return Promise.resolve(true);
E
Erich Gamma 已提交
254 255 256 257 258
	}
}

export class ReloadWindowAction extends Action {

259
	static readonly ID = 'workbench.action.reloadWindow';
260
	static LABEL = nls.localize('reloadWindow', "Reload Window");
E
Erich Gamma 已提交
261

262 263 264
	constructor(
		id: string,
		label: string,
B
Benjamin Pasero 已提交
265
		@IWindowService private windowService: IWindowService
266
	) {
E
Erich Gamma 已提交
267 268 269
		super(id, label);
	}

B
Benjamin Pasero 已提交
270
	run(): Thenable<boolean> {
271
		return this.windowService.reloadWindow().then(() => true);
E
Erich Gamma 已提交
272 273 274
	}
}

275 276 277 278 279 280 281 282 283 284 285 286 287
export class ReloadWindowWithExtensionsDisabledAction extends Action {

	static readonly ID = 'workbench.action.reloadWindowWithExtensionsDisabled';
	static LABEL = nls.localize('reloadWindowWithExntesionsDisabled', "Reload Window With Extensions Disabled");

	constructor(
		id: string,
		label: string,
		@IWindowService private windowService: IWindowService
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
288
	run(): Thenable<boolean> {
289
		return this.windowService.reloadWindow({ _: [], 'disable-extensions': true }).then(() => true);
290 291 292
	}
}

B
Benjamin Pasero 已提交
293
export abstract class BaseSwitchWindow extends Action {
C
Christof Marti 已提交
294 295 296 297 298

	private closeWindowAction: IQuickInputButton = {
		iconClass: 'action-remove-from-recently-opened',
		tooltip: nls.localize('close', "Close Window")
	};
E
Erich Gamma 已提交
299

B
Benjamin Pasero 已提交
300 301 302 303 304
	constructor(
		id: string,
		label: string,
		private windowsService: IWindowsService,
		private windowService: IWindowService,
C
Christof Marti 已提交
305
		private quickInputService: IQuickInputService,
306
		private keybindingService: IKeybindingService,
C
Christof Marti 已提交
307 308
		private modelService: IModelService,
		private modeService: IModeService,
B
Benjamin Pasero 已提交
309 310
	) {
		super(id, label);
311

B
Benjamin Pasero 已提交
312 313 314 315
	}

	protected abstract isQuickNavigate(): boolean;

B
Benjamin Pasero 已提交
316
	run(): Thenable<void> {
B
Benjamin Pasero 已提交
317 318
		const currentWindowId = this.windowService.getCurrentWindowId();

319
		return this.windowsService.getWindows().then(windows => {
B
Benjamin Pasero 已提交
320
			const placeHolder = nls.localize('switchWindowPlaceHolder', "Select a window to switch to");
C
Christof Marti 已提交
321 322 323 324 325 326 327 328 329 330 331
			const picks = windows.map(win => {
				const resource = win.filename ? URI.file(win.filename) : win.folderUri ? win.folderUri : win.workspace ? URI.file(win.workspace.configPath) : void 0;
				const fileKind = win.filename ? FileKind.FILE : win.workspace ? FileKind.ROOT_FOLDER : win.folderUri ? FileKind.FOLDER : FileKind.FILE;
				return {
					payload: win.id,
					label: win.title,
					iconClasses: getIconClasses(this.modelService, this.modeService, resource, fileKind),
					description: (currentWindowId === win.id) ? nls.localize('current', "Current Window") : void 0,
					buttons: (!this.isQuickNavigate() && currentWindowId !== win.id) ? [this.closeWindowAction] : void 0
				} as (IQuickPickItem & { payload: number });
			});
B
Benjamin Pasero 已提交
332

333 334
			const autoFocusIndex = (picks.indexOf(picks.filter(pick => pick.payload === currentWindowId)[0]) + 1) % picks.length;

C
Christof Marti 已提交
335
			return this.quickInputService.pick(picks, {
336
				contextKey: 'inWindowsPicker',
C
Christof Marti 已提交
337
				activeItem: picks[autoFocusIndex],
B
Benjamin Pasero 已提交
338
				placeHolder,
C
Christof Marti 已提交
339 340 341 342 343 344
				quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : void 0,
				onDidTriggerItemButton: context => {
					this.windowsService.closeWindow(context.item.payload).then(() => {
						context.removeItem();
					});
				}
B
Benjamin Pasero 已提交
345
			});
C
Christof Marti 已提交
346 347
		}).then(pick => {
			if (pick) {
348
				this.windowsService.showWindow(pick.payload);
C
Christof Marti 已提交
349
			}
350 351
		});
	}
B
Benjamin Pasero 已提交
352 353 354 355
}

export class SwitchWindow extends BaseSwitchWindow {

356
	static readonly ID = 'workbench.action.switchWindow';
B
Benjamin Pasero 已提交
357
	static LABEL = nls.localize('switchWindow', "Switch Window...");
E
Erich Gamma 已提交
358 359 360 361

	constructor(
		id: string,
		label: string,
B
Benjamin Pasero 已提交
362 363
		@IWindowsService windowsService: IWindowsService,
		@IWindowService windowService: IWindowService,
C
Christof Marti 已提交
364
		@IQuickInputService quickInputService: IQuickInputService,
365
		@IKeybindingService keybindingService: IKeybindingService,
C
Christof Marti 已提交
366 367
		@IModelService modelService: IModelService,
		@IModeService modeService: IModeService,
B
Benjamin Pasero 已提交
368
	) {
C
Christof Marti 已提交
369
		super(id, label, windowsService, windowService, quickInputService, keybindingService, modelService, modeService);
B
Benjamin Pasero 已提交
370 371 372 373 374 375 376 377 378
	}

	protected isQuickNavigate(): boolean {
		return false;
	}
}

export class QuickSwitchWindow extends BaseSwitchWindow {

379
	static readonly ID = 'workbench.action.quickSwitchWindow';
B
Benjamin Pasero 已提交
380 381 382 383 384 385 386
	static LABEL = nls.localize('quickSwitchWindow', "Quick Switch Window...");

	constructor(
		id: string,
		label: string,
		@IWindowsService windowsService: IWindowsService,
		@IWindowService windowService: IWindowService,
C
Christof Marti 已提交
387
		@IQuickInputService quickInputService: IQuickInputService,
388
		@IKeybindingService keybindingService: IKeybindingService,
C
Christof Marti 已提交
389 390
		@IModelService modelService: IModelService,
		@IModeService modeService: IModeService,
B
Benjamin Pasero 已提交
391
	) {
C
Christof Marti 已提交
392
		super(id, label, windowsService, windowService, quickInputService, keybindingService, modelService, modeService);
B
Benjamin Pasero 已提交
393 394 395 396 397 398 399
	}

	protected isQuickNavigate(): boolean {
		return true;
	}
}

400 401
export const inRecentFilesPickerContextKey = 'inRecentFilesPicker';

B
Benjamin Pasero 已提交
402 403
export abstract class BaseOpenRecentAction extends Action {

C
Christof Marti 已提交
404 405 406 407 408
	private removeFromRecentlyOpened: IQuickInputButton = {
		iconClass: 'action-remove-from-recently-opened',
		tooltip: nls.localize('remove', "Remove from Recently Opened")
	};

B
Benjamin Pasero 已提交
409 410 411 412
	constructor(
		id: string,
		label: string,
		private windowService: IWindowService,
C
Christof Marti 已提交
413 414
		private windowsService: IWindowsService,
		private quickInputService: IQuickInputService,
B
Benjamin Pasero 已提交
415
		private contextService: IWorkspaceContextService,
I
isidor 已提交
416
		private labelService: ILabelService,
417
		private keybindingService: IKeybindingService,
C
Christof Marti 已提交
418 419
		private modelService: IModelService,
		private modeService: IModeService,
E
Erich Gamma 已提交
420 421 422 423
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
424 425
	protected abstract isQuickNavigate(): boolean;

B
Benjamin Pasero 已提交
426
	run(): Thenable<void> {
B
Benjamin Pasero 已提交
427
		return this.windowService.getRecentlyOpened()
428
			.then(({ workspaces, files }) => this.openRecent(workspaces, files));
B
Benjamin Pasero 已提交
429 430
	}

431
	private openRecent(recentWorkspaces: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier)[], recentFiles: URI[]): void {
432

433
		const toPick = (workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI, fileKind: FileKind, labelService: ILabelService, buttons: IQuickInputButton[]) => {
434
			let resource: URI;
B
Benjamin Pasero 已提交
435 436
			let label: string;
			let description: string;
437
			if (isSingleFolderWorkspaceIdentifier(workspace) && fileKind !== FileKind.FILE) {
438
				resource = workspace;
I
isidor 已提交
439 440
				label = labelService.getWorkspaceLabel(workspace);
				description = labelService.getUriLabel(dirname(resource));
441 442
			} else if (isWorkspaceIdentifier(workspace)) {
				resource = URI.file(workspace.configPath);
I
isidor 已提交
443 444
				label = labelService.getWorkspaceLabel(workspace);
				description = labelService.getUriLabel(dirname(resource));
445
			} else {
446
				resource = workspace;
447
				label = getBaseLabel(workspace);
I
isidor 已提交
448
				description = labelService.getUriLabel(dirname(resource));
B
Benjamin Pasero 已提交
449
			}
B
Benjamin Pasero 已提交
450

B
Benjamin Pasero 已提交
451
			return {
C
Christof Marti 已提交
452
				iconClasses: getIconClasses(this.modelService, this.modeService, resource, fileKind),
453 454
				label,
				description,
C
Christof Marti 已提交
455 456 457 458
				buttons,
				workspace,
				resource,
				fileKind,
B
Benjamin Pasero 已提交
459
			};
C
Christof Marti 已提交
460
		};
B
Benjamin Pasero 已提交
461

C
Christof Marti 已提交
462 463 464
		const runPick = (resource: URI, isFile: boolean, keyMods: IKeyMods) => {
			const forceNewWindow = keyMods.ctrlCmd;
			return this.windowService.openWindow([resource], { forceNewWindow, forceOpenWorkspaceAsFile: isFile });
465
		};
B
Benjamin Pasero 已提交
466

467 468
		const workspacePicks = recentWorkspaces.map(workspace => toPick(workspace, isSingleFolderWorkspaceIdentifier(workspace) ? FileKind.FOLDER : FileKind.ROOT_FOLDER, this.labelService, !this.isQuickNavigate() ? [this.removeFromRecentlyOpened] : void 0));
		const filePicks = recentFiles.map(p => toPick(p, FileKind.FILE, this.labelService, !this.isQuickNavigate() ? [this.removeFromRecentlyOpened] : void 0));
B
Benjamin Pasero 已提交
469

470 471 472
		// focus second entry if the first recent workspace is the current workspace
		let autoFocusSecondEntry: boolean = recentWorkspaces[0] && this.contextService.isCurrentWorkspace(recentWorkspaces[0]);

C
Christof Marti 已提交
473 474
		let keyMods: IKeyMods;
		const workspaceSeparator: IQuickPickSeparator = { type: 'separator', label: nls.localize('workspaces', "workspaces") };
C
Christof Marti 已提交
475
		const fileSeparator: IQuickPickSeparator = { type: 'separator', label: nls.localize('files', "files") };
C
Christof Marti 已提交
476 477
		const picks = [workspaceSeparator, ...workspacePicks, fileSeparator, ...filePicks];
		this.quickInputService.pick(picks, {
478
			contextKey: inRecentFilesPickerContextKey,
C
Christof Marti 已提交
479
			activeItem: [...workspacePicks, ...filePicks][autoFocusSecondEntry ? 1 : 0],
B
Benjamin Pasero 已提交
480
			placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to open in new window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to open in new window)"),
B
Benjamin Pasero 已提交
481
			matchOnDescription: true,
C
Christof Marti 已提交
482 483 484 485 486 487 488 489 490 491 492 493 494
			onKeyMods: mods => keyMods = mods,
			quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : void 0,
			onDidTriggerItemButton: context => {
				this.windowsService.removeFromRecentlyOpened([context.item.workspace]).then(() => {
					context.removeItem();
				}).then(null, errors.onUnexpectedError);
			}
		})
			.then(pick => {
				if (pick) {
					return runPick(pick.resource, pick.fileKind === FileKind.FILE, keyMods);
				}
				return null;
495
			});
496
	}
E
Erich Gamma 已提交
497 498
}

B
Benjamin Pasero 已提交
499 500
export class OpenRecentAction extends BaseOpenRecentAction {

B
Benjamin Pasero 已提交
501 502
	static readonly ID = 'workbench.action.openRecent';
	static readonly LABEL = nls.localize('openRecent', "Open Recent...");
B
Benjamin Pasero 已提交
503 504 505 506 507

	constructor(
		id: string,
		label: string,
		@IWindowService windowService: IWindowService,
C
Christof Marti 已提交
508 509
		@IWindowsService windowsService: IWindowsService,
		@IQuickInputService quickInputService: IQuickInputService,
B
Benjamin Pasero 已提交
510
		@IWorkspaceContextService contextService: IWorkspaceContextService,
511
		@IKeybindingService keybindingService: IKeybindingService,
C
Christof Marti 已提交
512 513
		@IModelService modelService: IModelService,
		@IModeService modeService: IModeService,
I
isidor 已提交
514
		@ILabelService labelService: ILabelService
B
Benjamin Pasero 已提交
515
	) {
516
		super(id, label, windowService, windowsService, quickInputService, contextService, labelService, keybindingService, modelService, modeService);
B
Benjamin Pasero 已提交
517 518 519 520 521 522 523 524 525
	}

	protected isQuickNavigate(): boolean {
		return false;
	}
}

export class QuickOpenRecentAction extends BaseOpenRecentAction {

B
Benjamin Pasero 已提交
526 527
	static readonly ID = 'workbench.action.quickOpenRecent';
	static readonly LABEL = nls.localize('quickOpenRecent', "Quick Open Recent...");
B
Benjamin Pasero 已提交
528 529 530 531 532

	constructor(
		id: string,
		label: string,
		@IWindowService windowService: IWindowService,
C
Christof Marti 已提交
533 534
		@IWindowsService windowsService: IWindowsService,
		@IQuickInputService quickInputService: IQuickInputService,
B
Benjamin Pasero 已提交
535
		@IWorkspaceContextService contextService: IWorkspaceContextService,
536
		@IKeybindingService keybindingService: IKeybindingService,
C
Christof Marti 已提交
537 538
		@IModelService modelService: IModelService,
		@IModeService modeService: IModeService,
I
isidor 已提交
539
		@ILabelService labelService: ILabelService
B
Benjamin Pasero 已提交
540
	) {
541
		super(id, label, windowService, windowsService, quickInputService, contextService, labelService, keybindingService, modelService, modeService);
B
Benjamin Pasero 已提交
542 543 544 545 546 547 548
	}

	protected isQuickNavigate(): boolean {
		return true;
	}
}

549
export class OpenIssueReporterAction extends Action {
B
Benjamin Pasero 已提交
550 551
	static readonly ID = 'workbench.action.openIssueReporter';
	static readonly LABEL = nls.localize({ key: 'reportIssueInEnglish', comment: ['Translate this to "Report Issue in English" in all languages please!'] }, "Report Issue");
552 553 554 555

	constructor(
		id: string,
		label: string,
556
		@IWorkbenchIssueService private issueService: IWorkbenchIssueService
557 558 559 560
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
561
	run(): Thenable<boolean> {
562 563
		return this.issueService.openReporter()
			.then(() => true);
564 565 566
	}
}

567
export class OpenProcessExplorer extends Action {
B
Benjamin Pasero 已提交
568 569
	static readonly ID = 'workbench.action.openProcessExplorer';
	static readonly LABEL = nls.localize('openProcessExplorer', "Open Process Explorer");
570 571 572 573 574 575 576 577 578

	constructor(
		id: string,
		label: string,
		@IWorkbenchIssueService private issueService: IWorkbenchIssueService
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
579
	run(): Thenable<boolean> {
580 581 582 583 584
		return this.issueService.openProcessExplorer()
			.then(() => true);
	}
}

585
export class ReportPerformanceIssueUsingReporterAction extends Action {
B
Benjamin Pasero 已提交
586 587
	static readonly ID = 'workbench.action.reportPerformanceIssueUsingReporter';
	static readonly LABEL = nls.localize('reportPerformanceIssue', "Report Performance Issue");
588 589 590 591

	constructor(
		id: string,
		label: string,
592
		@IWorkbenchIssueService private issueService: IWorkbenchIssueService
593 594 595 596
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
597
	run(): Thenable<boolean> {
598 599 600
		// TODO: Reporter should send timings table as well
		return this.issueService.openReporter({ issueType: IssueType.PerformanceIssue })
			.then(() => true);
601 602 603
	}
}

604

605 606
export class KeybindingsReferenceAction extends Action {

B
Benjamin Pasero 已提交
607 608
	static readonly ID = 'workbench.action.keybindingsReference';
	static readonly LABEL = nls.localize('keybindingsReference', "Keyboard Shortcuts Reference");
609

610
	private static readonly URL = isLinux ? product.keyboardShortcutsUrlLinux : isMacintosh ? product.keyboardShortcutsUrlMac : product.keyboardShortcutsUrlWin;
B
Benjamin Pasero 已提交
611
	static readonly AVAILABLE = !!KeybindingsReferenceAction.URL;
612 613 614 615 616 617 618 619

	constructor(
		id: string,
		label: string
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
620
	run(): Thenable<void> {
621 622 623 624 625
		window.open(KeybindingsReferenceAction.URL);
		return null;
	}
}

C
Christof Marti 已提交
626 627
export class OpenDocumentationUrlAction extends Action {

B
Benjamin Pasero 已提交
628 629
	static readonly ID = 'workbench.action.openDocumentationUrl';
	static readonly LABEL = nls.localize('openDocumentationUrl', "Documentation");
C
Christof Marti 已提交
630

631
	private static readonly URL = product.documentationUrl;
B
Benjamin Pasero 已提交
632
	static readonly AVAILABLE = !!OpenDocumentationUrlAction.URL;
C
Christof Marti 已提交
633 634 635 636 637 638 639 640

	constructor(
		id: string,
		label: string
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
641
	run(): Thenable<void> {
C
Christof Marti 已提交
642 643 644 645 646
		window.open(OpenDocumentationUrlAction.URL);
		return null;
	}
}

647 648
export class OpenIntroductoryVideosUrlAction extends Action {

B
Benjamin Pasero 已提交
649 650
	static readonly ID = 'workbench.action.openIntroductoryVideosUrl';
	static readonly LABEL = nls.localize('openIntroductoryVideosUrl', "Introductory Videos");
651

652
	private static readonly URL = product.introductoryVideosUrl;
B
Benjamin Pasero 已提交
653
	static readonly AVAILABLE = !!OpenIntroductoryVideosUrlAction.URL;
654 655 656 657 658 659 660 661

	constructor(
		id: string,
		label: string
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
662
	run(): Thenable<void> {
663 664 665
		window.open(OpenIntroductoryVideosUrlAction.URL);
		return null;
	}
666
}
667

668 669
export class OpenTipsAndTricksUrlAction extends Action {

B
Benjamin Pasero 已提交
670 671
	static readonly ID = 'workbench.action.openTipsAndTricksUrl';
	static readonly LABEL = nls.localize('openTipsAndTricksUrl', "Tips and Tricks");
672

673
	private static readonly URL = product.tipsAndTricksUrl;
B
Benjamin Pasero 已提交
674
	static readonly AVAILABLE = !!OpenTipsAndTricksUrlAction.URL;
675 676 677 678 679 680 681 682

	constructor(
		id: string,
		label: string
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
683
	run(): Thenable<void> {
684 685 686 687 688
		window.open(OpenTipsAndTricksUrlAction.URL);
		return null;
	}
}

689 690
export class ToggleSharedProcessAction extends Action {

691
	static readonly ID = 'workbench.action.toggleSharedProcess';
692 693 694 695 696 697
	static LABEL = nls.localize('toggleSharedProcess', "Toggle Shared Process");

	constructor(id: string, label: string, @IWindowsService private windowsService: IWindowsService) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
698
	run(): Thenable<void> {
699 700
		return this.windowsService.toggleSharedProcess();
	}
701 702
}

703
export const enum Direction {
S
sj.hwang 已提交
704 705 706
	Next,
	Previous,
}
707

S
sj.hwang 已提交
708
export abstract class BaseNavigationAction extends Action {
709

710
	constructor(
S
sj.hwang 已提交
711 712
		id: string,
		label: string,
B
Benjamin Pasero 已提交
713
		@IEditorGroupsService protected editorGroupService: IEditorGroupsService,
S
sj.hwang 已提交
714 715 716 717 718 719 720
		@IPanelService protected panelService: IPanelService,
		@IPartService protected partService: IPartService,
		@IViewletService protected viewletService: IViewletService
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
721
	run(): Thenable<any> {
S
sj.hwang 已提交
722 723 724 725
		const isEditorFocus = this.partService.hasFocus(Parts.EDITOR_PART);
		const isPanelFocus = this.partService.hasFocus(Parts.PANEL_PART);
		const isSidebarFocus = this.partService.hasFocus(Parts.SIDEBAR_PART);

726 727
		const isSidebarPositionLeft = this.partService.getSideBarPosition() === PartPosition.LEFT;
		const isPanelPositionDown = this.partService.getPanelPosition() === PartPosition.BOTTOM;
S
sj.hwang 已提交
728 729

		if (isEditorFocus) {
730
			return this.navigateOnEditorFocus(isSidebarPositionLeft, isPanelPositionDown);
731 732
		}

S
sj.hwang 已提交
733
		if (isPanelFocus) {
734
			return this.navigateOnPanelFocus(isSidebarPositionLeft, isPanelPositionDown);
735 736
		}

S
sj.hwang 已提交
737
		if (isSidebarFocus) {
738
			return this.navigateOnSidebarFocus(isSidebarPositionLeft, isPanelPositionDown);
739 740
		}

B
Benjamin Pasero 已提交
741
		return Promise.resolve(false);
742 743
	}

B
Benjamin Pasero 已提交
744 745
	protected navigateOnEditorFocus(_isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IViewlet | IPanel> {
		return Promise.resolve(true);
746 747
	}

B
Benjamin Pasero 已提交
748 749
	protected navigateOnPanelFocus(_isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IPanel> {
		return Promise.resolve(true);
750 751
	}

B
Benjamin Pasero 已提交
752 753
	protected navigateOnSidebarFocus(_isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IViewlet> {
		return Promise.resolve(true);
754 755
	}

B
Benjamin Pasero 已提交
756
	protected navigateToPanel(): Thenable<IPanel | boolean> {
S
sj.hwang 已提交
757
		if (!this.partService.isVisible(Parts.PANEL_PART)) {
B
Benjamin Pasero 已提交
758
			return Promise.resolve(false);
759 760
		}

S
sj.hwang 已提交
761
		const activePanelId = this.panelService.getActivePanel().getId();
B
Benjamin Pasero 已提交
762

S
sj.hwang 已提交
763
		return this.panelService.openPanel(activePanelId, true);
764 765
	}

B
Benjamin Pasero 已提交
766
	protected navigateToSidebar(): Promise<IViewlet | boolean> {
S
sj.hwang 已提交
767
		if (!this.partService.isVisible(Parts.SIDEBAR_PART)) {
B
Benjamin Pasero 已提交
768
			return Promise.resolve(false);
769 770
		}

S
sj.hwang 已提交
771
		const activeViewletId = this.viewletService.getActiveViewlet().getId();
B
Benjamin Pasero 已提交
772

S
sj.hwang 已提交
773
		return this.viewletService.openViewlet(activeViewletId, true);
774 775
	}

B
Benjamin Pasero 已提交
776
	protected navigateAcrossEditorGroup(direction: GroupDirection): Promise<boolean> {
B
Benjamin Pasero 已提交
777 778 779
		return this.doNavigateToEditorGroup({ direction });
	}

B
Benjamin Pasero 已提交
780
	protected navigateToEditorGroup(location: GroupLocation): Promise<boolean> {
B
Benjamin Pasero 已提交
781 782 783
		return this.doNavigateToEditorGroup({ location });
	}

B
Benjamin Pasero 已提交
784
	private doNavigateToEditorGroup(scope: IFindGroupScope): Promise<boolean> {
B
Benjamin Pasero 已提交
785 786 787
		const targetGroup = this.editorGroupService.findGroup(scope, this.editorGroupService.activeGroup);
		if (targetGroup) {
			targetGroup.focus();
788

B
Benjamin Pasero 已提交
789
			return Promise.resolve(true);
790 791
		}

B
Benjamin Pasero 已提交
792
		return Promise.resolve(false);
793 794
	}
}
S
sj.hwang 已提交
795 796 797

export class NavigateLeftAction extends BaseNavigationAction {

B
Benjamin Pasero 已提交
798 799
	static readonly ID = 'workbench.action.navigateLeft';
	static readonly LABEL = nls.localize('navigateLeft', "Navigate to the View on the Left");
S
sj.hwang 已提交
800 801 802 803

	constructor(
		id: string,
		label: string,
B
Benjamin Pasero 已提交
804
		@IEditorGroupsService editorGroupService: IEditorGroupsService,
S
sj.hwang 已提交
805 806 807 808
		@IPanelService panelService: IPanelService,
		@IPartService partService: IPartService,
		@IViewletService viewletService: IViewletService
	) {
B
Benjamin Pasero 已提交
809
		super(id, label, editorGroupService, panelService, partService, viewletService);
S
sj.hwang 已提交
810 811
	}

B
Benjamin Pasero 已提交
812
	protected navigateOnEditorFocus(isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IViewlet> {
813
		return this.navigateAcrossEditorGroup(GroupDirection.LEFT)
814
			.then(didNavigate => {
815
				if (didNavigate) {
B
Benjamin Pasero 已提交
816
					return Promise.resolve(true);
817 818 819
				}

				if (isSidebarPositionLeft) {
820 821
					return this.navigateToSidebar();
				}
822

B
Benjamin Pasero 已提交
823
				return Promise.resolve(false);
824
			});
S
sj.hwang 已提交
825 826
	}

B
Benjamin Pasero 已提交
827
	protected navigateOnPanelFocus(isSidebarPositionLeft: boolean, isPanelPositionDown: boolean): Promise<boolean | IViewlet> {
828
		if (isPanelPositionDown && isSidebarPositionLeft) {
S
sj.hwang 已提交
829 830
			return this.navigateToSidebar();
		}
B
Benjamin Pasero 已提交
831

832
		if (!isPanelPositionDown) {
B
Benjamin Pasero 已提交
833
			return this.navigateToEditorGroup(GroupLocation.LAST);
834 835
		}

B
Benjamin Pasero 已提交
836
		return Promise.resolve(false);
S
sj.hwang 已提交
837 838
	}

B
Benjamin Pasero 已提交
839
	protected navigateOnSidebarFocus(isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean> {
840
		if (!isSidebarPositionLeft) {
B
Benjamin Pasero 已提交
841
			return this.navigateToEditorGroup(GroupLocation.LAST);
S
sj.hwang 已提交
842
		}
B
Benjamin Pasero 已提交
843

B
Benjamin Pasero 已提交
844
		return Promise.resolve(false);
S
sj.hwang 已提交
845 846
	}
}
847 848 849

export class NavigateRightAction extends BaseNavigationAction {

B
Benjamin Pasero 已提交
850 851
	static readonly ID = 'workbench.action.navigateRight';
	static readonly LABEL = nls.localize('navigateRight', "Navigate to the View on the Right");
852 853 854 855

	constructor(
		id: string,
		label: string,
B
Benjamin Pasero 已提交
856
		@IEditorGroupsService editorGroupService: IEditorGroupsService,
857 858 859 860
		@IPanelService panelService: IPanelService,
		@IPartService partService: IPartService,
		@IViewletService viewletService: IViewletService
	) {
B
Benjamin Pasero 已提交
861
		super(id, label, editorGroupService, panelService, partService, viewletService);
862 863
	}

B
Benjamin Pasero 已提交
864
	protected navigateOnEditorFocus(isSidebarPositionLeft: boolean, isPanelPositionDown: boolean): Promise<boolean | IViewlet | IPanel> {
865
		return this.navigateAcrossEditorGroup(GroupDirection.RIGHT)
866
			.then(didNavigate => {
867
				if (didNavigate) {
B
Benjamin Pasero 已提交
868
					return Promise.resolve(true);
869 870 871 872 873 874 875
				}

				if (!isPanelPositionDown) {
					return this.navigateToPanel();
				}

				if (!isSidebarPositionLeft) {
876 877
					return this.navigateToSidebar();
				}
878

B
Benjamin Pasero 已提交
879
				return Promise.resolve(false);
880
			});
881 882
	}

B
Benjamin Pasero 已提交
883
	protected navigateOnPanelFocus(isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IViewlet> {
884 885 886
		if (!isSidebarPositionLeft) {
			return this.navigateToSidebar();
		}
B
Benjamin Pasero 已提交
887

B
Benjamin Pasero 已提交
888
		return Promise.resolve(false);
889 890
	}

B
Benjamin Pasero 已提交
891
	protected navigateOnSidebarFocus(isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean> {
892
		if (isSidebarPositionLeft) {
B
Benjamin Pasero 已提交
893
			return this.navigateToEditorGroup(GroupLocation.FIRST);
894
		}
B
Benjamin Pasero 已提交
895

B
Benjamin Pasero 已提交
896
		return Promise.resolve(false);
897 898
	}
}
S
sj.hwang 已提交
899 900 901

export class NavigateUpAction extends BaseNavigationAction {

B
Benjamin Pasero 已提交
902 903
	static readonly ID = 'workbench.action.navigateUp';
	static readonly LABEL = nls.localize('navigateUp', "Navigate to the View Above");
S
sj.hwang 已提交
904 905 906 907

	constructor(
		id: string,
		label: string,
B
Benjamin Pasero 已提交
908
		@IEditorGroupsService editorGroupService: IEditorGroupsService,
S
sj.hwang 已提交
909 910 911 912
		@IPanelService panelService: IPanelService,
		@IPartService partService: IPartService,
		@IViewletService viewletService: IViewletService
	) {
B
Benjamin Pasero 已提交
913
		super(id, label, editorGroupService, panelService, partService, viewletService);
S
sj.hwang 已提交
914 915
	}

B
Benjamin Pasero 已提交
916
	protected navigateOnEditorFocus(_isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean> {
917
		return this.navigateAcrossEditorGroup(GroupDirection.UP);
S
sj.hwang 已提交
918 919
	}

B
Benjamin Pasero 已提交
920
	protected navigateOnPanelFocus(_isSidebarPositionLeft: boolean, isPanelPositionDown: boolean): Promise<boolean> {
921
		if (isPanelPositionDown) {
B
Benjamin Pasero 已提交
922
			return this.navigateToEditorGroup(GroupLocation.LAST);
S
sj.hwang 已提交
923
		}
924

B
Benjamin Pasero 已提交
925
		return Promise.resolve(false);
S
sj.hwang 已提交
926 927
	}
}
S
sj.hwang 已提交
928 929 930

export class NavigateDownAction extends BaseNavigationAction {

B
Benjamin Pasero 已提交
931 932
	static readonly ID = 'workbench.action.navigateDown';
	static readonly LABEL = nls.localize('navigateDown', "Navigate to the View Below");
S
sj.hwang 已提交
933 934 935 936

	constructor(
		id: string,
		label: string,
B
Benjamin Pasero 已提交
937
		@IEditorGroupsService editorGroupService: IEditorGroupsService,
S
sj.hwang 已提交
938 939 940 941
		@IPanelService panelService: IPanelService,
		@IPartService partService: IPartService,
		@IViewletService viewletService: IViewletService
	) {
B
Benjamin Pasero 已提交
942
		super(id, label, editorGroupService, panelService, partService, viewletService);
S
sj.hwang 已提交
943 944
	}

B
Benjamin Pasero 已提交
945
	protected navigateOnEditorFocus(_isSidebarPositionLeft: boolean, isPanelPositionDown: boolean): Promise<boolean | IPanel> {
946
		return this.navigateAcrossEditorGroup(GroupDirection.DOWN)
947 948
			.then(didNavigate => {
				if (didNavigate) {
B
Benjamin Pasero 已提交
949
					return Promise.resolve(true);
950
				}
951 952 953 954 955

				if (isPanelPositionDown) {
					return this.navigateToPanel();
				}

B
Benjamin Pasero 已提交
956
				return Promise.resolve(false);
957
			});
S
sj.hwang 已提交
958 959
	}
}
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979

// Resize focused view actions
export abstract class BaseResizeViewAction extends Action {

	// This is a media-size percentage
	protected static RESIZE_INCREMENT = 6.5;

	constructor(
		id: string,
		label: string,
		@IPartService protected partService: IPartService
	) {
		super(id, label);
	}

	protected resizePart(sizeChange: number): void {
		const isEditorFocus = this.partService.hasFocus(Parts.EDITOR_PART);
		const isSidebarFocus = this.partService.hasFocus(Parts.SIDEBAR_PART);
		const isPanelFocus = this.partService.hasFocus(Parts.PANEL_PART);

B
Benjamin Pasero 已提交
980
		let part: Parts;
981
		if (isSidebarFocus) {
B
Benjamin Pasero 已提交
982 983 984 985 986
			part = Parts.SIDEBAR_PART;
		} else if (isPanelFocus) {
			part = Parts.PANEL_PART;
		} else if (isEditorFocus) {
			part = Parts.EDITOR_PART;
987
		}
B
Benjamin Pasero 已提交
988 989 990

		if (part) {
			this.partService.resizePart(part, sizeChange);
991 992 993 994 995 996
		}
	}
}

export class IncreaseViewSizeAction extends BaseResizeViewAction {

B
Benjamin Pasero 已提交
997 998
	static readonly ID = 'workbench.action.increaseViewSize';
	static readonly LABEL = nls.localize('increaseViewSize', "Increase Current View Size");
999 1000 1001 1002 1003 1004 1005 1006 1007

	constructor(
		id: string,
		label: string,
		@IPartService partService: IPartService
	) {
		super(id, label, partService);
	}

B
Benjamin Pasero 已提交
1008
	run(): Thenable<boolean> {
1009
		this.resizePart(BaseResizeViewAction.RESIZE_INCREMENT);
B
Benjamin Pasero 已提交
1010
		return Promise.resolve(true);
1011 1012 1013 1014 1015
	}
}

export class DecreaseViewSizeAction extends BaseResizeViewAction {

B
Benjamin Pasero 已提交
1016 1017
	static readonly ID = 'workbench.action.decreaseViewSize';
	static readonly LABEL = nls.localize('decreaseViewSize', "Decrease Current View Size");
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027

	constructor(
		id: string,
		label: string,
		@IPartService partService: IPartService

	) {
		super(id, label, partService);
	}

B
Benjamin Pasero 已提交
1028
	run(): Thenable<boolean> {
1029
		this.resizePart(-BaseResizeViewAction.RESIZE_INCREMENT);
B
Benjamin Pasero 已提交
1030
		return Promise.resolve(true);
1031
	}
1032 1033
}

1034 1035 1036 1037 1038 1039
export class NewWindowTab extends Action {

	static readonly ID = 'workbench.action.newWindowTab';
	static readonly LABEL = nls.localize('newTab', "New Window Tab");

	constructor(
1040 1041
		_id: string,
		_label: string,
1042 1043 1044 1045 1046
		@IWindowsService private windowsService: IWindowsService
	) {
		super(NewWindowTab.ID, NewWindowTab.LABEL);
	}

B
Benjamin Pasero 已提交
1047
	run(): Thenable<boolean> {
1048 1049 1050 1051
		return this.windowsService.newWindowTab().then(() => true);
	}
}

1052 1053
export class ShowPreviousWindowTab extends Action {

B
Benjamin Pasero 已提交
1054 1055
	static readonly ID = 'workbench.action.showPreviousWindowTab';
	static readonly LABEL = nls.localize('showPreviousTab', "Show Previous Window Tab");
1056 1057

	constructor(
1058 1059
		_id: string,
		_label: string,
1060 1061 1062 1063 1064
		@IWindowsService private windowsService: IWindowsService
	) {
		super(ShowPreviousWindowTab.ID, ShowPreviousWindowTab.LABEL);
	}

B
Benjamin Pasero 已提交
1065
	run(): Thenable<boolean> {
1066 1067 1068 1069 1070 1071
		return this.windowsService.showPreviousWindowTab().then(() => true);
	}
}

export class ShowNextWindowTab extends Action {

B
Benjamin Pasero 已提交
1072 1073
	static readonly ID = 'workbench.action.showNextWindowTab';
	static readonly LABEL = nls.localize('showNextWindowTab', "Show Next Window Tab");
1074 1075

	constructor(
1076 1077
		_id: string,
		_label: string,
1078 1079 1080 1081 1082
		@IWindowsService private windowsService: IWindowsService
	) {
		super(ShowNextWindowTab.ID, ShowNextWindowTab.LABEL);
	}

B
Benjamin Pasero 已提交
1083
	run(): Thenable<boolean> {
1084 1085 1086 1087 1088 1089
		return this.windowsService.showNextWindowTab().then(() => true);
	}
}

export class MoveWindowTabToNewWindow extends Action {

B
Benjamin Pasero 已提交
1090 1091
	static readonly ID = 'workbench.action.moveWindowTabToNewWindow';
	static readonly LABEL = nls.localize('moveWindowTabToNewWindow', "Move Window Tab to New Window");
1092 1093

	constructor(
1094 1095
		_id: string,
		_label: string,
1096 1097 1098 1099 1100
		@IWindowsService private windowsService: IWindowsService
	) {
		super(MoveWindowTabToNewWindow.ID, MoveWindowTabToNewWindow.LABEL);
	}

B
Benjamin Pasero 已提交
1101
	run(): Thenable<boolean> {
1102 1103 1104 1105 1106 1107
		return this.windowsService.moveWindowTabToNewWindow().then(() => true);
	}
}

export class MergeAllWindowTabs extends Action {

B
Benjamin Pasero 已提交
1108 1109
	static readonly ID = 'workbench.action.mergeAllWindowTabs';
	static readonly LABEL = nls.localize('mergeAllWindowTabs', "Merge All Windows");
1110 1111

	constructor(
1112 1113
		_id: string,
		_label: string,
1114 1115 1116 1117 1118
		@IWindowsService private windowsService: IWindowsService
	) {
		super(MergeAllWindowTabs.ID, MergeAllWindowTabs.LABEL);
	}

B
Benjamin Pasero 已提交
1119
	run(): Thenable<boolean> {
1120 1121 1122 1123 1124 1125
		return this.windowsService.mergeAllWindowTabs().then(() => true);
	}
}

export class ToggleWindowTabsBar extends Action {

B
Benjamin Pasero 已提交
1126 1127
	static readonly ID = 'workbench.action.toggleWindowTabsBar';
	static readonly LABEL = nls.localize('toggleWindowTabsBar', "Toggle Window Tabs Bar");
1128 1129

	constructor(
1130 1131
		_id: string,
		_label: string,
1132 1133 1134 1135 1136
		@IWindowsService private windowsService: IWindowsService
	) {
		super(ToggleWindowTabsBar.ID, ToggleWindowTabsBar.LABEL);
	}

B
Benjamin Pasero 已提交
1137
	run(): Thenable<boolean> {
1138 1139
		return this.windowsService.toggleWindowTabsBar().then(() => true);
	}
J
Joao Moreno 已提交
1140 1141
}

S
SteVen Batten 已提交
1142 1143
export class OpenTwitterUrlAction extends Action {

B
Benjamin Pasero 已提交
1144 1145
	static readonly ID = 'workbench.action.openTwitterUrl';
	static LABEL = nls.localize('openTwitterUrl', "Join us on Twitter", product.applicationName);
S
SteVen Batten 已提交
1146 1147 1148 1149 1150 1151 1152 1153

	constructor(
		id: string,
		label: string
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
1154
	run(): Thenable<boolean> {
S
SteVen Batten 已提交
1155
		if (product.twitterUrl) {
B
Benjamin Pasero 已提交
1156
			return Promise.resolve(shell.openExternal(product.twitterUrl));
S
SteVen Batten 已提交
1157 1158
		}

B
Benjamin Pasero 已提交
1159
		return Promise.resolve(false);
S
SteVen Batten 已提交
1160 1161 1162 1163 1164
	}
}

export class OpenRequestFeatureUrlAction extends Action {

B
Benjamin Pasero 已提交
1165 1166
	static readonly ID = 'workbench.action.openRequestFeatureUrl';
	static LABEL = nls.localize('openUserVoiceUrl', "Search Feature Requests");
S
SteVen Batten 已提交
1167 1168 1169 1170 1171 1172 1173 1174

	constructor(
		id: string,
		label: string
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
1175
	run(): Thenable<boolean> {
S
SteVen Batten 已提交
1176
		if (product.requestFeatureUrl) {
B
Benjamin Pasero 已提交
1177
			return Promise.resolve(shell.openExternal(product.requestFeatureUrl));
S
SteVen Batten 已提交
1178 1179
		}

B
Benjamin Pasero 已提交
1180
		return Promise.resolve(false);
S
SteVen Batten 已提交
1181 1182 1183 1184 1185
	}
}

export class OpenLicenseUrlAction extends Action {

B
Benjamin Pasero 已提交
1186 1187
	static readonly ID = 'workbench.action.openLicenseUrl';
	static LABEL = nls.localize('openLicenseUrl', "View License");
S
SteVen Batten 已提交
1188 1189 1190 1191 1192 1193 1194 1195

	constructor(
		id: string,
		label: string
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
1196
	run(): Thenable<boolean> {
S
SteVen Batten 已提交
1197 1198 1199
		if (product.licenseUrl) {
			if (language) {
				const queryArgChar = product.licenseUrl.indexOf('?') > 0 ? '&' : '?';
B
Benjamin Pasero 已提交
1200
				return Promise.resolve(shell.openExternal(`${product.licenseUrl}${queryArgChar}lang=${language}`));
S
SteVen Batten 已提交
1201
			} else {
B
Benjamin Pasero 已提交
1202
				return Promise.resolve(shell.openExternal(product.licenseUrl));
S
SteVen Batten 已提交
1203 1204 1205
			}
		}

B
Benjamin Pasero 已提交
1206
		return Promise.resolve(false);
S
SteVen Batten 已提交
1207 1208 1209 1210 1211 1212
	}
}


export class OpenPrivacyStatementUrlAction extends Action {

B
Benjamin Pasero 已提交
1213 1214
	static readonly ID = 'workbench.action.openPrivacyStatementUrl';
	static LABEL = nls.localize('openPrivacyStatement', "Privacy Statement");
S
SteVen Batten 已提交
1215 1216 1217 1218 1219 1220 1221 1222

	constructor(
		id: string,
		label: string
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
1223
	run(): Thenable<boolean> {
S
SteVen Batten 已提交
1224 1225 1226
		if (product.privacyStatementUrl) {
			if (language) {
				const queryArgChar = product.privacyStatementUrl.indexOf('?') > 0 ? '&' : '?';
B
Benjamin Pasero 已提交
1227
				return Promise.resolve(shell.openExternal(`${product.privacyStatementUrl}${queryArgChar}lang=${language}`));
S
SteVen Batten 已提交
1228
			} else {
B
Benjamin Pasero 已提交
1229
				return Promise.resolve(shell.openExternal(product.privacyStatementUrl));
S
SteVen Batten 已提交
1230 1231 1232 1233
			}
		}


B
Benjamin Pasero 已提交
1234
		return Promise.resolve(false);
S
SteVen Batten 已提交
1235 1236 1237
	}
}

J
Joao Moreno 已提交
1238 1239
export class ShowAboutDialogAction extends Action {

B
Benjamin Pasero 已提交
1240 1241
	static readonly ID = 'workbench.action.showAboutDialog';
	static LABEL = nls.localize('about', "About {0}", product.applicationName);
J
Joao Moreno 已提交
1242 1243 1244 1245 1246 1247 1248 1249 1250

	constructor(
		id: string,
		label: string,
		@IWindowsService private windowsService: IWindowsService
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
1251
	run(): Thenable<void> {
J
Joao Moreno 已提交
1252 1253
		return this.windowsService.openAboutDialog();
	}
J
Joao Moreno 已提交
1254 1255 1256 1257
}

export class InspectContextKeysAction extends Action {

B
Benjamin Pasero 已提交
1258 1259
	static readonly ID = 'workbench.action.inspectContextKeys';
	static LABEL = nls.localize('inspect context keys', "Inspect Context Keys");
J
Joao Moreno 已提交
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269

	constructor(
		id: string,
		label: string,
		@IContextKeyService private contextKeyService: IContextKeyService,
		@IWindowService private windowService: IWindowService,
	) {
		super(id, label);
	}

B
Benjamin Pasero 已提交
1270
	run(): Thenable<void> {
J
Joao Moreno 已提交
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
		const disposables: IDisposable[] = [];

		const stylesheet = createStyleSheet();
		disposables.push(toDisposable(() => stylesheet.parentNode.removeChild(stylesheet)));
		createCSSRule('*', 'cursor: crosshair !important;', stylesheet);

		const hoverFeedback = document.createElement('div');
		document.body.appendChild(hoverFeedback);
		disposables.push(toDisposable(() => document.body.removeChild(hoverFeedback)));

		hoverFeedback.style.position = 'absolute';
		hoverFeedback.style.pointerEvents = 'none';
		hoverFeedback.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
		hoverFeedback.style.zIndex = '1000';

		const onMouseMove = domEvent(document.body, 'mousemove', true);
		disposables.push(onMouseMove(e => {
			const target = e.target as HTMLElement;
			const position = getDomNodePagePosition(target);

			hoverFeedback.style.top = `${position.top}px`;
			hoverFeedback.style.left = `${position.left}px`;
			hoverFeedback.style.width = `${position.width}px`;
			hoverFeedback.style.height = `${position.height}px`;
		}));

		const onMouseDown = once(domEvent(document.body, 'mousedown', true));
		onMouseDown(e => { e.preventDefault(); e.stopPropagation(); }, null, disposables);

		const onMouseUp = once(domEvent(document.body, 'mouseup', true));
		onMouseUp(e => {
			e.preventDefault();
			e.stopPropagation();

			const context = this.contextKeyService.getContext(e.target as HTMLElement) as Context;
			console.log(context.collectAllValues());
			this.windowService.openDevTools();

			dispose(disposables);
		}, null, disposables);

B
Benjamin Pasero 已提交
1312
		return Promise.resolve(null);
J
Joao Moreno 已提交
1313
	}
I
isidor 已提交
1314
}