Merge from vscode 8df646d3c5477b02737fc10343fa7cf0cc3f606b

This commit is contained in:
ADS Merger
2020-03-25 06:20:54 +00:00
parent 6e5fbc9012
commit d810da9d87
114 changed files with 2036 additions and 797 deletions

View File

@@ -452,6 +452,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments
id: COMMENTS_VIEW_ID,
name: COMMENTS_VIEW_TITLE,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [COMMENTS_VIEW_ID, COMMENTS_VIEW_TITLE, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
hideIfEmpty: true,
order: 10,
}, ViewContainerLocation.Panel);
@@ -460,6 +461,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments
name: COMMENTS_VIEW_TITLE,
canToggleVisibility: false,
ctorDescriptor: new SyncDescriptor(CommentsPanel),
canMoveView: true,
focusCommand: {
id: 'workbench.action.focusCommentsPanel'
}

View File

@@ -199,6 +199,14 @@ export class MainThreadNotebookController implements IMainNotebookController {
let notebookHandle = await this._mainThreadNotebook.resolveNotebook(viewType, uri);
if (notebookHandle !== undefined) {
mainthreadNotebook = this._mapping.get(URI.from(uri).toString());
if (mainthreadNotebook && mainthreadNotebook.textModel.cells.length === 0) {
// it's empty, we should create an empty template one
const templateCell = await this._proxy.$createEmptyCell(this._viewType, uri, 0, mainthreadNotebook.textModel.languages.length ? mainthreadNotebook.textModel.languages[0] : '', CellKind.Code);
if (templateCell) {
let mainCell = new NotebookCellTextModel(URI.revive(templateCell.uri), templateCell.handle, templateCell.source, templateCell.language, templateCell.cellKind, templateCell.outputs, templateCell.metadata);
mainthreadNotebook.textModel.insertTemplateCell(mainCell);
}
}
return mainthreadNotebook?.textModel;
}

View File

@@ -64,6 +64,11 @@ export const viewsContainersContribution: IJSONSchema = {
description: localize('views.container.activitybar', "Contribute views containers to Activity Bar"),
type: 'array',
items: viewsContainerSchema
},
'panel': {
description: localize('views.container.panel', "Contribute views containers to Panel"),
type: 'array',
items: viewsContainerSchema
}
}
};
@@ -214,7 +219,8 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
private addCustomViewContainers(extensionPoints: readonly IExtensionPointUser<ViewContainerExtensionPointType>[], existingViewContainers: ViewContainer[]): void {
const viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
let order = TEST_VIEW_CONTAINER_ORDER + viewContainersRegistry.all.filter(v => !!v.extensionId).length + 1;
let activityBarOrder = TEST_VIEW_CONTAINER_ORDER + viewContainersRegistry.all.filter(v => !!v.extensionId && viewContainersRegistry.getViewContainerLocation(v) === ViewContainerLocation.Sidebar).length + 1;
let panelOrder = 5 + viewContainersRegistry.all.filter(v => !!v.extensionId && viewContainersRegistry.getViewContainerLocation(v) === ViewContainerLocation.Panel).length + 1;
for (let { value, collector, description } of extensionPoints) {
forEach(value, entry => {
if (!this.isValidViewsContainer(entry.value, collector)) {
@@ -222,7 +228,10 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
}
switch (entry.key) {
case 'activitybar':
order = this.registerCustomViewContainers(entry.value, description, order, existingViewContainers);
activityBarOrder = this.registerCustomViewContainers(entry.value, description, activityBarOrder, existingViewContainers, ViewContainerLocation.Sidebar);
break;
case 'panel':
panelOrder = this.registerCustomViewContainers(entry.value, description, panelOrder, existingViewContainers, ViewContainerLocation.Panel);
break;
}
});
@@ -248,7 +257,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
const title = localize('test', "Test");
const icon = URI.parse(require.toUrl('./media/test.svg'));
this.registerCustomViewContainer(TEST_VIEW_CONTAINER_ID, title, icon, TEST_VIEW_CONTAINER_ORDER, undefined);
this.registerCustomViewContainer(TEST_VIEW_CONTAINER_ID, title, icon, TEST_VIEW_CONTAINER_ORDER, undefined, ViewContainerLocation.Sidebar);
}
private isValidViewsContainer(viewsContainersDescriptors: IUserFriendlyViewsContainerDescriptor[], collector: ExtensionMessageCollector): boolean {
@@ -279,11 +288,11 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
return true;
}
private registerCustomViewContainers(containers: IUserFriendlyViewsContainerDescriptor[], extension: IExtensionDescription, order: number, existingViewContainers: ViewContainer[]): number {
private registerCustomViewContainers(containers: IUserFriendlyViewsContainerDescriptor[], extension: IExtensionDescription, order: number, existingViewContainers: ViewContainer[], location: ViewContainerLocation): number {
containers.forEach(descriptor => {
const icon = resources.joinPath(extension.extensionLocation, descriptor.icon);
const id = `workbench.view.extension.${descriptor.id}`;
const viewContainer = this.registerCustomViewContainer(id, descriptor.title, icon, order++, extension.identifier);
const viewContainer = this.registerCustomViewContainer(id, descriptor.title, icon, order++, extension.identifier, location);
// Move those views that belongs to this container
if (existingViewContainers.length) {
@@ -301,7 +310,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
return order;
}
private registerCustomViewContainer(id: string, title: string, icon: URI, order: number, extensionId: ExtensionIdentifier | undefined): ViewContainer {
private registerCustomViewContainer(id: string, title: string, icon: URI, order: number, extensionId: ExtensionIdentifier | undefined, location: ViewContainerLocation): ViewContainer {
let viewContainer = this.viewContainersRegistry.get(id);
if (!viewContainer) {
@@ -316,7 +325,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
hideIfEmpty: true,
order,
icon,
}, ViewContainerLocation.Sidebar);
}, location);
// Register Action to Open Viewlet
class OpenCustomViewletAction extends ShowViewletAction {

View File

@@ -24,7 +24,7 @@ import { InEditorZenModeContext, IsCenteredLayoutContext, EditorAreaVisibleConte
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { SideBarVisibleContext } from 'vs/workbench/common/viewlet';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IViewDescriptorService, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewsService, FocusedViewContext, ViewContainerLocation } from 'vs/workbench/common/views';
import { IViewDescriptorService, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewsService, FocusedViewContext, ViewContainerLocation, IViewDescriptor } from 'vs/workbench/common/views';
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
@@ -598,6 +598,49 @@ export class MoveFocusedViewAction extends Action {
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveFocusedViewAction, MoveFocusedViewAction.ID, MoveFocusedViewAction.LABEL), 'View: Move Focused View', viewCategory, FocusedViewContext.notEqualsTo(''));
// --- Reset View Location with Command
export class ResetFocusedViewLocationAction extends Action {
static readonly ID = 'workbench.action.resetFocusedViewLocation';
static readonly LABEL = nls.localize('resetFocusedViewLocation', "Reset Focused View Location");
constructor(
id: string,
label: string,
@IViewDescriptorService private viewDescriptorService: IViewDescriptorService,
@IContextKeyService private contextKeyService: IContextKeyService,
@INotificationService private notificationService: INotificationService,
@IViewsService private viewsService: IViewsService
) {
super(id, label);
}
async run(): Promise<void> {
const focusedViewId = FocusedViewContext.getValue(this.contextKeyService);
let viewDescriptor: IViewDescriptor | null = null;
if (focusedViewId !== undefined && focusedViewId.trim() !== '') {
viewDescriptor = this.viewDescriptorService.getViewDescriptor(focusedViewId);
}
if (!viewDescriptor) {
this.notificationService.error(nls.localize('resetFocusedView.error.noFocusedView', "There is no view currently focused."));
return;
}
const defaultContainer = this.viewDescriptorService.getDefaultContainer(viewDescriptor.id);
if (!defaultContainer || defaultContainer === this.viewDescriptorService.getViewContainer(viewDescriptor.id)) {
return;
}
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], defaultContainer);
this.viewsService.openView(viewDescriptor.id, true);
}
}
registry.registerWorkbenchAction(SyncActionDescriptor.create(ResetFocusedViewLocationAction, ResetFocusedViewLocationAction.ID, ResetFocusedViewLocationAction.LABEL), 'View: Reset Focused View Location', viewCategory, FocusedViewContext.notEqualsTo(''));
// --- Resize View
export abstract class BaseResizeViewAction extends Action {

View File

@@ -39,6 +39,21 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { getMenuBarVisibility } from 'vs/platform/windows/common/windows';
import { isWeb } from 'vs/base/common/platform';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
interface IPlaceholderViewlet {
id: string;
name?: string;
iconUrl?: UriComponents;
views?: { when?: string }[];
}
interface IPinnedViewlet {
id: string;
pinned: boolean;
order?: number;
visible: boolean;
}
interface ICachedViewlet {
id: string;
@@ -55,7 +70,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
_serviceBrand: undefined;
private static readonly ACTION_HEIGHT = 48;
private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets';
private static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets2';
private static readonly PLACEHOLDER_VIEWLETS = 'workbench.activity.placeholderViewlets';
//#region IView
@@ -92,9 +108,12 @@ export class ActivitybarPart extends Part implements IActivityBarService {
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkbenchEnvironmentService workbenchEnvironmentService: IWorkbenchEnvironmentService,
@IEnvironmentService private readonly environmentService: IEnvironmentService
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
) {
super(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
this.migrateFromOldCachedViewletsValue();
storageKeysSyncRegistryService.registerStorageKey({ key: ActivitybarPart.PINNED_VIEWLETS, version: 1 });
this.cachedViewlets = this.getCachedViewlets();
for (const cachedViewlet of this.cachedViewlets) {
@@ -528,10 +547,15 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.compositeBar.layout(new Dimension(width, availableHeight));
}
private getViewContainer(viewletId: string): ViewContainer | undefined {
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
return viewContainerRegistry.get(viewletId);
}
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
if (e.key === ActivitybarPart.PINNED_VIEWLETS && e.scope === StorageScope.GLOBAL
&& this.cachedViewletsValue !== this.getStoredCachedViewletsValue() /* This checks if current window changed the value or not */) {
this._cachedViewletsValue = undefined;
&& this.pinnedViewletsValue !== this.getStoredPinnedViewletsValue() /* This checks if current window changed the value or not */) {
this._pinnedViewletsValue = undefined;
const newCompositeItems: ICompositeBarItem[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
const cachedViewlets = this.getCachedViewlets();
@@ -583,64 +607,88 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
this.cachedViewletsValue = JSON.stringify(state);
this.storeCachedViewletsState(state);
}
private getCachedViewlets(): ICachedViewlet[] {
const storedStates: Array<string | ICachedViewlet> = JSON.parse(this.cachedViewletsValue);
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, iconUrl: undefined, views: undefined } : c;
serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible;
return serialized;
});
for (const old of this.loadOldCachedViewlets()) {
const cachedViewlet = cachedViewlets.filter(cached => cached.id === old.id)[0];
const cachedViewlets: Array<ICachedViewlet> = JSON.parse(this.pinnedViewletsValue);
for (const placeholderViewlet of JSON.parse(this.placeholderViewletsValue)) {
const cachedViewlet = cachedViewlets.filter(cached => cached.id === placeholderViewlet.id)[0];
if (cachedViewlet) {
cachedViewlet.name = old.name;
cachedViewlet.iconUrl = old.iconUrl;
cachedViewlet.views = old.views;
cachedViewlet.name = placeholderViewlet.name;
cachedViewlet.iconUrl = placeholderViewlet.iconUrl;
cachedViewlet.views = placeholderViewlet.views;
}
}
return cachedViewlets;
}
private loadOldCachedViewlets(): ICachedViewlet[] {
const previousState = this.storageService.get('workbench.activity.placeholderViewlets', StorageScope.GLOBAL, '[]');
const result: ICachedViewlet[] = JSON.parse(previousState);
this.storageService.remove('workbench.activity.placeholderViewlets', StorageScope.GLOBAL);
return result;
private storeCachedViewletsState(cachedViewlets: ICachedViewlet[]): void {
this.pinnedViewletsValue = JSON.stringify(cachedViewlets.map(({ id, pinned, visible, order }) => (<IPinnedViewlet>{ id, pinned, visible, order })));
this.placeholderViewletsValue = JSON.stringify(cachedViewlets.map(({ id, iconUrl, name, views }) => (<IPlaceholderViewlet>{ id, iconUrl, name, views })));
}
private _cachedViewletsValue: string | undefined;
private get cachedViewletsValue(): string {
if (!this._cachedViewletsValue) {
this._cachedViewletsValue = this.getStoredCachedViewletsValue();
private _pinnedViewletsValue: string | undefined;
private get pinnedViewletsValue(): string {
if (!this._pinnedViewletsValue) {
this._pinnedViewletsValue = this.getStoredPinnedViewletsValue();
}
return this._cachedViewletsValue;
return this._pinnedViewletsValue;
}
private set cachedViewletsValue(cachedViewletsValue: string) {
if (this.cachedViewletsValue !== cachedViewletsValue) {
this._cachedViewletsValue = cachedViewletsValue;
this.setStoredCachedViewletsValue(cachedViewletsValue);
private set pinnedViewletsValue(pinnedViewletsValue: string) {
if (this.pinnedViewletsValue !== pinnedViewletsValue) {
this._pinnedViewletsValue = pinnedViewletsValue;
this.setStoredPinnedViewletsValue(pinnedViewletsValue);
}
}
private getStoredCachedViewletsValue(): string {
private getStoredPinnedViewletsValue(): string {
return this.storageService.get(ActivitybarPart.PINNED_VIEWLETS, StorageScope.GLOBAL, '[]');
}
private setStoredCachedViewletsValue(value: string): void {
private setStoredPinnedViewletsValue(value: string): void {
this.storageService.store(ActivitybarPart.PINNED_VIEWLETS, value, StorageScope.GLOBAL);
}
private getViewContainer(viewletId: string): ViewContainer | undefined {
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
return viewContainerRegistry.get(viewletId);
private _placeholderViewletsValue: string | undefined;
private get placeholderViewletsValue(): string {
if (!this._placeholderViewletsValue) {
this._placeholderViewletsValue = this.getStoredPlaceholderViewletsValue();
}
return this._placeholderViewletsValue;
}
private set placeholderViewletsValue(placeholderViewletsValue: string) {
if (this.placeholderViewletsValue !== placeholderViewletsValue) {
this._placeholderViewletsValue = placeholderViewletsValue;
this.setStoredPlaceholderViewletsValue(placeholderViewletsValue);
}
}
private getStoredPlaceholderViewletsValue(): string {
return this.storageService.get(ActivitybarPart.PLACEHOLDER_VIEWLETS, StorageScope.GLOBAL, '[]');
}
private setStoredPlaceholderViewletsValue(value: string): void {
this.storageService.store(ActivitybarPart.PLACEHOLDER_VIEWLETS, value, StorageScope.GLOBAL);
}
private migrateFromOldCachedViewletsValue(): 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, iconUrl: undefined, views: undefined } : c;
serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible;
return serialized;
});
this.storeCachedViewletsState(cachedViewlets);
this.storageService.remove('workbench.activity.pinnedViewlets', StorageScope.GLOBAL);
}
}
toJSON(): object {

View File

@@ -133,9 +133,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
}
// ... single view
const defaultContainer = this.viewDescriptorService.getDefaultContainer(draggedViews[0].id);
const canMoveToDefault = !!defaultContainer && this.viewDescriptorService.getViewContainerLocation(defaultContainer) === this.targetContainerLocation;
return !!draggedViews[0].canMoveView && (!!draggedViews[0].containerIcon || canMoveToDefault || this.targetContainerLocation === ViewContainerLocation.Panel);
return !!draggedViews[0].canMoveView;
} else {
// Dragging an individual view
const viewDescriptor = this.viewDescriptorService.getViewDescriptor(dragData.id);
@@ -146,7 +144,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
}
// ... to create a view container
return this.targetContainerLocation === ViewContainerLocation.Panel || !!viewDescriptor.containerIcon;
return true;
}
}
}

View File

@@ -36,7 +36,9 @@ import {
SplitEditorUpAction, SplitEditorDownAction, MoveEditorToLeftGroupAction, MoveEditorToRightGroupAction, MoveEditorToAboveGroupAction, MoveEditorToBelowGroupAction, CloseAllEditorGroupsAction,
JoinAllGroupsAction, FocusLeftGroup, FocusAboveGroup, FocusRightGroup, FocusBelowGroup, EditorLayoutSingleAction, EditorLayoutTwoColumnsAction, EditorLayoutThreeColumnsAction, EditorLayoutTwoByTwoGridAction,
EditorLayoutTwoRowsAction, EditorLayoutThreeRowsAction, EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoRowsRightAction, NewEditorGroupLeftAction, NewEditorGroupRightAction,
NewEditorGroupAboveAction, NewEditorGroupBelowAction, SplitEditorOrthogonalAction, CloseEditorInAllGroupsAction, NavigateToLastEditLocationAction, ToggleGroupSizesAction, ShowAllEditorsByMostRecentlyUsedAction, QuickOpenPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction, QuickOpenNextRecentlyUsedEditorAction as QuickOpenLeastRecentlyUsedEditorAction, QuickOpenLeastRecentlyUsedEditorInGroupAction
NewEditorGroupAboveAction, NewEditorGroupBelowAction, SplitEditorOrthogonalAction, CloseEditorInAllGroupsAction, NavigateToLastEditLocationAction, ToggleGroupSizesAction, ShowAllEditorsByMostRecentlyUsedAction,
QuickOpenPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction, QuickOpenNextRecentlyUsedEditorAction as QuickOpenLeastRecentlyUsedEditorAction,
QuickOpenLeastRecentlyUsedEditorInGroupAction
} from 'vs/workbench/browser/parts/editor/editorActions';
import * as editorCommands from 'vs/workbench/browser/parts/editor/editorCommands';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';

View File

@@ -24,6 +24,7 @@ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IFileDialogService, ConfirmResult } from 'vs/platform/dialogs/common/dialogs';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { values } from 'vs/base/common/map';
import { ItemActivation } from 'vs/platform/quickinput/common/quickInput';
export class ExecuteCommandAction extends Action {
@@ -1261,6 +1262,7 @@ export class BaseQuickOpenEditorAction extends Action {
id: string,
label: string,
private prefix: string,
private itemActivation: ItemActivation | undefined,
@IQuickOpenService private readonly quickOpenService: IQuickOpenService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) {
@@ -1270,7 +1272,10 @@ export class BaseQuickOpenEditorAction extends Action {
async run(): Promise<void> {
const keybindings = this.keybindingService.lookupKeybindings(this.id);
this.quickOpenService.show(this.prefix, { quickNavigateConfiguration: { keybindings } });
this.quickOpenService.show(this.prefix, {
quickNavigateConfiguration: { keybindings },
autoFocus: this.itemActivation === ItemActivation.LAST ? { autoFocusLastEntry: true } : undefined
});
}
}
@@ -1285,7 +1290,7 @@ export class QuickOpenPreviousRecentlyUsedEditorAction extends BaseQuickOpenEdit
@IQuickOpenService quickOpenService: IQuickOpenService,
@IKeybindingService keybindingService: IKeybindingService
) {
super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService, keybindingService);
super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService);
}
}
@@ -1300,7 +1305,7 @@ export class QuickOpenNextRecentlyUsedEditorAction extends BaseQuickOpenEditorAc
@IQuickOpenService quickOpenService: IQuickOpenService,
@IKeybindingService keybindingService: IKeybindingService
) {
super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService, keybindingService);
super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService);
}
}
@@ -1315,7 +1320,7 @@ export class QuickOpenPreviousRecentlyUsedEditorInGroupAction extends BaseQuickO
@IQuickOpenService quickOpenService: IQuickOpenService,
@IKeybindingService keybindingService: IKeybindingService
) {
super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService, keybindingService);
super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService);
}
}
@@ -1330,7 +1335,7 @@ export class QuickOpenLeastRecentlyUsedEditorInGroupAction extends BaseQuickOpen
@IQuickOpenService quickOpenService: IQuickOpenService,
@IKeybindingService keybindingService: IKeybindingService
) {
super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService, keybindingService);
super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, ItemActivation.LAST, quickOpenService, keybindingService);
}
}

View File

@@ -37,6 +37,7 @@ import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExte
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';
interface ICachedPanel {
id: string;
@@ -104,6 +105,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IExtensionService private readonly extensionService: IExtensionService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
) {
super(
notificationService,
@@ -125,6 +127,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
);
this.panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
storageKeysSyncRegistryService.registerStorageKey({ key: PanelPart.PINNED_PANELS, version: 1 });
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.getCachedPanels(), {
icon: false,

View File

@@ -47,7 +47,7 @@ import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { ILabelService } from 'vs/platform/label/common/label';
import { timeout } from 'vs/base/common/async';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IQuickInputService, IQuickPickItem, ItemActivation } from 'vs/platform/quickinput/common/quickInput';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
@@ -179,7 +179,20 @@ export class QuickOpenController extends Component implements IQuickOpenService
show(prefix?: string, options?: IShowOptions): Promise<void> {
if (this.useNewExperimentalVersion) {
this.quickInputService.quickAccess.show(prefix, options);
this.quickInputService.quickAccess.show(prefix, {
quickNavigateConfiguration: options?.quickNavigateConfiguration,
itemActivation: (() => {
if (options?.autoFocus?.autoFocusSecondEntry) {
return ItemActivation.SECOND;
}
if (options?.autoFocus?.autoFocusLastEntry) {
return ItemActivation.LAST;
}
return undefined;
})()
});
return Promise.resolve();
}

View File

@@ -21,8 +21,8 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Event, Emitter } from 'vs/base/common/event';
import { IThemeService, IColorTheme, ICssStyleCollector, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { SIDE_BAR_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND, SIDE_BAR_BORDER, SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { EventType, addDisposableListener, trackFocus } from 'vs/base/browser/dom';
@@ -333,23 +333,6 @@ class FocusSideBarAction extends Action {
}
}
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
// Sidebar Background: since views can host editors, we apply a background rule if the sidebar background
// color is different from the editor background color. This is a bit of a hack though. The better way
// would be to have a way to push the background color onto each editor widget itself somehow.
const sidebarBackground = theme.getColor(SIDE_BAR_BACKGROUND);
if (sidebarBackground && sidebarBackground !== theme.getColor(editorBackground)) {
collector.addRule(`
.monaco-workbench .part.sidebar > .content .monaco-editor,
.monaco-workbench .part.sidebar > .content .monaco-editor .margin,
.monaco-workbench .part.sidebar > .content .monaco-editor .monaco-editor-background {
background-color: ${sidebarBackground};
}
`);
}
});
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusSideBarAction, FocusSideBarAction.ID, FocusSideBarAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.KEY_0

View File

@@ -35,6 +35,7 @@ import { values } from 'vs/base/common/map';
import { assertIsDefined } from 'vs/base/common/types';
import { Emitter, Event } from 'vs/base/common/event';
import { Command } from 'vs/editor/common/modes';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
interface IPendingStatusbarEntry {
id: string;
@@ -55,7 +56,7 @@ interface IStatusbarViewModelEntry {
class StatusbarViewModel extends Disposable {
private static readonly HIDDEN_ENTRIES_KEY = 'workbench.statusbar.hidden';
static readonly HIDDEN_ENTRIES_KEY = 'workbench.statusbar.hidden';
private readonly _entries: IStatusbarViewModelEntry[] = [];
get entries(): IStatusbarViewModelEntry[] { return this._entries; }
@@ -354,12 +355,14 @@ export class StatusbarPart extends Part implements IStatusbarService {
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IContextMenuService private contextMenuService: IContextMenuService
@IContextMenuService private contextMenuService: IContextMenuService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService,
) {
super(Parts.STATUSBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
this.viewModel = this._register(new StatusbarViewModel(storageService));
this.onDidChangeEntryVisibility = this.viewModel.onDidChangeEntryVisibility;
storageKeysSyncRegistryService.registerStorageKey({ key: StatusbarViewModel.HIDDEN_ENTRIES_KEY, version: 1 });
this.registerListeners();
}

View File

@@ -467,7 +467,7 @@ export class TitlebarPart extends Part implements ITitleService {
if ((!isWeb && isMacintosh) || this.currentMenubarVisibility === 'hidden') {
this.title.style.zoom = `${1 / getZoomFactor()}`;
} else {
this.title.style.zoom = null;
this.title.style.zoom = '';
}
runAtThisOrScheduleAtNextAnimationFrame(() => this.adjustTitleMarginToCenter());

View File

@@ -414,7 +414,7 @@ export class TreeView extends Disposable implements ITreeView {
const actionViewItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuEntryActionViewItem, action) : undefined;
const treeMenus = this._register(this.instantiationService.createInstance(TreeMenus, this.id));
this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this));
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, <T>(task: Promise<T>) => this.progressService.withProgress({ location: this.viewContainer.id }, () => task));
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, <T>(task: Promise<T>) => this.progressService.withProgress({ location: this.id }, () => task));
const aligner = new Aligner(this.themeService);
const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner);
@@ -1015,7 +1015,7 @@ export class CustomTreeView extends TreeView {
private activate() {
if (!this.activated) {
this.progressService.withProgress({ location: this.viewContainer.id }, () => this.extensionService.activateByEvent(`onView:${this.id}`))
this.progressService.withProgress({ location: this.id }, () => this.extensionService.activateByEvent(`onView:${this.id}`))
.then(() => timeout(2000))
.then(() => {
this.updateMessage();

View File

@@ -22,7 +22,6 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { VIEW_ID as SEARCH_VIEW_ID } from 'vs/workbench/services/search/common/search';
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';
@@ -571,33 +570,28 @@ export class ViewsService extends Disposable implements IViewsService {
}
}));
const newLocation = location === ViewContainerLocation.Panel ? ViewContainerLocation.Sidebar : ViewContainerLocation.Panel;
disposables.add(registerAction2(class MoveViewAction extends Action2 {
disposables.add(registerAction2(class ResetViewLocationAction extends Action2 {
constructor() {
super({
id: `${viewDescriptor.id}.moveView`,
id: `${viewDescriptor.id}.resetViewLocation`,
title: {
original: newLocation === ViewContainerLocation.Sidebar ? 'Move to Sidebar' : 'Move to Panel',
value: newLocation === ViewContainerLocation.Sidebar ? localize('moveViewToSidebar', "Move to Sidebar") : localize('moveViewToPanel', "Move to Panel")
original: 'Reset View Location',
value: localize('resetViewLocation', "Reset View Location")
},
menu: [{
id: MenuId.ViewTitleContext,
when: ContextKeyExpr.or(
ContextKeyExpr.and(
ContextKeyExpr.equals('view', viewDescriptor.id),
ContextKeyExpr.has(`${viewDescriptor.id}.canMove`),
ContextKeyExpr.equals('config.workbench.view.experimental.allowMovingToNewContainer', true)),
ContextKeyExpr.and(
ContextKeyExpr.equals('view', viewDescriptor.id),
ContextKeyExpr.has(`${viewDescriptor.id}.canMove`),
ContextKeyExpr.equals('view', SEARCH_VIEW_ID)
ContextKeyExpr.equals(`${viewDescriptor.id}.defaultViewLocation`, false)
)
)
}],
});
}
run(accessor: ServicesAccessor): void {
accessor.get(IViewDescriptorService).moveViewToLocation(viewDescriptor, newLocation);
const viewDescriptorService = accessor.get(IViewDescriptorService);
viewDescriptorService.moveViewsToContainer([viewDescriptor], viewDescriptorService.getDefaultContainer(viewDescriptor.id)!);
accessor.get(IViewsService).openView(viewDescriptor.id, true);
}
}));

View File

@@ -226,11 +226,6 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
'default': true, // {{SQL CARBON EDIT}} - change the default value from false to true.
'description': nls.localize('viewVisibility', "Controls the visibility of view header actions. View header actions may either be always visible, or only visible when that view is focused or hovered over.")
},
'workbench.view.experimental.allowMovingToNewContainer': {
'type': 'boolean',
'default': true,
'description': nls.localize('movingViewContainer', "Controls whether specific views will have a context menu entry allowing them to be moved to a new container. Currently, this setting only affects the outline view and views contributed by extensions.")
},
'workbench.fontAliasing': {
'type': 'string',
'enum': ['default', 'antialiased', 'none', 'auto'],

View File

@@ -20,7 +20,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { WorkbenchAsyncDataTree, IListService } from 'vs/platform/list/browser/listService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { PANEL_BACKGROUND } from 'vs/workbench/common/theme';
import { IColorMapping } from 'vs/platform/theme/common/styler';
export const COMMENTS_VIEW_ID = 'workbench.panel.comments';
export const COMMENTS_VIEW_TITLE = 'Comments';
@@ -149,10 +149,15 @@ export class CommentNodeRenderer implements IListRenderer<ITreeNode<CommentNode>
}
}
export interface ICommentsListOptions {
overrideStyles?: IColorMapping;
}
export class CommentsList extends WorkbenchAsyncDataTree<any, any> {
constructor(
labels: ResourceLabels,
container: HTMLElement,
options: ICommentsListOptions,
@IContextKeyService contextKeyService: IContextKeyService,
@IListService listService: IListService,
@IThemeService themeService: IThemeService,
@@ -202,9 +207,7 @@ export class CommentsList extends WorkbenchAsyncDataTree<any, any> {
collapseByDefault: () => {
return false;
},
overrideStyles: {
listBackground: PANEL_BACKGROUND
}
overrideStyles: options.overrideStyles
},
contextKeyService,
listService,

View File

@@ -149,7 +149,7 @@ export class CommentsPanel extends ViewPane {
private createTree(): void {
this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this));
this.tree = this._register(this.instantiationService.createInstance(CommentsList, this.treeLabels, this.treeContainer));
this.tree = this._register(this.instantiationService.createInstance(CommentsList, this.treeLabels, this.treeContainer, { overrideStyles: { listBackground: this.getBackgroundColor() } }));
const commentsNavigator = this._register(ResourceNavigator.createTreeResourceNavigator(this.tree, { openOnFocus: true }));
this._register(commentsNavigator.onDidOpenResource(e => {

View File

@@ -13,7 +13,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import * as nls from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { EditorActivation, IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { FileOperation, IFileService } from 'vs/platform/files/common/files';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
@@ -21,16 +21,16 @@ import * as colorRegistry from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { EditorInput, EditorOptions, IEditorInput, IEditorPane, GroupIdentifier } from 'vs/workbench/common/editor';
import { EditorInput, EditorOptions, GroupIdentifier, IEditorInput, IEditorPane } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { webviewEditorsExtensionPoint } from 'vs/workbench/contrib/customEditor/browser/extensionPoint';
import { CONTEXT_CUSTOM_EDITORS, CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CustomEditorInfo, CustomEditorInfoCollection, CustomEditorPriority, CustomEditorSelector, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { CustomEditorModelManager } from 'vs/workbench/contrib/customEditor/common/customEditorModelManager';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { IWebviewService, webviewHasOwnEditFunctionsContext } from 'vs/workbench/contrib/webview/browser/webview';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService';
import { CustomEditorInput } from './customEditorInput';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
export const defaultEditorId = 'default';
@@ -284,6 +284,10 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
): Promise<IEditorPane | undefined> {
const targetGroup = group || this.editorGroupService.activeGroup;
if (options && typeof options.activation === 'undefined') {
options = { ...options, activation: options.preserveFocus ? EditorActivation.RESTORE : undefined };
}
// Try to replace existing editors for resource
const existingEditors = targetGroup.editors.filter(editor => editor.resource && isEqual(editor.resource, resource));
if (existingEditors.length) {
@@ -454,7 +458,11 @@ export class CustomEditorContribution extends Disposable implements IWorkbenchCo
const existingEditorForResource = group.editors.find(editor => isEqual(resource, editor.resource));
if (existingEditorForResource) {
return {
override: this.editorService.openEditor(existingEditorForResource, { ...options, ignoreOverrides: true }, group)
override: this.editorService.openEditor(existingEditorForResource, {
...options,
ignoreOverrides: true,
activation: options?.preserveFocus ? EditorActivation.RESTORE : undefined,
}, group)
};
}

View File

@@ -96,6 +96,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewE
id: OpenDebugPanelAction.ID,
keybindings: openPanelKb
},
order: 3,
hideIfEmpty: true
}, ViewContainerLocation.Panel);

View File

@@ -234,7 +234,7 @@ export class DebugSession implements IDebugSession {
this.initialized = true;
this._onDidChangeState.fire();
this.model.setExceptionBreakpoints(this.raw!.capabilities.exceptionBreakpointFilters || []);
this.model.setExceptionBreakpoints((this.raw && this.raw.capabilities.exceptionBreakpointFilters) || []);
} catch (err) {
this.initialized = true;
this._onDidChangeState.fire();

View File

@@ -208,9 +208,20 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
}));
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('debug.console.lineHeight') || e.affectsConfiguration('debug.console.fontSize') || e.affectsConfiguration('debug.console.fontFamily')) {
this.onDidFontChange();
this.onDidStyleChange();
}
}));
this._register(this.themeService.onDidColorThemeChange(e => {
this.onDidStyleChange();
}));
this._register(this.viewDescriptorService.onDidChangeLocation(e => {
if (e.views.some(v => v.id === this.id)) {
this.onDidStyleChange();
}
}));
this._register(this.editorService.onDidActiveEditorChange(() => {
this.setMode();
}));
@@ -253,14 +264,15 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
}
}
private onDidFontChange(): void {
private onDidStyleChange(): void {
if (this.styleElement) {
const debugConsole = this.configurationService.getValue<IDebugConfiguration>('debug').console;
const fontSize = debugConsole.fontSize;
const fontFamily = debugConsole.fontFamily === 'default' ? 'var(--monaco-monospace-font)' : debugConsole.fontFamily;
const lineHeight = debugConsole.lineHeight ? `${debugConsole.lineHeight}px` : '1.4em';
const backgroundColor = this.themeService.getColorTheme().getColor(this.getBackgroundColor());
// Set the font size, font family, line height and align the twistie to be centered
// Set the font size, font family, line height and align the twistie to be centered, and input theme color
this.styleElement.innerHTML = `
.repl .repl-tree .expression {
font-size: ${fontSize}px;
@@ -274,6 +286,10 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
.repl .repl-tree .monaco-tl-twistie {
background-position-y: calc(100% - ${fontSize * 1.4 / 2 - 8}px);
}
.repl .repl-input-wrapper .monaco-editor .lines-content {
background-color: ${backgroundColor};
}
`;
this.tree.rerender();
@@ -510,7 +526,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
// Make sure to select the session if debugging is already active
this.selectSession();
this.styleElement = dom.createStyleSheet(this.container);
this.onDidFontChange();
this.onDidStyleChange();
}
private createReplInput(container: HTMLElement): void {

View File

@@ -80,8 +80,11 @@ export class VariablesView extends ViewPane {
if (stackFrame) {
const scopes = await stackFrame.getScopes();
// Expand the first scope if it is not expensive and if there is no expansion state (all are collapsed)
if (scopes.every(s => this.tree.getNode(s).collapsed) && scopes.length > 0 && !scopes[0].expensive) {
this.tree.expand(scopes[0]);
if (scopes.every(s => this.tree.getNode(s).collapsed) && scopes.length > 0) {
const toExpand = scopes.filter(s => !s.expensive).shift();
if (toExpand) {
this.tree.expand(toExpand);
}
}
}

View File

@@ -305,9 +305,19 @@ export class StackFrame implements IStackFrame {
getScopes(): Promise<IScope[]> {
if (!this.scopes) {
this.scopes = this.thread.session.scopes(this.frameId, this.thread.threadId).then(response => {
return response && response.body && response.body.scopes ?
response.body.scopes.map((rs, index) => new Scope(this, index, rs.name, rs.variablesReference, rs.expensive, rs.namedVariables, rs.indexedVariables,
rs.line && rs.column && rs.endLine && rs.endColumn ? new Range(rs.line, rs.column, rs.endLine, rs.endColumn) : undefined)) : [];
if (!response || !response.body || !response.body.scopes) {
return [];
}
const scopeNameIndexes = new Map<string, number>();
return response.body.scopes.map(rs => {
const previousIndex = scopeNameIndexes.get(rs.name);
const index = typeof previousIndex === 'number' ? previousIndex + 1 : 0;
scopeNameIndexes.set(rs.name, index);
return new Scope(this, index, rs.name, rs.variablesReference, rs.expensive, rs.namedVariables, rs.indexedVariables,
rs.line && rs.column && rs.endLine && rs.endColumn ? new Range(rs.line, rs.column, rs.endLine, rs.endColumn) : undefined);
});
}, err => [new ErrorScope(this, 0, err.message)]);
}

View File

@@ -48,12 +48,10 @@ export class InstallExtensionQuickAccessProvider extends PickerQuickAccessProvid
}
// Extension name typed: offer to search it
else {
return [genericSearchPickItem];
}
return [genericSearchPickItem];
}
protected async getPicksForExtensionId(filter: string, fallback: IPickerQuickAccessItem, token: CancellationToken): Promise<Array<IPickerQuickAccessItem | IQuickPickSeparator>> {
private async getPicksForExtensionId(filter: string, fallback: IPickerQuickAccessItem, token: CancellationToken): Promise<Array<IPickerQuickAccessItem | IQuickPickSeparator>> {
try {
const galleryResult = await this.galleryService.query({ names: [filter], pageSize: 1 }, token);
if (token.isCancellationRequested) {
@@ -63,12 +61,12 @@ export class InstallExtensionQuickAccessProvider extends PickerQuickAccessProvid
const galleryExtension = galleryResult.firstPage[0];
if (!galleryExtension) {
return [fallback];
} else {
return [{
label: localize('install', "Press Enter to install extension '{0}'.", filter),
accept: () => this.installExtension(galleryExtension, filter)
}];
}
return [{
label: localize('install', "Press Enter to install extension '{0}'.", filter),
accept: () => this.installExtension(galleryExtension, filter)
}];
} catch (error) {
if (token.isCancellationRequested) {
return []; // expected error

View File

@@ -46,6 +46,7 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura
import { IWorkingCopyService, IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { sequence } from 'vs/base/common/async';
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
import { once } from 'vs/base/common/functional';
export const NEW_FILE_COMMAND_ID = 'explorer.newFile';
export const NEW_FILE_LABEL = nls.localize('newFile', "New File");
@@ -519,9 +520,10 @@ export class GlobalCompareResourcesAction extends Action {
return undefined;
});
once(this.quickOpenService.onHide)((() => toDispose.dispose()));
// Bring up quick open
await this.quickOpenService.show('', { autoFocus: { autoFocusSecondEntry: true } });
toDispose.dispose(); // make sure to unbind if quick open is closing
} else {
this.notificationService.info(nls.localize('openFileToCompare', "Open a file first to compare it with another file."));
}

View File

@@ -112,6 +112,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewC
id: Constants.MARKERS_CONTAINER_ID,
name: Messages.MARKERS_PANEL_TITLE_PROBLEMS,
hideIfEmpty: true,
order: 0,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [Constants.MARKERS_CONTAINER_ID, Constants.MARKERS_VIEW_STORAGE_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
focusCommand: {
id: ToggleMarkersPanelAction.ID, keybindings: {
@@ -122,6 +123,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewC
Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry).registerViews([{
id: Constants.MARKERS_VIEW_ID,
containerIcon: 'codicon-warning',
name: Messages.MARKERS_PANEL_TITLE_PROBLEMS,
canToggleVisibility: false,
canMoveView: true,

View File

@@ -201,6 +201,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
mouseSupport: true,
multipleSelectionSupport: false,
enableKeyboardNavigation: true,
additionalScrollHeight: 0,
overrideStyles: {
listBackground: editorBackground,
listActiveSelectionBackground: editorBackground,
@@ -419,6 +420,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
DOM.toggleClass(this.rootElement, 'mid-width', dimension.width < 1000 && dimension.width >= 600);
DOM.toggleClass(this.rootElement, 'narrow-width', dimension.width < 600);
DOM.size(this.body, dimension.width, dimension.height);
this.list?.updateOptions({ additionalScrollHeight: dimension.height });
this.list?.layout(dimension.height, dimension.width);
this.eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
}
@@ -742,6 +744,13 @@ export const focusedCellIndicator = registerColor('notebook.focusedCellIndicator
hc: new Color(new RGBA(0, 73, 122))
}, nls.localize('notebook.focusedCellIndicator', "The color of the focused notebook cell indicator."));
export const notebookOutputContainerColor = registerColor('notebook.outputContainerBackgroundColor', {
dark: new Color(new RGBA(255, 255, 255, 0.06)),
light: new Color(new RGBA(228, 230, 241)),
hc: null
}
, nls.localize('notebook.outputContainerBackgroundColor', "The Color of the notebook output container background."));
registerThemingParticipant((theme, collector) => {
const color = getExtraColor(theme, embeddedEditorBackground, { dark: 'rgba(0, 0, 0, .4)', extra_dark: 'rgba(200, 235, 255, .064)', light: '#f4f4f4', hc: null });
@@ -776,10 +785,10 @@ registerThemingParticipant((theme, collector) => {
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor blockquote { border-color: ${quoteBorder}; }`);
}
const inactiveListItem = theme.getColor('list.inactiveSelectionBackground');
const containerBackground = theme.getColor(notebookOutputContainerColor);
if (inactiveListItem) {
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { background-color: ${inactiveListItem}; }`);
if (containerBackground) {
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { background-color: ${containerBackground}; }`);
}
const focusedCellIndicatorColor = theme.getColor(focusedCellIndicator);

View File

@@ -94,9 +94,13 @@ abstract class AbstractCellRenderer {
horizontalHasArrows: false,
alwaysConsumeMouseWheel: false
},
overviewRulerLanes: 3,
renderLineHighlightOnlyWhenFocus: true,
overviewRulerLanes: 0,
selectOnLineNumbers: false,
lineNumbers: 'off',
lineDecorationsWidth: 0,
glyphMargin: false,
fixedOverflowWidgets: false,
lineNumbersMinChars: 1,
minimap: { enabled: false },
};
}

View File

@@ -15,6 +15,7 @@ import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/commo
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
import { IModeService } from 'vs/editor/common/services/modeService';
interface IMimeTypeRenderer extends IQuickPickItem {
index: number;
@@ -28,7 +29,8 @@ export class CodeCell extends Disposable {
private viewCell: CodeCellViewModel,
private templateData: CellRenderTemplate,
@INotebookService private notebookService: INotebookService,
@IQuickInputService private readonly quickInputService: IQuickInputService
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IModeService private readonly _modeService: IModeService
) {
super();
@@ -85,6 +87,11 @@ export class CodeCell extends Disposable {
templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel?.metadata).editable) });
}));
this._register(viewCell.onDidChangeLanguage((e) => {
const mode = this._modeService.create(e);
templateData.editor?.getModel()?.setMode(mode.languageIdentifier);
}));
let cellWidthResizeObserver = getResizesObserver(templateData.editorContainer!, {
width: width,
height: totalHeight

View File

@@ -34,6 +34,8 @@ export abstract class BaseCellViewModel extends Disposable {
public readonly onDidChangeCursorSelection: Event<void> = this._onDidChangeCursorSelection.event;
protected readonly _onDidChangeMetadata: Emitter<NotebookCellMetadata | undefined> = this._register(new Emitter<NotebookCellMetadata | undefined>());
public readonly onDidChangeMetadata: Event<NotebookCellMetadata | undefined> = this._onDidChangeMetadata.event;
protected readonly _onDidChangeLanguage: Emitter<string> = this._register(new Emitter<string>());
public readonly onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
get handle() {
return this.cell.handle;
}
@@ -100,6 +102,10 @@ export abstract class BaseCellViewModel extends Disposable {
constructor(readonly viewType: string, readonly notebookHandle: number, readonly cell: ICell, public id: string) {
super();
this._register(cell.onDidChangeLanguage((e) => {
this._onDidChangeLanguage.fire(e);
}));
this._register(cell.onDidChangeMetadata((e) => {
this._onDidChangeMetadata.fire(e);
}));

View File

@@ -89,6 +89,12 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
this.layoutChange({ outerWidth: e.value.width, font: e.value.fontInfo });
}
}));
this._register(this.onDidChangeLanguage((e) => {
if (this._textModel && !this._textModel.isDisposed()) {
}
}));
}
layoutChange(state: CodeCellLayoutChangeEvent) {

View File

@@ -18,6 +18,9 @@ export class NotebookCellTextModel implements ICell {
private _onDidChangeMetadata = new Emitter<NotebookCellMetadata | undefined>();
onDidChangeMetadata: Event<NotebookCellMetadata | undefined> = this._onDidChangeMetadata.event;
private _onDidChangeLanguage = new Emitter<string>();
onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
private _outputs: IOutput[];
get outputs(): IOutput[] {
@@ -44,13 +47,22 @@ export class NotebookCellTextModel implements ICell {
this._onDidChangeMetadata.fire(this._metadata);
}
get language() {
return this._language;
}
set language(newLanguage: string) {
this._language = newLanguage;
this._onDidChangeLanguage.fire(newLanguage);
}
private _buffer: PieceTreeTextBufferFactory | null = null;
constructor(
readonly uri: URI,
public handle: number,
private _source: string[],
public language: string,
private _language: string,
public cellKind: CellKind,
outputs: IOutput[],
metadata: NotebookCellMetadata | undefined

View File

@@ -24,6 +24,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
languages: string[] = [];
metadata: NotebookDocumentMetadata | undefined = { editable: true };
renderers = new Set<number>();
private _isUntitled: boolean | undefined = undefined;
constructor(
public handle: number,
@@ -36,6 +37,11 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
updateLanguages(languages: string[]) {
this.languages = languages;
// TODO@rebornix metadata: default language for cell
if (this._isUntitled && languages.length && this.cells.length) {
this.cells[0].language = languages[0];
}
}
updateNotebookMetadata(metadata: NotebookDocumentMetadata) {
@@ -57,7 +63,27 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
});
}
insertTemplateCell(cell: NotebookCellTextModel) {
if (this.cells.length > 0 || this._isUntitled !== undefined) {
return;
}
this._isUntitled = true;
this.cells = [cell];
let dirtyStateListener = cell.onDidChangeContent(() => {
this._isUntitled = false;
this._onDidChangeContent.fire();
});
this._cellListeners.set(cell.handle, dirtyStateListener);
this._onDidChangeContent.fire();
return;
}
insertNewCell(index: number, cell: NotebookCellTextModel): void {
this._isUntitled = false;
this._mapping.set(cell.handle, cell);
this.cells.splice(index, 0, cell);
let dirtyStateListener = cell.onDidChangeContent(() => {
@@ -70,6 +96,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
}
removeCell(index: number) {
this._isUntitled = false;
let cell = this.cells[index];
this._cellListeners.get(cell.handle)?.dispose();
this._cellListeners.delete(cell.handle);
@@ -80,6 +108,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
// TODO@rebornix should this trigger content change event?
$spliceNotebookCells(splices: NotebookCellsSplice[]): void {
if (!splices.length) {
return;
}
this._isUntitled = false;
splices.reverse().forEach(splice => {
let cellDtos = splice[2];
let newCells = cellDtos.map(cell => {

View File

@@ -136,6 +136,7 @@ export interface ICell {
metadata?: NotebookCellMetadata;
onDidChangeOutputs?: Event<NotebookCellOutputsSplice[]>;
onDidChangeMetadata: Event<NotebookCellMetadata | undefined>;
onDidChangeLanguage: Event<string>;
resolveTextBufferFactory(): PieceTreeTextBufferFactory;
// TODO@rebornix it should be later on replaced by moving textmodel resolution into CellTextModel
contentChange(): void;

View File

@@ -27,6 +27,9 @@ export class TestCell implements ICell {
onDidChangeOutputs: Event<NotebookCellOutputsSplice[]> = this._onDidChangeOutputs.event;
private _onDidChangeMetadata = new Emitter<NotebookCellMetadata>();
onDidChangeMetadata: Event<NotebookCellMetadata> = this._onDidChangeMetadata.event;
private _onDidChangeLanguage = new Emitter<string>();
onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
private _isDirty: boolean = false;
private _outputs: IOutput[];

View File

@@ -61,6 +61,7 @@ const toggleOutputActionKeybindings = {
const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({
id: OUTPUT_VIEW_ID,
name: nls.localize('output', "Output"),
order: 1,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [OUTPUT_VIEW_ID, OUTPUT_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
focusCommand: { id: toggleOutputAcitonId, keybindings: toggleOutputActionKeybindings }
}, ViewContainerLocation.Panel);

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./remoteViewlet';
import 'vs/css!./media/remoteViewlet';
import * as nls from 'vs/nls';
import * as dom from 'vs/base/browser/dom';
import { URI } from 'vs/base/common/uri';
@@ -55,6 +55,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Event } from 'vs/base/common/event';
import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { RemoteWindowActiveIndicator } from 'vs/workbench/contrib/remote/browser/remoteIndicator';
export interface HelpInformation {
extensionDescription: IExtensionDescription;
@@ -803,3 +804,5 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteAgentConnectionStatusListener, LifecyclePhase.Eventually);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteWindowActiveIndicator, LifecyclePhase.Starting);

View File

@@ -0,0 +1,229 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { STATUS_BAR_HOST_NAME_BACKGROUND, STATUS_BAR_HOST_NAME_FOREGROUND } from 'vs/workbench/common/theme';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { Disposable } from 'vs/base/common/lifecycle';
import { MenuId, IMenuService, MenuItemAction, IMenu, MenuRegistry, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
import { ILabelService } from 'vs/platform/label/common/label';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { PersistentConnectionEventType } from 'vs/platform/remote/common/remoteAgentConnection';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { RemoteConnectionState, Deprecated_RemoteAuthorityContext } from 'vs/workbench/browser/contextkeys';
import { isWeb } from 'vs/base/common/platform';
import { once } from 'vs/base/common/functional';
const WINDOW_ACTIONS_COMMAND_ID = 'workbench.action.remote.showMenu';
const CLOSE_REMOTE_COMMAND_ID = 'workbench.action.remote.close';
const SHOW_CLOSE_REMOTE_COMMAND_ID = !isWeb; // web does not have a "Close Remote" command
export class RemoteWindowActiveIndicator extends Disposable implements IWorkbenchContribution {
private windowIndicatorEntry: IStatusbarEntryAccessor | undefined;
private windowCommandMenu: IMenu;
private hasWindowActions: boolean = false;
private remoteAuthority: string | undefined;
private connectionState: 'initializing' | 'connected' | 'disconnected' | undefined = undefined;
constructor(
@IStatusbarService private readonly statusbarService: IStatusbarService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@ILabelService private readonly labelService: ILabelService,
@IContextKeyService private contextKeyService: IContextKeyService,
@IMenuService private menuService: IMenuService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@ICommandService private readonly commandService: ICommandService,
@IExtensionService extensionService: IExtensionService,
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
@IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService,
@IHostService hostService: IHostService
) {
super();
this.windowCommandMenu = this.menuService.createMenu(MenuId.StatusBarWindowIndicatorMenu, this.contextKeyService);
this._register(this.windowCommandMenu);
const category = nls.localize('remote.category', "Remote");
const that = this;
registerAction2(class extends Action2 {
constructor() {
super({
id: WINDOW_ACTIONS_COMMAND_ID,
category,
title: { value: nls.localize('remote.showMenu', "Show Remote Menu"), original: 'Show Remote Menu' },
f1: true,
});
}
run = () => that.showIndicatorActions(that.windowCommandMenu);
});
this.remoteAuthority = environmentService.configuration.remoteAuthority;
Deprecated_RemoteAuthorityContext.bindTo(this.contextKeyService).set(this.remoteAuthority || '');
if (this.remoteAuthority) {
if (SHOW_CLOSE_REMOTE_COMMAND_ID) {
registerAction2(class extends Action2 {
constructor() {
super({
id: CLOSE_REMOTE_COMMAND_ID,
category,
title: { value: nls.localize('remote.close', "Close Remote Connection"), original: 'Close Remote Connection' },
f1: true
});
}
run = () => that.remoteAuthority && hostService.openWindow({ forceReuseWindow: true });
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '6_close',
command: {
id: CLOSE_REMOTE_COMMAND_ID,
title: nls.localize({ key: 'miCloseRemote', comment: ['&& denotes a mnemonic'] }, "Close Re&&mote Connection")
},
order: 3.5
});
}
// Pending entry until extensions are ready
this.renderWindowIndicator('$(sync~spin) ' + nls.localize('host.open', "Opening Remote..."), undefined, WINDOW_ACTIONS_COMMAND_ID);
this.connectionState = 'initializing';
RemoteConnectionState.bindTo(this.contextKeyService).set(this.connectionState);
const connection = remoteAgentService.getConnection();
if (connection) {
this._register(connection.onDidStateChange((e) => {
switch (e.type) {
case PersistentConnectionEventType.ConnectionLost:
case PersistentConnectionEventType.ReconnectionPermanentFailure:
case PersistentConnectionEventType.ReconnectionRunning:
case PersistentConnectionEventType.ReconnectionWait:
this.setDisconnected(true);
break;
case PersistentConnectionEventType.ConnectionGain:
this.setDisconnected(false);
break;
}
}));
}
}
extensionService.whenInstalledExtensionsRegistered().then(_ => {
if (this.remoteAuthority) {
this._register(this.labelService.onDidChangeFormatters(e => this.updateWindowIndicator()));
remoteAuthorityResolverService.resolveAuthority(this.remoteAuthority).then(() => this.setDisconnected(false), () => this.setDisconnected(true));
}
this._register(this.windowCommandMenu.onDidChange(e => this.updateWindowActions()));
this.updateWindowIndicator();
});
}
private setDisconnected(isDisconnected: boolean): void {
const newState = isDisconnected ? 'disconnected' : 'connected';
if (this.connectionState !== newState) {
this.connectionState = newState;
RemoteConnectionState.bindTo(this.contextKeyService).set(this.connectionState);
Deprecated_RemoteAuthorityContext.bindTo(this.contextKeyService).set(isDisconnected ? `disconnected/${this.remoteAuthority!}` : this.remoteAuthority!);
this.updateWindowIndicator();
}
}
private updateWindowIndicator(): void {
const windowActionCommand = (this.remoteAuthority || this.windowCommandMenu.getActions().length) ? WINDOW_ACTIONS_COMMAND_ID : undefined;
if (this.remoteAuthority) {
const hostLabel = this.labelService.getHostLabel(REMOTE_HOST_SCHEME, this.remoteAuthority) || this.remoteAuthority;
if (this.connectionState !== 'disconnected') {
this.renderWindowIndicator(`$(remote) ${hostLabel}`, nls.localize('host.tooltip', "Editing on {0}", hostLabel), windowActionCommand);
} else {
this.renderWindowIndicator(`$(alert) ${nls.localize('disconnectedFrom', "Disconnected from")} ${hostLabel}`, nls.localize('host.tooltipDisconnected', "Disconnected from {0}", hostLabel), windowActionCommand);
}
} else {
if (windowActionCommand) {
this.renderWindowIndicator(`$(remote)`, nls.localize('noHost.tooltip', "Open a remote window"), windowActionCommand);
} else if (this.windowIndicatorEntry) {
this.windowIndicatorEntry.dispose();
this.windowIndicatorEntry = undefined;
}
}
}
private updateWindowActions() {
const newHasWindowActions = this.windowCommandMenu.getActions().length > 0;
if (newHasWindowActions !== this.hasWindowActions) {
this.hasWindowActions = newHasWindowActions;
this.updateWindowIndicator();
}
}
private renderWindowIndicator(text: string, tooltip?: string, command?: string): void {
const properties: IStatusbarEntry = {
backgroundColor: themeColorFromId(STATUS_BAR_HOST_NAME_BACKGROUND), color: themeColorFromId(STATUS_BAR_HOST_NAME_FOREGROUND), text, tooltip, command
};
if (this.windowIndicatorEntry) {
this.windowIndicatorEntry.update(properties);
} else {
this.windowIndicatorEntry = this.statusbarService.addEntry(properties, 'status.host', nls.localize('status.host', "Remote Host"), StatusbarAlignment.LEFT, Number.MAX_VALUE /* first entry */);
}
}
private showIndicatorActions(menu: IMenu) {
const actions = menu.getActions();
const items: (IQuickPickItem | IQuickPickSeparator)[] = [];
for (let actionGroup of actions) {
if (items.length) {
items.push({ type: 'separator' });
}
for (let action of actionGroup[1]) {
if (action instanceof MenuItemAction) {
let label = typeof action.item.title === 'string' ? action.item.title : action.item.title.value;
if (action.item.category) {
const category = typeof action.item.category === 'string' ? action.item.category : action.item.category.value;
label = nls.localize('cat.title', "{0}: {1}", category, label);
}
items.push({
type: 'item',
id: action.item.id,
label
});
}
}
}
if (SHOW_CLOSE_REMOTE_COMMAND_ID && this.remoteAuthority) {
if (items.length) {
items.push({ type: 'separator' });
}
items.push({
type: 'item',
id: CLOSE_REMOTE_COMMAND_ID,
label: nls.localize('closeRemote.title', 'Close Remote Connection')
});
}
const quickPick = this.quickInputService.createQuickPick();
quickPick.items = items;
quickPick.canSelectMany = false;
once(quickPick.onDidAccept)((_ => {
const selectedItems = quickPick.selectedItems;
if (selectedItems.length === 1) {
this.commandService.executeCommand(selectedItems[0].id!);
}
quickPick.hide();
}));
quickPick.show();
}
}

View File

@@ -5,23 +5,17 @@
import * as nls from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform';
import { STATUS_BAR_HOST_NAME_BACKGROUND, STATUS_BAR_HOST_NAME_FOREGROUND } from 'vs/workbench/common/theme';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { Disposable } from 'vs/base/common/lifecycle';
import { isMacintosh } from 'vs/base/common/platform';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { MenuId, IMenuService, MenuItemAction, IMenu, MenuRegistry, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchContributionsExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
import { ILabelService } from 'vs/platform/label/common/label';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { ILogService } from 'vs/platform/log/common/log';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { DialogChannel } from 'vs/platform/dialogs/electron-browser/dialogIpc';
@@ -34,211 +28,11 @@ import { PersistentConnectionEventType } from 'vs/platform/remote/common/remoteA
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { RemoteConnectionState, Deprecated_RemoteAuthorityContext, RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys';
import { RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys';
import { IDownloadService } from 'vs/platform/download/common/download';
import { OpenLocalFileFolderCommand, OpenLocalFileCommand, OpenLocalFolderCommand, SaveLocalFileCommand } from 'vs/workbench/services/dialogs/browser/simpleFileDialog';
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService';
const WINDOW_ACTIONS_COMMAND_ID = 'workbench.action.remote.showMenu';
const CLOSE_REMOTE_COMMAND_ID = 'workbench.action.remote.close';
export class RemoteWindowActiveIndicator extends Disposable implements IWorkbenchContribution {
private windowIndicatorEntry: IStatusbarEntryAccessor | undefined;
private windowCommandMenu: IMenu;
private hasWindowActions: boolean = false;
private remoteAuthority: string | undefined;
private connectionState: 'initializing' | 'connected' | 'disconnected' | undefined = undefined;
constructor(
@IStatusbarService private readonly statusbarService: IStatusbarService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@ILabelService private readonly labelService: ILabelService,
@IContextKeyService private contextKeyService: IContextKeyService,
@IMenuService private menuService: IMenuService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@ICommandService private readonly commandService: ICommandService,
@IExtensionService extensionService: IExtensionService,
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
@IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService,
@IHostService hostService: IHostService
) {
super();
this.windowCommandMenu = this.menuService.createMenu(MenuId.StatusBarWindowIndicatorMenu, this.contextKeyService);
this._register(this.windowCommandMenu);
const category = nls.localize('remote.category', "Remote");
const that = this;
registerAction2(class extends Action2 {
constructor() {
super({
id: WINDOW_ACTIONS_COMMAND_ID,
category,
title: { value: nls.localize('remote.showMenu', "Show Remote Menu"), original: 'Show Remote Menu' },
f1: true,
});
}
run = () => that.showIndicatorActions(that.windowCommandMenu);
});
this.remoteAuthority = environmentService.configuration.remoteAuthority;
Deprecated_RemoteAuthorityContext.bindTo(this.contextKeyService).set(this.remoteAuthority || '');
if (this.remoteAuthority) {
registerAction2(class extends Action2 {
constructor() {
super({
id: CLOSE_REMOTE_COMMAND_ID,
category,
title: { value: nls.localize('remote.close', "Close Remote Connection"), original: 'Close Remote Connection' },
f1: true
});
}
run = () => that.remoteAuthority && hostService.openWindow({ forceReuseWindow: true });
});
// Pending entry until extensions are ready
this.renderWindowIndicator('$(sync~spin) ' + nls.localize('host.open', "Opening Remote..."), undefined, WINDOW_ACTIONS_COMMAND_ID);
this.connectionState = 'initializing';
RemoteConnectionState.bindTo(this.contextKeyService).set(this.connectionState);
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '6_close',
command: {
id: CLOSE_REMOTE_COMMAND_ID,
title: nls.localize({ key: 'miCloseRemote', comment: ['&& denotes a mnemonic'] }, "Close Re&&mote Connection")
},
order: 3.5
});
const connection = remoteAgentService.getConnection();
if (connection) {
this._register(connection.onDidStateChange((e) => {
switch (e.type) {
case PersistentConnectionEventType.ConnectionLost:
case PersistentConnectionEventType.ReconnectionPermanentFailure:
case PersistentConnectionEventType.ReconnectionRunning:
case PersistentConnectionEventType.ReconnectionWait:
this.setDisconnected(true);
break;
case PersistentConnectionEventType.ConnectionGain:
this.setDisconnected(false);
break;
}
}));
}
}
extensionService.whenInstalledExtensionsRegistered().then(_ => {
if (this.remoteAuthority) {
this._register(this.labelService.onDidChangeFormatters(e => this.updateWindowIndicator()));
remoteAuthorityResolverService.resolveAuthority(this.remoteAuthority).then(() => this.setDisconnected(false), () => this.setDisconnected(true));
}
this._register(this.windowCommandMenu.onDidChange(e => this.updateWindowActions()));
this.updateWindowIndicator();
});
}
private setDisconnected(isDisconnected: boolean): void {
const newState = isDisconnected ? 'disconnected' : 'connected';
if (this.connectionState !== newState) {
this.connectionState = newState;
RemoteConnectionState.bindTo(this.contextKeyService).set(this.connectionState);
Deprecated_RemoteAuthorityContext.bindTo(this.contextKeyService).set(isDisconnected ? `disconnected/${this.remoteAuthority!}` : this.remoteAuthority!);
this.updateWindowIndicator();
}
}
private updateWindowIndicator(): void {
const windowActionCommand = (this.remoteAuthority || this.windowCommandMenu.getActions().length) ? WINDOW_ACTIONS_COMMAND_ID : undefined;
if (this.remoteAuthority) {
const hostLabel = this.labelService.getHostLabel(REMOTE_HOST_SCHEME, this.remoteAuthority) || this.remoteAuthority;
if (this.connectionState !== 'disconnected') {
this.renderWindowIndicator(`$(remote) ${hostLabel}`, nls.localize('host.tooltip', "Editing on {0}", hostLabel), windowActionCommand);
} else {
this.renderWindowIndicator(`$(alert) ${nls.localize('disconnectedFrom', "Disconnected from")} ${hostLabel}`, nls.localize('host.tooltipDisconnected', "Disconnected from {0}", hostLabel), windowActionCommand);
}
} else {
if (windowActionCommand) {
this.renderWindowIndicator(`$(remote)`, nls.localize('noHost.tooltip', "Open a remote window"), windowActionCommand);
} else if (this.windowIndicatorEntry) {
this.windowIndicatorEntry.dispose();
this.windowIndicatorEntry = undefined;
}
}
}
private updateWindowActions() {
const newHasWindowActions = this.windowCommandMenu.getActions().length > 0;
if (newHasWindowActions !== this.hasWindowActions) {
this.hasWindowActions = newHasWindowActions;
this.updateWindowIndicator();
}
}
private renderWindowIndicator(text: string, tooltip?: string, command?: string): void {
const properties: IStatusbarEntry = {
backgroundColor: themeColorFromId(STATUS_BAR_HOST_NAME_BACKGROUND), color: themeColorFromId(STATUS_BAR_HOST_NAME_FOREGROUND), text, tooltip, command
};
if (this.windowIndicatorEntry) {
this.windowIndicatorEntry.update(properties);
} else {
this.windowIndicatorEntry = this.statusbarService.addEntry(properties, 'status.host', nls.localize('status.host', "Remote Host"), StatusbarAlignment.LEFT, Number.MAX_VALUE /* first entry */);
}
}
private showIndicatorActions(menu: IMenu) {
const actions = menu.getActions();
const items: (IQuickPickItem | IQuickPickSeparator)[] = [];
for (let actionGroup of actions) {
if (items.length) {
items.push({ type: 'separator' });
}
for (let action of actionGroup[1]) {
if (action instanceof MenuItemAction) {
let label = typeof action.item.title === 'string' ? action.item.title : action.item.title.value;
if (action.item.category) {
const category = typeof action.item.category === 'string' ? action.item.category : action.item.category.value;
label = nls.localize('cat.title', "{0}: {1}", category, label);
}
items.push({
type: 'item',
id: action.item.id,
label
});
}
}
}
if (this.remoteAuthority) {
if (items.length) {
items.push({ type: 'separator' });
}
items.push({
type: 'item',
id: CLOSE_REMOTE_COMMAND_ID,
label: nls.localize('closeRemote.title', 'Close Remote Connection')
});
}
const quickPick = this.quickInputService.createQuickPick();
quickPick.items = items;
quickPick.canSelectMany = false;
quickPick.onDidAccept(_ => {
const selectedItems = quickPick.selectedItems;
if (selectedItems.length === 1) {
this.commandService.executeCommand(selectedItems[0].id!);
}
quickPick.hide();
});
quickPick.show();
}
}
class RemoteChannelsContribution implements IWorkbenchContribution {
constructor(
@@ -366,7 +160,6 @@ const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegist
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteChannelsContribution, LifecyclePhase.Starting);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteAgentDiagnosticListener, LifecyclePhase.Eventually);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteExtensionHostEnvironmentUpdater, LifecyclePhase.Eventually);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteWindowActiveIndicator, LifecyclePhase.Starting);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteTelemetryEnablementUpdater, LifecyclePhase.Ready);
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteEmptyWorkbenchPresentation, LifecyclePhase.Starting);

View File

@@ -496,6 +496,10 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
this.getRelativePathFileResults(query, token)
]);
if (token.isCancellationRequested) {
return [];
}
// Return quickly if no relative results are present
if (!relativePathFileResults) {
return fileSearchResults.results.map(result => result.resource);

View File

@@ -516,7 +516,7 @@ const viewContainer = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewCo
order: 1
}, ViewContainerLocation.Sidebar);
const viewDescriptor = { id: VIEW_ID, name: nls.localize('search', "Search"), ctorDescriptor: new SyncDescriptor(SearchView), canToggleVisibility: false, canMoveView: true };
const viewDescriptor = { id: VIEW_ID, containerIcon: 'codicon-search', name: nls.localize('search', "Search"), ctorDescriptor: new SyncDescriptor(SearchView), canToggleVisibility: false, canMoveView: true };
// Register search default location to sidebar
Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry).registerViews([viewDescriptor], viewContainer);

View File

@@ -462,8 +462,8 @@ export class SearchEditor extends BaseTextEditor {
_reason: 'searchEditor',
extraFileResources: this.instantiationService.invokeFunction(getOutOfWorkspaceEditorResources),
maxResults: 10000,
disregardIgnoreFiles: !config.useIgnores,
disregardExcludeSettings: !config.useIgnores,
disregardIgnoreFiles: !config.useIgnores || undefined,
disregardExcludeSettings: !config.useIgnores || undefined,
excludePattern: config.excludes,
includePattern: config.includes,
previewOptions: {

View File

@@ -382,7 +382,8 @@ const VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensi
name: nls.localize('terminal', "Terminal"),
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TERMINAL_VIEW_ID, TERMINAL_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
focusCommand: { id: TERMINAL_COMMAND_ID.FOCUS },
hideIfEmpty: true
hideIfEmpty: true,
order: 3
}, ViewContainerLocation.Panel);
Registry.as<panel.PanelRegistry>(panel.Extensions.Panels).setDefaultPanelId(TERMINAL_VIEW_ID);

View File

@@ -695,7 +695,6 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}, {
id: SyncResource.GlobalState,
label: getSyncAreaLabel(SyncResource.GlobalState),
description: localize('ui state description', "only 'Display Language' for now")
}];
}
@@ -914,7 +913,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
constructor() {
super({
id: signInCommand.id,
title: signInCommand.title,
title: localize('sign in 2', "Sync: Sign in to sync (1)"),
menu: {
group: '5_sync',
id: MenuId.GlobalActivity,

View File

@@ -7,10 +7,9 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ViewsWelcomeExtensionPoint, ViewWelcome, viewsWelcomeExtensionPointDescriptor, ViewIdentifierMap } from './viewsWelcomeExtensionPoint';
import { ViewsWelcomeExtensionPoint, ViewWelcome, ViewIdentifierMap } from './viewsWelcomeExtensionPoint';
import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions as ViewContainerExtensions, IViewsRegistry, ViewContentPriority } from 'vs/workbench/common/views';
import { localize } from 'vs/nls';
const viewsRegistry = Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry);
@@ -23,11 +22,6 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo
extensionPoint.setHandler((_, { added, removed }) => {
for (const contribution of removed) {
// Proposed API check
if (!contribution.description.enableProposedApi) {
continue;
}
for (const welcome of contribution.value) {
const disposable = this.viewWelcomeContents.get(welcome);
@@ -38,12 +32,6 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo
}
for (const contribution of added) {
// Proposed API check
if (!contribution.description.enableProposedApi) {
contribution.collector.error(localize('proposedAPI.invalid', "The '{0}' contribution is a proposed API and is only available when running out of dev or with the following command line switch: --enable-proposed-api {1}", viewsWelcomeExtensionPointDescriptor.extensionPoint, contribution.description.identifier.value));
continue;
}
for (const welcome of contribution.value) {
const id = ViewIdentifierMap[welcome.view] ?? welcome.view;
const disposable = viewsRegistry.registerViewWelcomeContent(id, {

View File

@@ -219,14 +219,14 @@ export class TitlebarPart extends BrowserTitleBarPart {
}
}
} else {
this.title.style.zoom = null;
this.title.style.zoom = '';
if (isWindows || isLinux) {
if (this.appIcon) {
this.appIcon.style.zoom = null;
this.appIcon.style.zoom = '';
}
if (this.windowControls) {
this.windowControls.style.zoom = null;
this.windowControls.style.zoom = '';
}
}
}

View File

@@ -81,7 +81,7 @@ export class CommandService extends Disposable implements ICommandService {
}
try {
this._onWillExecuteCommand.fire({ commandId: id, args });
const result = this._instantiationService.invokeFunction.apply(this._instantiationService, [command.handler, ...args]);
const result = this._instantiationService.invokeFunction(command.handler, ...args);
this._onDidExecuteCommand.fire({ commandId: id, args });
return Promise.resolve(result);
} catch (err) {
@@ -90,4 +90,4 @@ export class CommandService extends Disposable implements ICommandService {
}
}
registerSingleton(ICommandService, CommandService, true);
registerSingleton(ICommandService, CommandService, true);

View File

@@ -339,7 +339,7 @@ export class HistoryService extends Disposable implements IHistoryService {
const navigateToStackEntry = this.navigationStack[this.navigationStackIndex];
this.doNavigate(navigateToStackEntry).finally(() => this.navigatingInStack = false);
this.doNavigate(navigateToStackEntry).finally(() => { this.navigatingInStack = false; });
}
private doNavigate(location: IStackEntry): Promise<IEditorPane | undefined> {

View File

@@ -150,31 +150,19 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
// update settings schema setting for theme specific settings
this.colorThemeRegistry.onDidChange(async event => {
updateColorThemeConfigurationSchemas(event.themes);
const colorThemeSetting = this.settings.colorTheme;
if (colorThemeSetting !== this.currentColorTheme.settingsId) {
const theme = await this.colorThemeRegistry.findThemeBySettingsId(colorThemeSetting, undefined);
if (theme) {
this.setColorTheme(theme.id, undefined);
return;
}
}
if (this.currentColorTheme.isLoaded) {
const themeData = await this.colorThemeRegistry.findThemeById(this.currentColorTheme.id);
if (!themeData) {
// current theme is no longer available
prevColorId = this.currentColorTheme.id;
this.setColorTheme(DEFAULT_COLOR_THEME_ID, 'auto');
} else {
if (this.currentColorTheme.id === DEFAULT_COLOR_THEME_ID && !types.isUndefined(prevColorId) && await this.colorThemeRegistry.findThemeById(prevColorId)) {
// restore theme
this.setColorTheme(prevColorId, 'auto');
prevColorId = undefined;
} else if (event.added.some(t => t.settingsId === this.currentColorTheme.settingsId)) {
this.reloadCurrentColorTheme();
}
if (await this.restoreColorTheme()) { // checks if theme from settings exists and is set
// restore theme
if (this.currentColorTheme.id === DEFAULT_COLOR_THEME_ID && !types.isUndefined(prevColorId) && await this.colorThemeRegistry.findThemeById(prevColorId)) {
// restore theme
this.setColorTheme(prevColorId, 'auto');
prevColorId = undefined;
} else if (event.added.some(t => t.settingsId === this.currentColorTheme.settingsId)) {
this.reloadCurrentColorTheme();
}
} else if (event.removed.some(t => t.settingsId === this.currentColorTheme.settingsId)) {
// current theme is no longer available
prevColorId = this.currentColorTheme.id;
this.setColorTheme(DEFAULT_COLOR_THEME_ID, 'auto');
}
});
@@ -189,7 +177,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
} else if (event.added.some(t => t.settingsId === this.currentFileIconTheme.settingsId)) {
this.reloadCurrentFileIconTheme();
}
} else {
} else if (event.removed.some(t => t.settingsId === this.currentFileIconTheme.settingsId)) {
// current theme is no longer available
prevFileIconId = this.currentFileIconTheme.id;
this.setFileIconTheme(DEFAULT_FILE_ICON_THEME_ID, 'auto');
@@ -208,7 +196,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
} else if (event.added.some(t => t.settingsId === this.currentProductIconTheme.settingsId)) {
this.reloadCurrentProductIconTheme();
}
} else {
} else if (event.removed.some(t => t.settingsId === this.currentProductIconTheme.settingsId)) {
// current theme is no longer available
prevProductIconId = this.currentProductIconTheme.id;
this.setProductIconTheme(DEFAULT_PRODUCT_ICON_THEME_ID, 'auto');
@@ -391,17 +379,19 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
this.applyTheme(this.currentColorTheme, undefined, false);
}
public restoreColorTheme() {
const colorThemeSetting = this.settings.colorTheme;
if (colorThemeSetting !== this.currentColorTheme.settingsId) {
this.colorThemeRegistry.findThemeBySettingsId(colorThemeSetting, undefined).then(theme => {
if (theme) {
this.setColorTheme(theme.id, undefined);
}
});
public async restoreColorTheme(): Promise<boolean> {
const settingId = this.settings.colorTheme;
const theme = await this.colorThemeRegistry.findThemeBySettingsId(settingId);
if (theme) {
if (settingId !== this.currentColorTheme.settingsId) {
await this.setColorTheme(theme.id, undefined);
}
return true;
}
return false;
}
private updateDynamicCSSRules(themeData: IColorTheme) {
const cssRules = new Set<string>();
const ruleCollector = {

View File

@@ -107,6 +107,7 @@ export function registerProductIconThemeExtensionPoint() {
export interface ThemeChangeEvent<T> {
themes: T[];
added: T[];
removed: T[];
}
export interface IThemeData {
@@ -135,10 +136,11 @@ export class ThemeRegistry<T extends IThemeData> {
private initialize() {
this.themesExtPoint.setHandler((extensions, delta) => {
const previousIds: { [key: string]: boolean } = {};
const previousIds: { [key: string]: T } = {};
const added: T[] = [];
for (const theme of this.extensionThemes) {
previousIds[theme.id] = true;
previousIds[theme.id] = theme;
}
this.extensionThemes.length = 0;
for (let ext of extensions) {
@@ -154,9 +156,12 @@ export class ThemeRegistry<T extends IThemeData> {
for (const theme of this.extensionThemes) {
if (!previousIds[theme.id]) {
added.push(theme);
} else {
delete previousIds[theme.id];
}
}
this.onDidChangeEmitter.fire({ themes: this.extensionThemes, added });
const removed = Object.values(previousIds);
this.onDidChangeEmitter.fire({ themes: this.extensionThemes, added, removed });
});
}

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { StorageKeysSyncRegistryChannelClient } from 'vs/platform/userDataSync/common/userDataSyncIpc';
class StorageKeysSyncRegistryService extends StorageKeysSyncRegistryChannelClient implements IStorageKeysSyncRegistryService {
constructor(
@IMainProcessService mainProcessService: IMainProcessService
) {
super(mainProcessService.getChannel('storageKeysSyncRegistryService'));
}
}
registerSingleton(IStorageKeysSyncRegistryService, StorageKeysSyncRegistryService);

View File

@@ -14,8 +14,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { Event, Emitter } from 'vs/base/common/event';
import { firstIndex } from 'vs/base/common/arrays';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { VIEW_ID as SEARCH_VIEW_ID } from 'vs/workbench/services/search/common/search';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
class CounterSet<T> implements IReadableSet<T> {
@@ -192,6 +191,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
private readonly viewDescriptorCollections: Map<ViewContainer, { viewDescriptorCollection: ViewDescriptorCollection, disposable: IDisposable; }>;
private readonly activeViewContextKeys: Map<string, IContextKey<boolean>>;
private readonly movableViewContextKeys: Map<string, IContextKey<boolean>>;
private readonly defaultViewLocationContextKeys: Map<string, IContextKey<boolean>>;
private readonly viewsRegistry: IViewsRegistry;
private readonly viewContainersRegistry: IViewContainersRegistry;
@@ -219,13 +219,15 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IStorageService private readonly storageService: IStorageService,
@IExtensionService private readonly extensionService: IExtensionService,
@IConfigurationService private readonly configurationService: IConfigurationService
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
) {
super();
storageKeysSyncRegistryService.registerStorageKey({ key: ViewDescriptorService.CACHED_VIEW_POSITIONS, version: 1 });
this.viewDescriptorCollections = new Map<ViewContainer, { viewDescriptorCollection: ViewDescriptorCollection, disposable: IDisposable; }>();
this.activeViewContextKeys = new Map<string, IContextKey<boolean>>();
this.movableViewContextKeys = new Map<string, IContextKey<boolean>>();
this.defaultViewLocationContextKeys = new Map<string, IContextKey<boolean>>();
this.viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry);
this.viewsRegistry = Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry);
@@ -254,33 +256,6 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
this._register(this.storageService.onDidChangeStorage((e) => { this.onDidStorageChange(e); }));
this._register(this.extensionService.onDidRegisterExtensions(() => this.onDidRegisterExtensions()));
this._register(this.configurationService.onDidChangeConfiguration((changeEvent) => {
if (changeEvent.affectedKeys.find(key => key === 'workbench.view.experimental.allowMovingToNewContainer')) {
if (this.viewsCanMoveSettingValue) {
return;
}
// update all moved views to their default locations
for (const viewId of this.cachedViewInfo.keys()) {
if (viewId === SEARCH_VIEW_ID) {
continue;
}
const viewDescriptor = this.getViewDescriptor(viewId);
const viewLocation = this.getViewContainer(viewId);
const defaultLocation = this.getDefaultContainer(viewId);
if (viewDescriptor && viewLocation && defaultLocation && defaultLocation !== viewLocation) {
this.moveViews([viewDescriptor], viewLocation, defaultLocation);
}
}
}
}));
}
private get viewsCanMoveSettingValue(): boolean {
return !!this.configurationService.getValue<boolean>('workbench.view.experimental.allowMovingToNewContainer');
}
private registerGroupedViews(groupedViews: Map<string, { cachedContainerInfo?: ICachedViewContainerInfo, views: IViewDescriptor[] }>): void {
@@ -377,7 +352,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
}
private shouldGenerateContainer(containerInfo: ICachedViewContainerInfo): boolean {
return !!containerInfo.sourceViewId && containerInfo.location !== undefined && (this.viewsCanMoveSettingValue || containerInfo.sourceViewId === SEARCH_VIEW_ID);
return !!containerInfo.sourceViewId && containerInfo.location !== undefined;
}
private onDidDeregisterViews(views: IViewDescriptor[], viewContainer: ViewContainer): void {
@@ -445,11 +420,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
}
moveViewToLocation(view: IViewDescriptor, location: ViewContainerLocation): void {
let container = this.getDefaultContainer(view.id)!;
if (this.getViewContainerLocation(container) !== location) {
container = this.registerViewContainerForSingleView(view, location);
}
let container = this.registerViewContainerForSingleView(view, location);
this.moveViewsToContainer([view], container);
}
@@ -491,7 +462,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
id,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [id, `${id}.state`, { mergeViewWithContainerWhenSingleView: true }]),
name: sourceView.name,
icon: sourceView.containerIcon,
icon: location === ViewContainerLocation.Sidebar ? sourceView.containerIcon || 'codicon-window' : undefined,
hideIfEmpty: true
}, location);
}
@@ -675,12 +646,17 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
const sourceViewId = this.generatedContainerSourceViewIds.get(container.id);
views.forEach(view => {
this.cachedViewInfo.set(view.id, { containerId: container.id, location, sourceViewId });
this.getOrCreateDefaultViewLocationContextKey(view).set(this.getDefaultContainer(view.id) === container);
});
this.getViewDescriptors(container).addViews(views);
}
private removeViews(container: ViewContainer, views: IViewDescriptor[]): void {
// Set view default location keys to false
views.forEach(view => this.getOrCreateDefaultViewLocationContextKey(view).set(false));
// Remove the views
this.getViewDescriptors(container).removeViews(views);
}
@@ -703,6 +679,16 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
}
return contextKey;
}
private getOrCreateDefaultViewLocationContextKey(viewDescriptor: IViewDescriptor): IContextKey<boolean> {
const defaultViewLocationContextKeyId = `${viewDescriptor.id}.defaultViewLocation`;
let contextKey = this.defaultViewLocationContextKeys.get(defaultViewLocationContextKeyId);
if (!contextKey) {
contextKey = new RawContextKey(defaultViewLocationContextKeyId, false).bindTo(this.contextKeyService);
this.defaultViewLocationContextKeys.set(defaultViewLocationContextKeyId, contextKey);
}
return contextKey;
}
}
registerSingleton(IViewDescriptorService, ViewDescriptorService);

View File

@@ -535,8 +535,8 @@ suite('ViewDescriptorService', () => {
sidebarViews = viewDescriptorService.getViewDescriptors(sidebarContainer);
panelViews = viewDescriptorService.getViewDescriptors(panelContainer);
assert.equal(sidebarViews.activeViewDescriptors.length, 2, 'Sidebar should have 2 views');
assert.equal(panelViews.activeViewDescriptors.length, 1, 'Panel should have 1 view');
assert.equal(sidebarViews.activeViewDescriptors.length, 1, 'Sidebar should have 2 views');
assert.equal(panelViews.activeViewDescriptors.length, 0, 'Panel should have 1 view');
assert.equal(viewDescriptorService.getViewLocation(viewDescriptors[0].id), ViewContainerLocation.Sidebar, 'View should be located in the sidebar');
assert.equal(viewDescriptorService.getViewLocation(viewDescriptors[2].id), ViewContainerLocation.Panel, 'View should be located in the panel');
@@ -602,11 +602,11 @@ suite('ViewDescriptorService', () => {
expectedSequence += locationMoveString(viewDescriptors[0], ViewContainerLocation.Panel, ViewContainerLocation.Sidebar);
expectedSequence += containerMoveString(viewDescriptors[0], viewDescriptorService.getViewContainer(viewDescriptors[0].id)!, sidebarContainer);
viewDescriptorService.moveViewToLocation(viewDescriptors[0], ViewContainerLocation.Sidebar);
viewDescriptorService.moveViewsToContainer([viewDescriptors[0]], sidebarContainer);
expectedSequence += locationMoveString(viewDescriptors[2], ViewContainerLocation.Sidebar, ViewContainerLocation.Panel);
expectedSequence += containerMoveString(viewDescriptors[2], viewDescriptorService.getViewContainer(viewDescriptors[2].id)!, panelContainer);
viewDescriptorService.moveViewToLocation(viewDescriptors[2], ViewContainerLocation.Panel);
viewDescriptorService.moveViewsToContainer([viewDescriptors[2]], panelContainer);
expectedSequence += locationMoveString(viewDescriptors[0], ViewContainerLocation.Sidebar, ViewContainerLocation.Panel);
expectedSequence += containerMoveString(viewDescriptors[0], sidebarContainer, panelContainer);

View File

@@ -105,6 +105,7 @@ import { IListService } from 'vs/platform/list/browser/listService';
import { win32, posix } from 'vs/base/common/path';
import { TestWorkingCopyService, TestContextService, TestStorageService, TestTextResourcePropertiesService } from 'vs/workbench/test/common/workbenchTestServices';
import { IViewsService, IView } from 'vs/workbench/common/views';
import { IStorageKeysSyncRegistryService, StorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
export function createFileEditorInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput {
return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined);
@@ -168,6 +169,7 @@ export function workbenchInstantiationService(overrides?: { textFileService?: (i
instantiationService.stub(IViewletService, new TestViewletService());
instantiationService.stub(IListService, new TestListService());
instantiationService.stub(IQuickInputService, new QuickInputService(TestEnvironmentService, configService, instantiationService, keybindingService, contextKeyService, themeService, accessibilityService, layoutService));
instantiationService.stub(IStorageKeysSyncRegistryService, new StorageKeysSyncRegistryService());
return instantiationService;
}

View File

@@ -49,6 +49,7 @@ import 'vs/workbench/services/backup/node/backupFileService';
import 'vs/workbench/services/url/electron-browser/urlService';
import 'vs/workbench/services/workspaces/electron-browser/workspacesService';
import 'vs/workbench/services/workspaces/electron-browser/workspaceEditingService';
import 'vs/workbench/services/userDataSync/electron-browser/storageKeysSyncRegistryService';
import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncService';
import 'vs/workbench/services/userDataSync/electron-browser/userDataAutoSyncService';
import 'vs/workbench/services/authentication/electron-browser/authenticationTokenService';

View File

@@ -63,6 +63,7 @@ import { TunnelService } from 'vs/workbench/services/remote/common/tunnelService
import { ILoggerService } from 'vs/platform/log/common/log';
import { FileLoggerService } from 'vs/platform/log/common/fileLogService';
import { IUserDataSyncStoreService, IUserDataSyncService, IUserDataSyncLogService, IUserDataAutoSyncService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
import { StorageKeysSyncRegistryService, IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { AuthenticationService, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
@@ -84,6 +85,7 @@ registerSingleton(IAuthenticationService, AuthenticationService);
registerSingleton(IUserDataSyncLogService, UserDataSyncLogService);
registerSingleton(IUserDataSyncStoreService, UserDataSyncStoreService);
registerSingleton(IUserDataSyncBackupStoreService, UserDataSyncBackupStoreService);
registerSingleton(IStorageKeysSyncRegistryService, StorageKeysSyncRegistryService);
registerSingleton(IAuthenticationTokenService, AuthenticationTokenService);
registerSingleton(IUserDataAutoSyncService, UserDataAutoSyncService);
registerSingleton(IUserDataSyncService, UserDataSyncService);