Merge from vscode bd0efff9e3f36d6b3e1045cee9887003af8034d7

This commit is contained in:
ADS Merger
2020-05-06 02:35:49 +00:00
parent 9a7810cbee
commit 8420d9f04e
243 changed files with 4276 additions and 2478 deletions

View File

@@ -487,7 +487,7 @@ export class ResetViewLocationsAction extends Action {
}
async run(): Promise<void> {
this.viewDescriptorService.getViewContainers().forEach(viewContainer => {
this.viewDescriptorService.viewContainers.forEach(viewContainer => {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
viewContainerModel.allViewDescriptors.forEach(viewDescriptor => {
@@ -596,7 +596,7 @@ export class MoveFocusedViewAction extends Action {
});
}
const pinnedViewlets = this.activityBarService.getPinnedViewletIds();
const pinnedViewlets = this.activityBarService.getPinnedViewContainerIds();
items.push(...pinnedViewlets
.filter(viewletId => {
if (viewletId === this.viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) {

View File

@@ -7,7 +7,6 @@ import * as nls from 'vs/nls';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import * as resources from 'vs/base/common/resources';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { CancellationToken } from 'vs/base/common/cancellation';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
@@ -19,6 +18,7 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views';
export const ADD_ROOT_FOLDER_COMMAND_ID = 'addRootFolder';
export const ADD_ROOT_FOLDER_LABEL = nls.localize('addFolderToWorkspace', "Add Folder to Workspace...");
@@ -55,7 +55,8 @@ CommandsRegistry.registerCommand({
CommandsRegistry.registerCommand({
id: ADD_ROOT_FOLDER_COMMAND_ID,
handler: async (accessor) => {
const viewletService = accessor.get(IViewletService);
const viewDescriptorService = accessor.get(IViewDescriptorService);
const viewsService = accessor.get(IViewsService);
const workspaceEditingService = accessor.get(IWorkspaceEditingService);
const dialogsService = accessor.get(IFileDialogService);
const folders = await dialogsService.showOpenDialog({
@@ -71,7 +72,7 @@ CommandsRegistry.registerCommand({
}
await workspaceEditingService.addFolders(folders.map(folder => ({ uri: resources.removeTrailingPathSeparator(folder) })));
await viewletService.openViewlet(viewletService.getDefaultViewletId(), true);
await viewsService.openViewContainer(viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)!.id, true);
}
});

View File

@@ -15,7 +15,6 @@ import { trackFocus, Dimension } from 'vs/base/browser/dom';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { Disposable } from 'vs/base/common/lifecycle';
import { assertIsDefined } from 'vs/base/common/types';
import { find } from 'vs/base/common/arrays';
/**
* Composites are layed out in the sidebar and panel part of the workbench. At a time only one composite
@@ -256,7 +255,7 @@ export abstract class CompositeRegistry<T extends Composite> extends Disposable
private readonly _onDidDeregister = this._register(new Emitter<CompositeDescriptor<T>>());
readonly onDidDeregister = this._onDidDeregister.event;
private composites: CompositeDescriptor<T>[] = [];
private readonly composites: CompositeDescriptor<T>[] = [];
protected registerComposite(descriptor: CompositeDescriptor<T>): void {
if (this.compositeById(descriptor.id)) {
@@ -286,6 +285,6 @@ export abstract class CompositeRegistry<T extends Composite> extends Disposable
}
private compositeById(id: string): CompositeDescriptor<T> | undefined {
return find(this.composites, composite => composite.id === id);
return this.composites.find(composite => composite.id === id);
}
}

View File

@@ -8,7 +8,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { Registry } from 'vs/platform/registry/common/platform';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IConstructorSignature0, IInstantiationService, BrandedService } from 'vs/platform/instantiation/common/instantiation';
import { find, insert } from 'vs/base/common/arrays';
import { insert } from 'vs/base/common/arrays';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
export interface IEditorDescriptor {
@@ -154,7 +154,7 @@ class EditorRegistry implements IEditorRegistry {
}
getEditorById(editorId: string): EditorDescriptor | undefined {
return find(this.editors, editor => editor.getId() === editorId);
return this.editors.find(editor => editor.getId() === editorId);
}
getEditors(): readonly EditorDescriptor[] {

View File

@@ -43,6 +43,7 @@ import { WINDOW_ACTIVE_BORDER, WINDOW_INACTIVE_BORDER } from 'vs/workbench/commo
import { LineNumbersType } from 'vs/editor/common/config/editorOptions';
import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart';
import { URI } from 'vs/base/common/uri';
import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
export enum Settings {
ACTIVITYBAR_VISIBLE = 'workbench.activityBar.visible',
@@ -171,6 +172,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
private panelService!: IPanelService;
private titleService!: ITitleService;
private viewletService!: IViewletService;
private viewDescriptorService!: IViewDescriptorService;
private contextService!: IWorkspaceContextService;
private backupFileService!: IBackupFileService;
private notificationService!: INotificationService;
@@ -255,6 +257,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
this.editorGroupService = accessor.get(IEditorGroupsService);
this.panelService = accessor.get(IPanelService);
this.viewletService = accessor.get(IViewletService);
this.viewDescriptorService = accessor.get(IViewDescriptorService);
this.titleService = accessor.get(ITitleService);
this.notificationService = accessor.get(INotificationService);
accessor.get(IStatusbarService); // not used, but called to ensure instantiated
@@ -489,11 +492,11 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
if (!this.state.sideBar.hidden) {
// Only restore last viewlet if window was reloaded or we are in development mode
let viewletToRestore: string;
let viewletToRestore: string | undefined;
if (!this.environmentService.isBuilt || lifecycleService.startupKind === StartupKind.ReloadedWindow || isWeb) {
viewletToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, this.viewletService.getDefaultViewletId());
viewletToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, this.viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id);
} else {
viewletToRestore = this.viewletService.getDefaultViewletId();
viewletToRestore = this.viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id;
}
if (viewletToRestore) {
@@ -639,7 +642,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
if (sidebarState.length) {
storageService.store(ActivitybarPart.PINNED_VIEWLETS, JSON.stringify(sidebarState), StorageScope.GLOBAL);
storageService.store(ActivitybarPart.PINNED_VIEW_CONTAINERS, JSON.stringify(sidebarState), StorageScope.GLOBAL);
}
}
}
@@ -1344,7 +1347,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
if (viewletToOpen) {
const viewlet = this.viewletService.openViewlet(viewletToOpen, true);
if (!viewlet) {
this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true);
this.viewletService.openViewlet(this.viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id, true);
}
}
}

View File

@@ -19,7 +19,6 @@
width: 100%;
height: 100%;
backdrop-filter: brightness(97%) blur(2px);
pointer-events: none;
visibility: hidden;
opacity: 0;
transition: opacity .5s, visibility .5s;

View File

@@ -11,7 +11,6 @@ import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch
import { Action, IAction } from 'vs/base/common/actions';
import { KeyCode } from 'vs/base/common/keyCodes';
import { dispose } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { SyncActionDescriptor, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -19,7 +18,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry';
import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { ActivityAction, ActivityActionViewItem, ICompositeBar, ICompositeBarColors, ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
import { IActivity } from 'vs/workbench/common/activity';
import { ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_ACTIVE_FOCUS_BORDER, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_BACKGROUND } from 'vs/workbench/common/theme';
@@ -30,9 +28,8 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { Codicon } from 'vs/base/common/codicons';
import { isString } from 'vs/base/common/types';
export class ViewletActivityAction extends ActivityAction {
export class ViewContainerActivityAction extends ActivityAction {
private static readonly preventDoubleClickDelay = 300;
@@ -48,7 +45,6 @@ export class ViewletActivityAction extends ActivityAction {
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ITelemetryService telemetryService: ITelemetryService
) {
ViewletActivityAction.generateIconCSS(activity);
super(activity);
this.lastRun = 0;
@@ -57,23 +53,7 @@ export class ViewletActivityAction extends ActivityAction {
this.telemetryService = telemetryService;
}
private static generateIconCSS(activity: IActivity): void {
if (activity.iconUrl) {
activity.cssClass = activity.cssClass || `activity-${activity.id.replace(/\./g, '-')}`;
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${activity.cssClass}`;
DOM.createCSSRule(iconClass, `
mask: ${DOM.asCSSUrl(activity.iconUrl)} no-repeat 50% 50%;
mask-size: 24px;
-webkit-mask: ${DOM.asCSSUrl(activity.iconUrl)} no-repeat 50% 50%;
-webkit-mask-size: 24px;
`);
}
}
setActivity(activity: IActivity): void {
if (activity.iconUrl && this.activity.cssClass !== activity.cssClass) {
ViewletActivityAction.generateIconCSS(activity);
}
updateActivity(activity: IActivity): void {
this.activity = activity;
}
@@ -84,7 +64,7 @@ export class ViewletActivityAction extends ActivityAction {
// prevent accident trigger on a doubleclick (to help nervous people)
const now = Date.now();
if (now > this.lastRun /* https://github.com/Microsoft/vscode/issues/25830 */ && now - this.lastRun < ViewletActivityAction.preventDoubleClickDelay) {
if (now > this.lastRun /* https://github.com/Microsoft/vscode/issues/25830 */ && now - this.lastRun < ViewContainerActivityAction.preventDoubleClickDelay) {
return;
}
this.lastRun = now;
@@ -113,30 +93,6 @@ export class ViewletActivityAction extends ActivityAction {
}
}
export class ToggleViewletAction extends Action {
constructor(
private _viewlet: ViewletDescriptor,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@IViewletService private readonly viewletService: IViewletService
) {
super(_viewlet.id, _viewlet.name);
}
async run(): Promise<void> {
const sideBarVisible = this.layoutService.isVisible(Parts.SIDEBAR_PART);
const activeViewlet = this.viewletService.getActiveViewlet();
// Hide sidebar if selected viewlet already visible
if (sideBarVisible && activeViewlet?.getId() === this._viewlet.id) {
this.layoutService.setSideBarHidden(true);
return;
}
await this.viewletService.openViewlet(this._viewlet.id, true);
}
}
export class AccountsActionViewItem extends ActivityActionViewItem {
constructor(
action: ActivityAction,
@@ -248,23 +204,7 @@ export class GlobalActivityActionViewItem extends ActivityActionViewItem {
}
}
export class PlaceHolderViewletActivityAction extends ViewletActivityAction {
constructor(
id: string,
icon: URI | string | undefined,
@IViewletService viewletService: IViewletService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ITelemetryService telemetryService: ITelemetryService
) {
super({
id,
name: id,
iconUrl: URI.isUri(icon) ? icon : undefined,
cssClass: isString(icon) ? icon : undefined
}, viewletService, layoutService, telemetryService);
}
}
export class PlaceHolderViewContainerActivityAction extends ViewContainerActivityAction { }
export class PlaceHolderToggleCompositePinnedAction extends ToggleCompositePinnedAction {
@@ -289,16 +229,16 @@ class SwitchSideBarViewAction extends Action {
}
async run(offset: number): Promise<void> {
const pinnedViewletIds = this.activityBarService.getPinnedViewletIds();
const visibleViewletIds = this.activityBarService.getVisibleViewContainerIds();
const activeViewlet = this.viewletService.getActiveViewlet();
if (!activeViewlet) {
return;
}
let targetViewletId: string | undefined;
for (let i = 0; i < pinnedViewletIds.length; i++) {
if (pinnedViewletIds[i] === activeViewlet.getId()) {
targetViewletId = pinnedViewletIds[(i + pinnedViewletIds.length + offset) % pinnedViewletIds.length];
for (let i = 0; i < visibleViewletIds.length; i++) {
if (visibleViewletIds[i] === activeViewlet.getId()) {
targetViewletId = visibleViewletIds[(i + visibleViewletIds.length + offset) % visibleViewletIds.length];
break;
}
}

View File

@@ -8,8 +8,7 @@ import * as nls from 'vs/nls';
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { GLOBAL_ACTIVITY_ID, IActivity } from 'vs/workbench/common/activity';
import { Part } from 'vs/workbench/browser/part';
import { GlobalActivityActionViewItem, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction, AccountsActionViewItem, HomeAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { GlobalActivityActionViewItem, ViewContainerActivityAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewContainerActivityAction, AccountsActionViewItem, HomeAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
import { IBadge, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IWorkbenchLayoutService, Parts, Position as SideBarPosition } from 'vs/workbench/services/layout/browser/layoutService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -19,15 +18,13 @@ import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeServic
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar';
import { Dimension, addClass, removeNode } from 'vs/base/browser/dom';
import { Dimension, addClass, removeNode, createCSSRule, asCSSUrl } 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, UriComponents } from 'vs/base/common/uri';
import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { IViewDescriptorService, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewContainerModel, ViewContainerLocation } from 'vs/workbench/common/views';
import { IViewDescriptorService, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewContainerModel, ViewContainerLocation, IViewsService } from 'vs/workbench/common/views';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IViewlet } from 'vs/workbench/common/viewlet';
import { isUndefinedOrNull, assertIsDefined, isString } from 'vs/base/common/types';
import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
@@ -42,8 +39,10 @@ import { getUserDataSyncStore } from 'vs/platform/userDataSync/common/userDataSy
import { IProductService } from 'vs/platform/product/common/productService';
import { Before2D } from 'vs/workbench/browser/dnd';
import { Codicon, iconRegistry } from 'vs/base/common/codicons';
import { Action } from 'vs/base/common/actions';
import { Event } from 'vs/base/common/event';
interface IPlaceholderViewlet {
interface IPlaceholderViewContainer {
id: string;
name?: string;
iconUrl?: UriComponents;
@@ -51,14 +50,14 @@ interface IPlaceholderViewlet {
views?: { when?: string }[];
}
interface IPinnedViewlet {
interface IPinnedViewContainer {
id: string;
pinned: boolean;
order?: number;
visible: boolean;
}
interface ICachedViewlet {
interface ICachedViewContainer {
id: string;
name?: string;
icon?: URI | string;
@@ -73,8 +72,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
_serviceBrand: undefined;
private static readonly ACTION_HEIGHT = 48;
static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets2';
private static readonly PLACEHOLDER_VIEWLETS = 'workbench.activity.placeholderViewlets';
static readonly PINNED_VIEW_CONTAINERS = 'workbench.activity.pinnedViewlets2';
private static readonly PLACEHOLDER_VIEW_CONTAINERS = 'workbench.activity.placeholderViewlets';
//#region IView
@@ -99,18 +98,20 @@ export class ActivitybarPart extends Part implements IActivityBarService {
private globalActivityActionBar: ActionBar | undefined;
private readonly globalActivity: ICompositeActivity[] = [];
private readonly cachedViewlets: ICachedViewlet[] = [];
private readonly compositeActions = new Map<string, { activityAction: ViewletActivityAction, pinnedAction: ToggleCompositePinnedAction }>();
private readonly viewletDisposables = new Map<string, IDisposable>();
private readonly cachedViewContainers: ICachedViewContainer[] = [];
private readonly compositeActions = new Map<string, { activityAction: ViewContainerActivityAction, pinnedAction: ToggleCompositePinnedAction }>();
private readonly viewContainerDisposables = new Map<string, IDisposable>();
private readonly location = ViewContainerLocation.Sidebar;
constructor(
@IViewletService private readonly viewletService: IViewletService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IThemeService themeService: IThemeService,
@IStorageService private readonly storageService: IStorageService,
@IExtensionService private readonly extensionService: IExtensionService,
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IViewsService private readonly viewsService: IViewsService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@@ -119,27 +120,27 @@ export class ActivitybarPart extends Part implements IActivityBarService {
) {
super(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
storageKeysSyncRegistryService.registerStorageKey({ key: ActivitybarPart.PINNED_VIEWLETS, version: 1 });
this.migrateFromOldCachedViewletsValue();
storageKeysSyncRegistryService.registerStorageKey({ key: ActivitybarPart.PINNED_VIEW_CONTAINERS, version: 1 });
this.migrateFromOldCachedViewContainersValue();
this.cachedViewlets = this.getCachedViewlets();
for (const cachedViewlet of this.cachedViewlets) {
this.cachedViewContainers = this.getCachedViewContainers();
for (const cachedViewContainer of this.cachedViewContainers) {
if (environmentService.configuration.remoteAuthority // In remote window, hide activity bar entries until registered.
|| this.shouldBeHidden(cachedViewlet.id, cachedViewlet)
|| this.shouldBeHidden(cachedViewContainer.id, cachedViewContainer)
) {
cachedViewlet.visible = false;
cachedViewContainer.visible = false;
}
}
const cachedItems = this.cachedViewlets
const cachedItems = this.cachedViewContainers
.map(v => ({ id: v.id, name: v.name, visible: v.visible, order: v.order, pinned: v.pinned }));
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, cachedItems, {
icon: true,
orientation: ActionsOrientation.VERTICAL,
openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true),
openComposite: (compositeId: string) => this.viewsService.openViewContainer(compositeId, true),
getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction,
getCompositePinnedAction: (compositeId: string) => this.getCompositeActions(compositeId).pinnedAction,
getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, assertIsDefined(this.viewletService.getViewlet(compositeId))),
getOnCompositeClickAction: (compositeId: string) => new Action(compositeId, '', '', true, () => this.viewsService.isViewContainerVisible(compositeId) ? Promise.resolve(this.viewsService.closeViewContainer(compositeId)) : this.viewsService.openViewContainer(compositeId)),
getContextMenuActions: () => {
const menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService);
const actions = [];
@@ -152,10 +153,10 @@ export class ActivitybarPart extends Part implements IActivityBarService {
return actions;
},
getContextMenuActionsForComposite: () => [],
getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(),
getDefaultCompositeId: () => this.viewDescriptorService.getDefaultViewContainer(this.location)!.id,
hidePart: () => this.layoutService.setSideBarHidden(true),
dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Sidebar,
(id: string, focus?: boolean) => this.viewletService.openViewlet(id, focus),
(id: string, focus?: boolean) => this.viewsService.openViewContainer(id, focus),
(from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.verticallyBefore)
),
compositeSize: 52,
@@ -163,28 +164,25 @@ export class ActivitybarPart extends Part implements IActivityBarService {
overflowActionSize: ActivitybarPart.ACTION_HEIGHT
}));
this.onDidRegisterViewContainers(this.getViewContainers());
this.registerListeners();
this.onDidRegisterViewlets(viewletService.getViewlets());
}
private registerListeners(): void {
// Viewlet registration
this._register(this.viewletService.onDidViewletRegister(viewlet => this.onDidRegisterViewlets([viewlet])));
this._register(this.viewletService.onDidViewletDeregister(({ id }) => this.onDidDeregisterViewlet(id)));
// View Container Changes
this._register(this.viewDescriptorService.onDidChangeViewContainers(({ added, removed }) => this.onDidChangeViewContainers(added, removed)));
this._register(this.viewDescriptorService.onDidChangeContainerLocation(({ viewContainer, from, to }) => this.onDidChangeViewContainerLocation(viewContainer, from, to)));
// 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())));
// View Container Visibility Changes
this._register(Event.filter(this.viewsService.onDidChangeViewContainerVisibility, e => e.location === this.location)(({ id, visible }) => this.onDidChangeViewContainerVisibility(id, visible)));
// Extension registration
let disposables = this._register(new DisposableStore());
this._register(this.extensionService.onDidRegisterExtensions(() => {
disposables.clear();
this.onDidRegisterExtensions();
this.compositeBar.onDidChange(() => this.saveCachedViewlets(), this, disposables);
this.compositeBar.onDidChange(() => this.saveCachedViewContainers(), this, disposables);
this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables);
}));
@@ -200,39 +198,57 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}));
}
private onDidRegisterExtensions(): void {
this.removeNotExistingComposites();
this.saveCachedViewlets();
private onDidChangeViewContainers(added: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation }>, removed: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation }>) {
removed.filter(({ location }) => location === ViewContainerLocation.Sidebar).forEach(({ container }) => this.onDidDeregisterViewContainer(container));
this.onDidRegisterViewContainers(added.filter(({ location }) => location === ViewContainerLocation.Sidebar).map(({ container }) => container));
}
private onDidViewletOpen(viewlet: IViewlet): void {
// Update the composite bar by adding
const foundViewlet = this.viewletService.getViewlet(viewlet.getId());
if (foundViewlet) {
this.compositeBar.addComposite(foundViewlet);
private onDidChangeViewContainerLocation(container: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation) {
if (from === this.location) {
this.onDidDeregisterViewContainer(container);
}
if (to === this.location) {
this.onDidRegisterViewContainers([container]);
}
}
this.compositeBar.activateComposite(viewlet.getId());
private onDidChangeViewContainerVisibility(id: string, visible: boolean) {
if (visible) {
// Activate view container action on opening of a view container
this.onDidViewContainerVisible(id);
} else {
// Deactivate view container action on close
this.compositeBar.deactivateComposite(id);
}
}
const viewletDescriptor = this.viewletService.getViewlet(viewlet.getId());
if (viewletDescriptor) {
const viewContainer = this.getViewContainer(viewletDescriptor.id);
if (viewContainer?.hideIfEmpty) {
private onDidRegisterExtensions(): void {
this.removeNotExistingComposites();
this.saveCachedViewContainers();
}
private onDidViewContainerVisible(id: string): void {
const viewContainer = this.getViewContainer(id);
if (viewContainer) {
// Update the composite bar by adding
this.compositeBar.addComposite(viewContainer);
this.compositeBar.activateComposite(viewContainer.id);
if (viewContainer.hideIfEmpty) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
if (viewContainerModel.activeViewDescriptors.length === 0) {
this.hideComposite(viewletDescriptor.id); // Update the composite bar by hiding
this.hideComposite(viewContainer.id); // Update the composite bar by hiding
}
}
}
}
showActivity(viewletOrActionId: string, badge: IBadge, clazz?: string, priority?: number): IDisposable {
if (this.viewletService.getViewlet(viewletOrActionId)) {
return this.compositeBar.showActivity(viewletOrActionId, badge, clazz, priority);
showActivity(viewContainerOrActionId: string, badge: IBadge, clazz?: string, priority?: number): IDisposable {
if (this.getViewContainer(viewContainerOrActionId)) {
return this.compositeBar.showActivity(viewContainerOrActionId, badge, clazz, priority);
}
if (viewletOrActionId === GLOBAL_ACTIVITY_ID) {
if (viewContainerOrActionId === GLOBAL_ACTIVITY_ID) {
return this.showGlobalActivity(badge, clazz, priority);
}
@@ -342,7 +358,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.installMenubar();
}
// Viewlets action bar
// View Containers action bar
this.compositeBar.create(this.content);
// Global action bar
@@ -444,19 +460,20 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.globalActivityActionBar.push(this.globalActivityAction);
}
private getCompositeActions(compositeId: string): { activityAction: ViewletActivityAction, pinnedAction: ToggleCompositePinnedAction } {
private getCompositeActions(compositeId: string): { activityAction: ViewContainerActivityAction, pinnedAction: ToggleCompositePinnedAction } {
let compositeActions = this.compositeActions.get(compositeId);
if (!compositeActions) {
const viewlet = this.viewletService.getViewlet(compositeId);
if (viewlet) {
const viewContainer = this.getViewContainer(compositeId);
if (viewContainer) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
compositeActions = {
activityAction: this.instantiationService.createInstance(ViewletActivityAction, viewlet),
pinnedAction: new ToggleCompositePinnedAction(viewlet, this.compositeBar)
activityAction: this.instantiationService.createInstance(ViewContainerActivityAction, this.toActivity(viewContainer, viewContainerModel)),
pinnedAction: new ToggleCompositePinnedAction(viewContainer, this.compositeBar)
};
} else {
const cachedComposite = this.cachedViewlets.filter(c => c.id === compositeId)[0];
const cachedComposite = this.cachedViewContainers.filter(c => c.id === compositeId)[0];
compositeActions = {
activityAction: this.instantiationService.createInstance(PlaceHolderViewletActivityAction, compositeId, cachedComposite?.icon),
activityAction: this.instantiationService.createInstance(PlaceHolderViewContainerActivityAction, ActivitybarPart.toActivity(compositeId, compositeId, cachedComposite?.icon, undefined)),
pinnedAction: new PlaceHolderToggleCompositePinnedAction(compositeId, this.compositeBar)
};
}
@@ -467,28 +484,27 @@ export class ActivitybarPart extends Part implements IActivityBarService {
return compositeActions;
}
private onDidRegisterViewlets(viewlets: ViewletDescriptor[]): void {
for (const viewlet of viewlets) {
const cachedViewlet = this.cachedViewlets.filter(({ id }) => id === viewlet.id)[0];
const activeViewlet = this.viewletService.getActiveViewlet();
const isActive = activeViewlet?.getId() === viewlet.id;
private onDidRegisterViewContainers(viewContainers: ReadonlyArray<ViewContainer>): void {
for (const viewContainer of viewContainers) {
const cachedViewContainer = this.cachedViewContainers.filter(({ id }) => id === viewContainer.id)[0];
const visibleViewContainer = this.viewsService.getVisibleViewContainer(this.location);
const isActive = visibleViewContainer?.id === viewContainer.id;
if (isActive || !this.shouldBeHidden(viewlet.id, cachedViewlet)) {
this.compositeBar.addComposite(viewlet);
if (isActive || !this.shouldBeHidden(viewContainer.id, cachedViewContainer)) {
this.compositeBar.addComposite(viewContainer);
// Pin it by default if it is new
if (!cachedViewlet) {
this.compositeBar.pin(viewlet.id);
if (!cachedViewContainer) {
this.compositeBar.pin(viewContainer.id);
}
if (isActive) {
this.compositeBar.activateComposite(viewlet.id);
this.compositeBar.activateComposite(viewContainer.id);
}
}
}
for (const viewlet of viewlets) {
const viewContainer = this.getViewContainer(viewlet.id)!;
for (const viewContainer of viewContainers) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
this.updateActivity(viewContainer, viewContainerModel);
this.onDidChangeActiveViews(viewContainer, viewContainerModel);
@@ -497,38 +513,53 @@ export class ActivitybarPart extends Part implements IActivityBarService {
disposables.add(viewContainerModel.onDidChangeContainerInfo(() => this.updateActivity(viewContainer, viewContainerModel)));
disposables.add(viewContainerModel.onDidChangeActiveViewDescriptors(() => this.onDidChangeActiveViews(viewContainer, viewContainerModel)));
this.viewletDisposables.set(viewlet.id, disposables);
this.viewContainerDisposables.set(viewContainer.id, disposables);
}
}
private onDidDeregisterViewlet(viewletId: string): void {
const disposable = this.viewletDisposables.get(viewletId);
private onDidDeregisterViewContainer(viewContainer: ViewContainer): void {
const disposable = this.viewContainerDisposables.get(viewContainer.id);
if (disposable) {
disposable.dispose();
}
this.viewletDisposables.delete(viewletId);
this.hideComposite(viewletId);
this.viewContainerDisposables.delete(viewContainer.id);
this.hideComposite(viewContainer.id);
}
private updateActivity(viewContainer: ViewContainer, viewContainerModel: IViewContainerModel): void {
const activity: IActivity = {
id: viewContainer.id,
name: viewContainerModel.title,
iconUrl: URI.isUri(viewContainerModel.icon) ? viewContainerModel.icon : undefined,
cssClass: isString(viewContainerModel.icon) ? viewContainerModel.icon : undefined,
keybindingId: viewContainer.focusCommand?.id || viewContainer.id
};
const activity: IActivity = this.toActivity(viewContainer, viewContainerModel);
const { activityAction, pinnedAction } = this.getCompositeActions(viewContainer.id);
activityAction.setActivity(activity);
activityAction.updateActivity(activity);
if (pinnedAction instanceof PlaceHolderToggleCompositePinnedAction) {
pinnedAction.setActivity(activity);
}
this.saveCachedViewlets();
this.saveCachedViewContainers();
}
private toActivity({ id, focusCommand }: ViewContainer, { icon, title: name }: IViewContainerModel): IActivity {
return ActivitybarPart.toActivity(id, name, icon, focusCommand?.id || id);
}
private static toActivity(id: string, name: string, icon: URI | string | undefined, keybindingId: string | undefined): IActivity {
let cssClass: string | undefined = undefined;
let iconUrl: URI | undefined = undefined;
if (URI.isUri(icon)) {
iconUrl = icon;
cssClass = `activity-${id.replace(/\./g, '-')}`;
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`;
createCSSRule(iconClass, `
mask: ${asCSSUrl(icon)} no-repeat 50% 50%;
mask-size: 24px;
-webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%;
-webkit-mask-size: 24px;
`);
} else if (isString(icon)) {
cssClass = icon;
}
return { id, name, cssClass, iconUrl, keybindingId };
}
private onDidChangeActiveViews(viewContainer: ViewContainer, viewContainerModel: IViewContainerModel): void {
@@ -539,21 +570,21 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
private shouldBeHidden(viewletId: string, cachedViewlet?: ICachedViewlet): boolean {
const viewContainer = this.getViewContainer(viewletId);
private shouldBeHidden(viewContainerId: string, cachedViewContainer?: ICachedViewContainer): boolean {
const viewContainer = this.getViewContainer(viewContainerId);
if (!viewContainer || !viewContainer.hideIfEmpty) {
return false;
}
return cachedViewlet?.views && cachedViewlet.views.length
? cachedViewlet.views.every(({ when }) => !!when && !this.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(when)))
: viewletId === TEST_VIEW_CONTAINER_ID /* Hide Test viewlet for the first time or it had no views registered before */;
return cachedViewContainer?.views && cachedViewContainer.views.length
? cachedViewContainer.views.every(({ when }) => !!when && !this.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(when)))
: viewContainerId === TEST_VIEW_CONTAINER_ID /* Hide Test view container for the first time or it had no views registered before */;
}
private removeNotExistingComposites(): void {
const viewlets = this.viewletService.getViewlets();
for (const { id } of this.cachedViewlets) {
if (viewlets.every(viewlet => viewlet.id !== id)) {
const viewContainers = this.getViewContainers();
for (const { id } of this.cachedViewContainers) {
if (viewContainers.every(viewContainer => viewContainer.id !== id)) {
this.hideComposite(id);
}
}
@@ -570,15 +601,20 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
getPinnedViewletIds(): string[] {
getPinnedViewContainerIds(): string[] {
const pinnedCompositeIds = this.compositeBar.getPinnedComposites().map(v => v.id);
return this.viewletService.getViewlets()
return this.getViewContainers()
.filter(v => this.compositeBar.isPinned(v.id))
.sort((v1, v2) => pinnedCompositeIds.indexOf(v1.id) - pinnedCompositeIds.indexOf(v2.id))
.map(v => v.id);
}
getVisibleViewContainerIds(): string[] {
return this.compositeBar.getVisibleComposites()
.filter(v => this.viewsService.getVisibleViewContainer(this.location)?.id === v.id || this.compositeBar.isPinned(v.id))
.map(v => v.id);
}
layout(width: number, height: number): void {
if (!this.layoutService.isVisible(Parts.ACTIVITYBAR_PART)) {
return;
@@ -601,27 +637,32 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.compositeBar.layout(new Dimension(width, availableHeight));
}
private getViewContainer(viewletId: string): ViewContainer | undefined {
return this.viewDescriptorService.getViewContainerById(viewletId) || undefined;
private getViewContainer(id: string): ViewContainer | undefined {
const viewContainer = this.viewDescriptorService.getViewContainerById(id);
return viewContainer && this.viewDescriptorService.getViewContainerLocation(viewContainer) === this.location ? viewContainer : undefined;
}
private getViewContainers(): ReadonlyArray<ViewContainer> {
return this.viewDescriptorService.getViewContainersByLocation(this.location);
}
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
if (e.key === ActivitybarPart.PINNED_VIEWLETS && e.scope === StorageScope.GLOBAL
&& this.pinnedViewletsValue !== this.getStoredPinnedViewletsValue() /* This checks if current window changed the value or not */) {
this._pinnedViewletsValue = undefined;
if (e.key === ActivitybarPart.PINNED_VIEW_CONTAINERS && e.scope === StorageScope.GLOBAL
&& this.pinnedViewContainersValue !== this.getStoredPinnedViewContainersValue() /* This checks if current window changed the value or not */) {
this._pinnedViewContainersValue = undefined;
const newCompositeItems: ICompositeBarItem[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
const cachedViewlets = this.getCachedViewlets();
const cachedViewContainers = this.getCachedViewContainers();
for (const cachedViewlet of cachedViewlets) {
for (const cachedViewContainer of cachedViewContainers) {
// Add and update existing items
const existingItem = compositeItems.filter(({ id }) => id === cachedViewlet.id)[0];
const existingItem = compositeItems.filter(({ id }) => id === cachedViewContainer.id)[0];
if (existingItem) {
newCompositeItems.push({
id: existingItem.id,
name: existingItem.name,
order: existingItem.order,
pinned: cachedViewlet.pinned,
pinned: cachedViewContainer.pinned,
visible: existingItem.visible
});
}
@@ -638,8 +679,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
private saveCachedViewlets(): void {
const state: ICachedViewlet[] = [];
private saveCachedViewContainers(): void {
const state: ICachedViewContainer[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
for (const compositeItem of compositeItems) {
@@ -665,32 +706,32 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
this.storeCachedViewletsState(state);
this.storeCachedViewContainersState(state);
}
private getCachedViewlets(): ICachedViewlet[] {
const cachedViewlets: ICachedViewlet[] = this.getPinnedViewlets();
for (const placeholderViewlet of this.getPlaceholderViewlets()) {
const cachedViewlet = cachedViewlets.filter(cached => cached.id === placeholderViewlet.id)[0];
if (cachedViewlet) {
cachedViewlet.name = placeholderViewlet.name;
cachedViewlet.icon = placeholderViewlet.iconCSS ? placeholderViewlet.iconCSS :
placeholderViewlet.iconUrl ? URI.revive(placeholderViewlet.iconUrl) : undefined;
cachedViewlet.views = placeholderViewlet.views;
private getCachedViewContainers(): ICachedViewContainer[] {
const cachedViewContainers: ICachedViewContainer[] = this.getPinnedViewContainers();
for (const placeholderViewContainer of this.getPlaceholderViewContainers()) {
const cachedViewContainer = cachedViewContainers.filter(cached => cached.id === placeholderViewContainer.id)[0];
if (cachedViewContainer) {
cachedViewContainer.name = placeholderViewContainer.name;
cachedViewContainer.icon = placeholderViewContainer.iconCSS ? placeholderViewContainer.iconCSS :
placeholderViewContainer.iconUrl ? URI.revive(placeholderViewContainer.iconUrl) : undefined;
cachedViewContainer.views = placeholderViewContainer.views;
}
}
return cachedViewlets;
return cachedViewContainers;
}
private storeCachedViewletsState(cachedViewlets: ICachedViewlet[]): void {
this.setPinnedViewlets(cachedViewlets.map(({ id, pinned, visible, order }) => (<IPinnedViewlet>{
private storeCachedViewContainersState(cachedViewContainers: ICachedViewContainer[]): void {
this.setPinnedViewContainers(cachedViewContainers.map(({ id, pinned, visible, order }) => (<IPinnedViewContainer>{
id,
pinned,
visible,
order
})));
this.setPlaceholderViewlets(cachedViewlets.map(({ id, icon, name, views }) => (<IPlaceholderViewlet>{
this.setPlaceholderViewContainers(cachedViewContainers.map(({ id, icon, name, views }) => (<IPlaceholderViewContainer>{
id,
iconUrl: URI.isUri(icon) ? icon : undefined,
iconCSS: isString(icon) ? icon : undefined,
@@ -699,80 +740,80 @@ export class ActivitybarPart extends Part implements IActivityBarService {
})));
}
private getPinnedViewlets(): IPinnedViewlet[] {
return JSON.parse(this.pinnedViewletsValue);
private getPinnedViewContainers(): IPinnedViewContainer[] {
return JSON.parse(this.pinnedViewContainersValue);
}
private setPinnedViewlets(pinnedViewlets: IPinnedViewlet[]): void {
this.pinnedViewletsValue = JSON.stringify(pinnedViewlets);
private setPinnedViewContainers(pinnedViewContainers: IPinnedViewContainer[]): void {
this.pinnedViewContainersValue = JSON.stringify(pinnedViewContainers);
}
private _pinnedViewletsValue: string | undefined;
private get pinnedViewletsValue(): string {
if (!this._pinnedViewletsValue) {
this._pinnedViewletsValue = this.getStoredPinnedViewletsValue();
private _pinnedViewContainersValue: string | undefined;
private get pinnedViewContainersValue(): string {
if (!this._pinnedViewContainersValue) {
this._pinnedViewContainersValue = this.getStoredPinnedViewContainersValue();
}
return this._pinnedViewletsValue;
return this._pinnedViewContainersValue;
}
private set pinnedViewletsValue(pinnedViewletsValue: string) {
if (this.pinnedViewletsValue !== pinnedViewletsValue) {
this._pinnedViewletsValue = pinnedViewletsValue;
this.setStoredPinnedViewletsValue(pinnedViewletsValue);
private set pinnedViewContainersValue(pinnedViewContainersValue: string) {
if (this.pinnedViewContainersValue !== pinnedViewContainersValue) {
this._pinnedViewContainersValue = pinnedViewContainersValue;
this.setStoredPinnedViewContainersValue(pinnedViewContainersValue);
}
}
private getStoredPinnedViewletsValue(): string {
return this.storageService.get(ActivitybarPart.PINNED_VIEWLETS, StorageScope.GLOBAL, '[]');
private getStoredPinnedViewContainersValue(): string {
return this.storageService.get(ActivitybarPart.PINNED_VIEW_CONTAINERS, StorageScope.GLOBAL, '[]');
}
private setStoredPinnedViewletsValue(value: string): void {
this.storageService.store(ActivitybarPart.PINNED_VIEWLETS, value, StorageScope.GLOBAL);
private setStoredPinnedViewContainersValue(value: string): void {
this.storageService.store(ActivitybarPart.PINNED_VIEW_CONTAINERS, value, StorageScope.GLOBAL);
}
private getPlaceholderViewlets(): IPlaceholderViewlet[] {
return JSON.parse(this.placeholderViewletsValue);
private getPlaceholderViewContainers(): IPlaceholderViewContainer[] {
return JSON.parse(this.placeholderViewContainersValue);
}
private setPlaceholderViewlets(placeholderViewlets: IPlaceholderViewlet[]): void {
this.placeholderViewletsValue = JSON.stringify(placeholderViewlets);
private setPlaceholderViewContainers(placeholderViewContainers: IPlaceholderViewContainer[]): void {
this.placeholderViewContainersValue = JSON.stringify(placeholderViewContainers);
}
private _placeholderViewletsValue: string | undefined;
private get placeholderViewletsValue(): string {
if (!this._placeholderViewletsValue) {
this._placeholderViewletsValue = this.getStoredPlaceholderViewletsValue();
private _placeholderViewContainersValue: string | undefined;
private get placeholderViewContainersValue(): string {
if (!this._placeholderViewContainersValue) {
this._placeholderViewContainersValue = this.getStoredPlaceholderViewContainersValue();
}
return this._placeholderViewletsValue;
return this._placeholderViewContainersValue;
}
private set placeholderViewletsValue(placeholderViewletsValue: string) {
if (this.placeholderViewletsValue !== placeholderViewletsValue) {
this._placeholderViewletsValue = placeholderViewletsValue;
this.setStoredPlaceholderViewletsValue(placeholderViewletsValue);
private set placeholderViewContainersValue(placeholderViewContainesValue: string) {
if (this.placeholderViewContainersValue !== placeholderViewContainesValue) {
this._placeholderViewContainersValue = placeholderViewContainesValue;
this.setStoredPlaceholderViewContainersValue(placeholderViewContainesValue);
}
}
private getStoredPlaceholderViewletsValue(): string {
return this.storageService.get(ActivitybarPart.PLACEHOLDER_VIEWLETS, StorageScope.GLOBAL, '[]');
private getStoredPlaceholderViewContainersValue(): string {
return this.storageService.get(ActivitybarPart.PLACEHOLDER_VIEW_CONTAINERS, StorageScope.GLOBAL, '[]');
}
private setStoredPlaceholderViewletsValue(value: string): void {
this.storageService.store(ActivitybarPart.PLACEHOLDER_VIEWLETS, value, StorageScope.GLOBAL);
private setStoredPlaceholderViewContainersValue(value: string): void {
this.storageService.store(ActivitybarPart.PLACEHOLDER_VIEW_CONTAINERS, value, StorageScope.GLOBAL);
}
private migrateFromOldCachedViewletsValue(): void {
private migrateFromOldCachedViewContainersValue(): void {
const value = this.storageService.get('workbench.activity.pinnedViewlets', StorageScope.GLOBAL);
if (value !== undefined) {
const storedStates: Array<string | ICachedViewlet> = JSON.parse(value);
const cachedViewlets = storedStates.map(c => {
const serialized: ICachedViewlet = typeof c === 'string' /* migration from pinned states to composites states */ ? { id: c, pinned: true, order: undefined, visible: true, name: undefined, icon: undefined, views: undefined } : c;
const storedStates: Array<string | ICachedViewContainer> = JSON.parse(value);
const cachedViewContainers = storedStates.map(c => {
const serialized: ICachedViewContainer = typeof c === 'string' /* migration from pinned states to composites states */ ? { id: c, pinned: true, order: undefined, visible: true, name: undefined, icon: undefined, views: undefined } : c;
serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible;
return serialized;
});
this.storeCachedViewletsState(cachedViewlets);
this.storeCachedViewContainersState(cachedViewContainers);
this.storageService.remove('workbench.activity.pinnedViewlets', StorageScope.GLOBAL);
}
}

View File

@@ -37,11 +37,11 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
constructor(
private viewDescriptorService: IViewDescriptorService,
private targetContainerLocation: ViewContainerLocation,
private openComposite: (id: string, focus?: boolean) => Promise<IPaneComposite | undefined>,
private openComposite: (id: string, focus?: boolean) => Promise<IPaneComposite | null>,
private moveComposite: (from: string, to: string, before?: Before2D) => void,
) { }
drop(data: CompositeDragAndDropData, targetCompositeId: string, originalEvent: DragEvent, before?: Before2D): void {
drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent, before?: Before2D): void {
const dragData = data.getData();
if (dragData.type === 'composite') {
@@ -50,7 +50,9 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
// ... on the same composite bar
if (currentLocation === this.targetContainerLocation) {
this.moveComposite(dragData.id, targetCompositeId, before);
if (targetCompositeId) {
this.moveComposite(dragData.id, targetCompositeId, before);
}
}
// ... on a different composite bar
else {
@@ -60,7 +62,10 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
}
this.viewDescriptorService.moveViewContainerToLocation(currentContainer, this.targetContainerLocation);
this.moveComposite(currentContainer.id, targetCompositeId, before);
if (targetCompositeId) {
this.moveComposite(currentContainer.id, targetCompositeId, before);
}
this.openComposite(currentContainer.id, true);
}
@@ -74,7 +79,9 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
const newContainer = this.viewDescriptorService.getViewContainerByViewId(viewToMove.id)!;
this.moveComposite(newContainer.id, targetCompositeId, before);
if (targetCompositeId) {
this.moveComposite(newContainer.id, targetCompositeId, before);
}
this.openComposite(newContainer.id, true).then(composite => {
if (composite) {
@@ -140,7 +147,7 @@ export interface ICompositeBarOptions {
getOnCompositeClickAction: (compositeId: string) => Action;
getContextMenuActions: () => Action[];
getContextMenuActionsForComposite: (compositeId: string) => Action[];
openComposite: (compositeId: string) => Promise<IComposite | undefined>;
openComposite: (compositeId: string) => Promise<IComposite | null>;
getDefaultCompositeId: () => string;
hidePart: () => void;
}
@@ -188,6 +195,10 @@ export class CompositeBar extends Widget implements ICompositeBar {
return this.model.pinnedItems;
}
getVisibleComposites(): ICompositeBarItem[] {
return this.model.visibleItems;
}
create(parent: HTMLElement): HTMLElement {
const actionBarDiv = parent.appendChild($('.composite-bar'));
this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, {
@@ -264,7 +275,8 @@ export class CompositeBar extends Widget implements ICompositeBar {
// Add to the model
if (this.model.add(id, name, order)) {
this.computeSizes([this.model.findItem(id)]);
this.updateCompositeSwitcher();
// Set timeout helps prevent flicker
setTimeout(() => this.updateCompositeSwitcher(), 0);
}
}
@@ -526,7 +538,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
});
// Add overflow action as needed
if ((visibleCompositesChange && overflows) || compositeSwitcherBar.length() === 0) {
if ((visibleCompositesChange && overflows)) {
this.compositeOverflowAction = this.instantiationService.createInstance(CompositeOverflowActivityAction, () => {
if (this.compositeOverflowActionViewItem) {
this.compositeOverflowActionViewItem.showMenu();

View File

@@ -91,7 +91,7 @@ class Item extends BreadcrumbsItem {
fileKind: this.element.kind,
fileDecorations: { colors: this.options.showDecorationColors, badges: false },
});
dom.addClass(container, FileKind[this.element.kind].toLowerCase());
container.classList.add(FileKind[this.element.kind].toLowerCase());
this._disposables.add(label);
} else if (this.element instanceof OutlineModel) {
@@ -113,7 +113,7 @@ class Item extends BreadcrumbsItem {
let icon = document.createElement('div');
icon.className = SymbolKinds.toCssClassName(this.element.symbol.kind);
container.appendChild(icon);
dom.addClass(container, 'shows-symbol-icon');
container.classList.add('shows-symbol-icon');
}
let label = new IconLabel(container);
let title = this.element.symbol.name.replace(/\r|\n|\r\n/g, '\u23CE');
@@ -183,7 +183,7 @@ export class BreadcrumbsControl {
@IBreadcrumbsService breadcrumbsService: IBreadcrumbsService,
) {
this.domNode = document.createElement('div');
dom.addClass(this.domNode, 'breadcrumbs-control');
this.domNode.classList.add('breadcrumbs-control');
dom.append(container, this.domNode);
this._cfUseQuickPick = BreadcrumbsConfig.UseQuickPick.bindTo(_configurationService);
@@ -221,13 +221,13 @@ export class BreadcrumbsControl {
}
isHidden(): boolean {
return dom.hasClass(this.domNode, 'hidden');
return this.domNode.classList.contains('hidden');
}
hide(): void {
this._breadcrumbsDisposables.clear();
this._ckBreadcrumbsVisible.set(false);
dom.toggleClass(this.domNode, 'hidden', true);
this.domNode.classList.toggle('hidden', true);
}
update(): boolean {
@@ -251,7 +251,7 @@ export class BreadcrumbsControl {
}
}
dom.toggleClass(this.domNode, 'hidden', false);
this.domNode.classList.toggle('hidden', false);
this._ckBreadcrumbsVisible.set(true);
this._ckBreadcrumbsPossible.set(true);
@@ -263,8 +263,8 @@ export class BreadcrumbsControl {
this._textResourceConfigurationService,
this._workspaceService
);
dom.toggleClass(this.domNode, 'relative-path', model.isRelative());
dom.toggleClass(this.domNode, 'backslash-path', this._labelService.getSeparator(uri.scheme, uri.authority) === '\\');
this.domNode.classList.toggle('relative-path', model.isRelative());
this.domNode.classList.toggle('backslash-path', this._labelService.getSeparator(uri.scheme, uri.authority) === '\\');
const updateBreadcrumbs = () => {
const showIcons = this._cfShowIcons.getValue();

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { compareFileNames } from 'vs/base/common/comparers';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
@@ -375,11 +374,11 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
_createTree(container: HTMLElement) {
// tree icon theme specials
dom.addClass(this._treeContainer, 'file-icon-themable-tree');
dom.addClass(this._treeContainer, 'show-file-icons');
this._treeContainer.classList.add('file-icon-themable-tree');
this._treeContainer.classList.add('show-file-icons');
const onFileIconThemeChange = (fileIconTheme: IFileIconTheme) => {
dom.toggleClass(this._treeContainer, 'align-icons-and-twisties', fileIconTheme.hasFileIcons && !fileIconTheme.hasFolderIcons);
dom.toggleClass(this._treeContainer, 'hide-arrows', fileIconTheme.hidesExplorerArrows === true);
this._treeContainer.classList.toggle('align-icons-and-twisties', fileIconTheme.hasFileIcons && !fileIconTheme.hasFolderIcons);
this._treeContainer.classList.toggle('hide-arrows', fileIconTheme.hidesExplorerArrows === true);
};
this._disposables.add(this._themeService.onDidFileIconThemeChange(onFileIconThemeChange));
onFileIconThemeChange(this._themeService.getFileIconTheme());

View File

@@ -123,7 +123,7 @@ export class EditorControl extends Disposable {
private doInstantiateEditorPane(descriptor: IEditorDescriptor): BaseEditor {
// Return early if already instantiated
const existingEditorPane = this.editorPanes.filter(editorPane => descriptor.describes(editorPane))[0];
const existingEditorPane = this.editorPanes.find(editorPane => descriptor.describes(editorPane));
if (existingEditorPane) {
return existingEditorPane;
}

View File

@@ -16,7 +16,6 @@ import { GroupDirection, MergeGroupMode } from 'vs/workbench/services/editor/com
import { toDisposable } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { RunOnceScheduler } from 'vs/base/common/async';
import { find } from 'vs/base/common/arrays';
import { DataTransfers } from 'vs/base/browser/dnd';
import { VSBuffer } from 'vs/base/common/buffer';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
@@ -600,7 +599,7 @@ export class EditorDropTarget extends Themable {
private findTargetGroupView(child: HTMLElement): IEditorGroupView | undefined {
const groups = this.accessor.groups;
return find(groups, groupView => isAncestor(child, groupView.element) || this.delegate.groupContainsPredicate?.(groupView));
return groups.find(groupView => isAncestor(child, groupView.element) || this.delegate.groupContainsPredicate?.(groupView));
}
private updateContainer(isDraggedOver: boolean): void {

View File

@@ -1604,7 +1604,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Forward to controls
this.layoutTitleAreaControl(width);
this.editorControl.layout(new Dimension(this.dimension.width, this.dimension.height - this.titleAreaControl.getPreferredHeight()));
this.editorControl.layout(new Dimension(this.dimension.width, Math.max(0, this.dimension.height - this.titleAreaControl.getPreferredHeight())));
}
private layoutTitleAreaControl(width: number): void {

View File

@@ -6,7 +6,7 @@
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 { Dimension, isAncestor, toggleClass, addClass, $, EventHelper } from 'vs/base/browser/dom';
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, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -830,19 +830,23 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
addClass(overlay, 'drop-block-overlay');
parent.appendChild(overlay);
CompositeDragAndDropObserver.INSTANCE.registerTarget(this.element, {
onDragOver: e => {
if (e.eventData.dataTransfer) {
e.eventData.dataTransfer.dropEffect = 'none';
}
},
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(this.element, {
onDragStart: e => {
toggleClass(overlay, 'visible', true);
},
onDragEnd: e => {
toggleClass(overlay, 'visible', false);
}
});
}));
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(overlay, {
onDragOver: e => {
EventHelper.stop(e.eventData, true);
if (e.eventData.dataTransfer) {
e.eventData.dataTransfer.dropEffect = 'none';
}
}
}));
return this.container;
}

View File

@@ -50,7 +50,6 @@ import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessi
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
import { IMarker, IMarkerService, MarkerSeverity, IMarkerData } from 'vs/platform/markers/common/markers';
import { find } from 'vs/base/common/arrays';
import { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
@@ -972,7 +971,7 @@ class ShowCurrentMarkerInStatusbarContribution extends Disposable {
if (!position) {
return null;
}
return find(this.markers, marker => Range.containsPosition(marker, position)) || null;
return this.markers.find(marker => Range.containsPosition(marker, position)) || null;
}
private onMarkerChanged(changedResources: ReadonlyArray<URI>): void {

View File

@@ -48,7 +48,7 @@ export class EditorsObserver extends Disposable {
}
get editors(): IEditorIdentifier[] {
return this.mostRecentEditorsMap.values();
return [...this.mostRecentEditorsMap.values()];
}
hasEditor(resource: URI): boolean {
@@ -283,7 +283,7 @@ export class EditorsObserver extends Disposable {
// Across all editor groups
else {
await this.doEnsureOpenedEditorsLimit(limit, this.mostRecentEditorsMap.values(), exclude);
await this.doEnsureOpenedEditorsLimit(limit, [...this.mostRecentEditorsMap.values()], exclude);
}
}
@@ -342,7 +342,7 @@ export class EditorsObserver extends Disposable {
private serialize(): ISerializedEditorsList {
const registry = Registry.as<IEditorInputFactoryRegistry>(Extensions.EditorInputFactories);
const entries = this.mostRecentEditorsMap.values();
const entries = [...this.mostRecentEditorsMap.values()];
const mapGroupToSerializableEditorsOfGroup = new Map<IEditorGroup, IEditorInput[]>();
return {

View File

@@ -62,6 +62,22 @@
}
.monaco-workbench .part.panel .empty-panel-message-area {
position: absolute;
display: none;
top: 0px;
height: 100%;
width: 100%;
z-index: 10;
}
.monaco-workbench .part.panel .empty-panel-message-area.visible {
display: flex;
align-items: center;
align-content: center;
justify-content: center;
}
.monaco-workbench .part.panel > .composite.title > .composite-bar-excess {
width: 100px;
}

View File

@@ -20,13 +20,13 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ClosePanelAction, PanelActivityAction, ToggleMaximizedPanelAction, TogglePanelAction, PlaceHolderPanelActivityAction, PlaceHolderToggleCompositePinnedAction, PositionPanelActionConfigs, SetPanelPositionAction } from 'vs/workbench/browser/parts/panel/panelActions';
import { IThemeService, registerThemingParticipant, IColorTheme, 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, PANEL_INPUT_BORDER } from 'vs/workbench/common/theme';
import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BACKGROUND, PANEL_INPUT_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } 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';
import { Dimension, trackFocus } from 'vs/base/browser/dom';
import { Dimension, trackFocus, addClass, toggleClass, EventHelper } from 'vs/base/browser/dom';
import { localize } from 'vs/nls';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@@ -38,7 +38,7 @@ import { MenuId } from 'vs/platform/actions/common/actions';
import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { Before2D } from 'vs/workbench/browser/dnd';
import { Before2D, CompositeDragAndDropObserver, ICompositeDragAndDrop } from 'vs/workbench/browser/dnd';
import { IActivity } from 'vs/workbench/common/activity';
interface ICachedPanel {
@@ -96,6 +96,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
private panelRegistry: PanelRegistry;
private dndHandler: ICompositeDragAndDrop;
constructor(
@INotificationService notificationService: INotificationService,
@IStorageService storageService: IStorageService,
@@ -132,10 +134,15 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
this.panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
storageKeysSyncRegistryService.registerStorageKey({ key: PanelPart.PINNED_PANELS, version: 1 });
this.dndHandler = new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel,
(id: string, focus?: boolean) => (<unknown>this.openPanel(id, focus) as Promise<IPaneComposite | undefined>).then(panel => panel || null),
(from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.horizontallyBefore)
);
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.getCachedPanels(), {
icon: false,
orientation: ActionsOrientation.HORIZONTAL,
openComposite: (compositeId: string) => this.openPanel(compositeId, true),
openComposite: (compositeId: string) => this.openPanel(compositeId, true).then(panel => panel || null),
getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction,
getCompositePinnedAction: (compositeId: string) => this.getCompositeActions(compositeId).pinnedAction,
getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(PanelActivityAction, assertIsDefined(this.getPanel(compositeId))),
@@ -149,10 +156,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
getContextMenuActionsForComposite: (compositeId: string) => this.getContextMenuActionsForComposite(compositeId) as Action[],
getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(),
hidePart: () => this.layoutService.setPanelHidden(true),
dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel,
(id: string, focus?: boolean) => <unknown>this.openPanel(id, focus) as Promise<IPaneComposite | undefined>, // {{SQL CARBON EDIT}} strict-null-checks
(from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.horizontallyBefore)
),
dndHandler: this.dndHandler,
compositeSize: 0,
overflowActionSize: 44,
colors: (theme: IColorTheme) => ({
@@ -192,7 +196,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
for (const panel of panels) {
const cachedPanel = this.getCachedPanels().filter(({ id }) => id === panel.id)[0];
const activePanel = this.getActivePanel();
const isActive = activePanel?.getId() === panel.id;
const isActive = activePanel?.getId() === panel.id || (!activePanel && this.getLastActivePanelId() === panel.id);
if (isActive || !this.shouldBeHidden(panel.id, cachedPanel)) {
this.compositeBar.addComposite(panel);
@@ -203,6 +207,10 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
if (isActive) {
if (!activePanel) {
this.doOpenPanel(panel.id);
}
this.compositeBar.activateComposite(panel.id);
}
}
@@ -352,6 +360,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
this.layoutCompositeBar(); // Need to relayout composite bar since different panels have different action bar width
this.layoutEmptyMessage();
}
private onPanelClose(panel: IPanel): void {
@@ -362,6 +371,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
this.compositeBar.deactivateComposite(panel.getId());
this.layoutEmptyMessage();
}
create(parent: HTMLElement): void {
@@ -369,11 +379,51 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
super.create(parent);
this.createEmptyPanelMessage();
const focusTracker = this._register(trackFocus(parent));
this._register(focusTracker.onDidFocus(() => this.panelFocusContextKey.set(true)));
this._register(focusTracker.onDidBlur(() => this.panelFocusContextKey.set(false)));
}
private createEmptyPanelMessage(): void {
this.emptyPanelMessageElement = document.createElement('div');
addClass(this.emptyPanelMessageElement, 'empty-panel-message-area');
const messageElement = document.createElement('div');
addClass(messageElement, 'empty-panel-message');
messageElement.innerText = localize('panel.emptyMessage', "No panels to display. Drag a view into the panel.");
this.emptyPanelMessageElement.appendChild(messageElement);
this.element.appendChild(this.emptyPanelMessageElement);
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(this.emptyPanelMessageElement, {
onDragOver: (e) => {
EventHelper.stop(e.eventData, true);
},
onDragEnter: (e) => {
EventHelper.stop(e.eventData, true);
const validDropTarget = this.dndHandler.onDragEnter(e.dragAndDropData, undefined, e.eventData);
this.emptyPanelMessageElement!.style.backgroundColor = validDropTarget ? this.theme.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND)?.toString() || '' : '';
},
onDragLeave: (e) => {
EventHelper.stop(e.eventData, true);
this.emptyPanelMessageElement!.style.backgroundColor = '';
},
onDragEnd: (e) => {
EventHelper.stop(e.eventData, true);
this.emptyPanelMessageElement!.style.backgroundColor = '';
},
onDrop: (e) => {
EventHelper.stop(e.eventData, true);
this.emptyPanelMessageElement!.style.backgroundColor = '';
this.dndHandler.drop(e.dragAndDropData, undefined, e.eventData);
},
}));
}
updateStyles(): void {
super.updateStyles();
@@ -508,6 +558,9 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
// Layout composite bar
this.layoutCompositeBar();
// Add empty panel message
this.layoutEmptyMessage();
}
private layoutCompositeBar(): void {
@@ -521,6 +574,13 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
}
private emptyPanelMessageElement: HTMLElement | undefined;
private layoutEmptyMessage(): void {
if (this.emptyPanelMessageElement) {
toggleClass(this.emptyPanelMessageElement, 'visible', this.compositeBar.getVisibleComposites().length === 0);
}
}
private getCompositeActions(compositeId: string): { activityAction: PanelActivityAction, pinnedAction: ToggleCompositePinnedAction; } {
let compositeActions = this.compositeActions.get(compositeId);
if (!compositeActions) {

View File

@@ -109,7 +109,7 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
themeService,
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets),
SidebarPart.activeViewletSettingsKey,
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).getDefaultViewletId(),
viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)!.id,
'sideBar',
'viewlet',
SIDE_BAR_TITLE_FOREGROUND,
@@ -142,7 +142,7 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
if (activeContainers.length) {
if (this.getActiveComposite()?.getId() === viewletDescriptor.id) {
const defaultViewletId = this.getDefaultViewletId();
const defaultViewletId = this.viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id;
const containerToOpen = activeContainers.filter(c => c.id === defaultViewletId)[0] || activeContainers[0];
await this.openViewlet(containerToOpen.id);
}
@@ -253,10 +253,6 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
});
}
getDefaultViewletId(): string {
return this.viewletRegistry.getDefaultViewletId();
}
getViewlet(id: string): ViewletDescriptor {
return this.getViewlets().filter(viewlet => viewlet.id === id)[0];
}

View File

@@ -27,7 +27,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { coalesce, find } from 'vs/base/common/arrays';
import { coalesce } from 'vs/base/common/arrays';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { ToggleStatusbarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
@@ -181,7 +181,7 @@ class StatusbarViewModel extends Disposable {
}
findEntry(container: HTMLElement): IStatusbarViewModelEntry | undefined {
return find(this._entries, entry => entry.container === container);
return this._entries.find(entry => entry.container === container);
}
getEntries(alignment: StatusbarAlignment): IStatusbarViewModelEntry[] {

View File

@@ -72,7 +72,7 @@ export class TitlebarPart extends Part implements ITitleService {
private isInactive: boolean = false;
private readonly properties: ITitleProperties = { isPure: true, isAdmin: false };
private readonly properties: ITitleProperties = { isPure: true, isAdmin: false, prefix: undefined };
private readonly activeEditorListeners = this._register(new DisposableStore());
private readonly titleUpdater = this._register(new RunOnceScheduler(() => this.doUpdateTitle(), 0));
@@ -191,6 +191,10 @@ export class TitlebarPart extends Part implements ITitleService {
private getWindowTitle(): string {
let title = this.doGetWindowTitle();
if (this.properties.prefix) {
title = `${this.properties.prefix} ${title || this.productService.nameLong}`;
}
if (this.properties.isAdmin) {
title = `${title || this.productService.nameLong} ${TitlebarPart.NLS_USER_IS_ADMIN}`;
}
@@ -212,10 +216,12 @@ export class TitlebarPart extends Part implements ITitleService {
updateProperties(properties: ITitleProperties): void {
const isAdmin = typeof properties.isAdmin === 'boolean' ? properties.isAdmin : this.properties.isAdmin;
const isPure = typeof properties.isPure === 'boolean' ? properties.isPure : this.properties.isPure;
const prefix = typeof properties.prefix === 'string' ? properties.prefix : this.properties.prefix;
if (isAdmin !== this.properties.isAdmin || isPure !== this.properties.isPure) {
if (isAdmin !== this.properties.isAdmin || isPure !== this.properties.isPure || prefix !== this.properties.prefix) {
this.properties.isAdmin = isAdmin;
this.properties.isPure = isPure;
this.properties.prefix = prefix;
this.titleUpdater.schedule();
}

View File

@@ -5,7 +5,7 @@
import 'vs/css!./media/views';
import { Disposable, IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IViewDescriptorService, ViewContainer, IViewDescriptor, IViewContainersRegistry, Extensions as ViewExtensions, IView, ViewContainerLocation, IViewsService, IViewPaneContainer, getVisbileViewContextKey } from 'vs/workbench/common/views';
import { IViewDescriptorService, ViewContainer, IViewDescriptor, IView, ViewContainerLocation, IViewsService, IViewPaneContainer, getVisbileViewContextKey } from 'vs/workbench/common/views';
import { Registry } from 'vs/platform/registry/common/platform';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
@@ -15,7 +15,6 @@ import { isString } from 'vs/base/common/types';
import { MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { localize } from 'vs/nls';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { toggleClass, addClass } from 'vs/base/browser/dom';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
@@ -23,7 +22,7 @@ import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiati
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { PaneCompositePanel, PanelRegistry, PanelDescriptor, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService, IFileIconTheme } from 'vs/platform/theme/common/themeService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
@@ -37,15 +36,16 @@ export class ViewsService extends Disposable implements IViewsService {
_serviceBrand: undefined;
private readonly viewContainersRegistry: IViewContainersRegistry;
private readonly viewDisposable: Map<IViewDescriptor, IDisposable>;
private readonly viewPaneContainers: Map<string, { viewPaneContainer: ViewPaneContainer, disposable: IDisposable }>;
private readonly _onDidChangeViewVisibility: Emitter<{ id: string, visible: boolean }> = this._register(new Emitter<{ id: string, visible: boolean }>());
readonly onDidChangeViewVisibility: Event<{ id: string, visible: boolean }> = this._onDidChangeViewVisibility.event;
private readonly visibleViewContextKeys: Map<string, IContextKey<boolean>>;
private readonly _onDidChangeViewContainerVisibility = this._register(new Emitter<{ id: string, visible: boolean, location: ViewContainerLocation }>());
readonly onDidChangeViewContainerVisibility = this._onDidChangeViewContainerVisibility.event;
private readonly visibleViewContextKeys: Map<string, IContextKey<boolean>>;
constructor(
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@@ -56,7 +56,6 @@ export class ViewsService extends Disposable implements IViewsService {
) {
super();
this.viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry);
this.viewDisposable = new Map<IViewDescriptor, IDisposable>();
this.visibleViewContextKeys = new Map<string, IContextKey<boolean>>();
this.viewPaneContainers = new Map<string, { viewPaneContainer: ViewPaneContainer, disposable: IDisposable }>();
@@ -66,10 +65,16 @@ export class ViewsService extends Disposable implements IViewsService {
this.viewDisposable.clear();
}));
this.viewDescriptorService.getViewContainers().forEach(viewContainer => this.onDidRegisterViewContainer(viewContainer, this.viewDescriptorService.getViewContainerLocation(viewContainer)!));
this._register(this.viewContainersRegistry.onDidRegister(({ viewContainer }) => this.onDidRegisterViewContainer(viewContainer, this.viewDescriptorService.getViewContainerLocation(viewContainer)!)));
this._register(this.viewContainersRegistry.onDidDeregister(e => this.deregisterViewPaneContainer(e.viewContainer.id)));
this.viewDescriptorService.viewContainers.forEach(viewContainer => this.onDidRegisterViewContainer(viewContainer, this.viewDescriptorService.getViewContainerLocation(viewContainer)!));
this._register(this.viewDescriptorService.onDidChangeViewContainers(({ added, removed }) => this.onDidChangeContainers(added, removed)));
this._register(this.viewDescriptorService.onDidChangeContainerLocation(({ viewContainer, from, to }) => this.onDidChangeContainerLocation(viewContainer, from, to)));
// View Container Visibility
this._register(this.viewletService.onDidViewletOpen(viewlet => this._onDidChangeViewContainerVisibility.fire({ id: viewlet.getId(), visible: true, location: ViewContainerLocation.Sidebar })));
this._register(this.panelService.onDidPanelOpen(e => this._onDidChangeViewContainerVisibility.fire({ id: e.panel.getId(), visible: true, location: ViewContainerLocation.Panel })));
this._register(this.viewletService.onDidViewletClose(viewlet => this._onDidChangeViewContainerVisibility.fire({ id: viewlet.getId(), visible: false, location: ViewContainerLocation.Sidebar })));
this._register(this.panelService.onDidPanelClose(panel => this._onDidChangeViewContainerVisibility.fire({ id: panel.getId(), visible: false, location: ViewContainerLocation.Panel })));
}
private registerViewPaneContainer(viewPaneContainer: ViewPaneContainer): void {
@@ -117,6 +122,15 @@ export class ViewsService extends Disposable implements IViewsService {
return contextKey;
}
private onDidChangeContainers(added: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation }>, removed: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation }>): void {
for (const { container, location } of removed) {
this.deregisterViewletOrPanel(container, location);
}
for (const { container, location } of added) {
this.registerViewletOrPanel(container, location);
}
}
private onDidChangeContainerLocation(viewContainer: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation): void {
this.deregisterViewletOrPanel(viewContainer, from);
this.registerViewletOrPanel(viewContainer, to);
@@ -226,6 +240,62 @@ export class ViewsService extends Disposable implements IViewsService {
return undefined;
}
isViewContainerVisible(id: string): boolean {
const viewContainer = this.viewDescriptorService.getViewContainerById(id);
if (viewContainer) {
const viewContainerLocation = this.viewDescriptorService.getViewContainerLocation(viewContainer);
switch (viewContainerLocation) {
case ViewContainerLocation.Panel:
return this.panelService.getActivePanel()?.getId() === id;
case ViewContainerLocation.Sidebar:
return this.viewletService.getActiveViewlet()?.getId() === id;
}
}
return false;
}
getVisibleViewContainer(location: ViewContainerLocation): ViewContainer | null {
let viewContainerId: string | undefined = undefined;
switch (location) {
case ViewContainerLocation.Panel:
viewContainerId = this.panelService.getActivePanel()?.getId();
break;
case ViewContainerLocation.Sidebar:
viewContainerId = this.viewletService.getActiveViewlet()?.getId();
break;
}
return viewContainerId ? this.viewDescriptorService.getViewContainerById(viewContainerId) : null;
}
async openViewContainer(id: string, focus?: boolean): Promise<IPaneComposite | null> {
const viewContainer = this.viewDescriptorService.getViewContainerById(id);
if (viewContainer) {
const viewContainerLocation = this.viewDescriptorService.getViewContainerLocation(viewContainer);
switch (viewContainerLocation) {
case ViewContainerLocation.Panel:
const panel = await this.panelService.openPanel(id, focus);
return panel as IPaneComposite;
case ViewContainerLocation.Sidebar:
const viewlet = await this.viewletService.openViewlet(id, focus);
return viewlet || null;
}
}
return null;
}
async closeViewContainer(id: string): Promise<void> {
const viewContainer = this.viewDescriptorService.getViewContainerById(id);
if (viewContainer) {
const viewContainerLocation = this.viewDescriptorService.getViewContainerLocation(viewContainer);
switch (viewContainerLocation) {
case ViewContainerLocation.Panel:
return this.panelService.getActivePanel()?.getId() === id ? this.panelService.hideActivePanel() : undefined;
case ViewContainerLocation.Sidebar:
return this.viewletService.getActiveViewlet()?.getId() === id ? this.viewletService.hideActiveViewlet() : undefined;
}
}
}
isViewVisible(id: string): boolean {
const activeView = this.getActiveViewWithId(id);
return activeView?.isBodyVisible() || false;
@@ -306,13 +376,13 @@ export class ViewsService extends Disposable implements IViewsService {
return null;
}
getProgressIndicator(id: string): IProgressIndicator | undefined {
const viewContainer = this.viewDescriptorService.getViewContainerByViewId(id);
getViewProgressIndicator(viewId: string): IProgressIndicator | undefined {
const viewContainer = this.viewDescriptorService.getViewContainerByViewId(viewId);
if (viewContainer === null) {
return undefined;
}
const view = this.viewPaneContainers.get(viewContainer.id)?.viewPaneContainer?.getView(id);
const view = this.viewPaneContainers.get(viewContainer.id)?.viewPaneContainer?.getView(viewId);
return view?.getProgressIndicator();
}
@@ -411,17 +481,4 @@ export class ViewsService extends Disposable implements IViewsService {
}
}
export function createFileIconThemableTreeContainerScope(container: HTMLElement, themeService: IThemeService): 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);
}
registerSingleton(IViewsService, ViewsService);

View File

@@ -20,7 +20,6 @@ import { URI } from 'vs/base/common/uri';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
import { AbstractTree } from 'vs/base/browser/ui/tree/abstractTree';
import { assertIsDefined } from 'vs/base/common/types';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
@@ -97,7 +96,6 @@ export const Extensions = {
};
export class ViewletRegistry extends CompositeRegistry<Viewlet> {
private defaultViewletId: string | undefined;
/**
* Registers a viewlet to the platform.
@@ -110,9 +108,6 @@ export class ViewletRegistry extends CompositeRegistry<Viewlet> {
* Deregisters a viewlet to the platform.
*/
deregisterViewlet(id: string): void {
if (id === this.defaultViewletId) {
throw new Error('Cannot deregister default viewlet');
}
super.deregisterComposite(id);
}
@@ -130,19 +125,6 @@ export class ViewletRegistry extends CompositeRegistry<Viewlet> {
return this.getComposites() as ViewletDescriptor[];
}
/**
* Sets the id of the viewlet that should open on startup by default.
*/
setDefaultViewletId(id: string): void {
this.defaultViewletId = id;
}
/**
* Gets the id of the viewlet that should open on startup by default.
*/
getDefaultViewletId(): string {
return assertIsDefined(this.defaultViewletId);
}
}
Registry.add(Extensions.Viewlets, new ViewletRegistry());

View File

@@ -46,6 +46,7 @@ import { Layout } from 'vs/workbench/browser/layout';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { ILanguageAssociationRegistry, Extensions as LanguageExtensions } from 'sql/workbench/services/languageAssociation/common/languageAssociation';
import { Extensions as PanelExtensions, PanelRegistry } from 'vs/workbench/browser/panel';
import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
export class Workbench extends Layout {
@@ -164,7 +165,7 @@ export class Workbench extends Layout {
// Restore
try {
await this.restoreWorkbench(accessor.get(IEditorService), accessor.get(IEditorGroupsService), accessor.get(IViewletService), accessor.get(IPanelService), accessor.get(ILogService), lifecycleService);
await this.restoreWorkbench(accessor.get(IEditorService), accessor.get(IEditorGroupsService), accessor.get(IViewDescriptorService), accessor.get(IViewletService), accessor.get(IPanelService), accessor.get(ILogService), lifecycleService);
} catch (error) {
onUnexpectedError(error);
}
@@ -402,6 +403,7 @@ export class Workbench extends Layout {
private async restoreWorkbench(
editorService: IEditorService,
editorGroupService: IEditorGroupsService,
viewDescriptorService: IViewDescriptorService,
viewletService: IViewletService,
panelService: IPanelService,
logService: ILogService,
@@ -438,7 +440,7 @@ export class Workbench extends Layout {
const viewlet = await viewletService.openViewlet(this.state.sideBar.viewletToRestore);
if (!viewlet) {
await viewletService.openViewlet(viewletService.getDefaultViewletId()); // fallback to default viewlet as needed
await viewletService.openViewlet(viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id); // fallback to default viewlet as needed
}
mark('didRestoreViewlet');