提交 31b6323e 编写于 作者: S Sandeep Somavarapu

Sync pinned state and order of composite items across windows

上级 c0766762
......@@ -15,14 +15,14 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { IPartService, Parts, Position as SideBarPosition } from 'vs/workbench/services/part/common/partService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/toggleActivityBarVisibility';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND } from 'vs/workbench/common/theme';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar, ICompositeBarItem } from 'vs/workbench/browser/parts/compositeBar';
import { Dimension, addClass } from 'vs/base/browser/dom';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ToggleCompositePinnedAction, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions';
......@@ -70,7 +70,7 @@ export class ActivitybarPart extends Part {
) {
super(id, { hasTitle: false }, themeService, storageService);
this.cachedViewlets = this.loadCachedViewlets();
this.cachedViewlets = this.getCachedViewlets();
for (const cachedViewlet of this.cachedViewlets) {
if (this.shouldBeHidden(cachedViewlet.id, cachedViewlet)) {
cachedViewlet.visible = false;
......@@ -97,7 +97,7 @@ export class ActivitybarPart extends Part {
}
private registerListeners(): void {
this._register(this.compositeBar.onDidChange(() => this.saveCachedViewlets()));
this._register(this.viewletService.onDidViewletRegister(viewlet => this.onDidRegisterViewlets([viewlet])));
// Activate viewlet action on opening of a viewlet
......@@ -113,7 +113,14 @@ export class ActivitybarPart extends Part {
}
}));
this._register(this.extensionService.onDidRegisterExtensions(() => this.onDidRegisterExtensions()));
let disposables: IDisposable[] = [];
this._register(this.extensionService.onDidRegisterExtensions(() => {
disposables = dispose(disposables);
this.onDidRegisterExtensions();
this.compositeBar.onDidChange(() => this.saveCachedViewlets(), this, disposables);
this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables);
}));
this._register(toDisposable(() => dispose(disposables)));
}
private onDidRegisterExtensions(): void {
......@@ -127,6 +134,7 @@ export class ActivitybarPart extends Part {
viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(viewlet, viewDescriptors));
}
}
this.saveCachedViewlets();
}
private onDidChangeActiveViews(viewlet: ViewletDescriptor, viewDescriptors: IViewDescriptorCollection): void {
......@@ -351,14 +359,42 @@ export class ActivitybarPart extends Part {
return sizes;
}
protected saveState(): void {
this.saveCachedViewlets();
super.saveState();
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
if (e.key === ActivitybarPart.PINNED_VIEWLETS && e.scope === StorageScope.GLOBAL
&& this.cachedViewletsValue !== this.getStoredCachedViewletsValue() /* This checks if current window changed the value or not */) {
this._cachedViewletsValue = null;
const newCompositeItems: ICompositeBarItem[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
const cachedViewlets = this.getCachedViewlets();
for (const cachedViewlet of cachedViewlets) {
// Add and update existing items
const existingItem = compositeItems.filter(({ id }) => id === cachedViewlet.id)[0];
if (existingItem) {
newCompositeItems.push({
id: existingItem.id,
name: existingItem.name,
order: existingItem.order,
pinned: cachedViewlet.pinned,
visible: existingItem.visible
});
}
}
for (let index = 0; index < compositeItems.length; index++) {
// Add items currently exists but does not exist in new.
if (!newCompositeItems.some(({ id }) => id === compositeItems[index].id)) {
newCompositeItems.splice(index, 0, compositeItems[index]);
}
}
this.compositeBar.setCompositeBarItems(newCompositeItems);
}
}
private saveCachedViewlets(): void {
const state: ICachedViewlet[] = [];
const compositeItems = this.compositeBar.getComposites();
const compositeItems = this.compositeBar.getCompositeBarItems();
const allViewlets = this.viewletService.getAllViewlets();
for (const compositeItem of compositeItems) {
const viewContainer = this.getViewContainer(compositeItem.id);
......@@ -373,11 +409,11 @@ export class ActivitybarPart extends Part {
state.push({ id: compositeItem.id, iconUrl: viewlet.iconUrl, views, pinned: compositeItem && compositeItem.pinned, order: compositeItem ? compositeItem.order : void 0, visible: compositeItem && compositeItem.visible });
}
}
this.storageService.store(ActivitybarPart.PINNED_VIEWLETS, JSON.stringify(state), StorageScope.GLOBAL);
this.cachedViewletsValue = JSON.stringify(state);
}
private loadCachedViewlets(): ICachedViewlet[] {
const storedStates = <Array<string | ICachedViewlet>>JSON.parse(this.storageService.get(ActivitybarPart.PINNED_VIEWLETS, StorageScope.GLOBAL, '[]'));
private getCachedViewlets(): ICachedViewlet[] {
const storedStates = <Array<string | ICachedViewlet>>JSON.parse(this.cachedViewletsValue);
const cachedViewlets = <ICachedViewlet[]>storedStates.map(c => {
const serialized: ICachedViewlet = typeof c === 'string' /* migration from pinned states to composites states */ ? <ICachedViewlet>{ id: c, pinned: true, order: void 0, visible: true, iconUrl: void 0, views: void 0 } : c;
serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible;
......@@ -400,6 +436,29 @@ export class ActivitybarPart extends Part {
return result;
}
private _cachedViewletsValue: string;
private get cachedViewletsValue(): string {
if (!this._cachedViewletsValue) {
this._cachedViewletsValue = this.getStoredCachedViewletsValue();
}
return this._cachedViewletsValue;
}
private set cachedViewletsValue(cachedViewletsValue: string) {
if (this.cachedViewletsValue !== cachedViewletsValue) {
this._cachedViewletsValue = cachedViewletsValue;
this.setStoredCachedViewletsValue(cachedViewletsValue);
}
}
private getStoredCachedViewletsValue(): string {
return this.storageService.get(ActivitybarPart.PINNED_VIEWLETS, StorageScope.GLOBAL, '[]');
}
private setStoredCachedViewletsValue(value: string): void {
this.storageService.store(ActivitybarPart.PINNED_VIEWLETS, value, StorageScope.GLOBAL);
}
private getViewContainer(viewletId: string): ViewContainer | undefined {
// TODO: @Joao Remove this after moving SCM Viewlet to ViewContainerViewlet - https://github.com/Microsoft/vscode/issues/49054
if (viewletId === SCM_VIEWLET_ID) {
......
......@@ -62,7 +62,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
readonly onDidChange: Event<void> = this._onDidChange.event;
constructor(
items: ICompositeBarModelItem[],
items: ICompositeBarItem[],
private options: ICompositeBarOptions,
@IInstantiationService private instantiationService: IInstantiationService,
@IContextMenuService private contextMenuService: IContextMenuService
......@@ -75,11 +75,17 @@ export class CompositeBar extends Widget implements ICompositeBar {
this.compositeTransfer = LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>();
}
getComposites(): ICompositeBarModelItem[] {
getCompositeBarItems(): ICompositeBarItem[] {
return [...this.model.items];
}
getPinnedComposites(): ICompositeBarModelItem[] {
setCompositeBarItems(items: ICompositeBarItem[]): void {
if (this.model.setItems(items)) {
this.updateCompositeSwitcher();
}
}
getPinnedComposites(): ICompositeBarItem[] {
return this.model.pinnedItems;
}
......@@ -445,7 +451,7 @@ interface ICompositeBarModelItem extends ICompositeBarItem {
class CompositeBarModel {
items: ICompositeBarModelItem[];
private _items: ICompositeBarModelItem[];
private readonly options: ICompositeBarOptions;
activeItem: ICompositeBarModelItem;
......@@ -454,7 +460,43 @@ class CompositeBarModel {
options: ICompositeBarOptions
) {
this.options = options;
this.items = items.map(i => this.createCompositeBarItem(i.id, i.name, i.order, i.pinned, i.visible));
this.setItems(items);
}
get items(): ICompositeBarModelItem[] {
return this._items;
}
setItems(items: ICompositeBarItem[]): boolean {
const result: ICompositeBarModelItem[] = [];
let hasChanges: boolean = false;
if (!this.items || this.items.length === 0) {
this._items = items.map(i => this.createCompositeBarItem(i.id, i.name, i.order, i.pinned, i.visible));
hasChanges = true;
} else {
const existingItems = this.items;
for (let index = 0; index < items.length; index++) {
const newItem = items[index];
const existingItem = existingItems.filter(({ id }) => id === newItem.id)[0];
if (existingItem) {
if (
existingItem.pinned !== newItem.pinned ||
index !== existingItems.indexOf(existingItem)
) {
existingItem.pinned = newItem.pinned;
result.push(existingItem);
hasChanges = true;
} else {
result.push(existingItem);
}
} else {
result.push(this.createCompositeBarItem(newItem.id, newItem.name, newItem.order, newItem.pinned, newItem.visible));
hasChanges = true;
}
}
this._items = result;
}
return hasChanges;
}
get visibleItems(): ICompositeBarModelItem[] {
......
......@@ -13,7 +13,7 @@ import { CompositePart, ICompositeTitleLabel } from 'vs/workbench/browser/parts/
import { Panel, PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel';
import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService';
import { IPartService, Parts, Position } from 'vs/workbench/services/part/common/partService';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
......@@ -22,7 +22,7 @@ import { ClosePanelAction, TogglePanelPositionAction, PanelActivityAction, Toggl
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar } from 'vs/workbench/browser/parts/compositeBar';
import { CompositeBar, ICompositeBarItem } from 'vs/workbench/browser/parts/compositeBar';
import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { INotificationService } from 'vs/platform/notification/common/notification';
......@@ -31,6 +31,7 @@ import { localize } from 'vs/nls';
import { IDisposable } from 'vs/base/common/lifecycle';
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
export const ActivePanelContext = new RawContextKey<string>('activePanel', '');
export const PanelFocusContext = new RawContextKey<boolean>('panelFocus', false);
......@@ -69,6 +70,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
@IInstantiationService instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService,
@ILifecycleService private lifecycleService: ILifecycleService
) {
super(
notificationService,
......@@ -89,7 +91,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
{ hasTitle: true }
);
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.loadCachedPanels(), {
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.getCachedPanels(), {
icon: false,
orientation: ActionsOrientation.HORIZONTAL,
openComposite: (compositeId: string) => Promise.resolve(this.openPanel(compositeId, true)),
......@@ -116,8 +118,6 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
})
}));
this._register(this.compositeBar.onDidChange(() => this.saveCachedPanels()));
for (const panel of this.getPanels()) {
this.compositeBar.addComposite(panel);
}
......@@ -155,6 +155,11 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
// Deactivate panel action on close
this._register(this.onDidPanelClose(panel => this.compositeBar.deactivateComposite(panel.getId())));
this.lifecycleService.when(LifecyclePhase.Eventually).then(() => {
this._register(this.compositeBar.onDidChange(() => this.saveCachedPanels()));
this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e)));
});
}
private _onDidPanelOpen(panel: IPanel): void {
......@@ -337,9 +342,42 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
return this.toolBar.getItemsWidth();
}
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
if (e.key === PanelPart.PINNED_PANELS && e.scope === StorageScope.GLOBAL
&& this.cachedPanelsValue !== this.getStoredCachedPanelsValue() /* This checks if current window changed the value or not */) {
this._cachedPanelsValue = null;
const newCompositeItems: ICompositeBarItem[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
const cachedPanels = this.getCachedPanels();
for (const cachedPanel of cachedPanels) {
// Add and update existing items
const existingItem = compositeItems.filter(({ id }) => id === cachedPanel.id)[0];
if (existingItem) {
newCompositeItems.push({
id: existingItem.id,
name: existingItem.name,
order: existingItem.order,
pinned: cachedPanel.pinned,
visible: existingItem.visible
});
}
}
for (let index = 0; index < compositeItems.length; index++) {
// Add items currently exists but does not exist in new.
if (!newCompositeItems.some(({ id }) => id === compositeItems[index].id)) {
newCompositeItems.splice(index, 0, compositeItems[index]);
}
}
this.compositeBar.setCompositeBarItems(newCompositeItems);
}
}
private saveCachedPanels(): void {
const state: ICachedPanel[] = [];
const compositeItems = this.compositeBar.getComposites();
const compositeItems = this.compositeBar.getCompositeBarItems();
const allPanels = this.getAllPanels();
for (const compositeItem of compositeItems) {
const panel = allPanels.filter(({ id }) => id === compositeItem.id)[0];
......@@ -347,11 +385,11 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
state.push({ id: panel.id, pinned: compositeItem && compositeItem.pinned, order: compositeItem ? compositeItem.order : void 0, visible: compositeItem && compositeItem.visible });
}
}
this.storageService.store(PanelPart.PINNED_PANELS, JSON.stringify(state), StorageScope.GLOBAL);
this.cachedPanelsValue = JSON.stringify(state);
}
private loadCachedPanels(): ICachedPanel[] {
const storedStates = <Array<string | ICachedPanel>>JSON.parse(this.storageService.get(PanelPart.PINNED_PANELS, StorageScope.GLOBAL, '[]'));
private getCachedPanels(): ICachedPanel[] {
const storedStates = <Array<string | ICachedPanel>>JSON.parse(this.cachedPanelsValue);
const cachedPanels = <ICachedPanel[]>storedStates.map(c => {
const serialized: ICachedPanel = typeof c === 'string' /* migration from pinned states to composites states */ ? <ICachedPanel>{ id: c, pinned: true, order: void 0, visible: true } : c;
serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible;
......@@ -359,6 +397,29 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
});
return cachedPanels;
}
private _cachedPanelsValue: string;
private get cachedPanelsValue(): string {
if (!this._cachedPanelsValue) {
this._cachedPanelsValue = this.getStoredCachedPanelsValue();
}
return this._cachedPanelsValue;
}
private set cachedPanelsValue(cachedViewletsValue: string) {
if (this.cachedPanelsValue !== cachedViewletsValue) {
this._cachedPanelsValue = cachedViewletsValue;
this.setStoredCachedViewletsValue(cachedViewletsValue);
}
}
private getStoredCachedPanelsValue(): string {
return this.storageService.get(PanelPart.PINNED_PANELS, StorageScope.GLOBAL, '[]');
}
private setStoredCachedViewletsValue(value: string): void {
this.storageService.store(PanelPart.PINNED_PANELS, value, StorageScope.GLOBAL);
}
}
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册