Merge from vscode 27ada910e121e23a6d95ecca9cae595fb98ab568

This commit is contained in:
ADS Merger
2020-04-30 00:53:43 +00:00
parent 87e5239713
commit 93f35ca321
413 changed files with 7190 additions and 8756 deletions

View File

@@ -498,6 +498,12 @@ export class ResetViewLocationsAction extends Action {
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], defaultContainer);
}
});
const defaultContainerLocation = this.viewDescriptorService.getDefaultViewContainerLocation(viewContainer);
const currentContainerLocation = this.viewDescriptorService.getViewContainerLocation(viewContainer);
if (defaultContainerLocation !== null && currentContainerLocation !== defaultContainerLocation) {
this.viewDescriptorService.moveViewContainerToLocation(viewContainer, defaultContainerLocation);
}
});
}
}

View File

@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys';
import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorIsReadonlyContext, EditorAreaVisibleContext, DirtyWorkingCopiesContext, ActiveEditorAvailableEditorsContext } from 'vs/workbench/common/editor';
import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorIsReadonlyContext, EditorAreaVisibleContext, DirtyWorkingCopiesContext, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -41,7 +41,7 @@ export class WorkbenchContextKeysHandler extends Disposable {
private activeEditorContext: IContextKey<string | null>;
private activeEditorIsReadonly: IContextKey<boolean>;
private activeEditorAvailableEditors: IContextKey<string>;
private activeEditorAvailableEditorIds: IContextKey<string>;
private activeEditorGroupEmpty: IContextKey<boolean>;
private activeEditorGroupIndex: IContextKey<number>;
@@ -92,7 +92,7 @@ export class WorkbenchContextKeysHandler extends Disposable {
// Editors
this.activeEditorContext = ActiveEditorContext.bindTo(this.contextKeyService);
this.activeEditorIsReadonly = ActiveEditorIsReadonlyContext.bindTo(this.contextKeyService);
this.activeEditorAvailableEditors = ActiveEditorAvailableEditorsContext.bindTo(this.contextKeyService);
this.activeEditorAvailableEditorIds = ActiveEditorAvailableEditorIdsContext.bindTo(this.contextKeyService);
this.editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
this.textCompareEditorVisibleContext = TextCompareEditorVisibleContext.bindTo(this.contextKeyService);
this.textCompareEditorActiveContext = TextCompareEditorActiveContext.bindTo(this.contextKeyService);
@@ -210,12 +210,12 @@ export class WorkbenchContextKeysHandler extends Disposable {
this.activeEditorContext.set(activeEditorPane.getId());
this.activeEditorIsReadonly.set(activeEditorPane.input.isReadonly());
const editors = this.editorService.getEditorOverrides(activeEditorPane.input, undefined, activeGroup);
this.activeEditorAvailableEditors.set(editors.map(([_, entry]) => entry.id).join(','));
const editors = activeEditorPane.input.resource ? this.editorService.getEditorOverrides(activeEditorPane.input.resource, undefined, activeGroup) : [];
this.activeEditorAvailableEditorIds.set(editors.map(([_, entry]) => entry.id).join(','));
} else {
this.activeEditorContext.reset();
this.activeEditorIsReadonly.reset();
this.activeEditorAvailableEditors.reset();
this.activeEditorAvailableEditorIds.reset();
}
}

View File

@@ -23,7 +23,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { LifecyclePhase, StartupKind, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility } from 'vs/platform/windows/common/windows';
import { MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, IPath } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IEditor } from 'vs/editor/common/editorCommon';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
@@ -41,6 +41,8 @@ import { INotificationService, NotificationsFilter } from 'vs/platform/notificat
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { WINDOW_ACTIVE_BORDER, WINDOW_INACTIVE_BORDER } from 'vs/workbench/common/theme';
import { LineNumbersType } from 'vs/editor/common/config/editorOptions';
import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart';
import { URI } from 'vs/base/common/uri';
enum Settings {
ACTIVITYBAR_VISIBLE = 'workbench.activityBar.visible',
@@ -82,6 +84,21 @@ enum Classes {
WINDOW_BORDER = 'border'
}
interface PanelActivityState {
id: string;
name?: string;
pinned: boolean;
order: number;
visible: boolean;
}
interface SideBarActivityState {
id: string;
pinned: boolean;
order: number;
visible: boolean;
}
export abstract class Layout extends Disposable implements IWorkbenchLayoutService {
_serviceBrand: undefined;
@@ -450,6 +467,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
private initLayoutState(lifecycleService: ILifecycleService, fileService: IFileService): void {
this.applyDefaultLayout(this.environmentService, this.storageService);
// Fullscreen
this.state.fullscreen = isFullscreen();
@@ -471,7 +489,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
// Only restore last viewlet if window was reloaded or we are in development mode
let viewletToRestore: string;
if (!this.environmentService.isBuilt || lifecycleService.startupKind === StartupKind.ReloadedWindow) {
if (!this.environmentService.isBuilt || lifecycleService.startupKind === StartupKind.ReloadedWindow || isWeb) {
viewletToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, this.viewletService.getDefaultViewletId());
} else {
viewletToRestore = this.viewletService.getDefaultViewletId();
@@ -527,18 +545,181 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
private applyDefaultLayout(environmentService: IWorkbenchEnvironmentService, storageService: IStorageService) {
const defaultLayout = environmentService.options?.defaultLayout;
if (!defaultLayout || !defaultLayout.firstRun) {
return;
}
const { sidebar } = defaultLayout;
if (sidebar) {
if (sidebar.visible !== undefined) {
if (sidebar.visible) {
storageService.remove(Storage.SIDEBAR_HIDDEN, StorageScope.WORKSPACE);
} else {
storageService.store(Storage.SIDEBAR_HIDDEN, true, StorageScope.WORKSPACE);
}
}
if (sidebar.containers?.length) {
const sidebarState: SideBarActivityState[] = [];
let order = -1;
for (const container of sidebar.containers.sort((a, b) => (a.order ?? 1) - (b.order ?? 1))) {
let viewletId;
switch (container.id) {
case 'explorer':
viewletId = 'workbench.view.explorer';
break;
case 'run':
viewletId = 'workbench.view.debug';
break;
case 'scm':
viewletId = 'workbench.view.scm';
break;
case 'search':
viewletId = 'workbench.view.search';
break;
case 'extensions':
viewletId = 'workbench.view.extensions';
break;
case 'remote':
viewletId = 'workbench.view.remote';
break;
default:
viewletId = `workbench.view.extension.${container.id}`;
}
if (container.active) {
storageService.store(SidebarPart.activeViewletSettingsKey, viewletId, StorageScope.WORKSPACE);
}
if (container.order !== undefined || (container.active === undefined && (<any>container).visible !== undefined)) { // {{SQL CARBON EDIT}} strict-null-checks
order = container.order ?? (order + 1);
const state: SideBarActivityState = {
id: viewletId,
order: order,
pinned: (container.active || (<any>container).visible) ?? true, // {{SQL CARBON EDIT}} strict-null-checks
visible: (container.active || (<any>container).visible) ?? true // {{SQL CARBON EDIT}} strict-null-checks
};
sidebarState.push(state);
}
if (container.views !== undefined) {
const viewsState: { id: string, isHidden?: boolean, order?: number }[] = [];
const viewsWorkspaceState: { [id: string]: { collapsed: boolean, isHidden?: boolean, size?: number } } = {};
for (const view of container.views) {
if (view.order !== undefined || view.visible !== undefined) {
viewsState.push({
id: view.id,
isHidden: view.visible === undefined ? undefined : !view.visible,
order: view.order === undefined ? undefined : view.order
});
}
if (view.collapsed !== undefined) {
viewsWorkspaceState[view.id] = {
collapsed: view.collapsed,
isHidden: view.visible === undefined ? undefined : !view.visible,
};
}
}
storageService.store(`${viewletId}.state.hidden`, JSON.stringify(viewsState), StorageScope.GLOBAL);
storageService.store(`${viewletId}.state`, JSON.stringify(viewsWorkspaceState), StorageScope.WORKSPACE);
}
}
if (sidebarState.length) {
storageService.store(ActivitybarPart.PINNED_VIEWLETS, JSON.stringify(sidebarState), StorageScope.GLOBAL);
}
}
}
const { panel } = defaultLayout;
if (panel) {
if (panel.visible !== undefined) {
if (panel.visible) {
storageService.store(Storage.PANEL_HIDDEN, false, StorageScope.WORKSPACE);
} else {
storageService.remove(Storage.PANEL_HIDDEN, StorageScope.WORKSPACE);
}
}
if (panel.containers?.length) {
const panelState: PanelActivityState[] = [];
let order = -1;
for (const container of panel.containers.sort((a, b) => (a.order ?? 1) - (b.order ?? 1))) {
let name;
let panelId = container.id;
switch (panelId) {
case 'terminal':
name = 'Terminal';
panelId = 'workbench.panel.terminal';
break;
case 'debug':
name = 'Debug Console';
panelId = 'workbench.panel.repl';
break;
case 'problems':
name = 'Problems';
panelId = 'workbench.panel.markers';
break;
case 'output':
name = 'Output';
panelId = 'workbench.panel.output';
break;
case 'comments':
name = 'Comments';
panelId = 'workbench.panel.comments';
break;
case 'refactor':
name = 'Refactor Preview';
panelId = 'refactorPreview';
break;
default:
continue;
}
if (container.active) {
storageService.store(PanelPart.activePanelSettingsKey, panelId, StorageScope.WORKSPACE);
}
if (container.order !== undefined || (container.active === undefined && (<any>container).visible !== undefined)) { // {{SQL CARBON EDIT}} strict-null-checks
order = container.order ?? (order + 1);
const state: PanelActivityState = {
id: panelId,
name: name,
order: order,
pinned: (container.active || (<any>container).visible) ?? true, // {{SQL CARBON EDIT}} strict-null-checks
visible: (container.active || (<any>container).visible) ?? true // {{SQL CARBON EDIT}} strict-null-checks
};
panelState.push(state);
}
}
if (panelState.length) {
storageService.store(PanelPart.PINNED_PANELS, JSON.stringify(panelState), StorageScope.GLOBAL);
}
}
}
}
private resolveEditorsToOpen(fileService: IFileService): Promise<IResourceEditorInputType[]> | IResourceEditorInputType[] {
const configuration = this.environmentService.configuration;
const hasInitialFilesToOpen = this.hasInitialFilesToOpen();
const initialFilesToOpen = this.getInitialFilesToOpen();
// Only restore editors if we are not instructed to open files initially
this.state.editor.restoreEditors = !hasInitialFilesToOpen;
this.state.editor.restoreEditors = initialFilesToOpen === undefined;
// Files to open, diff or create
if (hasInitialFilesToOpen) {
if (initialFilesToOpen !== undefined) {
// Files to diff is exclusive
return pathsToEditors(configuration.filesToDiff, fileService).then(filesToDiff => {
return pathsToEditors(initialFilesToOpen.filesToDiff, fileService).then(filesToDiff => {
if (filesToDiff?.length === 2) {
return [{
leftResource: filesToDiff[0].resource,
@@ -549,7 +730,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
// Otherwise: Open/Create files
return pathsToEditors(configuration.filesToOpenOrCreate, fileService);
return pathsToEditors(initialFilesToOpen.filesToOpenOrCreate, fileService);
});
}
@@ -571,13 +752,26 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
return [];
}
private hasInitialFilesToOpen(): boolean {
const configuration = this.environmentService.configuration;
private getInitialFilesToOpen(): { filesToOpenOrCreate?: IPath[], filesToDiff?: IPath[] } | undefined {
const defaultLayout = this.environmentService.options?.defaultLayout;
if (defaultLayout?.firstRun && defaultLayout?.editors?.length) {
//
return {
filesToOpenOrCreate: defaultLayout.editors
.sort((a, b) => (a.active ? -1 : 1) - (b.active ? -1 : 1))
.map(f => ({ fileUri: URI.file(f.path).with({ scheme: f.scheme }), inactive: !f.active }))
};
}
return !!(
(configuration.filesToOpenOrCreate && configuration.filesToOpenOrCreate.length > 0) ||
(configuration.filesToDiff && configuration.filesToDiff.length > 0)
);
const configuration = this.environmentService.configuration;
if (configuration.filesToOpenOrCreate || configuration.filesToDiff) {
return {
filesToOpenOrCreate: configuration.filesToOpenOrCreate,
filesToDiff: configuration.filesToDiff
};
}
return undefined;
}
private updatePanelPosition() {

View File

@@ -59,8 +59,8 @@ export class PaneComposite extends Composite implements IPaneComposite {
return this.viewPaneContainer.getOptimalWidth();
}
openView(id: string, focus?: boolean): IView {
return this.viewPaneContainer.openView(id, focus);
openView<T extends IView>(id: string, focus?: boolean): T | undefined {
return this.viewPaneContainer.openView(id, focus) as T;
}
getViewPaneContainer(): ViewPaneContainer {

View File

@@ -73,7 +73,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
_serviceBrand: undefined;
private static readonly ACTION_HEIGHT = 48;
private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets2';
static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets2';
private static readonly PLACEHOLDER_VIEWLETS = 'workbench.activity.placeholderViewlets';
//#region IView
@@ -87,6 +87,9 @@ export class ActivitybarPart extends Part implements IActivityBarService {
private content: HTMLElement | undefined;
private homeBar: ActionBar | undefined;
private homeBarContainer: HTMLElement | undefined;
private menuBar: CustomMenubarControl | undefined;
private menuBarContainer: HTMLElement | undefined;
@@ -155,7 +158,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
(id: string, focus?: boolean) => this.viewletService.openViewlet(id, focus),
(from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.verticallyBefore)
),
compositeSize: 50,
compositeSize: 52,
colors: (theme: IColorTheme) => this.getActivitybarItemColors(theme),
overflowActionSize: ActivitybarPart.ACTION_HEIGHT
}));
@@ -353,20 +356,20 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
private createHomeBar(command: string, title: string, icon: Codicon): void {
const homeBarContainer = document.createElement('div');
homeBarContainer.setAttribute('aria-label', nls.localize('homeIndicator', "Home"));
homeBarContainer.setAttribute('role', 'toolbar');
addClass(homeBarContainer, 'home-bar');
this.homeBarContainer = document.createElement('div');
this.homeBarContainer.setAttribute('aria-label', nls.localize('homeIndicator', "Home"));
this.homeBarContainer.setAttribute('role', 'toolbar');
addClass(this.homeBarContainer, 'home-bar');
const homeActionBar = this._register(new ActionBar(homeBarContainer, {
this.homeBar = this._register(new ActionBar(this.homeBarContainer, {
orientation: ActionsOrientation.VERTICAL,
animated: false
}));
homeActionBar.push(this._register(this.instantiationService.createInstance(HomeAction, command, title, icon)), { icon: true, label: false });
this.homeBar.push(this._register(this.instantiationService.createInstance(HomeAction, command, title, icon)), { icon: true, label: false });
const content = assertIsDefined(this.content);
content.prepend(homeBarContainer);
content.prepend(this.homeBarContainer);
}
updateStyles(): void {
@@ -582,12 +585,15 @@ export class ActivitybarPart extends Part implements IActivityBarService {
// Layout composite bar
let availableHeight = contentAreaSize.height;
if (this.globalActivityActionBar) {
availableHeight -= (this.globalActivityActionBar.viewItems.length * ActivitybarPart.ACTION_HEIGHT); // adjust height for global actions showing
if (this.homeBarContainer) {
availableHeight -= this.homeBarContainer.clientHeight;
}
if (this.menuBarContainer) {
availableHeight -= this.menuBarContainer.clientHeight;
}
if (this.globalActivityActionBar) {
availableHeight -= (this.globalActivityActionBar.viewItems.length * ActivitybarPart.ACTION_HEIGHT); // adjust height for global actions showing
}
this.compositeBar.layout(new Dimension(width, availableHeight));
}
@@ -640,10 +646,11 @@ export class ActivitybarPart extends Part implements IActivityBarService {
for (const { when } of viewContainerModel.allViewDescriptors) {
views.push({ when: when ? when.serialize() : undefined });
}
const cacheIcon = URI.isUri(viewContainerModel.icon) ? viewContainerModel.icon.scheme === Schemas.file : true;
state.push({
id: compositeItem.id,
name: viewContainerModel.title,
icon: URI.isUri(viewContainerModel.icon) && viewContainerModel.icon.scheme === Schemas.file ? viewContainerModel.icon : viewContainerModel.icon,
icon: cacheIcon ? viewContainerModel.icon : undefined,
views,
pinned: compositeItem.pinned,
order: compositeItem.order,

View File

@@ -5,6 +5,7 @@
.monaco-workbench .part.activitybar {
width: 48px;
height: 100%;
}
.monaco-workbench .activitybar > .content {
@@ -17,7 +18,7 @@
/*
* Fix menu jumping and background inheritance in Safari
*/
.monaco-workbench .activitybar > .content {
.monaco-workbench.safari .activitybar > .content {
position: absolute;
background-color: inherit;
}

View File

@@ -59,19 +59,10 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
return;
}
this.viewDescriptorService.moveViewToLocation(viewsToMove[0], this.targetContainerLocation);
const newContainer = this.viewDescriptorService.getViewContainerById(viewsToMove[0].id)!;
this.moveComposite(newContainer.id, targetCompositeId, before);
this.viewDescriptorService.moveViewContainerToLocation(currentContainer, this.targetContainerLocation);
this.moveComposite(currentContainer.id, targetCompositeId, before);
if (viewsToMove.length > 1) {
this.viewDescriptorService.moveViewsToContainer(viewsToMove.slice(1), newContainer);
}
this.openComposite(newContainer.id, true).then(composite => {
if (composite && viewsToMove.length === 1) {
composite.openView(viewsToMove[0].id, true);
}
});
this.openComposite(currentContainer.id, true);
}
}
@@ -240,6 +231,9 @@ export class CompositeBar extends Widget implements ICompositeBar {
onDragLeave: (e: IDraggedCompositeData) => {
toggleClass(parent, 'dragged-over', false);
},
onDragEnd: (e: IDraggedCompositeData) => {
toggleClass(parent, 'dragged-over', false);
},
onDrop: (e: IDraggedCompositeData) => {
const pinnedItems = this.getPinnedComposites();
this.options.dndHandler.drop(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData, { horizontallyBefore: false, verticallyBefore: false });

View File

@@ -17,7 +17,7 @@ import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { DelayedDragHandler } from 'vs/base/browser/dnd';
import { IActivity } from 'vs/workbench/common/activity';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Emitter } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { CompositeDragAndDropObserver, ICompositeDragAndDrop, Before2D } from 'vs/workbench/browser/dnd';
import { Color } from 'vs/base/common/color';
import { Codicon } from 'vs/base/common/codicons';
@@ -477,32 +477,34 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
CompositeActionViewItem.manageExtensionAction = instantiationService.createInstance(ManageExtensionAction);
}
this._register(compositeActivityAction.onDidChangeActivity(() => { this.compositeActivity = undefined; this.updateActivity(); }, this));
this._register(compositeActivityAction.onDidChangeActivity(() => {
this.compositeActivity = undefined;
this.updateActivity();
}, this));
this._register(Event.any(
compositeActivityAction.onDidChangeActivity,
Event.filter(keybindingService.onDidUpdateKeybindings, () => this.compositeActivity!.name !== this.getActivtyName())
)(() => {
if (this.compositeActivity && this.compositeActivity.name !== this.getActivtyName()) {
this.compositeActivity = undefined;
this.updateActivity();
}
}));
}
protected get activity(): IActivity {
if (!this.compositeActivity) {
let activityName: string;
const keybinding = typeof this.compositeActivityAction.activity.keybindingId === 'string' ? this.getKeybindingLabel(this.compositeActivityAction.activity.keybindingId) : null;
if (keybinding) {
activityName = nls.localize('titleKeybinding', "{0} ({1})", this.compositeActivityAction.activity.name, keybinding);
} else {
activityName = this.compositeActivityAction.activity.name;
}
this.compositeActivity = { ...this.compositeActivityAction.activity, ... { name: activityName } };
this.compositeActivity = {
...this.compositeActivityAction.activity,
... { name: this.getActivtyName() }
};
}
return this.compositeActivity;
}
private getKeybindingLabel(id: string): string | null {
const kb = this.keybindingService.lookupKeybinding(id);
if (kb) {
return kb.getLabel();
}
return null;
private getActivtyName(): string {
const keybinding = this.compositeActivityAction.activity.keybindingId ? this.keybindingService.lookupKeybinding(this.compositeActivityAction.activity.keybindingId) : null;
return keybinding ? nls.localize('titleKeybinding', "{0} ({1})", this.compositeActivityAction.activity.name, keybinding.getLabel()) : this.compositeActivityAction.activity.name;
}
render(container: HTMLElement): void {

View File

@@ -24,7 +24,6 @@ import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platf
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 { IAsyncDataSource, ITreeRenderer, ITreeNode, ITreeFilter, TreeVisibility, ITreeSorter } from 'vs/base/browser/ui/tree/tree';
import { OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItemComparator, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineDataSource, OutlineSortOrder, OutlineFilter, OutlineAccessibilityProvider } from 'vs/editor/contrib/documentSymbols/outlineTree';
import { IIdentityProvider, IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list';

View File

@@ -52,9 +52,7 @@ export function getEditorPartOptions(config: IWorkbenchEditorConfiguration): IEd
return options;
}
if (typeof config.workbench.iconTheme === 'string') {
options.iconTheme = config.workbench.iconTheme;
}
options.iconTheme = config.workbench.iconTheme;
if (config.workbench.editor) {
Object.assign(options, config.workbench.editor);

View File

@@ -21,6 +21,7 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo
import { ItemActivation, IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { AllEditorsByMostRecentlyUsedQuickAccess, ActiveGroupEditorsByMostRecentlyUsedQuickAccess, AllEditorsByAppearanceQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess';
import { Codicon } from 'vs/base/common/codicons';
import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
export class ExecuteCommandAction extends Action {
@@ -522,7 +523,8 @@ export abstract class BaseCloseAllAction extends Action {
private workingCopyService: IWorkingCopyService,
private fileDialogService: IFileDialogService,
protected editorGroupService: IEditorGroupsService,
private editorService: IEditorService
private editorService: IEditorService,
private filesConfigurationService: IFilesConfigurationService
) {
super(id, label, clazz);
}
@@ -562,31 +564,51 @@ export abstract class BaseCloseAllAction extends Action {
}));
const dirtyEditorsToConfirm = new Set<string>();
const dirtyEditorsToAutoSave = new Set<IEditorInput>();
for (const editor of this.editorService.editors) {
if (!editor.isDirty() || editor.isSaving()) {
continue; // only interested in dirty editors (unless in the process of saving)
}
let name: string;
if (editor instanceof SideBySideEditorInput) {
name = editor.master.getName(); // prefer shorter names by using master's name in this case
} else {
name = editor.getName();
// Auto-save on focus change: assume to Save unless the editor is untitled
// because bringing up a dialog would save in this case anyway.
if (this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.ON_FOCUS_CHANGE && !editor.isUntitled()) {
dirtyEditorsToAutoSave.add(editor);
}
dirtyEditorsToConfirm.add(name);
// No auto-save on focus change: ask user
else {
let name: string;
if (editor instanceof SideBySideEditorInput) {
name = editor.master.getName(); // prefer shorter names by using master's name in this case
} else {
name = editor.getName();
}
dirtyEditorsToConfirm.add(name);
}
}
const confirm = await this.fileDialogService.showSaveConfirm(Array.from(dirtyEditorsToConfirm.values()));
if (confirm === ConfirmResult.CANCEL) {
let confirmation: ConfirmResult;
let saveReason = SaveReason.EXPLICIT;
if (dirtyEditorsToConfirm.size > 0) {
confirmation = await this.fileDialogService.showSaveConfirm(Array.from(dirtyEditorsToConfirm.values()));
} else if (dirtyEditorsToAutoSave.size > 0) {
confirmation = ConfirmResult.SAVE;
saveReason = SaveReason.FOCUS_CHANGE;
} else {
confirmation = ConfirmResult.DONT_SAVE;
}
if (confirmation === ConfirmResult.CANCEL) {
return;
}
if (confirm === ConfirmResult.DONT_SAVE) {
if (confirmation === ConfirmResult.DONT_SAVE) {
await this.editorService.revertAll({ soft: true, includeUntitled: true });
} else {
await this.editorService.saveAll({ reason: SaveReason.EXPLICIT, includeUntitled: true });
await this.editorService.saveAll({ reason: saveReason, includeUntitled: true });
}
if (!this.workingCopyService.hasDirty) {
@@ -608,9 +630,10 @@ export class CloseAllEditorsAction extends BaseCloseAllAction {
@IWorkingCopyService workingCopyService: IWorkingCopyService,
@IFileDialogService fileDialogService: IFileDialogService,
@IEditorGroupsService editorGroupService: IEditorGroupsService,
@IEditorService editorService: IEditorService
@IEditorService editorService: IEditorService,
@IFilesConfigurationService filesConfigurationService: IFilesConfigurationService
) {
super(id, label, Codicon.closeAll.classNames, workingCopyService, fileDialogService, editorGroupService, editorService);
super(id, label, Codicon.closeAll.classNames, workingCopyService, fileDialogService, editorGroupService, editorService, filesConfigurationService);
}
protected async doCloseAll(): Promise<void> {
@@ -629,9 +652,10 @@ export class CloseAllEditorGroupsAction extends BaseCloseAllAction {
@IWorkingCopyService workingCopyService: IWorkingCopyService,
@IFileDialogService fileDialogService: IFileDialogService,
@IEditorGroupsService editorGroupService: IEditorGroupsService,
@IEditorService editorService: IEditorService
@IEditorService editorService: IEditorService,
@IFilesConfigurationService filesConfigurationService: IFilesConfigurationService
) {
super(id, label, undefined, workingCopyService, fileDialogService, editorGroupService, editorService);
super(id, label, undefined, workingCopyService, fileDialogService, editorGroupService, editorService, filesConfigurationService);
}
protected async doCloseAll(): Promise<void> {

View File

@@ -52,6 +52,7 @@ import { EditorActivation, EditorOpenContext } from 'vs/platform/editor/common/e
import { IDialogService, IFileDialogService, ConfirmResult } from 'vs/platform/dialogs/common/dialogs';
import { ILogService } from 'vs/platform/log/common/log';
import { Codicon } from 'vs/base/common/codicons';
import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
export class EditorGroupView extends Themable implements IEditorGroupView {
@@ -134,7 +135,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
@IContextMenuService private readonly contextMenuService: IContextMenuService,
@IFileDialogService private readonly fileDialogService: IFileDialogService,
@ILogService private readonly logService: ILogService,
@IEditorService private readonly editorService: EditorServiceImpl
@IEditorService private readonly editorService: EditorServiceImpl,
@IFilesConfigurationService private readonly filesConfigurationService: IFilesConfigurationService
) {
super(themeService);
@@ -1306,30 +1308,43 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return false; // editor is still editable somewhere else
}
// Switch to editor that we want to handle and confirm to save/revert
await this.openEditor(editor);
let name: string;
if (editor instanceof SideBySideEditorInput) {
name = editor.master.getName(); // prefer shorter names by using master's name in this case
} else {
name = editor.getName();
// Auto-save on focus change: assume to Save unless the editor is untitled
// because bringing up a dialog would save in this case anyway.
let confirmation: ConfirmResult;
let saveReason = SaveReason.EXPLICIT;
if (this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.ON_FOCUS_CHANGE && !editor.isUntitled()) {
confirmation = ConfirmResult.SAVE;
saveReason = SaveReason.FOCUS_CHANGE;
}
const res = await this.fileDialogService.showSaveConfirm([name]);
// No auto-save on focus change: ask user
else {
// Switch to editor that we want to handle and confirm to save/revert
await this.openEditor(editor);
let name: string;
if (editor instanceof SideBySideEditorInput) {
name = editor.master.getName(); // prefer shorter names by using master's name in this case
} else {
name = editor.getName();
}
confirmation = await this.fileDialogService.showSaveConfirm([name]);
}
// It could be that the editor saved meanwhile or is saving, so we check
// again to see if anything needs to happen before closing for good.
// This can happen for example if autoSave: onFocusChange is configured
// so that the save happens when the dialog opens.
if (!editor.isDirty() || editor.isSaving()) {
return res === ConfirmResult.CANCEL ? true : false;
return confirmation === ConfirmResult.CANCEL ? true : false;
}
// Otherwise, handle accordingly
switch (res) {
switch (confirmation) {
case ConfirmResult.SAVE:
await editor.save(this.id, { reason: SaveReason.EXPLICIT });
await editor.save(this.id, { reason: saveReason });
return editor.isDirty(); // veto if still dirty
case ConfirmResult.DONT_SAVE:

View File

@@ -444,7 +444,6 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
this.screenRedearModeElement.value = this.statusbarService.addEntry({
text,
ariaLabel: text,
tooltip: nls.localize('screenReaderDetectedExtra', "If you are not using a Screen Reader, please change the setting `editor.accessibilitySupport` to \"off\"."),
command: 'showEditorScreenReaderNotification',
backgroundColor: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_BACKGROUND),
color: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_FOREGROUND)

View File

@@ -334,23 +334,18 @@ export class TabsTitleControl extends TitleControl {
}
// Shift-key enables or disables this behaviour depending on the setting
if (this.accessor.partOptions.scrollToSwitchTabs === 'off') {
if (!e.shiftKey) {
return; // 'off': only enable this when Shift-key is pressed
}
} else {
if (this.accessor.partOptions.scrollToSwitchTabs === true) {
if (e.shiftKey) {
return; // 'on': only enable this when Shift-key is not pressed
}
} else {
if (!e.shiftKey) {
return; // 'off': only enable this when Shift-key is pressed
}
}
// Figure out scrolling direction
let scrollingUp = e.deltaX < 0 || e.deltaY < 0;
if (this.accessor.partOptions.scrollToSwitchTabs === 'reverse') {
scrollingUp = !scrollingUp;
}
const nextEditor = this.group.getEditorByIndex(this.group.getIndexOfEditor(activeEditor) + (scrollingUp ? -1 : 1));
const nextEditor = this.group.getEditorByIndex(this.group.getIndexOfEditor(activeEditor) + (e.deltaX < 0 || e.deltaY < 0 /* scrolling up */ ? -1 : 1));
if (!nextEditor) {
return;
}

View File

@@ -54,7 +54,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
static readonly activePanelSettingsKey = 'workbench.panelpart.activepanelid';
private static readonly PINNED_PANELS = 'workbench.panel.pinnedPanels';
static readonly PINNED_PANELS = 'workbench.panel.pinnedPanels';
private static readonly MIN_COMPOSITE_BAR_WIDTH = 50;
_serviceBrand: undefined;
@@ -222,14 +222,27 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
}
private onDidDeregisterPanel(panelId: string): void {
private async onDidDeregisterPanel(panelId: string): Promise<void> {
const disposable = this.panelDisposables.get(panelId);
if (disposable) {
disposable.dispose();
}
this.panelDisposables.delete(panelId);
this.hideComposite(panelId);
const activeContainers = this.viewDescriptorService.getViewContainersByLocation(ViewContainerLocation.Panel)
.filter(container => this.viewDescriptorService.getViewContainerModel(container).activeViewDescriptors.length > 0);
if (activeContainers.length) {
if (this.getActivePanel()?.getId() === panelId) {
const defaultPanelId = this.panelRegistry.getDefaultPanelId();
const containerToOpen = activeContainers.filter(c => c.id === defaultPanelId)[0] || activeContainers[0];
await this.openPanel(containerToOpen.id);
}
} else {
this.layoutService.setPanelHidden(true);
}
this.removeComposite(panelId);
}
private updateActivity(viewContainer: ViewContainer, viewContainerModel: IViewContainerModel): void {
@@ -287,6 +300,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
this.compositeBar.onDidChange(() => this.saveCachedPanels(), this, disposables);
this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables);
}));
}
private onDidRegisterExtensions(): void {
@@ -537,6 +551,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
protected removeComposite(compositeId: string): boolean {
if (super.removeComposite(compositeId)) {
this.compositeBar.removeComposite(compositeId);
const compositeActions = this.compositeActions.get(compositeId);
if (compositeActions) {
compositeActions.activityAction.dispose();

View File

@@ -34,6 +34,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { LayoutPriority } from 'vs/base/browser/ui/grid/grid';
import { assertIsDefined } from 'vs/base/common/types';
import { CompositeDragAndDropObserver } from 'vs/workbench/browser/dnd';
import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
export class SidebarPart extends CompositePart<Viewlet> implements IViewletService {
@@ -93,6 +94,7 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
@IKeybindingService keybindingService: IKeybindingService,
@IInstantiationService instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IExtensionService private readonly extensionService: IExtensionService
) {
@@ -134,9 +136,18 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
// Viewlet deregister
this._register(this.registry.onDidDeregister(async (viewletDescriptor: ViewletDescriptor) => {
const activeViewlet = this.getActiveViewlet();
if (!activeViewlet || activeViewlet.getId() === viewletDescriptor.id) {
await this.openViewlet(this.getDefaultViewletId());
const activeContainers = this.viewDescriptorService.getViewContainersByLocation(ViewContainerLocation.Sidebar)
.filter(container => this.viewDescriptorService.getViewContainerModel(container).activeViewDescriptors.length > 0);
if (activeContainers.length) {
if (this.getActiveComposite()?.getId() === viewletDescriptor.id) {
const defaultViewletId = this.getDefaultViewletId();
const containerToOpen = activeContainers.filter(c => c.id === defaultViewletId)[0] || activeContainers[0];
await this.openViewlet(containerToOpen.id);
}
} else {
this.layoutService.setSideBarHidden(true);
}
this.removeComposite(viewletDescriptor.id);
@@ -165,12 +176,7 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
const draggedItemProvider = (): { type: 'view' | 'composite', id: string } => {
const activeViewlet = this.getActiveViewlet()!;
const visibleViews = activeViewlet.getViewPaneContainer().views.filter(v => v.isVisible());
if (visibleViews.length === 1) {
return { type: 'view', id: visibleViews[0].id };
} else {
return { type: 'composite', id: activeViewlet.getId() };
}
return { type: 'composite', id: activeViewlet.getId() };
};
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.titleLabelElement!, draggedItemProvider, {}));

View File

@@ -695,6 +695,8 @@ class StatusbarEntryItem extends Disposable {
}
if (!this.entry || entry.ariaLabel !== this.entry.ariaLabel) {
// Set the aria label on both elements so screen readers would read the correct thing without duplication #96210
this.container.setAttribute('aria-label', entry.ariaLabel);
this.labelContainer.setAttribute('aria-label', entry.ariaLabel);
}
@@ -703,7 +705,7 @@ class StatusbarEntryItem extends Disposable {
if (entry.tooltip) {
this.container.title = entry.tooltip;
} else {
delete this.container.title;
this.container.title = '';
}
}

View File

@@ -66,7 +66,6 @@
max-width: 260px;
margin-left: auto;
margin-right: auto;
display: block;
}
.monaco-workbench .pane > .pane-body .welcome-view-content {

View File

@@ -458,7 +458,7 @@ export abstract class ViewPane extends Pane implements IView {
if (linkedText.nodes.length === 1 && typeof linkedText.nodes[0] !== 'string') {
const node = linkedText.nodes[0];
const button = new Button(this.viewWelcomeContainer, { title: node.title });
const button = new Button(this.viewWelcomeContainer, { title: node.title, supportCodicons: true });
button.label = node.label;
button.onDidClick(_ => {
this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href });
@@ -878,8 +878,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}));
this._register(this.onDidSashChange(() => this.saveViewSizes()));
this.viewContainerModel.onDidAddVisibleViewDescriptors(added => this.onDidAddViewDescriptors(added));
this.viewContainerModel.onDidRemoveVisibleViewDescriptors(removed => this.onDidRemoveViewDescriptors(removed));
this._register(this.viewContainerModel.onDidAddVisibleViewDescriptors(added => this.onDidAddViewDescriptors(added)));
this._register(this.viewContainerModel.onDidRemoveVisibleViewDescriptors(removed => this.onDidRemoveViewDescriptors(removed)));
const addedViews: IAddedViewDescriptorRef[] = this.viewContainerModel.visibleViewDescriptors.map((viewDescriptor, index) => {
const size = this.viewContainerModel.getSize(viewDescriptor.id);
const collapsed = this.viewContainerModel.isCollapsed(viewDescriptor.id);
@@ -1140,15 +1140,17 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
});
}
openView(id: string, focus?: boolean): IView {
openView(id: string, focus?: boolean): IView | undefined {
let view = this.getView(id);
if (!view) {
this.toggleViewVisibility(id);
}
view = this.getView(id)!;
view.setExpanded(true);
if (focus) {
view.focus();
view = this.getView(id);
if (view) {
view.setExpanded(true);
if (focus) {
view.focus();
}
}
return view;
}
@@ -1199,17 +1201,19 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
panesToRemove.push(this.panes[index]);
}
this.removePanes(panesToRemove);
dispose(panesToRemove);
}
protected toggleViewVisibility(viewId: string): void {
const visible = !this.viewContainerModel.isVisible(viewId);
type ViewsToggleVisibilityClassification = {
viewId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
visible: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
};
this.telemetryService.publicLog2<{ viewId: String, visible: boolean }, ViewsToggleVisibilityClassification>('views.toggleVisibility', { viewId, visible });
this.viewContainerModel.setVisible(viewId, visible);
// Check if view is active
if (this.viewContainerModel.activeViewDescriptors.some(viewDescriptor => viewDescriptor.id === viewId)) {
const visible = !this.viewContainerModel.isVisible(viewId);
type ViewsToggleVisibilityClassification = {
viewId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
visible: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
};
this.telemetryService.publicLog2<{ viewId: String, visible: boolean }, ViewsToggleVisibilityClassification>('views.toggleVisibility', { viewId, visible });
this.viewContainerModel.setVisible(viewId, visible);
}
}
private addPane(pane: ViewPane, size: number, index = this.paneItems.length - 1): void {
@@ -1234,8 +1238,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
leftBorder: PANEL_BORDER,
dropBackground: SIDE_BAR_DRAG_AND_DROP_BACKGROUND
}, pane);
const disposable = combinedDisposable(onDidFocus, onDidChangeTitleArea, paneStyler, onDidChange, onDidChangeVisibility);
const paneItem: IViewPaneItem = { pane: pane, disposable };
const disposable = combinedDisposable(pane, onDidFocus, onDidChangeTitleArea, paneStyler, onDidChange, onDidChangeVisibility);
const paneItem: IViewPaneItem = { pane, disposable };
this.paneItems.splice(index, 0, paneItem);
assertIsDefined(this.paneview).addPane(pane, size, index);

View File

@@ -39,13 +39,13 @@ export class ViewsService extends Disposable implements IViewsService {
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 viewPaneContainers: Map<string, ViewPaneContainer>;
constructor(
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@@ -59,7 +59,7 @@ export class ViewsService extends Disposable implements IViewsService {
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>();
this.viewPaneContainers = new Map<string, { viewPaneContainer: ViewPaneContainer, disposable: IDisposable }>();
this._register(toDisposable(() => {
this.viewDisposable.forEach(disposable => disposable.dispose());
@@ -67,17 +67,27 @@ export class ViewsService extends Disposable implements IViewsService {
}));
this.viewDescriptorService.getViewContainers().forEach(viewContainer => this.onDidRegisterViewContainer(viewContainer, this.viewDescriptorService.getViewContainerLocation(viewContainer)!));
this._register(this.viewContainersRegistry.onDidRegister(({ viewContainer, viewContainerLocation }) => this.onDidRegisterViewContainer(viewContainer, viewContainerLocation)));
this._register(this.viewContainersRegistry.onDidDeregister(e => this.viewPaneContainers.delete(e.viewContainer.id)));
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._register(this.viewDescriptorService.onDidChangeContainerLocation(({ viewContainer, from, to }) => this.onDidChangeContainerLocation(viewContainer, from, to)));
}
private registerViewPaneContainer(viewPaneContainer: ViewPaneContainer): void {
this._register(viewPaneContainer.onDidAddViews(views => this.onViewsAdded(views)));
this._register(viewPaneContainer.onDidChangeViewVisibility(view => this.onViewsVisibilityChanged(view, view.isBodyVisible())));
this._register(viewPaneContainer.onDidRemoveViews(views => this.onViewsRemoved(views)));
const disposable = new DisposableStore();
disposable.add(viewPaneContainer);
disposable.add(viewPaneContainer.onDidAddViews(views => this.onViewsAdded(views)));
disposable.add(viewPaneContainer.onDidChangeViewVisibility(view => this.onViewsVisibilityChanged(view, view.isBodyVisible())));
disposable.add(viewPaneContainer.onDidRemoveViews(views => this.onViewsRemoved(views)));
this.viewPaneContainers.set(viewPaneContainer.getId(), viewPaneContainer);
this.viewPaneContainers.set(viewPaneContainer.getId(), { viewPaneContainer, disposable });
}
private deregisterViewPaneContainer(id: string): void {
const viewPaneContainerItem = this.viewPaneContainers.get(id);
if (viewPaneContainerItem) {
viewPaneContainerItem.disposable.dispose();
this.viewPaneContainers.delete(id);
}
}
private onViewsAdded(added: IView[]): void {
@@ -107,6 +117,11 @@ export class ViewsService extends Disposable implements IViewsService {
return contextKey;
}
private onDidChangeContainerLocation(viewContainer: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation): void {
this.deregisterViewletOrPanel(viewContainer, from);
this.registerViewletOrPanel(viewContainer, to);
}
private onDidRegisterViewContainer(viewContainer: ViewContainer, viewContainerLocation: ViewContainerLocation): void {
this.registerViewletOrPanel(viewContainer, viewContainerLocation);
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
@@ -134,6 +149,7 @@ export class ViewsService extends Disposable implements IViewsService {
category: composite ? composite.name : localize('view category', "View"),
menu: [{
id: MenuId.CommandPalette,
when: viewDescriptor.when,
}],
keybinding: {
when: ContextKeyExpr.has(`${viewDescriptor.id}.active`),
@@ -228,16 +244,22 @@ export class ViewsService extends Disposable implements IViewsService {
async openView<T extends IView>(id: string, focus: boolean): Promise<T | null> {
const viewContainer = this.viewDescriptorService.getViewContainerByViewId(id);
if (viewContainer) {
const location = this.viewDescriptorService.getViewContainerLocation(viewContainer);
const compositeDescriptor = this.getComposite(viewContainer.id, location!);
if (compositeDescriptor) {
const paneComposite = await this.openComposite(compositeDescriptor.id, location!) as IPaneComposite | undefined;
if (paneComposite && paneComposite.openView) {
return paneComposite.openView(id, focus) as T;
} else if (focus) {
paneComposite?.focus();
}
if (!viewContainer) {
return null;
}
if (!this.viewDescriptorService.getViewContainerModel(viewContainer).activeViewDescriptors.some(viewDescriptor => viewDescriptor.id === id)) {
return null;
}
const location = this.viewDescriptorService.getViewContainerLocation(viewContainer);
const compositeDescriptor = this.getComposite(viewContainer.id, location!);
if (compositeDescriptor) {
const paneComposite = await this.openComposite(compositeDescriptor.id, location!) as IPaneComposite | undefined;
if (paneComposite && paneComposite.openView) {
return paneComposite.openView<T>(id, focus) || null;
} else if (focus) {
paneComposite?.focus();
}
}
@@ -290,7 +312,7 @@ export class ViewsService extends Disposable implements IViewsService {
return undefined;
}
const view = this.viewPaneContainers.get(viewContainer.id)?.getView(id);
const view = this.viewPaneContainers.get(viewContainer.id)?.viewPaneContainer?.getView(id);
return view?.getProgressIndicator();
}
@@ -307,6 +329,19 @@ export class ViewsService extends Disposable implements IViewsService {
}
}
private deregisterViewletOrPanel(viewContainer: ViewContainer, viewContainerLocation: ViewContainerLocation): void {
switch (viewContainerLocation) {
case ViewContainerLocation.Panel:
this.deregisterPanel(viewContainer);
break;
case ViewContainerLocation.Sidebar:
if (viewContainer.ctorDescriptor) {
this.deregisterViewlet(viewContainer);
}
break;
}
}
private registerPanel(viewContainer: ViewContainer): void {
const that = this;
class PaneContainerPanel extends PaneCompositePanel {
@@ -329,12 +364,17 @@ export class ViewsService extends Disposable implements IViewsService {
PaneContainerPanel,
viewContainer.id,
viewContainer.name,
isString(viewContainer.icon) ? viewContainer.icon : undefined,
undefined,
viewContainer.order,
viewContainer.focusCommand?.id,
));
}
private deregisterPanel(viewContainer: ViewContainer): void {
this.deregisterViewPaneContainer(viewContainer.id);
Registry.as<PanelRegistry>(PanelExtensions.Panels).deregisterPanel(viewContainer.id);
}
private registerViewlet(viewContainer: ViewContainer): void {
const that = this;
class PaneContainerViewlet extends Viewlet {
@@ -364,6 +404,11 @@ export class ViewsService extends Disposable implements IViewsService {
viewContainer.icon instanceof URI ? viewContainer.icon : undefined
));
}
private deregisterViewlet(viewContainer: ViewContainer): void {
this.deregisterViewPaneContainer(viewContainer.id);
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).deregisterViewlet(viewContainer.id);
}
}
export function createFileIconThemableTreeContainerScope(container: HTMLElement, themeService: IThemeService): IDisposable {

View File

@@ -38,7 +38,7 @@ import { FileUserDataProvider } from 'vs/workbench/services/userData/common/file
import { BACKUPS } from 'vs/platform/environment/common/environment';
import { joinPath } from 'vs/base/common/resources';
import { BrowserStorageService } from 'vs/platform/storage/browser/storageService';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { getThemeTypeSelector, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService';
import { registerWindowDriver } from 'vs/platform/driver/browser/driver';
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
@@ -52,23 +52,6 @@ import { coalesce } from 'vs/base/common/arrays';
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
import { WebResourceIdentityService, IResourceIdentityService } from 'vs/platform/resource/common/resourceIdentityService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { firstSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
interface PanelActivityState {
id: string;
name?: string;
pinned: boolean;
order: number;
visible: boolean;
}
interface SideBarActivityState {
id: string;
pinned: boolean;
order: number;
visible: boolean;
}
class BrowserMain extends Disposable {
@@ -82,6 +65,11 @@ class BrowserMain extends Disposable {
async open(): Promise<IWorkbench> {
const services = await this.initServices();
// const defaultLayout = this.configuration?.defaultLayout;
// if (defaultLayout) {
// defaultLayout.firstRun = services.storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL) === undefined;
// }
await domContentLoaded();
mark('willStartWorkbench');
@@ -98,8 +86,6 @@ class BrowserMain extends Disposable {
// Listeners
this.registerListeners(workbench, services.storageService);
this.applyDefaultLayout(services.storageService);
// Driver
if (this.configuration.driver) {
(async () => this._register(await registerWindowDriver()))();
@@ -120,176 +106,6 @@ class BrowserMain extends Disposable {
});
}
private applyDefaultLayout(storageService: BrowserStorageService) {
const { defaultLayout } = this.configuration;
if (!defaultLayout) {
return;
}
const firstRun = storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL);
if (firstRun !== undefined) {
return;
}
const { sidebar } = defaultLayout;
if (sidebar) {
if (sidebar.visible !== undefined) {
if (sidebar.visible) {
storageService.remove('workbench.sidebar.hidden', StorageScope.WORKSPACE);
} else {
storageService.store('workbench.sidebar.hidden', true, StorageScope.WORKSPACE);
}
}
if (sidebar.containers !== undefined) {
const sidebarState: SideBarActivityState[] = [];
let order = -1;
for (const container of sidebar.containers.sort((a, b) => (a.order ?? 1) - (b.order ?? 1))) {
let viewletId;
switch (container.id) {
case 'explorer':
viewletId = 'workbench.view.explorer';
break;
case 'run':
viewletId = 'workbench.view.debug';
break;
case 'scm':
viewletId = 'workbench.view.scm';
break;
case 'search':
viewletId = 'workbench.view.search';
break;
case 'extensions':
viewletId = 'workbench.view.extensions';
break;
case 'remote':
viewletId = 'workbench.view.remote';
break;
default:
viewletId = `workbench.view.extension.${container.id}`;
}
order = container.order ?? (order + 1);
const state: SideBarActivityState = {
id: viewletId,
order: order,
pinned: true,
visible: true
};
if (container.active) {
storageService.store('workbench.sidebar.activeviewletid', viewletId, StorageScope.WORKSPACE);
} else {
if ((<any>container).visible !== undefined) { // {{SQL CARBON EDIT}} strict-null-checks
state.pinned = (<any>container).visible; // {{SQL CARBON EDIT}} strict-null-checks
state.visible = (<any>container).visible; // {{SQL CARBON EDIT}} strict-null-checks
}
}
sidebarState.push(state);
if (container.views !== undefined) {
const viewsState: { id: string, isHidden?: boolean, order?: number }[] = [];
const viewsWorkspaceState: { [id: string]: { collapsed: boolean, isHidden?: boolean, size?: number } } = {};
for (const view of container.views) {
if (view.order !== undefined || view.visible !== undefined) {
viewsState.push({
id: view.id,
isHidden: view.visible === undefined ? undefined : !view.visible,
order: view.order === undefined ? undefined : view.order
});
}
if (view.collapsed !== undefined) {
viewsWorkspaceState[view.id] = {
collapsed: view.collapsed,
isHidden: view.visible === undefined ? undefined : !view.visible,
};
}
}
storageService.store(`${viewletId}.state.hidden`, JSON.stringify(viewsState), StorageScope.GLOBAL);
storageService.store(`${viewletId}.state`, JSON.stringify(viewsWorkspaceState), StorageScope.WORKSPACE);
}
}
storageService.store('workbench.activity.pinnedViewlets2', JSON.stringify(sidebarState), StorageScope.GLOBAL);
}
}
const { panel } = defaultLayout;
if (panel) {
if (panel.visible !== undefined) {
if (panel.visible) {
storageService.store('workbench.panel.hidden', false, StorageScope.WORKSPACE);
} else {
storageService.remove('workbench.panel.hidden', StorageScope.WORKSPACE);
}
}
if (panel.containers !== undefined) {
const panelState: PanelActivityState[] = [];
let order = -1;
for (const container of panel.containers.sort((a, b) => (a.order ?? 1) - (b.order ?? 1))) {
let name;
let panelId = container.id;
switch (panelId) {
case 'terminal':
name = 'Terminal';
panelId = 'workbench.panel.terminal';
break;
case 'debug':
name = 'Debug Console';
panelId = 'workbench.panel.repl';
break;
case 'problems':
name = 'Problems';
panelId = 'workbench.panel.markers';
break;
case 'output':
name = 'Output';
panelId = 'workbench.panel.output';
break;
case 'comments':
name = 'Comments';
panelId = 'workbench.panel.comments';
break;
case 'refactor':
name = 'Refactor Preview';
panelId = 'refactorPreview';
default:
continue;
}
order = container.order ?? (order + 1);
const state: PanelActivityState = {
id: panelId,
name: name,
order: order,
pinned: true,
visible: true
};
if (container.active) {
storageService.store('workbench.panelpart.activepanelid', panelId, StorageScope.WORKSPACE);
} else {
if ((<any>container).visible !== undefined) { // {{SQL CARBON EDIT}} strict-null-checks
state.pinned = (<any>container).visible; // {{SQL CARBON EDIT}} strict-null-checks
state.visible = (<any>container).visible; // {{SQL CARBON EDIT}} strict-null-checks
}
}
panelState.push(state);
}
storageService.store('workbench.panel.pinnedPanels', JSON.stringify(panelState), StorageScope.GLOBAL);
}
}
}
private registerListeners(workbench: Workbench, storageService: BrowserStorageService): void {
// Layout

View File

@@ -33,15 +33,9 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
'default': true
},
'workbench.editor.scrollToSwitchTabs': {
'type': 'string',
'enum': ['off', 'natural', 'reverse'],
'enumDescriptions': [
nls.localize('workbench.editor.scrollToSwitchTabs.off', "Tabs will reveal when scrolling with the mouse but not open. You can press and hold the Shift-key to switch tabs while scrolling."),
nls.localize('workbench.editor.scrollToSwitchTabs.natural', "Tabs will open when scrolling with the mouse in natural scrolling direction (scroll up to switch to the tab on the left and down for the tab on the right). You can press and hold the Shift-key to disable this behaviour for that duration."),
nls.localize('workbench.editor.scrollToSwitchTabs.reverse', "Tabs will open when scrolling with the mouse in reverse scrolling direction (scroll down to switch to the tab on the left and up for the tab on the right). You can press and hold the Shift-key to disable this behaviour for that duration."),
],
'default': 'off',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'scrollToSwitchTabs' }, "Controls wether scrolling over tabs will open them or not. By default tabs will only reveal upon scrolling, but not open. You can press and hold the Shift-key while scrolling to change this behaviour for that duration.")
'type': 'boolean',
'description': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'scrollToSwitchTabs' }, "Controls wether scrolling over tabs will open them or not. By default tabs will only reveal upon scrolling, but not open. You can press and hold the Shift-key while scrolling to change this behaviour for that duration."),
'default': false
},
'workbench.editor.highlightModifiedTabs': {
'type': 'boolean',