From d4841dd04aeea054d5081576b0302a03e86a60f8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 22 Sep 2016 08:04:07 +0200 Subject: [PATCH 01/24] restore global actions to activitybar --- .../parts/activitybar/activitybarPart.ts | 95 ++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index e5c6aa533e6..45053f14f62 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -12,7 +12,7 @@ import {Builder, $} from 'vs/base/browser/builder'; import {Action} from 'vs/base/common/actions'; import errors = require('vs/base/common/errors'); import {ActionsOrientation, ActionBar, IActionItem} from 'vs/base/browser/ui/actionbar/actionbar'; -import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar'; +import {CONTEXT, ToolBar} from 'vs/base/browser/ui/toolbar/toolbar'; import {Registry} from 'vs/platform/platform'; import {IViewlet} from 'vs/workbench/common/viewlet'; import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions} from 'vs/workbench/browser/viewlet'; @@ -26,10 +26,15 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat import {IMessageService} from 'vs/platform/message/common/message'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding'; +import {Scope, IActionBarRegistry, Extensions as ActionBarExtensions, prepareActions} from 'vs/workbench/browser/actionBarRegistry'; +import Severity from 'vs/base/common/severity'; +import {IAction} from 'vs/base/common/actions'; +import events = require('vs/base/common/events'); export class ActivitybarPart extends Part implements IActivityService { public _serviceBrand: any; private viewletSwitcherBar: ActionBar; + private globalViewletSwitcherBar: ActionBar; private globalToolBar: ToolBar; private activityActionItems: { [actionId: string]: IActionItem; }; private viewletIdToActions: { [viewletId: string]: ActivityAction; }; @@ -100,6 +105,9 @@ export class ActivitybarPart extends Part implements IActivityService { // Top Actionbar with action items for each viewlet action this.createViewletSwitcher($result.clone()); + // Bottom Toolbar with action items for global actions + this.createGlobalToolBarArea($result.clone()); // not used currently + return $result; } @@ -113,6 +121,14 @@ export class ActivitybarPart extends Part implements IActivityService { }); this.viewletSwitcherBar.getContainer().addClass('position-top'); + // Global viewlet switcher is right below + this.globalViewletSwitcherBar = new ActionBar(div, { + actionItemProvider: (action: Action) => this.activityActionItems[action.id], + orientation: ActionsOrientation.VERTICAL, + ariaLabel: nls.localize('globalActivityBarAriaLabel', "Active Global View Switcher") + }); + this.globalViewletSwitcherBar.getContainer().addClass('position-bottom'); + // Build Viewlet Actions in correct order const activeViewlet = this.viewletService.getActiveViewlet(); const registry = (Registry.as(ViewletExtensions.Viewlets)); @@ -145,6 +161,83 @@ export class ActivitybarPart extends Part implements IActivityService { .sort((v1, v2) => v1.order - v2.order) .map(toAction) , actionOptions); + + // Add to viewlet switcher + this.globalViewletSwitcherBar.push(allViewletActions + .filter(v => v.isGlobal) + .sort((v1, v2) => v1.order - v2.order) + .map(toAction), + actionOptions); + } + + private createGlobalToolBarArea(div: Builder): void { + + // Global action bar is on the bottom + this.globalToolBar = new ToolBar(div.getHTMLElement(), this.contextMenuService, { + actionItemProvider: (action: Action) => this.activityActionItems[action.id], + orientation: ActionsOrientation.VERTICAL + }); + this.globalToolBar.getContainer().addClass('global'); + + this.globalToolBar.actionRunner.addListener2(events.EventType.RUN, (e: any) => { + + // Check for Error + if (e.error && !errors.isPromiseCanceledError(e.error)) { + this.messageService.show(Severity.Error, e.error); + } + + // Log in telemetry + if (this.telemetryService) { + this.telemetryService.publicLog('workbenchActionExecuted', { id: e.action.id, from: 'activityBar' }); + } + }); + + // Build Global Actions in correct order + let primaryActions = this.getGlobalActions(true); + let secondaryActions = this.getGlobalActions(false); + + if (primaryActions.length + secondaryActions.length > 0) { + this.globalToolBar.getContainer().addClass('position-bottom'); + } + + // Add to global action bar + this.globalToolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions))(); + } + + private getGlobalActions(primary: boolean): IAction[] { + let actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); + + // Collect actions from actionbar contributor + let actions: IAction[]; + if (primary) { + actions = actionBarRegistry.getActionBarActionsForContext(Scope.GLOBAL, CONTEXT); + } else { + actions = actionBarRegistry.getSecondaryActionBarActionsForContext(Scope.GLOBAL, CONTEXT); + } + + return actions.map((action: ActivityAction) => { + if (primary) { + let keybinding: string = null; + let keys = this.keybindingService.lookupKeybindings(action.id).map(k => this.keybindingService.getLabelFor(k)); + if (keys && keys.length) { + keybinding = keys[0]; + } + + let actionItem = actionBarRegistry.getActionItemForContext(Scope.GLOBAL, CONTEXT, action); + + if (!actionItem) { + actionItem = new ActivityActionItem(action, action.label, keybinding); + } + + if (actionItem instanceof ActivityActionItem) { + (actionItem).keybinding = keybinding; + } + + this.activityActionItems[action.id] = actionItem; + } + + return action; + }); } public dispose(): void { From 3fae274a486c5b32ca9f792e2252a3d880c8e80a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 22 Sep 2016 08:07:13 +0200 Subject: [PATCH 02/24] let => const --- .../parts/activitybar/activitybarPart.ts | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 45053f14f62..85ee6eced13 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -70,7 +70,7 @@ export class ActivitybarPart extends Part implements IActivityService { this.viewletIdToActions[viewlet.getId()].activate(); // There can only be one active viewlet action - for (let key in this.viewletIdToActions) { + for (const key in this.viewletIdToActions) { if (this.viewletIdToActions.hasOwnProperty(key) && key !== viewlet.getId()) { this.viewletIdToActions[key].deactivate(); } @@ -85,7 +85,7 @@ export class ActivitybarPart extends Part implements IActivityService { } public showActivity(viewletId: string, badge: IBadge, clazz?: string): void { - let action = this.viewletIdToActions[viewletId]; + const action = this.viewletIdToActions[viewletId]; if (action) { action.setBadge(badge); if (clazz) { @@ -99,8 +99,8 @@ export class ActivitybarPart extends Part implements IActivityService { } public createContentArea(parent: Builder): Builder { - let $el = $(parent); - let $result = $('.content').appendTo($el); + const $el = $(parent); + const $result = $('.content').appendTo($el); // Top Actionbar with action items for each viewlet action this.createViewletSwitcher($result.clone()); @@ -131,15 +131,15 @@ export class ActivitybarPart extends Part implements IActivityService { // Build Viewlet Actions in correct order const activeViewlet = this.viewletService.getActiveViewlet(); - const registry = (Registry.as(ViewletExtensions.Viewlets)); + const registry = Registry.as(ViewletExtensions.Viewlets); const allViewletActions = registry.getViewlets(); const actionOptions = { label: true, icon: true }; const toAction = (viewlet: ViewletDescriptor) => { - let action = this.instantiationService.createInstance(ViewletActivityAction, viewlet.id + '.activity-bar-action', viewlet); + const action = this.instantiationService.createInstance(ViewletActivityAction, viewlet.id + '.activity-bar-action', viewlet); let keybinding: string = null; - let keys = this.keybindingService.lookupKeybindings(viewlet.id).map(k => this.keybindingService.getLabelFor(k)); + const keys = this.keybindingService.lookupKeybindings(viewlet.id).map(k => this.keybindingService.getLabelFor(k)); if (keys && keys.length) { keybinding = keys[0]; } @@ -193,8 +193,8 @@ export class ActivitybarPart extends Part implements IActivityService { }); // Build Global Actions in correct order - let primaryActions = this.getGlobalActions(true); - let secondaryActions = this.getGlobalActions(false); + const primaryActions = this.getGlobalActions(true); + const secondaryActions = this.getGlobalActions(false); if (primaryActions.length + secondaryActions.length > 0) { this.globalToolBar.getContainer().addClass('position-bottom'); @@ -205,7 +205,7 @@ export class ActivitybarPart extends Part implements IActivityService { } private getGlobalActions(primary: boolean): IAction[] { - let actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); + const actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); // Collect actions from actionbar contributor let actions: IAction[]; @@ -218,13 +218,12 @@ export class ActivitybarPart extends Part implements IActivityService { return actions.map((action: ActivityAction) => { if (primary) { let keybinding: string = null; - let keys = this.keybindingService.lookupKeybindings(action.id).map(k => this.keybindingService.getLabelFor(k)); + const keys = this.keybindingService.lookupKeybindings(action.id).map(k => this.keybindingService.getLabelFor(k)); if (keys && keys.length) { keybinding = keys[0]; } let actionItem = actionBarRegistry.getActionItemForContext(Scope.GLOBAL, CONTEXT, action); - if (!actionItem) { actionItem = new ActivityActionItem(action, action.label, keybinding); } @@ -274,14 +273,14 @@ class ViewletActivityAction extends ActivityAction { public run(): TPromise { // prevent accident trigger on a doubleclick (to help nervous people) - let now = Date.now(); + const now = Date.now(); if (now - this.lastRun < ViewletActivityAction.preventDoubleClickDelay) { return TPromise.as(true); } this.lastRun = now; - let sideBarHidden = this.partService.isSideBarHidden(); - let activeViewlet = this.viewletService.getActiveViewlet(); + const sideBarHidden = this.partService.isSideBarHidden(); + const activeViewlet = this.viewletService.getActiveViewlet(); // Hide sidebar if selected viewlet already visible if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.viewlet.id) { From 0a9bc82711fc4b27e1f4253c7577eeb245de227d Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 22 Sep 2016 16:17:41 +0200 Subject: [PATCH 03/24] Revert "let => const" This reverts commit 3fae274a486c5b32ca9f792e2252a3d880c8e80a. --- .../parts/activitybar/activitybarPart.ts | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 85ee6eced13..45053f14f62 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -70,7 +70,7 @@ export class ActivitybarPart extends Part implements IActivityService { this.viewletIdToActions[viewlet.getId()].activate(); // There can only be one active viewlet action - for (const key in this.viewletIdToActions) { + for (let key in this.viewletIdToActions) { if (this.viewletIdToActions.hasOwnProperty(key) && key !== viewlet.getId()) { this.viewletIdToActions[key].deactivate(); } @@ -85,7 +85,7 @@ export class ActivitybarPart extends Part implements IActivityService { } public showActivity(viewletId: string, badge: IBadge, clazz?: string): void { - const action = this.viewletIdToActions[viewletId]; + let action = this.viewletIdToActions[viewletId]; if (action) { action.setBadge(badge); if (clazz) { @@ -99,8 +99,8 @@ export class ActivitybarPart extends Part implements IActivityService { } public createContentArea(parent: Builder): Builder { - const $el = $(parent); - const $result = $('.content').appendTo($el); + let $el = $(parent); + let $result = $('.content').appendTo($el); // Top Actionbar with action items for each viewlet action this.createViewletSwitcher($result.clone()); @@ -131,15 +131,15 @@ export class ActivitybarPart extends Part implements IActivityService { // Build Viewlet Actions in correct order const activeViewlet = this.viewletService.getActiveViewlet(); - const registry = Registry.as(ViewletExtensions.Viewlets); + const registry = (Registry.as(ViewletExtensions.Viewlets)); const allViewletActions = registry.getViewlets(); const actionOptions = { label: true, icon: true }; const toAction = (viewlet: ViewletDescriptor) => { - const action = this.instantiationService.createInstance(ViewletActivityAction, viewlet.id + '.activity-bar-action', viewlet); + let action = this.instantiationService.createInstance(ViewletActivityAction, viewlet.id + '.activity-bar-action', viewlet); let keybinding: string = null; - const keys = this.keybindingService.lookupKeybindings(viewlet.id).map(k => this.keybindingService.getLabelFor(k)); + let keys = this.keybindingService.lookupKeybindings(viewlet.id).map(k => this.keybindingService.getLabelFor(k)); if (keys && keys.length) { keybinding = keys[0]; } @@ -193,8 +193,8 @@ export class ActivitybarPart extends Part implements IActivityService { }); // Build Global Actions in correct order - const primaryActions = this.getGlobalActions(true); - const secondaryActions = this.getGlobalActions(false); + let primaryActions = this.getGlobalActions(true); + let secondaryActions = this.getGlobalActions(false); if (primaryActions.length + secondaryActions.length > 0) { this.globalToolBar.getContainer().addClass('position-bottom'); @@ -205,7 +205,7 @@ export class ActivitybarPart extends Part implements IActivityService { } private getGlobalActions(primary: boolean): IAction[] { - const actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); + let actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); // Collect actions from actionbar contributor let actions: IAction[]; @@ -218,12 +218,13 @@ export class ActivitybarPart extends Part implements IActivityService { return actions.map((action: ActivityAction) => { if (primary) { let keybinding: string = null; - const keys = this.keybindingService.lookupKeybindings(action.id).map(k => this.keybindingService.getLabelFor(k)); + let keys = this.keybindingService.lookupKeybindings(action.id).map(k => this.keybindingService.getLabelFor(k)); if (keys && keys.length) { keybinding = keys[0]; } let actionItem = actionBarRegistry.getActionItemForContext(Scope.GLOBAL, CONTEXT, action); + if (!actionItem) { actionItem = new ActivityActionItem(action, action.label, keybinding); } @@ -273,14 +274,14 @@ class ViewletActivityAction extends ActivityAction { public run(): TPromise { // prevent accident trigger on a doubleclick (to help nervous people) - const now = Date.now(); + let now = Date.now(); if (now - this.lastRun < ViewletActivityAction.preventDoubleClickDelay) { return TPromise.as(true); } this.lastRun = now; - const sideBarHidden = this.partService.isSideBarHidden(); - const activeViewlet = this.viewletService.getActiveViewlet(); + let sideBarHidden = this.partService.isSideBarHidden(); + let activeViewlet = this.viewletService.getActiveViewlet(); // Hide sidebar if selected viewlet already visible if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.viewlet.id) { From 8ae184a4424086518c5463a1d7a867fa2fe2b6d2 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 22 Sep 2016 16:17:53 +0200 Subject: [PATCH 04/24] Revert "restore global actions to activitybar" This reverts commit d4841dd04aeea054d5081576b0302a03e86a60f8. --- .../parts/activitybar/activitybarPart.ts | 95 +------------------ 1 file changed, 1 insertion(+), 94 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 45053f14f62..e5c6aa533e6 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -12,7 +12,7 @@ import {Builder, $} from 'vs/base/browser/builder'; import {Action} from 'vs/base/common/actions'; import errors = require('vs/base/common/errors'); import {ActionsOrientation, ActionBar, IActionItem} from 'vs/base/browser/ui/actionbar/actionbar'; -import {CONTEXT, ToolBar} from 'vs/base/browser/ui/toolbar/toolbar'; +import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar'; import {Registry} from 'vs/platform/platform'; import {IViewlet} from 'vs/workbench/common/viewlet'; import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions} from 'vs/workbench/browser/viewlet'; @@ -26,15 +26,10 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat import {IMessageService} from 'vs/platform/message/common/message'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding'; -import {Scope, IActionBarRegistry, Extensions as ActionBarExtensions, prepareActions} from 'vs/workbench/browser/actionBarRegistry'; -import Severity from 'vs/base/common/severity'; -import {IAction} from 'vs/base/common/actions'; -import events = require('vs/base/common/events'); export class ActivitybarPart extends Part implements IActivityService { public _serviceBrand: any; private viewletSwitcherBar: ActionBar; - private globalViewletSwitcherBar: ActionBar; private globalToolBar: ToolBar; private activityActionItems: { [actionId: string]: IActionItem; }; private viewletIdToActions: { [viewletId: string]: ActivityAction; }; @@ -105,9 +100,6 @@ export class ActivitybarPart extends Part implements IActivityService { // Top Actionbar with action items for each viewlet action this.createViewletSwitcher($result.clone()); - // Bottom Toolbar with action items for global actions - this.createGlobalToolBarArea($result.clone()); // not used currently - return $result; } @@ -121,14 +113,6 @@ export class ActivitybarPart extends Part implements IActivityService { }); this.viewletSwitcherBar.getContainer().addClass('position-top'); - // Global viewlet switcher is right below - this.globalViewletSwitcherBar = new ActionBar(div, { - actionItemProvider: (action: Action) => this.activityActionItems[action.id], - orientation: ActionsOrientation.VERTICAL, - ariaLabel: nls.localize('globalActivityBarAriaLabel', "Active Global View Switcher") - }); - this.globalViewletSwitcherBar.getContainer().addClass('position-bottom'); - // Build Viewlet Actions in correct order const activeViewlet = this.viewletService.getActiveViewlet(); const registry = (Registry.as(ViewletExtensions.Viewlets)); @@ -161,83 +145,6 @@ export class ActivitybarPart extends Part implements IActivityService { .sort((v1, v2) => v1.order - v2.order) .map(toAction) , actionOptions); - - // Add to viewlet switcher - this.globalViewletSwitcherBar.push(allViewletActions - .filter(v => v.isGlobal) - .sort((v1, v2) => v1.order - v2.order) - .map(toAction), - actionOptions); - } - - private createGlobalToolBarArea(div: Builder): void { - - // Global action bar is on the bottom - this.globalToolBar = new ToolBar(div.getHTMLElement(), this.contextMenuService, { - actionItemProvider: (action: Action) => this.activityActionItems[action.id], - orientation: ActionsOrientation.VERTICAL - }); - this.globalToolBar.getContainer().addClass('global'); - - this.globalToolBar.actionRunner.addListener2(events.EventType.RUN, (e: any) => { - - // Check for Error - if (e.error && !errors.isPromiseCanceledError(e.error)) { - this.messageService.show(Severity.Error, e.error); - } - - // Log in telemetry - if (this.telemetryService) { - this.telemetryService.publicLog('workbenchActionExecuted', { id: e.action.id, from: 'activityBar' }); - } - }); - - // Build Global Actions in correct order - let primaryActions = this.getGlobalActions(true); - let secondaryActions = this.getGlobalActions(false); - - if (primaryActions.length + secondaryActions.length > 0) { - this.globalToolBar.getContainer().addClass('position-bottom'); - } - - // Add to global action bar - this.globalToolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions))(); - } - - private getGlobalActions(primary: boolean): IAction[] { - let actionBarRegistry = Registry.as(ActionBarExtensions.Actionbar); - - // Collect actions from actionbar contributor - let actions: IAction[]; - if (primary) { - actions = actionBarRegistry.getActionBarActionsForContext(Scope.GLOBAL, CONTEXT); - } else { - actions = actionBarRegistry.getSecondaryActionBarActionsForContext(Scope.GLOBAL, CONTEXT); - } - - return actions.map((action: ActivityAction) => { - if (primary) { - let keybinding: string = null; - let keys = this.keybindingService.lookupKeybindings(action.id).map(k => this.keybindingService.getLabelFor(k)); - if (keys && keys.length) { - keybinding = keys[0]; - } - - let actionItem = actionBarRegistry.getActionItemForContext(Scope.GLOBAL, CONTEXT, action); - - if (!actionItem) { - actionItem = new ActivityActionItem(action, action.label, keybinding); - } - - if (actionItem instanceof ActivityActionItem) { - (actionItem).keybinding = keybinding; - } - - this.activityActionItems[action.id] = actionItem; - } - - return action; - }); } public dispose(): void { From c9c65c9c2f0ef7742dc74996448bb166697e2da5 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 22 Sep 2016 16:31:13 +0200 Subject: [PATCH 05/24] PanelActivityAction --- .../parts/activitybar/activitybarPart.ts | 73 +++++++++++++------ 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index e5c6aa533e6..add1c19051c 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -15,10 +15,13 @@ import {ActionsOrientation, ActionBar, IActionItem} from 'vs/base/browser/ui/act import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar'; import {Registry} from 'vs/platform/platform'; import {IViewlet} from 'vs/workbench/common/viewlet'; -import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions} from 'vs/workbench/browser/viewlet'; +import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions, Viewlet} from 'vs/workbench/browser/viewlet'; +import {CompositeDescriptor, Composite} from 'vs/workbench/browser/composite'; +import {Panel} from 'vs/workbench/browser/panel'; import {Part} from 'vs/workbench/browser/part'; import {ActivityAction, ActivityActionItem} from 'vs/workbench/browser/parts/activitybar/activityAction'; import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService'; +import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; import {IActivityService, IBadge} from 'vs/workbench/services/activity/common/activityService'; import {IPartService} from 'vs/workbench/services/part/common/partService'; import {IContextMenuService} from 'vs/platform/contextview/browser/contextView'; @@ -162,45 +165,69 @@ export class ActivitybarPart extends Part implements IActivityService { } } -class ViewletActivityAction extends ActivityAction { +abstract class CompositeActivityAction extends ActivityAction { private static preventDoubleClickDelay = 300; private lastRun: number = 0; - private viewlet: ViewletDescriptor; + protected composite: CompositeDescriptor; constructor( - id: string, viewlet: ViewletDescriptor, - @IViewletService private viewletService: IViewletService, - @IPartService private partService: IPartService + id: string, composite: CompositeDescriptor, + @IViewletService protected viewletService: IViewletService, + @IPanelService protected panelService: IPanelService, + @IPartService protected partService: IPartService ) { - super(id, viewlet.name, viewlet.cssClass); + super(id, composite.name, composite.cssClass); - this.viewlet = viewlet; + this.composite = composite; } public run(): TPromise { // prevent accident trigger on a doubleclick (to help nervous people) let now = Date.now(); - if (now - this.lastRun < ViewletActivityAction.preventDoubleClickDelay) { + if (now - this.lastRun < CompositeActivityAction.preventDoubleClickDelay) { return TPromise.as(true); } this.lastRun = now; - let sideBarHidden = this.partService.isSideBarHidden(); - let activeViewlet = this.viewletService.getActiveViewlet(); - - // Hide sidebar if selected viewlet already visible - if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.viewlet.id) { - this.partService.setSideBarHidden(true); - } - - // Open viewlet and focus it - else { - this.viewletService.openViewlet(this.viewlet.id, true).done(null, errors.onUnexpectedError); - this.activate(); - } + this.toggleComposite(); return TPromise.as(true); } -} \ No newline at end of file + + protected abstract toggleComposite(): void; +} + +class ViewletActivityAction extends CompositeActivityAction { + + protected toggleComposite(): void { + const sideBarHidden = this.partService.isSideBarHidden(); + const activeViewlet = this.viewletService.getActiveViewlet(); + + // Hide sidebar if selected viewlet already visible + if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.composite.id) { + this.partService.setSideBarHidden(true); + } else { + this.viewletService.openViewlet(this.composite.id, true).done(null, errors.onUnexpectedError); + this.activate(); + } + } +} + +class PanelActivityAction extends CompositeActivityAction { + + protected toggleComposite(): void { + + const panelHidden = this.partService.isPanelHidden(); + const activePanel = this.panelService.getActivePanel(); + + // Hide panel if selected panel already visible + if (!panelHidden && activePanel && activePanel.getId() === this.composite.id) { + this.partService.setPanelHidden(true); + } else { + this.panelService.openPanel(this.composite.id, true).done(null, errors.onUnexpectedError); + this.activate(); + } + } +} From 347df0bff9300d11bac99a247c2889b151910fa5 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 22 Sep 2016 17:21:16 +0200 Subject: [PATCH 06/24] activitybar: generalize code to talk about composites not viewlets --- .../parts/activitybar/activitybarPart.ts | 69 ++++++++++--------- .../activity/common/activityService.ts | 8 +-- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index add1c19051c..0bc63ab5ac8 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -32,14 +32,15 @@ import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding'; export class ActivitybarPart extends Part implements IActivityService { public _serviceBrand: any; - private viewletSwitcherBar: ActionBar; + private compositeSwitcherBar: ActionBar; private globalToolBar: ToolBar; private activityActionItems: { [actionId: string]: IActionItem; }; - private viewletIdToActions: { [viewletId: string]: ActivityAction; }; + private compositeIdToActions: { [compositeId: string]: ActivityAction; }; constructor( id: string, @IViewletService private viewletService: IViewletService, + @IPanelService private panelService: IPanelService, @IMessageService private messageService: IMessageService, @ITelemetryService private telemetryService: ITelemetryService, @IContextMenuService private contextMenuService: IContextMenuService, @@ -49,7 +50,7 @@ export class ActivitybarPart extends Part implements IActivityService { super(id); this.activityActionItems = {}; - this.viewletIdToActions = {}; + this.compositeIdToActions = {}; this.registerListeners(); } @@ -64,26 +65,26 @@ export class ActivitybarPart extends Part implements IActivityService { } private onActiveViewletChanged(viewlet: IViewlet): void { - if (this.viewletIdToActions[viewlet.getId()]) { - this.viewletIdToActions[viewlet.getId()].activate(); + if (this.compositeIdToActions[viewlet.getId()]) { + this.compositeIdToActions[viewlet.getId()].activate(); // There can only be one active viewlet action - for (let key in this.viewletIdToActions) { - if (this.viewletIdToActions.hasOwnProperty(key) && key !== viewlet.getId()) { - this.viewletIdToActions[key].deactivate(); + for (let key in this.compositeIdToActions) { + if (this.compositeIdToActions.hasOwnProperty(key) && key !== viewlet.getId() && this.compositeIdToActions[key] instanceof ViewletActivityAction) { + this.compositeIdToActions[key].deactivate(); } } } } private onViewletClosed(viewlet: IViewlet): void { - if (this.viewletIdToActions[viewlet.getId()]) { - this.viewletIdToActions[viewlet.getId()].deactivate(); + if (this.compositeIdToActions[viewlet.getId()]) { + this.compositeIdToActions[viewlet.getId()].deactivate(); } } - public showActivity(viewletId: string, badge: IBadge, clazz?: string): void { - let action = this.viewletIdToActions[viewletId]; + public showActivity(compositeId: string, badge: IBadge, clazz?: string): void { + const action = this.compositeIdToActions[compositeId]; if (action) { action.setBadge(badge); if (clazz) { @@ -92,50 +93,52 @@ export class ActivitybarPart extends Part implements IActivityService { } } - public clearActivity(viewletId: string): void { - this.showActivity(viewletId, null); + public clearActivity(compositeId: string): void { + this.showActivity(compositeId, null); } public createContentArea(parent: Builder): Builder { - let $el = $(parent); - let $result = $('.content').appendTo($el); + const $el = $(parent); + const $result = $('.content').appendTo($el); // Top Actionbar with action items for each viewlet action - this.createViewletSwitcher($result.clone()); + this.createCompositeSwitcher($result.clone()); return $result; } - private createViewletSwitcher(div: Builder): void { + private createCompositeSwitcher(div: Builder): void { - // Viewlet switcher is on top - this.viewletSwitcherBar = new ActionBar(div, { + // Composite switcher is on top + this.compositeSwitcherBar = new ActionBar(div, { actionItemProvider: (action: Action) => this.activityActionItems[action.id], orientation: ActionsOrientation.VERTICAL, ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher") }); - this.viewletSwitcherBar.getContainer().addClass('position-top'); + this.compositeSwitcherBar.getContainer().addClass('position-top'); // Build Viewlet Actions in correct order const activeViewlet = this.viewletService.getActiveViewlet(); + const activePanel = this.panelService.getActivePanel(); const registry = (Registry.as(ViewletExtensions.Viewlets)); const allViewletActions = registry.getViewlets(); const actionOptions = { label: true, icon: true }; - const toAction = (viewlet: ViewletDescriptor) => { - let action = this.instantiationService.createInstance(ViewletActivityAction, viewlet.id + '.activity-bar-action', viewlet); + const toAction = (composite: CompositeDescriptor) => { + const action = composite instanceof ViewletDescriptor ? this.instantiationService.createInstance(ViewletActivityAction, composite.id + '.activity-bar-action', composite) + : this.instantiationService.createInstance(PanelActivityAction, composite.id + '.activity-bar-action', composite); let keybinding: string = null; - let keys = this.keybindingService.lookupKeybindings(viewlet.id).map(k => this.keybindingService.getLabelFor(k)); + const keys = this.keybindingService.lookupKeybindings(composite.id).map(k => this.keybindingService.getLabelFor(k)); if (keys && keys.length) { keybinding = keys[0]; } - this.activityActionItems[action.id] = new ActivityActionItem(action, viewlet.name, keybinding); - this.viewletIdToActions[viewlet.id] = action; + this.activityActionItems[action.id] = new ActivityActionItem(action, composite.name, keybinding); + this.compositeIdToActions[composite.id] = action; - // Mark active viewlet action as active - if (activeViewlet && activeViewlet.getId() === viewlet.id) { + // Mark active viewlet and panel action as active + if (activeViewlet && activeViewlet.getId() === composite.id || activePanel && activePanel.getId() === composite.id) { action.activate(); } @@ -143,7 +146,7 @@ export class ActivitybarPart extends Part implements IActivityService { }; // Add to viewlet switcher - this.viewletSwitcherBar.push(allViewletActions + this.compositeSwitcherBar.push(allViewletActions .filter(v => !v.isGlobal) .sort((v1, v2) => v1.order - v2.order) .map(toAction) @@ -151,9 +154,9 @@ export class ActivitybarPart extends Part implements IActivityService { } public dispose(): void { - if (this.viewletSwitcherBar) { - this.viewletSwitcherBar.dispose(); - this.viewletSwitcherBar = null; + if (this.compositeSwitcherBar) { + this.compositeSwitcherBar.dispose(); + this.compositeSwitcherBar = null; } if (this.globalToolBar) { @@ -185,7 +188,7 @@ abstract class CompositeActivityAction extends ActivityActi public run(): TPromise { // prevent accident trigger on a doubleclick (to help nervous people) - let now = Date.now(); + const now = Date.now(); if (now - this.lastRun < CompositeActivityAction.preventDoubleClickDelay) { return TPromise.as(true); } diff --git a/src/vs/workbench/services/activity/common/activityService.ts b/src/vs/workbench/services/activity/common/activityService.ts index fba35bedb2a..dafed7f0905 100644 --- a/src/vs/workbench/services/activity/common/activityService.ts +++ b/src/vs/workbench/services/activity/common/activityService.ts @@ -62,12 +62,12 @@ export interface IActivityService { _serviceBrand: any; /** - * Show activity in the activitybar for the given viewlet. + * Show activity in the activitybar for the given viewlet or panel. */ - showActivity(viewletId: string, badge: IBadge, clazz?: string): void; + showActivity(compositeId: string, badge: IBadge, clazz?: string): void; /** - * Clears activity shown in the activitybar for the given viewlet. + * Clears activity shown in the activitybar for the given viewlet or panel. */ - clearActivity(viewletId: string): void; + clearActivity(compositeId: string): void; } \ No newline at end of file From 06046e08f758857804c3fb7295a102759c1cbbc2 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 22 Sep 2016 18:05:42 +0200 Subject: [PATCH 07/24] remove ViewletDescriptor.isGlobal since it is unused --- src/vs/workbench/browser/parts/activitybar/activitybarPart.ts | 1 - src/vs/workbench/browser/viewlet.ts | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 0bc63ab5ac8..e026e886c0a 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -147,7 +147,6 @@ export class ActivitybarPart extends Part implements IActivityService { // Add to viewlet switcher this.compositeSwitcherBar.push(allViewletActions - .filter(v => !v.isGlobal) .sort((v1, v2) => v1.order - v2.order) .map(toAction) , actionOptions); diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index 69356049505..41fe5e74d88 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -152,11 +152,9 @@ export abstract class ViewerViewlet extends Viewlet { * A viewlet descriptor is a leightweight descriptor of a viewlet in the workbench. */ export class ViewletDescriptor extends CompositeDescriptor { - public isGlobal: boolean; - constructor(moduleId: string, ctorName: string, id: string, name: string, cssClass?: string, order?: number, isGlobal?: boolean) { + constructor(moduleId: string, ctorName: string, id: string, name: string, cssClass?: string, order?: number) { super(moduleId, ctorName, id, name, cssClass, order); - this.isGlobal = isGlobal || false; } } From 867a5eddcdb528167187b82a596ed613b4e567d4 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 22 Sep 2016 18:13:00 +0200 Subject: [PATCH 08/24] activitybar: add panels --- .../browser/parts/activitybar/activitybarPart.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index e026e886c0a..b1e506f4913 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -17,7 +17,7 @@ import {Registry} from 'vs/platform/platform'; import {IViewlet} from 'vs/workbench/common/viewlet'; import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions, Viewlet} from 'vs/workbench/browser/viewlet'; import {CompositeDescriptor, Composite} from 'vs/workbench/browser/composite'; -import {Panel} from 'vs/workbench/browser/panel'; +import {Panel, PanelRegistry, Extensions as PanelExtensions} from 'vs/workbench/browser/panel'; import {Part} from 'vs/workbench/browser/part'; import {ActivityAction, ActivityActionItem} from 'vs/workbench/browser/parts/activitybar/activityAction'; import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService'; @@ -120,8 +120,8 @@ export class ActivitybarPart extends Part implements IActivityService { // Build Viewlet Actions in correct order const activeViewlet = this.viewletService.getActiveViewlet(); const activePanel = this.panelService.getActivePanel(); - const registry = (Registry.as(ViewletExtensions.Viewlets)); - const allViewletActions = registry.getViewlets(); + const allViewlets = (Registry.as(ViewletExtensions.Viewlets)).getViewlets().sort((v1, v2) => v1.order - v2.order); + const allPanels = (Registry.as(PanelExtensions.Panels)).getPanels().sort((p1, p2) => p1.order - p2.order); const actionOptions = { label: true, icon: true }; const toAction = (composite: CompositeDescriptor) => { @@ -145,11 +145,9 @@ export class ActivitybarPart extends Part implements IActivityService { return action; }; - // Add to viewlet switcher - this.compositeSwitcherBar.push(allViewletActions - .sort((v1, v2) => v1.order - v2.order) - .map(toAction) - , actionOptions); + // Add both viewlet and panel actions to the switcher + const allActions = allViewlets.concat(allPanels).map(toAction); + this.compositeSwitcherBar.push(allActions, actionOptions); } public dispose(): void { From d3e797ed6e5f88c5323b5fc2878001b6c272890b Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 10:31:28 +0200 Subject: [PATCH 09/24] panel icons for activity bar --- .../workbench/browser/parts/activitybar/media/panel.svg | 1 + src/vs/workbench/parts/debug/browser/media/repl-panel.svg | 1 + src/vs/workbench/parts/debug/browser/media/repl.css | 7 +++++++ src/vs/workbench/parts/markers/browser/media/markers.css | 7 +++++++ src/vs/workbench/parts/markers/browser/media/markers.svg | 1 + .../parts/output/browser/media/output.contribution.css | 8 ++++++++ src/vs/workbench/parts/output/browser/media/output.svg | 1 + .../parts/terminal/electron-browser/media/terminal.css | 7 +++++++ .../parts/terminal/electron-browser/media/terminal.svg | 1 + 9 files changed, 34 insertions(+) create mode 100644 src/vs/workbench/browser/parts/activitybar/media/panel.svg create mode 100755 src/vs/workbench/parts/debug/browser/media/repl-panel.svg create mode 100755 src/vs/workbench/parts/markers/browser/media/markers.svg create mode 100755 src/vs/workbench/parts/output/browser/media/output.svg create mode 100755 src/vs/workbench/parts/terminal/electron-browser/media/terminal.svg diff --git a/src/vs/workbench/browser/parts/activitybar/media/panel.svg b/src/vs/workbench/browser/parts/activitybar/media/panel.svg new file mode 100644 index 00000000000..bda3f782124 --- /dev/null +++ b/src/vs/workbench/browser/parts/activitybar/media/panel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/repl-panel.svg b/src/vs/workbench/parts/debug/browser/media/repl-panel.svg new file mode 100755 index 00000000000..92e940776a9 --- /dev/null +++ b/src/vs/workbench/parts/debug/browser/media/repl-panel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/repl.css b/src/vs/workbench/parts/debug/browser/media/repl.css index da25304d6af..2f3a298a195 100644 --- a/src/vs/workbench/parts/debug/browser/media/repl.css +++ b/src/vs/workbench/parts/debug/browser/media/repl.css @@ -5,6 +5,13 @@ /* Debug repl */ +/* Activity Bar */ +.monaco-workbench > .activitybar .monaco-action-bar .action-label.repl { + background: url('repl-panel.svg') center center no-repeat; + background-position: 50% !important; + background-size: 32px; +} + .monaco-workbench .repl { height: 100%; position: relative; diff --git a/src/vs/workbench/parts/markers/browser/media/markers.css b/src/vs/workbench/parts/markers/browser/media/markers.css index 491e4ac3590..3e46357bb35 100644 --- a/src/vs/workbench/parts/markers/browser/media/markers.css +++ b/src/vs/workbench/parts/markers/browser/media/markers.css @@ -3,6 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* Activity Bar */ +.monaco-workbench > .activitybar .monaco-action-bar .action-label.markersPanel { + background: url('markers.svg') center center no-repeat; + background-position: 50% !important; + background-size: 32px; +} + .monaco-action-bar .action-item.markers-panel-action-filter { max-width: 400px; min-width: 100px; diff --git a/src/vs/workbench/parts/markers/browser/media/markers.svg b/src/vs/workbench/parts/markers/browser/media/markers.svg new file mode 100755 index 00000000000..d0173c16c20 --- /dev/null +++ b/src/vs/workbench/parts/markers/browser/media/markers.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/parts/output/browser/media/output.contribution.css b/src/vs/workbench/parts/output/browser/media/output.contribution.css index 093845880a3..a1c1e78a40d 100644 --- a/src/vs/workbench/parts/output/browser/media/output.contribution.css +++ b/src/vs/workbench/parts/output/browser/media/output.contribution.css @@ -3,6 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* Activity Bar */ +.monaco-workbench > .activitybar .monaco-action-bar .action-label.output { + background: url('output.svg') center center no-repeat; + background-position: 50% !important; + background-size: 32px; +} + + .monaco-workbench .output-action.clear-output { background: url('clear_output.svg') center center no-repeat; } diff --git a/src/vs/workbench/parts/output/browser/media/output.svg b/src/vs/workbench/parts/output/browser/media/output.svg new file mode 100755 index 00000000000..3fecd330de0 --- /dev/null +++ b/src/vs/workbench/parts/output/browser/media/output.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css index 35c4f0f5188..d2ce5e6a324 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css @@ -3,6 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* Activity Bar */ +.monaco-workbench > .activitybar .monaco-action-bar .action-label.terminal { + background: url('terminal.svg') center center no-repeat; + background-position: 50% !important; + background-size: 32px; +} + .monaco-workbench .panel.integrated-terminal { align-content: flex-start; align-items: baseline; diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.svg b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.svg new file mode 100755 index 00000000000..1ff3eda7230 --- /dev/null +++ b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.svg @@ -0,0 +1 @@ + \ No newline at end of file From a860d6a54ca0ff40cb407d9ea24540655a5d1a53 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 11:25:56 +0200 Subject: [PATCH 10/24] panel toggle icon --- .../browser/parts/activitybar/media/activitybarpart.css | 6 ++++++ src/vs/workbench/browser/parts/activitybar/media/panel.svg | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) mode change 100644 => 100755 src/vs/workbench/browser/parts/activitybar/media/panel.svg diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css index abbddbe8e9e..bef5a86cb36 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css @@ -3,6 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +.monaco-workbench > .activitybar .monaco-action-bar .action-label.panel { + background: url('panel.svg') center center no-repeat; + background-position: 50% !important; + background-size: 32px; +} + .monaco-workbench > .part.activitybar { z-index: 20; min-width: 50px; diff --git a/src/vs/workbench/browser/parts/activitybar/media/panel.svg b/src/vs/workbench/browser/parts/activitybar/media/panel.svg old mode 100644 new mode 100755 index bda3f782124..88c05455cb3 --- a/src/vs/workbench/browser/parts/activitybar/media/panel.svg +++ b/src/vs/workbench/browser/parts/activitybar/media/panel.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 05fe07ac61678e8c063aae4b4a166e7301f4b6f6 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 11:33:49 +0200 Subject: [PATCH 11/24] activity bar actions --- .../parts/activitybar/activitybarPart.ts | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index b1e506f4913..e37fcf229ba 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -36,6 +36,9 @@ export class ActivitybarPart extends Part implements IActivityService { private globalToolBar: ToolBar; private activityActionItems: { [actionId: string]: IActionItem; }; private compositeIdToActions: { [compositeId: string]: ActivityAction; }; + private viewletActions: Action[]; + private panelActions: Action[]; + private showPanelAction: ShowPanelAction; constructor( id: string, @@ -45,7 +48,8 @@ export class ActivitybarPart extends Part implements IActivityService { @ITelemetryService private telemetryService: ITelemetryService, @IContextMenuService private contextMenuService: IContextMenuService, @IKeybindingService private keybindingService: IKeybindingService, - @IInstantiationService private instantiationService: IInstantiationService + @IInstantiationService private instantiationService: IInstantiationService, + @IPartService private partService: IPartService ) { super(id); @@ -120,9 +124,8 @@ export class ActivitybarPart extends Part implements IActivityService { // Build Viewlet Actions in correct order const activeViewlet = this.viewletService.getActiveViewlet(); const activePanel = this.panelService.getActivePanel(); - const allViewlets = (Registry.as(ViewletExtensions.Viewlets)).getViewlets().sort((v1, v2) => v1.order - v2.order); - const allPanels = (Registry.as(PanelExtensions.Panels)).getPanels().sort((p1, p2) => p1.order - p2.order); - const actionOptions = { label: true, icon: true }; + const allViewlets = (Registry.as(ViewletExtensions.Viewlets)).getViewlets(); + const allPanels = (Registry.as(PanelExtensions.Panels)).getPanels(); const toAction = (composite: CompositeDescriptor) => { const action = composite instanceof ViewletDescriptor ? this.instantiationService.createInstance(ViewletActivityAction, composite.id + '.activity-bar-action', composite) @@ -144,10 +147,20 @@ export class ActivitybarPart extends Part implements IActivityService { return action; }; + this.viewletActions = allViewlets.sort((v1, v2) => v1.order - v2.order).map(toAction); + this.showPanelAction = this.instantiationService.createInstance(ShowPanelAction); + this.panelActions = allPanels.sort((p1, p2) => p1.order - p2.order).map(toAction); + // Add both viewlet and panel actions to the switcher - const allActions = allViewlets.concat(allPanels).map(toAction); - this.compositeSwitcherBar.push(allActions, actionOptions); + this.updateActionBar(); + } + + private updateActionBar(): void { + this.compositeSwitcherBar.clear(); + const actions = this.partService.isPanelHidden() ? this.viewletActions.concat(this.showPanelAction) : this.viewletActions.concat(this.panelActions); + + this.compositeSwitcherBar.push(actions, { label: true, icon: true }); } public dispose(): void { @@ -231,3 +244,16 @@ class PanelActivityAction extends CompositeActivityAction { } } } + +class ShowPanelAction extends ActivityAction { + private static ID = 'workbench.action.panel.show'; + + constructor(@IPartService private partService: IPartService) { + super(ShowPanelAction.ID, nls.localize('showPanel', "Show Panel"), 'panel'); + } + + public run(): TPromise { + this.partService.setPanelHidden(false); + return TPromise.as(null); + } +} From c0f8a7d97e1b8ec5ac1a85285a2ac020deda6d1a Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 12:24:24 +0200 Subject: [PATCH 12/24] update panel activity actions dynamically --- .../parts/activitybar/activitybarPart.ts | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index e37fcf229ba..a31609f66af 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -12,9 +12,9 @@ import {Builder, $} from 'vs/base/browser/builder'; import {Action} from 'vs/base/common/actions'; import errors = require('vs/base/common/errors'); import {ActionsOrientation, ActionBar, IActionItem} from 'vs/base/browser/ui/actionbar/actionbar'; -import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar'; import {Registry} from 'vs/platform/platform'; -import {IViewlet} from 'vs/workbench/common/viewlet'; +import {IComposite} from 'vs/workbench/common/composite'; +import {IPanel} from 'vs/workbench/common/panel'; import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions, Viewlet} from 'vs/workbench/browser/viewlet'; import {CompositeDescriptor, Composite} from 'vs/workbench/browser/composite'; import {Panel, PanelRegistry, Extensions as PanelExtensions} from 'vs/workbench/browser/panel'; @@ -33,7 +33,6 @@ import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding'; export class ActivitybarPart extends Part implements IActivityService { public _serviceBrand: any; private compositeSwitcherBar: ActionBar; - private globalToolBar: ToolBar; private activityActionItems: { [actionId: string]: IActionItem; }; private compositeIdToActions: { [compositeId: string]: ActivityAction; }; private viewletActions: Action[]; @@ -62,31 +61,36 @@ export class ActivitybarPart extends Part implements IActivityService { private registerListeners(): void { // Activate viewlet action on opening of a viewlet - this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.onActiveViewletChanged(viewlet))); + this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.onActiveCompositeChanged(viewlet))); + this.toUnbind.push(this.panelService.onDidPanelOpen(panel => this.onActivePanelChanged(panel))); // Deactivate viewlet action on close - this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.onViewletClosed(viewlet))); + this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.onCompositeClosed(viewlet))); + this.toUnbind.push(this.panelService.onDidPanelClose(panel => this.onPanelClosed(panel))); } - private onActiveViewletChanged(viewlet: IViewlet): void { - if (this.compositeIdToActions[viewlet.getId()]) { - this.compositeIdToActions[viewlet.getId()].activate(); - - // There can only be one active viewlet action - for (let key in this.compositeIdToActions) { - if (this.compositeIdToActions.hasOwnProperty(key) && key !== viewlet.getId() && this.compositeIdToActions[key] instanceof ViewletActivityAction) { - this.compositeIdToActions[key].deactivate(); - } - } + private onActiveCompositeChanged(composite: IComposite): void { + if (this.compositeIdToActions[composite.getId()]) { + this.compositeIdToActions[composite.getId()].activate(); } } - private onViewletClosed(viewlet: IViewlet): void { - if (this.compositeIdToActions[viewlet.getId()]) { - this.compositeIdToActions[viewlet.getId()].deactivate(); + private onActivePanelChanged(panel: IPanel): void { + this.updateActionBar(); + this.onActiveCompositeChanged(panel); + } + + private onCompositeClosed(composite: IComposite): void { + if (this.compositeIdToActions[composite.getId()]) { + this.compositeIdToActions[composite.getId()].deactivate(); } } + private onPanelClosed(panel: IPanel): void { + this.updateActionBar(); + this.onCompositeClosed(panel); + } + public showActivity(compositeId: string, badge: IBadge, clazz?: string): void { const action = this.compositeIdToActions[compositeId]; if (action) { @@ -149,6 +153,7 @@ export class ActivitybarPart extends Part implements IActivityService { }; this.viewletActions = allViewlets.sort((v1, v2) => v1.order - v2.order).map(toAction); this.showPanelAction = this.instantiationService.createInstance(ShowPanelAction); + this.activityActionItems[this.showPanelAction.id] = new ActivityActionItem(this.showPanelAction); this.panelActions = allPanels.sort((p1, p2) => p1.order - p2.order).map(toAction); @@ -169,9 +174,8 @@ export class ActivitybarPart extends Part implements IActivityService { this.compositeSwitcherBar = null; } - if (this.globalToolBar) { - this.globalToolBar.dispose(); - this.globalToolBar = null; + if (this.showPanelAction) { + this.showPanelAction.dispose(); } super.dispose(); From 0534afdfae1dca8b242006740b1801d1d088c150 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 12:30:36 +0200 Subject: [PATCH 13/24] action bar: do not dispose action items if they were provided from outside --- src/vs/base/browser/ui/actionbar/actionbar.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index b23736c80fb..8c6d9466041 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -529,7 +529,8 @@ export class ActionBar extends EventEmitter implements IActionRunner { } public clear(): void { - this.items = lifecycle.dispose(this.items); + // Do not dispose action items if they were provided from outside + this.items = this.options.actionItemProvider ? [] : lifecycle.dispose(this.items); $(this.actionsList).empty(); } @@ -642,7 +643,7 @@ export class ActionBar extends EventEmitter implements IActionRunner { public dispose(): void { if (this.items !== null) { - this.clear(); + lifecycle.dispose(this.items); } this.items = null; From 4dfde59c6de0beedaa8dc8506bd79c3085851d20 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 12:41:39 +0200 Subject: [PATCH 14/24] use two activity bars --- .../parts/activitybar/activitybarPart.ts | 104 +++++++++++------- 1 file changed, 63 insertions(+), 41 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index a31609f66af..dcda10a30f3 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -32,10 +32,10 @@ import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding'; export class ActivitybarPart extends Part implements IActivityService { public _serviceBrand: any; - private compositeSwitcherBar: ActionBar; + private viewletSwitcherBar: ActionBar; + private panelSwitcherBar: ActionBar; private activityActionItems: { [actionId: string]: IActionItem; }; private compositeIdToActions: { [compositeId: string]: ActivityAction; }; - private viewletActions: Action[]; private panelActions: Action[]; private showPanelAction: ShowPanelAction; @@ -76,7 +76,7 @@ export class ActivitybarPart extends Part implements IActivityService { } private onActivePanelChanged(panel: IPanel): void { - this.updateActionBar(); + this.updatePanelSwitcher(); this.onActiveCompositeChanged(panel); } @@ -87,7 +87,7 @@ export class ActivitybarPart extends Part implements IActivityService { } private onPanelClosed(panel: IPanel): void { - this.updateActionBar(); + this.updatePanelSwitcher(); this.onCompositeClosed(panel); } @@ -110,68 +110,90 @@ export class ActivitybarPart extends Part implements IActivityService { const $result = $('.content').appendTo($el); // Top Actionbar with action items for each viewlet action - this.createCompositeSwitcher($result.clone()); + this.createViewletSwitcher($result.clone()); + this.createPanelSwitcher($result.clone()); return $result; } - private createCompositeSwitcher(div: Builder): void { + private createViewletSwitcher(div: Builder): void { // Composite switcher is on top - this.compositeSwitcherBar = new ActionBar(div, { + this.viewletSwitcherBar = new ActionBar(div, { actionItemProvider: (action: Action) => this.activityActionItems[action.id], orientation: ActionsOrientation.VERTICAL, ariaLabel: nls.localize('activityBarAriaLabel', "Active View Switcher") }); - this.compositeSwitcherBar.getContainer().addClass('position-top'); + this.viewletSwitcherBar.getContainer().addClass('position-top'); // Build Viewlet Actions in correct order - const activeViewlet = this.viewletService.getActiveViewlet(); - const activePanel = this.panelService.getActivePanel(); const allViewlets = (Registry.as(ViewletExtensions.Viewlets)).getViewlets(); + const viewletActions = allViewlets.sort((v1, v2) => v1.order - v2.order).map(viewlet => this.toAction(viewlet)); + + this.viewletSwitcherBar.push(viewletActions, { label: true, icon: true }); + } + + private createPanelSwitcher(div: Builder): void { + + // Composite switcher is on top + this.panelSwitcherBar = new ActionBar(div, { + actionItemProvider: (action: Action) => this.activityActionItems[action.id], + orientation: ActionsOrientation.VERTICAL, + ariaLabel: nls.localize('activityBarPanelAriaLabel', "Active Panel Switcher") + }); + this.panelSwitcherBar.getContainer().addClass('position-bottom'); + + // Build Viewlet Actions in correct order + const allPanels = (Registry.as(PanelExtensions.Panels)).getPanels(); - const toAction = (composite: CompositeDescriptor) => { - const action = composite instanceof ViewletDescriptor ? this.instantiationService.createInstance(ViewletActivityAction, composite.id + '.activity-bar-action', composite) - : this.instantiationService.createInstance(PanelActivityAction, composite.id + '.activity-bar-action', composite); - - let keybinding: string = null; - const keys = this.keybindingService.lookupKeybindings(composite.id).map(k => this.keybindingService.getLabelFor(k)); - if (keys && keys.length) { - keybinding = keys[0]; - } - - this.activityActionItems[action.id] = new ActivityActionItem(action, composite.name, keybinding); - this.compositeIdToActions[composite.id] = action; - - // Mark active viewlet and panel action as active - if (activeViewlet && activeViewlet.getId() === composite.id || activePanel && activePanel.getId() === composite.id) { - action.activate(); - } - - return action; - }; - this.viewletActions = allViewlets.sort((v1, v2) => v1.order - v2.order).map(toAction); this.showPanelAction = this.instantiationService.createInstance(ShowPanelAction); this.activityActionItems[this.showPanelAction.id] = new ActivityActionItem(this.showPanelAction); - this.panelActions = allPanels.sort((p1, p2) => p1.order - p2.order).map(toAction); - + this.panelActions = allPanels.sort((p1, p2) => p1.order - p2.order).map(panel => this.toAction(panel)); // Add both viewlet and panel actions to the switcher - this.updateActionBar(); + this.updatePanelSwitcher(); } - private updateActionBar(): void { - this.compositeSwitcherBar.clear(); - const actions = this.partService.isPanelHidden() ? this.viewletActions.concat(this.showPanelAction) : this.viewletActions.concat(this.panelActions); + private updatePanelSwitcher(): void { + this.panelSwitcherBar.clear(); + const actions = this.partService.isPanelHidden() ? this.showPanelAction : this.panelActions; - this.compositeSwitcherBar.push(actions, { label: true, icon: true }); + this.panelSwitcherBar.push(actions, { label: true, icon: true }); } + private toAction(composite: CompositeDescriptor): ActivityAction { + const activeViewlet = this.viewletService.getActiveViewlet(); + const activePanel = this.panelService.getActivePanel(); + const action = composite instanceof ViewletDescriptor ? this.instantiationService.createInstance(ViewletActivityAction, composite.id + '.activity-bar-action', composite) + : this.instantiationService.createInstance(PanelActivityAction, composite.id + '.activity-bar-action', composite); + + let keybinding: string = null; + const keys = this.keybindingService.lookupKeybindings(composite.id).map(k => this.keybindingService.getLabelFor(k)); + if (keys && keys.length) { + keybinding = keys[0]; + } + + this.activityActionItems[action.id] = new ActivityActionItem(action, composite.name, keybinding); + this.compositeIdToActions[composite.id] = action; + + // Mark active viewlet and panel action as active + if (activeViewlet && activeViewlet.getId() === composite.id || activePanel && activePanel.getId() === composite.id) { + action.activate(); + } + + return action; + }; + public dispose(): void { - if (this.compositeSwitcherBar) { - this.compositeSwitcherBar.dispose(); - this.compositeSwitcherBar = null; + if (this.viewletSwitcherBar) { + this.viewletSwitcherBar.dispose(); + this.viewletSwitcherBar = null; + } + + if (this.panelSwitcherBar) { + this.panelSwitcherBar.dispose(); + this.panelSwitcherBar = null; } if (this.showPanelAction) { From 1bd80ec78868abe02774d64670c6eaafdcadba20 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 15:00:31 +0200 Subject: [PATCH 15/24] cleanup debug panel actions --- src/vs/code/electron-main/menus.ts | 2 +- .../parts/debug/browser/debugActions.ts | 46 ------------------- .../parts/debug/browser/debugViewlet.ts | 3 +- .../electron-browser/debug.contribution.ts | 24 +++++++++- 4 files changed, 24 insertions(+), 51 deletions(-) diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index f7775e1c8f1..5f0f989a68e 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -496,7 +496,7 @@ export class VSCodeMenu { const debug = this.createMenuItem(nls.localize({ key: 'miViewDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug"), 'workbench.view.debug'); const extensions = this.createMenuItem(nls.localize({ key: 'miViewExtensions', comment: ['&& denotes a mnemonic'] }, "E&&xtensions"), 'workbench.view.extensions'); const output = this.createMenuItem(nls.localize({ key: 'miToggleOutput', comment: ['&& denotes a mnemonic'] }, "&&Output"), 'workbench.action.output.toggleOutput'); - const debugConsole = this.createMenuItem(nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console"), 'workbench.debug.action.toggleRepl'); + const debugConsole = this.createMenuItem(nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console"), 'workbench.panel.repl'); const integratedTerminal = this.createMenuItem(nls.localize({ key: 'miToggleIntegratedTerminal', comment: ['&& denotes a mnemonic'] }, "&&Integrated Terminal"), 'workbench.action.terminal.toggleTerminal'); const problems = this.createMenuItem(nls.localize({ key: 'miMarker', comment: ['&& denotes a mnemonic'] }, "&&Problems"), 'workbench.actions.view.problems'); diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index f88ec15f033..f8640c7cf3f 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -19,7 +19,6 @@ import {IInstantiationService} from 'vs/platform/instantiation/common/instantiat import debug = require('vs/workbench/parts/debug/common/debug'); import model = require('vs/workbench/parts/debug/common/debugModel'); import {BreakpointWidget} from 'vs/workbench/parts/debug/browser/breakpointWidget'; -import {IPartService} from 'vs/workbench/services/part/common/partService'; import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService'; import IDebugService = debug.IDebugService; @@ -827,51 +826,6 @@ export class ClearReplAction extends AbstractDebugAction { } } -export class ToggleReplAction extends AbstractDebugAction { - static ID = 'workbench.debug.action.toggleRepl'; - static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugConsoleAction' }, 'Debug Console'); - - constructor(id: string, label: string, - @IDebugService debugService: IDebugService, - @IPartService private partService: IPartService, - @IPanelService private panelService: IPanelService, - @IKeybindingService keybindingService: IKeybindingService - ) { - super(id, label, 'debug-action toggle-repl', debugService, keybindingService); - this.enabled = this.debugService.state !== debug.State.Disabled; - this.registerListeners(); - } - - public run(): TPromise { - if (this.isReplVisible()) { - this.partService.setPanelHidden(true); - return TPromise.as(null); - } - - return this.panelService.openPanel(debug.REPL_ID, true); - } - - private registerListeners(): void { - this.toDispose.push(this.debugService.getModel().onDidChangeReplElements(() => { - if (!this.isReplVisible()) { - this.class = 'debug-action toggle-repl notification'; - this.tooltip = nls.localize('unreadOutput', "New Output in Debug Console"); - } - })); - this.toDispose.push(this.panelService.onDidPanelOpen(panel => { - if (panel.getId() === debug.REPL_ID) { - this.class = 'debug-action toggle-repl'; - this.tooltip = ToggleReplAction.LABEL; - } - })); - } - - private isReplVisible(): boolean { - const panel = this.panelService.getActivePanel(); - return panel && panel.getId() === debug.REPL_ID; - } -} - export class FocusReplAction extends Action { static ID = 'workbench.debug.action.focusRepl'; diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index 50e3595eb4e..ee24e4100a6 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -126,8 +126,7 @@ export class DebugViewlet extends Viewlet { this.actions = [ this.instantiationService.createInstance(debugactions.StartAction, debugactions.StartAction.ID, debugactions.StartAction.LABEL), this.instantiationService.createInstance(debugactions.SelectConfigAction, debugactions.SelectConfigAction.ID, debugactions.SelectConfigAction.LABEL), - this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL), - this.instantiationService.createInstance(debugactions.ToggleReplAction, debugactions.ToggleReplAction.ID, debugactions.ToggleReplAction.LABEL) + this.instantiationService.createInstance(debugactions.ConfigureAction, debugactions.ConfigureAction.ID, debugactions.ConfigureAction.LABEL) ]; this.actions.forEach(a => { diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index d0d12a0a847..4d3eb018173 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -23,9 +23,11 @@ import {VariablesView, WatchExpressionsView, CallStackView, BreakpointsView} fro import wbext = require('vs/workbench/common/contributions'); import {EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor'; import * as debug from 'vs/workbench/parts/debug/common/debug'; +import {IPartService} from 'vs/workbench/services/part/common/partService'; +import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; import {DebugEditorModelManager} from 'vs/workbench/parts/debug/browser/debugEditorModelManager'; import {StepOverAction, ClearReplAction, FocusReplAction, StepIntoAction, StepOutAction, StartAction, StepBackAction, RestartAction, ContinueAction, StopAction, DisconnectAction, PauseAction, AddFunctionBreakpointAction, - ConfigureAction, ToggleReplAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction} from 'vs/workbench/parts/debug/browser/debugActions'; + ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction} from 'vs/workbench/parts/debug/browser/debugActions'; import debugwidget = require('vs/workbench/parts/debug/browser/debugActionsWidget'); import service = require('vs/workbench/parts/debug/electron-browser/debugService'); import {DebugErrorEditorInput} from 'vs/workbench/parts/debug/browser/debugEditorInputs'; @@ -51,6 +53,21 @@ class OpenDebugViewletAction extends viewlet.ToggleViewletAction { } } +class OpenDebugPanelAction extends panel.TogglePanelAction { + public static ID = debug.REPL_ID; + public static LABEL = nls.localize('toggleDebugPanel', "Debug Console"); + + constructor( + id: string, + label: string, + @IPanelService panelService: IPanelService, + @IWorkbenchEditorService editorService: IWorkbenchEditorService, + @IPartService partService: IPartService + ) { + super(id, label, debug.REPL_ID, panelService, partService, editorService); + } +} + // register viewlet (platform.Registry.as(viewlet.Extensions.Viewlets)).registerViewlet(new viewlet.ViewletDescriptor( 'vs/workbench/parts/debug/browser/debugViewlet', @@ -64,6 +81,9 @@ class OpenDebugViewletAction extends viewlet.ToggleViewletAction { const openViewletKb: IKeybindings = { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_D }; +const openPanelKb: IKeybindings = { + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y +}; // register repl panel (platform.Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor( @@ -83,6 +103,7 @@ DebugViewRegistry.registerDebugView(BreakpointsView, 40); // register action to open viewlet const registry = (platform.Registry.as(wbaregistry.Extensions.WorkbenchActions)); +registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDebugPanelAction, OpenDebugPanelAction.ID, OpenDebugPanelAction.LABEL, openPanelKb), 'View: Debug Console', nls.localize('view', "View")); registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDebugViewletAction, OpenDebugViewletAction.ID, OpenDebugViewletAction.LABEL, openViewletKb), 'View: Show Debug', nls.localize('view', "View")); (platform.Registry.as(wbext.Extensions.Workbench)).registerWorkbenchContribution(DebugEditorModelManager); @@ -101,7 +122,6 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(DisconnectAction, Disc registry.registerWorkbenchAction(new SyncActionDescriptor(ContinueAction, ContinueAction.ID, ContinueAction.LABEL, { primary: KeyCode.F5 }, debug.CONTEXT_IN_DEBUG_MODE), 'Debug: Continue', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(PauseAction, PauseAction.ID, PauseAction.LABEL), 'Debug: Pause', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL), 'Debug: Open launch.json', debugCategory); -registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y, }), 'Debug: Debug Console', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(AddFunctionBreakpointAction, AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL), 'Debug: Add Function Breakpoint', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(ReapplyBreakpointsAction, ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(RunAction, RunAction.ID, RunAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.F5 }, debug.CONTEXT_NOT_IN_DEBUG_MODE), 'Debug: Start Without Debugging', debugCategory); From 0bf3f435f930cee385407850ceb1dcadd49fd75f Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 15:25:34 +0200 Subject: [PATCH 16/24] markers: cleanup show panel action --- .../workbench/parts/markers/browser/markersPanelActions.ts | 2 -- .../parts/markers/browser/markersWorkbenchContributions.ts | 7 ++----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts index fa2ba4416e0..28f7f708e8d 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts +++ b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts @@ -26,8 +26,6 @@ import Tree = require('vs/base/parts/tree/browser/tree'); export class ToggleMarkersPanelAction extends TogglePanelAction { - public static ID:string = 'workbench.actions.view.problems'; - constructor(id: string, label: string, @IPartService partService: IPartService, @IPanelService panelService: IPanelService, diff --git a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts index f0c71e08d01..2274900e0d4 100644 --- a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts +++ b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts @@ -40,11 +40,8 @@ export function registerContributions(): void { let registry = platform.Registry.as(ActionExtensions.WorkbenchActions); - registry.registerWorkbenchAction(new SyncActionDescriptor(markersPanelActions.ToggleMarkersPanelAction, markersPanelActions.ToggleMarkersPanelAction.ID, Messages.MARKERS_PANEL_TOGGLE_LABEL, { - primary: null, - win: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M }, - linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M }, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M } + registry.registerWorkbenchAction(new SyncActionDescriptor(markersPanelActions.ToggleMarkersPanelAction, Constants.MARKERS_PANEL_ID, Messages.MARKERS_PANEL_TOGGLE_LABEL, { + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M }), 'View: ' + Messages.MARKERS_PANEL_TOGGLE_LABEL, Messages.MARKERS_PANEL_VIEW_CATEGORY); // Retaining old action to show errors and warnings, so that custom bindings to this action for existing users works. From f08238c089d02e66ac7af28178a19fc5f3fc79cc Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 15:31:05 +0200 Subject: [PATCH 17/24] panel: show shortcuts on hover in activity bar --- src/vs/workbench/parts/output/browser/outputActions.ts | 2 +- .../parts/terminal/electron-browser/terminalActions.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/output/browser/outputActions.ts b/src/vs/workbench/parts/output/browser/outputActions.ts index e78b22885f5..9db006d569a 100644 --- a/src/vs/workbench/parts/output/browser/outputActions.ts +++ b/src/vs/workbench/parts/output/browser/outputActions.ts @@ -15,7 +15,7 @@ import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; export class ToggleOutputAction extends Action { - public static ID = 'workbench.action.output.toggleOutput'; + public static ID = OUTPUT_PANEL_ID; public static LABEL = nls.localize('toggleOutput', "Toggle Output"); constructor( diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index 05068fbb4d7..1fff93ec267 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -8,13 +8,13 @@ import os = require('os'); import { Action, IAction } from 'vs/base/common/actions'; import { EndOfLinePreference } from 'vs/editor/common/editorCommon'; import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService'; -import { ITerminalService } from 'vs/workbench/parts/terminal/electron-browser/terminal'; +import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/electron-browser/terminal'; import { SelectActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { TPromise } from 'vs/base/common/winjs.base'; export class ToggleTerminalAction extends Action { - public static ID = 'workbench.action.terminal.toggleTerminal'; + public static ID = TERMINAL_PANEL_ID; public static LABEL = nls.localize('workbench.action.terminal.toggleTerminal', "Toggle Integrated Terminal"); constructor( From cff0fb9e4ae64ea30f2562aa244be1389dd245ca Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 15:50:30 +0200 Subject: [PATCH 18/24] reuse togglePanel action, different icon direction --- .../parts/activitybar/activitybarPart.ts | 18 +++--------------- .../browser/parts/activitybar/media/panel.svg | 2 +- .../workbench/browser/parts/panel/panelPart.ts | 7 ++++--- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index dcda10a30f3..29c3c14be43 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -20,6 +20,7 @@ import {CompositeDescriptor, Composite} from 'vs/workbench/browser/composite'; import {Panel, PanelRegistry, Extensions as PanelExtensions} from 'vs/workbench/browser/panel'; import {Part} from 'vs/workbench/browser/part'; import {ActivityAction, ActivityActionItem} from 'vs/workbench/browser/parts/activitybar/activityAction'; +import {TogglePanelAction} from 'vs/workbench/browser/parts/panel/panelPart'; import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService'; import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; import {IActivityService, IBadge} from 'vs/workbench/services/activity/common/activityService'; @@ -37,7 +38,7 @@ export class ActivitybarPart extends Part implements IActivityService { private activityActionItems: { [actionId: string]: IActionItem; }; private compositeIdToActions: { [compositeId: string]: ActivityAction; }; private panelActions: Action[]; - private showPanelAction: ShowPanelAction; + private showPanelAction: TogglePanelAction; constructor( id: string, @@ -147,7 +148,7 @@ export class ActivitybarPart extends Part implements IActivityService { const allPanels = (Registry.as(PanelExtensions.Panels)).getPanels(); - this.showPanelAction = this.instantiationService.createInstance(ShowPanelAction); + this.showPanelAction = this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, TogglePanelAction.LABEL); this.activityActionItems[this.showPanelAction.id] = new ActivityActionItem(this.showPanelAction); this.panelActions = allPanels.sort((p1, p2) => p1.order - p2.order).map(panel => this.toAction(panel)); @@ -270,16 +271,3 @@ class PanelActivityAction extends CompositeActivityAction { } } } - -class ShowPanelAction extends ActivityAction { - private static ID = 'workbench.action.panel.show'; - - constructor(@IPartService private partService: IPartService) { - super(ShowPanelAction.ID, nls.localize('showPanel', "Show Panel"), 'panel'); - } - - public run(): TPromise { - this.partService.setPanelHidden(false); - return TPromise.as(null); - } -} diff --git a/src/vs/workbench/browser/parts/activitybar/media/panel.svg b/src/vs/workbench/browser/parts/activitybar/media/panel.svg index 88c05455cb3..906bb60cb40 100755 --- a/src/vs/workbench/browser/parts/activitybar/media/panel.svg +++ b/src/vs/workbench/browser/parts/activitybar/media/panel.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index ea9b9056795..9ce3bd18ffb 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -11,6 +11,7 @@ import {Action, IAction} from 'vs/base/common/actions'; import Event from 'vs/base/common/event'; import {Builder} from 'vs/base/browser/builder'; import {Registry} from 'vs/platform/platform'; +import {ActivityAction} from 'vs/workbench/browser/parts/activitybar/activityAction'; import {Scope} from 'vs/workbench/browser/actionBarRegistry'; import {SyncActionDescriptor} from 'vs/platform/actions/common/actions'; import {IWorkbenchActionRegistry, Extensions as WorkbenchExtensions} from 'vs/workbench/common/actionRegistry'; @@ -127,16 +128,16 @@ class ClosePanelAction extends Action { } } -class TogglePanelAction extends Action { +export class TogglePanelAction extends ActivityAction { static ID = 'workbench.action.togglePanel'; - static LABEL = nls.localize('togglePanel', "Toggle Panel Visibility"); + static LABEL = nls.localize('togglePanel', "Toggle Panel"); constructor( id: string, name: string, @IPartService private partService: IPartService ) { - super(id, name, null); + super(id, name, 'panel'); } public run(): TPromise { From cc95494567cfededb9bd28ebf035fd5c384b3a8d Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 15:59:45 +0200 Subject: [PATCH 19/24] always show toggle panel action in activity bar --- .../workbench/browser/parts/activitybar/activitybarPart.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 29c3c14be43..470ae13016b 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -37,7 +37,7 @@ export class ActivitybarPart extends Part implements IActivityService { private panelSwitcherBar: ActionBar; private activityActionItems: { [actionId: string]: IActionItem; }; private compositeIdToActions: { [compositeId: string]: ActivityAction; }; - private panelActions: Action[]; + private panelActions: ActivityAction[]; private showPanelAction: TogglePanelAction; constructor( @@ -158,7 +158,10 @@ export class ActivitybarPart extends Part implements IActivityService { private updatePanelSwitcher(): void { this.panelSwitcherBar.clear(); - const actions = this.partService.isPanelHidden() ? this.showPanelAction : this.panelActions; + const actions:ActivityAction[] = [this.showPanelAction]; + if (!this.partService.isPanelHidden()) { + actions.push(...this.panelActions); + } this.panelSwitcherBar.push(actions, { label: true, icon: true }); } From 16c03c2cce11714120b89321b025c1defb8bc0da Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 16:05:43 +0200 Subject: [PATCH 20/24] activity bar: no need for code reuse between panel and viewlet activity action --- .../parts/activitybar/activitybarPart.ts | 59 +++++++------------ 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 470ae13016b..8af41a647d2 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -16,8 +16,8 @@ import {Registry} from 'vs/platform/platform'; import {IComposite} from 'vs/workbench/common/composite'; import {IPanel} from 'vs/workbench/common/panel'; import {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions, Viewlet} from 'vs/workbench/browser/viewlet'; -import {CompositeDescriptor, Composite} from 'vs/workbench/browser/composite'; -import {Panel, PanelRegistry, Extensions as PanelExtensions} from 'vs/workbench/browser/panel'; +import {CompositeDescriptor} from 'vs/workbench/browser/composite'; +import {Panel, PanelRegistry, Extensions as PanelExtensions, PanelDescriptor} from 'vs/workbench/browser/panel'; import {Part} from 'vs/workbench/browser/part'; import {ActivityAction, ActivityActionItem} from 'vs/workbench/browser/parts/activitybar/activityAction'; import {TogglePanelAction} from 'vs/workbench/browser/parts/panel/panelPart'; @@ -208,69 +208,52 @@ export class ActivitybarPart extends Part implements IActivityService { } } -abstract class CompositeActivityAction extends ActivityAction { +class ViewletActivityAction extends ActivityAction { private static preventDoubleClickDelay = 300; private lastRun: number = 0; - protected composite: CompositeDescriptor; - constructor( - id: string, composite: CompositeDescriptor, - @IViewletService protected viewletService: IViewletService, - @IPanelService protected panelService: IPanelService, - @IPartService protected partService: IPartService + id: string, private viewlet: ViewletDescriptor, + @IViewletService private viewletService: IViewletService, + @IPartService private partService: IPartService ) { - super(id, composite.name, composite.cssClass); - - this.composite = composite; + super(id, viewlet.name, viewlet.cssClass); } public run(): TPromise { // prevent accident trigger on a doubleclick (to help nervous people) const now = Date.now(); - if (now - this.lastRun < CompositeActivityAction.preventDoubleClickDelay) { + if (now - this.lastRun < ViewletActivityAction.preventDoubleClickDelay) { return TPromise.as(true); } this.lastRun = now; - this.toggleComposite(); - - return TPromise.as(true); - } - - protected abstract toggleComposite(): void; -} - -class ViewletActivityAction extends CompositeActivityAction { - - protected toggleComposite(): void { const sideBarHidden = this.partService.isSideBarHidden(); const activeViewlet = this.viewletService.getActiveViewlet(); // Hide sidebar if selected viewlet already visible - if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.composite.id) { + if (!sideBarHidden && activeViewlet && activeViewlet.getId() === this.viewlet.id) { this.partService.setSideBarHidden(true); } else { - this.viewletService.openViewlet(this.composite.id, true).done(null, errors.onUnexpectedError); + this.viewletService.openViewlet(this.viewlet.id, true).done(null, errors.onUnexpectedError); this.activate(); } + + return TPromise.as(true); } } -class PanelActivityAction extends CompositeActivityAction { +class PanelActivityAction extends ActivityAction { - protected toggleComposite(): void { + constructor( + id: string, private panel: PanelDescriptor, + @IPanelService private panelService: IPanelService + ) { + super(id, panel.name, panel.cssClass); + } - const panelHidden = this.partService.isPanelHidden(); - const activePanel = this.panelService.getActivePanel(); - - // Hide panel if selected panel already visible - if (!panelHidden && activePanel && activePanel.getId() === this.composite.id) { - this.partService.setPanelHidden(true); - } else { - this.panelService.openPanel(this.composite.id, true).done(null, errors.onUnexpectedError); - this.activate(); - } + public run(): TPromise { + return this.panelService.openPanel(this.panel.id, true).then(() => this.activate()); } } From e3e7cca3a6c5a54f2b4f9be34a8204e7cfe2ffa7 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 16:11:45 +0200 Subject: [PATCH 21/24] activitybar: keybinding label for toggle panel --- .../parts/activitybar/activitybarPart.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 8af41a647d2..25fbcfe09be 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -149,7 +149,7 @@ export class ActivitybarPart extends Part implements IActivityService { const allPanels = (Registry.as(PanelExtensions.Panels)).getPanels(); this.showPanelAction = this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, TogglePanelAction.LABEL); - this.activityActionItems[this.showPanelAction.id] = new ActivityActionItem(this.showPanelAction); + this.activityActionItems[this.showPanelAction.id] = new ActivityActionItem(this.showPanelAction, TogglePanelAction.LABEL, this.getKeybindingLabel(TogglePanelAction.ID)); this.panelActions = allPanels.sort((p1, p2) => p1.order - p2.order).map(panel => this.toAction(panel)); // Add both viewlet and panel actions to the switcher @@ -172,13 +172,7 @@ export class ActivitybarPart extends Part implements IActivityService { const action = composite instanceof ViewletDescriptor ? this.instantiationService.createInstance(ViewletActivityAction, composite.id + '.activity-bar-action', composite) : this.instantiationService.createInstance(PanelActivityAction, composite.id + '.activity-bar-action', composite); - let keybinding: string = null; - const keys = this.keybindingService.lookupKeybindings(composite.id).map(k => this.keybindingService.getLabelFor(k)); - if (keys && keys.length) { - keybinding = keys[0]; - } - - this.activityActionItems[action.id] = new ActivityActionItem(action, composite.name, keybinding); + this.activityActionItems[action.id] = new ActivityActionItem(action, composite.name, this.getKeybindingLabel(composite.id)); this.compositeIdToActions[composite.id] = action; // Mark active viewlet and panel action as active @@ -189,6 +183,15 @@ export class ActivitybarPart extends Part implements IActivityService { return action; }; + private getKeybindingLabel(id: string): string { + const keys = this.keybindingService.lookupKeybindings(id).map(k => this.keybindingService.getLabelFor(k)); + if (keys && keys.length) { + return keys[0]; + } + + return null; + } + public dispose(): void { if (this.viewletSwitcherBar) { this.viewletSwitcherBar.dispose(); From c8e7f34ec86a0b86cac2d8acc3145d3e34dec5aa Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 16:56:45 +0200 Subject: [PATCH 22/24] do not change ids of actions - can break people --- src/vs/code/electron-main/menus.ts | 2 +- .../parts/debug/electron-browser/debug.contribution.ts | 2 +- src/vs/workbench/parts/markers/browser/markersPanelActions.ts | 2 ++ .../parts/markers/browser/markersWorkbenchContributions.ts | 2 +- src/vs/workbench/parts/output/browser/outputActions.ts | 2 +- .../parts/terminal/electron-browser/terminalActions.ts | 4 ++-- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index 5f0f989a68e..f7775e1c8f1 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -496,7 +496,7 @@ export class VSCodeMenu { const debug = this.createMenuItem(nls.localize({ key: 'miViewDebug', comment: ['&& denotes a mnemonic'] }, "&&Debug"), 'workbench.view.debug'); const extensions = this.createMenuItem(nls.localize({ key: 'miViewExtensions', comment: ['&& denotes a mnemonic'] }, "E&&xtensions"), 'workbench.view.extensions'); const output = this.createMenuItem(nls.localize({ key: 'miToggleOutput', comment: ['&& denotes a mnemonic'] }, "&&Output"), 'workbench.action.output.toggleOutput'); - const debugConsole = this.createMenuItem(nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console"), 'workbench.panel.repl'); + const debugConsole = this.createMenuItem(nls.localize({ key: 'miToggleDebugConsole', comment: ['&& denotes a mnemonic'] }, "De&&bug Console"), 'workbench.debug.action.toggleRepl'); const integratedTerminal = this.createMenuItem(nls.localize({ key: 'miToggleIntegratedTerminal', comment: ['&& denotes a mnemonic'] }, "&&Integrated Terminal"), 'workbench.action.terminal.toggleTerminal'); const problems = this.createMenuItem(nls.localize({ key: 'miMarker', comment: ['&& denotes a mnemonic'] }, "&&Problems"), 'workbench.actions.view.problems'); diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index 4d3eb018173..bf430840d75 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -54,7 +54,7 @@ class OpenDebugViewletAction extends viewlet.ToggleViewletAction { } class OpenDebugPanelAction extends panel.TogglePanelAction { - public static ID = debug.REPL_ID; + public static ID = 'workbench.debug.action.toggleRepl'; public static LABEL = nls.localize('toggleDebugPanel', "Debug Console"); constructor( diff --git a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts index 28f7f708e8d..514fb267a9d 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts +++ b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts @@ -26,6 +26,8 @@ import Tree = require('vs/base/parts/tree/browser/tree'); export class ToggleMarkersPanelAction extends TogglePanelAction { + public static ID = 'workbench.actions.view.problems'; + constructor(id: string, label: string, @IPartService partService: IPartService, @IPanelService panelService: IPanelService, diff --git a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts index 2274900e0d4..1c935d0929d 100644 --- a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts +++ b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts @@ -40,7 +40,7 @@ export function registerContributions(): void { let registry = platform.Registry.as(ActionExtensions.WorkbenchActions); - registry.registerWorkbenchAction(new SyncActionDescriptor(markersPanelActions.ToggleMarkersPanelAction, Constants.MARKERS_PANEL_ID, Messages.MARKERS_PANEL_TOGGLE_LABEL, { + registry.registerWorkbenchAction(new SyncActionDescriptor(markersPanelActions.ToggleMarkersPanelAction, markersPanelActions.ToggleMarkersPanelAction.ID, Messages.MARKERS_PANEL_TOGGLE_LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M }), 'View: ' + Messages.MARKERS_PANEL_TOGGLE_LABEL, Messages.MARKERS_PANEL_VIEW_CATEGORY); diff --git a/src/vs/workbench/parts/output/browser/outputActions.ts b/src/vs/workbench/parts/output/browser/outputActions.ts index 9db006d569a..e78b22885f5 100644 --- a/src/vs/workbench/parts/output/browser/outputActions.ts +++ b/src/vs/workbench/parts/output/browser/outputActions.ts @@ -15,7 +15,7 @@ import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; export class ToggleOutputAction extends Action { - public static ID = OUTPUT_PANEL_ID; + public static ID = 'workbench.action.output.toggleOutput'; public static LABEL = nls.localize('toggleOutput', "Toggle Output"); constructor( diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index 1fff93ec267..05068fbb4d7 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -8,13 +8,13 @@ import os = require('os'); import { Action, IAction } from 'vs/base/common/actions'; import { EndOfLinePreference } from 'vs/editor/common/editorCommon'; import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService'; -import { ITerminalService, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/electron-browser/terminal'; +import { ITerminalService } from 'vs/workbench/parts/terminal/electron-browser/terminal'; import { SelectActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { TPromise } from 'vs/base/common/winjs.base'; export class ToggleTerminalAction extends Action { - public static ID = TERMINAL_PANEL_ID; + public static ID = 'workbench.action.terminal.toggleTerminal'; public static LABEL = nls.localize('workbench.action.terminal.toggleTerminal', "Toggle Integrated Terminal"); constructor( From 09601caa09e1a6272d78d1024f8107124ee710b1 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 17:35:41 +0200 Subject: [PATCH 23/24] activitybar: use blue as the default badge background color --- .../browser/parts/activitybar/media/activityaction.css | 1 + .../extensions/electron-browser/media/extensionsViewlet.css | 4 ---- .../workbench/parts/files/browser/media/explorerviewlet.css | 4 ---- src/vs/workbench/parts/git/browser/media/git.contribution.css | 4 ---- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index 09b21680eda..7fd426208ac 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -93,6 +93,7 @@ border-radius: 20px; text-align: center; color: white; + background-color: #007ACC; } .monaco-workbench > .activitybar > .content .monaco-action-bar .action-item .action-label.active, diff --git a/src/vs/workbench/parts/extensions/electron-browser/media/extensionsViewlet.css b/src/vs/workbench/parts/extensions/electron-browser/media/extensionsViewlet.css index 96b2a7067be..bf596ce7a66 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/media/extensionsViewlet.css +++ b/src/vs/workbench/parts/extensions/electron-browser/media/extensionsViewlet.css @@ -129,10 +129,6 @@ text-overflow: ellipsis; } -.extensions-badge > .badge-content { - background-color: #007ACC; -} - .extensions-badge.progress-badge > .badge-content { background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgdmlld0JveD0iMiAyIDE0IDE0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDIgMiAxNCAxNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTkgMTZjLTMuODYgMC03LTMuMTQtNy03czMuMTQtNyA3LTdjMy44NTkgMCA3IDMuMTQxIDcgN3MtMy4xNDEgNy03IDd6bTAtMTIuNmMtMy4wODggMC01LjYgMi41MTMtNS42IDUuNnMyLjUxMiA1LjYgNS42IDUuNiA1LjYtMi41MTIgNS42LTUuNi0yLjUxMi01LjYtNS42LTUuNnptMy44NiA3LjFsLTMuMTYtMS44OTZ2LTMuODA0aC0xLjR2NC41OTZsMy44NCAyLjMwNS43Mi0xLjIwMXoiLz48L3N2Zz4="); background-position: center center; diff --git a/src/vs/workbench/parts/files/browser/media/explorerviewlet.css b/src/vs/workbench/parts/files/browser/media/explorerviewlet.css index 1ebd28e3ec8..4127709e7d1 100644 --- a/src/vs/workbench/parts/files/browser/media/explorerviewlet.css +++ b/src/vs/workbench/parts/files/browser/media/explorerviewlet.css @@ -104,10 +104,6 @@ height: 20px; } -.explorer-viewlet-label > .badge-content { - background-color: #007ACC; -} - .explorer-viewlet .explorer-open-editors .monaco-tree .monaco-tree-row .editor-group { font-size: 11px; font-weight: bold; diff --git a/src/vs/workbench/parts/git/browser/media/git.contribution.css b/src/vs/workbench/parts/git/browser/media/git.contribution.css index d2e76eb5d36..e8c1731508a 100644 --- a/src/vs/workbench/parts/git/browser/media/git.contribution.css +++ b/src/vs/workbench/parts/git/browser/media/git.contribution.css @@ -31,12 +31,8 @@ } /* Git viewlet label */ -.git-viewlet-label > .badge-content, .git-viewlet-label-progress > .badge-content { - background-color: #007ACC; -} .git-viewlet-label-progress > .badge-content { - background-color: #007ACC; background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgdmlld0JveD0iMiAyIDE0IDE0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDIgMiAxNCAxNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTkgMTZjLTMuODYgMC03LTMuMTQtNy03czMuMTQtNyA3LTdjMy44NTkgMCA3IDMuMTQxIDcgN3MtMy4xNDEgNy03IDd6bTAtMTIuNmMtMy4wODggMC01LjYgMi41MTMtNS42IDUuNnMyLjUxMiA1LjYgNS42IDUuNiA1LjYtMi41MTIgNS42LTUuNi0yLjUxMi01LjYtNS42LTUuNnptMy44NiA3LjFsLTMuMTYtMS44OTZ2LTMuODA0aC0xLjR2NC41OTZsMy44NCAyLjMwNS43Mi0xLjIwMXoiLz48L3N2Zz4="); background-position: center center; background-repeat: no-repeat; From 93e53de0f9e5e3bb5dcaa8fbc9e822b9d52ed89f Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 23 Sep 2016 17:55:39 +0200 Subject: [PATCH 24/24] show badge for markers --- .../parts/activitybar/activitybarPart.ts | 31 +++++++++--- .../browser/markersWorkbenchContributions.ts | 47 ++++++++++++++++++- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 25fbcfe09be..6a902ebf8c5 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -38,7 +38,7 @@ export class ActivitybarPart extends Part implements IActivityService { private activityActionItems: { [actionId: string]: IActionItem; }; private compositeIdToActions: { [compositeId: string]: ActivityAction; }; private panelActions: ActivityAction[]; - private showPanelAction: TogglePanelAction; + private togglePanelAction: TogglePanelAction; constructor( id: string, @@ -95,6 +95,12 @@ export class ActivitybarPart extends Part implements IActivityService { public showActivity(compositeId: string, badge: IBadge, clazz?: string): void { const action = this.compositeIdToActions[compositeId]; if (action) { + if (action instanceof PanelActivityAction && this.partService.isPanelHidden()) { + // while the panel badges are hidden we show the badge on the parent action which is visible + this.togglePanelAction.setBadge(badge); + return; + } + action.setBadge(badge); if (clazz) { action.class = clazz; @@ -148,8 +154,8 @@ export class ActivitybarPart extends Part implements IActivityService { const allPanels = (Registry.as(PanelExtensions.Panels)).getPanels(); - this.showPanelAction = this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, TogglePanelAction.LABEL); - this.activityActionItems[this.showPanelAction.id] = new ActivityActionItem(this.showPanelAction, TogglePanelAction.LABEL, this.getKeybindingLabel(TogglePanelAction.ID)); + this.togglePanelAction = this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, TogglePanelAction.LABEL); + this.activityActionItems[this.togglePanelAction.id] = new ActivityActionItem(this.togglePanelAction, TogglePanelAction.LABEL, this.getKeybindingLabel(TogglePanelAction.ID)); this.panelActions = allPanels.sort((p1, p2) => p1.order - p2.order).map(panel => this.toAction(panel)); // Add both viewlet and panel actions to the switcher @@ -158,12 +164,25 @@ export class ActivitybarPart extends Part implements IActivityService { private updatePanelSwitcher(): void { this.panelSwitcherBar.clear(); - const actions:ActivityAction[] = [this.showPanelAction]; + const actions: ActivityAction[] = [this.togglePanelAction]; if (!this.partService.isPanelHidden()) { actions.push(...this.panelActions); } this.panelSwitcherBar.push(actions, { label: true, icon: true }); + + // TODO@Isidor fix this aweful badge(r) hacks + if (!this.partService.isPanelHidden()) { + if (!this.panelActions[0].getBadge()) { + this.panelActions[0].setBadge(this.togglePanelAction.getBadge()); + } else { + this.panelActions[0].setBadge(this.panelActions[0].getBadge()); + } + this.togglePanelAction.setBadge(null); + } else { + this.togglePanelAction.setBadge(this.panelActions[0].getBadge()); + this.panelActions[0].setBadge(null); + } } private toAction(composite: CompositeDescriptor): ActivityAction { @@ -203,8 +222,8 @@ export class ActivitybarPart extends Part implements IActivityService { this.panelSwitcherBar = null; } - if (this.showPanelAction) { - this.showPanelAction.dispose(); + if (this.togglePanelAction) { + this.togglePanelAction.dispose(); } super.dispose(); diff --git a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts index 1c935d0929d..aa3095c3494 100644 --- a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts +++ b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts @@ -3,16 +3,56 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import {localize} from 'vs/nls'; +import lifecycle = require('vs/base/common/lifecycle'); import Messages from 'vs/workbench/parts/markers/common/messages'; import Constants from 'vs/workbench/parts/markers/common/constants'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; +import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import * as platform from 'vs/platform/platform'; +import { IMarkerService } from 'vs/platform/markers/common/markers'; +import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activityService'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actionRegistry'; import * as panel from 'vs/workbench/browser/panel'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import * as markersPanelActions from 'vs/workbench/parts/markers/browser/markersPanelActions'; +class StatusUpdater implements IWorkbenchContribution +{ + static ID = 'vs.markers.statusUpdater'; + + private toDispose: lifecycle.IDisposable[]; + + constructor( + @IMarkerService private markerService: IMarkerService, + @IActivityService private activityService: IActivityService + ) { + + this.toDispose = []; + this.toDispose.push(markerService.onMarkerChanged(() => this.updateActivityBadge()); + } + + private updateActivityBadge(): void { + const stats = this.markerService.getStatistics(); + const problemCount = stats.errors + stats.warnings + stats.infos + stats.unknowns; + if (problemCount > 0) { + const badge = new NumberBadge(problemCount, n => localize('errorsAndWarnings', '{0} Errors and Warnings', n)); + this.activityService.showActivity(Constants.MARKERS_PANEL_ID, badge); + } else { + this.activityService.showActivity(Constants.MARKERS_PANEL_ID, null); + } + } + + public getId(): string { + return StatusUpdater.ID; + } + + public dispose(): void { + this.toDispose = lifecycle.dispose(this.toDispose); + } +} + export function registerContributions(): void { (platform.Registry.as(Extensions.Configuration)).registerConfiguration({ @@ -46,4 +86,9 @@ export function registerContributions(): void { // Retaining old action to show errors and warnings, so that custom bindings to this action for existing users works. registry.registerWorkbenchAction(new SyncActionDescriptor(markersPanelActions.ToggleErrorsAndWarningsAction, markersPanelActions.ToggleErrorsAndWarningsAction.ID, ''), Messages.SHOW_ERRORS_WARNINGS_ACTION_LABEL); -} \ No newline at end of file + + // Register StatusUpdater + (platform.Registry.as(WorkbenchExtensions.Workbench)).registerWorkbenchContribution( + StatusUpdater + ); +}