mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 09:42:34 -05:00
Merge VS Code 1.31.1 (#4283)
This commit is contained in:
@@ -45,7 +45,7 @@ export class ActionBarContributor {
|
||||
/**
|
||||
* Can return a specific IActionItem to render the given action.
|
||||
*/
|
||||
getActionItem(context: any, action: Action): BaseActionItem {
|
||||
getActionItem(context: any, action: Action): BaseActionItem | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ export class ActionBarContributor {
|
||||
* Some predefined scopes to contribute actions to
|
||||
*/
|
||||
export const Scope = {
|
||||
|
||||
/**
|
||||
* Actions inside tree widgets.
|
||||
*/
|
||||
@@ -81,8 +82,7 @@ export class ContributableActionProvider implements IActionProvider {
|
||||
const context = this.toContext(tree, element);
|
||||
|
||||
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
||||
for (let i = 0; i < contributors.length; i++) {
|
||||
const contributor = contributors[i];
|
||||
for (const contributor of contributors) {
|
||||
if (contributor.hasActions(context)) {
|
||||
return true;
|
||||
}
|
||||
@@ -97,8 +97,7 @@ export class ContributableActionProvider implements IActionProvider {
|
||||
|
||||
// Collect Actions
|
||||
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
||||
for (let i = 0; i < contributors.length; i++) {
|
||||
const contributor = contributors[i];
|
||||
for (const contributor of contributors) {
|
||||
if (contributor.hasActions(context)) {
|
||||
actions.push(...contributor.getActions(context));
|
||||
}
|
||||
@@ -111,8 +110,7 @@ export class ContributableActionProvider implements IActionProvider {
|
||||
const context = this.toContext(tree, element);
|
||||
|
||||
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
||||
for (let i = 0; i < contributors.length; i++) {
|
||||
const contributor = contributors[i];
|
||||
for (const contributor of contributors) {
|
||||
if (contributor.hasSecondaryActions(context)) {
|
||||
return true;
|
||||
}
|
||||
@@ -127,8 +125,7 @@ export class ContributableActionProvider implements IActionProvider {
|
||||
|
||||
// Collect Actions
|
||||
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
||||
for (let i = 0; i < contributors.length; i++) {
|
||||
const contributor = contributors[i];
|
||||
for (const contributor of contributors) {
|
||||
if (contributor.hasSecondaryActions(context)) {
|
||||
actions.push(...contributor.getSecondaryActions(context));
|
||||
}
|
||||
@@ -137,7 +134,7 @@ export class ContributableActionProvider implements IActionProvider {
|
||||
return prepareActions(actions);
|
||||
}
|
||||
|
||||
getActionItem(tree: ITree, element: any, action: Action): BaseActionItem {
|
||||
getActionItem(tree: ITree, element: any, action: Action): BaseActionItem | null {
|
||||
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
||||
const context = this.toContext(tree, element);
|
||||
|
||||
@@ -225,7 +222,7 @@ export interface IActionBarRegistry {
|
||||
* Goes through all action bar contributors and asks them for contributed action item for
|
||||
* the provided scope and context.
|
||||
*/
|
||||
getActionItemForContext(scope: string, context: any, action: Action): BaseActionItem;
|
||||
getActionItemForContext(scope: string, context: any, action: Action): BaseActionItem | null;
|
||||
|
||||
/**
|
||||
* Registers an Actionbar contributor. It will be called to contribute actions to all the action bars
|
||||
@@ -250,7 +247,7 @@ class ActionBarRegistry implements IActionBarRegistry {
|
||||
this.instantiationService = service;
|
||||
|
||||
while (this.actionBarContributorConstructors.length > 0) {
|
||||
const entry = this.actionBarContributorConstructors.shift();
|
||||
const entry = this.actionBarContributorConstructors.shift()!;
|
||||
this.createActionBarContributor(entry.scope, entry.ctor);
|
||||
}
|
||||
}
|
||||
@@ -298,10 +295,9 @@ class ActionBarRegistry implements IActionBarRegistry {
|
||||
return actions;
|
||||
}
|
||||
|
||||
getActionItemForContext(scope: string, context: any, action: Action): BaseActionItem {
|
||||
getActionItemForContext(scope: string, context: any, action: Action): BaseActionItem | null {
|
||||
const contributors = this.getContributors(scope);
|
||||
for (let i = 0; i < contributors.length; i++) {
|
||||
const contributor = contributors[i];
|
||||
for (const contributor of contributors) {
|
||||
const item = contributor.getActionItem(context, action);
|
||||
if (item) {
|
||||
return item;
|
||||
|
||||
511
src/vs/workbench/browser/actions/layoutActions.ts
Normal file
511
src/vs/workbench/browser/actions/layoutActions.ts
Normal file
@@ -0,0 +1,511 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/actions';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IPartService, Parts, Position } from 'vs/workbench/services/part/common/partService';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IEditorGroupsService, GroupOrientation } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { MenuBarVisibility } from 'vs/platform/windows/common/windows';
|
||||
import { isWindows, isLinux } from 'vs/base/common/platform';
|
||||
import { IsMacContext } from 'vs/platform/workbench/common/contextkeys';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { InEditorZenModeContext } from 'vs/workbench/common/editor';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
const viewCategory = nls.localize('view', "View");
|
||||
|
||||
// --- Toggle Activity Bar
|
||||
|
||||
export class ToggleActivityBarVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleActivityBarVisibility';
|
||||
static readonly LABEL = nls.localize('toggleActivityBar', "Toggle Activity Bar Visibility");
|
||||
|
||||
private static readonly activityBarVisibleKey = 'workbench.activityBar.visible';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const visibility = this.partService.isVisible(Parts.ACTIVITYBAR_PART);
|
||||
const newVisibilityValue = !visibility;
|
||||
|
||||
return this.configurationService.updateValue(ToggleActivityBarVisibilityAction.activityBarVisibleKey, newVisibilityValue, ConfigurationTarget.USER);
|
||||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, ToggleActivityBarVisibilityAction.LABEL), 'View: Toggle Activity Bar Visibility', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
command: {
|
||||
id: ToggleActivityBarVisibilityAction.ID,
|
||||
title: nls.localize({ key: 'miToggleActivityBar', comment: ['&& denotes a mnemonic'] }, "Toggle &&Activity Bar")
|
||||
},
|
||||
order: 4
|
||||
});
|
||||
|
||||
// --- Toggle Centered Layout
|
||||
|
||||
class ToggleCenteredLayout extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleCenteredLayout';
|
||||
static readonly LABEL = nls.localize('toggleCenteredLayout', "Toggle Centered Layout");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
this.partService.centerEditorLayout(!this.partService.isEditorLayoutCentered());
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCenteredLayout, ToggleCenteredLayout.ID, ToggleCenteredLayout.LABEL), 'View: Toggle Centered Layout', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '1_toggle_view',
|
||||
command: {
|
||||
id: ToggleCenteredLayout.ID,
|
||||
title: nls.localize('miToggleCenteredLayout', "Toggle Centered Layout")
|
||||
},
|
||||
order: 3
|
||||
});
|
||||
|
||||
// --- Toggle Editor Layout
|
||||
|
||||
export class ToggleEditorLayoutAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleEditorGroupLayout';
|
||||
static readonly LABEL = nls.localize('flipLayout', "Toggle Vertical/Horizontal Editor Layout");
|
||||
|
||||
private toDispose: IDisposable[];
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.toDispose = [];
|
||||
|
||||
this.class = 'flip-editor-layout';
|
||||
this.updateEnablement();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this.toDispose.push(this.editorGroupService.onDidAddGroup(() => this.updateEnablement()));
|
||||
this.toDispose.push(this.editorGroupService.onDidRemoveGroup(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
private updateEnablement(): void {
|
||||
this.enabled = this.editorGroupService.count > 1;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const newOrientation = (this.editorGroupService.orientation === GroupOrientation.VERTICAL) ? GroupOrientation.HORIZONTAL : GroupOrientation.VERTICAL;
|
||||
this.editorGroupService.setGroupOrientation(newOrientation);
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.toDispose = dispose(this.toDispose);
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
CommandsRegistry.registerCommand('_workbench.editor.setGroupOrientation', function (accessor: ServicesAccessor, args: [GroupOrientation]) {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
const [orientation] = args;
|
||||
|
||||
editorGroupService.setGroupOrientation(orientation);
|
||||
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
|
||||
const group = viewCategory;
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleEditorLayoutAction, ToggleEditorLayoutAction.ID, ToggleEditorLayoutAction.LABEL, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_0, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_0 } }), 'View: Flip Editor Group Layout', group);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, {
|
||||
group: 'z_flip',
|
||||
command: {
|
||||
id: ToggleEditorLayoutAction.ID,
|
||||
title: nls.localize({ key: 'miToggleEditorLayout', comment: ['&& denotes a mnemonic'] }, "Flip &&Layout")
|
||||
},
|
||||
order: 1
|
||||
});
|
||||
|
||||
// --- Toggle Sidebar Position
|
||||
|
||||
export class ToggleSidebarPositionAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleSidebarPosition';
|
||||
static readonly LABEL = nls.localize('toggleSidebarPosition', "Toggle Side Bar Position");
|
||||
|
||||
private static readonly sidebarPositionConfigurationKey = 'workbench.sideBar.location';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService && !!this.configurationService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const position = this.partService.getSideBarPosition();
|
||||
const newPositionValue = (position === Position.LEFT) ? 'right' : 'left';
|
||||
|
||||
return this.configurationService.updateValue(ToggleSidebarPositionAction.sidebarPositionConfigurationKey, newPositionValue, ConfigurationTarget.USER);
|
||||
}
|
||||
|
||||
static getLabel(partService: IPartService): string {
|
||||
return partService.getSideBarPosition() === Position.LEFT ? nls.localize('moveSidebarRight', "Move Side Bar Right") : nls.localize('moveSidebarLeft', "Move Side Bar Left");
|
||||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.LABEL), 'View: Toggle Side Bar Position', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
command: {
|
||||
id: ToggleSidebarPositionAction.ID,
|
||||
title: nls.localize({ key: 'miMoveSidebarLeftRight', comment: ['&& denotes a mnemonic'] }, "&&Move Side Bar Left/Right")
|
||||
},
|
||||
order: 2
|
||||
});
|
||||
|
||||
// --- Toggle Sidebar Visibility
|
||||
|
||||
export class ToggleEditorVisibilityAction extends Action {
|
||||
static readonly ID = 'workbench.action.toggleEditorVisibility';
|
||||
static readonly LABEL = nls.localize('toggleEditor', "Toggle Editor Area");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const hideEditor = this.partService.isVisible(Parts.EDITOR_PART);
|
||||
this.partService.setEditorHidden(hideEditor);
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleEditorVisibilityAction, ToggleEditorVisibilityAction.ID, ToggleEditorVisibilityAction.LABEL), 'View: Toggle Editor Area Visibility', viewCategory, ContextKeyExpr.equals('config.workbench.useExperimentalGridLayout', true));
|
||||
|
||||
|
||||
export class ToggleSidebarVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleSidebarVisibility';
|
||||
static readonly LABEL = nls.localize('toggleSidebar', "Toggle Side Bar Visibility");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const hideSidebar = this.partService.isVisible(Parts.SIDEBAR_PART);
|
||||
this.partService.setSideBarHidden(hideSidebar);
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSidebarVisibilityAction, ToggleSidebarVisibilityAction.ID, ToggleSidebarVisibilityAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_B }), 'View: Toggle Side Bar Visibility', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
command: {
|
||||
id: ToggleSidebarVisibilityAction.ID,
|
||||
title: nls.localize({ key: 'miToggleSidebar', comment: ['&& denotes a mnemonic'] }, "&&Toggle Side Bar")
|
||||
},
|
||||
order: 1
|
||||
});
|
||||
|
||||
// --- Toggle Statusbar Visibility
|
||||
|
||||
class ToggleStatusbarVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleStatusbarVisibility';
|
||||
static readonly LABEL = nls.localize('toggleStatusbar', "Toggle Status Bar Visibility");
|
||||
|
||||
private static readonly statusbarVisibleKey = 'workbench.statusBar.visible';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const visibility = this.partService.isVisible(Parts.STATUSBAR_PART);
|
||||
const newVisibilityValue = !visibility;
|
||||
|
||||
return this.configurationService.updateValue(ToggleStatusbarVisibilityAction.statusbarVisibleKey, newVisibilityValue, ConfigurationTarget.USER);
|
||||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleStatusbarVisibilityAction, ToggleStatusbarVisibilityAction.ID, ToggleStatusbarVisibilityAction.LABEL), 'View: Toggle Status Bar Visibility', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
command: {
|
||||
id: ToggleStatusbarVisibilityAction.ID,
|
||||
title: nls.localize({ key: 'miToggleStatusbar', comment: ['&& denotes a mnemonic'] }, "&&Toggle Status Bar")
|
||||
},
|
||||
order: 3
|
||||
});
|
||||
|
||||
// --- Toggle Tabs Visibility
|
||||
|
||||
class ToggleTabsVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleTabsVisibility';
|
||||
static readonly LABEL = nls.localize('toggleTabs', "Toggle Tab Visibility");
|
||||
|
||||
private static readonly tabsVisibleKey = 'workbench.editor.showTabs';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const visibility = this.configurationService.getValue<string>(ToggleTabsVisibilityAction.tabsVisibleKey);
|
||||
const newVisibilityValue = !visibility;
|
||||
|
||||
return this.configurationService.updateValue(ToggleTabsVisibilityAction.tabsVisibleKey, newVisibilityValue);
|
||||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTabsVisibilityAction, ToggleTabsVisibilityAction.ID, ToggleTabsVisibilityAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W }), 'View: Toggle Tab Visibility', viewCategory);
|
||||
|
||||
// --- Toggle Zen Mode
|
||||
|
||||
class ToggleZenMode extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleZenMode';
|
||||
static readonly LABEL = nls.localize('toggleZenMode', "Toggle Zen Mode");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
this.partService.toggleZenMode();
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleZenMode, ToggleZenMode.ID, ToggleZenMode.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_Z) }), 'View: Toggle Zen Mode', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '1_toggle_view',
|
||||
command: {
|
||||
id: ToggleZenMode.ID,
|
||||
title: nls.localize('miToggleZenMode', "Toggle Zen Mode")
|
||||
},
|
||||
order: 2
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.action.exitZenMode',
|
||||
weight: KeybindingWeight.EditorContrib - 1000,
|
||||
handler(accessor: ServicesAccessor) {
|
||||
const partService = accessor.get(IPartService);
|
||||
partService.toggleZenMode();
|
||||
},
|
||||
when: InEditorZenModeContext,
|
||||
primary: KeyChord(KeyCode.Escape, KeyCode.Escape)
|
||||
});
|
||||
|
||||
// --- Toggle Menu Bar
|
||||
|
||||
export class ToggleMenuBarAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleMenuBar';
|
||||
static LABEL = nls.localize('toggleMenuBar', "Toggle Menu Bar");
|
||||
|
||||
private static readonly menuBarVisibilityKey = 'window.menuBarVisibility';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Promise<void> {
|
||||
let currentVisibilityValue = this.configurationService.getValue<MenuBarVisibility>(ToggleMenuBarAction.menuBarVisibilityKey);
|
||||
if (typeof currentVisibilityValue !== 'string') {
|
||||
currentVisibilityValue = 'default';
|
||||
}
|
||||
|
||||
let newVisibilityValue: string;
|
||||
if (currentVisibilityValue === 'visible' || currentVisibilityValue === 'default') {
|
||||
newVisibilityValue = 'toggle';
|
||||
} else {
|
||||
newVisibilityValue = 'default';
|
||||
}
|
||||
|
||||
this.configurationService.updateValue(ToggleMenuBarAction.menuBarVisibilityKey, newVisibilityValue, ConfigurationTarget.USER);
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
if (isWindows || isLinux) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMenuBarAction, ToggleMenuBarAction.ID, ToggleMenuBarAction.LABEL), 'View: Toggle Menu Bar', viewCategory);
|
||||
}
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '1_toggle_view',
|
||||
command: {
|
||||
id: ToggleMenuBarAction.ID,
|
||||
title: nls.localize({ key: 'miToggleMenuBar', comment: ['&& denotes a mnemonic'] }, "Toggle Menu &&Bar")
|
||||
},
|
||||
when: IsMacContext.toNegated(),
|
||||
order: 4
|
||||
});
|
||||
|
||||
// --- Resize View
|
||||
|
||||
export abstract class BaseResizeViewAction extends Action {
|
||||
|
||||
protected static RESIZE_INCREMENT = 6.5; // This is a media-size percentage
|
||||
|
||||
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);
|
||||
|
||||
let part: Parts | undefined;
|
||||
if (isSidebarFocus) {
|
||||
part = Parts.SIDEBAR_PART;
|
||||
} else if (isPanelFocus) {
|
||||
part = Parts.PANEL_PART;
|
||||
} else if (isEditorFocus) {
|
||||
part = Parts.EDITOR_PART;
|
||||
}
|
||||
|
||||
if (part) {
|
||||
this.partService.resizePart(part, sizeChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class IncreaseViewSizeAction extends BaseResizeViewAction {
|
||||
|
||||
static readonly ID = 'workbench.action.increaseViewSize';
|
||||
static readonly LABEL = nls.localize('increaseViewSize', "Increase Current View Size");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService partService: IPartService
|
||||
) {
|
||||
super(id, label, partService);
|
||||
}
|
||||
|
||||
run(): Promise<boolean> {
|
||||
this.resizePart(BaseResizeViewAction.RESIZE_INCREMENT);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
}
|
||||
|
||||
export class DecreaseViewSizeAction extends BaseResizeViewAction {
|
||||
|
||||
static readonly ID = 'workbench.action.decreaseViewSize';
|
||||
static readonly LABEL = nls.localize('decreaseViewSize', "Decrease Current View Size");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService partService: IPartService
|
||||
|
||||
) {
|
||||
super(id, label, partService);
|
||||
}
|
||||
|
||||
run(): Promise<boolean> {
|
||||
this.resizePart(-BaseResizeViewAction.RESIZE_INCREMENT);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(IncreaseViewSizeAction, IncreaseViewSizeAction.ID, IncreaseViewSizeAction.LABEL, undefined), 'View: Increase Current View Size', viewCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(DecreaseViewSizeAction, DecreaseViewSizeAction.ID, DecreaseViewSizeAction.LABEL, undefined), 'View: Decrease Current View Size', viewCategory);
|
||||
782
src/vs/workbench/browser/actions/listCommands.ts
Normal file
782
src/vs/workbench/browser/actions/listCommands.ts
Normal file
@@ -0,0 +1,782 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { WorkbenchListFocusContextKey, IListService, WorkbenchListSupportsMultiSelectContextKey, ListWidget, WorkbenchListHasSelectionOrFocus, getSelectionKeyboardEvent } from 'vs/platform/list/browser/listService';
|
||||
import { PagedList } from 'vs/base/browser/ui/list/listPaging';
|
||||
import { range } from 'vs/base/common/arrays';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ITree } from 'vs/base/parts/tree/browser/tree';
|
||||
import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree';
|
||||
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
|
||||
import { DataTree } from 'vs/base/browser/ui/tree/dataTree';
|
||||
import { ITreeNode } from 'vs/base/browser/ui/tree/tree';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
|
||||
function ensureDOMFocus(widget: ListWidget): void {
|
||||
// it can happen that one of the commands is executed while
|
||||
// DOM focus is within another focusable control within the
|
||||
// list/tree item. therefor we should ensure that the
|
||||
// list/tree has DOM focus again after the command ran.
|
||||
if (widget && widget.getHTMLElement() !== document.activeElement) {
|
||||
widget.domFocus();
|
||||
}
|
||||
}
|
||||
|
||||
function focusDown(accessor: ServicesAccessor, arg2?: number, loop: boolean = true): void {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
const count = typeof arg2 === 'number' ? arg2 : 1;
|
||||
|
||||
// Ensure DOM Focus
|
||||
ensureDOMFocus(focused);
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
|
||||
list.focusNext(count);
|
||||
const listFocus = list.getFocus();
|
||||
if (listFocus.length) {
|
||||
list.reveal(listFocus[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
tree.focusNext(count, loop, fakeKeyboardEvent);
|
||||
|
||||
const listFocus = tree.getFocus();
|
||||
if (listFocus.length) {
|
||||
tree.reveal(listFocus[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
tree.focusNext(count, { origin: 'keyboard' });
|
||||
tree.reveal(tree.getFocus());
|
||||
}
|
||||
}
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.focusDown',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.DownArrow,
|
||||
mac: {
|
||||
primary: KeyCode.DownArrow,
|
||||
secondary: [KeyMod.WinCtrl | KeyCode.KEY_N]
|
||||
},
|
||||
handler: (accessor, arg2) => focusDown(accessor, arg2)
|
||||
});
|
||||
|
||||
function expandMultiSelection(focused: List<any> | PagedList<any> | ITree | ObjectTree<any, any> | DataTree<any, any, any> | AsyncDataTree<any, any, any>, previousFocus: any): void {
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
|
||||
const focus = list.getFocus() ? list.getFocus()[0] : undefined;
|
||||
const selection = list.getSelection();
|
||||
if (selection && selection.indexOf(focus) >= 0) {
|
||||
list.setSelection(selection.filter(s => s !== previousFocus));
|
||||
} else {
|
||||
list.setSelection(selection.concat(focus));
|
||||
}
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const list = focused;
|
||||
|
||||
const focus = list.getFocus() ? list.getFocus()[0] : undefined;
|
||||
|
||||
if (previousFocus === focus) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = list.getSelection();
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown', { shiftKey: true });
|
||||
|
||||
if (selection && selection.indexOf(focus) >= 0) {
|
||||
list.setSelection(selection.filter(s => s !== previousFocus), fakeKeyboardEvent);
|
||||
} else {
|
||||
list.setSelection(selection.concat(focus), fakeKeyboardEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
const focus = tree.getFocus();
|
||||
const selection = tree.getSelection();
|
||||
if (selection && selection.indexOf(focus) >= 0) {
|
||||
tree.setSelection(selection.filter(s => s !== previousFocus));
|
||||
} else {
|
||||
tree.setSelection(selection.concat(focus));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.expandSelectionDown',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
|
||||
primary: KeyMod.Shift | KeyCode.DownArrow,
|
||||
handler: (accessor, arg2) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList || focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const list = focused;
|
||||
|
||||
// Focus down first
|
||||
const previousFocus = list.getFocus() ? list.getFocus()[0] : undefined;
|
||||
focusDown(accessor, arg2, false);
|
||||
|
||||
// Then adjust selection
|
||||
expandMultiSelection(focused, previousFocus);
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
// Focus down first
|
||||
const previousFocus = tree.getFocus();
|
||||
focusDown(accessor, arg2);
|
||||
|
||||
// Then adjust selection
|
||||
expandMultiSelection(focused, previousFocus);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function focusUp(accessor: ServicesAccessor, arg2?: number, loop: boolean = true): void {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
const count = typeof arg2 === 'number' ? arg2 : 1;
|
||||
|
||||
// Ensure DOM Focus
|
||||
ensureDOMFocus(focused);
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
|
||||
list.focusPrevious(count);
|
||||
const listFocus = list.getFocus();
|
||||
if (listFocus.length) {
|
||||
list.reveal(listFocus[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
tree.focusPrevious(count, loop, fakeKeyboardEvent);
|
||||
|
||||
const listFocus = tree.getFocus();
|
||||
if (listFocus.length) {
|
||||
tree.reveal(listFocus[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
tree.focusPrevious(count, { origin: 'keyboard' });
|
||||
tree.reveal(tree.getFocus());
|
||||
}
|
||||
}
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.focusUp',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.UpArrow,
|
||||
mac: {
|
||||
primary: KeyCode.UpArrow,
|
||||
secondary: [KeyMod.WinCtrl | KeyCode.KEY_P]
|
||||
},
|
||||
handler: (accessor, arg2) => focusUp(accessor, arg2)
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.expandSelectionUp',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
|
||||
primary: KeyMod.Shift | KeyCode.UpArrow,
|
||||
handler: (accessor, arg2) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList || focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const list = focused;
|
||||
|
||||
// Focus up first
|
||||
const previousFocus = list.getFocus() ? list.getFocus()[0] : undefined;
|
||||
focusUp(accessor, arg2, false);
|
||||
|
||||
// Then adjust selection
|
||||
expandMultiSelection(focused, previousFocus);
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
// Focus up first
|
||||
const previousFocus = tree.getFocus();
|
||||
focusUp(accessor, arg2);
|
||||
|
||||
// Then adjust selection
|
||||
expandMultiSelection(focused, previousFocus);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.collapse',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.LeftArrow,
|
||||
mac: {
|
||||
primary: KeyCode.LeftArrow,
|
||||
secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow]
|
||||
},
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// Tree only
|
||||
if (focused && !(focused instanceof List || focused instanceof PagedList)) {
|
||||
if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
const focusedElements = tree.getFocus();
|
||||
|
||||
if (focusedElements.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const focus = focusedElements[0];
|
||||
|
||||
if (!tree.collapse(focus)) {
|
||||
const parent = tree.getParentElement(focus);
|
||||
|
||||
if (parent) {
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
tree.setFocus([parent], fakeKeyboardEvent);
|
||||
tree.reveal(parent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const tree = focused;
|
||||
const focus = tree.getFocus();
|
||||
|
||||
tree.collapse(focus).then(didCollapse => {
|
||||
if (focus && !didCollapse) {
|
||||
tree.focusParent({ origin: 'keyboard' });
|
||||
|
||||
return tree.reveal(tree.getFocus());
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.expand',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.RightArrow,
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// Tree only
|
||||
if (focused && !(focused instanceof List || focused instanceof PagedList)) {
|
||||
if (focused instanceof ObjectTree || focused instanceof DataTree) {
|
||||
// TODO@Joao: instead of doing this here, just delegate to a tree method
|
||||
const tree = focused;
|
||||
const focusedElements = tree.getFocus();
|
||||
|
||||
if (focusedElements.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const focus = focusedElements[0];
|
||||
|
||||
if (!tree.expand(focus)) {
|
||||
const child = tree.getFirstElementChild(focus);
|
||||
|
||||
if (child) {
|
||||
const node = tree.getNode(child);
|
||||
|
||||
if (node.visible) {
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
tree.setFocus([child], fakeKeyboardEvent);
|
||||
tree.reveal(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (focused instanceof AsyncDataTree) {
|
||||
// TODO@Joao: instead of doing this here, just delegate to a tree method
|
||||
const tree = focused;
|
||||
const focusedElements = tree.getFocus();
|
||||
|
||||
if (focusedElements.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const focus = focusedElements[0];
|
||||
tree.expand(focus).then(didExpand => {
|
||||
if (focus && !didExpand) {
|
||||
const child = tree.getFirstElementChild(focus);
|
||||
|
||||
if (child) {
|
||||
const node = tree.getNode(child);
|
||||
|
||||
if (node.visible) {
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
tree.setFocus([child], fakeKeyboardEvent);
|
||||
tree.reveal(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const tree = focused;
|
||||
const focus = tree.getFocus();
|
||||
|
||||
tree.expand(focus).then(didExpand => {
|
||||
if (focus && !didExpand) {
|
||||
tree.focusFirstChild({ origin: 'keyboard' });
|
||||
|
||||
return tree.reveal(tree.getFocus());
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.focusPageUp',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.PageUp,
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// Ensure DOM Focus
|
||||
ensureDOMFocus(focused);
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
|
||||
list.focusPreviousPage();
|
||||
list.reveal(list.getFocus()[0]);
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const list = focused;
|
||||
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
list.focusPreviousPage(fakeKeyboardEvent);
|
||||
list.reveal(list.getFocus()[0]);
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
tree.focusPreviousPage({ origin: 'keyboard' });
|
||||
tree.reveal(tree.getFocus());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.focusPageDown',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.PageDown,
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// Ensure DOM Focus
|
||||
ensureDOMFocus(focused);
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
|
||||
list.focusNextPage();
|
||||
list.reveal(list.getFocus()[0]);
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const list = focused;
|
||||
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
list.focusNextPage(fakeKeyboardEvent);
|
||||
list.reveal(list.getFocus()[0]);
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
tree.focusNextPage({ origin: 'keyboard' });
|
||||
tree.reveal(tree.getFocus());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.focusFirst',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.Home,
|
||||
handler: accessor => listFocusFirst(accessor)
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.focusFirstChild',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: 0,
|
||||
handler: accessor => listFocusFirst(accessor, { fromFocused: true })
|
||||
});
|
||||
|
||||
function listFocusFirst(accessor: ServicesAccessor, options?: { fromFocused: boolean }): void {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// Ensure DOM Focus
|
||||
ensureDOMFocus(focused);
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
|
||||
list.setFocus([0]);
|
||||
list.reveal(0);
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
tree.focusFirst(fakeKeyboardEvent);
|
||||
|
||||
const focus = tree.getFocus();
|
||||
|
||||
if (focus.length > 0) {
|
||||
tree.reveal(focus[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
tree.focusFirst({ origin: 'keyboard' }, options && options.fromFocused ? tree.getFocus() : undefined);
|
||||
tree.reveal(tree.getFocus());
|
||||
}
|
||||
}
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.focusLast',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.End,
|
||||
handler: accessor => listFocusLast(accessor)
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.focusLastChild',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: 0,
|
||||
handler: accessor => listFocusLast(accessor, { fromFocused: true })
|
||||
});
|
||||
|
||||
function listFocusLast(accessor: ServicesAccessor, options?: { fromFocused: boolean }): void {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// Ensure DOM Focus
|
||||
ensureDOMFocus(focused);
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
|
||||
list.setFocus([list.length - 1]);
|
||||
list.reveal(list.length - 1);
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
tree.focusLast(fakeKeyboardEvent);
|
||||
|
||||
const focus = tree.getFocus();
|
||||
|
||||
if (focus.length > 0) {
|
||||
tree.reveal(focus[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
tree.focusLast({ origin: 'keyboard' }, options && options.fromFocused ? tree.getFocus() : undefined);
|
||||
tree.reveal(tree.getFocus());
|
||||
}
|
||||
}
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.select',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.Enter,
|
||||
mac: {
|
||||
primary: KeyCode.Enter,
|
||||
secondary: [KeyMod.CtrlCmd | KeyCode.DownArrow]
|
||||
},
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
list.setSelection(list.getFocus());
|
||||
list.open(list.getFocus());
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const list = focused;
|
||||
const fakeKeyboardEvent = getSelectionKeyboardEvent('keydown', false);
|
||||
list.setSelection(list.getFocus(), fakeKeyboardEvent);
|
||||
list.open(list.getFocus());
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
const focus = tree.getFocus();
|
||||
|
||||
if (focus) {
|
||||
tree.setSelection([focus], { origin: 'keyboard' });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.selectAll',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListSupportsMultiSelectContextKey),
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_A,
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
list.setSelection(range(list.length));
|
||||
}
|
||||
|
||||
// Trees
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
const focus = tree.getFocus();
|
||||
const selection = tree.getSelection();
|
||||
|
||||
// Which element should be considered to start selecting all?
|
||||
let start: any | undefined = undefined;
|
||||
|
||||
if (focus.length > 0 && (selection.length === 0 || selection.indexOf(focus[0]) === -1)) {
|
||||
start = focus[0];
|
||||
}
|
||||
|
||||
if (!start && selection.length > 0) {
|
||||
start = selection[0];
|
||||
}
|
||||
|
||||
// What is the scope of select all?
|
||||
let scope: any | undefined = undefined;
|
||||
|
||||
if (!start) {
|
||||
scope = undefined;
|
||||
} else {
|
||||
const selectedNode = tree.getNode(start);
|
||||
const parentNode = selectedNode.parent;
|
||||
|
||||
if (!parentNode.parent) { // root
|
||||
scope = undefined;
|
||||
} else {
|
||||
scope = parentNode.element;
|
||||
}
|
||||
}
|
||||
|
||||
const newSelection: any[] = [];
|
||||
const visit = (node: ITreeNode<any, any>) => {
|
||||
for (const child of node.children) {
|
||||
if (child.visible) {
|
||||
newSelection.push(child.element);
|
||||
|
||||
if (!child.collapsed) {
|
||||
visit(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add the whole scope subtree to the new selection
|
||||
visit(tree.getNode(scope));
|
||||
|
||||
// If the scope isn't the tree root, it should be part of the new selection
|
||||
if (scope && selection.length === newSelection.length) {
|
||||
newSelection.unshift(scope);
|
||||
}
|
||||
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
tree.setSelection(newSelection, fakeKeyboardEvent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.toggleExpand',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: WorkbenchListFocusContextKey,
|
||||
primary: KeyCode.Space,
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// Tree only
|
||||
if (focused && !(focused instanceof List || focused instanceof PagedList)) {
|
||||
if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
const focus = tree.getFocus();
|
||||
|
||||
if (focus.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
tree.toggleCollapsed(focus[0]);
|
||||
} else {
|
||||
const tree = focused;
|
||||
const focus = tree.getFocus();
|
||||
|
||||
if (focus) {
|
||||
tree.toggleExpansion(focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'list.clear',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, WorkbenchListHasSelectionOrFocus),
|
||||
primary: KeyCode.Escape,
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
const list = focused;
|
||||
|
||||
if (list.getSelection().length > 0) {
|
||||
list.setSelection([]);
|
||||
} else if (list.getFocus().length > 0) {
|
||||
list.setFocus([]);
|
||||
}
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const list = focused;
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
|
||||
if (list.getSelection().length > 0) {
|
||||
list.setSelection([], fakeKeyboardEvent);
|
||||
} else if (list.getFocus().length > 0) {
|
||||
list.setFocus([], fakeKeyboardEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// Tree
|
||||
else if (focused) {
|
||||
const tree = focused;
|
||||
|
||||
if (tree.getSelection().length) {
|
||||
tree.clearSelection({ origin: 'keyboard' });
|
||||
} else if (tree.getFocus()) {
|
||||
tree.clearFocus({ origin: 'keyboard' });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: 'list.toggleKeyboardNavigation',
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
// TODO@joao
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
tree.toggleKeyboardNavigation();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: 'list.toggleFilterOnType',
|
||||
handler: (accessor) => {
|
||||
const focused = accessor.get(IListService).lastFocusedList;
|
||||
|
||||
// List
|
||||
if (focused instanceof List || focused instanceof PagedList) {
|
||||
// TODO@joao
|
||||
}
|
||||
|
||||
// ObjectTree
|
||||
else if (focused instanceof ObjectTree || focused instanceof DataTree || focused instanceof AsyncDataTree) {
|
||||
const tree = focused;
|
||||
tree.updateOptions({ filterOnType: !tree.filterOnType });
|
||||
}
|
||||
}
|
||||
});
|
||||
272
src/vs/workbench/browser/actions/navigationActions.ts
Normal file
272
src/vs/workbench/browser/actions/navigationActions.ts
Normal file
@@ -0,0 +1,272 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IEditorGroupsService, GroupDirection, GroupLocation, IFindGroupScope } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { IPartService, Parts, Position as PartPosition } from 'vs/workbench/services/part/common/partService';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IViewlet } from 'vs/workbench/common/viewlet';
|
||||
import { IPanel } from 'vs/workbench/common/panel';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
|
||||
abstract class BaseNavigationAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService protected editorGroupService: IEditorGroupsService,
|
||||
@IPanelService protected panelService: IPanelService,
|
||||
@IPartService protected partService: IPartService,
|
||||
@IViewletService protected viewletService: IViewletService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const isEditorFocus = this.partService.hasFocus(Parts.EDITOR_PART);
|
||||
const isPanelFocus = this.partService.hasFocus(Parts.PANEL_PART);
|
||||
const isSidebarFocus = this.partService.hasFocus(Parts.SIDEBAR_PART);
|
||||
|
||||
const isSidebarPositionLeft = this.partService.getSideBarPosition() === PartPosition.LEFT;
|
||||
const isPanelPositionDown = this.partService.getPanelPosition() === PartPosition.BOTTOM;
|
||||
|
||||
if (isEditorFocus) {
|
||||
return this.navigateOnEditorFocus(isSidebarPositionLeft, isPanelPositionDown);
|
||||
}
|
||||
|
||||
if (isPanelFocus) {
|
||||
return this.navigateOnPanelFocus(isSidebarPositionLeft, isPanelPositionDown);
|
||||
}
|
||||
|
||||
if (isSidebarFocus) {
|
||||
return Promise.resolve(this.navigateOnSidebarFocus(isSidebarPositionLeft, isPanelPositionDown));
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
protected navigateOnEditorFocus(_isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IViewlet | IPanel> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
protected navigateOnPanelFocus(_isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IPanel> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
protected navigateOnSidebarFocus(_isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): boolean | IViewlet {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected navigateToPanel(): IPanel | boolean {
|
||||
if (!this.partService.isVisible(Parts.PANEL_PART)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const activePanelId = this.panelService.getActivePanel().getId();
|
||||
|
||||
return this.panelService.openPanel(activePanelId, true);
|
||||
}
|
||||
|
||||
protected navigateToSidebar(): Promise<IViewlet | boolean> {
|
||||
if (!this.partService.isVisible(Parts.SIDEBAR_PART)) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
const activeViewletId = this.viewletService.getActiveViewlet().getId();
|
||||
|
||||
return this.viewletService.openViewlet(activeViewletId, true)
|
||||
.then(value => value === null ? false : value);
|
||||
}
|
||||
|
||||
protected navigateAcrossEditorGroup(direction: GroupDirection): boolean {
|
||||
return this.doNavigateToEditorGroup({ direction });
|
||||
}
|
||||
|
||||
protected navigateToEditorGroup(location: GroupLocation): boolean {
|
||||
return this.doNavigateToEditorGroup({ location });
|
||||
}
|
||||
|
||||
private doNavigateToEditorGroup(scope: IFindGroupScope): boolean {
|
||||
const targetGroup = this.editorGroupService.findGroup(scope, this.editorGroupService.activeGroup);
|
||||
if (targetGroup) {
|
||||
targetGroup.focus();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class NavigateLeftAction extends BaseNavigationAction {
|
||||
|
||||
static readonly ID = 'workbench.action.navigateLeft';
|
||||
static readonly LABEL = nls.localize('navigateLeft', "Navigate to the View on the Left");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService,
|
||||
@IPanelService panelService: IPanelService,
|
||||
@IPartService partService: IPartService,
|
||||
@IViewletService viewletService: IViewletService
|
||||
) {
|
||||
super(id, label, editorGroupService, panelService, partService, viewletService);
|
||||
}
|
||||
|
||||
protected navigateOnEditorFocus(isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IViewlet> {
|
||||
const didNavigate = this.navigateAcrossEditorGroup(GroupDirection.LEFT);
|
||||
if (didNavigate) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
if (isSidebarPositionLeft) {
|
||||
return this.navigateToSidebar();
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
protected navigateOnPanelFocus(isSidebarPositionLeft: boolean, isPanelPositionDown: boolean): Promise<boolean | IViewlet> {
|
||||
if (isPanelPositionDown && isSidebarPositionLeft) {
|
||||
return this.navigateToSidebar();
|
||||
}
|
||||
|
||||
if (!isPanelPositionDown) {
|
||||
return Promise.resolve(this.navigateToEditorGroup(GroupLocation.LAST));
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
protected navigateOnSidebarFocus(isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): boolean {
|
||||
if (!isSidebarPositionLeft) {
|
||||
return this.navigateToEditorGroup(GroupLocation.LAST);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class NavigateRightAction extends BaseNavigationAction {
|
||||
|
||||
static readonly ID = 'workbench.action.navigateRight';
|
||||
static readonly LABEL = nls.localize('navigateRight', "Navigate to the View on the Right");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService,
|
||||
@IPanelService panelService: IPanelService,
|
||||
@IPartService partService: IPartService,
|
||||
@IViewletService viewletService: IViewletService
|
||||
) {
|
||||
super(id, label, editorGroupService, panelService, partService, viewletService);
|
||||
}
|
||||
|
||||
protected navigateOnEditorFocus(isSidebarPositionLeft: boolean, isPanelPositionDown: boolean): Promise<boolean | IViewlet | IPanel> {
|
||||
const didNavigate = this.navigateAcrossEditorGroup(GroupDirection.RIGHT);
|
||||
if (didNavigate) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
if (!isPanelPositionDown) {
|
||||
return Promise.resolve(this.navigateToPanel());
|
||||
}
|
||||
|
||||
if (!isSidebarPositionLeft) {
|
||||
return this.navigateToSidebar();
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
protected navigateOnPanelFocus(isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean | IViewlet> {
|
||||
if (!isSidebarPositionLeft) {
|
||||
return this.navigateToSidebar();
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
protected navigateOnSidebarFocus(isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): boolean {
|
||||
if (isSidebarPositionLeft) {
|
||||
return this.navigateToEditorGroup(GroupLocation.FIRST);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class NavigateUpAction extends BaseNavigationAction {
|
||||
|
||||
static readonly ID = 'workbench.action.navigateUp';
|
||||
static readonly LABEL = nls.localize('navigateUp', "Navigate to the View Above");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService,
|
||||
@IPanelService panelService: IPanelService,
|
||||
@IPartService partService: IPartService,
|
||||
@IViewletService viewletService: IViewletService
|
||||
) {
|
||||
super(id, label, editorGroupService, panelService, partService, viewletService);
|
||||
}
|
||||
|
||||
protected navigateOnEditorFocus(_isSidebarPositionLeft: boolean, _isPanelPositionDown: boolean): Promise<boolean> {
|
||||
return Promise.resolve(this.navigateAcrossEditorGroup(GroupDirection.UP));
|
||||
}
|
||||
|
||||
protected navigateOnPanelFocus(_isSidebarPositionLeft: boolean, isPanelPositionDown: boolean): Promise<boolean> {
|
||||
if (isPanelPositionDown) {
|
||||
return Promise.resolve(this.navigateToEditorGroup(GroupLocation.LAST));
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
class NavigateDownAction extends BaseNavigationAction {
|
||||
|
||||
static readonly ID = 'workbench.action.navigateDown';
|
||||
static readonly LABEL = nls.localize('navigateDown', "Navigate to the View Below");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService,
|
||||
@IPanelService panelService: IPanelService,
|
||||
@IPartService partService: IPartService,
|
||||
@IViewletService viewletService: IViewletService
|
||||
) {
|
||||
super(id, label, editorGroupService, panelService, partService, viewletService);
|
||||
}
|
||||
|
||||
protected navigateOnEditorFocus(_isSidebarPositionLeft: boolean, isPanelPositionDown: boolean): Promise<boolean | IPanel> {
|
||||
const didNavigate = this.navigateAcrossEditorGroup(GroupDirection.DOWN);
|
||||
if (didNavigate) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
if (isPanelPositionDown) {
|
||||
return Promise.resolve(this.navigateToPanel());
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
const viewCategory = nls.localize('view', "View");
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateUpAction, NavigateUpAction.ID, NavigateUpAction.LABEL, undefined), 'View: Navigate to the View Above', viewCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateDownAction, NavigateDownAction.ID, NavigateDownAction.LABEL, undefined), 'View: Navigate to the View Below', viewCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateLeftAction, NavigateLeftAction.ID, NavigateLeftAction.LABEL, undefined), 'View: Navigate to the View on the Left', viewCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateRightAction, NavigateRightAction.ID, NavigateRightAction.LABEL, undefined), 'View: Navigate to the View on the Right', viewCategory);
|
||||
@@ -1,50 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
export class ToggleActivityBarVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleActivityBarVisibility';
|
||||
static readonly LABEL = nls.localize('toggleActivityBar', "Toggle Activity Bar Visibility");
|
||||
|
||||
private static readonly activityBarVisibleKey = 'workbench.activityBar.visible';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private partService: IPartService,
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const visibility = this.partService.isVisible(Parts.ACTIVITYBAR_PART);
|
||||
const newVisibilityValue = !visibility;
|
||||
|
||||
return this.configurationService.updateValue(ToggleActivityBarVisibilityAction.activityBarVisibleKey, newVisibilityValue, ConfigurationTarget.USER);
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, ToggleActivityBarVisibilityAction.LABEL), 'View: Toggle Activity Bar Visibility', nls.localize('view', "View"));
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
command: {
|
||||
id: ToggleActivityBarVisibilityAction.ID,
|
||||
title: nls.localize({ key: 'miToggleActivityBar', comment: ['&& denotes a mnemonic'] }, "Toggle &&Activity Bar")
|
||||
},
|
||||
order: 4
|
||||
});
|
||||
@@ -1,44 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
class ToggleCenteredLayout extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleCenteredLayout';
|
||||
static readonly LABEL = nls.localize('toggleCenteredLayout', "Toggle Centered Layout");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
this.partService.centerEditorLayout(!this.partService.isEditorLayoutCentered());
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCenteredLayout, ToggleCenteredLayout.ID, ToggleCenteredLayout.LABEL), 'View: Toggle Centered Layout', nls.localize('view', "View"));
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '1_toggle_view',
|
||||
command: {
|
||||
id: ToggleCenteredLayout.ID,
|
||||
title: nls.localize('miToggleCenteredLayout', "Toggle Centered Layout")
|
||||
},
|
||||
order: 3
|
||||
});
|
||||
@@ -1,83 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/actions';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorGroupsService, GroupOrientation } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
|
||||
export class ToggleEditorLayoutAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleEditorGroupLayout';
|
||||
static readonly LABEL = nls.localize('flipLayout', "Toggle Vertical/Horizontal Editor Layout");
|
||||
|
||||
private toDispose: IDisposable[];
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.toDispose = [];
|
||||
|
||||
this.class = 'flip-editor-layout';
|
||||
this.updateEnablement();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this.toDispose.push(this.editorGroupService.onDidAddGroup(() => this.updateEnablement()));
|
||||
this.toDispose.push(this.editorGroupService.onDidRemoveGroup(() => this.updateEnablement()));
|
||||
}
|
||||
|
||||
private updateEnablement(): void {
|
||||
this.enabled = this.editorGroupService.count > 1;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const newOrientation = (this.editorGroupService.orientation === GroupOrientation.VERTICAL) ? GroupOrientation.HORIZONTAL : GroupOrientation.VERTICAL;
|
||||
this.editorGroupService.setGroupOrientation(newOrientation);
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.toDispose = dispose(this.toDispose);
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
CommandsRegistry.registerCommand('_workbench.editor.setGroupOrientation', function (accessor: ServicesAccessor, args: [GroupOrientation]) {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
const [orientation] = args;
|
||||
|
||||
editorGroupService.setGroupOrientation(orientation);
|
||||
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
const group = nls.localize('view', "View");
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleEditorLayoutAction, ToggleEditorLayoutAction.ID, ToggleEditorLayoutAction.LABEL, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_0, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_0 } }), 'View: Flip Editor Group Layout', group);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, {
|
||||
group: 'z_flip',
|
||||
command: {
|
||||
id: ToggleEditorLayoutAction.ID,
|
||||
title: nls.localize({ key: 'miToggleEditorLayout', comment: ['&& denotes a mnemonic'] }, "Flip &&Layout")
|
||||
},
|
||||
order: 1
|
||||
});
|
||||
@@ -1,54 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { IPartService, Position } from 'vs/workbench/services/part/common/partService';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
export class ToggleSidebarPositionAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleSidebarPosition';
|
||||
static readonly LABEL = nls.localize('toggleSidebarPosition', "Toggle Side Bar Position");
|
||||
|
||||
private static readonly sidebarPositionConfigurationKey = 'workbench.sideBar.location';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private partService: IPartService,
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService && !!this.configurationService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const position = this.partService.getSideBarPosition();
|
||||
const newPositionValue = (position === Position.LEFT) ? 'right' : 'left';
|
||||
|
||||
return this.configurationService.updateValue(ToggleSidebarPositionAction.sidebarPositionConfigurationKey, newPositionValue, ConfigurationTarget.USER);
|
||||
}
|
||||
|
||||
static getLabel(partService: IPartService): string {
|
||||
return partService.getSideBarPosition() === Position.LEFT ? nls.localize('moveSidebarRight', "Move Side Bar Right") : nls.localize('moveSidebarLeft', "Move Side Bar Left");
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.LABEL), 'View: Toggle Side Bar Position', nls.localize('view', "View"));
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
command: {
|
||||
id: ToggleSidebarPositionAction.ID,
|
||||
title: nls.localize({ key: 'miMoveSidebarLeftRight', comment: ['&& denotes a mnemonic'] }, "&&Move Side Bar Left/Right")
|
||||
},
|
||||
order: 2
|
||||
});
|
||||
@@ -1,47 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
|
||||
export class ToggleSidebarVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleSidebarVisibility';
|
||||
static readonly LABEL = nls.localize('toggleSidebar', "Toggle Side Bar Visibility");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
const hideSidebar = this.partService.isVisible(Parts.SIDEBAR_PART);
|
||||
this.partService.setSideBarHidden(hideSidebar);
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSidebarVisibilityAction, ToggleSidebarVisibilityAction.ID, ToggleSidebarVisibilityAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_B }), 'View: Toggle Side Bar Visibility', nls.localize('view', "View"));
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
command: {
|
||||
id: ToggleSidebarVisibilityAction.ID,
|
||||
title: nls.localize({ key: 'miToggleSidebar', comment: ['&& denotes a mnemonic'] }, "&&Toggle Side Bar")
|
||||
},
|
||||
order: 1
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
export class ToggleStatusbarVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleStatusbarVisibility';
|
||||
static readonly LABEL = nls.localize('toggleStatusbar', "Toggle Status Bar Visibility");
|
||||
|
||||
private static readonly statusbarVisibleKey = 'workbench.statusBar.visible';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private partService: IPartService,
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const visibility = this.partService.isVisible(Parts.STATUSBAR_PART);
|
||||
const newVisibilityValue = !visibility;
|
||||
|
||||
return this.configurationService.updateValue(ToggleStatusbarVisibilityAction.statusbarVisibleKey, newVisibilityValue, ConfigurationTarget.USER);
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleStatusbarVisibilityAction, ToggleStatusbarVisibilityAction.ID, ToggleStatusbarVisibilityAction.LABEL), 'View: Toggle Status Bar Visibility', nls.localize('view', "View"));
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
command: {
|
||||
id: ToggleStatusbarVisibilityAction.ID,
|
||||
title: nls.localize({ key: 'miToggleStatusbar', comment: ['&& denotes a mnemonic'] }, "&&Toggle Status Bar")
|
||||
},
|
||||
order: 3
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
|
||||
export class ToggleTabsVisibilityAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleTabsVisibility';
|
||||
static readonly LABEL = nls.localize('toggleTabs', "Toggle Tab Visibility");
|
||||
|
||||
private static readonly tabsVisibleKey = 'workbench.editor.showTabs';
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
const visibility = this.configurationService.getValue<string>(ToggleTabsVisibilityAction.tabsVisibleKey);
|
||||
const newVisibilityValue = !visibility;
|
||||
|
||||
return this.configurationService.updateValue(ToggleTabsVisibilityAction.tabsVisibleKey, newVisibilityValue);
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTabsVisibilityAction, ToggleTabsVisibilityAction.ID, ToggleTabsVisibilityAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W }), 'View: Toggle Tab Visibility', nls.localize('view', "View"));
|
||||
@@ -1,45 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
class ToggleZenMode extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.toggleZenMode';
|
||||
static readonly LABEL = nls.localize('toggleZenMode', "Toggle Zen Mode");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
this.partService.toggleZenMode();
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleZenMode, ToggleZenMode.ID, ToggleZenMode.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_Z) }), 'View: Toggle Zen Mode', nls.localize('view', "View"));
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '1_toggle_view',
|
||||
command: {
|
||||
id: ToggleZenMode.ID,
|
||||
title: nls.localize('miToggleZenMode', "Toggle Zen Mode")
|
||||
},
|
||||
order: 2
|
||||
});
|
||||
@@ -17,6 +17,7 @@ import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL, PICK_WORKSPACE_FOLDE
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
||||
export class OpenFileAction extends Action {
|
||||
|
||||
@@ -26,12 +27,12 @@ export class OpenFileAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IFileDialogService private dialogService: IFileDialogService
|
||||
@IFileDialogService private readonly dialogService: IFileDialogService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(event?: any, data?: ITelemetryData): Thenable<any> {
|
||||
run(event?: any, data?: ITelemetryData): Promise<any> {
|
||||
return this.dialogService.pickFileAndOpen({ forceNewWindow: false, telemetryExtraData: data });
|
||||
}
|
||||
}
|
||||
@@ -44,12 +45,12 @@ export class OpenFolderAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IFileDialogService private dialogService: IFileDialogService
|
||||
@IFileDialogService private readonly dialogService: IFileDialogService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(event?: any, data?: ITelemetryData): Thenable<any> {
|
||||
run(event?: any, data?: ITelemetryData): Promise<any> {
|
||||
return this.dialogService.pickFolderAndOpen({ forceNewWindow: false, telemetryExtraData: data });
|
||||
}
|
||||
}
|
||||
@@ -62,12 +63,12 @@ export class OpenFileFolderAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IFileDialogService private dialogService: IFileDialogService
|
||||
@IFileDialogService private readonly dialogService: IFileDialogService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(event?: any, data?: ITelemetryData): Thenable<any> {
|
||||
run(event?: any, data?: ITelemetryData): Promise<any> {
|
||||
return this.dialogService.pickFileFolderAndOpen({ forceNewWindow: false, telemetryExtraData: data });
|
||||
}
|
||||
}
|
||||
@@ -80,12 +81,12 @@ export class AddRootFolderAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
return this.commandService.executeCommand(ADD_ROOT_FOLDER_COMMAND_ID);
|
||||
}
|
||||
}
|
||||
@@ -98,14 +99,14 @@ export class GlobalRemoveRootFolderAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const state = this.contextService.getWorkbenchState();
|
||||
|
||||
// Workspace / Folder
|
||||
@@ -131,34 +132,31 @@ export class SaveWorkspaceAsAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
|
||||
@IFileDialogService private dialogService: IFileDialogService
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService,
|
||||
@IFileDialogService private readonly dialogService: IFileDialogService
|
||||
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
return this.getNewWorkspaceConfigPath().then(configPathUri => {
|
||||
run(): Promise<any> {
|
||||
return this.getNewWorkspaceConfigPath().then((configPathUri): Promise<void> | void => {
|
||||
if (configPathUri) {
|
||||
const configPath = configPathUri.fsPath;
|
||||
switch (this.contextService.getWorkbenchState()) {
|
||||
case WorkbenchState.EMPTY:
|
||||
case WorkbenchState.FOLDER:
|
||||
const folders = this.contextService.getWorkspace().folders.map(folder => ({ uri: folder.uri }));
|
||||
return this.workspaceEditingService.createAndEnterWorkspace(folders, configPath);
|
||||
return this.workspaceEditingService.createAndEnterWorkspace(folders, configPathUri);
|
||||
|
||||
case WorkbenchState.WORKSPACE:
|
||||
return this.workspaceEditingService.saveAndEnterWorkspace(configPath);
|
||||
return this.workspaceEditingService.saveAndEnterWorkspace(configPathUri);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private getNewWorkspaceConfigPath(): Thenable<URI> {
|
||||
private getNewWorkspaceConfigPath(): Promise<URI | undefined> {
|
||||
return this.dialogService.showSaveDialog({
|
||||
saveLabel: mnemonicButtonLabel(nls.localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")),
|
||||
title: nls.localize('saveWorkspace', "Save Workspace"),
|
||||
@@ -176,16 +174,42 @@ export class OpenWorkspaceAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IFileDialogService private dialogService: IFileDialogService
|
||||
@IFileDialogService private readonly dialogService: IFileDialogService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(event?: any, data?: ITelemetryData): Thenable<any> {
|
||||
run(event?: any, data?: ITelemetryData): Promise<any> {
|
||||
return this.dialogService.pickWorkspaceAndOpen({ telemetryExtraData: data });
|
||||
}
|
||||
}
|
||||
|
||||
export class CloseWorkspaceAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.closeFolder';
|
||||
static LABEL = nls.localize('closeWorkspace', "Close Workspace");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IWindowService private readonly windowService: IWindowService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Promise<void> {
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
|
||||
this.notificationService.info(nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close."));
|
||||
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return this.windowService.closeWorkspace();
|
||||
}
|
||||
}
|
||||
|
||||
export class OpenWorkspaceConfigFileAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.openWorkspaceConfigFile';
|
||||
@@ -194,16 +218,20 @@ export class OpenWorkspaceConfigFileAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
|
||||
@IEditorService private editorService: IEditorService
|
||||
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
|
||||
@IEditorService private readonly editorService: IEditorService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
this.enabled = !!this.workspaceContextService.getWorkspace().configuration;
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
return this.editorService.openEditor({ resource: this.workspaceContextService.getWorkspace().configuration });
|
||||
run(): Promise<any> {
|
||||
const configuration = this.workspaceContextService.getWorkspace().configuration;
|
||||
if (configuration) {
|
||||
return this.editorService.openEditor({ resource: configuration });
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,18 +243,18 @@ export class DuplicateWorkspaceInNewWindowAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
|
||||
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
|
||||
@IWindowService private windowService: IWindowService,
|
||||
@IWorkspacesService private workspacesService: IWorkspacesService
|
||||
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
|
||||
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IWorkspacesService private readonly workspacesService: IWorkspacesService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const folders = this.workspaceContextService.getWorkspace().folders;
|
||||
|
||||
return this.workspacesService.createWorkspace(folders).then(newWorkspace => {
|
||||
return this.workspacesService.createUntitledWorkspace(folders).then(newWorkspace => {
|
||||
return this.workspaceEditingService.copyWorkspaceSettings(newWorkspace).then(() => {
|
||||
return this.windowService.openWindow([URI.file(newWorkspace.configPath)], { forceNewWindow: true });
|
||||
});
|
||||
|
||||
@@ -65,7 +65,7 @@ CommandsRegistry.registerCommand({
|
||||
canSelectFolders: true,
|
||||
canSelectMany: true,
|
||||
defaultUri: dialogsService.defaultFolderPath(Schemas.file)
|
||||
}).then(folders => {
|
||||
}).then((folders): Promise<any> | null => {
|
||||
if (!folders || !folders.length) {
|
||||
return null;
|
||||
}
|
||||
@@ -73,7 +73,7 @@ CommandsRegistry.registerCommand({
|
||||
// Add and show Files Explorer viewlet
|
||||
return workspaceEditingService.addFolders(folders.map(folder => ({ uri: folder })))
|
||||
.then(() => viewletService.openViewlet(viewletService.getDefaultViewletId(), true))
|
||||
.then(() => void 0);
|
||||
.then(() => undefined);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -87,26 +87,19 @@ CommandsRegistry.registerCommand(PICK_WORKSPACE_FOLDER_COMMAND_ID, function (acc
|
||||
|
||||
const folders = contextService.getWorkspace().folders;
|
||||
if (!folders.length) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const folderPicks = folders.map(folder => {
|
||||
return {
|
||||
label: folder.name,
|
||||
description: labelService.getUriLabel(resources.dirname(folder.uri), { relative: true }),
|
||||
description: labelService.getUriLabel(resources.dirname(folder.uri)!, { relative: true }),
|
||||
folder,
|
||||
iconClasses: getIconClasses(modelService, modeService, folder.uri, FileKind.ROOT_FOLDER)
|
||||
} as IQuickPickItem;
|
||||
});
|
||||
|
||||
let options: IPickOptions<IQuickPickItem>;
|
||||
if (args) {
|
||||
options = args[0];
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = Object.create(null);
|
||||
}
|
||||
const options: IPickOptions<IQuickPickItem> = (args ? args[0] : undefined) || Object.create(null);
|
||||
|
||||
if (!options.activeItem) {
|
||||
options.activeItem = folderPicks[0];
|
||||
@@ -120,18 +113,11 @@ CommandsRegistry.registerCommand(PICK_WORKSPACE_FOLDER_COMMAND_ID, function (acc
|
||||
options.matchOnDescription = true;
|
||||
}
|
||||
|
||||
let token: CancellationToken;
|
||||
if (args) {
|
||||
token = args[1];
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
token = CancellationToken.None;
|
||||
}
|
||||
const token: CancellationToken = (args ? args[1] : undefined) || CancellationToken.None;
|
||||
|
||||
return quickInputService.pick(folderPicks, options, token).then(pick => {
|
||||
if (!pick) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return folders[folderPicks.indexOf(pick)];
|
||||
|
||||
@@ -32,6 +32,9 @@ export abstract class Composite extends Component implements IComposite {
|
||||
private readonly _onTitleAreaUpdate: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onTitleAreaUpdate(): Event<void> { return this._onTitleAreaUpdate.event; }
|
||||
|
||||
private readonly _onDidChangeVisibility: Emitter<boolean> = this._register(new Emitter<boolean>());
|
||||
get onDidChangeVisibility(): Event<boolean> { return this._onDidChangeVisibility.event; }
|
||||
|
||||
private _onDidFocus: Emitter<void>;
|
||||
get onDidFocus(): Event<void> {
|
||||
if (!this._onDidFocus) {
|
||||
@@ -64,9 +67,6 @@ export abstract class Composite extends Component implements IComposite {
|
||||
private visible: boolean;
|
||||
private parent: HTMLElement;
|
||||
|
||||
/**
|
||||
* Create a new composite with the given ID and context.
|
||||
*/
|
||||
constructor(
|
||||
id: string,
|
||||
private _telemetryService: ITelemetryService,
|
||||
@@ -78,7 +78,7 @@ export abstract class Composite extends Component implements IComposite {
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
getTitle(): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,11 @@ export abstract class Composite extends Component implements IComposite {
|
||||
* If there is a long running opertaion it is fine to have it running in the background asyncly and return before.
|
||||
*/
|
||||
setVisible(visible: boolean): void {
|
||||
this.visible = visible;
|
||||
if (this.visible !== !!visible) {
|
||||
this.visible = visible;
|
||||
|
||||
this._onDidChangeVisibility.fire(visible);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +169,7 @@ export abstract class Composite extends Component implements IComposite {
|
||||
* of an action. Returns null to indicate that the action is not rendered through
|
||||
* an action item.
|
||||
*/
|
||||
getActionItem(action: IAction): IActionItem {
|
||||
getActionItem(action: IAction): IActionItem | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -201,7 +205,7 @@ export abstract class Composite extends Component implements IComposite {
|
||||
/**
|
||||
* Returns the underlying composite control or null if it is not accessible.
|
||||
*/
|
||||
getControl(): ICompositeControl {
|
||||
getControl(): ICompositeControl | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -210,24 +214,15 @@ export abstract class Composite extends Component implements IComposite {
|
||||
* A composite descriptor is a leightweight descriptor of a composite in the workbench.
|
||||
*/
|
||||
export abstract class CompositeDescriptor<T extends Composite> {
|
||||
id: string;
|
||||
name: string;
|
||||
cssClass: string;
|
||||
order: number;
|
||||
keybindingId: string;
|
||||
enabled: boolean;
|
||||
|
||||
private ctor: IConstructorSignature0<T>;
|
||||
|
||||
constructor(ctor: IConstructorSignature0<T>, id: string, name: string, cssClass?: string, order?: number, keybindingId?: string, ) {
|
||||
this.ctor = ctor;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.cssClass = cssClass;
|
||||
this.order = order;
|
||||
this.enabled = true;
|
||||
this.keybindingId = keybindingId;
|
||||
}
|
||||
constructor(
|
||||
private readonly ctor: IConstructorSignature0<T>,
|
||||
public readonly id: string,
|
||||
public readonly name: string,
|
||||
public readonly cssClass?: string,
|
||||
public readonly order?: number,
|
||||
public readonly keybindingId?: string,
|
||||
) { }
|
||||
|
||||
instantiate(instantiationService: IInstantiationService): T {
|
||||
return instantiationService.createInstance(this.ctor);
|
||||
@@ -239,6 +234,9 @@ export abstract class CompositeRegistry<T extends Composite> extends Disposable
|
||||
private readonly _onDidRegister: Emitter<CompositeDescriptor<T>> = this._register(new Emitter<CompositeDescriptor<T>>());
|
||||
get onDidRegister(): Event<CompositeDescriptor<T>> { return this._onDidRegister.event; }
|
||||
|
||||
private readonly _onDidDeregister: Emitter<CompositeDescriptor<T>> = this._register(new Emitter<CompositeDescriptor<T>>());
|
||||
get onDidDeregister(): Event<CompositeDescriptor<T>> { return this._onDidDeregister.event; }
|
||||
|
||||
private composites: CompositeDescriptor<T>[] = [];
|
||||
|
||||
protected registerComposite(descriptor: CompositeDescriptor<T>): void {
|
||||
@@ -250,7 +248,17 @@ export abstract class CompositeRegistry<T extends Composite> extends Disposable
|
||||
this._onDidRegister.fire(descriptor);
|
||||
}
|
||||
|
||||
getComposite(id: string): CompositeDescriptor<T> {
|
||||
protected deregisterComposite(id: string): void {
|
||||
const descriptor = this.compositeById(id);
|
||||
if (descriptor === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.composites.splice(this.composites.indexOf(descriptor), 1);
|
||||
this._onDidDeregister.fire(descriptor);
|
||||
}
|
||||
|
||||
getComposite(id: string): CompositeDescriptor<T> | null {
|
||||
return this.compositeById(id);
|
||||
}
|
||||
|
||||
@@ -258,10 +266,10 @@ export abstract class CompositeRegistry<T extends Composite> extends Disposable
|
||||
return this.composites.slice(0);
|
||||
}
|
||||
|
||||
private compositeById(id: string): CompositeDescriptor<T> {
|
||||
for (let i = 0; i < this.composites.length; i++) {
|
||||
if (this.composites[i].id === id) {
|
||||
return this.composites[i];
|
||||
private compositeById(id: string): CompositeDescriptor<T> | null {
|
||||
for (const composite of this.composites) {
|
||||
if (composite.id === id) {
|
||||
return composite;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@ import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/un
|
||||
import { DefaultEndOfLine } from 'vs/editor/common/model';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IEditorViewState } from 'vs/editor/common/editorCommon';
|
||||
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { DefaultDragAndDrop } from 'vs/base/parts/tree/browser/treeDefaults';
|
||||
import { DragMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { normalizeDriveLetter } from 'vs/base/common/labels';
|
||||
import { MIME_BINARY } from 'vs/base/common/mime';
|
||||
import { ITree, IDragAndDropData } from 'vs/base/parts/tree/browser/tree';
|
||||
import { ITree } from 'vs/base/parts/tree/browser/tree';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -69,8 +69,8 @@ export const CodeDataTransfers = {
|
||||
FILES: 'CodeFiles'
|
||||
};
|
||||
|
||||
export function extractResources(e: DragEvent, externalOnly?: boolean): (IDraggedResource | IDraggedEditor)[] {
|
||||
const resources: (IDraggedResource | IDraggedEditor)[] = [];
|
||||
export function extractResources(e: DragEvent, externalOnly?: boolean): Array<IDraggedResource | IDraggedEditor> {
|
||||
const resources: Array<IDraggedResource | IDraggedEditor> = [];
|
||||
if (e.dataTransfer.types.length > 0) {
|
||||
|
||||
// Check for window-to-window DND
|
||||
@@ -82,7 +82,7 @@ export function extractResources(e: DragEvent, externalOnly?: boolean): (IDragge
|
||||
try {
|
||||
const draggedEditors = JSON.parse(rawEditorsData) as ISerializedDraggedEditor[];
|
||||
draggedEditors.forEach(draggedEditor => {
|
||||
resources.push({ resource: URI.parse(draggedEditor.resource), backupResource: draggedEditor.backupResource ? URI.parse(draggedEditor.backupResource) : void 0, viewState: draggedEditor.viewState, isExternal: false });
|
||||
resources.push({ resource: URI.parse(draggedEditor.resource), backupResource: draggedEditor.backupResource ? URI.parse(draggedEditor.backupResource) : undefined, viewState: draggedEditor.viewState, isExternal: false });
|
||||
});
|
||||
} catch (error) {
|
||||
// Invalid transfer
|
||||
@@ -153,15 +153,15 @@ export class ResourcesDropHandler {
|
||||
|
||||
constructor(
|
||||
private options: IResourcesDropHandlerOptions,
|
||||
@IFileService private fileService: IFileService,
|
||||
@IWindowsService private windowsService: IWindowsService,
|
||||
@IWindowService private windowService: IWindowService,
|
||||
@IWorkspacesService private workspacesService: IWorkspacesService,
|
||||
@ITextFileService private textFileService: ITextFileService,
|
||||
@IBackupFileService private backupFileService: IBackupFileService,
|
||||
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IWorkspacesService private readonly workspacesService: IWorkspacesService,
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@IBackupFileService private readonly backupFileService: IBackupFileService,
|
||||
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ export class ResourcesDropHandler {
|
||||
// Check for special things being dropped
|
||||
return this.doHandleDrop(untitledOrFileResources).then(isWorkspaceOpening => {
|
||||
if (isWorkspaceOpening) {
|
||||
return void 0; // return early if the drop operation resulted in this window changing to a workspace
|
||||
return undefined; // return early if the drop operation resulted in this window changing to a workspace
|
||||
}
|
||||
|
||||
// Add external ones to recently open list unless dropped resource is a workspace
|
||||
@@ -206,7 +206,7 @@ export class ResourcesDropHandler {
|
||||
});
|
||||
}
|
||||
|
||||
private doHandleDrop(untitledOrFileResources: (IDraggedResource | IDraggedEditor)[]): Thenable<boolean> {
|
||||
private doHandleDrop(untitledOrFileResources: Array<IDraggedResource | IDraggedEditor>): Promise<boolean> {
|
||||
|
||||
// Check for dirty editors being dropped
|
||||
const resourcesWithBackups: IDraggedEditor[] = untitledOrFileResources.filter(resource => !resource.isExternal && !!(resource as IDraggedEditor).backupResource);
|
||||
@@ -225,7 +225,7 @@ export class ResourcesDropHandler {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
private handleDirtyEditorDrop(droppedDirtyEditor: IDraggedEditor): Thenable<boolean> {
|
||||
private handleDirtyEditorDrop(droppedDirtyEditor: IDraggedEditor): Promise<boolean> {
|
||||
|
||||
// Untitled: always ensure that we open a new untitled for each file we drop
|
||||
if (droppedDirtyEditor.resource.scheme === Schemas.untitled) {
|
||||
@@ -254,7 +254,7 @@ export class ResourcesDropHandler {
|
||||
return DefaultEndOfLine.LF;
|
||||
}
|
||||
|
||||
private handleWorkspaceFileDrop(fileOnDiskResources: URI[]): Thenable<boolean> {
|
||||
private handleWorkspaceFileDrop(fileOnDiskResources: URI[]): Promise<boolean> {
|
||||
const workspaceResources: { workspaces: URI[], folders: URI[] } = {
|
||||
workspaces: [],
|
||||
folders: []
|
||||
@@ -266,7 +266,7 @@ export class ResourcesDropHandler {
|
||||
if (extname(fileOnDiskResource.fsPath) === `.${WORKSPACE_EXTENSION}`) {
|
||||
workspaceResources.workspaces.push(fileOnDiskResource);
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Check for Folder
|
||||
@@ -274,7 +274,7 @@ export class ResourcesDropHandler {
|
||||
if (stat.isDirectory) {
|
||||
workspaceResources.folders.push(stat.resource);
|
||||
}
|
||||
}, error => void 0);
|
||||
}, error => undefined);
|
||||
})).then(_ => {
|
||||
const { workspaces, folders } = workspaceResources;
|
||||
|
||||
@@ -286,7 +286,7 @@ export class ResourcesDropHandler {
|
||||
// Pass focus to window
|
||||
this.windowService.focusWindow();
|
||||
|
||||
let workspacesToOpen: Thenable<URI[]>;
|
||||
let workspacesToOpen: Promise<URI[]>;
|
||||
|
||||
// Open in separate windows if we drop workspaces or just one folder
|
||||
if (workspaces.length > 0 || folders.length === 1) {
|
||||
@@ -295,7 +295,7 @@ export class ResourcesDropHandler {
|
||||
|
||||
// Multiple folders: Create new workspace with folders and open
|
||||
else if (folders.length > 1) {
|
||||
workspacesToOpen = this.workspacesService.createWorkspace(folders.map(folder => ({ uri: folder }))).then(workspace => [URI.file(workspace.configPath)]);
|
||||
workspacesToOpen = this.workspacesService.createUntitledWorkspace(folders.map(folder => ({ uri: folder }))).then(workspace => [URI.file(workspace.configPath)]);
|
||||
}
|
||||
|
||||
// Open
|
||||
@@ -323,7 +323,7 @@ export class SimpleFileResourceDragAndDrop extends DefaultDragAndDrop {
|
||||
return resource.toString();
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getDragLabel(tree: ITree, elements: any[]): string {
|
||||
@@ -336,7 +336,7 @@ export class SimpleFileResourceDragAndDrop extends DefaultDragAndDrop {
|
||||
return basenameOrAuthority(resource);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
onDragStart(tree: ITree, data: IDragAndDropData, originalEvent: DragMouseEvent): void {
|
||||
@@ -390,8 +390,7 @@ export function fillResourceDataTransfers(accessor: ServicesAccessor, resources:
|
||||
// Try to find editor view state from the visible editors that match given resource
|
||||
let viewState: IEditorViewState;
|
||||
const textEditorWidgets = editorService.visibleTextEditorWidgets;
|
||||
for (let i = 0; i < textEditorWidgets.length; i++) {
|
||||
const textEditorWidget = textEditorWidgets[i];
|
||||
for (const textEditorWidget of textEditorWidgets) {
|
||||
if (isCodeEditor(textEditorWidget)) {
|
||||
const model = textEditorWidget.getModel();
|
||||
if (model && model.uri && model.uri.toString() === file.resource.toString()) {
|
||||
@@ -404,7 +403,7 @@ export function fillResourceDataTransfers(accessor: ServicesAccessor, resources:
|
||||
// Add as dragged editor
|
||||
draggedEditors.push({
|
||||
resource: file.resource.toString(),
|
||||
backupResource: textFileService.isDirty(file.resource) ? backupFileService.toBackupResource(file.resource).toString() : void 0,
|
||||
backupResource: textFileService.isDirty(file.resource) ? backupFileService.toBackupResource(file.resource).toString() : undefined,
|
||||
viewState
|
||||
});
|
||||
});
|
||||
@@ -438,8 +437,8 @@ export class LocalSelectionTransfer<T> {
|
||||
|
||||
clearData(proto: T): void {
|
||||
if (this.hasData(proto)) {
|
||||
this.proto = void 0;
|
||||
this.data = void 0;
|
||||
this.proto = undefined;
|
||||
this.data = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,7 +447,7 @@ export class LocalSelectionTransfer<T> {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
setData(data: T[], proto: T): void {
|
||||
|
||||
@@ -36,12 +36,12 @@ export interface IEditorRegistry {
|
||||
/**
|
||||
* Returns the editor descriptor for the given input or null if none.
|
||||
*/
|
||||
getEditor(input: EditorInput): IEditorDescriptor;
|
||||
getEditor(input: EditorInput): IEditorDescriptor | null;
|
||||
|
||||
/**
|
||||
* Returns the editor descriptor for the given identifier or null if none.
|
||||
*/
|
||||
getEditorById(editorId: string): IEditorDescriptor;
|
||||
getEditorById(editorId: string): IEditorDescriptor | null;
|
||||
|
||||
/**
|
||||
* Returns an array of registered editors known to the platform.
|
||||
@@ -103,15 +103,14 @@ class EditorRegistry implements IEditorRegistry {
|
||||
this.editors.push(descriptor);
|
||||
}
|
||||
|
||||
getEditor(input: EditorInput): EditorDescriptor {
|
||||
getEditor(input: EditorInput): EditorDescriptor | null {
|
||||
const findEditorDescriptors = (input: EditorInput, byInstanceOf?: boolean): EditorDescriptor[] => {
|
||||
const matchingDescriptors: EditorDescriptor[] = [];
|
||||
|
||||
for (let i = 0; i < this.editors.length; i++) {
|
||||
const editor = this.editors[i];
|
||||
for (const editor of this.editors) {
|
||||
const inputDescriptors = <SyncDescriptor<EditorInput>[]>editor[INPUT_DESCRIPTORS_PROPERTY];
|
||||
for (let j = 0; j < inputDescriptors.length; j++) {
|
||||
const inputClass = inputDescriptors[j].ctor;
|
||||
for (const inputDescriptor of inputDescriptors) {
|
||||
const inputClass = inputDescriptor.ctor;
|
||||
|
||||
// Direct check on constructor type (ignores prototype chain)
|
||||
if (!byInstanceOf && input.constructor === inputClass) {
|
||||
@@ -155,9 +154,8 @@ class EditorRegistry implements IEditorRegistry {
|
||||
return null;
|
||||
}
|
||||
|
||||
getEditorById(editorId: string): EditorDescriptor {
|
||||
for (let i = 0; i < this.editors.length; i++) {
|
||||
const editor = this.editors[i];
|
||||
getEditorById(editorId: string): EditorDescriptor | null {
|
||||
for (const editor of this.editors) {
|
||||
if (editor.getId() === editorId) {
|
||||
return editor;
|
||||
}
|
||||
@@ -176,8 +174,7 @@ class EditorRegistry implements IEditorRegistry {
|
||||
|
||||
getEditorInputs(): any[] {
|
||||
const inputClasses: any[] = [];
|
||||
for (let i = 0; i < this.editors.length; i++) {
|
||||
const editor = this.editors[i];
|
||||
for (const editor of this.editors) {
|
||||
const editorInputDescriptors = <SyncDescriptor<EditorInput>[]>editor[INPUT_DESCRIPTORS_PROPERTY];
|
||||
inputClasses.push(...editorInputDescriptors.map(descriptor => descriptor.ctor));
|
||||
}
|
||||
|
||||
@@ -22,11 +22,13 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { getIconClasses, getConfiguredLangId } from 'vs/editor/common/services/getIconClasses';
|
||||
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export interface IResourceLabel {
|
||||
export interface IResourceLabelProps {
|
||||
resource?: uri;
|
||||
name: string;
|
||||
description?: string;
|
||||
resource?: uri;
|
||||
}
|
||||
|
||||
export interface IResourceLabelOptions extends IIconLabelValueOptions {
|
||||
@@ -34,68 +36,231 @@ export interface IResourceLabelOptions extends IIconLabelValueOptions {
|
||||
fileDecorations?: { colors: boolean, badges: boolean, data?: IDecorationData };
|
||||
}
|
||||
|
||||
export class ResourceLabel extends IconLabel {
|
||||
export interface IFileLabelOptions extends IResourceLabelOptions {
|
||||
hideLabel?: boolean;
|
||||
hidePath?: boolean;
|
||||
}
|
||||
|
||||
export interface IResourceLabel extends IDisposable {
|
||||
readonly element: HTMLElement;
|
||||
readonly onDidRender: Event<void>;
|
||||
|
||||
/**
|
||||
* Most generic way to apply a label with raw information.
|
||||
*/
|
||||
setLabel(label?: string, description?: string, options?: IIconLabelValueOptions): void;
|
||||
|
||||
/**
|
||||
* Convinient method to apply a label by passing a resource along.
|
||||
*
|
||||
* Note: for file resources consider to use the #setFile() method instead.
|
||||
*/
|
||||
setResource(label: IResourceLabelProps, options?: IResourceLabelOptions): void;
|
||||
|
||||
/**
|
||||
* Convinient method to render a file label based on a resource.
|
||||
*/
|
||||
setFile(resource: uri, options?: IFileLabelOptions): void;
|
||||
|
||||
/**
|
||||
* Convinient method to apply a label by passing an editor along.
|
||||
*/
|
||||
setEditor(editor: IEditorInput, options?: IResourceLabelOptions): void;
|
||||
|
||||
/**
|
||||
* Resets the label to be empty.
|
||||
*/
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
export interface IResourceLabelsContainer {
|
||||
readonly onDidChangeVisibility: Event<boolean>;
|
||||
}
|
||||
|
||||
export const DEFAULT_LABELS_CONTAINER: IResourceLabelsContainer = {
|
||||
onDidChangeVisibility: Event.None
|
||||
};
|
||||
|
||||
export class ResourceLabels extends Disposable {
|
||||
private _widgets: ResourceLabelWidget[] = [];
|
||||
private _labels: IResourceLabel[] = [];
|
||||
|
||||
constructor(
|
||||
container: IResourceLabelsContainer,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IDecorationsService private readonly decorationsService: IDecorationsService,
|
||||
@IThemeService private readonly themeService: IThemeService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.registerListeners(container);
|
||||
}
|
||||
|
||||
private registerListeners(container: IResourceLabelsContainer): void {
|
||||
|
||||
// notify when visibility changes
|
||||
this._register(container.onDidChangeVisibility(visible => {
|
||||
this._widgets.forEach(widget => widget.notifyVisibilityChanged(visible));
|
||||
}));
|
||||
|
||||
// notify when extensions are registered with potentially new languages
|
||||
this._register(this.extensionService.onDidRegisterExtensions(() => this._widgets.forEach(widget => widget.notifyExtensionsRegistered())));
|
||||
|
||||
// notify when model mode changes
|
||||
this._register(this.modelService.onModelModeChanged(e => {
|
||||
if (!e.model.uri) {
|
||||
return; // we need the resource to compare
|
||||
}
|
||||
|
||||
if (e.model.uri.scheme === Schemas.file && e.oldModeId === PLAINTEXT_MODE_ID) { // todo@remote does this apply?
|
||||
return; // ignore transitions in files from no mode to specific mode because this happens each time a model is created
|
||||
}
|
||||
|
||||
this._widgets.forEach(widget => widget.notifyModelModeChanged(e));
|
||||
}));
|
||||
|
||||
// notify when file decoration changes
|
||||
this._register(this.decorationsService.onDidChangeDecorations(e => this._widgets.forEach(widget => widget.notifyFileDecorationsChanges(e))));
|
||||
|
||||
// notify when theme changes
|
||||
this._register(this.themeService.onThemeChange(() => this._widgets.forEach(widget => widget.notifyThemeChange())));
|
||||
|
||||
// notify when files.associations changes
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(FILES_ASSOCIATIONS_CONFIG)) {
|
||||
this._widgets.forEach(widget => widget.notifyFileAssociationsChange());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
get(index: number): IResourceLabel {
|
||||
return this._labels[index];
|
||||
}
|
||||
|
||||
create(container: HTMLElement, options?: IIconLabelCreationOptions): IResourceLabel {
|
||||
const widget = this.instantiationService.createInstance(ResourceLabelWidget, container, options);
|
||||
|
||||
// Only expose a handle to the outside
|
||||
const label: IResourceLabel = {
|
||||
element: widget.element,
|
||||
onDidRender: widget.onDidRender,
|
||||
setLabel: (label?: string, description?: string, options?: IIconLabelValueOptions) => widget.setLabel(label, description, options),
|
||||
setResource: (label: IResourceLabelProps, options?: IResourceLabelOptions) => widget.setResource(label, options),
|
||||
setEditor: (editor: IEditorInput, options?: IResourceLabelOptions) => widget.setEditor(editor, options),
|
||||
setFile: (resource: uri, options?: IFileLabelOptions) => widget.setFile(resource, options),
|
||||
clear: () => widget.clear(),
|
||||
dispose: () => this.disposeWidget(widget)
|
||||
};
|
||||
|
||||
// Store
|
||||
this._labels.push(label);
|
||||
this._widgets.push(widget);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
private disposeWidget(widget: ResourceLabelWidget): void {
|
||||
const index = this._widgets.indexOf(widget);
|
||||
if (index > -1) {
|
||||
this._widgets.splice(index, 1);
|
||||
this._labels.splice(index, 1);
|
||||
}
|
||||
|
||||
dispose(widget);
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this._widgets = dispose(this._widgets);
|
||||
this._labels = [];
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: please consider to use ResourceLabels if you are in need
|
||||
* of more than one label for your widget.
|
||||
*/
|
||||
export class ResourceLabel extends ResourceLabels {
|
||||
|
||||
private _label: IResourceLabel;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
options: IIconLabelCreationOptions,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IModelService modelService: IModelService,
|
||||
@IDecorationsService decorationsService: IDecorationsService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@ILabelService labelService: ILabelService
|
||||
) {
|
||||
super(DEFAULT_LABELS_CONTAINER, instantiationService, extensionService, configurationService, modelService, decorationsService, themeService);
|
||||
|
||||
this._label = this._register(this.create(container, options));
|
||||
}
|
||||
|
||||
get element(): IResourceLabel {
|
||||
return this._label;
|
||||
}
|
||||
}
|
||||
|
||||
enum Redraw {
|
||||
Basic = 1,
|
||||
Full = 2
|
||||
}
|
||||
|
||||
class ResourceLabelWidget extends IconLabel {
|
||||
|
||||
private _onDidRender = this._register(new Emitter<void>());
|
||||
get onDidRender(): Event<void> { return this._onDidRender.event; }
|
||||
|
||||
private label: IResourceLabel;
|
||||
private label: IResourceLabelProps;
|
||||
private options: IResourceLabelOptions;
|
||||
private computedIconClasses: string[];
|
||||
private lastKnownConfiguredLangId: string;
|
||||
private computedPathLabel: string;
|
||||
|
||||
private needsRedraw: Redraw;
|
||||
private isHidden: boolean = false;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
options: IIconLabelCreationOptions,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IModelService private modelService: IModelService,
|
||||
@IDecorationsService protected decorationsService: IDecorationsService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@ILabelService protected labelService: ILabelService
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IDecorationsService private readonly decorationsService: IDecorationsService,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService
|
||||
) {
|
||||
super(container, options);
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
notifyVisibilityChanged(visible: boolean): void {
|
||||
if (visible === this.isHidden) {
|
||||
this.isHidden = !visible;
|
||||
|
||||
// update when extensions are registered with potentially new languages
|
||||
this._register(this.extensionService.onDidRegisterExtensions(() => this.render(true /* clear cache */)));
|
||||
|
||||
// react to model mode changes
|
||||
this._register(this.modelService.onModelModeChanged(e => this.onModelModeChanged(e)));
|
||||
|
||||
// react to file decoration changes
|
||||
this._register(this.decorationsService.onDidChangeDecorations(this.onFileDecorationsChanges, this));
|
||||
|
||||
// react to theme changes
|
||||
this._register(this.themeService.onThemeChange(() => this.render(false)));
|
||||
|
||||
// react to files.associations changes
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(FILES_ASSOCIATIONS_CONFIG)) {
|
||||
this.render(true /* clear cache */);
|
||||
if (visible && this.needsRedraw) {
|
||||
this.render(this.needsRedraw === Redraw.Basic ? false : true);
|
||||
this.needsRedraw = undefined;
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private onModelModeChanged(e: { model: ITextModel; oldModeId: string; }): void {
|
||||
notifyModelModeChanged(e: { model: ITextModel; oldModeId: string; }): void {
|
||||
if (!this.label || !this.label.resource) {
|
||||
return; // only update if label exists
|
||||
}
|
||||
|
||||
if (!e.model.uri) {
|
||||
return; // we need the resource to compare
|
||||
}
|
||||
|
||||
if (e.model.uri.scheme === Schemas.file && e.oldModeId === PLAINTEXT_MODE_ID) { // todo@remote does this apply?
|
||||
return; // ignore transitions in files from no mode to specific mode because this happens each time a model is created
|
||||
}
|
||||
|
||||
if (e.model.uri.toString() === this.label.resource.toString()) {
|
||||
if (this.lastKnownConfiguredLangId !== e.model.getLanguageIdentifier().language) {
|
||||
this.render(true); // update if the language id of the model has changed from our last known state
|
||||
@@ -103,7 +268,7 @@ export class ResourceLabel extends IconLabel {
|
||||
}
|
||||
}
|
||||
|
||||
private onFileDecorationsChanges(e: IResourceDecorationChangeEvent): void {
|
||||
notifyFileDecorationsChanges(e: IResourceDecorationChangeEvent): void {
|
||||
if (!this.options || !this.label || !this.label.resource) {
|
||||
return;
|
||||
}
|
||||
@@ -113,25 +278,37 @@ export class ResourceLabel extends IconLabel {
|
||||
}
|
||||
}
|
||||
|
||||
setLabel(label: IResourceLabel, options?: IResourceLabelOptions): void {
|
||||
notifyExtensionsRegistered(): void {
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
notifyThemeChange(): void {
|
||||
this.render(false);
|
||||
}
|
||||
|
||||
notifyFileAssociationsChange(): void {
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
setResource(label: IResourceLabelProps, options?: IResourceLabelOptions): void {
|
||||
const hasResourceChanged = this.hasResourceChanged(label, options);
|
||||
|
||||
this.label = label;
|
||||
this.options = options;
|
||||
|
||||
if (hasResourceChanged) {
|
||||
this.computedPathLabel = void 0; // reset path label due to resource change
|
||||
this.computedPathLabel = undefined; // reset path label due to resource change
|
||||
}
|
||||
|
||||
this.render(hasResourceChanged);
|
||||
}
|
||||
|
||||
private hasResourceChanged(label: IResourceLabel, options: IResourceLabelOptions): boolean {
|
||||
const newResource = label ? label.resource : void 0;
|
||||
const oldResource = this.label ? this.label.resource : void 0;
|
||||
private hasResourceChanged(label: IResourceLabelProps, options: IResourceLabelOptions): boolean {
|
||||
const newResource = label ? label.resource : undefined;
|
||||
const oldResource = this.label ? this.label.resource : undefined;
|
||||
|
||||
const newFileKind = options ? options.fileKind : void 0;
|
||||
const oldFileKind = this.options ? this.options.fileKind : void 0;
|
||||
const newFileKind = options ? options.fileKind : undefined;
|
||||
const oldFileKind = this.options ? this.options.fileKind : undefined;
|
||||
|
||||
if (newFileKind !== oldFileKind) {
|
||||
return true; // same resource but different kind (file, folder)
|
||||
@@ -152,17 +329,62 @@ export class ResourceLabel extends IconLabel {
|
||||
return true;
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.label = void 0;
|
||||
this.options = void 0;
|
||||
this.lastKnownConfiguredLangId = void 0;
|
||||
this.computedIconClasses = void 0;
|
||||
this.computedPathLabel = void 0;
|
||||
setEditor(editor: IEditorInput, options?: IResourceLabelOptions): void {
|
||||
this.setResource({
|
||||
resource: toResource(editor, { supportSideBySide: true }),
|
||||
name: editor.getName(),
|
||||
description: editor.getDescription()
|
||||
}, options);
|
||||
}
|
||||
|
||||
this.setValue();
|
||||
setFile(resource: uri, options?: IFileLabelOptions): void {
|
||||
const hideLabel = options && options.hideLabel;
|
||||
let name: string;
|
||||
if (!hideLabel) {
|
||||
if (options && options.fileKind === FileKind.ROOT_FOLDER) {
|
||||
const workspaceFolder = this.contextService.getWorkspaceFolder(resource);
|
||||
if (workspaceFolder) {
|
||||
name = workspaceFolder.name;
|
||||
}
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
name = resources.basenameOrAuthority(resource);
|
||||
}
|
||||
}
|
||||
|
||||
let description: string;
|
||||
const hidePath = (options && options.hidePath) || (resource.scheme === Schemas.untitled && !this.untitledEditorService.hasAssociatedFilePath(resource));
|
||||
if (!hidePath) {
|
||||
description = this.labelService.getUriLabel(resources.dirname(resource), { relative: true });
|
||||
}
|
||||
|
||||
this.setResource({ resource, name, description }, options);
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.label = undefined;
|
||||
this.options = undefined;
|
||||
this.lastKnownConfiguredLangId = undefined;
|
||||
this.computedIconClasses = undefined;
|
||||
this.computedPathLabel = undefined;
|
||||
|
||||
this.setLabel();
|
||||
}
|
||||
|
||||
private render(clearIconCache: boolean): void {
|
||||
if (this.isHidden) {
|
||||
if (!this.needsRedraw) {
|
||||
this.needsRedraw = clearIconCache ? Redraw.Full : Redraw.Basic;
|
||||
}
|
||||
|
||||
if (this.needsRedraw === Redraw.Basic && clearIconCache) {
|
||||
this.needsRedraw = Redraw.Full;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.label) {
|
||||
const configuredLangId = getConfiguredLangId(this.modelService, this.label.resource);
|
||||
if (this.lastKnownConfiguredLangId !== configuredLangId) {
|
||||
@@ -172,7 +394,7 @@ export class ResourceLabel extends IconLabel {
|
||||
}
|
||||
|
||||
if (clearIconCache) {
|
||||
this.computedIconClasses = void 0;
|
||||
this.computedIconClasses = undefined;
|
||||
}
|
||||
|
||||
if (!this.label) {
|
||||
@@ -231,7 +453,7 @@ export class ResourceLabel extends IconLabel {
|
||||
}
|
||||
}
|
||||
|
||||
this.setValue(label, this.label.description, iconLabelOptions);
|
||||
this.setLabel(label, this.label.description, iconLabelOptions);
|
||||
|
||||
this._onDidRender.fire();
|
||||
}
|
||||
@@ -239,70 +461,10 @@ export class ResourceLabel extends IconLabel {
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
this.label = void 0;
|
||||
this.options = void 0;
|
||||
this.lastKnownConfiguredLangId = void 0;
|
||||
this.computedIconClasses = void 0;
|
||||
this.computedPathLabel = void 0;
|
||||
}
|
||||
}
|
||||
|
||||
export class EditorLabel extends ResourceLabel {
|
||||
|
||||
setEditor(editor: IEditorInput, options?: IResourceLabelOptions): void {
|
||||
this.setLabel({
|
||||
resource: toResource(editor, { supportSideBySide: true }),
|
||||
name: editor.getName(),
|
||||
description: editor.getDescription()
|
||||
}, options);
|
||||
}
|
||||
}
|
||||
|
||||
export interface IFileLabelOptions extends IResourceLabelOptions {
|
||||
hideLabel?: boolean;
|
||||
hidePath?: boolean;
|
||||
}
|
||||
|
||||
export class FileLabel extends ResourceLabel {
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
options: IIconLabelCreationOptions,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IModeService modeService: IModeService,
|
||||
@IModelService modelService: IModelService,
|
||||
@IDecorationsService decorationsService: IDecorationsService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
|
||||
@ILabelService labelService: ILabelService
|
||||
) {
|
||||
super(container, options, extensionService, configurationService, modeService, modelService, decorationsService, themeService, labelService);
|
||||
}
|
||||
|
||||
setFile(resource: uri, options?: IFileLabelOptions): void {
|
||||
const hideLabel = options && options.hideLabel;
|
||||
let name: string;
|
||||
if (!hideLabel) {
|
||||
if (options && options.fileKind === FileKind.ROOT_FOLDER) {
|
||||
const workspaceFolder = this.contextService.getWorkspaceFolder(resource);
|
||||
if (workspaceFolder) {
|
||||
name = workspaceFolder.name;
|
||||
}
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
name = resources.basenameOrAuthority(resource);
|
||||
}
|
||||
}
|
||||
|
||||
let description: string;
|
||||
const hidePath = (options && options.hidePath) || (resource.scheme === Schemas.untitled && !this.untitledEditorService.hasAssociatedFilePath(resource));
|
||||
if (!hidePath) {
|
||||
description = this.labelService.getUriLabel(resources.dirname(resource), { relative: true });
|
||||
}
|
||||
|
||||
this.setLabel({ resource, name, description }, options);
|
||||
this.label = undefined;
|
||||
this.options = undefined;
|
||||
this.lastKnownConfiguredLangId = undefined;
|
||||
this.computedIconClasses = undefined;
|
||||
this.computedPathLabel = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,12 +82,12 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr
|
||||
private quickInput: QuickInputService,
|
||||
private notificationsCenter: NotificationsCenter,
|
||||
private notificationsToasts: NotificationsToasts,
|
||||
@IStorageService private storageService: IStorageService,
|
||||
@IContextViewService private contextViewService: IContextViewService,
|
||||
@IPartService private partService: IPartService,
|
||||
@IViewletService private viewletService: IViewletService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super();
|
||||
|
||||
|
||||
@@ -3,34 +3,34 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench > .part > .title {
|
||||
.monaco-workbench .part > .title {
|
||||
display: none; /* Parts have to opt in to show title area */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title {
|
||||
.monaco-workbench .part > .title {
|
||||
height: 35px;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title {
|
||||
.monaco-workbench .part > .title {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title > .title-label {
|
||||
.monaco-workbench .part > .title > .title-label {
|
||||
line-height: 35px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title > .title-label {
|
||||
.monaco-workbench .part > .title > .title-label {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title > .title-label h2 {
|
||||
.monaco-workbench .part > .title > .title-label h2 {
|
||||
font-size: 11px;
|
||||
cursor: default;
|
||||
font-weight: normal;
|
||||
@@ -41,19 +41,19 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title > .title-label a {
|
||||
.monaco-workbench .part > .title > .title-label a {
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title > .title-actions {
|
||||
.monaco-workbench .part > .title > .title-actions {
|
||||
height: 35px;
|
||||
flex: 1;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title > .title-actions .action-label {
|
||||
.monaco-workbench .part > .title > .title-actions .action-label {
|
||||
display: block;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
@@ -63,16 +63,16 @@
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .title > .title-actions .action-label .label {
|
||||
.monaco-workbench .part > .title > .title-actions .action-label .label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .content {
|
||||
.monaco-workbench .part > .content {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .content > .monaco-progress-container,
|
||||
.monaco-workbench > .part.editor > .content .monaco-progress-container {
|
||||
.monaco-workbench .part > .content > .monaco-progress-container,
|
||||
.monaco-workbench .part.editor > .content .monaco-progress-container {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 33px; /* at the bottom of the 35px height title container */
|
||||
@@ -80,7 +80,7 @@
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .content > .monaco-progress-container .progress-bit,
|
||||
.monaco-workbench > .part.editor > .content .monaco-progress-container .progress-bit {
|
||||
.monaco-workbench .part > .content > .monaco-progress-container .progress-bit,
|
||||
.monaco-workbench .part.editor > .content .monaco-progress-container .progress-bit {
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,13 @@ export class PanelRegistry extends CompositeRegistry<Panel> {
|
||||
super.registerComposite(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregisters a panel to the platform.
|
||||
*/
|
||||
deregisterPanel(id: string): void {
|
||||
super.deregisterComposite(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of registered panels known to the platform.
|
||||
*/
|
||||
@@ -75,7 +82,7 @@ export abstract class TogglePanelAction extends Action {
|
||||
this.panelId = panelId;
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
if (this.isPanelFocused()) {
|
||||
this.partService.setPanelHidden(true);
|
||||
} else {
|
||||
@@ -94,7 +101,7 @@ export abstract class TogglePanelAction extends Action {
|
||||
private isPanelFocused(): boolean {
|
||||
const activeElement = document.activeElement;
|
||||
|
||||
return this.isPanelActive() && activeElement && isAncestor(activeElement, this.partService.getContainer(Parts.PANEL_PART));
|
||||
return !!(this.isPanelActive() && activeElement && isAncestor(activeElement, this.partService.getContainer(Parts.PANEL_PART)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,14 +36,14 @@ export class ViewletActivityAction extends ActivityAction {
|
||||
|
||||
constructor(
|
||||
activity: IActivity,
|
||||
@IViewletService private viewletService: IViewletService,
|
||||
@IPartService private partService: IPartService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService
|
||||
) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
run(event: any): Thenable<any> {
|
||||
run(event: any): Promise<any> {
|
||||
if (event instanceof MouseEvent && event.button === 2) {
|
||||
return Promise.resolve(false); // do not run on right click
|
||||
}
|
||||
@@ -84,13 +84,13 @@ export class ToggleViewletAction extends Action {
|
||||
|
||||
constructor(
|
||||
private _viewlet: ViewletDescriptor,
|
||||
@IPartService private partService: IPartService,
|
||||
@IViewletService private viewletService: IViewletService
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IViewletService private readonly viewletService: IViewletService
|
||||
) {
|
||||
super(_viewlet.id, _viewlet.name);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const sideBarVisible = this.partService.isVisible(Parts.SIDEBAR_PART);
|
||||
const activeViewlet = this.viewletService.getActiveViewlet();
|
||||
|
||||
@@ -175,7 +175,7 @@ export class PlaceHolderViewletActivityAction extends ViewletActivityAction {
|
||||
) {
|
||||
super({ id, name: id, cssClass: `extensionViewlet-placeholder-${id.replace(/\./g, '-')}` }, viewletService, partService, telemetryService);
|
||||
|
||||
const iconClass = `.monaco-workbench > .activitybar .monaco-action-bar .action-label.${this.class}`; // Generate Placeholder CSS to show the icon in the activity bar
|
||||
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${this.class}`; // Generate Placeholder CSS to show the icon in the activity bar
|
||||
DOM.createCSSRule(iconClass, `-webkit-mask: url('${iconUrl || ''}') no-repeat 50% 50%`);
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ export class PlaceHolderViewletActivityAction extends ViewletActivityAction {
|
||||
export class PlaceHolderToggleCompositePinnedAction extends ToggleCompositePinnedAction {
|
||||
|
||||
constructor(id: string, compositeBar: ICompositeBar) {
|
||||
super({ id, name: id, cssClass: void 0 }, compositeBar);
|
||||
super({ id, name: id, cssClass: undefined }, compositeBar);
|
||||
}
|
||||
|
||||
setActivity(activity: IActivity): void {
|
||||
@@ -200,13 +200,13 @@ class SwitchSideBarViewAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
name: string,
|
||||
@IViewletService private viewletService: IViewletService,
|
||||
@IActivityService private activityService: IActivityService
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IActivityService private readonly activityService: IActivityService
|
||||
) {
|
||||
super(id, name);
|
||||
}
|
||||
|
||||
run(offset: number): Thenable<any> {
|
||||
run(offset: number): Promise<any> {
|
||||
const pinnedViewletIds = this.activityService.getPinnedViewletIds();
|
||||
|
||||
const activeViewlet = this.viewletService.getActiveViewlet();
|
||||
@@ -238,7 +238,7 @@ export class PreviousSideBarViewAction extends SwitchSideBarViewAction {
|
||||
super(id, name, viewletService, activityService);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
return super.run(-1);
|
||||
}
|
||||
}
|
||||
@@ -257,7 +257,7 @@ export class NextSideBarViewAction extends SwitchSideBarViewAction {
|
||||
super(id, name, viewletService, activityService);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
return super.run(1);
|
||||
}
|
||||
}
|
||||
@@ -271,9 +271,9 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const activeForegroundColor = theme.getColor(ACTIVITY_BAR_FOREGROUND);
|
||||
if (activeForegroundColor) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active .action-label,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus .action-label,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover .action-label {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active .action-label,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:focus .action-label,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:hover .action-label {
|
||||
background-color: ${activeForegroundColor} !important;
|
||||
}
|
||||
`);
|
||||
@@ -283,7 +283,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const outline = theme.getColor(activeContrastBorder);
|
||||
if (outline) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:before {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
@@ -292,26 +292,26 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:before,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.checked:before,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.checked:hover:before {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active:before,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.checked:before,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.checked:hover:before {
|
||||
outline: 1px solid;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover:before {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:hover:before {
|
||||
outline: 1px dashed;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:focus:before {
|
||||
border-left-color: ${outline};
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:before,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.checked:before,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.checked:hover:before,
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:hover:before {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active:before,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.active:hover:before,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.checked:before,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.checked:hover:before,
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:hover:before {
|
||||
outline-color: ${outline};
|
||||
}
|
||||
`);
|
||||
@@ -322,7 +322,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const focusBorderColor = theme.getColor(focusBorder);
|
||||
if (focusBorderColor) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:focus:before {
|
||||
border-left-color: ${focusBorderColor};
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import 'vs/css!./media/activitybarpart';
|
||||
import * as nls from 'vs/nls';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
@@ -15,38 +16,39 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
import { IPartService, Parts, Position as SideBarPosition } from 'vs/workbench/services/part/common/partService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/toggleActivityBarVisibility';
|
||||
import { IThemeService, registerThemingParticipant, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions';
|
||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { CompositeBar } from 'vs/workbench/browser/parts/compositeBar';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { scheduleAtNextAnimationFrame, Dimension, addClass } from 'vs/base/browser/dom';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { CompositeBar, ICompositeBarItem } from 'vs/workbench/browser/parts/compositeBar';
|
||||
import { Dimension, addClass } from 'vs/base/browser/dom';
|
||||
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ToggleCompositePinnedAction, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions';
|
||||
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
|
||||
import { IViewsService, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewDescriptorCollection } from 'vs/workbench/common/views';
|
||||
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IViewlet } from 'vs/workbench/common/viewlet';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
|
||||
|
||||
const SCM_VIEWLET_ID = 'workbench.view.scm';
|
||||
|
||||
interface ICachedViewlet {
|
||||
id: string;
|
||||
iconUrl: URI;
|
||||
iconUrl: UriComponents;
|
||||
pinned: boolean;
|
||||
order: number;
|
||||
visible: boolean;
|
||||
views?: { when: string }[];
|
||||
}
|
||||
|
||||
export class ActivitybarPart extends Part {
|
||||
export class ActivitybarPart extends Part implements ISerializableView {
|
||||
|
||||
private static readonly ACTION_HEIGHT = 50;
|
||||
private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets';
|
||||
private static readonly CACHED_VIEWLETS = 'workbench.activity.placeholderViewlets';
|
||||
|
||||
private dimension: Dimension;
|
||||
|
||||
@@ -57,23 +59,37 @@ export class ActivitybarPart extends Part {
|
||||
private compositeBar: CompositeBar;
|
||||
private compositeActions: { [compositeId: string]: { activityAction: ViewletActivityAction, pinnedAction: ToggleCompositePinnedAction } } = Object.create(null);
|
||||
|
||||
element: HTMLElement;
|
||||
minimumWidth: number = 50;
|
||||
maximumWidth: number = 50;
|
||||
minimumHeight: number = 0;
|
||||
maximumHeight: number = Number.POSITIVE_INFINITY;
|
||||
|
||||
private _onDidChange = new Emitter<{ width: number; height: number; }>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@IViewletService private viewletService: IViewletService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IPartService private partService: IPartService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@ILifecycleService private lifecycleService: ILifecycleService,
|
||||
@IStorageService private storageService: IStorageService,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IViewsService private viewsService: IViewsService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IViewsService private readonly viewsService: IViewsService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService
|
||||
) {
|
||||
super(id, { hasTitle: false }, themeService, storageService);
|
||||
|
||||
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, {
|
||||
this.cachedViewlets = this.getCachedViewlets();
|
||||
for (const cachedViewlet of this.cachedViewlets) {
|
||||
if (this.shouldBeHidden(cachedViewlet.id, cachedViewlet)) {
|
||||
cachedViewlet.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.cachedViewlets.map(v => (<ICompositeBarItem>{ id: v.id, name: undefined, visible: v.visible, order: v.order, pinned: v.pinned })), {
|
||||
icon: true,
|
||||
storageId: ActivitybarPart.PINNED_VIEWLETS,
|
||||
orientation: ActionsOrientation.VERTICAL,
|
||||
openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true),
|
||||
getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction,
|
||||
@@ -87,16 +103,8 @@ export class ActivitybarPart extends Part {
|
||||
overflowActionSize: ActivitybarPart.ACTION_HEIGHT
|
||||
}));
|
||||
|
||||
const previousState = this.storageService.get(ActivitybarPart.CACHED_VIEWLETS, StorageScope.GLOBAL, '[]');
|
||||
this.cachedViewlets = (<ICachedViewlet[]>JSON.parse(previousState)).map(({ id, iconUrl, views }) => ({ id, views, iconUrl: typeof iconUrl === 'object' ? URI.revive(iconUrl) : void 0 }));
|
||||
for (const cachedViewlet of this.cachedViewlets) {
|
||||
if (this.shouldBeHidden(cachedViewlet.id, cachedViewlet)) {
|
||||
this.compositeBar.hideComposite(cachedViewlet.id);
|
||||
}
|
||||
}
|
||||
|
||||
this.registerListeners();
|
||||
this.onDidRegisterViewlets(viewletService.getAllViewlets());
|
||||
this.onDidRegisterViewlets(viewletService.getViewlets());
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
@@ -112,35 +120,40 @@ export class ActivitybarPart extends Part {
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
this._register(this.viewletService.onDidViewletRegister(viewlet => this.onDidRegisterViewlets([viewlet])));
|
||||
this._register(this.viewletService.onDidViewletDeregister(({ id }) => this.removeComposite(id, true)));
|
||||
|
||||
// Activate viewlet action on opening of a viewlet
|
||||
this._register(this.viewletService.onDidViewletOpen(viewlet => this.onDidViewletOpen(viewlet)));
|
||||
|
||||
// Deactivate viewlet action on close
|
||||
this._register(this.viewletService.onDidViewletClose(viewlet => this.compositeBar.deactivateComposite(viewlet.getId())));
|
||||
this._register(this.viewletService.onDidViewletEnablementChange(({ id, enabled }) => {
|
||||
if (enabled) {
|
||||
this.compositeBar.addComposite(this.viewletService.getViewlet(id));
|
||||
} else {
|
||||
this.removeComposite(id, true);
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.extensionService.onDidRegisterExtensions(() => this.onDidRegisterExtensions()));
|
||||
let disposables: IDisposable[] = [];
|
||||
this._register(this.extensionService.onDidRegisterExtensions(() => {
|
||||
disposables = dispose(disposables);
|
||||
this.onDidRegisterExtensions();
|
||||
this.compositeBar.onDidChange(() => this.saveCachedViewlets(), this, disposables);
|
||||
this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables);
|
||||
}));
|
||||
this._register(toDisposable(() => dispose(disposables)));
|
||||
}
|
||||
|
||||
private onDidRegisterExtensions(): void {
|
||||
this.removeNotExistingComposites();
|
||||
for (const viewlet of this.viewletService.getAllViewlets()) {
|
||||
for (const viewlet of this.viewletService.getViewlets()) {
|
||||
this.enableCompositeActions(viewlet);
|
||||
const viewContainer = this.getViewContainer(viewlet.id);
|
||||
if (viewContainer) {
|
||||
const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer);
|
||||
this.onDidChangeActiveViews(viewlet, viewDescriptors);
|
||||
viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(viewlet, viewDescriptors));
|
||||
if (viewDescriptors) {
|
||||
this.onDidChangeActiveViews(viewlet, viewDescriptors);
|
||||
viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(viewlet, viewDescriptors));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.saveCachedViewlets();
|
||||
}
|
||||
|
||||
private onDidChangeActiveViews(viewlet: ViewletDescriptor, viewDescriptors: IViewDescriptorCollection): void {
|
||||
@@ -157,9 +170,12 @@ export class ActivitybarPart extends Part {
|
||||
this.compositeBar.activateComposite(viewlet.getId());
|
||||
const viewletDescriptor = this.viewletService.getViewlet(viewlet.getId());
|
||||
const viewContainer = this.getViewContainer(viewletDescriptor.id);
|
||||
if (viewContainer && this.viewsService.getViewDescriptors(viewContainer).activeViewDescriptors.length === 0) {
|
||||
// Update the composite bar by hiding
|
||||
this.removeComposite(viewletDescriptor.id, true);
|
||||
if (viewContainer) {
|
||||
const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer);
|
||||
if (viewDescriptors && viewDescriptors.activeViewDescriptors.length === 0) {
|
||||
// Update the composite bar by hiding
|
||||
this.removeComposite(viewletDescriptor.id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +203,7 @@ export class ActivitybarPart extends Part {
|
||||
}
|
||||
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
this.element = parent;
|
||||
const content = document.createElement('div');
|
||||
addClass(content, 'content');
|
||||
parent.appendChild(content);
|
||||
@@ -201,27 +218,6 @@ export class ActivitybarPart extends Part {
|
||||
|
||||
this.createGlobalActivityActionBar(globalActivities);
|
||||
|
||||
// TODO@Ben: workaround for https://github.com/Microsoft/vscode/issues/45700
|
||||
// It looks like there are rendering glitches on macOS with Chrome 61 when
|
||||
// using --webkit-mask with a background color that is different from the image
|
||||
// The workaround is to promote the element onto its own drawing layer. We do
|
||||
// this only after the workbench has loaded because otherwise there is ugly flicker.
|
||||
if (isMacintosh) {
|
||||
this.lifecycleService.when(LifecyclePhase.Restored).then(() => {
|
||||
scheduleAtNextAnimationFrame(() => { // another delay...
|
||||
scheduleAtNextAnimationFrame(() => { // ...to prevent more flickering on startup
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
const activityBarForeground = theme.getColor(ACTIVITY_BAR_FOREGROUND);
|
||||
if (activityBarForeground && !activityBarForeground.equals(Color.white)) {
|
||||
// only apply this workaround if the color is different from the image one (white)
|
||||
collector.addRule('.monaco-workbench .activitybar > .content .monaco-action-bar .action-label { will-change: transform; }');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -287,7 +283,7 @@ export class ActivitybarPart extends Part {
|
||||
} else {
|
||||
const cachedComposite = this.cachedViewlets.filter(c => c.id === compositeId)[0];
|
||||
compositeActions = {
|
||||
activityAction: this.instantiationService.createInstance(PlaceHolderViewletActivityAction, compositeId, cachedComposite && cachedComposite.iconUrl),
|
||||
activityAction: this.instantiationService.createInstance(PlaceHolderViewletActivityAction, compositeId, cachedComposite ? URI.revive(cachedComposite.iconUrl) : undefined),
|
||||
pinnedAction: new PlaceHolderToggleCompositePinnedAction(compositeId, this.compositeBar)
|
||||
};
|
||||
}
|
||||
@@ -326,8 +322,8 @@ export class ActivitybarPart extends Part {
|
||||
}
|
||||
|
||||
private removeNotExistingComposites(): void {
|
||||
const viewlets = this.viewletService.getAllViewlets();
|
||||
for (const { id } of this.compositeBar.getComposites()) {
|
||||
const viewlets = this.viewletService.getViewlets();
|
||||
for (const { id } of this.cachedViewlets) {
|
||||
if (viewlets.every(viewlet => viewlet.id !== id)) {
|
||||
this.removeComposite(id, false);
|
||||
}
|
||||
@@ -366,13 +362,19 @@ export class ActivitybarPart extends Part {
|
||||
.map(v => v.id);
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): Dimension[] {
|
||||
layout(dimension: Dimension): Dimension[];
|
||||
layout(width: number, height: number): void;
|
||||
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
|
||||
if (!this.partService.isVisible(Parts.ACTIVITYBAR_PART)) {
|
||||
return [dimension];
|
||||
if (dim1 instanceof Dimension) {
|
||||
return [dim1];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass to super
|
||||
const sizes = super.layout(dimension);
|
||||
const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2));
|
||||
|
||||
this.dimension = sizes[1];
|
||||
|
||||
@@ -381,26 +383,114 @@ export class ActivitybarPart extends Part {
|
||||
// adjust height for global actions showing
|
||||
availableHeight -= (this.globalActionBar.items.length * ActivitybarPart.ACTION_HEIGHT);
|
||||
}
|
||||
this.compositeBar.layout(new Dimension(dimension.width, availableHeight));
|
||||
this.compositeBar.layout(new Dimension(dim1 instanceof Dimension ? dim1.width : dim1, availableHeight));
|
||||
|
||||
return sizes;
|
||||
if (dim1 instanceof Dimension) {
|
||||
return sizes;
|
||||
}
|
||||
}
|
||||
|
||||
protected saveState(): void {
|
||||
const state: ICachedViewlet[] = [];
|
||||
for (const { id, iconUrl } of this.viewletService.getAllViewlets()) {
|
||||
const viewContainer = this.getViewContainer(id);
|
||||
const views: { when: string }[] = [];
|
||||
if (viewContainer) {
|
||||
for (const { when } of this.viewsService.getViewDescriptors(viewContainer).allViewDescriptors) {
|
||||
views.push({ when: when ? when.serialize() : void 0 });
|
||||
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
|
||||
if (e.key === ActivitybarPart.PINNED_VIEWLETS && e.scope === StorageScope.GLOBAL
|
||||
&& this.cachedViewletsValue !== this.getStoredCachedViewletsValue() /* This checks if current window changed the value or not */) {
|
||||
this._cachedViewletsValue = null;
|
||||
const newCompositeItems: ICompositeBarItem[] = [];
|
||||
const compositeItems = this.compositeBar.getCompositeBarItems();
|
||||
const cachedViewlets = this.getCachedViewlets();
|
||||
|
||||
for (const cachedViewlet of cachedViewlets) {
|
||||
// Add and update existing items
|
||||
const existingItem = compositeItems.filter(({ id }) => id === cachedViewlet.id)[0];
|
||||
if (existingItem) {
|
||||
newCompositeItems.push({
|
||||
id: existingItem.id,
|
||||
name: existingItem.name,
|
||||
order: existingItem.order,
|
||||
pinned: cachedViewlet.pinned,
|
||||
visible: existingItem.visible
|
||||
});
|
||||
}
|
||||
}
|
||||
state.push({ id, iconUrl, views });
|
||||
}
|
||||
this.storageService.store(ActivitybarPart.CACHED_VIEWLETS, JSON.stringify(state), StorageScope.GLOBAL);
|
||||
|
||||
super.saveState();
|
||||
for (let index = 0; index < compositeItems.length; index++) {
|
||||
// Add items currently exists but does not exist in new.
|
||||
if (!newCompositeItems.some(({ id }) => id === compositeItems[index].id)) {
|
||||
newCompositeItems.splice(index, 0, compositeItems[index]);
|
||||
}
|
||||
}
|
||||
|
||||
this.compositeBar.setCompositeBarItems(newCompositeItems);
|
||||
}
|
||||
}
|
||||
|
||||
private saveCachedViewlets(): void {
|
||||
const state: ICachedViewlet[] = [];
|
||||
const compositeItems = this.compositeBar.getCompositeBarItems();
|
||||
const allViewlets = this.viewletService.getViewlets();
|
||||
for (const compositeItem of compositeItems) {
|
||||
const viewContainer = this.getViewContainer(compositeItem.id);
|
||||
const viewlet = allViewlets.filter(({ id }) => id === compositeItem.id)[0];
|
||||
if (viewlet) {
|
||||
const views: { when: string }[] = [];
|
||||
if (viewContainer) {
|
||||
const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer);
|
||||
if (viewDescriptors) {
|
||||
for (const { when } of viewDescriptors.allViewDescriptors) {
|
||||
views.push({ when: when ? when.serialize() : undefined });
|
||||
}
|
||||
}
|
||||
}
|
||||
state.push({ id: compositeItem.id, iconUrl: viewlet.iconUrl, views, pinned: compositeItem && compositeItem.pinned, order: compositeItem ? compositeItem.order : undefined, visible: compositeItem && compositeItem.visible });
|
||||
}
|
||||
}
|
||||
this.cachedViewletsValue = JSON.stringify(state);
|
||||
}
|
||||
|
||||
private getCachedViewlets(): ICachedViewlet[] {
|
||||
const storedStates = <Array<string | ICachedViewlet>>JSON.parse(this.cachedViewletsValue);
|
||||
const cachedViewlets = <ICachedViewlet[]>storedStates.map(c => {
|
||||
const serialized: ICachedViewlet = typeof c === 'string' /* migration from pinned states to composites states */ ? <ICachedViewlet>{ id: c, pinned: true, order: undefined, visible: true, iconUrl: undefined, views: undefined } : c;
|
||||
serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible;
|
||||
return serialized;
|
||||
});
|
||||
for (const old of this.loadOldCachedViewlets()) {
|
||||
const cachedViewlet = cachedViewlets.filter(cached => cached.id === old.id)[0];
|
||||
if (cachedViewlet) {
|
||||
cachedViewlet.iconUrl = old.iconUrl;
|
||||
cachedViewlet.views = old.views;
|
||||
}
|
||||
}
|
||||
return cachedViewlets;
|
||||
}
|
||||
|
||||
private loadOldCachedViewlets(): ICachedViewlet[] {
|
||||
const previousState = this.storageService.get('workbench.activity.placeholderViewlets', StorageScope.GLOBAL, '[]');
|
||||
const result = (<ICachedViewlet[]>JSON.parse(previousState));
|
||||
this.storageService.remove('workbench.activity.placeholderViewlets', StorageScope.GLOBAL);
|
||||
return result;
|
||||
}
|
||||
|
||||
private _cachedViewletsValue: string;
|
||||
private get cachedViewletsValue(): string {
|
||||
if (!this._cachedViewletsValue) {
|
||||
this._cachedViewletsValue = this.getStoredCachedViewletsValue();
|
||||
}
|
||||
return this._cachedViewletsValue;
|
||||
}
|
||||
|
||||
private set cachedViewletsValue(cachedViewletsValue: string) {
|
||||
if (this.cachedViewletsValue !== cachedViewletsValue) {
|
||||
this._cachedViewletsValue = cachedViewletsValue;
|
||||
this.setStoredCachedViewletsValue(cachedViewletsValue);
|
||||
}
|
||||
}
|
||||
|
||||
private getStoredCachedViewletsValue(): string {
|
||||
return this.storageService.get(ActivitybarPart.PINNED_VIEWLETS, StorageScope.GLOBAL, '[]');
|
||||
}
|
||||
|
||||
private setStoredCachedViewletsValue(value: string): void {
|
||||
this.storageService.store(ActivitybarPart.PINNED_VIEWLETS, value, StorageScope.GLOBAL);
|
||||
}
|
||||
|
||||
private getViewContainer(viewletId: string): ViewContainer | undefined {
|
||||
@@ -411,4 +501,10 @@ export class ActivitybarPart extends Part {
|
||||
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
return viewContainerRegistry.get(viewletId);
|
||||
}
|
||||
|
||||
toJSON(): object {
|
||||
return {
|
||||
type: Parts.ACTIVITYBAR_PART
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-label {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-label {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
height: 40px;
|
||||
@@ -20,7 +20,7 @@
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item:focus:before {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item:focus:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
@@ -29,19 +29,19 @@
|
||||
border-left: 2px solid;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .action-item.clicked:focus:before {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-item.clicked:focus:before {
|
||||
border-left: none !important; /* no focus feedback when using mouse */
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar.left > .content .monaco-action-bar .action-item:focus:before {
|
||||
.monaco-workbench .activitybar.left > .content .monaco-action-bar .action-item:focus:before {
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .action-item:focus:before {
|
||||
.monaco-workbench .activitybar.right > .content .monaco-action-bar .action-item:focus:before {
|
||||
right: 1px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .badge {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .badge {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 0;
|
||||
@@ -50,7 +50,7 @@
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar .badge .badge-content {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .badge .badge-content {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 8px;
|
||||
@@ -65,13 +65,13 @@
|
||||
|
||||
/* Right aligned */
|
||||
|
||||
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .action-label {
|
||||
.monaco-workbench .activitybar.right > .content .monaco-action-bar .action-label {
|
||||
margin-left: 0;
|
||||
padding: 0 50px 0 0;
|
||||
background-position: calc(100% - 9px) center;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar.right > .content .monaco-action-bar .badge {
|
||||
.monaco-workbench .activitybar.right > .content .monaco-action-bar .badge {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
@@ -3,23 +3,23 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench > .part.activitybar {
|
||||
.monaco-workbench .part.activitybar {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content {
|
||||
.monaco-workbench .activitybar > .content {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar > .content .monaco-action-bar {
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar {
|
||||
text-align: left;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.monaco-workbench > .activitybar .action-item:focus {
|
||||
.monaco-workbench .activitybar .action-item:focus {
|
||||
outline: 0 !important; /* activity bar indicates focus custom */
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import { illegalArgument } from 'vs/base/common/errors';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar, ICompositeBarColors, DraggedCompositeIdentifier } from 'vs/workbench/browser/parts/compositeBarActions';
|
||||
@@ -20,10 +19,18 @@ import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
|
||||
import { ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
|
||||
export interface ICompositeBarItem {
|
||||
id: string;
|
||||
name: string;
|
||||
pinned: boolean;
|
||||
order: number;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export interface ICompositeBarOptions {
|
||||
icon: boolean;
|
||||
storageId: string;
|
||||
orientation: ActionsOrientation;
|
||||
colors: (theme: ITheme) => ICompositeBarColors;
|
||||
compositeSize: number;
|
||||
@@ -32,7 +39,7 @@ export interface ICompositeBarOptions {
|
||||
getCompositePinnedAction: (compositeId: string) => Action;
|
||||
getOnCompositeClickAction: (compositeId: string) => Action;
|
||||
getContextMenuActions: () => Action[];
|
||||
openComposite: (compositeId: string) => Thenable<any>;
|
||||
openComposite: (compositeId: string) => Promise<any>;
|
||||
getDefaultCompositeId: () => string;
|
||||
hidePart: () => void;
|
||||
}
|
||||
@@ -51,24 +58,33 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
|
||||
private compositeTransfer: LocalSelectionTransfer<DraggedCompositeIdentifier>;
|
||||
|
||||
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
items: ICompositeBarItem[],
|
||||
private options: ICompositeBarOptions,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.model = new CompositeBarModel(options, storageService);
|
||||
this.model = new CompositeBarModel(items, options);
|
||||
this.visibleComposites = [];
|
||||
this.compositeSizeInBar = new Map<string, number>();
|
||||
this.compositeTransfer = LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>();
|
||||
}
|
||||
|
||||
getComposites(): ICompositeBarItem[] {
|
||||
getCompositeBarItems(): ICompositeBarItem[] {
|
||||
return [...this.model.items];
|
||||
}
|
||||
|
||||
setCompositeBarItems(items: ICompositeBarItem[]): void {
|
||||
if (this.model.setItems(items)) {
|
||||
this.updateCompositeSwitcher();
|
||||
}
|
||||
}
|
||||
|
||||
getPinnedComposites(): ICompositeBarItem[] {
|
||||
return this.model.pinnedItems;
|
||||
}
|
||||
@@ -125,7 +141,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
this.updateCompositeSwitcher();
|
||||
}
|
||||
|
||||
addComposite({ id, name, order }: { id: string; name: string, order: number }): void {
|
||||
addComposite({ id, name, order }: { id: string; name: string, order?: number }): void {
|
||||
// Add to the model
|
||||
if (this.model.add(id, name, order)) {
|
||||
this.computeSizes([this.model.findItem(id)]);
|
||||
@@ -254,7 +270,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
return item && item.activityAction;
|
||||
}
|
||||
|
||||
private computeSizes(items: ICompositeBarItem[]): void {
|
||||
private computeSizes(items: ICompositeBarModelItem[]): void {
|
||||
const size = this.options.compositeSize;
|
||||
if (size) {
|
||||
items.forEach(composite => this.compositeSizeInBar.set(composite.id, size));
|
||||
@@ -367,7 +383,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
CompositeOverflowActivityActionItem,
|
||||
this.compositeOverflowAction,
|
||||
() => this.getOverflowingComposites(),
|
||||
() => this.model.activeItem ? this.model.activeItem.id : void 0,
|
||||
() => this.model.activeItem ? this.model.activeItem.id : undefined,
|
||||
(compositeId: string) => {
|
||||
const item = this.model.findItem(compositeId);
|
||||
return item && item.activity[0] && item.activity[0].badge;
|
||||
@@ -379,8 +395,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
this.compositeSwitcherBar.push(this.compositeOverflowAction, { label: false, icon: true });
|
||||
}
|
||||
|
||||
// Persist
|
||||
this.model.saveState();
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
|
||||
private getOverflowingComposites(): { id: string, name: string }[] {
|
||||
@@ -428,15 +443,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
}
|
||||
}
|
||||
|
||||
interface ISerializedCompositeBarItem {
|
||||
id: string;
|
||||
pinned: boolean;
|
||||
order: number;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
interface ICompositeBarItem extends ISerializedCompositeBarItem {
|
||||
name: string;
|
||||
interface ICompositeBarModelItem extends ICompositeBarItem {
|
||||
activityAction: ActivityAction;
|
||||
pinnedAction: Action;
|
||||
activity: ICompositeActivity[];
|
||||
@@ -444,28 +451,63 @@ interface ICompositeBarItem extends ISerializedCompositeBarItem {
|
||||
|
||||
class CompositeBarModel {
|
||||
|
||||
private _items: ICompositeBarModelItem[];
|
||||
private readonly options: ICompositeBarOptions;
|
||||
readonly items: ICompositeBarItem[];
|
||||
|
||||
activeItem: ICompositeBarItem;
|
||||
activeItem: ICompositeBarModelItem;
|
||||
|
||||
constructor(
|
||||
options: ICompositeBarOptions,
|
||||
private storageService: IStorageService,
|
||||
items: ICompositeBarItem[],
|
||||
options: ICompositeBarOptions
|
||||
) {
|
||||
this.options = options;
|
||||
this.items = this.loadItemStates();
|
||||
this.setItems(items);
|
||||
}
|
||||
|
||||
get visibleItems(): ICompositeBarItem[] {
|
||||
get items(): ICompositeBarModelItem[] {
|
||||
return this._items;
|
||||
}
|
||||
|
||||
setItems(items: ICompositeBarItem[]): boolean {
|
||||
const result: ICompositeBarModelItem[] = [];
|
||||
let hasChanges: boolean = false;
|
||||
if (!this.items || this.items.length === 0) {
|
||||
this._items = items.map(i => this.createCompositeBarItem(i.id, i.name, i.order, i.pinned, i.visible));
|
||||
hasChanges = true;
|
||||
} else {
|
||||
const existingItems = this.items;
|
||||
for (let index = 0; index < items.length; index++) {
|
||||
const newItem = items[index];
|
||||
const existingItem = existingItems.filter(({ id }) => id === newItem.id)[0];
|
||||
if (existingItem) {
|
||||
if (
|
||||
existingItem.pinned !== newItem.pinned ||
|
||||
index !== existingItems.indexOf(existingItem)
|
||||
) {
|
||||
existingItem.pinned = newItem.pinned;
|
||||
result.push(existingItem);
|
||||
hasChanges = true;
|
||||
} else {
|
||||
result.push(existingItem);
|
||||
}
|
||||
} else {
|
||||
result.push(this.createCompositeBarItem(newItem.id, newItem.name, newItem.order, newItem.pinned, newItem.visible));
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
this._items = result;
|
||||
}
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
get visibleItems(): ICompositeBarModelItem[] {
|
||||
return this.items.filter(item => item.visible);
|
||||
}
|
||||
|
||||
get pinnedItems(): ICompositeBarItem[] {
|
||||
get pinnedItems(): ICompositeBarModelItem[] {
|
||||
return this.items.filter(item => item.visible && item.pinned);
|
||||
}
|
||||
|
||||
private createCompositeBarItem(id: string, name: string, order: number, pinned: boolean, visible: boolean): ICompositeBarItem {
|
||||
private createCompositeBarItem(id: string, name: string, order: number, pinned: boolean, visible: boolean): ICompositeBarModelItem {
|
||||
const options = this.options;
|
||||
return {
|
||||
id, name, pinned, order, visible,
|
||||
@@ -551,8 +593,7 @@ class CompositeBarModel {
|
||||
}
|
||||
|
||||
setPinned(id: string, pinned: boolean): boolean {
|
||||
for (let index = 0; index < this.items.length; index++) {
|
||||
const item = this.items[index];
|
||||
for (const item of this.items) {
|
||||
if (item.id === id) {
|
||||
if (item.pinned !== pinned) {
|
||||
item.pinned = pinned;
|
||||
@@ -614,8 +655,7 @@ class CompositeBarModel {
|
||||
if (this.activeItem) {
|
||||
this.deactivate();
|
||||
}
|
||||
for (let index = 0; index < this.items.length; index++) {
|
||||
const item = this.items[index];
|
||||
for (const item of this.items) {
|
||||
if (item.id === id) {
|
||||
this.activeItem = item;
|
||||
this.activeItem.activityAction.activate();
|
||||
@@ -629,13 +669,13 @@ class CompositeBarModel {
|
||||
deactivate(): boolean {
|
||||
if (this.activeItem) {
|
||||
this.activeItem.activityAction.deactivate();
|
||||
this.activeItem = void 0;
|
||||
this.activeItem = undefined;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
findItem(id: string): ICompositeBarItem {
|
||||
findItem(id: string): ICompositeBarModelItem {
|
||||
return this.items.filter(item => item.id === id)[0];
|
||||
}
|
||||
|
||||
@@ -647,17 +687,4 @@ class CompositeBarModel {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private loadItemStates(): ICompositeBarItem[] {
|
||||
const storedStates = <Array<string | ISerializedCompositeBarItem>>JSON.parse(this.storageService.get(this.options.storageId, StorageScope.GLOBAL, '[]'));
|
||||
return <ICompositeBarItem[]>storedStates.map(c => {
|
||||
const serialized: ISerializedCompositeBarItem = typeof c === 'string' /* migration from pinned states to composites states */ ? { id: c, pinned: true, order: void 0, visible: true } : c;
|
||||
return this.createCompositeBarItem(serialized.id, void 0, serialized.order, serialized.pinned, isUndefinedOrNull(serialized.visible) ? true : serialized.visible);
|
||||
});
|
||||
}
|
||||
|
||||
saveState(): void {
|
||||
const serialized = this.items.map(({ id, pinned, order, visible }) => ({ id, pinned, order, visible }));
|
||||
this.storageService.store(this.options.storageId, JSON.stringify(serialized), StorageScope.GLOBAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ export class ActivityActionItem extends BaseActionItem {
|
||||
}));
|
||||
|
||||
// Label
|
||||
this.label = dom.append(this.element, dom.$('a.action-label'));
|
||||
this.label = dom.append(this.element, dom.$('a'));
|
||||
|
||||
// Badge
|
||||
this.badge = dom.append(this.element, dom.$('.badge'));
|
||||
@@ -301,8 +301,9 @@ export class ActivityActionItem extends BaseActionItem {
|
||||
}
|
||||
|
||||
protected updateLabel(): void {
|
||||
this.label.className = 'action-label';
|
||||
if (this.activity.cssClass) {
|
||||
dom.addClasses(this.label, this.activity.cssClass);
|
||||
dom.addClass(this.label, this.activity.cssClass);
|
||||
}
|
||||
if (!this.options.icon) {
|
||||
this.label.textContent = this.getAction().label;
|
||||
@@ -358,7 +359,7 @@ export class CompositeOverflowActivityActionItem extends ActivityActionItem {
|
||||
private getBadge: (compositeId: string) => IBadge,
|
||||
private getCompositeOpenAction: (compositeId: string) => Action,
|
||||
colors: (theme: ITheme) => ICompositeBarColors,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IThemeService themeService: IThemeService
|
||||
) {
|
||||
super(action, { icon: true, colors }, themeService);
|
||||
@@ -411,7 +412,7 @@ export class CompositeOverflowActivityActionItem extends ActivityActionItem {
|
||||
class ManageExtensionAction extends Action {
|
||||
|
||||
constructor(
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super('activitybar.manage.extension', nls.localize('manageExtension', "Manage Extension"));
|
||||
}
|
||||
@@ -434,7 +435,6 @@ export class CompositeActionItem extends ActivityActionItem {
|
||||
private static manageExtensionAction: ManageExtensionAction;
|
||||
|
||||
private compositeActivity: IActivity;
|
||||
private cssClass: string;
|
||||
private compositeTransfer: LocalSelectionTransfer<DraggedCompositeIdentifier>;
|
||||
|
||||
constructor(
|
||||
@@ -444,14 +444,13 @@ export class CompositeActionItem extends ActivityActionItem {
|
||||
colors: (theme: ITheme) => ICompositeBarColors,
|
||||
icon: boolean,
|
||||
private compositeBar: ICompositeBar,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService
|
||||
) {
|
||||
super(compositeActivityAction, { draggable: true, colors, icon }, themeService);
|
||||
|
||||
this.cssClass = compositeActivityAction.class;
|
||||
this.compositeTransfer = LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>();
|
||||
|
||||
if (!CompositeActionItem.manageExtensionAction) {
|
||||
@@ -473,7 +472,7 @@ export class CompositeActionItem extends ActivityActionItem {
|
||||
|
||||
this.compositeActivity = {
|
||||
id: this.compositeActivityAction.activity.id,
|
||||
cssClass: this.cssClass,
|
||||
cssClass: this.compositeActivityAction.activity.cssClass,
|
||||
name: activityName
|
||||
};
|
||||
}
|
||||
@@ -606,17 +605,6 @@ export class CompositeActionItem extends ActivityActionItem {
|
||||
this.container.focus();
|
||||
}
|
||||
|
||||
protected updateClass(): void {
|
||||
if (this.cssClass) {
|
||||
dom.removeClasses(this.label, this.cssClass);
|
||||
}
|
||||
|
||||
this.cssClass = this.getAction().class;
|
||||
if (this.cssClass) {
|
||||
dom.addClasses(this.label, this.cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
protected updateChecked(): void {
|
||||
if (this.getAction().checked) {
|
||||
dom.addClass(this.container, 'checked');
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import 'vs/css!./media/compositepart';
|
||||
import * as nls from 'vs/nls';
|
||||
import { defaultGenerator } from 'vs/base/common/idGenerator';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
@@ -46,6 +46,12 @@ export interface ICompositeTitleLabel {
|
||||
updateStyles(): void;
|
||||
}
|
||||
|
||||
interface CompositeItem {
|
||||
composite: Composite;
|
||||
disposable: IDisposable;
|
||||
progressService: IProgressService;
|
||||
}
|
||||
|
||||
export abstract class CompositePart<T extends Composite> extends Part {
|
||||
|
||||
protected _onDidCompositeOpen = this._register(new Emitter<{ composite: IComposite, focus: boolean }>());
|
||||
@@ -53,22 +59,20 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
|
||||
protected toolBar: ToolBar;
|
||||
|
||||
private instantiatedCompositeListeners: IDisposable[];
|
||||
private mapCompositeToCompositeContainer: { [compositeId: string]: HTMLElement; };
|
||||
private mapActionsBindingToComposite: { [compositeId: string]: () => void; };
|
||||
private mapProgressServiceToComposite: { [compositeId: string]: IProgressService; };
|
||||
private activeComposite: Composite;
|
||||
private activeComposite: Composite | null;
|
||||
private lastActiveCompositeId: string;
|
||||
private instantiatedComposites: Composite[];
|
||||
private instantiatedCompositeItems: Map<string, CompositeItem>;
|
||||
private titleLabel: ICompositeTitleLabel;
|
||||
private progressBar: ProgressBar;
|
||||
private contentAreaSize: Dimension;
|
||||
private telemetryActionsListener: IDisposable;
|
||||
private telemetryActionsListener: IDisposable | null;
|
||||
private currentCompositeOpenToken: string;
|
||||
|
||||
constructor(
|
||||
private notificationService: INotificationService,
|
||||
private storageService: IStorageService,
|
||||
protected storageService: IStorageService,
|
||||
private telemetryService: ITelemetryService,
|
||||
protected contextMenuService: IContextMenuService,
|
||||
protected partService: IPartService,
|
||||
@@ -86,16 +90,14 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
) {
|
||||
super(id, options, themeService, storageService);
|
||||
|
||||
this.instantiatedCompositeListeners = [];
|
||||
this.mapCompositeToCompositeContainer = {};
|
||||
this.mapActionsBindingToComposite = {};
|
||||
this.mapProgressServiceToComposite = {};
|
||||
this.activeComposite = null;
|
||||
this.instantiatedComposites = [];
|
||||
this.instantiatedCompositeItems = new Map<string, CompositeItem>();
|
||||
this.lastActiveCompositeId = storageService.get(activeCompositeSettingsKey, StorageScope.WORKSPACE, this.defaultCompositeId);
|
||||
}
|
||||
|
||||
protected openComposite(id: string, focus?: boolean): Composite {
|
||||
protected openComposite(id: string, focus?: boolean): Composite | undefined {
|
||||
// Check if composite already visible and just focus in that case
|
||||
if (this.activeComposite && this.activeComposite.getId() === id) {
|
||||
if (focus) {
|
||||
@@ -110,7 +112,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
return this.doOpenComposite(id, focus);
|
||||
}
|
||||
|
||||
private doOpenComposite(id: string, focus?: boolean): Composite {
|
||||
private doOpenComposite(id: string, focus: boolean = false): Composite | undefined {
|
||||
|
||||
// Use a generated token to avoid race conditions from long running promises
|
||||
const currentCompositeOpenToken = defaultGenerator.nextId();
|
||||
@@ -159,10 +161,9 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
protected createComposite(id: string, isActive?: boolean): Composite {
|
||||
|
||||
// Check if composite is already created
|
||||
for (let i = 0; i < this.instantiatedComposites.length; i++) {
|
||||
if (this.instantiatedComposites[i].getId() === id) {
|
||||
return this.instantiatedComposites[i];
|
||||
}
|
||||
const compositeItem = this.instantiatedCompositeItems.get(id);
|
||||
if (compositeItem) {
|
||||
return compositeItem.composite;
|
||||
}
|
||||
|
||||
// Instantiate composite from registry otherwise
|
||||
@@ -172,18 +173,18 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
const compositeInstantiationService = this.instantiationService.createChild(new ServiceCollection([IProgressService, progressService]));
|
||||
|
||||
const composite = compositeDescriptor.instantiate(compositeInstantiationService);
|
||||
this.mapProgressServiceToComposite[composite.getId()] = progressService;
|
||||
const disposables: IDisposable[] = [];
|
||||
|
||||
// Remember as Instantiated
|
||||
this.instantiatedComposites.push(composite);
|
||||
this.instantiatedCompositeItems.set(id, { composite, disposable: toDisposable(() => dispose(disposables)), progressService });
|
||||
|
||||
// Register to title area update events from the composite
|
||||
this.instantiatedCompositeListeners.push(composite.onTitleAreaUpdate(() => this.onTitleAreaUpdate(composite.getId())));
|
||||
composite.onTitleAreaUpdate(() => this.onTitleAreaUpdate(composite.getId()), this, disposables);
|
||||
|
||||
return composite;
|
||||
}
|
||||
|
||||
throw new Error(strings.format('Unable to find composite with id {0}', id));
|
||||
throw new Error(`Unable to find composite with id ${id}`);
|
||||
}
|
||||
|
||||
protected showComposite(composite: Composite): void {
|
||||
@@ -219,19 +220,22 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
}
|
||||
|
||||
// Report progress for slow loading composites (but only if we did not create the composites before already)
|
||||
const progressService = this.mapProgressServiceToComposite[composite.getId()];
|
||||
if (progressService && !compositeContainer) {
|
||||
this.mapProgressServiceToComposite[composite.getId()].showWhile(Promise.resolve(), this.partService.isRestored() ? 800 : 3200 /* less ugly initial startup */);
|
||||
const compositeItem = this.instantiatedCompositeItems.get(composite.getId());
|
||||
if (compositeItem && !compositeContainer) {
|
||||
compositeItem.progressService.showWhile(Promise.resolve(), this.partService.isRestored() ? 800 : 3200 /* less ugly initial startup */);
|
||||
}
|
||||
|
||||
// Fill Content and Actions
|
||||
// Make sure that the user meanwhile did not open another composite or closed the part containing the composite
|
||||
if (!this.activeComposite || composite.getId() !== this.activeComposite.getId()) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Take Composite on-DOM and show
|
||||
this.getContentArea().appendChild(compositeContainer);
|
||||
const contentArea = this.getContentArea();
|
||||
if (contentArea) {
|
||||
contentArea.appendChild(compositeContainer);
|
||||
}
|
||||
show(compositeContainer);
|
||||
|
||||
// Setup action runner
|
||||
@@ -240,7 +244,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
// Update title with composite title if it differs from descriptor
|
||||
const descriptor = this.registry.getComposite(composite.getId());
|
||||
if (descriptor && descriptor.name !== composite.getTitle()) {
|
||||
this.updateTitle(composite.getId(), composite.getTitle());
|
||||
this.updateTitle(composite.getId(), composite.getTitle() || undefined);
|
||||
}
|
||||
|
||||
// Handle Composite Actions
|
||||
@@ -296,7 +300,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
if (this.activeComposite && this.activeComposite.getId() === compositeId) {
|
||||
|
||||
// Title
|
||||
this.updateTitle(this.activeComposite.getId(), this.activeComposite.getTitle());
|
||||
this.updateTitle(this.activeComposite.getId(), this.activeComposite.getTitle() || undefined);
|
||||
|
||||
// Actions
|
||||
const actionsBinding = this.collectCompositeActions(this.activeComposite);
|
||||
@@ -322,7 +326,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
|
||||
const keybinding = this.keybindingService.lookupKeybinding(compositeId);
|
||||
|
||||
this.titleLabel.updateTitle(compositeId, compositeTitle, keybinding ? keybinding.getLabel() : undefined);
|
||||
this.titleLabel.updateTitle(compositeId, compositeTitle, (keybinding && keybinding.getLabel()) || undefined);
|
||||
|
||||
this.toolBar.setAriaLabel(nls.localize('ariaCompositeToolbarLabel', "{0} actions", compositeTitle));
|
||||
}
|
||||
@@ -341,7 +345,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
return this.toolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions));
|
||||
}
|
||||
|
||||
protected getActiveComposite(): IComposite {
|
||||
protected getActiveComposite(): IComposite | null {
|
||||
return this.activeComposite;
|
||||
}
|
||||
|
||||
@@ -349,7 +353,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
return this.lastActiveCompositeId;
|
||||
}
|
||||
|
||||
protected hideActiveComposite(): Composite {
|
||||
protected hideActiveComposite(): Composite | undefined {
|
||||
if (!this.activeComposite) {
|
||||
return undefined; // Nothing to do
|
||||
}
|
||||
@@ -423,14 +427,14 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
this.titleLabel.updateStyles();
|
||||
}
|
||||
|
||||
protected actionItemProvider(action: Action): IActionItem {
|
||||
protected actionItemProvider(action: Action): IActionItem | null {
|
||||
|
||||
// Check Active Composite
|
||||
if (this.activeComposite) {
|
||||
return this.activeComposite.getActionItem(action);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return null;
|
||||
}
|
||||
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
@@ -443,8 +447,9 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
return contentContainer;
|
||||
}
|
||||
|
||||
getProgressIndicator(id: string): IProgressService {
|
||||
return this.mapProgressServiceToComposite[id];
|
||||
getProgressIndicator(id: string): IProgressService | null {
|
||||
const compositeItem = this.instantiatedCompositeItems.get(id);
|
||||
return compositeItem ? compositeItem.progressService : null;
|
||||
}
|
||||
|
||||
protected getActions(): IAction[] {
|
||||
@@ -459,10 +464,11 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
return AnchorAlignment.RIGHT;
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): Dimension[] {
|
||||
|
||||
layout(dimension: Dimension): Dimension[];
|
||||
layout(width: number, height: number): void;
|
||||
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
|
||||
// Pass to super
|
||||
const sizes = super.layout(dimension);
|
||||
const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2!));
|
||||
|
||||
// Pass Contentsize to composite
|
||||
this.contentAreaSize = sizes[1];
|
||||
@@ -470,20 +476,38 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
||||
this.activeComposite.layout(this.contentAreaSize);
|
||||
}
|
||||
|
||||
return sizes;
|
||||
if (dim1 instanceof Dimension) {
|
||||
return sizes;
|
||||
}
|
||||
}
|
||||
|
||||
protected removeComposite(compositeId: string): boolean {
|
||||
if (this.activeComposite && this.activeComposite.getId() === compositeId) {
|
||||
// do not remove active compoiste
|
||||
return false;
|
||||
}
|
||||
|
||||
delete this.mapCompositeToCompositeContainer[compositeId];
|
||||
delete this.mapActionsBindingToComposite[compositeId];
|
||||
const compositeItem = this.instantiatedCompositeItems.get(compositeId);
|
||||
if (compositeItem) {
|
||||
compositeItem.composite.dispose();
|
||||
dispose(compositeItem.disposable);
|
||||
this.instantiatedCompositeItems.delete(compositeId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.mapCompositeToCompositeContainer = null;
|
||||
this.mapProgressServiceToComposite = null;
|
||||
this.mapActionsBindingToComposite = null;
|
||||
this.mapCompositeToCompositeContainer = null!; // StrictNullOverride: nulling out ok in dispose
|
||||
this.mapActionsBindingToComposite = null!; // StrictNullOverride: nulling out ok in dispose
|
||||
|
||||
for (let i = 0; i < this.instantiatedComposites.length; i++) {
|
||||
this.instantiatedComposites[i].dispose();
|
||||
}
|
||||
this.instantiatedCompositeItems.forEach(compositeItem => {
|
||||
compositeItem.composite.dispose();
|
||||
dispose(compositeItem.disposable);
|
||||
});
|
||||
|
||||
this.instantiatedComposites = [];
|
||||
this.instantiatedCompositeListeners = dispose(this.instantiatedCompositeListeners);
|
||||
this.instantiatedCompositeItems.clear();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/group/
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { LRUCache } from 'vs/base/common/map';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { once, Event } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { isEmptyObject } from 'vs/base/common/types';
|
||||
import { DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor';
|
||||
|
||||
@@ -38,12 +38,12 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
readonly minimumHeight = DEFAULT_EDITOR_MIN_DIMENSIONS.height;
|
||||
readonly maximumHeight = DEFAULT_EDITOR_MAX_DIMENSIONS.height;
|
||||
|
||||
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }> = Event.None;
|
||||
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; } | undefined> = Event.None;
|
||||
|
||||
protected _input: EditorInput;
|
||||
protected _options: EditorOptions;
|
||||
protected _input: EditorInput | null;
|
||||
protected _options: EditorOptions | null;
|
||||
|
||||
private _group: IEditorGroup;
|
||||
private _group?: IEditorGroup;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -54,15 +54,15 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
super(id, telemetryService, themeService, storageService);
|
||||
}
|
||||
|
||||
get input(): EditorInput {
|
||||
get input(): EditorInput | null {
|
||||
return this._input;
|
||||
}
|
||||
|
||||
get options(): EditorOptions {
|
||||
get options(): EditorOptions | null {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
get group(): IEditorGroup {
|
||||
get group(): IEditorGroup | undefined {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
* The provided cancellation token should be used to test if the operation
|
||||
* was cancelled.
|
||||
*/
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
|
||||
setInput(input: EditorInput, options: EditorOptions | null, token: CancellationToken): Promise<void> {
|
||||
this._input = input;
|
||||
this._options = options;
|
||||
|
||||
@@ -100,7 +100,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
* Sets the given options to the editor. Clients should apply the options
|
||||
* to the current input.
|
||||
*/
|
||||
setOptions(options: EditorOptions): void {
|
||||
setOptions(options: EditorOptions | null): void {
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
|
||||
setVisible(visible: boolean, group?: IEditorGroup): void {
|
||||
super.setVisible(visible);
|
||||
|
||||
// Propagate to Editor
|
||||
this.setEditorVisible(visible, group);
|
||||
}
|
||||
@@ -129,7 +130,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
* @param visible the state of visibility of this editor
|
||||
* @param group the editor group this editor is in.
|
||||
*/
|
||||
protected setEditorVisible(visible: boolean, group: IEditorGroup): void {
|
||||
protected setEditorVisible(visible: boolean, group: IEditorGroup | undefined): void {
|
||||
this._group = group;
|
||||
}
|
||||
|
||||
@@ -205,18 +206,18 @@ export class EditorMemento<T> implements IEditorMemento<T> {
|
||||
|
||||
// Automatically clear when editor input gets disposed if any
|
||||
if (resourceOrEditor instanceof EditorInput) {
|
||||
once(resourceOrEditor.onDispose)(() => {
|
||||
Event.once(resourceOrEditor.onDispose)(() => {
|
||||
this.clearEditorState(resource);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
loadEditorState(group: IEditorGroup, resource: URI): T;
|
||||
loadEditorState(group: IEditorGroup, editor: EditorInput): T;
|
||||
loadEditorState(group: IEditorGroup, resourceOrEditor: URI | EditorInput): T {
|
||||
loadEditorState(group: IEditorGroup, resource: URI): T | undefined;
|
||||
loadEditorState(group: IEditorGroup, editor: EditorInput): T | undefined;
|
||||
loadEditorState(group: IEditorGroup, resourceOrEditor: URI | EditorInput): T | undefined {
|
||||
const resource = this.doGetResource(resourceOrEditor);
|
||||
if (!resource || !group) {
|
||||
return void 0; // we are not in a good state to load any state for a resource
|
||||
return undefined; // we are not in a good state to load any state for a resource
|
||||
}
|
||||
|
||||
const cache = this.doLoad();
|
||||
@@ -226,7 +227,7 @@ export class EditorMemento<T> implements IEditorMemento<T> {
|
||||
return mementoForResource[group.id];
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
clearEditorState(resource: URI, group?: IEditorGroup): void;
|
||||
@@ -247,7 +248,7 @@ export class EditorMemento<T> implements IEditorMemento<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private doGetResource(resourceOrEditor: URI | EditorInput): URI {
|
||||
private doGetResource(resourceOrEditor: URI | EditorInput): URI | null {
|
||||
if (resourceOrEditor instanceof EditorInput) {
|
||||
return resourceOrEditor.getResource();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ export class BinaryResourceDiffEditor extends SideBySideEditor {
|
||||
super(telemetryService, instantiationService, themeService, storageService);
|
||||
}
|
||||
|
||||
getMetadata(): string {
|
||||
getMetadata(): string | null {
|
||||
const master = this.masterEditor;
|
||||
const details = this.detailsEditor;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
|
||||
export interface IOpenCallbacks {
|
||||
openInternal: (input: EditorInput, options: EditorOptions) => Thenable<void>;
|
||||
openInternal: (input: EditorInput, options: EditorOptions) => Promise<void>;
|
||||
openExternal: (uri: URI) => void;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
get onDidOpenInPlace(): Event<void> { return this._onDidOpenInPlace.event; }
|
||||
|
||||
private callbacks: IOpenCallbacks;
|
||||
private metadata: string;
|
||||
private metadata: string | null;
|
||||
private binaryContainer: HTMLElement;
|
||||
private scrollbar: DomScrollableElement;
|
||||
private resourceViewerContext: ResourceViewerContext;
|
||||
@@ -55,7 +55,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
getTitle() {
|
||||
return this.input ? this.input.getName() : nls.localize('binaryEditor', "Binary Viewer");
|
||||
}
|
||||
|
||||
@@ -72,13 +72,13 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
parent.appendChild(this.scrollbar.getDomNode());
|
||||
}
|
||||
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
|
||||
return super.setInput(input, options, token).then(() => {
|
||||
return input.resolve().then(model => {
|
||||
|
||||
// Check for cancellation
|
||||
if (token.isCancellationRequested) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Assert Model instance
|
||||
@@ -97,7 +97,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
meta => this.handleMetadataChanged(meta)
|
||||
);
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -110,13 +110,13 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
});
|
||||
}
|
||||
|
||||
private handleMetadataChanged(meta: string): void {
|
||||
private handleMetadataChanged(meta: string | null): void {
|
||||
this.metadata = meta;
|
||||
|
||||
this._onMetadataChanged.fire();
|
||||
}
|
||||
|
||||
getMetadata(): string {
|
||||
getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export interface IBreadcrumbsService {
|
||||
|
||||
register(group: GroupIdentifier, widget: BreadcrumbsWidget): IDisposable;
|
||||
|
||||
getWidget(group: GroupIdentifier): BreadcrumbsWidget;
|
||||
getWidget(group: GroupIdentifier): BreadcrumbsWidget | undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,12 +43,12 @@ export class BreadcrumbsService implements IBreadcrumbsService {
|
||||
};
|
||||
}
|
||||
|
||||
getWidget(group: number): BreadcrumbsWidget {
|
||||
getWidget(group: number): BreadcrumbsWidget | undefined {
|
||||
return this._map.get(group);
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IBreadcrumbsService, BreadcrumbsService);
|
||||
registerSingleton(IBreadcrumbsService, BreadcrumbsService, true);
|
||||
|
||||
|
||||
//#region config
|
||||
@@ -59,7 +59,7 @@ export abstract class BreadcrumbsConfig<T> {
|
||||
onDidChange: Event<void>;
|
||||
|
||||
abstract getValue(overrides?: IConfigurationOverrides): T;
|
||||
abstract updateValue(value: T, overrides?: IConfigurationOverrides): Thenable<void>;
|
||||
abstract updateValue(value: T, overrides?: IConfigurationOverrides): Promise<void>;
|
||||
abstract dispose(): void;
|
||||
|
||||
private constructor() {
|
||||
@@ -90,10 +90,18 @@ export abstract class BreadcrumbsConfig<T> {
|
||||
readonly name = name;
|
||||
readonly onDidChange = onDidChange.event;
|
||||
getValue(overrides?: IConfigurationOverrides): T {
|
||||
return service.getValue(name, overrides);
|
||||
if (overrides) {
|
||||
return service.getValue(name, overrides);
|
||||
} else {
|
||||
return service.getValue(name);
|
||||
}
|
||||
}
|
||||
updateValue(newValue: T, overrides?: IConfigurationOverrides): Thenable<void> {
|
||||
return service.updateValue(name, newValue, overrides);
|
||||
updateValue(newValue: T, overrides?: IConfigurationOverrides): Promise<void> {
|
||||
if (overrides) {
|
||||
return service.updateValue(name, newValue, overrides);
|
||||
} else {
|
||||
return service.updateValue(name, newValue);
|
||||
}
|
||||
}
|
||||
dispose(): void {
|
||||
listener.dispose();
|
||||
@@ -112,7 +120,7 @@ Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfigurat
|
||||
type: 'object',
|
||||
properties: {
|
||||
'breadcrumbs.enabled': {
|
||||
description: localize('enabled', "Enable/disable navigation breadcrumbs"),
|
||||
description: localize('enabled', "Enable/disable navigation breadcrumbs."),
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@ import { ColorIdentifier, ColorFunction } from 'vs/platform/theme/common/colorRe
|
||||
import { attachBreadcrumbsStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { FileLabel } from 'vs/workbench/browser/labels';
|
||||
import { ResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { BreadcrumbsConfig, IBreadcrumbsService } from 'vs/workbench/browser/parts/editor/breadcrumbs';
|
||||
import { BreadcrumbElement, EditorBreadcrumbsModel, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel';
|
||||
import { BreadcrumbsPicker, createBreadcrumbsPicker } from 'vs/workbench/browser/parts/editor/breadcrumbsPicker';
|
||||
@@ -78,8 +78,8 @@ class Item extends BreadcrumbsItem {
|
||||
render(container: HTMLElement): void {
|
||||
if (this.element instanceof FileElement) {
|
||||
// file/folder
|
||||
let label = this._instantiationService.createInstance(FileLabel, container, {});
|
||||
label.setFile(this.element.uri, {
|
||||
let label = this._instantiationService.createInstance(ResourceLabel, container, {});
|
||||
label.element.setFile(this.element.uri, {
|
||||
hidePath: true,
|
||||
hideIcon: this.element.kind === FileKind.FOLDER || !this.options.showFileIcons,
|
||||
fileKind: this.element.kind,
|
||||
@@ -98,7 +98,7 @@ class Item extends BreadcrumbsItem {
|
||||
} else if (this.element instanceof OutlineGroup) {
|
||||
// provider
|
||||
let label = new IconLabel(container);
|
||||
label.setValue(this.element.provider.displayName);
|
||||
label.setLabel(this.element.provider.displayName);
|
||||
this._disposables.push(label);
|
||||
|
||||
} else if (this.element instanceof OutlineElement) {
|
||||
@@ -111,7 +111,7 @@ class Item extends BreadcrumbsItem {
|
||||
}
|
||||
let label = new IconLabel(container);
|
||||
let title = this.element.symbol.name.replace(/\r|\n|\r\n/g, '\u23CE');
|
||||
label.setValue(title);
|
||||
label.setLabel(title);
|
||||
this._disposables.push(label);
|
||||
}
|
||||
}
|
||||
@@ -356,7 +356,7 @@ export class BreadcrumbsControl {
|
||||
},
|
||||
getAnchor: () => {
|
||||
let maxInnerWidth = window.innerWidth - 8 /*a little less the full widget*/;
|
||||
let maxHeight = Math.min(window.innerHeight * .7, 300);
|
||||
let maxHeight = Math.min(window.innerHeight * 0.7, 300);
|
||||
|
||||
let pickerWidth = Math.min(maxInnerWidth, Math.max(240, maxInnerWidth / 4.17));
|
||||
let pickerArrowSize = 8;
|
||||
@@ -379,7 +379,7 @@ export class BreadcrumbsControl {
|
||||
pickerArrowOffset = maxPickerArrowOffset;
|
||||
}
|
||||
} else {
|
||||
pickerArrowOffset = (data.left + (data.width * .3)) - x;
|
||||
pickerArrowOffset = (data.left + (data.width * 0.3)) - x;
|
||||
}
|
||||
picker.setInput(element, maxHeight, pickerWidth, pickerArrowSize, Math.max(0, pickerArrowOffset));
|
||||
return { x, y };
|
||||
@@ -453,15 +453,17 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
category: localize('cmd.category', "View")
|
||||
}
|
||||
});
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
|
||||
group: '5_editor',
|
||||
order: 99,
|
||||
command: {
|
||||
id: 'breadcrumbs.toggle',
|
||||
title: localize('miToggleBreadcrumbs', "Toggle &&Breadcrumbs"),
|
||||
toggled: ContextKeyExpr.equals('config.breadcrumbs.enabled', true)
|
||||
}
|
||||
});
|
||||
// {{SQL CARBON EDIT}} - Disable unused menu item
|
||||
// MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
|
||||
// group: '5_editor',
|
||||
// order: 99,
|
||||
// command: {
|
||||
// id: 'breadcrumbs.toggle',
|
||||
// title: localize('miToggleBreadcrumbs', "Toggle &&Breadcrumbs"),
|
||||
// toggled: ContextKeyExpr.equals('config.breadcrumbs.enabled', true)
|
||||
// }
|
||||
// });
|
||||
// {{SQL CARBON EDIT}} - End
|
||||
CommandsRegistry.registerCommand('breadcrumbs.toggle', accessor => {
|
||||
let config = accessor.get(IConfigurationService);
|
||||
let value = BreadcrumbsConfig.IsEnabled.bindTo(config).getValue();
|
||||
|
||||
@@ -8,7 +8,7 @@ import { TimeoutTimer } from 'vs/base/common/async';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { size } from 'vs/base/common/collections';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { debounceEvent, Emitter, Event } from 'vs/base/common/event';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isEqual, dirname } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -31,7 +31,7 @@ export class FileElement {
|
||||
|
||||
export type BreadcrumbElement = FileElement | OutlineModel | OutlineGroup | OutlineElement;
|
||||
|
||||
type FileInfo = { path: FileElement[], folder: IWorkspaceFolder };
|
||||
type FileInfo = { path: FileElement[], folder?: IWorkspaceFolder };
|
||||
|
||||
export class EditorBreadcrumbsModel {
|
||||
|
||||
@@ -41,7 +41,7 @@ export class EditorBreadcrumbsModel {
|
||||
private readonly _cfgFilePath: BreadcrumbsConfig<'on' | 'off' | 'last'>;
|
||||
private readonly _cfgSymbolPath: BreadcrumbsConfig<'on' | 'off' | 'last'>;
|
||||
|
||||
private _outlineElements: (OutlineModel | OutlineGroup | OutlineElement)[] = [];
|
||||
private _outlineElements: Array<OutlineModel | OutlineGroup | OutlineElement> = [];
|
||||
private _outlineDisposables: IDisposable[] = [];
|
||||
|
||||
private _onDidUpdate = new Emitter<this>();
|
||||
@@ -105,16 +105,21 @@ export class EditorBreadcrumbsModel {
|
||||
}
|
||||
|
||||
let info: FileInfo = {
|
||||
folder: workspaceService.getWorkspaceFolder(uri),
|
||||
folder: workspaceService.getWorkspaceFolder(uri) || undefined,
|
||||
path: []
|
||||
};
|
||||
|
||||
while (uri.path !== '/') {
|
||||
if (info.folder && isEqual(info.folder.uri, uri)) {
|
||||
let uriPrefix: URI | null = uri;
|
||||
while (uriPrefix && uriPrefix.path !== '/') {
|
||||
if (info.folder && isEqual(info.folder.uri, uriPrefix)) {
|
||||
break;
|
||||
}
|
||||
info.path.unshift(new FileElement(uriPrefix, info.path.length === 0 ? FileKind.FILE : FileKind.FOLDER));
|
||||
let prevPathLength = uriPrefix.path.length;
|
||||
uriPrefix = dirname(uriPrefix);
|
||||
if (!uriPrefix || uriPrefix.path.length === prevPathLength) {
|
||||
break;
|
||||
}
|
||||
info.path.unshift(new FileElement(uri, info.path.length === 0 ? FileKind.FILE : FileKind.FOLDER));
|
||||
uri = dirname(uri);
|
||||
}
|
||||
|
||||
if (info.folder && workspaceService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
|
||||
@@ -131,7 +136,7 @@ export class EditorBreadcrumbsModel {
|
||||
this._disposables.push(DocumentSymbolProviderRegistry.onDidChange(_ => this._updateOutline()));
|
||||
this._disposables.push(this._editor.onDidChangeModel(_ => this._updateOutline()));
|
||||
this._disposables.push(this._editor.onDidChangeModelLanguage(_ => this._updateOutline()));
|
||||
this._disposables.push(debounceEvent(this._editor.onDidChangeModelContent, _ => _, 350)(_ => this._updateOutline(true)));
|
||||
this._disposables.push(Event.debounce(this._editor.onDidChangeModelContent, _ => _, 350)(_ => this._updateOutline(true)));
|
||||
this._updateOutline();
|
||||
|
||||
// stop when editor dies
|
||||
@@ -145,7 +150,9 @@ export class EditorBreadcrumbsModel {
|
||||
this._updateOutlineElements([]);
|
||||
}
|
||||
|
||||
const buffer = this._editor.getModel();
|
||||
const editor = this._editor!;
|
||||
|
||||
const buffer = editor.getModel();
|
||||
if (!buffer || !DocumentSymbolProviderRegistry.has(buffer) || !isEqual(buffer.uri, this._uri)) {
|
||||
return;
|
||||
}
|
||||
@@ -171,11 +178,11 @@ export class EditorBreadcrumbsModel {
|
||||
// copy the model
|
||||
model = model.adopt();
|
||||
|
||||
this._updateOutlineElements(this._getOutlineElements(model, this._editor.getPosition()));
|
||||
this._outlineDisposables.push(this._editor.onDidChangeCursorPosition(_ => {
|
||||
this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition()));
|
||||
this._outlineDisposables.push(editor.onDidChangeCursorPosition(_ => {
|
||||
timeout.cancelAndSet(() => {
|
||||
if (!buffer.isDisposed() && versionIdThen === buffer.getVersionId() && this._editor.getModel()) {
|
||||
this._updateOutlineElements(this._getOutlineElements(model, this._editor.getPosition()));
|
||||
if (!buffer.isDisposed() && versionIdThen === buffer.getVersionId() && editor.getModel()) {
|
||||
this._updateOutlineElements(this._getOutlineElements(model, editor.getPosition()));
|
||||
}
|
||||
}, 150);
|
||||
}));
|
||||
@@ -186,22 +193,22 @@ export class EditorBreadcrumbsModel {
|
||||
});
|
||||
}
|
||||
|
||||
private _getOutlineElements(model: OutlineModel, position: IPosition): (OutlineModel | OutlineGroup | OutlineElement)[] {
|
||||
if (!model) {
|
||||
private _getOutlineElements(model: OutlineModel, position: IPosition | null): Array<OutlineModel | OutlineGroup | OutlineElement> {
|
||||
if (!model || !position) {
|
||||
return [];
|
||||
}
|
||||
let item: OutlineGroup | OutlineElement = model.getItemEnclosingPosition(position);
|
||||
let item: OutlineGroup | OutlineElement | undefined = model.getItemEnclosingPosition(position);
|
||||
if (!item) {
|
||||
return [model];
|
||||
}
|
||||
let chain: (OutlineGroup | OutlineElement)[] = [];
|
||||
let chain: Array<OutlineGroup | OutlineElement> = [];
|
||||
while (item) {
|
||||
chain.push(item);
|
||||
let parent = item.parent;
|
||||
if (parent instanceof OutlineModel) {
|
||||
break;
|
||||
}
|
||||
if (parent instanceof OutlineGroup && size(parent.parent.children) === 1) {
|
||||
if (parent instanceof OutlineGroup && parent.parent && size(parent.parent.children) === 1) {
|
||||
break;
|
||||
}
|
||||
item = parent;
|
||||
@@ -209,7 +216,7 @@ export class EditorBreadcrumbsModel {
|
||||
return chain.reverse();
|
||||
}
|
||||
|
||||
private _updateOutlineElements(elements: (OutlineModel | OutlineGroup | OutlineElement)[]): void {
|
||||
private _updateOutlineElements(elements: Array<OutlineModel | OutlineGroup | OutlineElement>): void {
|
||||
if (!equals(elements, this._outlineElements, EditorBreadcrumbsModel._outlineElementEquals)) {
|
||||
this._outlineElements = elements;
|
||||
this._onDidUpdate.fire(this);
|
||||
|
||||
@@ -14,7 +14,6 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { join } from 'vs/base/common/paths';
|
||||
import { basename, dirname, isEqual } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IDataSource, IFilter, IRenderer, ISorter, ITree } from 'vs/base/parts/tree/browser/tree';
|
||||
import 'vs/css!./media/breadcrumbscontrol';
|
||||
import { OutlineElement, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel';
|
||||
@@ -26,7 +25,7 @@ import { IConstructorSignature1, IInstantiationService } from 'vs/platform/insta
|
||||
import { HighlightingWorkbenchTree, IHighlighter, IHighlightingTreeConfiguration, IHighlightingTreeOptions } from 'vs/platform/list/browser/listService';
|
||||
import { breadcrumbsPickerBackground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { FileLabel } from 'vs/workbench/browser/labels';
|
||||
import { ResourceLabels, IResourceLabel, DEFAULT_LABELS_CONTAINER } from 'vs/workbench/browser/labels';
|
||||
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
|
||||
import { BreadcrumbElement, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel';
|
||||
import { IFileIconTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
@@ -160,7 +159,7 @@ export abstract class BreadcrumbsPicker {
|
||||
// use proper selection, reveal
|
||||
let selection = this._getInitialSelection(this._tree, input);
|
||||
if (selection) {
|
||||
return this._tree.reveal(selection, .5).then(() => {
|
||||
return this._tree.reveal(selection, 0.5).then(() => {
|
||||
this._tree.setSelection([selection], this._tree);
|
||||
this._tree.setFocus(selection);
|
||||
this._tree.domFocus();
|
||||
@@ -228,7 +227,7 @@ export class FileDataSource implements IDataSource {
|
||||
return URI.isUri(element) || IWorkspace.isIWorkspace(element) || IWorkspaceFolder.isIWorkspaceFolder(element) || element.isDirectory;
|
||||
}
|
||||
|
||||
getChildren(tree: ITree, element: IWorkspace | IWorkspaceFolder | IFileStat | URI): TPromise<IWorkspaceFolder[] | IFileStat[]> {
|
||||
getChildren(tree: ITree, element: IWorkspace | IWorkspaceFolder | IFileStat | URI): Promise<IWorkspaceFolder[] | IFileStat[]> {
|
||||
if (IWorkspace.isIWorkspace(element)) {
|
||||
return Promise.resolve(element.folders).then(folders => {
|
||||
for (let child of folders) {
|
||||
@@ -253,7 +252,7 @@ export class FileDataSource implements IDataSource {
|
||||
});
|
||||
}
|
||||
|
||||
getParent(tree: ITree, element: IWorkspace | URI | IWorkspaceFolder | IFileStat): TPromise<IWorkspaceFolder | IFileStat> {
|
||||
getParent(tree: ITree, element: IWorkspace | URI | IWorkspaceFolder | IFileStat): Promise<IWorkspaceFolder | IFileStat> {
|
||||
return Promise.resolve(this._parents.get(element));
|
||||
}
|
||||
}
|
||||
@@ -330,7 +329,7 @@ export class FileHighlighter implements IHighlighter {
|
||||
export class FileRenderer implements IRenderer {
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
private readonly _labels: ResourceLabels,
|
||||
@IConfigurationService private readonly _configService: IConfigurationService,
|
||||
) { }
|
||||
|
||||
@@ -343,10 +342,10 @@ export class FileRenderer implements IRenderer {
|
||||
}
|
||||
|
||||
renderTemplate(tree: ITree, templateId: string, container: HTMLElement) {
|
||||
return this._instantiationService.createInstance(FileLabel, container, { supportHighlights: true });
|
||||
return this._labels.create(container, { supportHighlights: true });
|
||||
}
|
||||
|
||||
renderElement(tree: ITree, element: IFileStat | IWorkspaceFolder, templateId: string, templateData: FileLabel): void {
|
||||
renderElement(tree: ITree, element: IFileStat | IWorkspaceFolder, templateId: string, templateData: IResourceLabel): void {
|
||||
let fileDecorations = this._configService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
|
||||
let resource: URI;
|
||||
let fileKind: FileKind;
|
||||
@@ -366,7 +365,7 @@ export class FileRenderer implements IRenderer {
|
||||
});
|
||||
}
|
||||
|
||||
disposeTemplate(tree: ITree, templateId: string, templateData: FileLabel): void {
|
||||
disposeTemplate(tree: ITree, templateId: string, templateData: IResourceLabel): void {
|
||||
templateData.dispose();
|
||||
}
|
||||
}
|
||||
@@ -428,7 +427,9 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
|
||||
this._disposables.push(filter);
|
||||
|
||||
config.dataSource = this._instantiationService.createInstance(FileDataSource);
|
||||
config.renderer = this._instantiationService.createInstance(FileRenderer);
|
||||
const labels = this._instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER /* TODO@Jo visibility propagation */);
|
||||
this._disposables.push(labels);
|
||||
config.renderer = this._instantiationService.createInstance(FileRenderer, labels);
|
||||
config.sorter = new FileSorter();
|
||||
config.highlighter = new FileHighlighter();
|
||||
config.filter = filter;
|
||||
|
||||
@@ -50,6 +50,7 @@ import { AllEditorsPicker, ActiveEditorGroupPicker } from 'vs/workbench/browser/
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { OpenWorkspaceButtonContribution } from 'vs/workbench/browser/parts/editor/editorWidgets';
|
||||
import { ZoomStatusbarItem } from 'vs/workbench/browser/parts/editor/resourceViewer';
|
||||
|
||||
// Register String Editor
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
@@ -110,7 +111,7 @@ interface ISerializedUntitledEditorInput {
|
||||
class UntitledEditorInputFactory implements IEditorInputFactory {
|
||||
|
||||
constructor(
|
||||
@ITextFileService private textFileService: ITextFileService
|
||||
@ITextFileService private readonly textFileService: ITextFileService
|
||||
) { }
|
||||
|
||||
serialize(editorInput: EditorInput): string {
|
||||
@@ -144,7 +145,7 @@ class UntitledEditorInputFactory implements IEditorInputFactory {
|
||||
return instantiationService.invokeFunction<UntitledEditorInput>(accessor => {
|
||||
const deserialized: ISerializedUntitledEditorInput = JSON.parse(serializedEditorInput);
|
||||
const resource = !!deserialized.resourceJSON ? URI.revive(deserialized.resourceJSON) : URI.parse(deserialized.resource);
|
||||
const filePath = resource.scheme === Schemas.file ? resource.fsPath : void 0;
|
||||
const filePath = resource.scheme === Schemas.file ? resource.fsPath : undefined;
|
||||
const language = deserialized.modeId;
|
||||
const encoding = deserialized.encoding;
|
||||
|
||||
@@ -226,6 +227,9 @@ registerEditorContribution(OpenWorkspaceButtonContribution);
|
||||
const statusBar = Registry.as<IStatusbarRegistry>(StatusExtensions.Statusbar);
|
||||
statusBar.registerStatusbarItem(new StatusbarItemDescriptor(EditorStatus, StatusbarAlignment.RIGHT, 100 /* towards the left of the right hand side */));
|
||||
|
||||
// Register Zoom Status
|
||||
statusBar.registerStatusbarItem(new StatusbarItemDescriptor(ZoomStatusbarItem, StatusbarAlignment.RIGHT, 101 /* to the left of editor status (100) */));
|
||||
|
||||
// Register Status Actions
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeModeAction, ChangeModeAction.ID, ChangeModeAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_M) }), 'Change Language Mode');
|
||||
@@ -235,7 +239,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeEncodingAction,
|
||||
export class QuickOpenActionContributor extends ActionBarContributor {
|
||||
private openToSideActionInstance: OpenToSideFromQuickOpenAction;
|
||||
|
||||
constructor(@IInstantiationService private instantiationService: IInstantiationService) {
|
||||
constructor(@IInstantiationService private readonly instantiationService: IInstantiationService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -745,7 +749,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, {
|
||||
|
||||
// Forward/Back
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
||||
group: '1_fwd_back',
|
||||
group: '1_history_nav',
|
||||
command: {
|
||||
id: 'workbench.action.navigateBack',
|
||||
title: nls.localize({ key: 'miBack', comment: ['&& denotes a mnemonic'] }, "&&Back"),
|
||||
@@ -755,7 +759,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
||||
group: '1_fwd_back',
|
||||
group: '1_history_nav',
|
||||
command: {
|
||||
id: 'workbench.action.navigateForward',
|
||||
title: nls.localize({ key: 'miForward', comment: ['&& denotes a mnemonic'] }, "&&Forward"),
|
||||
@@ -764,6 +768,16 @@ MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
||||
order: 2
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
||||
group: '1_history_nav',
|
||||
command: {
|
||||
id: 'workbench.action.navigateToLastEditLocation',
|
||||
title: nls.localize({ key: 'miLastEditLocation', comment: ['&& denotes a mnemonic'] }, "&&Last Edit Location"),
|
||||
precondition: ContextKeyExpr.has('canNavigateToLastEditLocation')
|
||||
},
|
||||
order: 3
|
||||
});
|
||||
|
||||
// Switch Editor
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
|
||||
group: '1_any',
|
||||
@@ -802,7 +816,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarSwitchEditorMenu, {
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
||||
group: '2_switch',
|
||||
group: '2_editor_nav',
|
||||
title: nls.localize({ key: 'miSwitchEditor', comment: ['&& denotes a mnemonic'] }, "Switch &&Editor"),
|
||||
submenu: MenuId.MenubarSwitchEditorMenu,
|
||||
order: 1
|
||||
@@ -909,7 +923,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarSwitchGroupMenu, {
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
||||
group: '2_switch',
|
||||
group: '2_editor_nav',
|
||||
title: nls.localize({ key: 'miSwitchGroup', comment: ['&& denotes a mnemonic'] }, "Switch &&Group"),
|
||||
submenu: MenuId.MenubarSwitchGroupMenu,
|
||||
order: 2
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration, IWorkbenchEditorPartConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent } from 'vs/workbench/common/editor';
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration, IWorkbenchEditorPartConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditor } from 'vs/workbench/common/editor';
|
||||
import { EditorGroup } from 'vs/workbench/common/editor/editorGroup';
|
||||
import { IEditorGroup, GroupDirection, IAddGroupOptions, IMergeGroupOptions, GroupsOrder, IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -30,6 +30,7 @@ export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
|
||||
highlightModifiedTabs: false,
|
||||
tabCloseButton: 'right',
|
||||
tabSizing: 'fit',
|
||||
focusRecentEditorAfterClose: true,
|
||||
showIcons: true,
|
||||
enablePreview: true,
|
||||
openPositioning: 'right',
|
||||
@@ -74,9 +75,9 @@ export interface IEditorOpeningEvent extends IEditorIdentifier {
|
||||
* that will be executed instead. By returning another editor promise
|
||||
* it is possible to override the opening with another editor. It is ok
|
||||
* to return a promise that resolves to NULL to prevent the opening
|
||||
* altogether.
|
||||
* alltogether.
|
||||
*/
|
||||
prevent(callback: () => Thenable<any>): void;
|
||||
prevent(callback: () => Promise<IEditor>): void;
|
||||
}
|
||||
|
||||
export interface IEditorGroupsAccessor {
|
||||
@@ -102,7 +103,7 @@ export interface IEditorGroupsAccessor {
|
||||
|
||||
export interface IEditorGroupView extends IDisposable, ISerializableView, IEditorGroup {
|
||||
readonly group: EditorGroup;
|
||||
readonly whenRestored: Thenable<void>;
|
||||
readonly whenRestored: Promise<void>;
|
||||
readonly disposed: boolean;
|
||||
|
||||
readonly onDidFocus: Event<void>;
|
||||
@@ -119,7 +120,7 @@ export interface IEditorGroupView extends IDisposable, ISerializableView, IEdito
|
||||
}
|
||||
|
||||
export function getActiveTextEditorOptions(group: IEditorGroup, expectedActiveEditor?: IEditorInput, presetOptions?: EditorOptions): EditorOptions {
|
||||
const activeGroupCodeEditor = group.activeControl ? getCodeEditor(group.activeControl.getControl()) : void 0;
|
||||
const activeGroupCodeEditor = group.activeControl ? getCodeEditor(group.activeControl.getControl()) : undefined;
|
||||
if (activeGroupCodeEditor) {
|
||||
if (!expectedActiveEditor || expectedActiveEditor.matches(group.activeEditor)) {
|
||||
return TextEditorOptions.fromEditor(activeGroupCodeEditor, presetOptions);
|
||||
@@ -155,5 +156,5 @@ export interface EditorGroupsServiceImpl extends IEditorGroupsService {
|
||||
/**
|
||||
* A promise that resolves when groups have been restored.
|
||||
*/
|
||||
readonly whenRestored: Thenable<void>;
|
||||
readonly whenRestored: Promise<void>;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export class ExecuteCommandAction extends Action {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
return this.commandService.executeCommand(this.commandId, this.commandArgs);
|
||||
}
|
||||
}
|
||||
@@ -182,7 +182,7 @@ export class JoinTwoGroupsAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
@@ -196,8 +196,8 @@ export class JoinTwoGroupsAction extends Action {
|
||||
}
|
||||
|
||||
const targetGroupDirections = [GroupDirection.RIGHT, GroupDirection.DOWN, GroupDirection.LEFT, GroupDirection.UP];
|
||||
for (let i = 0; i < targetGroupDirections.length; i++) {
|
||||
const targetGroup = this.editorGroupService.findGroup({ direction: targetGroupDirections[i] }, sourceGroup);
|
||||
for (const targetGroupDirection of targetGroupDirections) {
|
||||
const targetGroup = this.editorGroupService.findGroup({ direction: targetGroupDirection }, sourceGroup);
|
||||
if (targetGroup && sourceGroup !== targetGroup) {
|
||||
this.editorGroupService.mergeGroup(sourceGroup, targetGroup);
|
||||
|
||||
@@ -217,7 +217,7 @@ export class JoinAllGroupsAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
@@ -237,12 +237,12 @@ export class NavigateBetweenGroupsAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const nextGroup = this.editorGroupService.findGroup({ location: GroupLocation.NEXT }, this.editorGroupService.activeGroup, true);
|
||||
nextGroup.focus();
|
||||
|
||||
@@ -258,12 +258,12 @@ export class FocusActiveGroupAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.editorGroupService.activeGroup.focus();
|
||||
|
||||
return Promise.resolve(true);
|
||||
@@ -276,12 +276,12 @@ export abstract class BaseFocusGroupAction extends Action {
|
||||
id: string,
|
||||
label: string,
|
||||
private scope: IFindGroupScope,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const group = this.editorGroupService.findGroup(this.scope, this.editorGroupService.activeGroup, true);
|
||||
if (group) {
|
||||
group.focus();
|
||||
@@ -409,8 +409,8 @@ export class OpenToSideFromQuickOpenAction extends Action {
|
||||
static readonly OPEN_TO_SIDE_LABEL = nls.localize('openToSide', "Open to the Side");
|
||||
|
||||
constructor(
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super(OpenToSideFromQuickOpenAction.OPEN_TO_SIDE_ID, OpenToSideFromQuickOpenAction.OPEN_TO_SIDE_LABEL);
|
||||
|
||||
@@ -423,7 +423,7 @@ export class OpenToSideFromQuickOpenAction extends Action {
|
||||
this.class = (preferredDirection === GroupDirection.RIGHT) ? 'quick-open-sidebyside-vertical' : 'quick-open-sidebyside-horizontal';
|
||||
}
|
||||
|
||||
run(context: any): Thenable<any> {
|
||||
run(context: any): Promise<any> {
|
||||
const entry = toEditorQuickOpenEntry(context);
|
||||
if (entry) {
|
||||
const input = entry.getInput();
|
||||
@@ -467,13 +467,13 @@ export class CloseEditorAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super(id, label, 'close-editor-action');
|
||||
}
|
||||
|
||||
run(context?: IEditorCommandsContext): Promise<any> {
|
||||
return this.commandService.executeCommand(CLOSE_EDITOR_COMMAND_ID, void 0, context);
|
||||
return this.commandService.executeCommand(CLOSE_EDITOR_COMMAND_ID, undefined, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,12 +485,12 @@ export class CloseOneEditorAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label, 'close-editor-action');
|
||||
}
|
||||
|
||||
run(context?: IEditorCommandsContext): Thenable<any> {
|
||||
run(context?: IEditorCommandsContext): Promise<any> {
|
||||
let group: IEditorGroup;
|
||||
let editorIndex: number;
|
||||
if (context) {
|
||||
@@ -530,12 +530,12 @@ export class RevertAndCloseEditorAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorService private editorService: IEditorService
|
||||
@IEditorService private readonly editorService: IEditorService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const activeControl = this.editorService.activeControl;
|
||||
if (activeControl) {
|
||||
const editor = activeControl.input;
|
||||
@@ -563,13 +563,13 @@ export class CloseLeftEditorsInGroupAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(context?: IEditorIdentifier): Thenable<any> {
|
||||
run(context?: IEditorIdentifier): Promise<any> {
|
||||
const { group, editor } = getTarget(this.editorService, this.editorGroupService, context);
|
||||
if (group && editor) {
|
||||
return group.closeEditors({ direction: CloseDirection.LEFT, except: editor });
|
||||
@@ -614,7 +614,7 @@ export abstract class BaseCloseAllAction extends Action {
|
||||
return groupsToClose;
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
|
||||
// Just close all if there are no or one dirty editor
|
||||
if (this.textFileService.getDirty().length < 2) {
|
||||
@@ -624,10 +624,10 @@ export abstract class BaseCloseAllAction extends Action {
|
||||
// Otherwise ask for combined confirmation
|
||||
return this.textFileService.confirmSave().then(confirm => {
|
||||
if (confirm === ConfirmResult.CANCEL) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let saveOrRevertPromise: Thenable<boolean>;
|
||||
let saveOrRevertPromise: Promise<boolean>;
|
||||
if (confirm === ConfirmResult.DONT_SAVE) {
|
||||
saveOrRevertPromise = this.textFileService.revertAll(null, { soft: true }).then(() => true);
|
||||
} else {
|
||||
@@ -639,12 +639,12 @@ export abstract class BaseCloseAllAction extends Action {
|
||||
return this.doCloseAll();
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract doCloseAll(): Thenable<any>;
|
||||
protected abstract doCloseAll(): Promise<any>;
|
||||
}
|
||||
|
||||
export class CloseAllEditorsAction extends BaseCloseAllAction {
|
||||
@@ -677,7 +677,7 @@ export class CloseAllEditorGroupsAction extends BaseCloseAllAction {
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
super(id, label, void 0, textFileService, editorGroupService);
|
||||
super(id, label, undefined, textFileService, editorGroupService);
|
||||
}
|
||||
|
||||
protected doCloseAll(): Promise<any> {
|
||||
@@ -695,12 +695,12 @@ export class CloseEditorsInOtherGroupsAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(context?: IEditorIdentifier): Thenable<any> {
|
||||
run(context?: IEditorIdentifier): Promise<any> {
|
||||
const groupToSkip = context ? this.editorGroupService.getGroup(context.groupId) : this.editorGroupService.activeGroup;
|
||||
return Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(g => {
|
||||
if (g.id === groupToSkip.id) {
|
||||
@@ -720,13 +720,13 @@ export class CloseEditorInAllGroupsAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
|
||||
@IEditorService private editorService: IEditorService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IEditorService private readonly editorService: IEditorService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const activeEditor = this.editorService.activeEditor;
|
||||
if (activeEditor) {
|
||||
return Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(g => g.closeEditor(activeEditor)));
|
||||
@@ -780,14 +780,14 @@ export class BaseMoveGroupAction extends Action {
|
||||
break;
|
||||
}
|
||||
|
||||
for (let i = 0; i < targetNeighbours.length; i++) {
|
||||
const targetNeighbour = this.editorGroupService.findGroup({ direction: targetNeighbours[i] }, sourceGroup);
|
||||
if (targetNeighbour) {
|
||||
return targetNeighbour;
|
||||
for (const targetNeighbour of targetNeighbours) {
|
||||
const targetNeighbourGroup = this.editorGroupService.findGroup({ direction: targetNeighbour }, sourceGroup);
|
||||
if (targetNeighbourGroup) {
|
||||
return targetNeighbourGroup;
|
||||
}
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -852,11 +852,11 @@ export class MinimizeOtherGroupsAction extends Action {
|
||||
static readonly ID = 'workbench.action.minimizeOtherEditors';
|
||||
static readonly LABEL = nls.localize('minimizeOtherEditorGroups', "Maximize Editor Group");
|
||||
|
||||
constructor(id: string, label: string, @IEditorGroupsService private editorGroupService: IEditorGroupsService) {
|
||||
constructor(id: string, label: string, @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.editorGroupService.arrangeGroups(GroupsArrangement.MINIMIZE_OTHERS);
|
||||
|
||||
return Promise.resolve(false);
|
||||
@@ -868,11 +868,11 @@ export class ResetGroupSizesAction extends Action {
|
||||
static readonly ID = 'workbench.action.evenEditorWidths';
|
||||
static readonly LABEL = nls.localize('evenEditorGroups', "Reset Editor Group Sizes");
|
||||
|
||||
constructor(id: string, label: string, @IEditorGroupsService private editorGroupService: IEditorGroupsService) {
|
||||
constructor(id: string, label: string, @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.editorGroupService.arrangeGroups(GroupsArrangement.EVEN);
|
||||
|
||||
return Promise.resolve(false);
|
||||
@@ -887,14 +887,14 @@ export class MaximizeGroupAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
|
||||
@IPartService private partService: IPartService
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
if (this.editorService.activeEditor) {
|
||||
this.editorGroupService.arrangeGroups(GroupsArrangement.MINIMIZE_OTHERS);
|
||||
this.partService.setSideBarHidden(true);
|
||||
@@ -915,7 +915,7 @@ export abstract class BaseNavigateEditorAction extends Action {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const result = this.navigate();
|
||||
if (!result) {
|
||||
return Promise.resolve(false);
|
||||
@@ -964,7 +964,7 @@ export class OpenNextEditor extends BaseNavigateEditorAction {
|
||||
return { editor: previousGroupEditors[0], groupId: nextGroup.id };
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -999,7 +999,7 @@ export class OpenPreviousEditor extends BaseNavigateEditorAction {
|
||||
return { editor: previousGroupEditors[previousGroupEditors.length - 1], groupId: previousGroup.id };
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1098,11 +1098,11 @@ export class NavigateForwardAction extends Action {
|
||||
static readonly ID = 'workbench.action.navigateForward';
|
||||
static readonly LABEL = nls.localize('navigateNext', "Go Forward");
|
||||
|
||||
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
|
||||
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.historyService.forward();
|
||||
|
||||
return Promise.resolve(null);
|
||||
@@ -1114,11 +1114,11 @@ export class NavigateBackwardsAction extends Action {
|
||||
static readonly ID = 'workbench.action.navigateBack';
|
||||
static readonly LABEL = nls.localize('navigatePrevious', "Go Back");
|
||||
|
||||
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
|
||||
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.historyService.back();
|
||||
|
||||
return Promise.resolve(null);
|
||||
@@ -1130,11 +1130,11 @@ export class NavigateToLastEditLocationAction extends Action {
|
||||
static readonly ID = 'workbench.action.navigateToLastEditLocation';
|
||||
static readonly LABEL = nls.localize('navigateToLastEditLocation', "Go to Last Edit Location");
|
||||
|
||||
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
|
||||
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.historyService.openLastEditLocation();
|
||||
|
||||
return Promise.resolve(null);
|
||||
@@ -1146,11 +1146,11 @@ export class NavigateLastAction extends Action {
|
||||
static readonly ID = 'workbench.action.navigateLast';
|
||||
static readonly LABEL = nls.localize('navigateLast', "Go Last");
|
||||
|
||||
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
|
||||
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.historyService.last();
|
||||
|
||||
return Promise.resolve(null);
|
||||
@@ -1165,12 +1165,12 @@ export class ReopenClosedEditorAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IHistoryService private historyService: IHistoryService
|
||||
@IHistoryService private readonly historyService: IHistoryService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.historyService.reopenLastClosedEditor();
|
||||
|
||||
return Promise.resolve(false);
|
||||
@@ -1185,13 +1185,13 @@ export class ClearRecentFilesAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IWindowsService private windowsService: IWindowsService,
|
||||
@IHistoryService private historyService: IHistoryService
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
@IHistoryService private readonly historyService: IHistoryService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
|
||||
// Clear global recently opened
|
||||
this.windowsService.clearRecentlyOpened();
|
||||
@@ -1232,13 +1232,13 @@ export class BaseQuickOpenEditorInGroupAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService private quickOpenService: IQuickOpenService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const keys = this.keybindingService.lookupKeybindings(this.id);
|
||||
|
||||
|
||||
@@ -1287,13 +1287,13 @@ export class OpenPreviousEditorFromHistoryAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickOpenService private quickOpenService: IQuickOpenService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const keys = this.keybindingService.lookupKeybindings(this.id);
|
||||
|
||||
this.quickOpenService.show(null, { quickNavigateConfiguration: { keybindings: keys } });
|
||||
@@ -1307,11 +1307,11 @@ export class OpenNextRecentlyUsedEditorAction extends Action {
|
||||
static readonly ID = 'workbench.action.openNextRecentlyUsedEditor';
|
||||
static readonly LABEL = nls.localize('openNextRecentlyUsedEditor', "Open Next Recently Used Editor");
|
||||
|
||||
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
|
||||
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.historyService.forward(true);
|
||||
|
||||
return Promise.resolve(null);
|
||||
@@ -1323,11 +1323,11 @@ export class OpenPreviousRecentlyUsedEditorAction extends Action {
|
||||
static readonly ID = 'workbench.action.openPreviousRecentlyUsedEditor';
|
||||
static readonly LABEL = nls.localize('openPreviousRecentlyUsedEditor', "Open Previous Recently Used Editor");
|
||||
|
||||
constructor(id: string, label: string, @IHistoryService private historyService: IHistoryService) {
|
||||
constructor(id: string, label: string, @IHistoryService private readonly historyService: IHistoryService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.historyService.back(true);
|
||||
|
||||
return Promise.resolve(null);
|
||||
@@ -1342,12 +1342,12 @@ export class ClearEditorHistoryAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IHistoryService private historyService: IHistoryService
|
||||
@IHistoryService private readonly historyService: IHistoryService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
|
||||
// Editor history
|
||||
this.historyService.clear();
|
||||
@@ -1619,7 +1619,7 @@ export class BaseCreateEditorGroupAction extends Action {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.editorGroupService.addGroup(this.editorGroupService.activeGroup, this.direction, { activate: true });
|
||||
|
||||
return Promise.resolve(true);
|
||||
|
||||
@@ -267,8 +267,8 @@ function registerDiffEditorCommands(): void {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: TOGGLE_DIFF_SIDE_BY_SIDE,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
primary: void 0,
|
||||
when: undefined,
|
||||
primary: undefined,
|
||||
handler: accessor => toggleDiffSideBySide(accessor)
|
||||
});
|
||||
|
||||
@@ -287,8 +287,8 @@ function registerDiffEditorCommands(): void {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
primary: void 0,
|
||||
when: undefined,
|
||||
primary: undefined,
|
||||
handler: accessor => toggleDiffIgnoreTrimWhitespace(accessor)
|
||||
});
|
||||
}
|
||||
@@ -319,7 +319,7 @@ function registerOpenEditorAtIndexCommands(): void {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: OPEN_EDITOR_AT_INDEX_COMMAND_ID + visibleIndex,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
when: undefined,
|
||||
primary: KeyMod.Alt | toKeyCode(visibleIndex),
|
||||
mac: { primary: KeyMod.WinCtrl | toKeyCode(visibleIndex) },
|
||||
handler: accessor => openEditorAtIndex(accessor, editorIndex)
|
||||
@@ -340,7 +340,7 @@ function registerOpenEditorAtIndexCommands(): void {
|
||||
case 9: return KeyCode.KEY_9;
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ function registerFocusEditorGroupAtIndexCommands(): void {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: toCommandId(groupIndex),
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
when: undefined,
|
||||
primary: KeyMod.CtrlCmd | toKeyCode(groupIndex),
|
||||
handler: accessor => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
@@ -392,7 +392,7 @@ function registerFocusEditorGroupAtIndexCommands(): void {
|
||||
case 7: return 'workbench.action.focusEighthEditorGroup';
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function toKeyCode(index: number): KeyCode {
|
||||
@@ -406,7 +406,7 @@ function registerFocusEditorGroupAtIndexCommands(): void {
|
||||
case 7: return KeyCode.KEY_8;
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,7 +455,7 @@ function registerCloseEditorCommands() {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: CLOSE_SAVED_EDITORS_COMMAND_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
when: undefined,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_U),
|
||||
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
@@ -475,7 +475,7 @@ function registerCloseEditorCommands() {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
when: undefined,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_W),
|
||||
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
@@ -495,7 +495,7 @@ function registerCloseEditorCommands() {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: CLOSE_EDITOR_COMMAND_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
when: undefined,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_W,
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] },
|
||||
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
@@ -544,8 +544,8 @@ function registerCloseEditorCommands() {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
primary: void 0,
|
||||
when: undefined,
|
||||
primary: undefined,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_T },
|
||||
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
@@ -573,8 +573,8 @@ function registerCloseEditorCommands() {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
primary: void 0,
|
||||
when: undefined,
|
||||
primary: undefined,
|
||||
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
|
||||
@@ -590,7 +590,7 @@ function registerCloseEditorCommands() {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: KEEP_EDITOR_COMMAND_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
when: undefined,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.Enter),
|
||||
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
@@ -607,8 +607,8 @@ function registerCloseEditorCommands() {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: SHOW_EDITORS_IN_GROUP,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: void 0,
|
||||
primary: void 0,
|
||||
when: undefined,
|
||||
primary: undefined,
|
||||
handler: (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
@@ -638,7 +638,7 @@ function registerCloseEditorCommands() {
|
||||
});
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -655,7 +655,7 @@ function getCommandsContext(resourceOrContext: URI | IEditorCommandsContext, con
|
||||
return context;
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function resolveCommandsContext(editorGroupService: IEditorGroupsService, context?: IEditorCommandsContext): { group: IEditorGroup, editor: IEditorInput, control: IEditor } {
|
||||
@@ -682,7 +682,7 @@ export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsCon
|
||||
if (list instanceof List && list.getHTMLElement() === document.activeElement) {
|
||||
const elementToContext = (element: IEditorIdentifier | IEditorGroup) => {
|
||||
if (isEditorGroup(element)) {
|
||||
return { groupId: element.id, editorIndex: void 0 };
|
||||
return { groupId: element.id, editorIndex: undefined };
|
||||
}
|
||||
|
||||
return { groupId: element.groupId, editorIndex: editorGroupService.getGroup(element.groupId).getIndexOfEditor(element.editor) };
|
||||
@@ -690,11 +690,11 @@ export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsCon
|
||||
|
||||
const onlyEditorGroupAndEditor = (e: IEditorIdentifier | IEditorGroup) => isEditorGroup(e) || isEditorIdentifier(e);
|
||||
|
||||
const focusedElements: (IEditorIdentifier | IEditorGroup)[] = list.getFocusedElements().filter(onlyEditorGroupAndEditor);
|
||||
const focus = editorContext ? editorContext : focusedElements.length ? focusedElements.map(elementToContext)[0] : void 0; // need to take into account when editor context is { group: group }
|
||||
const focusedElements: Array<IEditorIdentifier | IEditorGroup> = list.getFocusedElements().filter(onlyEditorGroupAndEditor);
|
||||
const focus = editorContext ? editorContext : focusedElements.length ? focusedElements.map(elementToContext)[0] : undefined; // need to take into account when editor context is { group: group }
|
||||
|
||||
if (focus) {
|
||||
const selection: (IEditorIdentifier | IEditorGroup)[] = list.getSelectedElements().filter(onlyEditorGroupAndEditor);
|
||||
const selection: Array<IEditorIdentifier | IEditorGroup> = list.getSelectedElements().filter(onlyEditorGroupAndEditor);
|
||||
|
||||
// Only respect selection if it contains focused element
|
||||
if (selection && selection.some(s => isEditorGroup(s) ? s.id === focus.groupId : s.groupId === focus.groupId && editorGroupService.getGroup(s.groupId).getIndexOfEditor(s.editor) === focus.editorIndex)) {
|
||||
|
||||
@@ -8,7 +8,6 @@ import { EditorInput, EditorOptions } from 'vs/workbench/common/editor';
|
||||
import { Dimension, show, hide, addClass } from 'vs/base/browser/dom';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IEditorRegistry, Extensions as EditorExtensions, IEditorDescriptor } from 'vs/workbench/browser/editor';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -31,10 +30,10 @@ export class EditorControl extends Disposable {
|
||||
private _onDidFocus: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onDidFocus(): Event<void> { return this._onDidFocus.event; }
|
||||
|
||||
private _onDidSizeConstraintsChange = this._register(new Emitter<{ width: number; height: number; }>());
|
||||
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return this._onDidSizeConstraintsChange.event; }
|
||||
private _onDidSizeConstraintsChange = this._register(new Emitter<{ width: number; height: number; } | undefined>());
|
||||
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; } | undefined> { return this._onDidSizeConstraintsChange.event; }
|
||||
|
||||
private _activeControl: BaseEditor;
|
||||
private _activeControl: BaseEditor | null;
|
||||
private controls: BaseEditor[] = [];
|
||||
|
||||
private activeControlDisposeables: IDisposable[] = [];
|
||||
@@ -44,8 +43,8 @@ export class EditorControl extends Disposable {
|
||||
constructor(
|
||||
private parent: HTMLElement,
|
||||
private groupView: IEditorGroupView,
|
||||
@IPartService private partService: IPartService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IProgressService progressService: IProgressService
|
||||
) {
|
||||
super();
|
||||
@@ -53,21 +52,24 @@ export class EditorControl extends Disposable {
|
||||
this.editorOperation = this._register(new LongRunningOperation(progressService));
|
||||
}
|
||||
|
||||
get activeControl(): BaseEditor {
|
||||
get activeControl() {
|
||||
return this._activeControl;
|
||||
}
|
||||
|
||||
openEditor(editor: EditorInput, options?: EditorOptions): TPromise<IOpenEditorResult> {
|
||||
openEditor(editor: EditorInput, options?: EditorOptions): Promise<IOpenEditorResult> {
|
||||
|
||||
// Editor control
|
||||
const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editor);
|
||||
const control = this.doShowEditorControl(descriptor, options);
|
||||
if (!descriptor) {
|
||||
throw new Error('No editor descriptor found');
|
||||
}
|
||||
const control = this.doShowEditorControl(descriptor);
|
||||
|
||||
// Set input
|
||||
return this.doSetInput(control, editor, options).then((editorChanged => (({ control, editorChanged } as IOpenEditorResult))));
|
||||
return this.doSetInput(control, editor, options || null).then((editorChanged => (({ control, editorChanged } as IOpenEditorResult))));
|
||||
}
|
||||
|
||||
private doShowEditorControl(descriptor: IEditorDescriptor, options: EditorOptions): BaseEditor {
|
||||
private doShowEditorControl(descriptor: IEditorDescriptor): BaseEditor {
|
||||
|
||||
// Return early if the currently active editor control can handle the input
|
||||
if (this._activeControl && descriptor.describes(this._activeControl)) {
|
||||
@@ -130,7 +132,7 @@ export class EditorControl extends Disposable {
|
||||
return control;
|
||||
}
|
||||
|
||||
private doSetActiveControl(control: BaseEditor) {
|
||||
private doSetActiveControl(control: BaseEditor | null) {
|
||||
this._activeControl = control;
|
||||
|
||||
// Clear out previous active control listeners
|
||||
@@ -143,10 +145,10 @@ export class EditorControl extends Disposable {
|
||||
}
|
||||
|
||||
// Indicate that size constraints could have changed due to new editor
|
||||
this._onDidSizeConstraintsChange.fire();
|
||||
this._onDidSizeConstraintsChange.fire(undefined);
|
||||
}
|
||||
|
||||
private doSetInput(control: BaseEditor, editor: EditorInput, options: EditorOptions): TPromise<boolean> {
|
||||
private doSetInput(control: BaseEditor, editor: EditorInput, options: EditorOptions | null): Promise<boolean> {
|
||||
|
||||
// If the input did not change, return early and only apply the options
|
||||
// unless the options instruct us to force open it even if it is the same
|
||||
@@ -163,7 +165,7 @@ export class EditorControl extends Disposable {
|
||||
control.focus();
|
||||
}
|
||||
|
||||
return TPromise.as(false);
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
// Show progress while setting input after a certain timeout. If the workbench is opening
|
||||
@@ -172,7 +174,7 @@ export class EditorControl extends Disposable {
|
||||
|
||||
// Call into editor control
|
||||
const editorWillChange = !inputMatches;
|
||||
return TPromise.wrap(control.setInput(editor, options, operation.token)).then(() => {
|
||||
return control.setInput(editor, options, operation.token).then(() => {
|
||||
|
||||
// Focus (unless prevented or another operation is running)
|
||||
if (operation.isCurrent()) {
|
||||
@@ -191,7 +193,7 @@ export class EditorControl extends Disposable {
|
||||
// Operation done
|
||||
operation.stop();
|
||||
|
||||
return TPromise.wrapError(e);
|
||||
return Promise.reject(e);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ class DropOverlay extends Themable {
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(new DragAndDropObserver(this.container, {
|
||||
onDragEnter: e => void 0,
|
||||
onDragEnter: e => undefined,
|
||||
onDragOver: e => {
|
||||
const isDraggingGroup = this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype);
|
||||
const isDraggingEditor = this.editorTransfer.hasData(DraggedEditorIdentifier.prototype);
|
||||
@@ -170,7 +170,7 @@ class DropOverlay extends Themable {
|
||||
return this.accessor.getGroup(this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier.groupId);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private handleDrop(event: DragEvent, splitDirection?: GroupDirection): void {
|
||||
@@ -303,7 +303,7 @@ class DropOverlay extends Themable {
|
||||
mousePosX > edgeWidthThreshold && mousePosX < editorControlWidth - edgeWidthThreshold &&
|
||||
mousePosY > edgeHeightThreshold && mousePosY < editorControlHeight - edgeHeightThreshold
|
||||
) {
|
||||
splitDirection = void 0;
|
||||
splitDirection = undefined;
|
||||
}
|
||||
|
||||
// Offer to split otherwise
|
||||
@@ -413,7 +413,7 @@ class DropOverlay extends Themable {
|
||||
removeClass(this.overlay, 'overlay-move-transition');
|
||||
|
||||
// Reset current operation
|
||||
this.currentDropOperation = void 0;
|
||||
this.currentDropOperation = undefined;
|
||||
}
|
||||
|
||||
contains(element: HTMLElement): boolean {
|
||||
@@ -440,7 +440,7 @@ export class EditorDropTarget extends Themable {
|
||||
private accessor: IEditorGroupsAccessor,
|
||||
private container: HTMLElement,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
@@ -452,7 +452,7 @@ export class EditorDropTarget extends Themable {
|
||||
return this._overlay;
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
@@ -512,15 +512,13 @@ export class EditorDropTarget extends Themable {
|
||||
|
||||
private findTargetGroupView(child: HTMLElement): IEditorGroupView {
|
||||
const groups = this.accessor.groups;
|
||||
for (let i = 0; i < groups.length; i++) {
|
||||
const groupView = groups[i];
|
||||
|
||||
for (const groupView of groups) {
|
||||
if (isAncestor(child, groupView.element)) {
|
||||
return groupView;
|
||||
}
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private updateContainer(isDraggedOver: boolean): void {
|
||||
@@ -536,7 +534,7 @@ export class EditorDropTarget extends Themable {
|
||||
private disposeOverlay(): void {
|
||||
if (this.overlay) {
|
||||
this.overlay.dispose();
|
||||
this._overlay = void 0;
|
||||
this._overlay = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/editorgroupview';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup';
|
||||
import { EditorInput, EditorOptions, GroupIdentifier, ConfirmResult, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext } from 'vs/workbench/common/editor';
|
||||
import { Event, Emitter, once, Relay } from 'vs/base/common/event';
|
||||
import { EditorInput, EditorOptions, GroupIdentifier, ConfirmResult, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor } from 'vs/workbench/common/editor';
|
||||
import { Event, Emitter, Relay } from 'vs/base/common/event';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
@@ -100,7 +99,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
private active: boolean;
|
||||
private dimension: Dimension;
|
||||
|
||||
private _whenRestored: Thenable<void>;
|
||||
private _whenRestored: Promise<void>;
|
||||
private isRestored: boolean;
|
||||
|
||||
private scopedInstantiationService: IInstantiationService;
|
||||
@@ -116,21 +115,21 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
private ignoreOpenEditorErrors: boolean;
|
||||
private disposedEditorsWorker: RunOnceWorker<EditorInput>;
|
||||
|
||||
private mapEditorToPendingConfirmation: Map<EditorInput, TPromise<boolean>> = new Map<EditorInput, TPromise<boolean>>();
|
||||
private mapEditorToPendingConfirmation: Map<EditorInput, Promise<boolean>> = new Map<EditorInput, Promise<boolean>>();
|
||||
|
||||
constructor(
|
||||
private accessor: IEditorGroupsAccessor,
|
||||
from: IEditorGroupView | ISerializedEditorGroup,
|
||||
private _label: string,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@IMenuService private menuService: IMenuService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
// {{SQL CARBON EDIT}}
|
||||
@ICommandService private commandService: ICommandService
|
||||
) {
|
||||
@@ -141,7 +140,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
} else if (isSerializedEditorGroup(from)) {
|
||||
this._group = this._register(instantiationService.createInstance(EditorGroup, from));
|
||||
} else {
|
||||
this._group = this._register(instantiationService.createInstance(EditorGroup, void 0));
|
||||
this._group = this._register(instantiationService.createInstance(EditorGroup, undefined));
|
||||
}
|
||||
|
||||
this.disposedEditorsWorker = this._register(new RunOnceWorker(editors => this.handleDisposedEditors(editors), 0));
|
||||
@@ -283,9 +282,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
});
|
||||
|
||||
// Toolbar actions
|
||||
const removeGroupAction = this._register(new Action(CLOSE_EDITOR_GROUP_COMMAND_ID, localize('closeGroupAction', "Close"), 'close-editor-group', true, () => { this.accessor.removeGroup(this); return TPromise.as(true); }));
|
||||
const removeGroupAction = this._register(new Action(CLOSE_EDITOR_GROUP_COMMAND_ID, localize('closeGroupAction', "Close"), 'close-editor-group', true, () => { this.accessor.removeGroup(this); return Promise.resolve(true); }));
|
||||
const keybinding = this.keybindingService.lookupKeybinding(removeGroupAction.id);
|
||||
containerToolbar.push(removeGroupAction, { icon: true, label: false, keybinding: keybinding ? keybinding.getLabel() : void 0 });
|
||||
containerToolbar.push(removeGroupAction, { icon: true, label: false, keybinding: keybinding ? keybinding.getLabel() : undefined });
|
||||
}
|
||||
|
||||
private createContainerContextMenu(): void {
|
||||
@@ -309,7 +308,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Fill in contributed actions
|
||||
const actions: IAction[] = [];
|
||||
fillInContextMenuActions(menu, void 0, actions, this.contextMenuService);
|
||||
fillInContextMenuActions(menu, undefined, actions, this.contextMenuService);
|
||||
|
||||
// Show it
|
||||
this.contextMenuService.showContextMenu({
|
||||
@@ -334,7 +333,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
let target: HTMLElement;
|
||||
if (e instanceof MouseEvent) {
|
||||
if (e.button !== 0) {
|
||||
return void 0; // only for left mouse click
|
||||
return undefined; // only for left mouse click
|
||||
}
|
||||
|
||||
target = e.target as HTMLElement;
|
||||
@@ -404,9 +403,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
}
|
||||
|
||||
private restoreEditors(from: IEditorGroupView | ISerializedEditorGroup): Thenable<void> {
|
||||
private restoreEditors(from: IEditorGroupView | ISerializedEditorGroup): Promise<void> {
|
||||
if (this._group.count === 0) {
|
||||
return Promise.resolve(void 0); // nothing to show
|
||||
return Promise.resolve(); // nothing to show
|
||||
}
|
||||
|
||||
// Determine editor options
|
||||
@@ -491,7 +490,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Close the editor when it is no longer open in any group including diff editors
|
||||
editorsToClose.forEach(editorToClose => {
|
||||
const resource = editorToClose ? editorToClose.getResource() : void 0; // prefer resource to not close right-hand side editors of a diff editor
|
||||
const resource = editorToClose ? editorToClose.getResource() : undefined; // prefer resource to not close right-hand side editors of a diff editor
|
||||
if (!this.accessor.groups.some(groupView => groupView.group.contains(resource || editorToClose))) {
|
||||
editorToClose.close();
|
||||
}
|
||||
@@ -609,7 +608,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return this._disposed;
|
||||
}
|
||||
|
||||
get whenRestored(): Thenable<void> {
|
||||
get whenRestored(): Promise<void> {
|
||||
return this._whenRestored;
|
||||
}
|
||||
|
||||
@@ -660,7 +659,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
get activeControl(): BaseEditor {
|
||||
return this.editorControl ? this.editorControl.activeControl : void 0;
|
||||
return this.editorControl ? this.editorControl.activeControl : undefined;
|
||||
}
|
||||
|
||||
get activeEditor(): EditorInput {
|
||||
@@ -731,11 +730,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region openEditor()
|
||||
|
||||
openEditor(editor: EditorInput, options?: EditorOptions): TPromise<void> {
|
||||
openEditor(editor: EditorInput, options?: EditorOptions): Promise<IEditor | null> {
|
||||
|
||||
// Guard against invalid inputs
|
||||
if (!editor) {
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
// Editor opening event allows for prevention
|
||||
@@ -750,11 +749,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return this.doOpenEditor(editor, options);
|
||||
}
|
||||
|
||||
private doOpenEditor(editor: EditorInput, options?: EditorOptions): TPromise<void> {
|
||||
private doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise<IEditor> {
|
||||
|
||||
// Determine options
|
||||
const openEditorOptions: IEditorOpenOptions = {
|
||||
index: options ? options.index : void 0,
|
||||
index: options ? options.index : undefined,
|
||||
pinned: !this.accessor.partOptions.enablePreview || editor.isDirty() || (options && options.pinned) || (options && typeof options.index === 'number'),
|
||||
active: this._group.count === 0 || !options || !options.inactive
|
||||
};
|
||||
@@ -791,10 +790,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return this.doShowEditor(editor, openEditorOptions.active, options);
|
||||
}
|
||||
|
||||
private doShowEditor(editor: EditorInput, active: boolean, options?: EditorOptions): TPromise<void> {
|
||||
private doShowEditor(editor: EditorInput, active: boolean, options?: EditorOptions): Promise<IEditor> {
|
||||
|
||||
// Show in editor control if the active editor changed
|
||||
let openEditorPromise: TPromise<void>;
|
||||
let openEditorPromise: Promise<IEditor>;
|
||||
if (active) {
|
||||
openEditorPromise = this.editorControl.openEditor(editor, options).then(result => {
|
||||
|
||||
@@ -802,13 +801,17 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
if (result.editorChanged) {
|
||||
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_ACTIVE, editor });
|
||||
}
|
||||
|
||||
return result.control;
|
||||
}, error => {
|
||||
|
||||
// Handle errors but do not bubble them up
|
||||
this.doHandleOpenEditorError(error, editor, options);
|
||||
|
||||
return null; // error: return NULL as result to signal this
|
||||
});
|
||||
} else {
|
||||
openEditorPromise = TPromise.as(void 0);
|
||||
openEditorPromise = Promise.resolve(null); // inactive: return NULL as result to signal this
|
||||
}
|
||||
|
||||
// Show in title control after editor control because some actions depend on it
|
||||
@@ -833,7 +836,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
actions
|
||||
});
|
||||
|
||||
once(handle.onDidClose)(() => dispose(actions.primary));
|
||||
Event.once(handle.onDidClose)(() => dispose(actions.primary));
|
||||
}
|
||||
|
||||
// Event
|
||||
@@ -850,17 +853,21 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region openEditors()
|
||||
|
||||
openEditors(editors: { editor: EditorInput, options?: EditorOptions }[]): TPromise<void> {
|
||||
openEditors(editors: { editor: EditorInput, options?: EditorOptions }[]): Promise<IEditor | null> {
|
||||
if (!editors.length) {
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
// Do not modify original array
|
||||
editors = editors.slice(0);
|
||||
|
||||
let result: IEditor;
|
||||
|
||||
// Use the first editor as active editor
|
||||
const { editor, options } = editors.shift();
|
||||
return this.openEditor(editor, options).then(() => {
|
||||
return this.openEditor(editor, options).then(activeEditor => {
|
||||
result = activeEditor; // this can be NULL if the opening failed
|
||||
|
||||
const startingIndex = this.getIndexOfEditor(editor) + 1;
|
||||
|
||||
// Open the other ones inactive
|
||||
@@ -870,8 +877,12 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
adjustedEditorOptions.pinned = true;
|
||||
adjustedEditorOptions.index = startingIndex + index;
|
||||
|
||||
return this.openEditor(editor, adjustedEditorOptions);
|
||||
})).then(() => void 0);
|
||||
return this.openEditor(editor, adjustedEditorOptions).then(activeEditor => {
|
||||
if (!result) {
|
||||
result = activeEditor; // only take if the first editor opening failed
|
||||
}
|
||||
});
|
||||
})).then(() => result);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -893,7 +904,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
private doMoveEditorInsideGroup(editor: EditorInput, moveOptions?: IMoveEditorOptions): void {
|
||||
const moveToIndex = moveOptions ? moveOptions.index : void 0;
|
||||
const moveToIndex = moveOptions ? moveOptions.index : undefined;
|
||||
if (typeof moveToIndex !== 'number') {
|
||||
return; // do nothing if we move into same group without index
|
||||
}
|
||||
@@ -953,9 +964,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region closeEditor()
|
||||
|
||||
closeEditor(editor: EditorInput = this.activeEditor): TPromise<void> {
|
||||
closeEditor(editor: EditorInput = this.activeEditor): Promise<void> {
|
||||
if (!editor) {
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Check for dirty and veto
|
||||
@@ -1025,7 +1036,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.ignoreOpenEditorErrors = true;
|
||||
}
|
||||
|
||||
const options = !focusNext ? EditorOptions.create({ preserveFocus: true }) : void 0;
|
||||
const options = !focusNext ? EditorOptions.create({ preserveFocus: true }) : undefined;
|
||||
this.openEditor(nextActiveEditor, options).then(() => {
|
||||
this.ignoreOpenEditorErrors = false;
|
||||
});
|
||||
@@ -1069,9 +1080,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this._group.closeEditor(editor);
|
||||
}
|
||||
|
||||
private handleDirty(editors: EditorInput[]): TPromise<boolean /* veto */> {
|
||||
private handleDirty(editors: EditorInput[]): Promise<boolean /* veto */> {
|
||||
if (!editors.length) {
|
||||
return TPromise.as(false); // no veto
|
||||
return Promise.resolve(false); // no veto
|
||||
}
|
||||
|
||||
const editor = editors.shift();
|
||||
@@ -1099,13 +1110,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
});
|
||||
}
|
||||
|
||||
private doHandleDirty(editor: EditorInput): TPromise<boolean /* veto */> {
|
||||
private doHandleDirty(editor: EditorInput): Promise<boolean /* veto */> {
|
||||
if (
|
||||
!editor.isDirty() || // editor must be dirty
|
||||
this.accessor.groups.some(groupView => groupView !== this && groupView.group.contains(editor, true /* support side by side */)) || // editor is opened in other group
|
||||
editor instanceof SideBySideEditorInput && this.isOpened(editor.master) // side by side editor master is still opened
|
||||
) {
|
||||
return TPromise.as(false);
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
// Switch to editor that we want to handle and confirm to save/revert
|
||||
@@ -1146,9 +1157,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region closeEditors()
|
||||
|
||||
closeEditors(args: EditorInput[] | ICloseEditorsFilter): TPromise<void> {
|
||||
closeEditors(args: EditorInput[] | ICloseEditorsFilter): Promise<void> {
|
||||
if (this.isEmpty()) {
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const editors = this.getEditorsToClose(args);
|
||||
@@ -1219,7 +1230,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region closeAllEditors()
|
||||
|
||||
closeAllEditors(): TPromise<void> {
|
||||
closeAllEditors(): Promise<void> {
|
||||
if (this.isEmpty()) {
|
||||
|
||||
// If the group is empty and the request is to close all editors, we still close
|
||||
@@ -1229,7 +1240,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.accessor.removeGroup(this);
|
||||
}
|
||||
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Check for dirty and veto
|
||||
@@ -1264,7 +1275,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region replaceEditors()
|
||||
|
||||
replaceEditors(editors: EditorReplacement[]): TPromise<void> {
|
||||
replaceEditors(editors: EditorReplacement[]): Promise<void> {
|
||||
|
||||
// Extract active vs. inactive replacements
|
||||
let activeReplacement: EditorReplacement;
|
||||
@@ -1322,10 +1333,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// Forward to title control
|
||||
this.titleAreaControl.closeEditor(activeReplacement.editor);
|
||||
|
||||
return openEditorResult;
|
||||
return openEditorResult.then(() => undefined);
|
||||
}
|
||||
|
||||
return TPromise.as(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -1379,6 +1390,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
layout(width: number, height: number): void {
|
||||
this.dimension = new Dimension(width, height);
|
||||
|
||||
// Ensure editor container gets height as CSS depending
|
||||
// on the preferred height of the title control
|
||||
this.editorContainer.style.height = `calc(100% - ${this.titleAreaControl.getPreferredHeight()}px)`;
|
||||
|
||||
// Forward to controls
|
||||
this.titleAreaControl.layout(new Dimension(this.dimension.width, this.titleAreaControl.getPreferredHeight()));
|
||||
this.editorControl.layout(new Dimension(this.dimension.width, this.dimension.height - this.titleAreaControl.getPreferredHeight()));
|
||||
@@ -1410,7 +1425,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
class EditorOpeningEvent implements IEditorOpeningEvent {
|
||||
private override: () => TPromise<any>;
|
||||
private override: () => Promise<IEditor>;
|
||||
|
||||
constructor(
|
||||
private _group: GroupIdentifier,
|
||||
@@ -1431,11 +1446,11 @@ class EditorOpeningEvent implements IEditorOpeningEvent {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
prevent(callback: () => TPromise<any>): void {
|
||||
prevent(callback: () => Promise<IEditor>): void {
|
||||
this.override = callback;
|
||||
}
|
||||
|
||||
isPrevented(): () => TPromise<any> {
|
||||
isPrevented(): () => Promise<IEditor> {
|
||||
return this.override;
|
||||
}
|
||||
}
|
||||
@@ -1451,7 +1466,7 @@ registerThemingParticipant((theme, collector, environment) => {
|
||||
// Letterpress
|
||||
const letterpress = `resources/letterpress${theme.type === 'dark' ? '-dark' : theme.type === 'hc' ? '-hc' : ''}.svg`;
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.empty .editor-group-letterpress {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty .editor-group-letterpress {
|
||||
background-image: url('${URI.file(join(environment.appRoot, letterpress)).toString()}')
|
||||
}
|
||||
`);
|
||||
@@ -1460,20 +1475,20 @@ registerThemingParticipant((theme, collector, environment) => {
|
||||
const focusedEmptyGroupBorder = theme.getColor(EDITOR_GROUP_FOCUSED_EMPTY_BORDER);
|
||||
if (focusedEmptyGroupBorder) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content:not(.empty) .editor-group-container.empty.active:focus {
|
||||
.monaco-workbench .part.editor > .content:not(.empty) .editor-group-container.empty.active:focus {
|
||||
outline-width: 1px;
|
||||
outline-color: ${focusedEmptyGroupBorder};
|
||||
outline-offset: -2px;
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content.empty .editor-group-container.empty.active:focus {
|
||||
.monaco-workbench .part.editor > .content.empty .editor-group-container.empty.active:focus {
|
||||
outline: none; /* never show outline for empty group if it is the last */
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.empty.active:focus {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty.active:focus {
|
||||
outline: none; /* disable focus outline unless active empty group border is defined */
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -7,11 +7,11 @@ import 'vs/workbench/browser/parts/editor/editor.contribution';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Part } from 'vs/workbench/browser/part';
|
||||
import { Dimension, isAncestor, toggleClass, addClass, $ } from 'vs/base/browser/dom';
|
||||
import { Event, Emitter, once, Relay, anyEvent } from 'vs/base/common/event';
|
||||
import { Event, Emitter, Relay } from 'vs/base/common/event';
|
||||
import { contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { GroupDirection, IAddGroupOptions, GroupsArrangement, GroupOrientation, IMergeGroupOptions, MergeGroupMode, ICopyEditorOptions, GroupsOrder, GroupChangeKind, GroupLocation, IFindGroupScope, EditorGroupLayout, GroupLayoutArgument } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Direction, SerializableGrid, Sizing, ISerializedGrid, Orientation, GridBranchNode, isGridBranchNode, GridNode, createSerializedGrid, Grid } from 'vs/base/browser/ui/grid/grid';
|
||||
import { Direction, SerializableGrid, Sizing, ISerializedGrid, Orientation, GridBranchNode, isGridBranchNode, GridNode, createSerializedGrid, Grid, ISerializableView } from 'vs/base/browser/ui/grid/grid';
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import { EDITOR_GROUP_BORDER, EDITOR_PANE_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
@@ -23,13 +23,13 @@ import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup';
|
||||
import { always } from 'vs/base/common/async';
|
||||
import { EditorDropTarget } from 'vs/workbench/browser/parts/editor/editorDropTarget';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { CenteredViewLayout } from 'vs/base/browser/ui/centered/centeredViewLayout';
|
||||
import { IView, orthogonal } from 'vs/base/browser/ui/grid/gridview';
|
||||
import { IView, orthogonal, LayoutPriority } from 'vs/base/browser/ui/grid/gridview';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Parts } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { convertEditorInput } from 'sql/parts/common/customInputConverter';
|
||||
@@ -83,7 +83,7 @@ class GridWidgetView<T extends IView> implements IView {
|
||||
}
|
||||
}
|
||||
|
||||
export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditorGroupsAccessor {
|
||||
export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditorGroupsAccessor, ISerializableView {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
@@ -109,11 +109,14 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
|
||||
private onDidSetGridWidget = this._register(new Emitter<{ width: number; height: number; }>());
|
||||
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; }>());
|
||||
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return anyEvent(this.onDidSetGridWidget.event, this._onDidSizeConstraintsChange.event); }
|
||||
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return Event.any(this.onDidSetGridWidget.event, this._onDidSizeConstraintsChange.event); }
|
||||
|
||||
private _onDidPreferredSizeChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onDidPreferredSizeChange(): Event<void> { return this._onDidPreferredSizeChange.event; }
|
||||
|
||||
private _onDidActivateGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
get onDidActivateGroup(): Event<IEditorGroupView> { return this._onDidActivateGroup.event; }
|
||||
|
||||
//#endregion
|
||||
|
||||
private dimension: Dimension;
|
||||
@@ -133,15 +136,22 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
private gridWidget: SerializableGrid<IEditorGroupView>;
|
||||
private gridWidgetView: GridWidgetView<IEditorGroupView>;
|
||||
|
||||
private _whenRestored: Thenable<void>;
|
||||
private _whenRestored: Promise<void>;
|
||||
private whenRestoredResolve: () => void;
|
||||
|
||||
element: HTMLElement;
|
||||
|
||||
private _onDidChange = new Emitter<{ width: number; height: number; }>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
priority: LayoutPriority = LayoutPriority.High;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
private restorePreviousState: boolean,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IStorageService storageService: IStorageService
|
||||
) {
|
||||
super(id, { hasTitle: false }, themeService, storageService);
|
||||
@@ -220,13 +230,13 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
|
||||
get orientation(): GroupOrientation {
|
||||
if (!this.gridWidget) {
|
||||
return void 0; // we have not been created yet
|
||||
return undefined; // we have not been created yet
|
||||
}
|
||||
|
||||
return this.gridWidget.orientation === Orientation.VERTICAL ? GroupOrientation.VERTICAL : GroupOrientation.HORIZONTAL;
|
||||
}
|
||||
|
||||
get whenRestored(): Thenable<void> {
|
||||
get whenRestored(): Promise<void> {
|
||||
return this._whenRestored;
|
||||
}
|
||||
|
||||
@@ -316,6 +326,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
const groupView = this.assertGroupView(group);
|
||||
this.doSetGroupActive(groupView);
|
||||
|
||||
this._onDidActivateGroup.fire(groupView);
|
||||
return groupView;
|
||||
}
|
||||
|
||||
@@ -527,7 +538,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
}));
|
||||
|
||||
// Track dispose
|
||||
once(groupView.onWillDispose)(() => {
|
||||
Event.once(groupView.onWillDispose)(() => {
|
||||
groupDisposables = dispose(groupDisposables);
|
||||
this.groupViews.delete(groupView.id);
|
||||
this.doUpdateMostRecentActive(groupView);
|
||||
@@ -762,7 +773,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
private resetPreferredSize(): void {
|
||||
|
||||
// Reset (will be computed upon next access)
|
||||
this._preferredSize = void 0;
|
||||
this._preferredSize = undefined;
|
||||
|
||||
// Event
|
||||
this._onDidPreferredSizeChange.fire();
|
||||
@@ -783,6 +794,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
|
||||
// Container
|
||||
this.element = parent;
|
||||
this.container = document.createElement('div');
|
||||
addClass(this.container, 'content');
|
||||
parent.appendChild(this.container);
|
||||
@@ -824,7 +836,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
}
|
||||
|
||||
// Signal restored
|
||||
always(Promise.all(this.groups.map(group => group.whenRestored)), () => this.whenRestoredResolve());
|
||||
Promise.all(this.groups.map(group => group.whenRestored)).finally(() => this.whenRestoredResolve());
|
||||
|
||||
// Update container
|
||||
this.updateContainer();
|
||||
@@ -861,7 +873,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
|
||||
this.groupViews.forEach(group => group.dispose());
|
||||
this.groupViews.clear();
|
||||
this._activeGroup = void 0;
|
||||
this._activeGroup = undefined;
|
||||
this.mostRecentActiveGroups = [];
|
||||
}
|
||||
|
||||
@@ -924,7 +936,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
this._onDidSizeConstraintsChange.input = gridWidget.onDidChange;
|
||||
}
|
||||
|
||||
this.onDidSetGridWidget.fire();
|
||||
this.onDidSetGridWidget.fire(undefined);
|
||||
}
|
||||
|
||||
private updateContainer(): void {
|
||||
@@ -950,12 +962,16 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
return this.groupViews.size === 1 && this._activeGroup.isEmpty();
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): Dimension[] {
|
||||
const sizes = super.layout(dimension);
|
||||
layout(dimension: Dimension): Dimension[];
|
||||
layout(width: number, height: number): void;
|
||||
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
|
||||
const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2));
|
||||
|
||||
this.doLayout(sizes[1]);
|
||||
|
||||
return sizes;
|
||||
if (dim1 instanceof Dimension) {
|
||||
return sizes;
|
||||
}
|
||||
}
|
||||
|
||||
private doLayout(dimension: Dimension): void {
|
||||
@@ -1016,4 +1032,10 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
toJSON(): object {
|
||||
return {
|
||||
type: Parts.EDITOR_PART
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ export class EditorPickerEntry extends QuickOpenEntryGroup {
|
||||
constructor(
|
||||
private editor: EditorInput,
|
||||
private _group: IEditorGroup,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IModelService private modelService: IModelService
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -90,7 +90,7 @@ export abstract class BaseEditorPicker extends QuickOpenHandler {
|
||||
this.scorerCache = Object.create(null);
|
||||
}
|
||||
|
||||
getResults(searchValue: string, token: CancellationToken): Thenable<QuickOpenModel> {
|
||||
getResults(searchValue: string, token: CancellationToken): Promise<QuickOpenModel | null> {
|
||||
const editorEntries = this.getEditorEntries();
|
||||
if (!editorEntries.length) {
|
||||
return Promise.resolve(null);
|
||||
|
||||
@@ -50,7 +50,7 @@ import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/
|
||||
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { once } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
|
||||
class SideBySideEditorEncodingSupport implements IEncodingSupport {
|
||||
constructor(private master: IEncodingSupport, private details: IEncodingSupport) { }
|
||||
@@ -290,12 +290,12 @@ export class EditorStatus implements IStatusbarItem {
|
||||
private screenReaderNotification: INotificationHandle;
|
||||
|
||||
constructor(
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IQuickOpenService private quickOpenService: IQuickOpenService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
|
||||
@IModeService private modeService: IModeService,
|
||||
@ITextFileService private textFileService: ITextFileService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
|
||||
@INotificationService private readonly notificationService: INotificationService
|
||||
) {
|
||||
@@ -518,7 +518,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
{ sticky: true }
|
||||
);
|
||||
|
||||
once(this.screenReaderNotification.onDidClose)(() => {
|
||||
Event.once(this.screenReaderNotification.onDidClose)(() => {
|
||||
this.screenReaderNotification = null;
|
||||
});
|
||||
}
|
||||
@@ -548,7 +548,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
|
||||
private updateStatusBar(): void {
|
||||
const activeControl = this.editorService.activeControl;
|
||||
const activeCodeEditor = activeControl ? getCodeEditor(activeControl.getControl()) : void 0;
|
||||
const activeCodeEditor = activeControl ? getCodeEditor(activeControl.getControl()) : undefined;
|
||||
|
||||
// Update all states
|
||||
this.onScreenReaderModeChange(activeCodeEditor);
|
||||
@@ -587,8 +587,8 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.onEOLChange(activeCodeEditor);
|
||||
|
||||
let selections = activeCodeEditor.getSelections();
|
||||
for (let i = 0; i < e.changes.length; i++) {
|
||||
if (selections.some(selection => Range.areIntersecting(selection, e.changes[i].range))) {
|
||||
for (const change of e.changes) {
|
||||
if (selections.some(selection => Range.areIntersecting(selection, change.range))) {
|
||||
this.onSelectionChange(activeCodeEditor);
|
||||
break;
|
||||
}
|
||||
@@ -820,7 +820,7 @@ export class ShowLanguageExtensionsAction extends Action {
|
||||
|
||||
constructor(
|
||||
private fileExtension: string,
|
||||
@ICommandService private commandService: ICommandService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IExtensionGalleryService galleryService: IExtensionGalleryService
|
||||
) {
|
||||
super(ShowLanguageExtensionsAction.ID, nls.localize('showLanguageExtensions', "Search Marketplace Extensions for '{0}'...", fileExtension));
|
||||
@@ -828,8 +828,8 @@ export class ShowLanguageExtensionsAction extends Action {
|
||||
this.enabled = galleryService.isEnabled();
|
||||
}
|
||||
|
||||
run(): Thenable<void> {
|
||||
return this.commandService.executeCommand('workbench.extensions.action.showExtensionsForLanguage', this.fileExtension).then(() => void 0);
|
||||
run(): Promise<void> {
|
||||
return this.commandService.executeCommand('workbench.extensions.action.showExtensionsForLanguage', this.fileExtension).then(() => undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -841,19 +841,19 @@ export class ChangeModeAction extends Action {
|
||||
constructor(
|
||||
actionId: string,
|
||||
actionLabel: string,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IModelService private modelService: IModelService,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
|
||||
@IQuickInputService private quickInputService: IQuickInputService,
|
||||
@IPreferencesService private preferencesService: IPreferencesService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IUntitledEditorService private untitledEditorService: IUntitledEditorService
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IPreferencesService private readonly preferencesService: IPreferencesService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService
|
||||
) {
|
||||
super(actionId, actionLabel);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const activeTextEditorWidget = getCodeEditor(this.editorService.activeTextEditorWidget);
|
||||
if (!activeTextEditorWidget) {
|
||||
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
|
||||
@@ -958,6 +958,7 @@ export class ChangeModeAction extends Action {
|
||||
}
|
||||
|
||||
// Change mode for active editor
|
||||
// {{SQL CARBON EDIT}} - Get activeControl instead of activeEditor
|
||||
const activeEditor = this.editorService.activeControl;
|
||||
const activeTextEditorWidget = this.editorService.activeTextEditorWidget;
|
||||
const models: ITextModel[] = [];
|
||||
@@ -1012,7 +1013,7 @@ export class ChangeModeAction extends Action {
|
||||
return <IQuickPickItem>{
|
||||
id,
|
||||
label: lang,
|
||||
description: (id === currentAssociation) ? nls.localize('currentAssociation', "Current Association") : void 0
|
||||
description: (id === currentAssociation) ? nls.localize('currentAssociation', "Current Association") : undefined
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1061,13 +1062,13 @@ class ChangeIndentationAction extends Action {
|
||||
constructor(
|
||||
actionId: string,
|
||||
actionLabel: string,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IQuickInputService private quickInputService: IQuickInputService
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
super(actionId, actionLabel);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const activeTextEditorWidget = getCodeEditor(this.editorService.activeTextEditorWidget);
|
||||
if (!activeTextEditorWidget) {
|
||||
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
|
||||
@@ -1111,13 +1112,13 @@ export class ChangeEOLAction extends Action {
|
||||
constructor(
|
||||
actionId: string,
|
||||
actionLabel: string,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IQuickInputService private quickInputService: IQuickInputService
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
super(actionId, actionLabel);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const activeTextEditorWidget = getCodeEditor(this.editorService.activeTextEditorWidget);
|
||||
if (!activeTextEditorWidget) {
|
||||
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
|
||||
@@ -1156,15 +1157,15 @@ export class ChangeEncodingAction extends Action {
|
||||
constructor(
|
||||
actionId: string,
|
||||
actionLabel: string,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IQuickInputService private quickInputService: IQuickInputService,
|
||||
@ITextResourceConfigurationService private textResourceConfigurationService: ITextResourceConfigurationService,
|
||||
@IFileService private fileService: IFileService
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@ITextResourceConfigurationService private readonly textResourceConfigurationService: ITextResourceConfigurationService,
|
||||
@IFileService private readonly fileService: IFileService
|
||||
) {
|
||||
super(actionId, actionLabel);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
if (!getCodeEditor(this.editorService.activeTextEditorWidget)) {
|
||||
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
|
||||
}
|
||||
@@ -1196,7 +1197,7 @@ export class ChangeEncodingAction extends Action {
|
||||
|
||||
return pickActionPromise.then(action => {
|
||||
if (!action) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const resource = toResource(activeControl.input, { supportSideBySide: true });
|
||||
|
||||
@@ -34,7 +34,7 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget {
|
||||
private label: string,
|
||||
keyBindingAction: string,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IThemeService private themeService: IThemeService
|
||||
@IThemeService private readonly themeService: IThemeService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -106,9 +106,9 @@ export class OpenWorkspaceButtonContribution extends Disposable implements IEdit
|
||||
|
||||
constructor(
|
||||
private editor: ICodeEditor,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IWindowService private windowService: IWindowService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService
|
||||
) {
|
||||
super();
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 266 B |
@@ -3,17 +3,17 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control.hidden {
|
||||
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.selected .monaco-icon-label,
|
||||
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.focused .monaco-icon-label {
|
||||
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.selected .monaco-icon-label,
|
||||
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.focused .monaco-icon-label {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.selected .hint-more,
|
||||
.monaco-workbench>.part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.focused .hint-more {
|
||||
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.selected .hint-more,
|
||||
.monaco-workbench .part.editor>.content .editor-group-container .breadcrumbs-control .monaco-breadcrumb-item.focused .hint-more {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,26 +5,26 @@
|
||||
|
||||
/* Container */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.empty {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty {
|
||||
opacity: 0.5; /* dimmed to indicate inactive state */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.empty.active,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.empty.dragged-over {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty.active,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty.dragged-over {
|
||||
opacity: 1; /* indicate active/dragged-over group through undimmed state */
|
||||
}
|
||||
|
||||
/* Letterpress */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-letterpress {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-letterpress {
|
||||
display: none; /* only visible when empty */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .editor-group-letterpress {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty > .editor-group-letterpress {
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
@@ -35,25 +35,25 @@
|
||||
background-size: 70% 70%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content.empty .editor-group-container.empty > .editor-group-letterpress {
|
||||
.monaco-workbench .part.editor > .content.empty .editor-group-container.empty > .editor-group-letterpress {
|
||||
background-size: 100% 100%; /* larger for empty editor part */
|
||||
height: 100%; /* no toolbar in this case */
|
||||
}
|
||||
|
||||
/* Title */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title:not(.tabs) {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title:not(.tabs) {
|
||||
display: flex; /* when tabs are not shown, use flex layout */
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.title-border-bottom::after {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.title-border-bottom::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@@ -65,21 +65,21 @@
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .title {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty > .title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Toolbar */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content:not(.empty) .editor-group-container.empty > .editor-group-container-toolbar {
|
||||
.monaco-workbench .part.editor > .content:not(.empty) .editor-group-container.empty > .editor-group-container-toolbar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .action-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar .action-label {
|
||||
display: block;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
@@ -89,30 +89,26 @@
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
|
||||
.vs .monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
|
||||
background-image: url('close-big.svg');
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group,
|
||||
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
|
||||
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group,
|
||||
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
|
||||
background-image: url('close-big-inverse.svg');
|
||||
}
|
||||
|
||||
/* Editor */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-container {
|
||||
height: calc(100% - 35px); /* below title control */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .editor-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty > .editor-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-container > .editor-instance {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .editor-container > .editor-instance {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .grid-view-container {
|
||||
.monaco-workbench .part.editor > .content .grid-view-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation {
|
||||
.monaco-workbench .screen-reader-detected-explanation {
|
||||
width: 420px;
|
||||
top: 30px;
|
||||
right: 6px;
|
||||
@@ -30,7 +30,7 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation .cancel {
|
||||
.monaco-workbench .screen-reader-detected-explanation .cancel {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@@ -41,27 +41,27 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation h2 {
|
||||
.monaco-workbench .screen-reader-detected-explanation h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: 400;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation p {
|
||||
.monaco-workbench .screen-reader-detected-explanation p {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation hr {
|
||||
.monaco-workbench .screen-reader-detected-explanation hr {
|
||||
border: 0;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation .buttons {
|
||||
.monaco-workbench .screen-reader-detected-explanation .buttons {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation .buttons a {
|
||||
.monaco-workbench .screen-reader-detected-explanation .buttons a {
|
||||
font-size: 13px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
@@ -69,11 +69,11 @@
|
||||
max-width: fit-content;
|
||||
}
|
||||
|
||||
.monaco-shell.vs .screen-reader-detected-explanation .cancel {
|
||||
.vs .monaco-workbench .screen-reader-detected-explanation .cancel {
|
||||
background: url('close-statusview.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.monaco-shell.vs-dark .screen-reader-detected-explanation .cancel,
|
||||
.monaco-shell.hc-black .screen-reader-detected-explanation .cancel {
|
||||
.vs-dark .monaco-workbench .screen-reader-detected-explanation .cancel,
|
||||
.hc-black .monaco-workbench .screen-reader-detected-explanation .cancel {
|
||||
background: url('close-statusview-inverse.svg') center center no-repeat;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 258 B |
@@ -5,7 +5,8 @@
|
||||
|
||||
/* Title Label */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title > .label-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title > .label-container {
|
||||
height: 35px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
@@ -13,7 +14,7 @@
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label {
|
||||
line-height: 35px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -21,31 +22,31 @@
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .no-tabs.title-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .no-tabs.title-label {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .monaco-icon-label::before {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before {
|
||||
height: 35px; /* tweak the icon size of the editor labels when icons are enabled */
|
||||
}
|
||||
|
||||
/* Breadcrumbs */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control {
|
||||
flex: 1 50%;
|
||||
overflow: hidden;
|
||||
margin-left: .45em;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.preview .monaco-breadcrumb-item {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.preview .monaco-breadcrumb-item {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
content: '/';
|
||||
opacity: 1;
|
||||
height: inherit;
|
||||
@@ -54,35 +55,36 @@
|
||||
}
|
||||
|
||||
/* {{SQL CARBON EDIT}} */
|
||||
.monaco-workbench.windows > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
.windows > .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
content: '/';
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::before,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder + .monaco-breadcrumb-item::before,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.relative-path .monaco-breadcrumb-item:nth-child(2)::before {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::before,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder + .monaco-breadcrumb-item::before,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.relative-path .monaco-breadcrumb-item:nth-child(2)::before,
|
||||
.windows > .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:nth-child(2)::before {
|
||||
/* workspace folder, item following workspace folder, or relative path -> hide first seperator */
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::after {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::after {
|
||||
/* use dot separator for workspace folder */
|
||||
content: '\00a0•\00a0';
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child {
|
||||
padding-right: 4px; /* does not have trailing separator*/
|
||||
}
|
||||
|
||||
/* Title Actions */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-actions {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions {
|
||||
display: flex;
|
||||
flex: initial;
|
||||
opacity: 0.5;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .title-actions {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .title-actions {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -5,37 +5,37 @@
|
||||
|
||||
/* Title Container */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element .scrollbar {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container > .monaco-scrollable-element .scrollbar {
|
||||
z-index: 3; /* on top of tabs */
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Tabs Container */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container {
|
||||
display: flex;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container.scroll {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.scroll {
|
||||
overflow: scroll !important;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container::-webkit-scrollbar {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Tab */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab {
|
||||
position: relative;
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
@@ -45,45 +45,45 @@
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-right,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-off {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-right,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-off {
|
||||
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab close button is not left */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
|
||||
width: 120px;
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink {
|
||||
min-width: 60px;
|
||||
flex-basis: 0; /* all tabs are even */
|
||||
flex-grow: 1; /* all tabs grow even */
|
||||
max-width: fit-content;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left::after,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off::after {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left::after,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off::after {
|
||||
content: '';
|
||||
display: flex;
|
||||
flex: 0;
|
||||
width: 5px; /* Reserve space to hide tab fade when close button is left or off (fixes https://github.com/Microsoft/vscode/issues/45728) */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left {
|
||||
min-width: 80px; /* make more room for close button when it shows to the left */
|
||||
padding-right: 5px; /* we need less room when sizing is shrink */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged {
|
||||
will-change: transform; /* forces tab to be drawn on a separate layer (fixes https://github.com/Microsoft/vscode/issues/18733) */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged-over div {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dragged-over div {
|
||||
pointer-events: none; /* prevents cursor flickering (fixes https://github.com/Microsoft/vscode/issues/38753) */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left {
|
||||
flex-direction: row-reverse;
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
@@ -91,14 +91,14 @@
|
||||
|
||||
/* Tab border top/bottom */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-border-top-container,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-border-bottom-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-border-top-container,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-border-bottom-container {
|
||||
display: none; /* hidden by default until a color is provided (see below) */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
@@ -107,19 +107,19 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-top > .tab-border-top-container {
|
||||
top: 0;
|
||||
height: 1px;
|
||||
background-color: var(--tab-border-top-color);
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active.tab-border-bottom > .tab-border-bottom-container {
|
||||
bottom: 0;
|
||||
height: 1px;
|
||||
background-color: var(--tab-border-bottom-color);
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty-border-top > .tab-border-top-container {
|
||||
top: 0;
|
||||
height: 2px;
|
||||
background-color: var(--tab-dirty-border-top-color);
|
||||
@@ -127,16 +127,16 @@
|
||||
|
||||
/* Tab Label */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink .tab-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink .tab-label {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .tab-label::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
@@ -146,66 +146,66 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:focus > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:focus > .tab-label::after {
|
||||
opacity: 0; /* when tab has the focus this shade breaks the tab border (fixes https://github.com/Microsoft/vscode/issues/57819) */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label > .monaco-icon-label-description-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label > .monaco-icon-label-description-container {
|
||||
overflow: visible; /* fixes https://github.com/Microsoft/vscode/issues/20182 */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-description-container {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-description-container {
|
||||
text-overflow: clip;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-description-container {
|
||||
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink > .monaco-icon-label > .monaco-icon-label-description-container {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before {
|
||||
height: 16px; /* tweak the icon size of the editor labels when icons are enabled */
|
||||
}
|
||||
|
||||
/* Tab Close */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close {
|
||||
flex: 0;
|
||||
overflow: hidden; /* let the close button be pushed out of view when sizing is set to shrink to make more room... */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.close-button-right.sizing-shrink > .tab-close,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink:hover > .tab-close,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close:focus-within {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.close-button-right.sizing-shrink > .tab-close,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink:hover > .tab-close,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close:focus-within {
|
||||
overflow: visible; /* ...but still show the close button on hover, focus and when dirty */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off > .tab-close {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off > .tab-close {
|
||||
display: none; /* hide the close action bar when we are configured to hide it */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label:focus, /* always show it on focus */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-close .action-label, /* always show it on hover */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label { /* always show it for dirty tabs */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label:focus, /* always show it on focus */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-close .action-label, /* always show it on hover */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label { /* always show it for dirty tabs */
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label { /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label { /* show dimmed for inactive group */
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close .action-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close .action-label {
|
||||
opacity: 0;
|
||||
display: block;
|
||||
height: 16px;
|
||||
@@ -216,53 +216,53 @@
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action {
|
||||
.vs .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action {
|
||||
background: url('close-dirty.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action,
|
||||
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action {
|
||||
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action,
|
||||
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action {
|
||||
background: url('close-dirty-inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover {
|
||||
.vs .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover {
|
||||
background: url('close.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover,
|
||||
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover {
|
||||
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover,
|
||||
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty .close-editor-action:hover {
|
||||
background: url('close-inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
/* No Tab Close Button */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off {
|
||||
padding-right: 10px; /* give a little bit more room if close button is off */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off {
|
||||
padding-right: 5px; /* we need less room when sizing is shrink */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top) {
|
||||
background-repeat: no-repeat;
|
||||
background-position-y: center;
|
||||
background-position-x: calc(100% - 6px); /* to the right of the tab label */
|
||||
padding-right: 28px; /* make room for dirty indication when we are running without close button */
|
||||
}
|
||||
|
||||
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty {
|
||||
.vs .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top) {
|
||||
background-image: url('close-dirty.svg');
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty,
|
||||
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty {
|
||||
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top),
|
||||
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty {
|
||||
background-image: url('close-dirty-inverse.svg');
|
||||
}
|
||||
|
||||
/* Editor Actions */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .editor-actions {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions {
|
||||
cursor: default;
|
||||
flex: initial;
|
||||
padding-left: 4px;
|
||||
@@ -271,30 +271,30 @@
|
||||
|
||||
/* Breadcrumbs */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control {
|
||||
flex: 1 100%;
|
||||
height: 22px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-icon-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-icon-label {
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-icon-label::before {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-icon-label::before {
|
||||
height: 22px; /* tweak the icon size of the editor labels when icons are enabled */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item {
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
min-width: 16px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:last-child {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
@@ -5,31 +5,31 @@
|
||||
|
||||
/* Editor Label */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label {
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label a,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label a,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a {
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .monaco-icon-label::before,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label a,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-label h2,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label span {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .monaco-icon-label::before,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label a,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label h2,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Title Actions */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-actions .action-label,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .editor-actions .action-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions .action-label {
|
||||
display: block;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
@@ -39,29 +39,29 @@
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .title-actions .action-label,
|
||||
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .editor-actions .action-label {
|
||||
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions .action-label,
|
||||
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions .action-label {
|
||||
line-height: initial;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .editor-actions .action-label .label,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .title-actions .action-label .label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions .action-label .label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-actions .action-label .label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Drag Cursor */
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title {
|
||||
cursor: -webkit-grab;
|
||||
}
|
||||
|
||||
/* Actions */
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .close-editor-action {
|
||||
background: url('close.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action,
|
||||
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action {
|
||||
.vs-dark .monaco-workbench .part.editor > .content .editor-group-container > .title .close-editor-action,
|
||||
.hc-black .monaco-workbench .part.editor > .content .editor-group-container > .title .close-editor-action {
|
||||
background: url('close-inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import 'vs/css!./media/notabstitlecontrol';
|
||||
import { toResource, Verbosity, IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { TitleControl, IToolbarActions } from 'vs/workbench/browser/parts/editor/titleControl';
|
||||
import { ResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { ResourceLabel, IResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { TAB_ACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch';
|
||||
import { addDisposableListener, EventType, addClass, EventHelper, removeClass, toggleClass } from 'vs/base/browser/dom';
|
||||
@@ -22,7 +22,7 @@ interface IRenderedEditorLabel {
|
||||
|
||||
export class NoTabsTitleControl extends TitleControl {
|
||||
private titleContainer: HTMLElement;
|
||||
private editorLabel: ResourceLabel;
|
||||
private editorLabel: IResourceLabel;
|
||||
private activeLabel: IRenderedEditorLabel = Object.create(null);
|
||||
|
||||
protected create(parent: HTMLElement): void {
|
||||
@@ -40,8 +40,8 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
this.titleContainer.appendChild(labelContainer);
|
||||
|
||||
// Editor Label
|
||||
this.editorLabel = this._register(this.instantiationService.createInstance(ResourceLabel, labelContainer, void 0));
|
||||
this._register(this.editorLabel.onClick(e => this.onTitleLabelClick(e)));
|
||||
this.editorLabel = this._register(this.instantiationService.createInstance(ResourceLabel, labelContainer, undefined)).element;
|
||||
this._register(addDisposableListener(this.editorLabel.element, EventType.CLICK, e => this.onTitleLabelClick(e)));
|
||||
|
||||
// Breadcrumbs
|
||||
this.createBreadcrumbsControl(labelContainer, { showFileIcons: false, showSymbolIcons: true, showDecorationColors: false, breadcrumbsBackground: () => Color.transparent });
|
||||
@@ -244,7 +244,7 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
title = ''; // dont repeat what is already shown
|
||||
}
|
||||
|
||||
this.editorLabel.setLabel({ name, description, resource }, { title, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] });
|
||||
this.editorLabel.setResource({ name, description, resource }, { title, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] });
|
||||
if (isGroupActive) {
|
||||
this.editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND);
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ export class RangeHighlightDecorations extends Disposable {
|
||||
private readonly _onHighlightRemoved: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onHighlghtRemoved(): Event<void> { return this._onHighlightRemoved.event; }
|
||||
|
||||
constructor(@IEditorService private editorService: IEditorService) {
|
||||
constructor(@IEditorService private readonly editorService: IEditorService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export class RangeHighlightDecorations extends Disposable {
|
||||
this.setEditor(editor);
|
||||
}
|
||||
|
||||
private getEditor(resourceRange: IRangeHighlightDecoration): ICodeEditor {
|
||||
private getEditor(resourceRange: IRangeHighlightDecoration): ICodeEditor | undefined {
|
||||
const activeEditor = this.editorService.activeEditor;
|
||||
const resource = activeEditor && activeEditor.getResource();
|
||||
if (resource) {
|
||||
@@ -67,7 +67,7 @@ export class RangeHighlightDecorations extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private setEditor(editor: ICodeEditor) {
|
||||
|
||||
@@ -13,12 +13,10 @@ import { LRUCache } from 'vs/base/common/map';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { clamp } from 'vs/base/common/numbers';
|
||||
import { Themable } from 'vs/workbench/common/theme';
|
||||
import { IStatusbarItem, StatusbarItemDescriptor, IStatusbarRegistry, Extensions } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import { StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IDisposable, Disposable, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
@@ -234,7 +232,7 @@ class FileSeemsBinaryFileView {
|
||||
|
||||
type Scale = number | 'fit';
|
||||
|
||||
class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
export class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
|
||||
static instance: ZoomStatusbarItem;
|
||||
|
||||
@@ -244,7 +242,7 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
private onSelectScale?: (scale: Scale) => void;
|
||||
|
||||
constructor(
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IThemeService themeService: IThemeService
|
||||
) {
|
||||
@@ -257,7 +255,7 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
|
||||
private onActiveEditorChanged(): void {
|
||||
this.hide();
|
||||
this.onSelectScale = void 0;
|
||||
this.onSelectScale = undefined;
|
||||
}
|
||||
|
||||
show(scale: Scale, onSelectScale: (scale: number) => void) {
|
||||
@@ -298,12 +296,12 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
private get zoomActions(): Action[] {
|
||||
const scales: Scale[] = [10, 5, 2, 1, 0.5, 0.2, 'fit'];
|
||||
return scales.map(scale =>
|
||||
new Action(`zoom.${scale}`, ZoomStatusbarItem.zoomLabel(scale), void 0, void 0, () => {
|
||||
new Action(`zoom.${scale}`, ZoomStatusbarItem.zoomLabel(scale), undefined, undefined, () => {
|
||||
if (this.onSelectScale) {
|
||||
this.onSelectScale(scale);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return Promise.resolve(undefined);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -314,10 +312,6 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
}
|
||||
}
|
||||
|
||||
Registry.as<IStatusbarRegistry>(Extensions.Statusbar).registerStatusbarItem(
|
||||
new StatusbarItemDescriptor(ZoomStatusbarItem, StatusbarAlignment.RIGHT, 101 /* to the left of editor status (100) */)
|
||||
);
|
||||
|
||||
interface ImageState {
|
||||
scale: Scale;
|
||||
offsetX: number;
|
||||
@@ -394,7 +388,7 @@ class InlineImageView {
|
||||
DOM.removeClass(image, 'pixelated');
|
||||
image.style.minWidth = 'auto';
|
||||
image.style.width = 'auto';
|
||||
InlineImageView.imageStateCache.set(cacheKey, null);
|
||||
InlineImageView.imageStateCache.delete(cacheKey);
|
||||
} else {
|
||||
const oldWidth = image.width;
|
||||
const oldHeight = image.height;
|
||||
@@ -432,6 +426,10 @@ class InlineImageView {
|
||||
}
|
||||
|
||||
function firstZoom() {
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
|
||||
scale = image.clientWidth / image.naturalWidth;
|
||||
updateScale(scale);
|
||||
}
|
||||
@@ -537,10 +535,13 @@ class InlineImageView {
|
||||
DOM.clearNode(container);
|
||||
DOM.addClasses(container, 'image', 'zoom-in');
|
||||
|
||||
image = DOM.append(container, DOM.$('img.scale-to-fit'));
|
||||
image = DOM.append(container, DOM.$<HTMLImageElement>('img.scale-to-fit'));
|
||||
image.style.visibility = 'hidden';
|
||||
|
||||
disposables.push(DOM.addDisposableListener(image, DOM.EventType.LOAD, e => {
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
if (typeof descriptor.size === 'number') {
|
||||
metadataClb(nls.localize('imgMeta', '{0}x{1} {2}', image.naturalWidth, image.naturalHeight, BinarySize.formatSize(descriptor.size)));
|
||||
} else {
|
||||
@@ -568,7 +569,7 @@ class InlineImageView {
|
||||
return context;
|
||||
}
|
||||
|
||||
private static imageSrc(descriptor: IResourceDescriptor, fileService: IFileService): Thenable<string> {
|
||||
private static imageSrc(descriptor: IResourceDescriptor, fileService: IFileService): Promise<string> {
|
||||
if (descriptor.resource.scheme === Schemas.data) {
|
||||
return Promise.resolve(descriptor.resource.toString(true /* skip encoding */));
|
||||
}
|
||||
@@ -582,7 +583,7 @@ class InlineImageView {
|
||||
}
|
||||
|
||||
function getMime(descriptor: IResourceDescriptor) {
|
||||
let mime = descriptor.mime;
|
||||
let mime: string | undefined = descriptor.mime;
|
||||
if (!mime && descriptor.resource.scheme !== Schemas.data) {
|
||||
mime = mimes.getMediaMime(descriptor.resource.path);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/br
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { SplitView, Sizing, Orientation } from 'vs/base/browser/ui/splitview/splitview';
|
||||
import { Event, Relay, anyEvent, mapEvent, Emitter } from 'vs/base/common/event';
|
||||
import { Event, Relay, Emitter } from 'vs/base/common/event';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
|
||||
export class SideBySideEditor extends BaseEditor {
|
||||
@@ -43,8 +43,8 @@ export class SideBySideEditor extends BaseEditor {
|
||||
get minimumHeight() { return this.minimumMasterHeight + this.minimumDetailsHeight; }
|
||||
get maximumHeight() { return this.maximumMasterHeight + this.maximumDetailsHeight; }
|
||||
|
||||
protected masterEditor: BaseEditor;
|
||||
protected detailsEditor: BaseEditor;
|
||||
protected masterEditor?: BaseEditor;
|
||||
protected detailsEditor?: BaseEditor;
|
||||
|
||||
private masterEditorContainer: HTMLElement;
|
||||
private detailsEditorContainer: HTMLElement;
|
||||
@@ -52,13 +52,13 @@ export class SideBySideEditor extends BaseEditor {
|
||||
private splitview: SplitView;
|
||||
private dimension: DOM.Dimension = new DOM.Dimension(0, 0);
|
||||
|
||||
private onDidCreateEditors = this._register(new Emitter<{ width: number; height: number; }>());
|
||||
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; }>());
|
||||
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }> = anyEvent(this.onDidCreateEditors.event, this._onDidSizeConstraintsChange.event);
|
||||
private onDidCreateEditors = this._register(new Emitter<{ width: number; height: number; } | undefined>());
|
||||
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; } | undefined>());
|
||||
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; } | undefined> = Event.any(this.onDidCreateEditors.event, this._onDidSizeConstraintsChange.event);
|
||||
|
||||
constructor(
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IStorageService storageService: IStorageService
|
||||
) {
|
||||
@@ -92,7 +92,7 @@ export class SideBySideEditor extends BaseEditor {
|
||||
this.updateStyles();
|
||||
}
|
||||
|
||||
setInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
|
||||
setInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
|
||||
const oldInput = <SideBySideEditorInput>this.input;
|
||||
return super.setInput(newInput, options, token)
|
||||
.then(() => this.updateInput(oldInput, newInput, options, token));
|
||||
@@ -141,7 +141,7 @@ export class SideBySideEditor extends BaseEditor {
|
||||
this.splitview.layout(dimension.width);
|
||||
}
|
||||
|
||||
getControl(): IEditorControl {
|
||||
getControl(): IEditorControl | null {
|
||||
if (this.masterEditor) {
|
||||
return this.masterEditor.getControl();
|
||||
}
|
||||
@@ -149,15 +149,15 @@ export class SideBySideEditor extends BaseEditor {
|
||||
return null;
|
||||
}
|
||||
|
||||
getMasterEditor(): IEditor {
|
||||
getMasterEditor(): IEditor | undefined {
|
||||
return this.masterEditor;
|
||||
}
|
||||
|
||||
getDetailsEditor(): IEditor {
|
||||
getDetailsEditor(): IEditor | undefined {
|
||||
return this.detailsEditor;
|
||||
}
|
||||
|
||||
private updateInput(oldInput: SideBySideEditorInput, newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
|
||||
private updateInput(oldInput: SideBySideEditorInput, newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
|
||||
if (!newInput.matches(oldInput)) {
|
||||
if (oldInput) {
|
||||
this.disposeEditors();
|
||||
@@ -165,22 +165,28 @@ export class SideBySideEditor extends BaseEditor {
|
||||
|
||||
return this.setNewInput(newInput, options, token);
|
||||
}
|
||||
if (!this.detailsEditor || !this.masterEditor) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
this.detailsEditor.setInput(newInput.details, null, token),
|
||||
this.masterEditor.setInput(newInput.master, options, token)]
|
||||
).then(() => void 0);
|
||||
).then(() => undefined);
|
||||
}
|
||||
|
||||
private setNewInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
|
||||
const detailsEditor = this._createEditor(<EditorInput>newInput.details, this.detailsEditorContainer);
|
||||
const masterEditor = this._createEditor(<EditorInput>newInput.master, this.masterEditorContainer);
|
||||
private setNewInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
|
||||
const detailsEditor = this.doCreateEditor(<EditorInput>newInput.details, this.detailsEditorContainer);
|
||||
const masterEditor = this.doCreateEditor(<EditorInput>newInput.master, this.masterEditorContainer);
|
||||
|
||||
return this.onEditorsCreated(detailsEditor, masterEditor, newInput.details, newInput.master, options, token);
|
||||
}
|
||||
|
||||
private _createEditor(editorInput: EditorInput, container: HTMLElement): BaseEditor {
|
||||
private doCreateEditor(editorInput: EditorInput, container: HTMLElement): BaseEditor {
|
||||
const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editorInput);
|
||||
if (!descriptor) {
|
||||
throw new Error('No descriptor for editor found');
|
||||
}
|
||||
|
||||
const editor = descriptor.instantiate(this.instantiationService);
|
||||
editor.create(container);
|
||||
@@ -193,12 +199,12 @@ export class SideBySideEditor extends BaseEditor {
|
||||
this.detailsEditor = details;
|
||||
this.masterEditor = master;
|
||||
|
||||
this._onDidSizeConstraintsChange.input = anyEvent(
|
||||
mapEvent(details.onDidSizeConstraintsChange, () => undefined),
|
||||
mapEvent(master.onDidSizeConstraintsChange, () => undefined)
|
||||
this._onDidSizeConstraintsChange.input = Event.any(
|
||||
Event.map(details.onDidSizeConstraintsChange, () => undefined),
|
||||
Event.map(master.onDidSizeConstraintsChange, () => undefined)
|
||||
);
|
||||
|
||||
this.onDidCreateEditors.fire();
|
||||
this.onDidCreateEditors.fire(undefined);
|
||||
|
||||
return Promise.all([this.detailsEditor.setInput(detailsInput, null, token), this.masterEditor.setInput(masterInput, options, token)]).then(() => this.focus());
|
||||
}
|
||||
@@ -214,12 +220,12 @@ export class SideBySideEditor extends BaseEditor {
|
||||
private disposeEditors(): void {
|
||||
if (this.detailsEditor) {
|
||||
this.detailsEditor.dispose();
|
||||
this.detailsEditor = null;
|
||||
this.detailsEditor = undefined;
|
||||
}
|
||||
|
||||
if (this.masterEditor) {
|
||||
this.masterEditor.dispose();
|
||||
this.masterEditor = null;
|
||||
this.masterEditor = undefined;
|
||||
}
|
||||
|
||||
this.detailsEditorContainer.innerHTML = '';
|
||||
|
||||
@@ -10,7 +10,7 @@ import { toResource, GroupIdentifier, IEditorInput, Verbosity, EditorCommandsCon
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { ResourceLabels, IResourceLabel, DEFAULT_LABELS_CONTAINER } from 'vs/workbench/browser/labels';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
@@ -69,7 +69,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
private tabsScrollbar: ScrollableElement;
|
||||
private closeOneEditorAction: CloseOneEditorAction;
|
||||
|
||||
private tabLabelWidgets: ResourceLabel[] = [];
|
||||
private tabResourceLabels: ResourceLabels;
|
||||
private tabLabels: IEditorInputLabel[] = [];
|
||||
private tabDisposeables: IDisposable[] = [];
|
||||
|
||||
@@ -83,7 +83,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
group: IEditorGroupView,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
|
||||
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@@ -142,6 +142,9 @@ export class TabsTitleControl extends TitleControl {
|
||||
addClass(breadcrumbsContainer, 'tabs-breadcrumbs');
|
||||
this.titleContainer.appendChild(breadcrumbsContainer);
|
||||
this.createBreadcrumbsControl(breadcrumbsContainer, { showFileIcons: true, showSymbolIcons: true, showDecorationColors: false, breadcrumbsBackground: breadcrumbsBackground });
|
||||
|
||||
// Tab Labels
|
||||
this.tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER));
|
||||
}
|
||||
|
||||
private createTabsScrollbar(scrollable: HTMLElement): ScrollableElement {
|
||||
@@ -314,7 +317,6 @@ export class TabsTitleControl extends TitleControl {
|
||||
(this.tabsContainer.lastChild as HTMLElement).remove();
|
||||
|
||||
// Remove associated tab label and widget
|
||||
this.tabLabelWidgets.pop();
|
||||
this.tabDisposeables.pop().dispose();
|
||||
}
|
||||
|
||||
@@ -330,7 +332,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
clearNode(this.tabsContainer);
|
||||
|
||||
this.tabDisposeables = dispose(this.tabDisposeables);
|
||||
this.tabLabelWidgets = [];
|
||||
this.tabResourceLabels.clear();
|
||||
this.tabLabels = [];
|
||||
|
||||
this.clearEditorActionsToolbar();
|
||||
@@ -414,12 +416,12 @@ export class TabsTitleControl extends TitleControl {
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
private withTab(editor: IEditorInput, fn: (tabContainer: HTMLElement, tabLabelWidget: ResourceLabel, tabLabel: IEditorInputLabel) => void): void {
|
||||
private withTab(editor: IEditorInput, fn: (tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
|
||||
const editorIndex = this.group.getIndexOfEditor(editor);
|
||||
|
||||
const tabContainer = this.tabsContainer.children[editorIndex] as HTMLElement;
|
||||
if (tabContainer) {
|
||||
fn(tabContainer, this.tabLabelWidgets[editorIndex], this.tabLabels[editorIndex]);
|
||||
fn(tabContainer, this.tabResourceLabels.get(editorIndex), this.tabLabels[editorIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,8 +443,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
tabContainer.appendChild(tabBorderTopContainer);
|
||||
|
||||
// Tab Editor Label
|
||||
const editorLabel = this.instantiationService.createInstance(ResourceLabel, tabContainer, void 0);
|
||||
this.tabLabelWidgets.push(editorLabel);
|
||||
const editorLabel = this.tabResourceLabels.create(tabContainer);
|
||||
|
||||
// Tab Close Button
|
||||
const tabCloseContainer = document.createElement('div');
|
||||
@@ -479,7 +480,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
e.preventDefault(); // required to prevent auto-scrolling (https://github.com/Microsoft/vscode/issues/16690)
|
||||
}
|
||||
|
||||
return void 0; // only for left mouse click
|
||||
return undefined; // only for left mouse click
|
||||
}
|
||||
|
||||
if (this.originatesFromTabActionBar(e)) {
|
||||
@@ -489,7 +490,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Open tabs editor
|
||||
this.group.openEditor(this.group.getEditor(index));
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const showContextMenu = (e: Event) => {
|
||||
@@ -836,16 +837,16 @@ export class TabsTitleControl extends TitleControl {
|
||||
this.layout(this.dimension);
|
||||
}
|
||||
|
||||
private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel, tabLabel: IEditorInputLabel) => void): void {
|
||||
private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
|
||||
this.group.editors.forEach((editor, index) => {
|
||||
const tabContainer = this.tabsContainer.children[index] as HTMLElement;
|
||||
if (tabContainer) {
|
||||
fn(editor, index, tabContainer, this.tabLabelWidgets[index], this.tabLabels[index]);
|
||||
fn(editor, index, tabContainer, this.tabResourceLabels.get(index), this.tabLabels[index]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel, tabLabel: IEditorInputLabel): void {
|
||||
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
|
||||
|
||||
// Label
|
||||
this.redrawLabel(editor, tabContainer, tabLabelWidget, tabLabel);
|
||||
@@ -880,7 +881,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
this.setEditorTabColor(editor, tabContainer, this.group.isActive(editor));
|
||||
}
|
||||
|
||||
private redrawLabel(editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel, tabLabel: IEditorInputLabel): void {
|
||||
private redrawLabel(editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
|
||||
const name = tabLabel.name;
|
||||
const description = tabLabel.description || '';
|
||||
const title = tabLabel.title || '';
|
||||
@@ -890,14 +891,14 @@ export class TabsTitleControl extends TitleControl {
|
||||
tabContainer.title = title;
|
||||
|
||||
// Label
|
||||
tabLabelWidget.setLabel({ name, description, resource: toResource(editor, { supportSideBySide: true }) }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) });
|
||||
tabLabelWidget.setResource({ name, description, resource: toResource(editor, { supportSideBySide: true }) }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) });
|
||||
|
||||
// {{SQL CARBON EDIT}} -- Display the editor's tab color
|
||||
const isTabActive = this.group.isActive(editor);
|
||||
this.setEditorTabColor(editor, tabContainer, isTabActive);
|
||||
}
|
||||
|
||||
private redrawEditorActiveAndDirty(isGroupActive: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel): void {
|
||||
private redrawEditorActiveAndDirty(isGroupActive: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel): void {
|
||||
const isTabActive = this.group.isActive(editor);
|
||||
|
||||
const hasModifiedBorderTop = this.doRedrawEditorDirty(isGroupActive, isTabActive, editor, tabContainer);
|
||||
@@ -905,7 +906,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
this.doRedrawEditorActive(isGroupActive, !hasModifiedBorderTop, editor, tabContainer, tabLabelWidget);
|
||||
}
|
||||
|
||||
private doRedrawEditorActive(isGroupActive: boolean, allowBorderTop: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: ResourceLabel): void {
|
||||
private doRedrawEditorActive(isGroupActive: boolean, allowBorderTop: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel): void {
|
||||
|
||||
// Tab is active
|
||||
if (this.group.isActive(editor)) {
|
||||
@@ -924,7 +925,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
tabContainer.style.removeProperty('--tab-border-bottom-color');
|
||||
}
|
||||
|
||||
const activeTabBorderColorTop = allowBorderTop ? this.getColor(isGroupActive ? TAB_ACTIVE_BORDER_TOP : TAB_UNFOCUSED_ACTIVE_BORDER_TOP) : void 0;
|
||||
const activeTabBorderColorTop = allowBorderTop ? this.getColor(isGroupActive ? TAB_ACTIVE_BORDER_TOP : TAB_UNFOCUSED_ACTIVE_BORDER_TOP) : undefined;
|
||||
if (activeTabBorderColorTop) {
|
||||
addClass(tabContainer, 'tab-border-top');
|
||||
tabContainer.style.setProperty('--tab-border-top-color', activeTabBorderColorTop.toString());
|
||||
@@ -1008,7 +1009,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
if (!this.layoutScheduled) {
|
||||
this.layoutScheduled = scheduleAtNextAnimationFrame(() => {
|
||||
this.doLayout(this.dimension);
|
||||
this.layoutScheduled = void 0;
|
||||
this.layoutScheduled = undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1073,7 +1074,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
return this.tabsContainer.children[editorIndex] as HTMLElement;
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private blockRevealActiveTabOnce(): void {
|
||||
@@ -1094,7 +1095,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
element = (e as GestureEvent).initialTarget as HTMLElement;
|
||||
}
|
||||
|
||||
return !!findParentWithClass(element, 'monaco-action-bar', 'tab');
|
||||
return !!findParentWithClass(element, 'action-item', 'tab');
|
||||
}
|
||||
|
||||
private onDrop(e: DragEvent, targetIndex: number): void {
|
||||
@@ -1185,21 +1186,21 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const activeContrastBorderColor = theme.getColor(activeContrastBorder);
|
||||
if (activeContrastBorderColor) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover {
|
||||
outline: 1px solid;
|
||||
outline-offset: -5px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
|
||||
outline: 1px dashed;
|
||||
outline-offset: -5px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label,
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
`);
|
||||
@@ -1209,7 +1210,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const tabHoverBackground = theme.getColor(TAB_HOVER_BACKGROUND);
|
||||
if (tabHoverBackground) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover {
|
||||
background-color: ${tabHoverBackground} !important;
|
||||
}
|
||||
`);
|
||||
@@ -1218,7 +1219,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const tabUnfocusedHoverBackground = theme.getColor(TAB_UNFOCUSED_HOVER_BACKGROUND);
|
||||
if (tabUnfocusedHoverBackground) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
|
||||
background-color: ${tabUnfocusedHoverBackground} !important;
|
||||
}
|
||||
`);
|
||||
@@ -1228,7 +1229,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const tabHoverBorder = theme.getColor(TAB_HOVER_BORDER);
|
||||
if (tabHoverBorder) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover {
|
||||
box-shadow: ${tabHoverBorder} 0 -1px inset !important;
|
||||
}
|
||||
`);
|
||||
@@ -1237,7 +1238,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const tabUnfocusedHoverBorder = theme.getColor(TAB_UNFOCUSED_HOVER_BORDER);
|
||||
if (tabUnfocusedHoverBorder) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover {
|
||||
box-shadow: ${tabUnfocusedHoverBorder} 0 -1px inset !important;
|
||||
}
|
||||
`);
|
||||
@@ -1265,12 +1266,12 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const adjustedColor = tabHoverBackground.flatten(adjustedTabBackground);
|
||||
const adjustedColorDrag = tabHoverBackground.flatten(adjustedTabDragBackground);
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content:not(.dragged-over) .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColor}, transparent) !important;
|
||||
}
|
||||
|
||||
|
||||
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
|
||||
}
|
||||
`);
|
||||
@@ -1281,11 +1282,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const adjustedColor = tabUnfocusedHoverBackground.flatten(adjustedTabBackground);
|
||||
const adjustedColorDrag = tabUnfocusedHoverBackground.flatten(adjustedTabDragBackground);
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColor}, transparent) !important;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
|
||||
}
|
||||
`);
|
||||
@@ -1295,8 +1296,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
if (editorDragAndDropBackground && adjustedTabDragBackground) {
|
||||
const adjustedColorDrag = editorDragAndDropBackground.flatten(adjustedTabDragBackground);
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged) > .tab-label::after,
|
||||
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged) > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged) > .tab-label::after,
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged) > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
|
||||
}
|
||||
`);
|
||||
@@ -1308,11 +1309,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const adjustedColor = tabActiveBackground.flatten(adjustedTabBackground);
|
||||
const adjustedColorDrag = tabActiveBackground.flatten(adjustedTabDragBackground);
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink.active:not(.dragged) > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink.active:not(.dragged) > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColor}, transparent);
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink.active:not(.dragged) > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink.active:not(.dragged) > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColorDrag}, transparent);
|
||||
}
|
||||
`);
|
||||
@@ -1324,11 +1325,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const adjustedColor = tabInactiveBackground.flatten(adjustedTabBackground);
|
||||
const adjustedColorDrag = tabInactiveBackground.flatten(adjustedTabDragBackground);
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged) > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged) > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColor}, transparent);
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged) > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.dragged) > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColorDrag}, transparent);
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -26,7 +26,7 @@ import { ScrollType, IDiffEditorViewState, IDiffEditorModel } from 'vs/editor/co
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { once } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -73,7 +73,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
||||
return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration);
|
||||
}
|
||||
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
|
||||
|
||||
// Dispose previous diff navigator
|
||||
this.diffNavigatorDisposables = dispose(this.diffNavigatorDisposables);
|
||||
@@ -87,12 +87,12 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
||||
|
||||
// Check for cancellation
|
||||
if (token.isCancellationRequested) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Assert Model Instance
|
||||
if (!(resolvedModel instanceof TextDiffEditorModel) && this.openAsBinary(input, options)) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Set Editor Model
|
||||
@@ -282,7 +282,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
||||
super.saveTextEditorViewState(resource);
|
||||
|
||||
// Make sure to clean up when the input gets disposed
|
||||
once(input.onDispose)(() => {
|
||||
Event.once(input.onDispose)(() => {
|
||||
super.clearTextEditorViewState([resource]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
private editorControl: IEditor;
|
||||
private _editorContainer: HTMLElement;
|
||||
private hasPendingConfigurationChange: boolean;
|
||||
private lastAppliedEditorOptions: IEditorOptions;
|
||||
private lastAppliedEditorOptions?: IEditorOptions;
|
||||
private editorMemento: IEditorMemento<IEditorViewState>;
|
||||
|
||||
constructor(
|
||||
@@ -53,13 +53,17 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
@ITextFileService private readonly _textFileService: ITextFileService,
|
||||
@IEditorService protected editorService: IEditorService,
|
||||
@IEditorGroupsService protected editorGroupService: IEditorGroupsService,
|
||||
@IWindowService private windowService: IWindowService
|
||||
@IWindowService private readonly windowService: IWindowService
|
||||
) {
|
||||
super(id, telemetryService, themeService, storageService);
|
||||
|
||||
this.editorMemento = this.getEditorMemento<IEditorViewState>(editorGroupService, TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY, 100);
|
||||
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => this.handleConfigurationChangeEvent(this.configurationService.getValue<IEditorConfiguration>(this.getResource()))));
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
const resource = this.getResource();
|
||||
const value = resource ? this.configurationService.getValue<IEditorConfiguration>(resource) : undefined;
|
||||
return this.handleConfigurationChangeEvent(value);
|
||||
}));
|
||||
}
|
||||
|
||||
protected get instantiationService(): IInstantiationService {
|
||||
@@ -129,7 +133,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
|
||||
// Editor for Text
|
||||
this._editorContainer = parent;
|
||||
this.editorControl = this._register(this.createEditorControl(parent, this.computeConfiguration(this.configurationService.getValue<IEditorConfiguration>(this.getResource()))));
|
||||
this.editorControl = this._register(this.createEditorControl(parent, this.computeConfiguration(this.configurationService.getValue<IEditorConfiguration>(this.getResource()!))));
|
||||
|
||||
// Model & Language changes
|
||||
const codeEditor = getCodeEditor(this.editorControl);
|
||||
@@ -170,7 +174,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
(reason === SaveReason.FOCUS_CHANGE && mode === AutoSaveMode.ON_FOCUS_CHANGE)
|
||||
) {
|
||||
if (this.textFileService.isDirty()) {
|
||||
this.textFileService.saveAll(void 0, { reason });
|
||||
this.textFileService.saveAll(undefined, { reason });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +191,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
return this.instantiationService.createInstance(CodeEditorWidget, parent, configuration, {});
|
||||
}
|
||||
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
|
||||
return super.setInput(input, options, token).then(() => {
|
||||
|
||||
// Update editor options after having set the input. We do this because there can be
|
||||
@@ -229,14 +233,14 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
*/
|
||||
protected saveTextEditorViewState(resource: URI): void {
|
||||
const editorViewState = this.retrieveTextEditorViewState(resource);
|
||||
if (!editorViewState) {
|
||||
if (!editorViewState || !this.group) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.editorMemento.saveEditorState(this.group, resource, editorViewState);
|
||||
}
|
||||
|
||||
protected retrieveTextEditorViewState(resource: URI): IEditorViewState {
|
||||
protected retrieveTextEditorViewState(resource: URI): IEditorViewState | null {
|
||||
const control = this.getControl() as ICodeEditor;
|
||||
const model = control.getModel();
|
||||
if (!model) {
|
||||
@@ -267,12 +271,18 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
/**
|
||||
* Loads the text editor view state for the given resource and returns it.
|
||||
*/
|
||||
protected loadTextEditorViewState(resource: URI): IEditorViewState {
|
||||
return this.editorMemento.loadEditorState(this.group, resource);
|
||||
protected loadTextEditorViewState(resource: URI): IEditorViewState | undefined {
|
||||
return this.group ? this.editorMemento.loadEditorState(this.group, resource) : undefined;
|
||||
}
|
||||
|
||||
private updateEditorConfiguration(configuration = this.configurationService.getValue<IEditorConfiguration>(this.getResource())): void {
|
||||
if (!this.editorControl) {
|
||||
private updateEditorConfiguration(configuration?: IEditorConfiguration): void {
|
||||
if (!configuration) {
|
||||
const resource = this.getResource();
|
||||
if (resource) {
|
||||
configuration = this.configurationService.getValue<IEditorConfiguration>(resource);
|
||||
}
|
||||
}
|
||||
if (!this.editorControl || !configuration) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -292,7 +302,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
}
|
||||
}
|
||||
|
||||
protected getResource(): URI {
|
||||
protected getResource(): URI | null {
|
||||
const codeEditor = getCodeEditor(this.editorControl);
|
||||
if (codeEditor) {
|
||||
const model = codeEditor.getModel();
|
||||
@@ -311,7 +321,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
|
||||
protected abstract getAriaLabel(): string;
|
||||
|
||||
dispose(): void {
|
||||
this.lastAppliedEditorOptions = void 0;
|
||||
this.lastAppliedEditorOptions = undefined;
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { once } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -54,7 +54,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
return nls.localize('textEditor', "Text Editor");
|
||||
}
|
||||
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
|
||||
setInput(input: EditorInput, options: EditorOptions, token: CancellationToken): Promise<void> {
|
||||
|
||||
// Remember view settings if input changes
|
||||
this.saveTextResourceEditorViewState(this.input);
|
||||
@@ -65,7 +65,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
|
||||
// Check for cancellation
|
||||
if (token.isCancellationRequested) {
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Assert Model instance
|
||||
@@ -90,7 +90,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
this.restoreTextResourceEditorViewState(input);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -136,19 +136,14 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
|
||||
/**
|
||||
* Reveals the last line of this editor if it has a model set.
|
||||
* When smart is true only scroll if the cursor is currently on the last line of the output panel.
|
||||
* This allows users to click on the output panel to stop scrolling when they see something of interest.
|
||||
* To resume, they should scroll to the end of the output panel again.
|
||||
*/
|
||||
revealLastLine(smart: boolean): void {
|
||||
revealLastLine(): void {
|
||||
const codeEditor = <ICodeEditor>this.getControl();
|
||||
const model = codeEditor.getModel();
|
||||
|
||||
if (model) {
|
||||
const lastLine = model.getLineCount();
|
||||
if (!smart || codeEditor.getPosition().lineNumber === lastLine) {
|
||||
codeEditor.revealPosition({ lineNumber: lastLine, column: model.getLineMaxColumn(lastLine) }, ScrollType.Smooth);
|
||||
}
|
||||
codeEditor.revealPosition({ lineNumber: lastLine, column: model.getLineMaxColumn(lastLine) }, ScrollType.Smooth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +185,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
super.saveTextEditorViewState(resource);
|
||||
|
||||
// Make sure to clean up when the input gets disposed
|
||||
once(input.onDispose)(() => {
|
||||
Event.once(input.onDispose)(() => {
|
||||
super.clearTextEditorViewState([resource]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -65,17 +65,17 @@ export abstract class TitleControl extends Themable {
|
||||
parent: HTMLElement,
|
||||
protected accessor: IEditorGroupsAccessor,
|
||||
protected group: IEditorGroupView,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IInstantiationService protected instantiationService: IInstantiationService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
// {{SQL CARBON EDIT}} -- need to make the notification service protected
|
||||
@INotificationService protected notificationService: INotificationService,
|
||||
@IMenuService private menuService: IMenuService,
|
||||
@INotificationService protected readonly notificationService: INotificationService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IQuickOpenService protected quickOpenService: IQuickOpenService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IConfigurationService protected configurationService: IConfigurationService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
) {
|
||||
@@ -320,11 +320,9 @@ export abstract class TitleControl extends Themable {
|
||||
protected getKeybindingLabel(action: IAction): string {
|
||||
const keybinding = this.getKeybinding(action);
|
||||
|
||||
return keybinding ? keybinding.getLabel() : void 0;
|
||||
return keybinding ? keybinding.getLabel() : undefined;
|
||||
}
|
||||
|
||||
//#region ITitleAreaControl
|
||||
|
||||
abstract openEditor(editor: IEditorInput): void;
|
||||
|
||||
abstract closeEditor(editor: IEditorInput): void;
|
||||
@@ -348,8 +346,6 @@ export abstract class TitleControl extends Themable {
|
||||
abstract updateStyles(): void;
|
||||
|
||||
layout(dimension: Dimension): void {
|
||||
// Optionally implemented in subclasses
|
||||
|
||||
if (this.breadcrumbsControl) {
|
||||
this.breadcrumbsControl.layout(undefined);
|
||||
}
|
||||
@@ -365,8 +361,6 @@ export abstract class TitleControl extends Themable {
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench > .part > .content > .composite {
|
||||
.monaco-workbench .part > .content > .composite {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .composite.title {
|
||||
.monaco-workbench .part > .composite.title {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part > .composite.title > .title-actions {
|
||||
.monaco-workbench .part > .composite.title > .title-actions {
|
||||
flex: 1;
|
||||
padding-left: 5px;
|
||||
}
|
||||
@@ -21,7 +21,7 @@ export class ClearNotificationAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super(id, label, 'clear-notification-action');
|
||||
}
|
||||
@@ -29,7 +29,7 @@ export class ClearNotificationAction extends Action {
|
||||
run(notification: INotificationViewItem): Promise<any> {
|
||||
this.commandService.executeCommand(CLEAR_NOTIFICATION, notification);
|
||||
|
||||
return Promise.resolve(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export class ClearAllNotificationsAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super(id, label, 'clear-all-notifications-action');
|
||||
}
|
||||
@@ -49,7 +49,7 @@ export class ClearAllNotificationsAction extends Action {
|
||||
run(notification: INotificationViewItem): Promise<any> {
|
||||
this.commandService.executeCommand(CLEAR_ALL_NOTIFICATIONS);
|
||||
|
||||
return Promise.resolve(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ export class HideNotificationsCenterAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super(id, label, 'hide-all-notifications-action');
|
||||
}
|
||||
@@ -69,7 +69,7 @@ export class HideNotificationsCenterAction extends Action {
|
||||
run(notification: INotificationViewItem): Promise<any> {
|
||||
this.commandService.executeCommand(HIDE_NOTIFICATIONS_CENTER);
|
||||
|
||||
return Promise.resolve(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ export class ExpandNotificationAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super(id, label, 'expand-notification-action');
|
||||
}
|
||||
@@ -89,7 +89,7 @@ export class ExpandNotificationAction extends Action {
|
||||
run(notification: INotificationViewItem): Promise<any> {
|
||||
this.commandService.executeCommand(EXPAND_NOTIFICATION, notification);
|
||||
|
||||
return Promise.resolve(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export class CollapseNotificationAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super(id, label, 'collapse-notification-action');
|
||||
}
|
||||
@@ -109,7 +109,7 @@ export class CollapseNotificationAction extends Action {
|
||||
run(notification: INotificationViewItem): Promise<any> {
|
||||
this.commandService.executeCommand(COLLAPSE_NOTIFICATION, notification);
|
||||
|
||||
return Promise.resolve(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ export class CopyNotificationMessageAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IClipboardService private clipboardService: IClipboardService
|
||||
@IClipboardService private readonly clipboardService: IClipboardService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
@@ -147,15 +147,15 @@ export class CopyNotificationMessageAction extends Action {
|
||||
run(notification: INotificationViewItem): Promise<any> {
|
||||
this.clipboardService.writeText(notification.message.raw);
|
||||
|
||||
return Promise.resolve(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
export class NotificationActionRunner extends ActionRunner {
|
||||
|
||||
constructor(
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@INotificationService private notificationService: INotificationService
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@INotificationService private readonly notificationService: INotificationService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -171,8 +171,8 @@ export class NotificationActionRunner extends ActionRunner {
|
||||
this.telemetryService.publicLog('workbenchActionExecuted', { id: action.id, from: 'message' });
|
||||
|
||||
// Run and make sure to notify on any error again
|
||||
super.runAction(action, context).then(null, error => this.notificationService.error(error));
|
||||
super.runAction(action, context).then(undefined, error => this.notificationService.error(error));
|
||||
|
||||
return Promise.resolve(void 0);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { INotificationViewItem, INotificationsModel, NotificationChangeType, INo
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { Severity } from 'vs/platform/notification/common/notification';
|
||||
import { once } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
|
||||
export class NotificationsAlerts extends Disposable {
|
||||
|
||||
@@ -52,7 +52,7 @@ export class NotificationsAlerts extends Disposable {
|
||||
}
|
||||
});
|
||||
|
||||
once(notifiation.onDidClose)(() => listener.dispose());
|
||||
Event.once(notifiation.onDidClose)(() => listener.dispose());
|
||||
|
||||
this.doTriggerAriaAlert(notifiation);
|
||||
}
|
||||
|
||||
@@ -42,11 +42,11 @@ export class NotificationsCenter extends Themable {
|
||||
private container: HTMLElement,
|
||||
private model: INotificationsModel,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IPartService private partService: IPartService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
@@ -152,10 +152,10 @@ export class NotificationsCenter extends Themable {
|
||||
this.container.appendChild(this.notificationsCenterContainer);
|
||||
}
|
||||
|
||||
private getKeybindingLabel(action: IAction): string {
|
||||
private getKeybindingLabel(action: IAction): string | null {
|
||||
const keybinding = this.keybindingService.lookupKeybinding(action.id);
|
||||
|
||||
return keybinding ? keybinding.getLabel() : void 0;
|
||||
return keybinding ? keybinding.getLabel() : null;
|
||||
}
|
||||
|
||||
private onDidNotificationChange(e: INotificationChangeEvent): void {
|
||||
|
||||
@@ -62,7 +62,7 @@ export interface INotificationsToastController {
|
||||
|
||||
export function registerNotificationCommands(center: INotificationsCenterController, toasts: INotificationsToastController): void {
|
||||
|
||||
function getNotificationFromContext(listService: IListService, context?: any): INotificationViewItem {
|
||||
function getNotificationFromContext(listService: IListService, context?: any): INotificationViewItem | undefined {
|
||||
if (isNotificationViewItem(context)) {
|
||||
return context;
|
||||
}
|
||||
@@ -75,7 +75,7 @@ export function registerNotificationCommands(center: INotificationsCenterControl
|
||||
}
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Show Notifications Cneter
|
||||
|
||||
@@ -26,9 +26,9 @@ export class NotificationsList extends Themable {
|
||||
constructor(
|
||||
private container: HTMLElement,
|
||||
private options: IListOptions<INotificationViewItem>,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
@@ -77,7 +77,8 @@ export class NotificationsList extends Themable {
|
||||
[renderer],
|
||||
{
|
||||
...this.options,
|
||||
setRowLineHeight: false
|
||||
setRowLineHeight: false,
|
||||
horizontalScrolling: false
|
||||
}
|
||||
));
|
||||
|
||||
@@ -89,7 +90,7 @@ export class NotificationsList extends Themable {
|
||||
}
|
||||
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
getAnchor: () => e.anchor!,
|
||||
getActions: () => [copyAction],
|
||||
getActionsContext: () => e.element,
|
||||
actionRunner
|
||||
@@ -133,7 +134,7 @@ export class NotificationsList extends Themable {
|
||||
const focusedIndex = this.list.getFocus()[0];
|
||||
const focusedItem = this.viewModel[focusedIndex];
|
||||
|
||||
let focusRelativeTop: number;
|
||||
let focusRelativeTop: number | null = null;
|
||||
if (typeof focusedIndex === 'number') {
|
||||
focusRelativeTop = this.list.getRelativeTop(focusedIndex);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export class NotificationsStatus extends Disposable {
|
||||
|
||||
constructor(
|
||||
private model: INotificationsModel,
|
||||
@IStatusbarService private statusbarService: IStatusbarService
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService
|
||||
) {
|
||||
super();
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { addClass, removeClass, isAncestor, addDisposableListener, EventType, Dimension } from 'vs/base/browser/dom';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { NotificationsList } from 'vs/workbench/browser/parts/notifications/notificationsList';
|
||||
import { once } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
|
||||
import { Themable, NOTIFICATIONS_TOAST_BORDER } from 'vs/workbench/common/theme';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
@@ -22,6 +22,7 @@ import { Severity } from 'vs/platform/notification/common/notification';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
|
||||
interface INotificationToast {
|
||||
item: INotificationViewItem;
|
||||
@@ -53,7 +54,6 @@ export class NotificationsToasts extends Themable {
|
||||
|
||||
private notificationsToastsContainer: HTMLElement;
|
||||
private workbenchDimensions: Dimension;
|
||||
private windowHasFocus: boolean;
|
||||
private isNotificationsCenterVisible: boolean;
|
||||
private mapNotificationToToast: Map<INotificationViewItem, INotificationToast>;
|
||||
private notificationsToastsVisibleContextKey: IContextKey<boolean>;
|
||||
@@ -61,28 +61,26 @@ export class NotificationsToasts extends Themable {
|
||||
constructor(
|
||||
private container: HTMLElement,
|
||||
private model: INotificationsModel,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IPartService private partService: IPartService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@ILifecycleService private lifecycleService: ILifecycleService,
|
||||
@IWindowService private windowService: IWindowService
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IWindowService private readonly windowService: IWindowService
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
this.mapNotificationToToast = new Map<INotificationViewItem, INotificationToast>();
|
||||
this.notificationsToastsVisibleContextKey = NotificationsToastsVisibleContext.bindTo(contextKeyService);
|
||||
|
||||
this.windowService.isFocused().then(isFocused => this.windowHasFocus = isFocused);
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Wait for the running phase to ensure we can draw notifications properly
|
||||
this.lifecycleService.when(LifecyclePhase.Ready).then(() => {
|
||||
// Delay some tasks until after we can show notifications
|
||||
this.onCanShowNotifications().then(() => {
|
||||
|
||||
// Show toast for initial notifications if any
|
||||
this.model.notifications.forEach(notification => this.addToast(notification));
|
||||
@@ -90,9 +88,20 @@ export class NotificationsToasts extends Themable {
|
||||
// Update toasts on notification changes
|
||||
this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
|
||||
});
|
||||
}
|
||||
|
||||
// Track window focus
|
||||
this.windowService.onDidChangeFocus(hasFocus => this.windowHasFocus = hasFocus);
|
||||
private onCanShowNotifications(): Promise<void> {
|
||||
|
||||
// Wait for the running phase to ensure we can draw notifications properly
|
||||
return this.lifecycleService.when(LifecyclePhase.Ready).then(() => {
|
||||
|
||||
// Push notificiations out until either workbench is restored
|
||||
// or some time has ellapsed to reduce pressure on the startup
|
||||
return Promise.race([
|
||||
this.lifecycleService.when(LifecyclePhase.Restored),
|
||||
timeout(2000)
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
private onDidNotificationChange(e: INotificationChangeEvent): void {
|
||||
@@ -185,7 +194,7 @@ export class NotificationsToasts extends Themable {
|
||||
}));
|
||||
|
||||
// Remove when item gets closed
|
||||
once(item.onDidClose)(() => {
|
||||
Event.once(item.onDidClose)(() => {
|
||||
this.removeToast(item);
|
||||
});
|
||||
|
||||
@@ -226,7 +235,7 @@ export class NotificationsToasts extends Themable {
|
||||
// the timeout again. This prevents an issue where focussing the window
|
||||
// could immediately hide the notification because the timeout was triggered
|
||||
// again.
|
||||
if ((item.sticky || item.hasPrompt()) && !this.windowHasFocus) {
|
||||
if ((item.sticky || item.hasPrompt()) && !this.windowService.hasFocus) {
|
||||
if (!listener) {
|
||||
listener = this.windowService.onDidChangeFocus(focus => {
|
||||
if (focus) {
|
||||
@@ -447,7 +456,7 @@ export class NotificationsToasts extends Themable {
|
||||
let maxWidth = NotificationsToasts.MAX_WIDTH;
|
||||
|
||||
let availableWidth = maxWidth;
|
||||
let availableHeight: number;
|
||||
let availableHeight: number | undefined;
|
||||
|
||||
if (this.workbenchDimensions) {
|
||||
|
||||
@@ -468,7 +477,9 @@ export class NotificationsToasts extends Themable {
|
||||
availableHeight -= (2 * 12); // adjust for paddings top and bottom
|
||||
}
|
||||
|
||||
availableHeight = Math.round(availableHeight * 0.618); // try to not cover the full height for stacked toasts
|
||||
availableHeight = typeof availableHeight === 'number'
|
||||
? Math.round(availableHeight * 0.618) // try to not cover the full height for stacked toasts
|
||||
: 0;
|
||||
|
||||
return new Dimension(Math.min(maxWidth, availableWidth), availableHeight);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,13 @@ import { IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { DropdownMenuActionItem } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { DropdownMenuActionItem, IContextMenuProvider } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { INotificationViewItem, NotificationViewItem, NotificationViewItemLabelKind, INotificationMessage, ChoiceAction } from 'vs/workbench/common/notifications';
|
||||
import { ClearNotificationAction, ExpandNotificationAction, CollapseNotificationAction, ConfigureNotificationAction } from 'vs/workbench/browser/parts/notifications/notificationsActions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { Severity } from 'vs/platform/notification/common/notification';
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
|
||||
export class NotificationsListDelegate implements IListVirtualDelegate<INotificationViewItem> {
|
||||
|
||||
@@ -61,7 +62,7 @@ export class NotificationsListDelegate implements IListVirtualDelegate<INotifica
|
||||
}
|
||||
|
||||
// Last row: source and buttons if we have any
|
||||
if (notification.source || notification.actions.primary.length > 0) {
|
||||
if (notification.source || isNonEmptyArray(notification.actions.primary)) {
|
||||
expandedHeight += NotificationsListDelegate.ROW_HEIGHT;
|
||||
}
|
||||
|
||||
@@ -81,7 +82,7 @@ export class NotificationsListDelegate implements IListVirtualDelegate<INotifica
|
||||
if (notification.canCollapse) {
|
||||
actions++; // expand/collapse
|
||||
}
|
||||
if (notification.actions.secondary.length > 0) {
|
||||
if (isNonEmptyArray(notification.actions.secondary)) {
|
||||
actions++; // secondary actions
|
||||
}
|
||||
this.offsetHelper.style.width = `calc(100% - ${10 /* padding */ + 24 /* severity icon */ + (actions * 24) /* 24px per action */}px)`;
|
||||
@@ -104,7 +105,7 @@ export class NotificationsListDelegate implements IListVirtualDelegate<INotifica
|
||||
return NotificationRenderer.TEMPLATE_ID;
|
||||
}
|
||||
|
||||
return void 0;
|
||||
throw new Error('unknown element type: ' + element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,8 +144,7 @@ class NotificationMessageRenderer {
|
||||
// Message has links
|
||||
else {
|
||||
let index = 0;
|
||||
for (let i = 0; i < message.links.length; i++) {
|
||||
const link = message.links[i];
|
||||
for (const link of message.links) {
|
||||
|
||||
const textBefore = message.value.substring(index, link.offset);
|
||||
if (textBefore) {
|
||||
@@ -182,9 +182,9 @@ export class NotificationRenderer implements IListRenderer<INotificationViewItem
|
||||
|
||||
constructor(
|
||||
private actionRunner: IActionRunner,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -220,8 +220,8 @@ export class NotificationRenderer implements IListRenderer<INotificationViewItem
|
||||
{
|
||||
ariaLabel: localize('notificationActions', "Notification Actions"),
|
||||
actionItemProvider: action => {
|
||||
if (action instanceof ConfigureNotificationAction) {
|
||||
const item = new DropdownMenuActionItem(action, action.configurationActions, this.contextMenuService, null, this.actionRunner, null, action.class);
|
||||
if (action && action instanceof ConfigureNotificationAction) {
|
||||
const item = new DropdownMenuActionItem(action, action.configurationActions, this.contextMenuService as IContextMenuProvider, undefined, this.actionRunner, undefined, action.class as string);
|
||||
data.toDispose.push(item);
|
||||
|
||||
return item;
|
||||
@@ -275,10 +275,6 @@ export class NotificationRenderer implements IListRenderer<INotificationViewItem
|
||||
data.renderer.setInput(notification);
|
||||
}
|
||||
|
||||
disposeElement(): void {
|
||||
// noop
|
||||
}
|
||||
|
||||
disposeTemplate(templateData: INotificationTemplateData): void {
|
||||
templateData.toDispose = dispose(templateData.toDispose);
|
||||
}
|
||||
@@ -290,17 +286,17 @@ export class NotificationTemplateRenderer {
|
||||
private static expandNotificationAction: ExpandNotificationAction;
|
||||
private static collapseNotificationAction: CollapseNotificationAction;
|
||||
|
||||
private static readonly SEVERITIES: ('info' | 'warning' | 'error')[] = ['info', 'warning', 'error'];
|
||||
private static readonly SEVERITIES: Array<'info' | 'warning' | 'error'> = ['info', 'warning', 'error'];
|
||||
|
||||
private inputDisposeables: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
private template: INotificationTemplateData,
|
||||
private actionRunner: IActionRunner,
|
||||
@IOpenerService private openerService: IOpenerService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService
|
||||
@IOpenerService private readonly openerService: IOpenerService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
if (!NotificationTemplateRenderer.closeNotificationAction) {
|
||||
NotificationTemplateRenderer.closeNotificationAction = instantiationService.createInstance(ClearNotificationAction, ClearNotificationAction.ID, ClearNotificationAction.LABEL);
|
||||
@@ -374,7 +370,7 @@ export class NotificationTemplateRenderer {
|
||||
|
||||
const messageOverflows = notification.canCollapse && !notification.expanded && this.template.message.scrollWidth > this.template.message.clientWidth;
|
||||
if (messageOverflows) {
|
||||
this.template.message.title = this.template.message.textContent;
|
||||
this.template.message.title = this.template.message.textContent + '';
|
||||
} else {
|
||||
this.template.message.removeAttribute('title');
|
||||
}
|
||||
@@ -391,7 +387,7 @@ export class NotificationTemplateRenderer {
|
||||
const actions: IAction[] = [];
|
||||
|
||||
// Secondary Actions
|
||||
if (notification.actions.secondary.length > 0) {
|
||||
if (isNonEmptyArray(notification.actions.secondary)) {
|
||||
const configureNotificationAction = this.instantiationService.createInstance(ConfigureNotificationAction, ConfigureNotificationAction.ID, ConfigureNotificationAction.LABEL, notification.actions.secondary);
|
||||
actions.push(configureNotificationAction);
|
||||
this.inputDisposeables.push(configureNotificationAction);
|
||||
@@ -434,10 +430,10 @@ export class NotificationTemplateRenderer {
|
||||
private renderButtons(notification: INotificationViewItem): void {
|
||||
clearNode(this.template.buttonsContainer);
|
||||
|
||||
if (notification.expanded) {
|
||||
if (notification.expanded && notification.actions.primary) {
|
||||
const buttonGroup = new ButtonGroup(this.template.buttonsContainer, notification.actions.primary.length, { title: true /* assign titles to buttons in case they overflow */ });
|
||||
buttonGroup.buttons.forEach((button, index) => {
|
||||
const action = notification.actions.primary[index];
|
||||
const action = notification.actions.primary![index];
|
||||
button.label = action.label;
|
||||
|
||||
this.inputDisposeables.push(button.onDidClick(e => {
|
||||
@@ -502,10 +498,10 @@ export class NotificationTemplateRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
private getKeybindingLabel(action: IAction): string {
|
||||
private getKeybindingLabel(action: IAction): string | null {
|
||||
const keybinding = this.keybindingService.lookupKeybinding(action.id);
|
||||
|
||||
return keybinding ? keybinding.getLabel() : void 0;
|
||||
return keybinding ? keybinding.getLabel() : null;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench.nopanel > .part.panel {
|
||||
.monaco-workbench.nopanel .part.panel {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel {
|
||||
.monaco-workbench .part.panel {
|
||||
z-index: initial;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel .title {
|
||||
.monaco-workbench .part.panel .title {
|
||||
padding-right: 0px;
|
||||
height: 35px;
|
||||
display: flex;
|
||||
@@ -20,23 +20,23 @@
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel.bottom .title {
|
||||
.monaco-workbench .part.panel.bottom .title {
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel.right {
|
||||
.monaco-workbench .part.panel.right {
|
||||
border-left-width: 1px;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .title-actions .monaco-action-bar .action-item .action-label {
|
||||
.monaco-workbench .part.panel > .title > .title-actions .monaco-action-bar .action-item .action-label {
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/** Panel Switcher */
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more {
|
||||
background-image: url('ellipsis.svg');
|
||||
display: block;
|
||||
height: 28px;
|
||||
@@ -48,16 +48,16 @@
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar {
|
||||
line-height: 27px; /* matches panel titles in settings */
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:first-child {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:first-child {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item {
|
||||
text-transform: uppercase;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
@@ -67,24 +67,24 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label{
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label{
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:last-child {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:last-child {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label {
|
||||
border-bottom: 1px solid;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge .badge-content {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .badge .badge-content {
|
||||
padding: 0.3em 0.5em;
|
||||
border-radius: 1em;
|
||||
font-weight: normal;
|
||||
@@ -152,7 +152,7 @@
|
||||
background: url('close-inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more,
|
||||
.hc-black .monaco-workbench > .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more {
|
||||
.vs-dark .monaco-workbench .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more,
|
||||
.hc-black .monaco-workbench .part.panel > .title > .panel-switcher-container.composite-bar > .monaco-action-bar .action-label.toggle-more {
|
||||
background-image: url('ellipsis-inverse.svg');
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ export class ClosePanelAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
name: string,
|
||||
@IPartService private partService: IPartService
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, name, 'hide-panel-action');
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.partService.setPanelHidden(true);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
@@ -43,12 +43,12 @@ export class TogglePanelAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
name: string,
|
||||
@IPartService private partService: IPartService
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, name, partService.isVisible(Parts.PANEL_PART) ? 'panel expanded' : 'panel');
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
this.partService.setPanelHidden(this.partService.isVisible(Parts.PANEL_PART));
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
@@ -62,13 +62,13 @@ class FocusPanelAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPanelService private panelService: IPanelService,
|
||||
@IPartService private partService: IPartService
|
||||
@IPanelService private readonly panelService: IPanelService,
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
|
||||
// Show panel
|
||||
if (!this.partService.isVisible(Parts.PANEL_PART)) {
|
||||
@@ -99,7 +99,7 @@ export class TogglePanelPositionAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private partService: IPartService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
) {
|
||||
super(id, label, partService.getPanelPosition() === Position.RIGHT ? 'move-panel-to-bottom' : 'move-panel-to-right');
|
||||
|
||||
@@ -116,7 +116,7 @@ export class TogglePanelPositionAction extends Action {
|
||||
setClassAndLabel();
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
const position = this.partService.getPanelPosition();
|
||||
|
||||
this.partService.setPanelPosition(position === Position.BOTTOM ? Position.RIGHT : Position.BOTTOM);
|
||||
@@ -143,7 +143,7 @@ export class ToggleMaximizedPanelAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IPartService private partService: IPartService
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, label, partService.isPanelMaximized() ? 'minimize-panel-action' : 'maximize-panel-action');
|
||||
|
||||
@@ -156,7 +156,7 @@ export class ToggleMaximizedPanelAction extends Action {
|
||||
}));
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
if (!this.partService.isVisible(Parts.PANEL_PART)) {
|
||||
this.partService.setPanelHidden(false);
|
||||
}
|
||||
@@ -176,12 +176,12 @@ export class PanelActivityAction extends ActivityAction {
|
||||
|
||||
constructor(
|
||||
activity: IActivity,
|
||||
@IPanelService private panelService: IPanelService
|
||||
@IPanelService private readonly panelService: IPanelService
|
||||
) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
run(event: any): Thenable<any> {
|
||||
run(event: any): Promise<any> {
|
||||
this.panelService.openPanel(this.activity.id, true);
|
||||
this.activate();
|
||||
return Promise.resolve(null);
|
||||
@@ -193,12 +193,12 @@ export class SwitchPanelViewAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
name: string,
|
||||
@IPanelService private panelService: IPanelService
|
||||
@IPanelService private readonly panelService: IPanelService
|
||||
) {
|
||||
super(id, name);
|
||||
}
|
||||
|
||||
run(offset: number): Thenable<any> {
|
||||
run(offset: number): Promise<any> {
|
||||
const pinnedPanels = this.panelService.getPinnedPanels();
|
||||
const activePanel = this.panelService.getActivePanel();
|
||||
if (!activePanel) {
|
||||
@@ -229,7 +229,7 @@ export class PreviousPanelViewAction extends SwitchPanelViewAction {
|
||||
super(id, name, panelService);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
return super.run(-1);
|
||||
}
|
||||
}
|
||||
@@ -247,7 +247,7 @@ export class NextPanelViewAction extends SwitchPanelViewAction {
|
||||
super(id, name, panelService);
|
||||
}
|
||||
|
||||
public run(): Thenable<any> {
|
||||
public run(): Promise<any> {
|
||||
return super.run(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import 'vs/css!./media/panelpart';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { Event, mapEvent } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IPanel } from 'vs/workbench/common/panel';
|
||||
@@ -13,7 +13,7 @@ import { CompositePart, ICompositeTitleLabel } from 'vs/workbench/browser/parts/
|
||||
import { Panel, PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel';
|
||||
import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { IPartService, Parts, Position } from 'vs/workbench/services/part/common/partService';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
@@ -22,7 +22,7 @@ import { ClosePanelAction, TogglePanelPositionAction, PanelActivityAction, Toggl
|
||||
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
|
||||
import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { CompositeBar } from 'vs/workbench/browser/parts/compositeBar';
|
||||
import { CompositeBar, ICompositeBarItem } from 'vs/workbench/browser/parts/compositeBar';
|
||||
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
|
||||
import { IBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
@@ -30,11 +30,22 @@ import { Dimension, trackFocus } from 'vs/base/browser/dom';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
|
||||
import { LayoutPriority } from 'vs/base/browser/ui/grid/gridview';
|
||||
|
||||
export const ActivePanelContext = new RawContextKey<string>('activePanel', '');
|
||||
export const PanelFocusContext = new RawContextKey<boolean>('panelFocus', false);
|
||||
|
||||
export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
interface ICachedPanel {
|
||||
id: string;
|
||||
pinned: boolean;
|
||||
order: number;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export class PanelPart extends CompositePart<Panel> implements IPanelService, ISerializableView {
|
||||
|
||||
static readonly activePanelSettingsKey = 'workbench.panelpart.activepanelid';
|
||||
|
||||
@@ -50,6 +61,17 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
private compositeActions: { [compositeId: string]: { activityAction: PanelActivityAction, pinnedAction: ToggleCompositePinnedAction } } = Object.create(null);
|
||||
private dimension: Dimension;
|
||||
|
||||
element: HTMLElement;
|
||||
minimumWidth: number = 300;
|
||||
maximumWidth: number = Number.POSITIVE_INFINITY;
|
||||
minimumHeight: number = 77;
|
||||
maximumHeight: number = Number.POSITIVE_INFINITY;
|
||||
snapSize: number = 50;
|
||||
priority: LayoutPriority = LayoutPriority.Low;
|
||||
|
||||
private _onDidChange = new Emitter<{ width: number; height: number; }>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@@ -61,6 +83,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService
|
||||
) {
|
||||
super(
|
||||
notificationService,
|
||||
@@ -81,9 +104,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
{ hasTitle: true }
|
||||
);
|
||||
|
||||
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, {
|
||||
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.getCachedPanels(), {
|
||||
icon: false,
|
||||
storageId: PanelPart.PINNED_PANELS,
|
||||
orientation: ActionsOrientation.HORIZONTAL,
|
||||
openComposite: (compositeId: string) => Promise.resolve(this.openPanel(compositeId, true)),
|
||||
getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction,
|
||||
@@ -120,6 +142,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
}
|
||||
|
||||
create(parent: HTMLElement): void {
|
||||
this.element = parent;
|
||||
|
||||
super.create(parent);
|
||||
|
||||
const focusTracker = trackFocus(parent);
|
||||
@@ -137,6 +161,10 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
this._register(this.onDidPanelClose(this._onDidPanelClose, this));
|
||||
|
||||
this._register(this.registry.onDidRegister(panelDescriptor => this.compositeBar.addComposite(panelDescriptor)));
|
||||
this._register(this.registry.onDidDeregister(panelDescriptor => {
|
||||
this.compositeBar.hideComposite(panelDescriptor.id);
|
||||
this.removeComposite(panelDescriptor.id);
|
||||
}));
|
||||
|
||||
// Activate panel action on opening of a panel
|
||||
this._register(this.onDidPanelOpen(({ panel }) => {
|
||||
@@ -146,6 +174,11 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
|
||||
// Deactivate panel action on close
|
||||
this._register(this.onDidPanelClose(panel => this.compositeBar.deactivateComposite(panel.getId())));
|
||||
|
||||
this.lifecycleService.when(LifecyclePhase.Eventually).then(() => {
|
||||
this._register(this.compositeBar.onDidChange(() => this.saveCachedPanels()));
|
||||
this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e)));
|
||||
});
|
||||
}
|
||||
|
||||
private _onDidPanelOpen(panel: IPanel): void {
|
||||
@@ -161,7 +194,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
}
|
||||
|
||||
get onDidPanelOpen(): Event<{ panel: IPanel, focus: boolean }> {
|
||||
return mapEvent(this._onDidCompositeOpen.event, compositeOpen => ({ panel: compositeOpen.composite, focus: compositeOpen.focus }));
|
||||
return Event.map(this._onDidCompositeOpen.event, compositeOpen => ({ panel: compositeOpen.composite, focus: compositeOpen.focus }));
|
||||
}
|
||||
|
||||
get onDidPanelClose(): Event<IPanel> {
|
||||
@@ -207,7 +240,6 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
|
||||
getPanels(): PanelDescriptor[] {
|
||||
return Registry.as<PanelRegistry>(PanelExtensions.Panels).getPanels()
|
||||
.filter(p => p.enabled)
|
||||
.sort((v1, v2) => v1.order - v2.order);
|
||||
}
|
||||
|
||||
@@ -218,18 +250,6 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
.sort((p1, p2) => pinnedCompositeIds.indexOf(p1.id) - pinnedCompositeIds.indexOf(p2.id));
|
||||
}
|
||||
|
||||
setPanelEnablement(id: string, enabled: boolean): void {
|
||||
const descriptor = Registry.as<PanelRegistry>(PanelExtensions.Panels).getPanels().filter(p => p.id === id).pop();
|
||||
if (descriptor && descriptor.enabled !== enabled) {
|
||||
descriptor.enabled = enabled;
|
||||
if (enabled) {
|
||||
this.compositeBar.addComposite(descriptor);
|
||||
} else {
|
||||
this.removeComposite(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected getActions(): IAction[] {
|
||||
return [
|
||||
this.instantiationService.createInstance(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, ToggleMaximizedPanelAction.LABEL),
|
||||
@@ -266,21 +286,32 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
};
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): Dimension[] {
|
||||
layout(dimension: Dimension): Dimension[];
|
||||
layout(width: number, height: number): void;
|
||||
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
|
||||
if (!this.partService.isVisible(Parts.PANEL_PART)) {
|
||||
return [dimension];
|
||||
if (dim1 instanceof Dimension) {
|
||||
return [dim1];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const { width, height } = dim1 instanceof Dimension ? dim1 : { width: dim1, height: dim2 };
|
||||
|
||||
if (this.partService.getPanelPosition() === Position.RIGHT) {
|
||||
// Take into account the 1px border when layouting
|
||||
this.dimension = new Dimension(dimension.width - 1, dimension.height);
|
||||
this.dimension = new Dimension(width - 1, height);
|
||||
} else {
|
||||
this.dimension = dimension;
|
||||
this.dimension = new Dimension(width, height);
|
||||
}
|
||||
const sizes = super.layout(this.dimension);
|
||||
|
||||
const sizes = super.layout(this.dimension.width, this.dimension.height);
|
||||
this.layoutCompositeBar();
|
||||
|
||||
return sizes;
|
||||
if (dim1 instanceof Dimension) {
|
||||
return sizes;
|
||||
}
|
||||
}
|
||||
|
||||
private layoutCompositeBar(): void {
|
||||
@@ -306,14 +337,17 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
return compositeActions;
|
||||
}
|
||||
|
||||
private removeComposite(compositeId: string): void {
|
||||
this.compositeBar.hideComposite(compositeId);
|
||||
const compositeActions = this.compositeActions[compositeId];
|
||||
if (compositeActions) {
|
||||
compositeActions.activityAction.dispose();
|
||||
compositeActions.pinnedAction.dispose();
|
||||
delete this.compositeActions[compositeId];
|
||||
protected removeComposite(compositeId: string): boolean {
|
||||
if (super.removeComposite(compositeId)) {
|
||||
const compositeActions = this.compositeActions[compositeId];
|
||||
if (compositeActions) {
|
||||
compositeActions.activityAction.dispose();
|
||||
compositeActions.pinnedAction.dispose();
|
||||
delete this.compositeActions[compositeId];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private getToolbarWidth(): number {
|
||||
@@ -323,6 +357,89 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
}
|
||||
return this.toolBar.getItemsWidth();
|
||||
}
|
||||
|
||||
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
|
||||
if (e.key === PanelPart.PINNED_PANELS && e.scope === StorageScope.GLOBAL
|
||||
&& this.cachedPanelsValue !== this.getStoredCachedPanelsValue() /* This checks if current window changed the value or not */) {
|
||||
this._cachedPanelsValue = null;
|
||||
const newCompositeItems: ICompositeBarItem[] = [];
|
||||
const compositeItems = this.compositeBar.getCompositeBarItems();
|
||||
const cachedPanels = this.getCachedPanels();
|
||||
|
||||
for (const cachedPanel of cachedPanels) {
|
||||
// Add and update existing items
|
||||
const existingItem = compositeItems.filter(({ id }) => id === cachedPanel.id)[0];
|
||||
if (existingItem) {
|
||||
newCompositeItems.push({
|
||||
id: existingItem.id,
|
||||
name: existingItem.name,
|
||||
order: existingItem.order,
|
||||
pinned: cachedPanel.pinned,
|
||||
visible: existingItem.visible
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (let index = 0; index < compositeItems.length; index++) {
|
||||
// Add items currently exists but does not exist in new.
|
||||
if (!newCompositeItems.some(({ id }) => id === compositeItems[index].id)) {
|
||||
newCompositeItems.splice(index, 0, compositeItems[index]);
|
||||
}
|
||||
}
|
||||
|
||||
this.compositeBar.setCompositeBarItems(newCompositeItems);
|
||||
}
|
||||
}
|
||||
|
||||
private saveCachedPanels(): void {
|
||||
const state: ICachedPanel[] = [];
|
||||
const compositeItems = this.compositeBar.getCompositeBarItems();
|
||||
for (const compositeItem of compositeItems) {
|
||||
state.push({ id: compositeItem.id, pinned: compositeItem.pinned, order: compositeItem.order, visible: compositeItem.visible });
|
||||
}
|
||||
this.cachedPanelsValue = JSON.stringify(state);
|
||||
}
|
||||
|
||||
private getCachedPanels(): ICachedPanel[] {
|
||||
const storedStates = <Array<string | ICachedPanel>>JSON.parse(this.cachedPanelsValue);
|
||||
const registeredPanels = this.getPanels();
|
||||
const cachedPanels = <ICachedPanel[]>storedStates.map(c => {
|
||||
const serialized: ICachedPanel = typeof c === 'string' /* migration from pinned states to composites states */ ? <ICachedPanel>{ id: c, pinned: true, order: undefined, visible: true } : c;
|
||||
const registered = registeredPanels.some(p => p.id === serialized.id);
|
||||
serialized.visible = registered ? isUndefinedOrNull(serialized.visible) ? true : serialized.visible : false;
|
||||
return serialized;
|
||||
});
|
||||
return cachedPanels;
|
||||
}
|
||||
|
||||
private _cachedPanelsValue: string;
|
||||
private get cachedPanelsValue(): string {
|
||||
if (!this._cachedPanelsValue) {
|
||||
this._cachedPanelsValue = this.getStoredCachedPanelsValue();
|
||||
}
|
||||
return this._cachedPanelsValue;
|
||||
}
|
||||
|
||||
private set cachedPanelsValue(cachedViewletsValue: string) {
|
||||
if (this.cachedPanelsValue !== cachedViewletsValue) {
|
||||
this._cachedPanelsValue = cachedViewletsValue;
|
||||
this.setStoredCachedViewletsValue(cachedViewletsValue);
|
||||
}
|
||||
}
|
||||
|
||||
private getStoredCachedPanelsValue(): string {
|
||||
return this.storageService.get(PanelPart.PINNED_PANELS, StorageScope.GLOBAL, '[]');
|
||||
}
|
||||
|
||||
private setStoredCachedViewletsValue(value: string): void {
|
||||
this.storageService.store(PanelPart.PINNED_PANELS, value, StorageScope.GLOBAL);
|
||||
}
|
||||
|
||||
toJSON(): object {
|
||||
return {
|
||||
type: Parts.PANEL_PART
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
@@ -333,9 +450,9 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const panelBackground = theme.getColor(PANEL_BACKGROUND);
|
||||
if (panelBackground && panelBackground !== theme.getColor(editorBackground)) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.panel > .content .monaco-editor,
|
||||
.monaco-workbench > .part.panel > .content .monaco-editor .margin,
|
||||
.monaco-workbench > .part.panel > .content .monaco-editor .monaco-editor-background {
|
||||
.monaco-workbench .part.panel > .content .monaco-editor,
|
||||
.monaco-workbench .part.panel > .content .monaco-editor .margin,
|
||||
.monaco-workbench .part.panel > .content .monaco-editor .monaco-editor-background {
|
||||
background-color: ${panelBackground};
|
||||
}
|
||||
`);
|
||||
@@ -346,7 +463,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const titleActiveBorder = theme.getColor(PANEL_ACTIVE_TITLE_BORDER);
|
||||
if (titleActive || titleActiveBorder) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:hover .action-label {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:hover .action-label {
|
||||
color: ${titleActive} !important;
|
||||
border-bottom-color: ${titleActiveBorder} !important;
|
||||
}
|
||||
@@ -357,14 +474,14 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const focusBorderColor = theme.getColor(focusBorder);
|
||||
if (focusBorderColor) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus .action-label {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus .action-label {
|
||||
color: ${titleActive} !important;
|
||||
border-bottom-color: ${focusBorderColor} !important;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
`);
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:focus {
|
||||
outline: none;
|
||||
}
|
||||
`);
|
||||
@@ -376,8 +493,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const outline = theme.getColor(activeContrastBorder);
|
||||
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label,
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label:hover {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item.checked .action-label,
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item .action-label:hover {
|
||||
outline-color: ${outline};
|
||||
outline-width: 1px;
|
||||
outline-style: solid;
|
||||
@@ -386,7 +503,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:not(.checked) .action-label:hover {
|
||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar .action-item:not(.checked) .action-label:hover {
|
||||
outline-style: dashed;
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -25,7 +25,7 @@ import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
||||
import { attachBadgeStyler, attachProgressBarStyler, attachButtonStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { debounceEvent, Emitter, Event } from 'vs/base/common/event';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
@@ -252,14 +252,20 @@ class QuickInput implements IQuickInput {
|
||||
this.ui.leftActionBar.clear();
|
||||
const leftButtons = this.buttons.filter(button => button === backButton);
|
||||
this.ui.leftActionBar.push(leftButtons.map((button, index) => {
|
||||
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => this.onDidTriggerButtonEmitter.fire(button));
|
||||
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => {
|
||||
this.onDidTriggerButtonEmitter.fire(button);
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
action.tooltip = button.tooltip;
|
||||
return action;
|
||||
}), { icon: true, label: false });
|
||||
this.ui.rightActionBar.clear();
|
||||
const rightButtons = this.buttons.filter(button => button !== backButton);
|
||||
this.ui.rightActionBar.push(rightButtons.map((button, index) => {
|
||||
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => this.onDidTriggerButtonEmitter.fire(button));
|
||||
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => {
|
||||
this.onDidTriggerButtonEmitter.fire(button);
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
action.tooltip = button.tooltip;
|
||||
return action;
|
||||
}), { icon: true, label: false });
|
||||
@@ -306,7 +312,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
private _placeholder;
|
||||
private onDidChangeValueEmitter = new Emitter<string>();
|
||||
private onDidAcceptEmitter = new Emitter<string>();
|
||||
private _items: (T | IQuickPickSeparator)[] = [];
|
||||
private _items: Array<T | IQuickPickSeparator> = [];
|
||||
private itemsUpdated = false;
|
||||
private _canSelectMany = false;
|
||||
private _matchOnDescription = false;
|
||||
@@ -360,7 +366,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
return this._items;
|
||||
}
|
||||
|
||||
set items(items: (T | IQuickPickSeparator)[]) {
|
||||
set items(items: Array<T | IQuickPickSeparator>) {
|
||||
this._items = items;
|
||||
this.itemsUpdated = true;
|
||||
this.update();
|
||||
@@ -482,7 +488,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
this._selectedItems = [this.activeItems[0]];
|
||||
this.onDidChangeSelectionEmitter.fire(this.selectedItems);
|
||||
}
|
||||
this.onDidAcceptEmitter.fire();
|
||||
this.onDidAcceptEmitter.fire(undefined);
|
||||
}),
|
||||
this.ui.list.onDidChangeFocus(focusedItems => {
|
||||
if (this.activeItemsUpdated) {
|
||||
@@ -507,7 +513,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
this._selectedItems = selectedItems as T[];
|
||||
this.onDidChangeSelectionEmitter.fire(selectedItems as T[]);
|
||||
if (selectedItems.length) {
|
||||
this.onDidAcceptEmitter.fire();
|
||||
this.onDidAcceptEmitter.fire(undefined);
|
||||
}
|
||||
}),
|
||||
this.ui.list.onChangedCheckedElements(checkedItems => {
|
||||
@@ -570,7 +576,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
if (wasTriggerKeyPressed && this.activeItems[0]) {
|
||||
this._selectedItems = [this.activeItems[0]];
|
||||
this.onDidChangeSelectionEmitter.fire(this.selectedItems);
|
||||
this.onDidAcceptEmitter.fire();
|
||||
this.onDidAcceptEmitter.fire(undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -723,7 +729,7 @@ class InputBox extends QuickInput implements IInputBox {
|
||||
this._value = value;
|
||||
this.onDidValueChangeEmitter.fire(value);
|
||||
}),
|
||||
this.ui.onDidAccept(() => this.onDidAcceptEmitter.fire()),
|
||||
this.ui.onDidAccept(() => this.onDidAcceptEmitter.fire(undefined)),
|
||||
);
|
||||
this.valueSelectionUpdated = true;
|
||||
}
|
||||
@@ -788,14 +794,14 @@ export class QuickInputService extends Component implements IQuickInputService {
|
||||
private controller: QuickInput;
|
||||
|
||||
constructor(
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IPartService private partService: IPartService,
|
||||
@IQuickOpenService private quickOpenService: IQuickOpenService,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IStorageService storageService: IStorageService
|
||||
) {
|
||||
@@ -1129,7 +1135,7 @@ export class QuickInputService extends Component implements IQuickInputService {
|
||||
}
|
||||
});
|
||||
input.show();
|
||||
Promise.resolve(picks).then(null, err => {
|
||||
Promise.resolve(picks).then(undefined, err => {
|
||||
reject(err);
|
||||
input.hide();
|
||||
});
|
||||
@@ -1143,8 +1149,8 @@ export class QuickInputService extends Component implements IQuickInputService {
|
||||
return;
|
||||
}
|
||||
const input = this.createInputBox();
|
||||
const validateInput = options.validateInput || (() => <Thenable<undefined>>Promise.resolve(undefined));
|
||||
const onDidValueChange = debounceEvent(input.onDidChangeValue, (last, cur) => cur, 100);
|
||||
const validateInput = options.validateInput || (() => <Promise<undefined>>Promise.resolve(undefined));
|
||||
const onDidValueChange = Event.debounce(input.onDidChangeValue, (last, cur) => cur, 100);
|
||||
let validationValue = options.value || '';
|
||||
let validation = Promise.resolve(validateInput(validationValue));
|
||||
const disposables = [
|
||||
@@ -1406,7 +1412,7 @@ export class BackAction extends Action {
|
||||
public static readonly ID = 'workbench.action.quickInputBack';
|
||||
public static readonly LABEL = localize('back', "Back");
|
||||
|
||||
constructor(id: string, label: string, @IQuickInputService private quickInputService: IQuickInputService) {
|
||||
constructor(id: string, label: string, @IQuickInputService private readonly quickInputService: IQuickInputService) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export class QuickInputBox {
|
||||
private parent: HTMLElement
|
||||
) {
|
||||
this.container = dom.append(this.parent, $('.quick-input-box'));
|
||||
this.inputBox = new InputBox(this.container, null);
|
||||
this.inputBox = new InputBox(this.container, undefined);
|
||||
this.disposables.push(this.inputBox);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export class QuickInputBox {
|
||||
}
|
||||
|
||||
get placeholder() {
|
||||
return this.inputBox.inputElement.getAttribute('placeholder');
|
||||
return this.inputBox.inputElement.getAttribute('placeholder') || '';
|
||||
}
|
||||
|
||||
set placeholder(placeholder: string) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import { IQuickPickItem, IQuickPickItemButtonEvent, IQuickPickSeparator } from '
|
||||
import { IMatch } from 'vs/base/common/filters';
|
||||
import { matchesFuzzyOcticonAware, parseOcticons } from 'vs/base/common/octicon';
|
||||
import { compareAnything } from 'vs/base/common/comparers';
|
||||
import { Emitter, Event, mapEvent } from 'vs/base/common/event';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
@@ -32,14 +32,14 @@ import { IListOptions } from 'vs/base/browser/ui/list/listWidget';
|
||||
const $ = dom.$;
|
||||
|
||||
interface IListElement {
|
||||
index: number;
|
||||
item: IQuickPickItem;
|
||||
saneLabel: string;
|
||||
saneDescription?: string;
|
||||
saneDetail?: string;
|
||||
checked: boolean;
|
||||
separator: IQuickPickSeparator;
|
||||
fireButtonTriggered: (event: IQuickPickItemButtonEvent<IQuickPickItem>) => void;
|
||||
readonly index: number;
|
||||
readonly item: IQuickPickItem;
|
||||
readonly saneLabel: string;
|
||||
readonly saneDescription?: string;
|
||||
readonly saneDetail?: string;
|
||||
readonly checked: boolean;
|
||||
readonly separator?: IQuickPickSeparator;
|
||||
readonly fireButtonTriggered: (event: IQuickPickItemButtonEvent<IQuickPickItem>) => void;
|
||||
}
|
||||
|
||||
class ListElement implements IListElement {
|
||||
@@ -53,7 +53,7 @@ class ListElement implements IListElement {
|
||||
onChecked = this._onChecked.event;
|
||||
_checked?: boolean;
|
||||
get checked() {
|
||||
return this._checked;
|
||||
return !!this._checked;
|
||||
}
|
||||
set checked(value: boolean) {
|
||||
if (value !== this._checked) {
|
||||
@@ -61,7 +61,7 @@ class ListElement implements IListElement {
|
||||
this._onChecked.fire(value);
|
||||
}
|
||||
}
|
||||
separator: IQuickPickSeparator;
|
||||
separator?: IQuickPickSeparator;
|
||||
labelHighlights?: IMatch[];
|
||||
descriptionHighlights?: IMatch[];
|
||||
detailHighlights?: IMatch[];
|
||||
@@ -144,7 +144,7 @@ class ListElementRenderer implements IListRenderer<ListElement, IListElementTemp
|
||||
options.descriptionTitle = element.saneDescription;
|
||||
options.descriptionMatches = descriptionHighlights || [];
|
||||
options.extraClasses = element.item.iconClasses;
|
||||
data.label.setValue(element.saneLabel, element.saneDescription, options);
|
||||
data.label.setLabel(element.saneLabel, element.saneDescription, options);
|
||||
|
||||
// Meta
|
||||
data.detail.set(element.saneDetail, detailHighlights);
|
||||
@@ -173,14 +173,14 @@ class ListElementRenderer implements IListRenderer<ListElement, IListElementTemp
|
||||
const buttons = element.item.buttons;
|
||||
if (buttons && buttons.length) {
|
||||
data.actionBar.push(buttons.map((button, index) => {
|
||||
const action = new Action(`id-${index}`, '', button.iconClass || getIconClass(button.iconPath), true, () => {
|
||||
const action = new Action(`id-${index}`, '', button.iconClass || (button.iconPath ? getIconClass(button.iconPath) : undefined), true, () => {
|
||||
element.fireButtonTriggered({
|
||||
button,
|
||||
item: element.item
|
||||
});
|
||||
return null;
|
||||
return Promise.resolve();
|
||||
});
|
||||
action.tooltip = button.tooltip;
|
||||
action.tooltip = button.tooltip || '';
|
||||
return action;
|
||||
}), { icon: true, label: false });
|
||||
dom.addClass(data.entry, 'has-actions');
|
||||
@@ -215,7 +215,7 @@ export class QuickInputList {
|
||||
readonly id: string;
|
||||
private container: HTMLElement;
|
||||
private list: WorkbenchList<ListElement>;
|
||||
private inputElements: (IQuickPickItem | IQuickPickSeparator)[];
|
||||
private inputElements: Array<IQuickPickItem | IQuickPickSeparator>;
|
||||
private elements: ListElement[] = [];
|
||||
private elementsToIndexes = new Map<IQuickPickItem, number>();
|
||||
matchOnDescription = false;
|
||||
@@ -239,7 +239,7 @@ export class QuickInputList {
|
||||
constructor(
|
||||
private parent: HTMLElement,
|
||||
id: string,
|
||||
@IInstantiationService private instantiationService: IInstantiationService
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
this.id = id;
|
||||
this.container = dom.append(this.parent, $('.quick-input-list'));
|
||||
@@ -248,7 +248,8 @@ export class QuickInputList {
|
||||
identityProvider: { getId: element => element.saneLabel },
|
||||
openController: { shouldOpen: () => false }, // Workaround #58124
|
||||
setRowLineHeight: false,
|
||||
multipleSelectionSupport: false
|
||||
multipleSelectionSupport: false,
|
||||
horizontalScrolling: false
|
||||
} as IListOptions<ListElement>) as WorkbenchList<ListElement>;
|
||||
this.list.getHTMLElement().id = id;
|
||||
this.disposables.push(this.list);
|
||||
@@ -294,12 +295,12 @@ export class QuickInputList {
|
||||
|
||||
@memoize
|
||||
get onDidChangeFocus() {
|
||||
return mapEvent(this.list.onFocusChange, e => e.elements.map(e => e.item));
|
||||
return Event.map(this.list.onFocusChange, e => e.elements.map(e => e.item));
|
||||
}
|
||||
|
||||
@memoize
|
||||
get onDidChangeSelection() {
|
||||
return mapEvent(this.list.onSelectionChange, e => e.elements.map(e => e.item));
|
||||
return Event.map(this.list.onSelectionChange, e => e.elements.map(e => e.item));
|
||||
}
|
||||
|
||||
getAllVisibleChecked() {
|
||||
@@ -356,7 +357,7 @@ export class QuickInputList {
|
||||
}
|
||||
}
|
||||
|
||||
setElements(inputElements: (IQuickPickItem | IQuickPickSeparator)[]): void {
|
||||
setElements(inputElements: Array<IQuickPickItem | IQuickPickSeparator>): void {
|
||||
this.elementDisposables = dispose(this.elementDisposables);
|
||||
const fireButtonTriggered = (event: IQuickPickItemButtonEvent<IQuickPickItem>) => this.fireButtonTriggered(event);
|
||||
this.inputElements = inputElements;
|
||||
@@ -395,7 +396,7 @@ export class QuickInputList {
|
||||
setFocusedElements(items: IQuickPickItem[]) {
|
||||
this.list.setFocus(items
|
||||
.filter(item => this.elementsToIndexes.has(item))
|
||||
.map(item => this.elementsToIndexes.get(item)));
|
||||
.map(item => this.elementsToIndexes.get(item)!));
|
||||
}
|
||||
|
||||
getActiveDescendant() {
|
||||
@@ -410,7 +411,7 @@ export class QuickInputList {
|
||||
setSelectedElements(items: IQuickPickItem[]) {
|
||||
this.list.setSelection(items
|
||||
.filter(item => this.elementsToIndexes.has(item))
|
||||
.map(item => this.elementsToIndexes.get(item)));
|
||||
.map(item => this.elementsToIndexes.get(item)!));
|
||||
}
|
||||
|
||||
getCheckedElements() {
|
||||
@@ -484,9 +485,9 @@ export class QuickInputList {
|
||||
// Filter by value (since we support octicons, use octicon aware fuzzy matching)
|
||||
else {
|
||||
this.elements.forEach(element => {
|
||||
const labelHighlights = matchesFuzzyOcticonAware(query, parseOcticons(element.saneLabel));
|
||||
const descriptionHighlights = this.matchOnDescription ? matchesFuzzyOcticonAware(query, parseOcticons(element.saneDescription || '')) : undefined;
|
||||
const detailHighlights = this.matchOnDetail ? matchesFuzzyOcticonAware(query, parseOcticons(element.saneDetail || '')) : undefined;
|
||||
const labelHighlights = matchesFuzzyOcticonAware(query, parseOcticons(element.saneLabel)) || undefined;
|
||||
const descriptionHighlights = this.matchOnDescription ? matchesFuzzyOcticonAware(query, parseOcticons(element.saneDescription || '')) || undefined : undefined;
|
||||
const detailHighlights = this.matchOnDetail ? matchesFuzzyOcticonAware(query, parseOcticons(element.saneDetail || '')) || undefined : undefined;
|
||||
|
||||
if (labelHighlights || descriptionHighlights || detailHighlights) {
|
||||
element.labelHighlights = labelHighlights;
|
||||
|
||||
@@ -53,7 +53,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
|
||||
const HELP_PREFIX = '?';
|
||||
|
||||
type ValueCallback<T = any> = (value: T | Thenable<T>) => void;
|
||||
type ValueCallback<T = any> = (value: T | Promise<T>) => void;
|
||||
|
||||
export class QuickOpenController extends Component implements IQuickOpenService {
|
||||
|
||||
@@ -86,13 +86,13 @@ export class QuickOpenController extends Component implements IQuickOpenService
|
||||
private pendingGetResultsInvocation: CancellationTokenSource;
|
||||
|
||||
constructor(
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IPartService private partService: IPartService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IStorageService storageService: IStorageService
|
||||
) {
|
||||
@@ -155,9 +155,9 @@ export class QuickOpenController extends Component implements IQuickOpenService
|
||||
}
|
||||
|
||||
show(prefix?: string, options?: IShowOptions): Promise<void> {
|
||||
let quickNavigateConfiguration = options ? options.quickNavigateConfiguration : void 0;
|
||||
let inputSelection = options ? options.inputSelection : void 0;
|
||||
let autoFocus = options ? options.autoFocus : void 0;
|
||||
let quickNavigateConfiguration = options ? options.quickNavigateConfiguration : undefined;
|
||||
let inputSelection = options ? options.inputSelection : undefined;
|
||||
let autoFocus = options ? options.autoFocus : undefined;
|
||||
|
||||
const promiseCompletedOnHide = new Promise<void>(c => {
|
||||
this.promisesToCompleteOnHide.push(c);
|
||||
@@ -452,11 +452,11 @@ export class QuickOpenController extends Component implements IQuickOpenService
|
||||
const previousInput = this.quickOpenWidget.getInput();
|
||||
const wasShowingHistory = previousInput && previousInput.entries && previousInput.entries.some(e => e instanceof EditorHistoryEntry || e instanceof EditorHistoryEntryGroup);
|
||||
if (wasShowingHistory || matchingHistoryEntries.length > 0) {
|
||||
let responseDelay: Thenable<void>;
|
||||
let responseDelay: Promise<void>;
|
||||
if (resolvedHandler.hasShortResponseTime()) {
|
||||
responseDelay = timeout(QuickOpenController.MAX_SHORT_RESPONSE_TIME);
|
||||
} else {
|
||||
responseDelay = Promise.resolve(void 0);
|
||||
responseDelay = Promise.resolve();
|
||||
}
|
||||
|
||||
responseDelay.then(() => {
|
||||
@@ -490,8 +490,7 @@ export class QuickOpenController extends Component implements IQuickOpenService
|
||||
// Remove results already showing by checking for a "resource" property
|
||||
const mapEntryToResource = this.mapEntriesToResource(quickOpenModel);
|
||||
const additionalHandlerResults: QuickOpenEntry[] = [];
|
||||
for (let i = 0; i < handlerResults.length; i++) {
|
||||
const result = handlerResults[i];
|
||||
for (const result of handlerResults) {
|
||||
const resource = result.getResource();
|
||||
|
||||
if (!result.mergeWithEditorHistory() || !resource || !mapEntryToResource[resource.toString()]) {
|
||||
@@ -529,7 +528,7 @@ export class QuickOpenController extends Component implements IQuickOpenService
|
||||
const model = new QuickOpenModel([new PlaceholderQuickOpenEntry(placeHolderLabel)], this.actionProvider);
|
||||
this.showModel(model, resolvedHandler.getAutoFocus(value, { model, quickNavigateConfiguration: this.quickOpenWidget.getQuickNavigateConfiguration() }), resolvedHandler.getAriaLabel());
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
// Support extra class from handler
|
||||
@@ -646,9 +645,9 @@ class EditorHistoryHandler {
|
||||
private scorerCache: ScorerCache;
|
||||
|
||||
constructor(
|
||||
@IHistoryService private historyService: IHistoryService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IFileService private fileService: IFileService
|
||||
@IHistoryService private readonly historyService: IHistoryService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IFileService private readonly fileService: IFileService
|
||||
) {
|
||||
this.scorerCache = Object.create(null);
|
||||
}
|
||||
@@ -709,7 +708,7 @@ class EditorHistoryItemAccessorClass extends QuickOpenItemAccessorClass {
|
||||
}
|
||||
|
||||
getItemDescription(entry: QuickOpenEntry): string {
|
||||
return this.allowMatchOnDescription ? entry.getDescription() : void 0;
|
||||
return this.allowMatchOnDescription ? entry.getDescription() : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,10 +729,10 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry {
|
||||
constructor(
|
||||
input: IEditorInput | IResourceInput,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IModelService private modelService: IModelService,
|
||||
@ITextFileService private textFileService: ITextFileService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@ILabelService labelService: ILabelService,
|
||||
@IFileService fileService: IFileService
|
||||
) {
|
||||
@@ -808,7 +807,7 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry {
|
||||
}
|
||||
|
||||
function resourceForEditorHistory(input: EditorInput, fileService: IFileService): URI {
|
||||
const resource = input ? input.getResource() : void 0;
|
||||
const resource = input ? input.getResource() : undefined;
|
||||
|
||||
// For the editor history we only prefer resources that are either untitled or
|
||||
// can be handled by the file service which indicates they are editable resources.
|
||||
@@ -816,7 +815,7 @@ function resourceForEditorHistory(input: EditorInput, fileService: IFileService)
|
||||
return resource;
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export class RemoveFromEditorHistoryAction extends Action {
|
||||
@@ -827,16 +826,16 @@ export class RemoveFromEditorHistoryAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService private quickInputService: IQuickInputService,
|
||||
@IModelService private modelService: IModelService,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IHistoryService private historyService: IHistoryService
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IHistoryService private readonly historyService: IHistoryService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
interface IHistoryPickEntry extends IQuickPickItem {
|
||||
input: IEditorInput | IResourceInput;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ CommandsRegistry.registerCommand(QUICKOPEN_ACTION_ID, function (accessor: Servic
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
|
||||
return quickOpenService.show(typeof prefix === 'string' ? prefix : undefined).then(() => {
|
||||
return void 0;
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ CommandsRegistry.registerCommand(QUICKOPEN_FOCUS_SECONDARY_ACTION_ID, function (
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
|
||||
return quickOpenService.show(undefined, { autoFocus: { autoFocusSecondEntry: true } }).then(() => {
|
||||
return void 0;
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,16 +43,16 @@ export class BaseQuickOpenNavigateAction extends Action {
|
||||
label: string,
|
||||
private next: boolean,
|
||||
private quickNavigate: boolean,
|
||||
@IQuickOpenService private quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService private quickInputService: IQuickInputService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(event?: any): Thenable<any> {
|
||||
run(event?: any): Promise<any> {
|
||||
const keys = this.keybindingService.lookupKeybindings(this.id);
|
||||
const quickNavigate = this.quickNavigate ? { keybindings: keys } : void 0;
|
||||
const quickNavigate = this.quickNavigate ? { keybindings: keys } : undefined;
|
||||
|
||||
this.quickOpenService.navigate(this.next, quickNavigate);
|
||||
this.quickInputService.navigate(this.next, quickNavigate);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench > .sidebar > .content {
|
||||
.monaco-workbench .sidebar > .content {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
.monaco-workbench > .sidebar > .title > .title-label h2 {
|
||||
.monaco-workbench .sidebar > .title > .title-label h2 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { CompositePart } from 'vs/workbench/browser/parts/compositePart';
|
||||
import { Viewlet, ViewletRegistry, Extensions as ViewletExtensions } from 'vs/workbench/browser/viewlet';
|
||||
import { Viewlet, ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
|
||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
@@ -20,25 +20,43 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Event, mapEvent } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { SIDE_BAR_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND, SIDE_BAR_BORDER } from 'vs/workbench/common/theme';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { Dimension, EventType, addDisposableListener, trackFocus } from 'vs/base/browser/dom';
|
||||
import { EventType, addDisposableListener, trackFocus, Dimension } from 'vs/base/browser/dom';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
|
||||
import { LayoutPriority } from 'vs/base/browser/ui/grid/gridview';
|
||||
|
||||
const SideBarFocusContextId = 'sideBarFocus';
|
||||
export const SidebarFocusContext = new RawContextKey<boolean>(SideBarFocusContextId, false);
|
||||
export const SidebarFocusContext = new RawContextKey<boolean>('sideBarFocus', false);
|
||||
export const ActiveViewletContext = new RawContextKey<string>('activeViewlet', '');
|
||||
|
||||
export class SidebarPart extends CompositePart<Viewlet> {
|
||||
export class SidebarPart extends CompositePart<Viewlet> implements ISerializableView, IViewletService {
|
||||
_serviceBrand: any;
|
||||
|
||||
static readonly activeViewletSettingsKey = 'workbench.sidebar.activeviewletid';
|
||||
|
||||
private viewletRegistry: ViewletRegistry;
|
||||
private sideBarFocusContextKey: IContextKey<boolean>;
|
||||
private activeViewletContextKey: IContextKey<string>;
|
||||
private blockOpeningViewlet: boolean;
|
||||
private _onDidViewletDeregister = this._register(new Emitter<ViewletDescriptor>());
|
||||
|
||||
element: HTMLElement;
|
||||
minimumWidth: number = 170;
|
||||
maximumWidth: number = Number.POSITIVE_INFINITY;
|
||||
minimumHeight: number = 0;
|
||||
maximumHeight: number = Number.POSITIVE_INFINITY;
|
||||
snapSize: number = 50;
|
||||
priority: LayoutPriority = LayoutPriority.Low;
|
||||
|
||||
private _onDidChange = new Emitter<{ width: number; height: number; }>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -51,6 +69,7 @@ export class SidebarPart extends CompositePart<Viewlet> {
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService
|
||||
) {
|
||||
super(
|
||||
notificationService,
|
||||
@@ -72,10 +91,32 @@ export class SidebarPart extends CompositePart<Viewlet> {
|
||||
);
|
||||
|
||||
this.sideBarFocusContextKey = SidebarFocusContext.bindTo(contextKeyService);
|
||||
this.viewletRegistry = Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets);
|
||||
|
||||
this.activeViewletContextKey = ActiveViewletContext.bindTo(contextKeyService);
|
||||
|
||||
this._register(this.onDidViewletOpen(viewlet => {
|
||||
this.activeViewletContextKey.set(viewlet.getId());
|
||||
}));
|
||||
this._register(this.onDidViewletClose(viewlet => {
|
||||
if (this.activeViewletContextKey.get() === viewlet.getId()) {
|
||||
this.activeViewletContextKey.reset();
|
||||
}
|
||||
}));
|
||||
this._register(this.registry.onDidDeregister(async (viewletDescriptor: ViewletDescriptor) => {
|
||||
if (this.getActiveViewlet().getId() === viewletDescriptor.id) {
|
||||
await this.openViewlet(this.getDefaultViewletId());
|
||||
}
|
||||
this.removeComposite(viewletDescriptor.id);
|
||||
this._onDidViewletDeregister.fire(viewletDescriptor);
|
||||
}));
|
||||
}
|
||||
|
||||
get onDidViewletRegister(): Event<ViewletDescriptor> { return <Event<ViewletDescriptor>>this.viewletRegistry.onDidRegister; }
|
||||
get onDidViewletDeregister(): Event<ViewletDescriptor> { return this._onDidViewletDeregister.event; }
|
||||
|
||||
get onDidViewletOpen(): Event<IViewlet> {
|
||||
return mapEvent(this._onDidCompositeOpen.event, compositeEvent => <IViewlet>compositeEvent.composite);
|
||||
return Event.map(this._onDidCompositeOpen.event, compositeEvent => <IViewlet>compositeEvent.composite);
|
||||
}
|
||||
|
||||
get onDidViewletClose(): Event<IViewlet> {
|
||||
@@ -83,6 +124,8 @@ export class SidebarPart extends CompositePart<Viewlet> {
|
||||
}
|
||||
|
||||
create(parent: HTMLElement): void {
|
||||
this.element = parent;
|
||||
|
||||
super.create(parent);
|
||||
|
||||
const focusTracker = trackFocus(parent);
|
||||
@@ -124,7 +167,65 @@ export class SidebarPart extends CompositePart<Viewlet> {
|
||||
container.style.borderLeftColor = !isPositionLeft ? borderColor : null;
|
||||
}
|
||||
|
||||
openViewlet(id: string, focus?: boolean): Viewlet {
|
||||
layout(dimension: Dimension): Dimension[];
|
||||
layout(width: number, height: number): void;
|
||||
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
|
||||
if (!this.partService.isVisible(Parts.SIDEBAR_PART)) {
|
||||
if (dim1 instanceof Dimension) {
|
||||
return [dim1];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (dim1 instanceof Dimension) {
|
||||
return super.layout(dim1);
|
||||
}
|
||||
|
||||
super.layout(dim1, dim2!);
|
||||
}
|
||||
|
||||
// Viewlet service
|
||||
|
||||
getActiveViewlet(): IViewlet {
|
||||
return <IViewlet>this.getActiveComposite();
|
||||
}
|
||||
|
||||
getLastActiveViewletId(): string {
|
||||
return this.getLastActiveCompositetId();
|
||||
}
|
||||
|
||||
hideActiveViewlet(): void {
|
||||
this.hideActiveComposite();
|
||||
}
|
||||
|
||||
openViewlet(id: string, focus?: boolean): Promise<IViewlet | null> {
|
||||
if (this.getViewlet(id)) {
|
||||
return Promise.resolve(this.doOpenViewlet(id, focus));
|
||||
}
|
||||
return this.extensionService.whenInstalledExtensionsRegistered()
|
||||
.then(() => {
|
||||
if (this.getViewlet(id)) {
|
||||
return this.doOpenViewlet(id, focus);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
getViewlets(): ViewletDescriptor[] {
|
||||
return this.viewletRegistry.getViewlets()
|
||||
.sort((v1, v2) => v1.order! - v2.order!);
|
||||
}
|
||||
|
||||
getDefaultViewletId(): string {
|
||||
return this.viewletRegistry.getDefaultViewletId();
|
||||
}
|
||||
|
||||
getViewlet(id: string): ViewletDescriptor {
|
||||
return this.getViewlets().filter(viewlet => viewlet.id === id)[0];
|
||||
}
|
||||
|
||||
private doOpenViewlet(id: string, focus?: boolean): Viewlet | null {
|
||||
if (this.blockOpeningViewlet) {
|
||||
return null; // Workaround against a potential race condition
|
||||
}
|
||||
@@ -142,26 +243,6 @@ export class SidebarPart extends CompositePart<Viewlet> {
|
||||
return this.openComposite(id, focus) as Viewlet;
|
||||
}
|
||||
|
||||
getActiveViewlet(): IViewlet {
|
||||
return <IViewlet>this.getActiveComposite();
|
||||
}
|
||||
|
||||
getLastActiveViewletId(): string {
|
||||
return this.getLastActiveCompositetId();
|
||||
}
|
||||
|
||||
hideActiveViewlet(): void {
|
||||
this.hideActiveComposite();
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): Dimension[] {
|
||||
if (!this.partService.isVisible(Parts.SIDEBAR_PART)) {
|
||||
return [dimension];
|
||||
}
|
||||
|
||||
return super.layout(dimension);
|
||||
}
|
||||
|
||||
protected getTitleAreaDropDownAnchorAlignment(): AnchorAlignment {
|
||||
return this.partService.getSideBarPosition() === SideBarPosition.LEFT ? AnchorAlignment.LEFT : AnchorAlignment.RIGHT;
|
||||
}
|
||||
@@ -181,6 +262,12 @@ export class SidebarPart extends CompositePart<Viewlet> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(): object {
|
||||
return {
|
||||
type: Parts.SIDEBAR_PART
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class FocusSideBarAction extends Action {
|
||||
@@ -191,13 +278,13 @@ class FocusSideBarAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IViewletService private viewletService: IViewletService,
|
||||
@IPartService private partService: IPartService
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
|
||||
// Show side bar
|
||||
if (!this.partService.isVisible(Parts.SIDEBAR_PART)) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench > .part.statusbar {
|
||||
.monaco-workbench .part.statusbar {
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
width: 100%;
|
||||
@@ -11,18 +11,18 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item {
|
||||
display: inline-block;
|
||||
line-height: 22px;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item.has-beak {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item.has-beak {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item.has-beak:before {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item.has-beak:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 11px;
|
||||
@@ -33,48 +33,48 @@
|
||||
border-right: 5px solid transparent;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item.left > :first-child {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item.left > :first-child {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item.right {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item.right > :first-child {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item.right > :first-child {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
/* adding padding to the most left status bar item */
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item.left:first-child, .monaco-workbench > .part.statusbar > .statusbar-item.right + .statusbar-item.left {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item.left:first-child, .monaco-workbench .part.statusbar > .statusbar-item.right + .statusbar-item.left {
|
||||
padding-left: 10px;
|
||||
}
|
||||
/* adding padding to the most right status bar item */
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item.right:first-child {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item.right:first-child {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item a {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item a {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-entry > span {
|
||||
.monaco-workbench .part.statusbar > .statusbar-entry > span {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-entry > span,
|
||||
.monaco-workbench > .part.statusbar > .statusbar-entry > a {
|
||||
.monaco-workbench .part.statusbar > .statusbar-entry > span,
|
||||
.monaco-workbench .part.statusbar > .statusbar-entry > a {
|
||||
padding: 0 5px 0 5px;
|
||||
white-space: pre; /* gives some degree of styling */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-entry span.octicon {
|
||||
.monaco-workbench .part.statusbar > .statusbar-entry span.octicon {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.statusbar > .statusbar-item a:hover {
|
||||
.monaco-workbench .part.statusbar > .statusbar-item a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
@@ -24,27 +24,39 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/
|
||||
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { isThemeColor } from 'vs/editor/common/editorCommon';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { addClass, EventHelper, createStyleSheet, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { addClass, EventHelper, createStyleSheet, addDisposableListener, Dimension } from 'vs/base/browser/dom';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
|
||||
import { Parts } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
export class StatusbarPart extends Part implements IStatusbarService {
|
||||
|
||||
export class StatusbarPart extends Part implements IStatusbarService, ISerializableView {
|
||||
_serviceBrand: any;
|
||||
|
||||
private static readonly PRIORITY_PROP = 'statusbar-entry-priority';
|
||||
private static readonly ALIGNMENT_PROP = 'statusbar-entry-alignment';
|
||||
|
||||
private statusItemsContainer: HTMLElement;
|
||||
element: HTMLElement;
|
||||
private statusMsgDispose: IDisposable;
|
||||
|
||||
|
||||
minimumWidth: number = 0;
|
||||
maximumWidth: number = Number.POSITIVE_INFINITY;
|
||||
minimumHeight: number = 22;
|
||||
maximumHeight: number = 22;
|
||||
|
||||
private _onDidChange = new Emitter<{ width: number; height: number; }>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
private styleElement: HTMLStyleElement;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IStorageService storageService: IStorageService
|
||||
) {
|
||||
super(id, { hasTitle: false }, themeService, storageService);
|
||||
@@ -59,16 +71,15 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
addEntry(entry: IStatusbarEntry, alignment: StatusbarAlignment, priority: number = 0): IDisposable {
|
||||
|
||||
// Render entry in status bar
|
||||
const el = this.doCreateStatusItem(alignment, priority, entry.showBeak ? 'has-beak' : void 0);
|
||||
const el = this.doCreateStatusItem(alignment, priority, entry.showBeak ? 'has-beak' : undefined);
|
||||
const item = this.instantiationService.createInstance(StatusBarEntryItem, entry);
|
||||
const toDispose = item.render(el);
|
||||
|
||||
// Insert according to priority
|
||||
const container = this.statusItemsContainer;
|
||||
const container = this.element;
|
||||
const neighbours = this.getEntries(alignment);
|
||||
let inserted = false;
|
||||
for (let i = 0; i < neighbours.length; i++) {
|
||||
const neighbour = neighbours[i];
|
||||
for (const neighbour of neighbours) {
|
||||
const nPriority = Number(neighbour.getAttribute(StatusbarPart.PRIORITY_PROP));
|
||||
if (
|
||||
alignment === StatusbarAlignment.LEFT && nPriority < priority ||
|
||||
@@ -96,7 +107,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
private getEntries(alignment: StatusbarAlignment): HTMLElement[] {
|
||||
const entries: HTMLElement[] = [];
|
||||
|
||||
const container = this.statusItemsContainer;
|
||||
const container = this.element;
|
||||
const children = container.children;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const childElement = <HTMLElement>children.item(i);
|
||||
@@ -109,7 +120,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
}
|
||||
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
this.statusItemsContainer = parent;
|
||||
this.element = parent;
|
||||
|
||||
// Fill in initial items that were contributed from the registry
|
||||
const registry = Registry.as<IStatusbarRegistry>(Extensions.Statusbar);
|
||||
@@ -135,10 +146,10 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
const el = this.doCreateStatusItem(descriptor.alignment, descriptor.priority);
|
||||
|
||||
this._register(item.render(el));
|
||||
this.statusItemsContainer.appendChild(el);
|
||||
this.element.appendChild(el);
|
||||
}
|
||||
|
||||
return this.statusItemsContainer;
|
||||
return this.element;
|
||||
}
|
||||
|
||||
protected updateStyles(): void {
|
||||
@@ -162,7 +173,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
this.styleElement = createStyleSheet(container);
|
||||
}
|
||||
|
||||
this.styleElement.innerHTML = `.monaco-workbench > .part.statusbar > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`;
|
||||
this.styleElement.innerHTML = `.monaco-workbench .part.statusbar > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`;
|
||||
}
|
||||
|
||||
private doCreateStatusItem(alignment: StatusbarAlignment, priority: number = 0, extraClass?: string): HTMLElement {
|
||||
@@ -191,7 +202,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
|
||||
// Create new
|
||||
let statusDispose: IDisposable;
|
||||
let showHandle = setTimeout(() => {
|
||||
let showHandle: any = setTimeout(() => {
|
||||
statusDispose = this.addEntry({ text: message }, StatusbarAlignment.LEFT, -Number.MAX_VALUE /* far right on left hand side */);
|
||||
showHandle = null;
|
||||
}, delayBy);
|
||||
@@ -221,6 +232,22 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
|
||||
return dispose;
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): Dimension[];
|
||||
layout(width: number, height: number): void;
|
||||
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
|
||||
if (dim1 instanceof Dimension) {
|
||||
return super.layout(dim1);
|
||||
} else {
|
||||
super.layout(new Dimension(dim1, dim2!));
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(): object {
|
||||
return {
|
||||
type: Parts.STATUSBAR_PART
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let manageExtensionAction: ManageExtensionAction;
|
||||
@@ -228,13 +255,13 @@ class StatusBarEntryItem implements IStatusbarItem {
|
||||
|
||||
constructor(
|
||||
private entry: IStatusbarEntry,
|
||||
@ICommandService private commandService: ICommandService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IThemeService private themeService: IThemeService
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IThemeService private readonly themeService: IThemeService
|
||||
) {
|
||||
this.entry = entry;
|
||||
|
||||
@@ -252,7 +279,7 @@ class StatusBarEntryItem implements IStatusbarItem {
|
||||
if (this.entry.command) {
|
||||
textContainer = document.createElement('a');
|
||||
|
||||
toDispose.push(addDisposableListener(textContainer, 'click', () => this.executeCommand(this.entry.command, this.entry.arguments)));
|
||||
toDispose.push(addDisposableListener(textContainer, 'click', () => this.executeCommand(this.entry.command!, this.entry.arguments)));
|
||||
} else {
|
||||
textContainer = document.createElement('span');
|
||||
}
|
||||
@@ -286,7 +313,7 @@ class StatusBarEntryItem implements IStatusbarItem {
|
||||
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => el,
|
||||
getActionsContext: () => this.entry.extensionId,
|
||||
getActionsContext: () => this.entry.extensionId!.value,
|
||||
getActions: () => [manageExtensionAction]
|
||||
});
|
||||
}));
|
||||
@@ -324,12 +351,12 @@ class StatusBarEntryItem implements IStatusbarItem {
|
||||
class ManageExtensionAction extends Action {
|
||||
|
||||
constructor(
|
||||
@ICommandService private commandService: ICommandService
|
||||
@ICommandService private readonly commandService: ICommandService
|
||||
) {
|
||||
super('statusbar.manage.extension', nls.localize('manageExtension', "Manage Extension"));
|
||||
}
|
||||
|
||||
run(extensionId: string): Thenable<any> {
|
||||
run(extensionId: string): Promise<any> {
|
||||
return this.commandService.executeCommand('_extensions.manage', extensionId);
|
||||
}
|
||||
}
|
||||
@@ -337,21 +364,21 @@ class ManageExtensionAction extends Action {
|
||||
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND);
|
||||
if (statusBarItemHoverBackground) {
|
||||
collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`);
|
||||
collector.addRule(`.monaco-workbench .part.statusbar > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`);
|
||||
}
|
||||
|
||||
const statusBarItemActiveBackground = theme.getColor(STATUS_BAR_ITEM_ACTIVE_BACKGROUND);
|
||||
if (statusBarItemActiveBackground) {
|
||||
collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a:active { background-color: ${statusBarItemActiveBackground}; }`);
|
||||
collector.addRule(`.monaco-workbench .part.statusbar > .statusbar-item a:active { background-color: ${statusBarItemActiveBackground}; }`);
|
||||
}
|
||||
|
||||
const statusBarProminentItemBackground = theme.getColor(STATUS_BAR_PROMINENT_ITEM_BACKGROUND);
|
||||
if (statusBarProminentItemBackground) {
|
||||
collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item .status-bar-info { background-color: ${statusBarProminentItemBackground}; }`);
|
||||
collector.addRule(`.monaco-workbench .part.statusbar > .statusbar-item .status-bar-info { background-color: ${statusBarProminentItemBackground}; }`);
|
||||
}
|
||||
|
||||
const statusBarProminentItemHoverBackground = theme.getColor(STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND);
|
||||
if (statusBarProminentItemHoverBackground) {
|
||||
collector.addRule(`.monaco-workbench > .part.statusbar > .statusbar-item a.status-bar-info:hover { background-color: ${statusBarProminentItemHoverBackground}; }`);
|
||||
collector.addRule(`.monaco-workbench .part.statusbar > .statusbar-item a.status-bar-info:hover { background-color: ${statusBarProminentItemHoverBackground}; }`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench > .part.titlebar {
|
||||
.monaco-workbench .part.titlebar {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 0 70px;
|
||||
@@ -18,7 +18,7 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .titlebar-drag-region {
|
||||
.monaco-workbench .part.titlebar > .titlebar-drag-region {
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
@@ -29,7 +29,7 @@
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-title {
|
||||
.monaco-workbench .part.titlebar > .window-title {
|
||||
flex: 0 1 auto;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
@@ -42,8 +42,8 @@
|
||||
|
||||
/* Windows/Linux: Rules for custom title (icon, window controls) */
|
||||
|
||||
.monaco-workbench.windows > .part.titlebar,
|
||||
.monaco-workbench.linux > .part.titlebar {
|
||||
.windows > .monaco-workbench .part.titlebar,
|
||||
.linux > .monaco-workbench .part.titlebar {
|
||||
padding: 0;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
@@ -51,17 +51,17 @@
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows > .part.titlebar > .window-title,
|
||||
.monaco-workbench.linux > .part.titlebar > .window-title {
|
||||
.windows > .monaco-workbench .part.titlebar > .window-title,
|
||||
.linux > .monaco-workbench .part.titlebar > .window-title {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.monaco-workbench.linux > .part.titlebar > .window-title {
|
||||
.linux > .monaco-workbench .part.titlebar > .window-title {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows > .part.titlebar > .resizer,
|
||||
.monaco-workbench.linux > .part.titlebar > .resizer {
|
||||
.windows > .monaco-workbench .part.titlebar > .resizer,
|
||||
.linux > .monaco-workbench .part.titlebar > .resizer {
|
||||
-webkit-app-region: no-drag;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -69,13 +69,13 @@
|
||||
height: 20%;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows.fullscreen > .part.titlebar > .resizer,
|
||||
.monaco-workbench.linux.fullscreen > .part.titlebar > .resizer {
|
||||
.windows > .monaco-workbench.fullscreen .part.titlebar > .resizer,
|
||||
.linux > .monaco-workbench.fullscreen .part.titlebar > .resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-appicon {
|
||||
.monaco-workbench .part.titlebar > .window-appicon {
|
||||
width: 35px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
@@ -87,11 +87,11 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench.fullscreen > .part.titlebar > .window-appicon {
|
||||
.monaco-workbench.fullscreen .part.titlebar > .window-appicon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container {
|
||||
display: flex;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
@@ -104,56 +104,56 @@
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.monaco-workbench.fullscreen > .part.titlebar > .window-controls-container {
|
||||
.monaco-workbench.fullscreen .part.titlebar > .window-controls-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container > .window-icon-bg {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg {
|
||||
display: inline-block;
|
||||
-webkit-app-region: no-drag;
|
||||
height: 100%;
|
||||
width: 33.34%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container .window-icon svg {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container .window-icon svg {
|
||||
shape-rendering: crispEdges;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar.titlebar > .window-controls-container .window-close {
|
||||
.monaco-workbench .part.titlebar.titlebar > .window-controls-container .window-close {
|
||||
-webkit-mask: url('chrome-close.svg') no-repeat 50% 50%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar.titlebar > .window-controls-container .window-unmaximize {
|
||||
.monaco-workbench .part.titlebar.titlebar > .window-controls-container .window-unmaximize {
|
||||
-webkit-mask: url('chrome-restore.svg') no-repeat 50% 50%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container .window-maximize {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container .window-maximize {
|
||||
-webkit-mask: url('chrome-maximize.svg') no-repeat 50% 50%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container .window-minimize {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container .window-minimize {
|
||||
-webkit-mask: url('chrome-minimize.svg') no-repeat 50% 50%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container > .window-icon-bg > .window-icon {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg > .window-icon {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
-webkit-mask-size: 23.1%;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container > .window-icon-bg:hover {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar.light > .window-controls-container > .window-icon-bg:hover {
|
||||
.monaco-workbench .part.titlebar.light > .window-controls-container > .window-icon-bg:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container > .window-icon-bg.window-close-bg:hover {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container > .window-icon-bg.window-close-bg:hover {
|
||||
background-color: rgba(232, 17, 35, 0.9);
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container .window-icon.window-close:hover {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container .window-icon.window-close:hover {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { IMenubarMenu, IMenubarMenuItemAction, IMenubarMenuItemSubmenu, IMenubarKeybinding, IMenubarService, IMenubarData } from 'vs/platform/menubar/common/menubar';
|
||||
import { IMenubarMenu, IMenubarMenuItemAction, IMenubarMenuItemSubmenu, IMenubarKeybinding, IMenubarService, IMenubarData, MenubarMenuItem } from 'vs/platform/menubar/common/menubar';
|
||||
import { IMenuService, MenuId, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { registerThemingParticipant, ITheme, ICssStyleCollector, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IWindowService, MenuBarVisibility, IWindowsService, getTitleBarStyle } from 'vs/platform/windows/common/windows';
|
||||
@@ -31,6 +31,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { MenuBar } from 'vs/base/browser/ui/menu/menubar';
|
||||
import { SubmenuAction } from 'vs/base/browser/ui/menu/menu';
|
||||
import { attachMenuStyler } from 'vs/platform/theme/common/styler';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
|
||||
export class MenubarControl extends Disposable {
|
||||
|
||||
@@ -45,27 +46,29 @@ export class MenubarControl extends Disposable {
|
||||
'window.nativeTabs'
|
||||
];
|
||||
|
||||
// {{SQL CARBON EDIT}} - Disable unusued menus
|
||||
private topLevelMenus: {
|
||||
'File': IMenu;
|
||||
'Edit': IMenu;
|
||||
'Selection': IMenu;
|
||||
// 'Selection': IMenu;
|
||||
'View': IMenu;
|
||||
'Go': IMenu;
|
||||
'Debug': IMenu;
|
||||
'Terminal': IMenu;
|
||||
// 'Go': IMenu;
|
||||
// 'Debug': IMenu;
|
||||
// 'Terminal': IMenu;
|
||||
'Window'?: IMenu;
|
||||
'Help': IMenu;
|
||||
[index: string]: IMenu;
|
||||
// [index: string]: IMenu;
|
||||
};
|
||||
|
||||
// {{SQL CARBON EDIT}} - Disable unused menus
|
||||
private topLevelTitles = {
|
||||
'File': nls.localize({ key: 'mFile', comment: ['&& denotes a mnemonic'] }, "&&File"),
|
||||
'Edit': nls.localize({ key: 'mEdit', comment: ['&& denotes a mnemonic'] }, "&&Edit"),
|
||||
'Selection': nls.localize({ key: 'mSelection', comment: ['&& denotes a mnemonic'] }, "&&Selection"),
|
||||
// 'Selection': nls.localize({ key: 'mSelection', comment: ['&& denotes a mnemonic'] }, "&&Selection"),
|
||||
'View': nls.localize({ key: 'mView', comment: ['&& denotes a mnemonic'] }, "&&View"),
|
||||
'Go': nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Go"),
|
||||
'Debug': nls.localize({ key: 'mDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug"),
|
||||
'Terminal': nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal"),
|
||||
// 'Go': nls.localize({ key: 'mGoto', comment: ['&& denotes a mnemonic'] }, "&&Go"),
|
||||
// 'Debug': nls.localize({ key: 'mDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug"),
|
||||
// 'Terminal': nls.localize({ key: 'mTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal"),
|
||||
'Help': nls.localize({ key: 'mHelp', comment: ['&& denotes a mnemonic'] }, "&&Help")
|
||||
};
|
||||
|
||||
@@ -80,32 +83,33 @@ export class MenubarControl extends Disposable {
|
||||
private static MAX_MENU_RECENT_ENTRIES = 10;
|
||||
|
||||
constructor(
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@IMenubarService private menubarService: IMenubarService,
|
||||
@IMenuService private menuService: IMenuService,
|
||||
@IWindowService private windowService: IWindowService,
|
||||
@IWindowsService private windowsService: IWindowsService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@ILabelService private labelService: ILabelService,
|
||||
@IUpdateService private updateService: IUpdateService,
|
||||
@IStorageService private storageService: IStorageService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@IPreferencesService private preferencesService: IPreferencesService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IMenubarService private readonly menubarService: IMenubarService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@IUpdateService private readonly updateService: IUpdateService,
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IPreferencesService private readonly preferencesService: IPreferencesService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService
|
||||
) {
|
||||
|
||||
super();
|
||||
|
||||
// {{SQL CARBON EDIT}} - Disable unused menus
|
||||
this.topLevelMenus = {
|
||||
'File': this._register(this.menuService.createMenu(MenuId.MenubarFileMenu, this.contextKeyService)),
|
||||
'Edit': this._register(this.menuService.createMenu(MenuId.MenubarEditMenu, this.contextKeyService)),
|
||||
'Selection': this._register(this.menuService.createMenu(MenuId.MenubarSelectionMenu, this.contextKeyService)),
|
||||
// 'Selection': this._register(this.menuService.createMenu(MenuId.MenubarSelectionMenu, this.contextKeyService)),
|
||||
'View': this._register(this.menuService.createMenu(MenuId.MenubarViewMenu, this.contextKeyService)),
|
||||
'Go': this._register(this.menuService.createMenu(MenuId.MenubarGoMenu, this.contextKeyService)),
|
||||
'Debug': this._register(this.menuService.createMenu(MenuId.MenubarDebugMenu, this.contextKeyService)),
|
||||
'Terminal': this._register(this.menuService.createMenu(MenuId.MenubarTerminalMenu, this.contextKeyService)),
|
||||
// 'Go': this._register(this.menuService.createMenu(MenuId.MenubarGoMenu, this.contextKeyService)),
|
||||
// 'Debug': this._register(this.menuService.createMenu(MenuId.MenubarDebugMenu, this.contextKeyService)),
|
||||
// 'Terminal': this._register(this.menuService.createMenu(MenuId.MenubarTerminalMenu, this.contextKeyService)),
|
||||
'Help': this._register(this.menuService.createMenu(MenuId.MenubarHelpMenu, this.contextKeyService))
|
||||
};
|
||||
|
||||
@@ -263,6 +267,9 @@ export class MenubarControl extends Disposable {
|
||||
this.menubar.blur();
|
||||
}));
|
||||
}
|
||||
|
||||
// Update recent menu items on formatter registration
|
||||
this._register(this.labelService.onDidChangeFormatters(() => { this.onRecentlyOpenedChange(); }));
|
||||
}
|
||||
|
||||
private doUpdateMenubar(firstTime: boolean): void {
|
||||
@@ -315,7 +322,7 @@ export class MenubarControl extends Disposable {
|
||||
return label;
|
||||
}
|
||||
|
||||
private createOpenRecentMenuAction(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI, commandId: string, isFile: boolean): IAction {
|
||||
private createOpenRecentMenuAction(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI, commandId: string, isFile: boolean): IAction & { uri: URI } {
|
||||
|
||||
let label: string;
|
||||
let uri: URI;
|
||||
@@ -331,7 +338,7 @@ export class MenubarControl extends Disposable {
|
||||
label = this.labelService.getUriLabel(uri);
|
||||
}
|
||||
|
||||
return new Action(commandId, label, undefined, undefined, (event) => {
|
||||
const ret: IAction = new Action(commandId, label, undefined, undefined, (event) => {
|
||||
const openInNewWindow = event && ((!isMacintosh && (event.ctrlKey || event.shiftKey)) || (isMacintosh && (event.metaKey || event.altKey)));
|
||||
|
||||
return this.windowService.openWindow([uri], {
|
||||
@@ -339,8 +346,11 @@ export class MenubarControl extends Disposable {
|
||||
forceOpenWorkspaceAsFile: isFile
|
||||
});
|
||||
});
|
||||
|
||||
return assign(ret, { uri: uri });
|
||||
}
|
||||
|
||||
/* Custom Menu takes actions */
|
||||
private getOpenRecentActions(): IAction[] {
|
||||
if (!this.recentlyOpened) {
|
||||
return [];
|
||||
@@ -369,6 +379,19 @@ export class MenubarControl extends Disposable {
|
||||
return result;
|
||||
}
|
||||
|
||||
private transformOpenRecentAction(action: Separator | (IAction & { uri: URI })): MenubarMenuItem {
|
||||
if (action instanceof Separator) {
|
||||
return { id: 'vscode.menubar.separator' };
|
||||
}
|
||||
|
||||
return {
|
||||
id: action.id,
|
||||
uri: action.uri,
|
||||
enabled: action.enabled,
|
||||
label: action.label
|
||||
};
|
||||
}
|
||||
|
||||
private getUpdateAction(): IAction | null {
|
||||
const state = this.updateService.state;
|
||||
|
||||
@@ -501,13 +524,13 @@ export class MenubarControl extends Disposable {
|
||||
// first try to resolve a native accelerator
|
||||
const electronAccelerator = binding.getElectronAccelerator();
|
||||
if (electronAccelerator) {
|
||||
return { label: electronAccelerator };
|
||||
return { label: electronAccelerator, userSettingsLabel: binding.getUserSettingsLabel() };
|
||||
}
|
||||
|
||||
// we need this fallback to support keybindings that cannot show in electron menus (e.g. chords)
|
||||
const acceleratorLabel = binding.getLabel();
|
||||
if (acceleratorLabel) {
|
||||
return { label: acceleratorLabel, isNative: false };
|
||||
return { label: acceleratorLabel, isNative: false, userSettingsLabel: binding.getUserSettingsLabel() };
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -534,6 +557,11 @@ export class MenubarControl extends Disposable {
|
||||
menuToPopulate.items.push(menubarSubmenuItem);
|
||||
menuToDispose.dispose();
|
||||
} else {
|
||||
if (menuItem.id === 'workbench.action.openRecent') {
|
||||
const actions = this.getOpenRecentActions().map(this.transformOpenRecentAction);
|
||||
menuToPopulate.items.push(...actions);
|
||||
}
|
||||
|
||||
let menubarMenuItem: IMenubarMenuItemAction = {
|
||||
id: menuItem.id,
|
||||
label: menuItem.label
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import 'vs/css!./media/titlebarpart';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { Part } from 'vs/workbench/browser/part';
|
||||
import { ITitleService, ITitleProperties } from 'vs/workbench/services/title/common/titleService';
|
||||
import { getZoomFactor } from 'vs/base/browser/browser';
|
||||
@@ -25,15 +26,17 @@ import { isMacintosh, isWindows, isLinux } from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { trim } from 'vs/base/common/strings';
|
||||
import { EventType, EventHelper, Dimension, isAncestor, hide, show, removeClass, addClass, append, $, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { EventType, EventHelper, Dimension, isAncestor, hide, show, removeClass, addClass, append, $, addDisposableListener, runAtThisOrScheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { MenubarControl } from 'vs/workbench/browser/parts/titlebar/menubarControl';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { template, getBaseLabel } from 'vs/base/common/labels';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
|
||||
import { Parts } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
export class TitlebarPart extends Part implements ITitleService {
|
||||
export class TitlebarPart extends Part implements ITitleService, ISerializableView {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
@@ -43,7 +46,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
private static readonly TITLE_DIRTY = '\u25cf ';
|
||||
private static readonly TITLE_SEPARATOR = isMacintosh ? ' — ' : ' - '; // macOS uses special - separator
|
||||
|
||||
private titleContainer: HTMLElement;
|
||||
element: HTMLElement;
|
||||
private title: HTMLElement;
|
||||
private dragRegion: HTMLElement;
|
||||
private windowControls: HTMLElement;
|
||||
@@ -61,18 +64,26 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
private properties: ITitleProperties;
|
||||
private activeEditorListeners: IDisposable[];
|
||||
|
||||
minimumWidth: number = 0;
|
||||
maximumWidth: number = Number.POSITIVE_INFINITY;
|
||||
get minimumHeight(): number { return isMacintosh ? 22 / getZoomFactor() : (30 / (this.configurationService.getValue<MenuBarVisibility>('window.menuBarVisibility') === 'hidden' ? getZoomFactor() : 1)); }
|
||||
get maximumHeight(): number { return isMacintosh ? 22 / getZoomFactor() : (30 / (this.configurationService.getValue<MenuBarVisibility>('window.menuBarVisibility') === 'hidden' ? getZoomFactor() : 1)); }
|
||||
|
||||
private _onDidChange = new Emitter<{ width: number; height: number; }>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IWindowService private windowService: IWindowService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IWindowsService private windowsService: IWindowsService,
|
||||
@IEditorService private editorService: IEditorService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@ILabelService private labelService: ILabelService,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@IStorageService storageService: IStorageService
|
||||
) {
|
||||
super(id, { hasTitle: false }, themeService, storageService);
|
||||
@@ -90,7 +101,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
this._register(this.contextService.onDidChangeWorkspaceFolders(() => this.doUpdateTitle()));
|
||||
this._register(this.contextService.onDidChangeWorkbenchState(() => this.doUpdateTitle()));
|
||||
this._register(this.contextService.onDidChangeWorkspaceName(() => this.doUpdateTitle()));
|
||||
this._register(this.labelService.onDidRegisterFormatter(() => this.doUpdateTitle()));
|
||||
this._register(this.labelService.onDidChangeFormatters(() => this.doUpdateTitle()));
|
||||
}
|
||||
|
||||
private onBlur(): void {
|
||||
@@ -107,6 +118,12 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
if (event.affectsConfiguration('window.title')) {
|
||||
this.doUpdateTitle();
|
||||
}
|
||||
|
||||
if (event.affectsConfiguration('window.doubleClickIconToClose')) {
|
||||
if (this.appIcon) {
|
||||
this.onUpdateAppIconDragBehavior();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onMenubarVisibilityChanged(visible: boolean) {
|
||||
@@ -184,7 +201,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
this.pendingTitle = title;
|
||||
}
|
||||
|
||||
if (isWindows || isLinux) {
|
||||
if ((isWindows || isLinux) && this.title) {
|
||||
this.adjustTitleMarginToCenter();
|
||||
}
|
||||
}
|
||||
@@ -222,21 +239,25 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
/**
|
||||
* Possible template values:
|
||||
*
|
||||
* {activeEditorLong}: e.g. /Users/Development/myProject/myFolder/myFile.txt
|
||||
* {activeEditorMedium}: e.g. myFolder/myFile.txt
|
||||
* {activeEditorLong}: e.g. /Users/Development/myFolder/myFileFolder/myFile.txt
|
||||
* {activeEditorMedium}: e.g. myFolder/myFileFolder/myFile.txt
|
||||
* {activeEditorShort}: e.g. myFile.txt
|
||||
* {activeFolderLong}: e.g. /Users/Development/myFolder/myFileFolder
|
||||
* {activeFolderMedium}: e.g. myFolder/myFileFolder
|
||||
* {activeFolderShort}: e.g. myFileFolder
|
||||
* {rootName}: e.g. myFolder1, myFolder2, myFolder3
|
||||
* {rootPath}: e.g. /Users/Development/myProject
|
||||
* {rootPath}: e.g. /Users/Development
|
||||
* {folderName}: e.g. myFolder
|
||||
* {folderPath}: e.g. /Users/Development/myFolder
|
||||
* {appName}: e.g. VS Code
|
||||
* {dirty}: indiactor
|
||||
* {dirty}: indicator
|
||||
* {separator}: conditional separator
|
||||
*/
|
||||
private doGetWindowTitle(): string {
|
||||
const editor = this.editorService.activeEditor;
|
||||
const workspace = this.contextService.getWorkspace();
|
||||
|
||||
// Compute root
|
||||
let root: URI;
|
||||
if (workspace.configuration) {
|
||||
root = workspace.configuration;
|
||||
@@ -244,15 +265,25 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
root = workspace.folders[0].uri;
|
||||
}
|
||||
|
||||
// Compute active editor folder
|
||||
const editorResource = editor ? toResource(editor) : undefined;
|
||||
let editorFolderResource = editorResource ? resources.dirname(editorResource) : undefined;
|
||||
if (editorFolderResource && editorFolderResource.path === '.') {
|
||||
editorFolderResource = undefined;
|
||||
}
|
||||
|
||||
// Compute folder resource
|
||||
// Single Root Workspace: always the root single workspace in this case
|
||||
// Otherwise: root folder of the currently active file if any
|
||||
let folder = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.folders[0] : this.contextService.getWorkspaceFolder(toResource(editor, { supportSideBySide: true }));
|
||||
const folder = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.folders[0] : this.contextService.getWorkspaceFolder(toResource(editor, { supportSideBySide: true }));
|
||||
|
||||
// Variables
|
||||
const activeEditorShort = editor ? editor.getTitle(Verbosity.SHORT) : '';
|
||||
const activeEditorMedium = editor ? editor.getTitle(Verbosity.MEDIUM) : activeEditorShort;
|
||||
const activeEditorLong = editor ? editor.getTitle(Verbosity.LONG) : activeEditorMedium;
|
||||
const activeFolderShort = editorFolderResource ? resources.basename(editorFolderResource) : '';
|
||||
const activeFolderMedium = editorFolderResource ? this.labelService.getUriLabel(editorFolderResource, { relative: true }) : '';
|
||||
const activeFolderLong = editorFolderResource ? this.labelService.getUriLabel(editorFolderResource) : '';
|
||||
const rootName = this.labelService.getWorkspaceLabel(workspace);
|
||||
const rootPath = root ? this.labelService.getUriLabel(root) : '';
|
||||
const folderName = folder ? folder.name : '';
|
||||
@@ -266,6 +297,9 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
activeEditorShort,
|
||||
activeEditorLong,
|
||||
activeEditorMedium,
|
||||
activeFolderShort,
|
||||
activeFolderMedium,
|
||||
activeFolderLong,
|
||||
rootName,
|
||||
rootPath,
|
||||
folderName,
|
||||
@@ -277,19 +311,24 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
}
|
||||
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
this.titleContainer = parent;
|
||||
this.element = parent;
|
||||
|
||||
// Draggable region that we can manipulate for #52522
|
||||
this.dragRegion = append(this.titleContainer, $('div.titlebar-drag-region'));
|
||||
this.dragRegion = append(this.element, $('div.titlebar-drag-region'));
|
||||
|
||||
// App Icon (Windows/Linux)
|
||||
if (!isMacintosh) {
|
||||
this.appIcon = append(this.titleContainer, $('div.window-appicon'));
|
||||
this.appIcon = append(this.element, $('div.window-appicon'));
|
||||
this.onUpdateAppIconDragBehavior();
|
||||
|
||||
this._register(addDisposableListener(this.appIcon, EventType.DBLCLICK, (e => {
|
||||
this.windowService.closeWindow();
|
||||
})));
|
||||
}
|
||||
|
||||
// Menubar: the menubar part which is responsible for populating both the custom and native menubars
|
||||
this.menubarPart = this.instantiationService.createInstance(MenubarControl);
|
||||
this.menubar = append(this.titleContainer, $('div.menubar'));
|
||||
this.menubar = append(this.element, $('div.menubar'));
|
||||
this.menubar.setAttribute('role', 'menubar');
|
||||
|
||||
this.menubarPart.create(this.menubar);
|
||||
@@ -300,7 +339,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
}
|
||||
|
||||
// Title
|
||||
this.title = append(this.titleContainer, $('div.window-title'));
|
||||
this.title = append(this.element, $('div.window-title'));
|
||||
if (this.pendingTitle) {
|
||||
this.title.innerText = this.pendingTitle;
|
||||
} else {
|
||||
@@ -309,7 +348,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
|
||||
// Maximize/Restore on doubleclick
|
||||
if (isMacintosh) {
|
||||
this._register(addDisposableListener(this.titleContainer, EventType.DBLCLICK, e => {
|
||||
this._register(addDisposableListener(this.element, EventType.DBLCLICK, e => {
|
||||
EventHelper.stop(e);
|
||||
|
||||
this.onTitleDoubleclick();
|
||||
@@ -329,7 +368,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
|
||||
// Window Controls (Windows/Linux)
|
||||
if (!isMacintosh) {
|
||||
this.windowControls = append(this.titleContainer, $('div.window-controls-container'));
|
||||
this.windowControls = append(this.element, $('div.window-controls-container'));
|
||||
|
||||
|
||||
// Minimize
|
||||
@@ -364,7 +403,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
}));
|
||||
|
||||
// Resizer
|
||||
this.resizer = append(this.titleContainer, $('div.resizer'));
|
||||
this.resizer = append(this.element, $('div.resizer'));
|
||||
|
||||
const isMaximized = this.windowService.getConfiguration().maximized ? true : false;
|
||||
this.onDidChangeMaximized(isMaximized);
|
||||
@@ -373,7 +412,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
|
||||
// Since the title area is used to drag the window, we do not want to steal focus from the
|
||||
// currently active element. So we restore focus after a timeout back to where it was.
|
||||
this._register(addDisposableListener(this.titleContainer, EventType.MOUSE_DOWN, e => {
|
||||
this._register(addDisposableListener(this.element, EventType.MOUSE_DOWN, e => {
|
||||
if (e.target && isAncestor(e.target as HTMLElement, this.menubar)) {
|
||||
return;
|
||||
}
|
||||
@@ -388,7 +427,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
|
||||
this.updateStyles();
|
||||
|
||||
return this.titleContainer;
|
||||
return this.element;
|
||||
}
|
||||
|
||||
private onDidChangeMaximized(maximized: boolean) {
|
||||
@@ -417,26 +456,26 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
super.updateStyles();
|
||||
|
||||
// Part container
|
||||
if (this.titleContainer) {
|
||||
if (this.element) {
|
||||
if (this.isInactive) {
|
||||
addClass(this.titleContainer, 'inactive');
|
||||
addClass(this.element, 'inactive');
|
||||
} else {
|
||||
removeClass(this.titleContainer, 'inactive');
|
||||
removeClass(this.element, 'inactive');
|
||||
}
|
||||
|
||||
const titleBackground = this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_BACKGROUND : TITLE_BAR_ACTIVE_BACKGROUND);
|
||||
this.titleContainer.style.backgroundColor = titleBackground;
|
||||
this.element.style.backgroundColor = titleBackground;
|
||||
if (Color.fromHex(titleBackground).isLighter()) {
|
||||
addClass(this.titleContainer, 'light');
|
||||
addClass(this.element, 'light');
|
||||
} else {
|
||||
removeClass(this.titleContainer, 'light');
|
||||
removeClass(this.element, 'light');
|
||||
}
|
||||
|
||||
const titleForeground = this.getColor(this.isInactive ? TITLE_BAR_INACTIVE_FOREGROUND : TITLE_BAR_ACTIVE_FOREGROUND);
|
||||
this.titleContainer.style.color = titleForeground;
|
||||
this.element.style.color = titleForeground;
|
||||
|
||||
const titleBorder = this.getColor(TITLE_BAR_BORDER);
|
||||
this.titleContainer.style.borderBottom = titleBorder ? `1px solid ${titleBorder}` : null;
|
||||
this.element.style.borderBottom = titleBorder ? `1px solid ${titleBorder}` : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,6 +483,16 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
this.windowService.onWindowTitleDoubleClick();
|
||||
}
|
||||
|
||||
private onUpdateAppIconDragBehavior() {
|
||||
const setting = this.configurationService.getValue('window.doubleClickIconToClose');
|
||||
if (setting) {
|
||||
this.appIcon.style['-webkit-app-region'] = 'no-drag';
|
||||
}
|
||||
else {
|
||||
this.appIcon.style['-webkit-app-region'] = 'drag';
|
||||
}
|
||||
}
|
||||
|
||||
private onContextMenu(e: MouseEvent): void {
|
||||
|
||||
// Find target anchor
|
||||
@@ -491,30 +540,27 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
}
|
||||
|
||||
private adjustTitleMarginToCenter(): void {
|
||||
setTimeout(() => {
|
||||
// Cannot center
|
||||
if (!isMacintosh &&
|
||||
(this.appIcon.clientWidth + this.menubar.clientWidth + 10 > (this.titleContainer.clientWidth - this.title.clientWidth) / 2 ||
|
||||
this.titleContainer.clientWidth - this.windowControls.clientWidth - 10 < (this.titleContainer.clientWidth + this.title.clientWidth) / 2)) {
|
||||
this.title.style.position = null;
|
||||
this.title.style.left = null;
|
||||
this.title.style.transform = null;
|
||||
} else {
|
||||
this.title.style.position = 'absolute';
|
||||
this.title.style.left = '50%';
|
||||
this.title.style.transform = 'translate(-50%, 0)';
|
||||
}
|
||||
}, 0); // delay so that we can get accurate information about widths
|
||||
if (!isMacintosh &&
|
||||
(this.appIcon.clientWidth + this.menubar.clientWidth + 10 > (this.element.clientWidth - this.title.clientWidth) / 2 ||
|
||||
this.element.clientWidth - this.windowControls.clientWidth - 10 < (this.element.clientWidth + this.title.clientWidth) / 2)) {
|
||||
this.title.style.position = null;
|
||||
this.title.style.left = null;
|
||||
this.title.style.transform = null;
|
||||
} else {
|
||||
this.title.style.position = 'absolute';
|
||||
this.title.style.left = '50%';
|
||||
this.title.style.transform = 'translate(-50%, 0)';
|
||||
}
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): Dimension[] {
|
||||
updateLayout(dimension: Dimension): void {
|
||||
if (getTitleBarStyle(this.configurationService, this.environmentService) === 'custom') {
|
||||
// Only prevent zooming behavior on macOS or when the menubar is not visible
|
||||
if (isMacintosh || this.configurationService.getValue<MenuBarVisibility>('window.menuBarVisibility') === 'hidden') {
|
||||
this.title.style.zoom = `${1.0 / getZoomFactor()}`;
|
||||
this.title.style.zoom = `${1 / getZoomFactor()}`;
|
||||
if (isWindows || isLinux) {
|
||||
this.appIcon.style.zoom = `${1.0 / getZoomFactor()}`;
|
||||
this.windowControls.style.zoom = `${1.0 / getZoomFactor()}`;
|
||||
this.appIcon.style.zoom = `${1 / getZoomFactor()}`;
|
||||
this.windowControls.style.zoom = `${1 / getZoomFactor()}`;
|
||||
}
|
||||
} else {
|
||||
this.title.style.zoom = null;
|
||||
@@ -524,15 +570,34 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
}
|
||||
}
|
||||
|
||||
this.adjustTitleMarginToCenter();
|
||||
runAtThisOrScheduleAtNextAnimationFrame(() => this.adjustTitleMarginToCenter());
|
||||
|
||||
if (this.menubarPart) {
|
||||
const menubarDimension = new Dimension(undefined, dimension.height);
|
||||
this.menubarPart.layout(menubarDimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.layout(dimension);
|
||||
layout(dimension: Dimension): Dimension[];
|
||||
layout(width: number, height: number): void;
|
||||
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
|
||||
if (dim1 instanceof Dimension) {
|
||||
this.updateLayout(dim1);
|
||||
|
||||
return super.layout(dim1);
|
||||
}
|
||||
|
||||
const dimensions = new Dimension(dim1, dim2);
|
||||
this.updateLayout(dimensions);
|
||||
|
||||
super.layout(dimensions);
|
||||
}
|
||||
|
||||
toJSON(): object {
|
||||
return {
|
||||
type: Parts.TITLEBAR_PART
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,7 +607,7 @@ class ShowItemInFolderAction extends Action {
|
||||
super('showItemInFolder.action.id', label);
|
||||
}
|
||||
|
||||
run(): Thenable<void> {
|
||||
run(): Promise<void> {
|
||||
return this.windowsService.showItemInFolder(this.path);
|
||||
}
|
||||
}
|
||||
@@ -551,7 +616,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const titlebarActiveFg = theme.getColor(TITLE_BAR_ACTIVE_FOREGROUND);
|
||||
if (titlebarActiveFg) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.titlebar > .window-controls-container .window-icon {
|
||||
.monaco-workbench .part.titlebar > .window-controls-container .window-icon {
|
||||
background-color: ${titlebarActiveFg};
|
||||
}
|
||||
`);
|
||||
@@ -560,7 +625,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const titlebarInactiveFg = theme.getColor(TITLE_BAR_INACTIVE_FOREGROUND);
|
||||
if (titlebarInactiveFg) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.titlebar.inactive > .window-controls-container .window-icon {
|
||||
.monaco-workbench .part.titlebar.inactive > .window-controls-container .window-icon {
|
||||
background-color: ${titlebarInactiveFg};
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -13,7 +13,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
||||
import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { ContextAwareMenuItemActionItem, fillInActionBarActions, fillInContextMenuActions } from 'vs/platform/actions/browser/menuItemActionItem';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IViewsService, ITreeView, ITreeItem, TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ICustomViewDescriptor, ViewsRegistry, ViewContainer, ITreeItemLabel } from 'vs/workbench/common/views';
|
||||
import { IViewsService, ITreeView, ITreeItem, TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ITreeViewDescriptor, ViewsRegistry, ViewContainer, ITreeItemLabel } from 'vs/workbench/common/views';
|
||||
import { IViewletViewOptions, FileIconThemableWorkbenchTree } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
@@ -23,7 +23,7 @@ import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/work
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IDataSource, ITree, IRenderer, ContextMenuEvent } from 'vs/base/parts/tree/browser/tree';
|
||||
import { ResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { ActionBar, IActionItemProvider, ActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { basename } from 'vs/base/common/paths';
|
||||
@@ -51,22 +51,18 @@ export class CustomTreeViewPanel extends ViewletPanel {
|
||||
|
||||
constructor(
|
||||
options: IViewletViewOptions,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IViewsService viewsService: IViewsService,
|
||||
) {
|
||||
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService);
|
||||
const { treeView } = (<ICustomViewDescriptor>ViewsRegistry.getView(options.id));
|
||||
const { treeView } = (<ITreeViewDescriptor>ViewsRegistry.getView(options.id));
|
||||
this.treeView = treeView;
|
||||
this.treeView.onDidChangeActions(() => this.updateActions(), this, this.disposables);
|
||||
this.disposables.push(toDisposable(() => this.treeView.setVisibility(false)));
|
||||
this.updateTreeVisibility();
|
||||
}
|
||||
|
||||
setVisible(visible: boolean): void {
|
||||
super.setVisible(visible);
|
||||
this.disposables.push(this.onDidChangeBodyVisibility(() => this.updateTreeVisibility()));
|
||||
this.updateTreeVisibility();
|
||||
}
|
||||
|
||||
@@ -79,11 +75,6 @@ export class CustomTreeViewPanel extends ViewletPanel {
|
||||
this.treeView.show(container);
|
||||
}
|
||||
|
||||
setExpanded(expanded: boolean): void {
|
||||
this.treeView.setVisibility(this.isVisible() && expanded);
|
||||
super.setExpanded(expanded);
|
||||
}
|
||||
|
||||
layoutBody(size: number): void {
|
||||
this.treeView.layout(size);
|
||||
}
|
||||
@@ -105,7 +96,7 @@ export class CustomTreeViewPanel extends ViewletPanel {
|
||||
}
|
||||
|
||||
private updateTreeVisibility(): void {
|
||||
this.treeView.setVisibility(this.isVisible() && this.isExpanded());
|
||||
this.treeView.setVisibility(this.isBodyVisible());
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@@ -126,8 +117,8 @@ class TitleMenus implements IDisposable {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IMenuService private menuService: IMenuService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
) {
|
||||
if (this.titleDisposable) {
|
||||
this.titleDisposable.dispose();
|
||||
@@ -175,7 +166,7 @@ class Root implements ITreeItem {
|
||||
handle = '0';
|
||||
parentHandle = null;
|
||||
collapsibleState = TreeItemCollapsibleState.Expanded;
|
||||
children = void 0;
|
||||
children = undefined;
|
||||
}
|
||||
|
||||
const noDataProviderMessage = localize('no-dataprovider', "There is no data provider registered that can provide view data.");
|
||||
@@ -194,6 +185,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
private _messageValue: string | IMarkdownString | undefined;
|
||||
private messageElement: HTMLDivElement;
|
||||
private tree: FileIconThemableWorkbenchTree;
|
||||
private treeLabels: ResourceLabels;
|
||||
private root: ITreeItem;
|
||||
private elementsToRefresh: ITreeItem[] = [];
|
||||
private menus: TitleMenus;
|
||||
@@ -218,13 +210,13 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
|
||||
constructor(
|
||||
private id: string,
|
||||
private container: ViewContainer,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IWorkbenchThemeService private themeService: IWorkbenchThemeService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@ICommandService private commandService: ICommandService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IProgressService2 private progressService: IProgressService2
|
||||
private viewContainer: ViewContainer,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IProgressService2 private readonly progressService: IProgressService2
|
||||
) {
|
||||
super();
|
||||
this.root = new Root();
|
||||
@@ -243,6 +235,11 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
this.markdownResult.dispose();
|
||||
}
|
||||
}));
|
||||
this._register(ViewsRegistry.onDidChangeContainer(({ views, from, to }) => {
|
||||
if (from === this.viewContainer && views.some(v => v.id === this.id)) {
|
||||
this.viewContainer = to;
|
||||
}
|
||||
}));
|
||||
this.create();
|
||||
}
|
||||
|
||||
@@ -382,13 +379,13 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
|
||||
private createTree() {
|
||||
const actionItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuItemActionItem, action) : undefined;
|
||||
const menus = this.instantiationService.createInstance(TreeMenus, this.id);
|
||||
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, this.container);
|
||||
const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, menus, actionItemProvider);
|
||||
const menus = this._register(this.instantiationService.createInstance(TreeMenus, this.id));
|
||||
this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this));
|
||||
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, <T>(task: Promise<T>) => this.progressService.withProgress({ location: this.viewContainer.id }, () => task));
|
||||
const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, menus, this.treeLabels, actionItemProvider);
|
||||
const controller = this.instantiationService.createInstance(TreeController, this.id, menus);
|
||||
this.tree = this.instantiationService.createInstance(FileIconThemableWorkbenchTree, this.treeContainer, { dataSource, renderer, controller }, {});
|
||||
this.tree = this._register(this.instantiationService.createInstance(FileIconThemableWorkbenchTree, this.treeContainer, { dataSource, renderer, controller }, {}));
|
||||
this.tree.contextKeyService.createKey<boolean>(this.id, true);
|
||||
this._register(this.tree);
|
||||
this._register(this.tree.onDidChangeSelection(e => this.onSelection(e)));
|
||||
this._register(this.tree.onDidExpandItem(e => this._onDidExpandItem.fire(e.item.getElement())));
|
||||
this._register(this.tree.onDidCollapseItem(e => this._onDidCollapseItem.fire(e.item.getElement())));
|
||||
@@ -451,7 +448,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
getOptimalWidth(): number {
|
||||
if (this.tree) {
|
||||
const parentNode = this.tree.getHTMLElement();
|
||||
const childNodes = ([] as Element[]).slice.call(parentNode.querySelectorAll('.outline-item-label > a'));
|
||||
const childNodes = ([] as HTMLElement[]).slice.call(parentNode.querySelectorAll('.outline-item-label > a'));
|
||||
return DOM.getLargestChildWidth(parentNode, childNodes);
|
||||
}
|
||||
return 0;
|
||||
@@ -459,25 +456,39 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
|
||||
refresh(elements?: ITreeItem[]): Promise<void> {
|
||||
if (this.dataProvider && this.tree) {
|
||||
elements = elements || [this.root];
|
||||
if (!elements) {
|
||||
elements = [this.root];
|
||||
// remove all waiting elements to refresh if root is asked to refresh
|
||||
this.elementsToRefresh = [];
|
||||
}
|
||||
for (const element of elements) {
|
||||
element.children = null; // reset children
|
||||
}
|
||||
if (this.isVisible) {
|
||||
return this.doRefresh(elements);
|
||||
} else {
|
||||
this.elementsToRefresh.push(...elements);
|
||||
if (this.elementsToRefresh.length) {
|
||||
const seen: Set<string> = new Set<string>();
|
||||
this.elementsToRefresh.forEach(element => seen.add(element.handle));
|
||||
for (const element of elements) {
|
||||
if (!seen.has(element.handle)) {
|
||||
this.elementsToRefresh.push(element);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.elementsToRefresh.push(...elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
expand(itemOrItems: ITreeItem | ITreeItem[]): Thenable<void> {
|
||||
expand(itemOrItems: ITreeItem | ITreeItem[]): Promise<void> {
|
||||
if (this.tree) {
|
||||
itemOrItems = Array.isArray(itemOrItems) ? itemOrItems : [itemOrItems];
|
||||
return this.tree.expandAll(itemOrItems);
|
||||
}
|
||||
return Promise.arguments(null);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
setSelection(items: ITreeItem[]): void {
|
||||
@@ -493,17 +504,17 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
}
|
||||
}
|
||||
|
||||
reveal(item: ITreeItem): Thenable<void> {
|
||||
reveal(item: ITreeItem): Promise<void> {
|
||||
if (this.tree) {
|
||||
return this.tree.reveal(item);
|
||||
}
|
||||
return Promise.arguments(null);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
private activate() {
|
||||
if (!this.activated) {
|
||||
this.createTree();
|
||||
this.progressService.withProgress({ location: this.container.id }, () => this.extensionService.activateByEvent(`onView:${this.id}`))
|
||||
this.progressService.withProgress({ location: this.viewContainer.id }, () => this.extensionService.activateByEvent(`onView:${this.id}`))
|
||||
.then(() => timeout(2000))
|
||||
.then(() => {
|
||||
this.updateMessage();
|
||||
@@ -525,7 +536,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
}
|
||||
});
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
private updateContentAreas(): void {
|
||||
@@ -563,8 +574,7 @@ class TreeDataSource implements IDataSource {
|
||||
|
||||
constructor(
|
||||
private treeView: ITreeView,
|
||||
private container: ViewContainer,
|
||||
@IProgressService2 private progressService: IProgressService2
|
||||
private withProgress: <T>(task: Promise<T>) => Promise<T>
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -578,7 +588,7 @@ class TreeDataSource implements IDataSource {
|
||||
|
||||
getChildren(tree: ITree, node: ITreeItem): Promise<any[]> {
|
||||
if (this.treeView.dataProvider) {
|
||||
return this.progressService.withProgress({ location: this.container.id }, () => this.treeView.dataProvider.getChildren(node));
|
||||
return this.withProgress(this.treeView.dataProvider.getChildren(node));
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
@@ -593,7 +603,7 @@ class TreeDataSource implements IDataSource {
|
||||
}
|
||||
|
||||
interface ITreeExplorerTemplateData {
|
||||
resourceLabel: ResourceLabel;
|
||||
resourceLabel: IResourceLabel;
|
||||
icon: HTMLElement;
|
||||
actionBar: ActionBar;
|
||||
aligner: Aligner;
|
||||
@@ -605,10 +615,12 @@ registerThemingParticipant((theme, collector) => {
|
||||
const findMatchHighlightColor = theme.getColor(editorFindMatchHighlight);
|
||||
if (findMatchHighlightColor) {
|
||||
collector.addRule(`.file-icon-themable-tree .monaco-tree-row .content .monaco-highlighted-label .highlight { color: unset !important; background-color: ${findMatchHighlightColor}; }`);
|
||||
collector.addRule(`.monaco-tl-contents .monaco-highlighted-label .highlight { color: unset !important; background-color: ${findMatchHighlightColor}; }`);
|
||||
}
|
||||
const findMatchHighlightColorBorder = theme.getColor(editorFindMatchHighlightBorder);
|
||||
if (findMatchHighlightColorBorder) {
|
||||
collector.addRule(`.file-icon-themable-tree .monaco-tree-row .content .monaco-highlighted-label .highlight { color: unset !important; border: 1px dotted ${findMatchHighlightColorBorder}; box-sizing: border-box; }`);
|
||||
collector.addRule(`.monaco-tl-contents .monaco-highlighted-label .highlight { color: unset !important; border: 1px dotted ${findMatchHighlightColorBorder}; box-sizing: border-box; }`);
|
||||
}
|
||||
const link = theme.getColor(textLinkForeground);
|
||||
if (link) {
|
||||
@@ -632,11 +644,11 @@ class TreeRenderer implements IRenderer {
|
||||
constructor(
|
||||
private treeViewId: string,
|
||||
private menus: TreeMenus,
|
||||
private labels: ResourceLabels,
|
||||
private actionItemProvider: IActionItemProvider,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IWorkbenchThemeService private themeService: IWorkbenchThemeService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@ILabelService private labelService: ILabelService
|
||||
@IWorkbenchThemeService private readonly themeService: IWorkbenchThemeService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@ILabelService private readonly labelService: ILabelService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -652,7 +664,7 @@ class TreeRenderer implements IRenderer {
|
||||
DOM.addClass(container, 'custom-view-tree-node-item');
|
||||
|
||||
const icon = DOM.append(container, DOM.$('.custom-view-tree-node-item-icon'));
|
||||
const resourceLabel = this.instantiationService.createInstance(ResourceLabel, container, { supportHighlights: true, donotSupportOcticons: true });
|
||||
const resourceLabel = this.labels.create(container, { supportHighlights: true, donotSupportOcticons: true });
|
||||
DOM.addClass(resourceLabel.element, 'custom-view-tree-node-item-resourceLabel');
|
||||
const actionsContainer = DOM.append(resourceLabel.element, DOM.$('.actions'));
|
||||
const actionBar = new ActionBar(actionsContainer, {
|
||||
@@ -665,23 +677,22 @@ class TreeRenderer implements IRenderer {
|
||||
|
||||
renderElement(tree: ITree, node: ITreeItem, templateId: string, templateData: ITreeExplorerTemplateData): void {
|
||||
const resource = node.resourceUri ? URI.revive(node.resourceUri) : null;
|
||||
const treeItemLabel: ITreeItemLabel = node.label ? node.label : resource ? { label: basename(resource.path) } : void 0;
|
||||
const description = isString(node.description) ? node.description : resource && node.description === true ? this.labelService.getUriLabel(dirname(resource), { relative: true }) : void 0;
|
||||
const label = treeItemLabel ? treeItemLabel.label : void 0;
|
||||
const matches = treeItemLabel && treeItemLabel.highlights ? treeItemLabel.highlights.map(([start, end]) => ({ start, end })) : void 0;
|
||||
const treeItemLabel: ITreeItemLabel = node.label ? node.label : resource ? { label: basename(resource.path) } : undefined;
|
||||
const description = isString(node.description) ? node.description : resource && node.description === true ? this.labelService.getUriLabel(dirname(resource), { relative: true }) : undefined;
|
||||
const label = treeItemLabel ? treeItemLabel.label : undefined;
|
||||
const matches = treeItemLabel && treeItemLabel.highlights ? treeItemLabel.highlights.map(([start, end]) => ({ start, end })) : undefined;
|
||||
const icon = this.themeService.getTheme().type === LIGHT ? node.icon : node.iconDark;
|
||||
const iconUrl = icon ? URI.revive(icon) : null;
|
||||
const title = node.tooltip ? node.tooltip : resource ? void 0 : label;
|
||||
const title = node.tooltip ? node.tooltip : resource ? undefined : label;
|
||||
|
||||
// reset
|
||||
templateData.resourceLabel.clear();
|
||||
templateData.actionBar.clear();
|
||||
|
||||
if (resource || node.themeIcon) {
|
||||
const fileDecorations = this.configurationService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
|
||||
templateData.resourceLabel.setLabel({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
|
||||
templateData.resourceLabel.setResource({ name: label, description, resource: resource ? resource : URI.parse('missing:_icon_resource') }, { fileKind: this.getFileKind(node), title, hideIcon: !!iconUrl, fileDecorations, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
|
||||
} else {
|
||||
templateData.resourceLabel.setLabel({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
|
||||
templateData.resourceLabel.setResource({ name: label, description }, { title, hideIcon: true, extraClasses: ['custom-view-tree-node-item-resourceLabel'], matches });
|
||||
}
|
||||
|
||||
templateData.icon.style.backgroundImage = iconUrl ? `url('${iconUrl.toString(true)}')` : '';
|
||||
@@ -772,7 +783,7 @@ class TreeController extends WorkbenchTreeController {
|
||||
constructor(
|
||||
private treeViewId: string,
|
||||
private menus: TreeMenus,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
) {
|
||||
@@ -827,7 +838,7 @@ class MultipleSelectionActionRunner extends ActionRunner {
|
||||
super();
|
||||
}
|
||||
|
||||
runAction(action: IAction, context: any): Thenable<any> {
|
||||
runAction(action: IAction, context: any): Promise<any> {
|
||||
if (action instanceof MenuItemAction) {
|
||||
const selection = this.getSelectedResources();
|
||||
const filteredSelection = selection.filter(s => s !== context);
|
||||
@@ -847,9 +858,9 @@ class TreeMenus extends Disposable implements IDisposable {
|
||||
|
||||
constructor(
|
||||
private id: string,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IMenuService private menuService: IMenuService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -914,4 +925,4 @@ class MarkdownRenderer {
|
||||
dispose: () => dispose(disposeables)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* File icon themeable tree style */
|
||||
/* File icon themeable OLD tree style */
|
||||
.file-icon-themable-tree .monaco-tree-row .content {
|
||||
display: flex;
|
||||
}
|
||||
@@ -50,6 +50,17 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* File icons in trees */
|
||||
|
||||
.file-icon-themable-tree.align-icons-and-twisties .monaco-tl-twistie:not(.collapsible),
|
||||
.file-icon-themable-tree.hide-arrows .monaco-tl-twistie {
|
||||
background-image: none !important;
|
||||
width: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
|
||||
.monaco-workbench .tree-explorer-viewlet-tree-view {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import 'vs/css!./media/panelviewlet';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Event, Emitter, filterEvent } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { attachStyler, IColorMapping } from 'vs/platform/theme/common/styler';
|
||||
import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER } from 'vs/workbench/common/theme';
|
||||
@@ -52,14 +52,17 @@ export abstract class ViewletPanel extends Panel implements IView {
|
||||
private _onDidBlur = new Emitter<void>();
|
||||
readonly onDidBlur: Event<void> = this._onDidBlur.event;
|
||||
|
||||
private _onDidChangeBodyVisibility = new Emitter<boolean>();
|
||||
readonly onDidChangeBodyVisibility: Event<boolean> = this._onDidChangeBodyVisibility.event;
|
||||
|
||||
protected _onDidChangeTitleArea = new Emitter<void>();
|
||||
readonly onDidChangeTitleArea: Event<void> = this._onDidChangeTitleArea.event;
|
||||
|
||||
private _isVisible: boolean = true;
|
||||
private _isVisible: boolean = false;
|
||||
readonly id: string;
|
||||
readonly title: string;
|
||||
|
||||
protected actionRunner: IActionRunner;
|
||||
protected actionRunner?: IActionRunner;
|
||||
protected toolbar: ToolBar;
|
||||
private headerContainer: HTMLElement;
|
||||
|
||||
@@ -74,11 +77,17 @@ export abstract class ViewletPanel extends Panel implements IView {
|
||||
this.id = options.id;
|
||||
this.title = options.title;
|
||||
this.actionRunner = options.actionRunner;
|
||||
|
||||
this.disposables.push(this._onDidFocus, this._onDidBlur, this._onDidChangeBodyVisibility, this._onDidChangeTitleArea);
|
||||
}
|
||||
|
||||
setVisible(visible: boolean): void {
|
||||
if (this._isVisible !== visible) {
|
||||
this._isVisible = visible;
|
||||
|
||||
if (this.isExpanded()) {
|
||||
this._onDidChangeBodyVisibility.fire(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +95,19 @@ export abstract class ViewletPanel extends Panel implements IView {
|
||||
return this._isVisible;
|
||||
}
|
||||
|
||||
isBodyVisible(): boolean {
|
||||
return this._isVisible && this.isExpanded();
|
||||
}
|
||||
|
||||
setExpanded(expanded: boolean): boolean {
|
||||
const changed = super.setExpanded(expanded);
|
||||
if (changed) {
|
||||
this._onDidChangeBodyVisibility.fire(expanded);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
render(): void {
|
||||
super.render();
|
||||
|
||||
@@ -105,20 +127,20 @@ export abstract class ViewletPanel extends Panel implements IView {
|
||||
orientation: ActionsOrientation.HORIZONTAL,
|
||||
actionItemProvider: action => this.getActionItem(action),
|
||||
ariaLabel: nls.localize('viewToolbarAriaLabel', "{0} actions", this.title),
|
||||
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
|
||||
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id) || undefined,
|
||||
actionRunner: this.actionRunner
|
||||
});
|
||||
|
||||
this.disposables.push(this.toolbar);
|
||||
this.setActions();
|
||||
|
||||
const onDidRelevantConfigurationChange = filterEvent(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ViewletPanel.AlwaysShowActionsConfig));
|
||||
const onDidRelevantConfigurationChange = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ViewletPanel.AlwaysShowActionsConfig));
|
||||
onDidRelevantConfigurationChange(this.updateActionsVisibility, this, this.disposables);
|
||||
this.updateActionsVisibility();
|
||||
}
|
||||
|
||||
protected renderHeaderTitle(container: HTMLElement, title: string): void {
|
||||
append(container, $('h3.title', null, title));
|
||||
append(container, $('h3.title', undefined, title));
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
@@ -151,7 +173,7 @@ export abstract class ViewletPanel extends Panel implements IView {
|
||||
return [];
|
||||
}
|
||||
|
||||
getActionItem(action: IAction): IActionItem {
|
||||
getActionItem(action: IAction): IActionItem | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -237,7 +259,7 @@ export class PanelViewlet extends Viewlet {
|
||||
let title = Registry.as<ViewletRegistry>(Extensions.Viewlets).getViewlet(this.getId()).name;
|
||||
|
||||
if (this.isSingleView()) {
|
||||
title += ': ' + this.panelItems[0].panel.title;
|
||||
title = `${title}: ${this.panelItems[0].panel.title}`;
|
||||
}
|
||||
|
||||
return title;
|
||||
@@ -259,7 +281,7 @@ export class PanelViewlet extends Viewlet {
|
||||
return [];
|
||||
}
|
||||
|
||||
getActionItem(action: IAction): IActionItem {
|
||||
getActionItem(action: IAction): IActionItem | null {
|
||||
if (this.isSingleView()) {
|
||||
return this.panelItems[0].panel.getActionItem(action);
|
||||
}
|
||||
@@ -283,7 +305,7 @@ export class PanelViewlet extends Viewlet {
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): void {
|
||||
this.panelview.layout(dimension.height);
|
||||
this.panelview.layout(dimension.height, dimension.width);
|
||||
}
|
||||
|
||||
getOptimalWidth(): number {
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/views';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IViewsService, ViewsRegistry, IViewsViewlet, ViewContainer, IViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, IView, IViewDescriptorCollection } from 'vs/workbench/common/views';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IContextKeyService, IContextKeyChangeEvent, IReadableSet, IContextKey, RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { Event, chain, filterEvent, Emitter } from 'vs/base/common/event';
|
||||
import { sortedDiff, firstIndex, move } from 'vs/base/common/arrays';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { sortedDiff, firstIndex, move, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { MenuId, MenuRegistry, ICommandAction } from 'vs/platform/actions/common/actions';
|
||||
@@ -19,14 +19,23 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { localize } from 'vs/nls';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import { IFileIconTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { toggleClass, addClass } from 'vs/base/browser/dom';
|
||||
|
||||
function filterViewEvent(container: ViewContainer, event: Event<IViewDescriptor[]>): Event<IViewDescriptor[]> {
|
||||
return chain(event)
|
||||
.map(views => views.filter(view => view.container === container))
|
||||
function filterViewRegisterEvent(container: ViewContainer, event: Event<{ viewContainer: ViewContainer, views: IViewDescriptor[] }>): Event<IViewDescriptor[]> {
|
||||
return Event.chain(event)
|
||||
.map(({ views, viewContainer }) => viewContainer === container ? views : [])
|
||||
.filter(views => views.length > 0)
|
||||
.event;
|
||||
}
|
||||
|
||||
function filterViewMoveEvent(container: ViewContainer, event: Event<{ from: ViewContainer, to: ViewContainer, views: IViewDescriptor[] }>): Event<{ added?: IViewDescriptor[], removed?: IViewDescriptor[] }> {
|
||||
return Event.chain(event)
|
||||
.map(({ views, from, to }) => from === container ? { removed: views } : to === container ? { added: views } : {})
|
||||
.filter(({ added, removed }) => isNonEmptyArray(added) || isNonEmptyArray(removed))
|
||||
.event;
|
||||
}
|
||||
|
||||
class CounterSet<T> implements IReadableSet<T> {
|
||||
|
||||
private map = new Map<T, number>();
|
||||
@@ -84,16 +93,26 @@ class ViewDescriptorCollection extends Disposable implements IViewDescriptorColl
|
||||
|
||||
constructor(
|
||||
container: ViewContainer,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService
|
||||
) {
|
||||
super();
|
||||
const onRelevantViewsRegistered = filterViewEvent(container, ViewsRegistry.onViewsRegistered);
|
||||
const onRelevantViewsRegistered = filterViewRegisterEvent(container, ViewsRegistry.onViewsRegistered);
|
||||
this._register(onRelevantViewsRegistered(this.onViewsRegistered, this));
|
||||
|
||||
const onRelevantViewsDeregistered = filterViewEvent(container, ViewsRegistry.onViewsDeregistered);
|
||||
const onRelevantViewsMoved = filterViewMoveEvent(container, ViewsRegistry.onDidChangeContainer);
|
||||
this._register(onRelevantViewsMoved(({ added, removed }) => {
|
||||
if (isNonEmptyArray(added)) {
|
||||
this.onViewsRegistered(added);
|
||||
}
|
||||
if (isNonEmptyArray(removed)) {
|
||||
this.onViewsDeregistered(removed);
|
||||
}
|
||||
}));
|
||||
|
||||
const onRelevantViewsDeregistered = filterViewRegisterEvent(container, ViewsRegistry.onViewsDeregistered);
|
||||
this._register(onRelevantViewsDeregistered(this.onViewsDeregistered, this));
|
||||
|
||||
const onRelevantContextChange = filterEvent(contextKeyService.onDidChangeContext, e => e.affectsSome(this.contextKeys));
|
||||
const onRelevantContextChange = Event.filter(contextKeyService.onDidChangeContext, e => e.affectsSome(this.contextKeys));
|
||||
this._register(onRelevantContextChange(this.onContextChanged, this));
|
||||
|
||||
this.onViewsRegistered(ViewsRegistry.getViews(container));
|
||||
@@ -204,7 +223,7 @@ export class ContributableViewsModel extends Disposable {
|
||||
|
||||
readonly viewDescriptors: IViewDescriptor[] = [];
|
||||
get visibleViewDescriptors(): IViewDescriptor[] {
|
||||
return this.viewDescriptors.filter(v => this.viewStates.get(v.id).visible);
|
||||
return this.viewDescriptors.filter(v => this.viewStates.get(v.id)!.visible);
|
||||
}
|
||||
|
||||
private _onDidAdd = this._register(new Emitter<IAddedViewDescriptorRef[]>());
|
||||
@@ -224,8 +243,10 @@ export class ContributableViewsModel extends Disposable {
|
||||
super();
|
||||
const viewDescriptorCollection = viewsService.getViewDescriptors(container);
|
||||
|
||||
this._register(viewDescriptorCollection.onDidChangeActiveViews(() => this.onDidChangeViewDescriptors(viewDescriptorCollection.activeViewDescriptors)));
|
||||
this.onDidChangeViewDescriptors(viewDescriptorCollection.activeViewDescriptors);
|
||||
if (viewDescriptorCollection) {
|
||||
this._register(viewDescriptorCollection.onDidChangeActiveViews(() => this.onDidChangeViewDescriptors(viewDescriptorCollection.activeViewDescriptors)));
|
||||
this.onDidChangeViewDescriptors(viewDescriptorCollection.activeViewDescriptors);
|
||||
}
|
||||
}
|
||||
|
||||
isVisible(id: string): boolean {
|
||||
@@ -298,7 +319,7 @@ export class ContributableViewsModel extends Disposable {
|
||||
move(this.viewDescriptors, fromIndex, toIndex);
|
||||
|
||||
for (let index = 0; index < this.viewDescriptors.length; index++) {
|
||||
const state = this.viewStates.get(this.viewDescriptors[index].id);
|
||||
const state = this.viewStates.get(this.viewDescriptors[index].id)!;
|
||||
state.order = index;
|
||||
}
|
||||
|
||||
@@ -312,6 +333,9 @@ export class ContributableViewsModel extends Disposable {
|
||||
for (let i = 0, visibleIndex = 0; i < this.viewDescriptors.length; i++) {
|
||||
const viewDescriptor = this.viewDescriptors[i];
|
||||
const state = this.viewStates.get(viewDescriptor.id);
|
||||
if (!state) {
|
||||
throw new Error(`View state for ${id} not found`);
|
||||
}
|
||||
|
||||
if (viewDescriptor.id === id) {
|
||||
return { index: i, visibleIndex, viewDescriptor, state };
|
||||
@@ -357,7 +381,7 @@ export class ContributableViewsModel extends Disposable {
|
||||
} else {
|
||||
this.viewStates.set(viewDescriptor.id, {
|
||||
visible: !viewDescriptor.hideByDefault,
|
||||
collapsed: viewDescriptor.collapsed
|
||||
collapsed: !!viewDescriptor.collapsed
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -369,7 +393,7 @@ export class ContributableViewsModel extends Disposable {
|
||||
).reverse();
|
||||
|
||||
const toRemove: { index: number, viewDescriptor: IViewDescriptor }[] = [];
|
||||
const toAdd: { index: number, viewDescriptor: IViewDescriptor, size: number, collapsed: boolean }[] = [];
|
||||
const toAdd: { index: number, viewDescriptor: IViewDescriptor, size?: number, collapsed: boolean }[] = [];
|
||||
|
||||
for (const splice of splices) {
|
||||
const startViewDescriptor = this.viewDescriptors[splice.start];
|
||||
@@ -384,9 +408,8 @@ export class ContributableViewsModel extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < splice.toInsert.length; i++) {
|
||||
const viewDescriptor = splice.toInsert[i];
|
||||
const state = this.viewStates.get(viewDescriptor.id);
|
||||
for (const viewDescriptor of splice.toInsert) {
|
||||
const state = this.viewStates.get(viewDescriptor.id)!;
|
||||
|
||||
if (state.visible) {
|
||||
toAdd.push({ index: startIndex++, viewDescriptor, size: state.size, collapsed: state.collapsed });
|
||||
@@ -437,7 +460,7 @@ export class PersistentContributableViewsModel extends ContributableViewsModel {
|
||||
}
|
||||
|
||||
private saveViewsStates(): void {
|
||||
const storedViewsStates: { [id: string]: { collapsed: boolean, size: number, order: number } } = {};
|
||||
const storedViewsStates: { [id: string]: { collapsed: boolean, size?: number, order?: number } } = {};
|
||||
|
||||
let hasState = false;
|
||||
for (const viewDescriptor of this.viewDescriptors) {
|
||||
@@ -460,7 +483,7 @@ export class PersistentContributableViewsModel extends ContributableViewsModel {
|
||||
for (const viewDescriptor of viewDescriptors) {
|
||||
if (viewDescriptor.canToggleVisibility) {
|
||||
const viewState = this.viewStates.get(viewDescriptor.id);
|
||||
storedViewsVisibilityStates.set(viewDescriptor.id, { id: viewDescriptor.id, isHidden: viewState ? !viewState.visible : void 0 });
|
||||
storedViewsVisibilityStates.set(viewDescriptor.id, { id: viewDescriptor.id, isHidden: viewState ? !viewState.visible : false });
|
||||
}
|
||||
}
|
||||
this.storageService.store(this.hiddenViewsStorageId, JSON.stringify(values(storedViewsVisibilityStates)), StorageScope.GLOBAL);
|
||||
@@ -513,34 +536,49 @@ export class ViewsService extends Disposable implements IViewsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private readonly viewDescriptorCollections: Map<ViewContainer, IViewDescriptorCollection>;
|
||||
private readonly viewDescriptorCollections: Map<ViewContainer, { viewDescriptorCollection: IViewDescriptorCollection, disposable: IDisposable }>;
|
||||
private readonly viewDisposable: Map<IViewDescriptor, IDisposable>;
|
||||
private readonly activeViewContextKeys: Map<string, IContextKey<boolean>>;
|
||||
|
||||
constructor(
|
||||
@IViewletService private viewletService: IViewletService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.viewDescriptorCollections = new Map<ViewContainer, IViewDescriptorCollection>();
|
||||
this.viewDescriptorCollections = new Map<ViewContainer, { viewDescriptorCollection: IViewDescriptorCollection, disposable: IDisposable }>();
|
||||
this.viewDisposable = new Map<IViewDescriptor, IDisposable>();
|
||||
this.activeViewContextKeys = new Map<string, IContextKey<boolean>>();
|
||||
|
||||
this.onDidRegisterViews(ViewsRegistry.getAllViews());
|
||||
this._register(ViewsRegistry.onViewsRegistered(views => this.onDidRegisterViews(views)));
|
||||
|
||||
const viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
viewContainersRegistry.all.forEach(viewContainer => this.onDidRegisterViewContainer(viewContainer));
|
||||
viewContainersRegistry.all.forEach(viewContainer => {
|
||||
this.onDidRegisterViews(viewContainer, ViewsRegistry.getViews(viewContainer));
|
||||
this.onDidRegisterViewContainer(viewContainer);
|
||||
});
|
||||
this._register(ViewsRegistry.onViewsRegistered(({ views, viewContainer }) => this.onDidRegisterViews(viewContainer, views)));
|
||||
this._register(ViewsRegistry.onViewsDeregistered(({ views }) => this.onDidDeregisterViews(views)));
|
||||
this._register(ViewsRegistry.onDidChangeContainer(({ views, to }) => { this.onDidDeregisterViews(views); this.onDidRegisterViews(to, views); }));
|
||||
this._register(toDisposable(() => {
|
||||
this.viewDisposable.forEach(disposable => disposable.dispose());
|
||||
this.viewDisposable.clear();
|
||||
}));
|
||||
this._register(viewContainersRegistry.onDidRegister(viewContainer => this.onDidRegisterViewContainer(viewContainer)));
|
||||
this._register(viewContainersRegistry.onDidDeregister(viewContainer => this.onDidDeregisterViewContainer(viewContainer)));
|
||||
this._register(toDisposable(() => {
|
||||
this.viewDescriptorCollections.forEach(({ disposable }) => disposable.dispose());
|
||||
this.viewDescriptorCollections.clear();
|
||||
}));
|
||||
}
|
||||
|
||||
getViewDescriptors(container: ViewContainer): IViewDescriptorCollection {
|
||||
return this.viewDescriptorCollections.get(container);
|
||||
getViewDescriptors(container: ViewContainer): IViewDescriptorCollection | null {
|
||||
const viewDescriptorCollectionItem = this.viewDescriptorCollections.get(container);
|
||||
return viewDescriptorCollectionItem ? viewDescriptorCollectionItem.viewDescriptorCollection : null;
|
||||
}
|
||||
|
||||
openView(id: string, focus: boolean): Thenable<IView> {
|
||||
const viewDescriptor = ViewsRegistry.getView(id);
|
||||
if (viewDescriptor) {
|
||||
const viewletDescriptor = this.viewletService.getViewlet(viewDescriptor.container.id);
|
||||
openView(id: string, focus: boolean): Promise<IView | null> {
|
||||
const viewContainer = ViewsRegistry.getViewContainer(id);
|
||||
if (viewContainer) {
|
||||
const viewletDescriptor = this.viewletService.getViewlet(viewContainer.id);
|
||||
if (viewletDescriptor) {
|
||||
return this.viewletService.openViewlet(viewletDescriptor.id, focus)
|
||||
.then((viewlet: IViewsViewlet) => {
|
||||
@@ -555,12 +593,21 @@ export class ViewsService extends Disposable implements IViewsService {
|
||||
}
|
||||
|
||||
private onDidRegisterViewContainer(viewContainer: ViewContainer): void {
|
||||
const viewDescriptorCollection = this._register(new ViewDescriptorCollection(viewContainer, this.contextKeyService));
|
||||
const viewDescriptorCollection = new ViewDescriptorCollection(viewContainer, this.contextKeyService);
|
||||
const disposables: IDisposable[] = [viewDescriptorCollection];
|
||||
|
||||
this.onDidChangeActiveViews({ added: viewDescriptorCollection.activeViewDescriptors, removed: [] });
|
||||
this._register(viewDescriptorCollection.onDidChangeActiveViews(changed => this.onDidChangeActiveViews(changed)));
|
||||
viewDescriptorCollection.onDidChangeActiveViews(changed => this.onDidChangeActiveViews(changed), this, disposables);
|
||||
|
||||
this.viewDescriptorCollections.set(viewContainer, viewDescriptorCollection);
|
||||
this.viewDescriptorCollections.set(viewContainer, { viewDescriptorCollection, disposable: toDisposable(() => dispose(disposables)) });
|
||||
}
|
||||
|
||||
private onDidDeregisterViewContainer(viewContainer: ViewContainer): void {
|
||||
const viewDescriptorCollectionItem = this.viewDescriptorCollections.get(viewContainer);
|
||||
if (viewDescriptorCollectionItem) {
|
||||
viewDescriptorCollectionItem.disposable.dispose();
|
||||
this.viewDescriptorCollections.delete(viewContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private onDidChangeActiveViews({ added, removed }: { added: IViewDescriptor[], removed: IViewDescriptor[] }): void {
|
||||
@@ -568,9 +615,10 @@ export class ViewsService extends Disposable implements IViewsService {
|
||||
removed.forEach(viewDescriptor => this.getOrCreateActiveViewContextKey(viewDescriptor).set(false));
|
||||
}
|
||||
|
||||
private onDidRegisterViews(viewDescriptors: IViewDescriptor[]): void {
|
||||
for (const viewDescriptor of viewDescriptors) {
|
||||
const viewlet = this.viewletService.getViewlet(viewDescriptor.container.id);
|
||||
private onDidRegisterViews(container: ViewContainer, views: IViewDescriptor[]): void {
|
||||
const viewlet = this.viewletService.getViewlet(container.id);
|
||||
for (const viewDescriptor of views) {
|
||||
const disposables: IDisposable[] = [];
|
||||
const command: ICommandAction = {
|
||||
id: viewDescriptor.focusCommand ? viewDescriptor.focusCommand.id : `${viewDescriptor.id}.focus`,
|
||||
title: { original: `Focus on ${viewDescriptor.name} View`, value: localize('focus view', "Focus on {0} View", viewDescriptor.name) },
|
||||
@@ -578,12 +626,12 @@ export class ViewsService extends Disposable implements IViewsService {
|
||||
};
|
||||
const when = ContextKeyExpr.has(`${viewDescriptor.id}.active`);
|
||||
|
||||
CommandsRegistry.registerCommand(command.id, () => this.openView(viewDescriptor.id, true).then(() => null));
|
||||
disposables.push(CommandsRegistry.registerCommand(command.id, () => this.openView(viewDescriptor.id, true).then(() => null)));
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
disposables.push(MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
command,
|
||||
when
|
||||
});
|
||||
}));
|
||||
|
||||
if (viewDescriptor.focusCommand && viewDescriptor.focusCommand.keybindings) {
|
||||
KeybindingsRegistry.registerKeybindingRule({
|
||||
@@ -597,6 +645,18 @@ export class ViewsService extends Disposable implements IViewsService {
|
||||
win: viewDescriptor.focusCommand.keybindings.win
|
||||
});
|
||||
}
|
||||
|
||||
this.viewDisposable.set(viewDescriptor, toDisposable(() => dispose(disposables)));
|
||||
}
|
||||
}
|
||||
|
||||
private onDidDeregisterViews(views: IViewDescriptor[]): void {
|
||||
for (const view of views) {
|
||||
const disposable = this.viewDisposable.get(view);
|
||||
if (disposable) {
|
||||
disposable.dispose();
|
||||
this.viewDisposable.delete(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -610,3 +670,16 @@ export class ViewsService extends Disposable implements IViewsService {
|
||||
return contextKey;
|
||||
}
|
||||
}
|
||||
|
||||
export function createFileIconThemableTreeContainerScope(container: HTMLElement, themeService: IWorkbenchThemeService): IDisposable {
|
||||
addClass(container, 'file-icon-themable-tree');
|
||||
addClass(container, 'show-file-icons');
|
||||
|
||||
const onDidChangeFileIconTheme = (theme: IFileIconTheme) => {
|
||||
toggleClass(container, 'align-icons-and-twisties', theme.hasFileIcons && !theme.hasFolderIcons);
|
||||
toggleClass(container, 'hide-arrows', theme.hidesExplorerArrows === true);
|
||||
};
|
||||
|
||||
onDidChangeFileIconTheme(themeService.getFileIconTheme());
|
||||
return themeService.onDidFileIconThemeChange(onDidChangeFileIconTheme);
|
||||
}
|
||||
@@ -23,83 +23,13 @@ import { DefaultPanelDndController } from 'vs/base/browser/ui/splitview/panelvie
|
||||
import { WorkbenchTree, IListService } from 'vs/platform/list/browser/listService';
|
||||
import { IWorkbenchThemeService, IFileIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree';
|
||||
import { latch, mapEvent } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IAddedViewDescriptorRef, IViewDescriptorRef, PersistentContributableViewsModel } from 'vs/workbench/browser/parts/views/views';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
|
||||
export abstract class TreeViewsViewletPanel extends ViewletPanel {
|
||||
|
||||
protected tree: WorkbenchTree;
|
||||
|
||||
setExpanded(expanded: boolean): void {
|
||||
if (this.isExpanded() !== expanded) {
|
||||
this.updateTreeVisibility(this.tree, expanded);
|
||||
super.setExpanded(expanded);
|
||||
}
|
||||
}
|
||||
|
||||
setVisible(visible: boolean): void {
|
||||
if (this.isVisible() !== visible) {
|
||||
super.setVisible(visible);
|
||||
this.updateTreeVisibility(this.tree, visible && this.isExpanded());
|
||||
}
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
super.focus();
|
||||
this.focusTree();
|
||||
}
|
||||
|
||||
layoutBody(size: number): void {
|
||||
if (this.tree) {
|
||||
this.tree.layout(size);
|
||||
}
|
||||
}
|
||||
|
||||
protected updateTreeVisibility(tree: WorkbenchTree, isVisible: boolean): void {
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isVisible) {
|
||||
DOM.show(tree.getHTMLElement());
|
||||
} else {
|
||||
DOM.hide(tree.getHTMLElement()); // make sure the tree goes out of the tabindex world by hiding it
|
||||
}
|
||||
|
||||
if (isVisible) {
|
||||
tree.onVisible();
|
||||
} else {
|
||||
tree.onHidden();
|
||||
}
|
||||
}
|
||||
|
||||
private focusTree(): void {
|
||||
if (!this.tree) {
|
||||
return; // return early if viewlet has not yet been created
|
||||
}
|
||||
|
||||
// Make sure the current selected element is revealed
|
||||
const selectedElement = this.tree.getSelection()[0];
|
||||
if (selectedElement) {
|
||||
this.tree.reveal(selectedElement);
|
||||
}
|
||||
|
||||
// Pass Focus to Viewer
|
||||
this.tree.domFocus();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
if (this.tree) {
|
||||
this.tree.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export interface IViewletViewOptions extends IViewletPanelOptions {
|
||||
viewletState: object;
|
||||
}
|
||||
@@ -274,7 +204,7 @@ export abstract class ViewContainerViewlet extends PanelViewlet implements IView
|
||||
this.onContextMenu(new StandardMouseEvent(e), viewDescriptor);
|
||||
});
|
||||
|
||||
const collapseDisposable = latch(mapEvent(panel.onDidChange, () => !panel.isExpanded()))(collapsed => {
|
||||
const collapseDisposable = Event.latch(Event.map(panel.onDidChange, () => !panel.isExpanded()))(collapsed => {
|
||||
this.viewsModel.setCollapsed(viewDescriptor.id, collapsed);
|
||||
});
|
||||
|
||||
@@ -284,7 +214,13 @@ export abstract class ViewContainerViewlet extends PanelViewlet implements IView
|
||||
|
||||
this.addPanels(panelsToAdd);
|
||||
this.restoreViewSizes();
|
||||
return panelsToAdd.map(({ panel }) => panel);
|
||||
|
||||
const panels: ViewletPanel[] = [];
|
||||
for (const { panel } of panelsToAdd) {
|
||||
panel.setVisible(this.isVisible());
|
||||
panels.push(panel);
|
||||
}
|
||||
return panels;
|
||||
}
|
||||
|
||||
private onDidRemoveViews(removed: IViewDescriptorRef[]): void {
|
||||
|
||||
@@ -43,14 +43,14 @@ export class QuickOpenHandler {
|
||||
* As such, returning the same model instance across multiple searches will yield best
|
||||
* results in terms of performance when many items are shown.
|
||||
*/
|
||||
getResults(searchValue: string, token: CancellationToken): Thenable<IModel<any>> {
|
||||
getResults(searchValue: string, token: CancellationToken): Promise<IModel<any> | null> {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ARIA label to apply when this quick open handler is active in quick open.
|
||||
*/
|
||||
getAriaLabel(): string {
|
||||
getAriaLabel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ export class QuickOpenAction extends Action {
|
||||
id: string,
|
||||
label: string,
|
||||
prefix: string,
|
||||
@IQuickOpenService private quickOpenService: IQuickOpenService
|
||||
@IQuickOpenService private readonly quickOpenService: IQuickOpenService
|
||||
) {
|
||||
super(id, label);
|
||||
|
||||
@@ -330,6 +330,6 @@ export class QuickOpenAction extends Action {
|
||||
// Show with prefix
|
||||
this.quickOpenService.show(this.prefix);
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,12 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IViewlet } from 'vs/workbench/common/viewlet';
|
||||
import { Composite, CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite';
|
||||
import { IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ToggleSidebarVisibilityAction } from 'vs/workbench/browser/actions/toggleSidebarVisibility';
|
||||
import { ToggleSidebarVisibilityAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/toggleSidebarPosition';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
|
||||
@@ -35,7 +34,7 @@ export abstract class Viewlet extends Composite implements IViewlet {
|
||||
super(id, telemetryService, themeService, storageService);
|
||||
}
|
||||
|
||||
getOptimalWidth(): number {
|
||||
getOptimalWidth(): number | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -67,7 +66,7 @@ export class ViewletDescriptor extends CompositeDescriptor<Viewlet> {
|
||||
super(ctor, id, name, cssClass, order, id);
|
||||
}
|
||||
|
||||
get iconUrl(): URI {
|
||||
get iconUrl(): URI | undefined {
|
||||
return this._iconUrl;
|
||||
}
|
||||
}
|
||||
@@ -86,6 +85,16 @@ export class ViewletRegistry extends CompositeRegistry<Viewlet> {
|
||||
super.registerComposite(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregisters a viewlet to the platform.
|
||||
*/
|
||||
deregisterViewlet(id: string): void {
|
||||
if (id === this.defaultViewletId) {
|
||||
throw new Error('Cannot deregister default viewlet');
|
||||
}
|
||||
super.deregisterComposite(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the viewlet descriptor for the given id or null if none.
|
||||
*/
|
||||
@@ -128,8 +137,8 @@ export class ShowViewletAction extends Action {
|
||||
name: string,
|
||||
viewletId: string,
|
||||
@IViewletService protected viewletService: IViewletService,
|
||||
@IEditorGroupsService private editorGroupService: IEditorGroupsService,
|
||||
@IPartService private partService: IPartService
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IPartService private readonly partService: IPartService
|
||||
) {
|
||||
super(id, name);
|
||||
|
||||
@@ -137,7 +146,7 @@ export class ShowViewletAction extends Action {
|
||||
this.enabled = !!this.viewletService && !!this.editorGroupService;
|
||||
}
|
||||
|
||||
run(): Thenable<any> {
|
||||
run(): Promise<any> {
|
||||
|
||||
// Pass focus to viewlet if not open or focused
|
||||
if (this.otherViewletShowing() || !this.sidebarHasFocus()) {
|
||||
@@ -160,7 +169,7 @@ export class ShowViewletAction extends Action {
|
||||
const activeViewlet = this.viewletService.getActiveViewlet();
|
||||
const activeElement = document.activeElement;
|
||||
|
||||
return activeViewlet && activeElement && DOM.isAncestor(activeElement, this.partService.getContainer(Parts.SIDEBAR_PART));
|
||||
return !!(activeViewlet && activeElement && DOM.isAncestor(activeElement, this.partService.getContainer(Parts.SIDEBAR_PART)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +195,7 @@ export class CollapseAction extends Action {
|
||||
|
||||
// Collapse All action for the new tree
|
||||
export class CollapseAction2 extends Action {
|
||||
constructor(tree: AsyncDataTree<any>, enabled: boolean, clazz: string) {
|
||||
constructor(tree: AsyncDataTree<any, any, any>, enabled: boolean, clazz: string) {
|
||||
super('workbench.action.collapse', nls.localize('collapse', "Collapse All"), clazz, enabled, () => {
|
||||
tree.collapseAll();
|
||||
return Promise.resolve(undefined);
|
||||
|
||||
287
src/vs/workbench/browser/workbench.contribution.ts
Normal file
287
src/vs/workbench/browser/workbench.contribution.ts
Normal file
@@ -0,0 +1,287 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
|
||||
// Configuration: Workbench
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': 'workbench',
|
||||
'order': 7,
|
||||
'title': nls.localize('workbenchConfigurationTitle', "Workbench"),
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'workbench.editor.showTabs': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('showEditorTabs', "Controls whether opened editors should show in tabs or not."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.highlightModifiedTabs': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('highlightModifiedTabs', "Controls whether a top border is drawn on modified (dirty) editor tabs or not."),
|
||||
'default': false
|
||||
},
|
||||
'workbench.editor.labelFormat': {
|
||||
'type': 'string',
|
||||
'enum': ['default', 'short', 'medium', 'long'],
|
||||
'enumDescriptions': [
|
||||
nls.localize('workbench.editor.labelFormat.default', "Show the name of the file. When tabs are enabled and two files have the same name in one group the distinguishing sections of each file's path are added. When tabs are disabled, the path relative to the workspace folder is shown if the editor is active."),
|
||||
nls.localize('workbench.editor.labelFormat.short', "Show the name of the file followed by its directory name."),
|
||||
nls.localize('workbench.editor.labelFormat.medium', "Show the name of the file followed by its path relative to the workspace folder."),
|
||||
nls.localize('workbench.editor.labelFormat.long', "Show the name of the file followed by its absolute path.")
|
||||
],
|
||||
'default': 'default',
|
||||
'description': nls.localize({
|
||||
comment: ['This is the description for a setting. Values surrounded by parenthesis are not to be translated.'],
|
||||
key: 'tabDescription'
|
||||
}, "Controls the format of the label for an editor."),
|
||||
},
|
||||
'workbench.editor.tabCloseButton': {
|
||||
'type': 'string',
|
||||
'enum': ['left', 'right', 'off'],
|
||||
'default': 'right',
|
||||
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons, or disables them when set to 'off'.")
|
||||
},
|
||||
'workbench.editor.tabSizing': {
|
||||
'type': 'string',
|
||||
'enum': ['fit', 'shrink'],
|
||||
'default': 'fit',
|
||||
'enumDescriptions': [
|
||||
nls.localize('workbench.editor.tabSizing.fit', "Always keep tabs large enough to show the full editor label."),
|
||||
nls.localize('workbench.editor.tabSizing.shrink', "Allow tabs to get smaller when the available space is not enough to show all tabs at once.")
|
||||
],
|
||||
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabSizing' }, "Controls the sizing of editor tabs.")
|
||||
},
|
||||
'workbench.editor.focusRecentEditorAfterClose': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('focusRecentEditorAfterClose', "Controls whether tabs are closed in most recently used order or from left to right."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.showIcons': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('showIcons', "Controls whether opened editors should show with an icon or not. This requires an icon theme to be enabled as well."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.enablePreview': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('enablePreview', "Controls whether opened editors show as preview. Preview editors are reused until they are pinned (e.g. via double click or editing) and show up with an italic font style."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.enablePreviewFromQuickOpen': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('enablePreviewFromQuickOpen', "Controls whether opened editors from Quick Open show as preview. Preview editors are reused until they are pinned (e.g. via double click or editing)."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.closeOnFileDelete': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('closeOnFileDelete', "Controls whether editors showing a file that was opened during the session should close automatically when getting deleted or renamed by some other process. Disabling this will keep the editor open on such an event. Note that deleting from within the application will always close the editor and that dirty files will never close to preserve your data."),
|
||||
'default': false
|
||||
},
|
||||
'workbench.editor.openPositioning': {
|
||||
'type': 'string',
|
||||
'enum': ['left', 'right', 'first', 'last'],
|
||||
'default': 'right',
|
||||
'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorOpenPositioning' }, "Controls where editors open. Select `left` or `right` to open editors to the left or right of the currently active one. Select `first` or `last` to open editors independently from the currently active one.")
|
||||
},
|
||||
'workbench.editor.openSideBySideDirection': {
|
||||
'type': 'string',
|
||||
'enum': ['right', 'down'],
|
||||
'default': 'right',
|
||||
'markdownDescription': nls.localize('sideBySideDirection', "Controls the default direction of editors that are opened side by side (e.g. from the explorer). By default, editors will open on the right hand side of the currently active one. If changed to `down`, the editors will open below the currently active one.")
|
||||
},
|
||||
'workbench.editor.closeEmptyGroups': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('closeEmptyGroups', "Controls the behavior of empty editor groups when the last tab in the group is closed. When enabled, empty groups will automatically close. When disabled, empty groups will remain part of the grid."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.revealIfOpen': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('revealIfOpen', "Controls whether an editor is revealed in any of the visible groups if opened. If disabled, an editor will prefer to open in the currently active editor group. If enabled, an already opened editor will be revealed instead of opened again in the currently active editor group. Note that there are some cases where this setting is ignored, e.g. when forcing an editor to open in a specific group or to the side of the currently active group."),
|
||||
'default': false
|
||||
},
|
||||
'workbench.editor.swipeToNavigate': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('swipeToNavigate', "Navigate between open files using three-finger swipe horizontally."),
|
||||
'default': false,
|
||||
'included': isMacintosh
|
||||
},
|
||||
'workbench.editor.restoreViewState': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('restoreViewState', "Restores the last view state (e.g. scroll position) when re-opening files after they have been closed."),
|
||||
'default': true,
|
||||
},
|
||||
'workbench.editor.centeredLayoutAutoResize': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('centeredLayoutAutoResize', "Controls if the centered layout should automatically resize to maximum width when more than one group is open. Once only one group is open it will resize back to the original centered width.")
|
||||
},
|
||||
'workbench.commandPalette.history': {
|
||||
'type': 'number',
|
||||
'description': nls.localize('commandHistory', "Controls the number of recently used commands to keep in history for the command palette. Set to 0 to disable command history."),
|
||||
'default': 50
|
||||
},
|
||||
'workbench.commandPalette.preserveInput': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('preserveInput', "Controls whether the last typed input to the command palette should be restored when opening it the next time."),
|
||||
'default': false
|
||||
},
|
||||
'workbench.quickOpen.closeOnFocusLost': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('closeOnFocusLost', "Controls whether Quick Open should close automatically once it loses focus."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.quickOpen.preserveInput': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('workbench.quickOpen.preserveInput', "Controls whether the last typed input to Quick Open should be restored when opening it the next time."),
|
||||
'default': false
|
||||
},
|
||||
'workbench.settings.openDefaultSettings': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('openDefaultSettings', "Controls whether opening settings also opens an editor showing all default settings."),
|
||||
'default': false
|
||||
},
|
||||
'workbench.settings.useSplitJSON': {
|
||||
'type': 'boolean',
|
||||
'markdownDescription': nls.localize('useSplitJSON', "Controls whether to use the split JSON editor when editing settings as JSON."),
|
||||
'default': false
|
||||
},
|
||||
'workbench.settings.openDefaultKeybindings': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('openDefaultKeybindings', "Controls whether opening keybinding settings also opens an editor showing all default keybindings."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.sideBar.location': {
|
||||
'type': 'string',
|
||||
'enum': ['left', 'right'],
|
||||
'default': 'left',
|
||||
'description': nls.localize('sideBarLocation', "Controls the location of the sidebar. It can either show on the left or right of the workbench.")
|
||||
},
|
||||
'workbench.panel.defaultLocation': {
|
||||
'type': 'string',
|
||||
'enum': ['bottom', 'right'],
|
||||
'default': 'bottom',
|
||||
'description': nls.localize('panelDefaultLocation', "Controls the default location of the panel (terminal, debug console, output, problems). It can either show at the bottom or on the right of the workbench.")
|
||||
},
|
||||
'workbench.statusBar.visible': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('statusBarVisibility', "Controls the visibility of the status bar at the bottom of the workbench.")
|
||||
},
|
||||
'workbench.activityBar.visible': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('activityBarVisibility', "Controls the visibility of the activity bar in the workbench.")
|
||||
},
|
||||
'workbench.view.alwaysShowHeaderActions': {
|
||||
'type': 'boolean',
|
||||
'default': false,
|
||||
'description': nls.localize('viewVisibility', "Controls the visibility of view header actions. View header actions may either be always visible, or only visible when that view is focused or hovered over.")
|
||||
},
|
||||
'workbench.fontAliasing': {
|
||||
'type': 'string',
|
||||
'enum': ['default', 'antialiased', 'none', 'auto'],
|
||||
'default': 'default',
|
||||
'description':
|
||||
nls.localize('fontAliasing', "Controls font aliasing method in the workbench."),
|
||||
'enumDescriptions': [
|
||||
nls.localize('workbench.fontAliasing.default', "Sub-pixel font smoothing. On most non-retina displays this will give the sharpest text."),
|
||||
nls.localize('workbench.fontAliasing.antialiased', "Smooth the font on the level of the pixel, as opposed to the subpixel. Can make the font appear lighter overall."),
|
||||
nls.localize('workbench.fontAliasing.none', "Disables font smoothing. Text will show with jagged sharp edges."),
|
||||
nls.localize('workbench.fontAliasing.auto', "Applies `default` or `antialiased` automatically based on the DPI of displays.")
|
||||
],
|
||||
'included': isMacintosh
|
||||
},
|
||||
'workbench.settings.enableNaturalLanguageSearch': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('enableNaturalLanguageSettingsSearch', "Controls whether to enable the natural language search mode for settings. The natural language search is provided by a Microsoft online service."),
|
||||
'default': true,
|
||||
'scope': ConfigurationScope.WINDOW,
|
||||
'tags': ['usesOnlineServices']
|
||||
},
|
||||
'workbench.settings.settingsSearchTocBehavior': {
|
||||
'type': 'string',
|
||||
'enum': ['hide', 'filter'],
|
||||
'enumDescriptions': [
|
||||
nls.localize('settingsSearchTocBehavior.hide', "Hide the Table of Contents while searching."),
|
||||
nls.localize('settingsSearchTocBehavior.filter', "Filter the Table of Contents to just categories that have matching settings. Clicking a category will filter the results to that category."),
|
||||
],
|
||||
'description': nls.localize('settingsSearchTocBehavior', "Controls the behavior of the settings editor Table of Contents while searching."),
|
||||
'default': 'filter',
|
||||
'scope': ConfigurationScope.WINDOW
|
||||
},
|
||||
'workbench.settings.editor': {
|
||||
'type': 'string',
|
||||
'enum': ['ui', 'json'],
|
||||
'enumDescriptions': [
|
||||
nls.localize('settings.editor.ui', "Use the settings UI editor."),
|
||||
nls.localize('settings.editor.json', "Use the JSON file editor."),
|
||||
],
|
||||
'description': nls.localize('settings.editor.desc', "Determines which settings editor to use by default."),
|
||||
'default': 'ui',
|
||||
'scope': ConfigurationScope.WINDOW
|
||||
},
|
||||
'workbench.enableExperiments': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('workbench.enableExperiments', "Fetches experiments to run from a Microsoft online service."),
|
||||
'default': true,
|
||||
'tags': ['usesOnlineServices']
|
||||
},
|
||||
'workbench.useExperimentalGridLayout': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('workbench.useExperimentalGridLayout', "Enables the grid layout for the workbench. This setting may enable additional layout options for workbench components."),
|
||||
'default': false,
|
||||
'scope': ConfigurationScope.APPLICATION
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Configuration: Zen Mode
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': 'zenMode',
|
||||
'order': 9,
|
||||
'title': nls.localize('zenModeConfigurationTitle', "Zen Mode"),
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'zenMode.fullScreen': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('zenMode.fullScreen', "Controls whether turning on Zen Mode also puts the workbench into full screen mode.")
|
||||
},
|
||||
'zenMode.centerLayout': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('zenMode.centerLayout', "Controls whether turning on Zen Mode also centers the layout.")
|
||||
},
|
||||
'zenMode.hideTabs': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('zenMode.hideTabs', "Controls whether turning on Zen Mode also hides workbench tabs.")
|
||||
},
|
||||
'zenMode.hideStatusBar': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('zenMode.hideStatusBar', "Controls whether turning on Zen Mode also hides the status bar at the bottom of the workbench.")
|
||||
},
|
||||
'zenMode.hideActivityBar': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('zenMode.hideActivityBar', "Controls whether turning on Zen Mode also hides the activity bar at the left of the workbench.")
|
||||
},
|
||||
'zenMode.hideLineNumbers': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
'description': nls.localize('zenMode.hideLineNumbers', "Controls whether turning on Zen Mode also hides the editor line numbers.")
|
||||
},
|
||||
'zenMode.restore': {
|
||||
'type': 'boolean',
|
||||
'default': false,
|
||||
'description': nls.localize('zenMode.restore', "Controls whether a window should restore to zen mode if it was exited in zen mode.")
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user