diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index d63f117ff4469044c7a7c858310f5b9fa2e338d3..5e0e78ec93ab80660a3d5667b3fd1d79dfbb0374 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -7,11 +7,9 @@ import 'vs/css!./media/activitybarpart'; import * as nls from 'vs/nls'; -import { TPromise } from 'vs/base/common/winjs.base'; import { illegalArgument } from 'vs/base/common/errors'; import { $ } from 'vs/base/browser/builder'; -import { Action } from 'vs/base/common/actions'; -import { ActionsOrientation, ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; +import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity'; import { Registry } from 'vs/platform/registry/common/platform'; import { Part } from 'vs/workbench/browser/part'; @@ -20,9 +18,7 @@ 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 { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ToggleActivityBarVisibilityAction } from 'vs/workbench/browser/actions/toggleActivityBarVisibility'; import { IThemeService } 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 } from 'vs/workbench/common/theme'; @@ -56,7 +52,6 @@ export class ActivitybarPart extends Part { constructor( id: string, @IViewletService private viewletService: IViewletService, - @IContextMenuService private contextMenuService: IContextMenuService, @IInstantiationService private instantiationService: IInstantiationService, @IPartService private partService: IPartService, @IThemeService themeService: IThemeService @@ -69,11 +64,12 @@ export class ActivitybarPart extends Part { icon: true, storageId: ActivitybarPart.PINNED_VIEWLETS, orientation: ActionsOrientation.VERTICAL, - composites: this.viewletService.getViewlets(), + composites: this.viewletService.getViewlets().filter(v => this.canShow(v)), openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true), getActivityAction: (compositeId: string) => this.instantiationService.createInstance(ViewletActivityAction, this.viewletService.getViewlet(compositeId)), getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.viewletService.getViewlet(compositeId), this.compositeBar), getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, this.viewletService.getViewlet(compositeId)), + getContextMenuActions: () => [this.instantiationService.createInstance(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, nls.localize('hideActivitBar', "Hide Activity Bar"))], getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(), hidePart: () => this.partService.setSideBarHidden(true), colors: ActivitybarPart.COLORS, @@ -95,7 +91,6 @@ export class ActivitybarPart extends Part { // Deactivate viewlet action on close this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.compositeBar.deactivateComposite(viewlet.getId()))); - this.toUnbind.push(this.compositeBar.onDidContextMenu(e => this.showContextMenu(e))); this.toUnbind.push(this.viewletService.onDidViewletEnablementChange(({ id, enabled }) => { if (enabled) { this.compositeBar.addComposite(this.viewletService.getViewlet(id), true); @@ -160,22 +155,6 @@ export class ActivitybarPart extends Part { container.style('border-left-color', !isPositionLeft ? borderColor : null); } - private showContextMenu(e: MouseEvent): void { - const event = new StandardMouseEvent(e); - - const actions: Action[] = this.viewletService.getViewlets() - .filter(viewlet => this.canShow(viewlet)) - .map(viewlet => this.instantiationService.createInstance(ToggleCompositePinnedAction, viewlet, this.compositeBar)); - actions.push(new Separator()); - actions.push(this.instantiationService.createInstance(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, nls.localize('hideActivitBar', "Hide Activity Bar"))); - - this.contextMenuService.showContextMenu({ - getAnchor: () => { return { x: event.posx, y: event.posy }; }, - getActions: () => TPromise.as(actions), - onHide: () => dispose(actions) - }); - } - private createGlobalActivityActionBar(container: HTMLElement): void { const activityRegistry = Registry.as(GlobalActivityExtensions); const descriptors = activityRegistry.getActivities(); diff --git a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts index cb576934bacc33ef6392c05f9c438a2bdb2bd3fb..9d65141562c0f89de1588fefc17d84042ce2a19a 100644 --- a/src/vs/workbench/browser/parts/compositebar/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositebar/compositeBar.ts @@ -6,18 +6,20 @@ 'use strict'; import * as nls from 'vs/nls'; -import { Action } from 'vs/base/common/actions'; +import { Action, IAction } from 'vs/base/common/actions'; import { illegalArgument } from 'vs/base/common/errors'; import * as arrays from 'vs/base/common/arrays'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ActionBar, IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; -import { Event, Emitter } from 'vs/base/common/event'; +import { ActionBar, IActionItem, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { CompositeActionItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; import { TPromise } from 'vs/base/common/winjs.base'; import { Dimension, $, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom'; +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { Widget } from 'vs/base/browser/ui/widget'; export interface ICompositeBarOptions { icon: boolean; @@ -29,6 +31,7 @@ export interface ICompositeBarOptions { getActivityAction: (compositeId: string) => ActivityAction; getCompositePinnedAction: (compositeId: string) => Action; getOnCompositeClickAction: (compositeId: string) => Action; + getContextMenuActions: () => Action[]; openComposite: (compositeId: string) => TPromise; getDefaultCompositeId: () => string; hidePart: () => TPromise; @@ -39,12 +42,9 @@ interface CompositeState { pinned: boolean; } -export class CompositeBar implements ICompositeBar { - - private readonly _onDidContextMenu: Emitter; +export class CompositeBar extends Widget implements ICompositeBar { private dimension: Dimension; - private toDispose: IDisposable[]; private compositeSwitcherBar: ActionBar; private compositeOverflowAction: CompositeOverflowActivityAction; @@ -64,14 +64,14 @@ export class CompositeBar implements ICompositeBar { private options: ICompositeBarOptions, @IInstantiationService private instantiationService: IInstantiationService, @IStorageService private storageService: IStorageService, + @IContextMenuService private contextMenuService: IContextMenuService ) { - this.toDispose = []; + super(); this.compositeIdToActionItems = Object.create(null); this.compositeIdToActions = Object.create(null); this.compositeIdToActivityStack = Object.create(null); this.compositeSizeInBar = new Map(); - this._onDidContextMenu = new Emitter(); this.initialCompositesStates = this.loadCompositesStates(); this.pinnedComposites = this.initialCompositesStates .filter(c => c.pinned) @@ -79,10 +79,6 @@ export class CompositeBar implements ICompositeBar { .filter(id => this.options.composites.some(c => c.id === id)); } - public get onDidContextMenu(): Event { - return this._onDidContextMenu.event; - } - public addComposite(compositeData: { id: string; name: string, order: number }, activate: boolean): void { if (this.options.composites.filter(c => c.id === compositeData.id).length) { return; @@ -216,22 +212,18 @@ export class CompositeBar implements ICompositeBar { public create(parent: HTMLElement): HTMLElement { const actionBarDiv = parent.appendChild($('.composite-bar')); - this.compositeSwitcherBar = new ActionBar(actionBarDiv, { + this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, { actionItemProvider: (action: Action) => action instanceof CompositeOverflowActivityAction ? this.compositeOverflowActionItem : this.compositeIdToActionItems[action.id], orientation: this.options.orientation, ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher"), animated: false, - }); - this.toDispose.push(this.compositeSwitcherBar); + })); // Contextmenu for composites - this.toDispose.push(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => { - EventHelper.stop(e, true); - this._onDidContextMenu.fire(e); - })); + this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e))); // Allow to drop at the end to move composites to the end - this.toDispose.push(addDisposableListener(parent, EventType.DROP, (e: DragEvent) => { + this._register(addDisposableListener(parent, EventType.DROP, (e: DragEvent) => { const draggedCompositeId = CompositeActionItem.getDraggedCompositeId(); if (draggedCompositeId) { EventHelper.stop(e, true); @@ -251,6 +243,38 @@ export class CompositeBar implements ICompositeBar { return this.compositeIdToActions[compositeId]; } + private showContextMenu(e: MouseEvent): void { + EventHelper.stop(e, true); + const event = new StandardMouseEvent(e); + this.options.composites.sort((c1, c2) => c1.order < c2.order ? -1 : 1); + const actions: IAction[] = this.options.composites + .map(({ id, name }) => ({ + id, + label: name, + checked: this.isPinned(id), + enabled: true, + run: () => this.togglePin(id) + })); + const otherActions = this.options.getContextMenuActions(); + if (otherActions.length) { + actions.push(new Separator()); + actions.push(...otherActions); + } + this.contextMenuService.showContextMenu({ + getAnchor: () => { return { x: event.posx, y: event.posy }; }, + getActions: () => TPromise.as(actions), + onHide: () => dispose(actions) + }); + } + + private togglePin(id: string): void { + if (this.isPinned(id)) { + this.unpin(id); + } else { + this.pin(id); + } + } + private updateCompositeSwitcher(): void { if (!this.compositeSwitcherBar || !this.dimension) { return; // We have not been rendered yet so there is nothing to update. @@ -554,8 +578,4 @@ export class CompositeBar implements ICompositeBar { public shutdown(): void { this.saveCompositesStates(); } - - public dispose(): void { - this.toDispose = dispose(this.toDispose); - } } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index d339b0cfe04a18464aa673eee0adf62a49fb43a1..fb5bbf0ac37f5ecdaffe355dc08796dc32bf4329 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/panelpart'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IAction, Action } from 'vs/base/common/actions'; +import { IAction } from 'vs/base/common/actions'; import { Event } from 'vs/base/common/event'; import { $ } from 'vs/base/browser/builder'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -20,17 +20,17 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ClosePanelAction, TogglePanelPositionAction, PanelActivityAction, ToggleMaximizedPanelAction } from 'vs/workbench/browser/parts/panel/panelActions'; +import { ClosePanelAction, TogglePanelPositionAction, PanelActivityAction, ToggleMaximizedPanelAction, TogglePanelAction } from 'vs/workbench/browser/parts/panel/panelActions'; 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/compositeBar'; import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositebar/compositeBarActions'; -import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; -import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { Dimension } from 'vs/base/browser/dom'; +import { localize } from 'vs/nls'; +import { IDisposable } from 'vs/base/common/lifecycle'; export class PanelPart extends CompositePart implements IPanelService { @@ -83,6 +83,7 @@ export class PanelPart extends CompositePart implements IPanelService { getActivityAction: (compositeId: string) => this.instantiationService.createInstance(PanelActivityAction, this.getPanel(compositeId)), getCompositePinnedAction: (compositeId: string) => new ToggleCompositePinnedAction(this.getPanel(compositeId), this.compositeBar), getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(PanelActivityAction, this.getPanel(compositeId)), + getContextMenuActions: () => [this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, localize('hidePanel', "Hide Panel"))], getDefaultCompositeId: () => Registry.as(PanelExtensions.Panels).getDefaultPanelId(), hidePart: () => this.partService.setPanelHidden(true), overflowActionSize: 44, @@ -108,7 +109,6 @@ export class PanelPart extends CompositePart implements IPanelService { // Need to relayout composite bar since different panels have different action bar width this.layoutCompositeBar(); })); - this.toUnbind.push(this.compositeBar.onDidContextMenu(e => this.showContextMenu(e))); // Deactivate panel action on close this.toUnbind.push(this.onDidPanelClose(panel => this.compositeBar.deactivateComposite(panel.getId()))); @@ -160,17 +160,6 @@ export class PanelPart extends CompositePart implements IPanelService { return this.getPanels().filter(p => p.id === panelId).pop(); } - private showContextMenu(e: MouseEvent): void { - const event = new StandardMouseEvent(e); - const actions: Action[] = this.getPanels().map(panel => this.instantiationService.createInstance(ToggleCompositePinnedAction, panel, this.compositeBar)); - - this.contextMenuService.showContextMenu({ - getAnchor: () => { return { x: event.posx, y: event.posy }; }, - getActions: () => TPromise.as(actions), - onHide: () => dispose(actions) - }); - } - public getPanels(): PanelDescriptor[] { return Registry.as(PanelExtensions.Panels).getPanels() .filter(p => p.enabled)