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; diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index e5c6aa533e6..6a902ebf8c5 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -12,13 +12,17 @@ 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 {ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions} from 'vs/workbench/browser/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} 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'; 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'; @@ -30,23 +34,27 @@ import {IKeybindingService} from 'vs/platform/keybinding/common/keybinding'; export class ActivitybarPart extends Part implements IActivityService { public _serviceBrand: any; private viewletSwitcherBar: ActionBar; - private globalToolBar: ToolBar; + private panelSwitcherBar: ActionBar; private activityActionItems: { [actionId: string]: IActionItem; }; - private viewletIdToActions: { [viewletId: string]: ActivityAction; }; + private compositeIdToActions: { [compositeId: string]: ActivityAction; }; + private panelActions: ActivityAction[]; + private togglePanelAction: TogglePanelAction; constructor( id: string, @IViewletService private viewletService: IViewletService, + @IPanelService private panelService: IPanelService, @IMessageService private messageService: IMessageService, @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); this.activityActionItems = {}; - this.viewletIdToActions = {}; + this.compositeIdToActions = {}; this.registerListeners(); } @@ -54,34 +62,45 @@ 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.viewletIdToActions[viewlet.getId()]) { - this.viewletIdToActions[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(); - } - } + private onActiveCompositeChanged(composite: IComposite): void { + if (this.compositeIdToActions[composite.getId()]) { + this.compositeIdToActions[composite.getId()].activate(); } } - private onViewletClosed(viewlet: IViewlet): void { - if (this.viewletIdToActions[viewlet.getId()]) { - this.viewletIdToActions[viewlet.getId()].deactivate(); + private onActivePanelChanged(panel: IPanel): void { + this.updatePanelSwitcher(); + this.onActiveCompositeChanged(panel); + } + + private onCompositeClosed(composite: IComposite): void { + if (this.compositeIdToActions[composite.getId()]) { + this.compositeIdToActions[composite.getId()].deactivate(); } } - public showActivity(viewletId: string, badge: IBadge, clazz?: string): void { - let action = this.viewletIdToActions[viewletId]; + private onPanelClosed(panel: IPanel): void { + this.updatePanelSwitcher(); + this.onCompositeClosed(panel); + } + + 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; @@ -89,23 +108,24 @@ 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.createPanelSwitcher($result.clone()); return $result; } private createViewletSwitcher(div: Builder): void { - // Viewlet switcher is on top + // Composite switcher is on top this.viewletSwitcherBar = new ActionBar(div, { actionItemProvider: (action: Action) => this.activityActionItems[action.id], orientation: ActionsOrientation.VERTICAL, @@ -114,37 +134,81 @@ export class ActivitybarPart extends Part implements IActivityService { this.viewletSwitcherBar.getContainer().addClass('position-top'); // Build Viewlet Actions in correct order + 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(); + + 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 + this.updatePanelSwitcher(); + } + + private updatePanelSwitcher(): void { + this.panelSwitcherBar.clear(); + 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 { const activeViewlet = this.viewletService.getActiveViewlet(); - const registry = (Registry.as(ViewletExtensions.Viewlets)); - const allViewletActions = registry.getViewlets(); - const actionOptions = { label: true, icon: true }; + 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); - const toAction = (viewlet: ViewletDescriptor) => { - let action = this.instantiationService.createInstance(ViewletActivityAction, viewlet.id + '.activity-bar-action', viewlet); + this.activityActionItems[action.id] = new ActivityActionItem(action, composite.name, this.getKeybindingLabel(composite.id)); + this.compositeIdToActions[composite.id] = action; - let keybinding: string = null; - let keys = this.keybindingService.lookupKeybindings(viewlet.id).map(k => this.keybindingService.getLabelFor(k)); - if (keys && keys.length) { - keybinding = keys[0]; - } + // Mark active viewlet and panel action as active + if (activeViewlet && activeViewlet.getId() === composite.id || activePanel && activePanel.getId() === composite.id) { + action.activate(); + } - this.activityActionItems[action.id] = new ActivityActionItem(action, viewlet.name, keybinding); - this.viewletIdToActions[viewlet.id] = action; + return action; + }; - // Mark active viewlet action as active - if (activeViewlet && activeViewlet.getId() === viewlet.id) { - action.activate(); - } + 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 action; - }; - - // Add to viewlet switcher - this.viewletSwitcherBar.push(allViewletActions - .filter(v => !v.isGlobal) - .sort((v1, v2) => v1.order - v2.order) - .map(toAction) - , actionOptions); + return null; } public dispose(): void { @@ -153,9 +217,13 @@ export class ActivitybarPart extends Part implements IActivityService { this.viewletSwitcherBar = null; } - if (this.globalToolBar) { - this.globalToolBar.dispose(); - this.globalToolBar = null; + if (this.panelSwitcherBar) { + this.panelSwitcherBar.dispose(); + this.panelSwitcherBar = null; + } + + if (this.togglePanelAction) { + this.togglePanelAction.dispose(); } super.dispose(); @@ -166,41 +234,48 @@ class ViewletActivityAction extends ActivityAction { private static preventDoubleClickDelay = 300; private lastRun: number = 0; - private viewlet: ViewletDescriptor; - constructor( - id: string, viewlet: ViewletDescriptor, + id: string, private viewlet: ViewletDescriptor, @IViewletService private viewletService: IViewletService, @IPartService private partService: IPartService ) { super(id, viewlet.name, viewlet.cssClass); - - this.viewlet = viewlet; } 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) { this.partService.setSideBarHidden(true); - } - - // Open viewlet and focus it - else { + } else { this.viewletService.openViewlet(this.viewlet.id, true).done(null, errors.onUnexpectedError); this.activate(); } return TPromise.as(true); } -} \ No newline at end of file +} + +class PanelActivityAction extends ActivityAction { + + constructor( + id: string, private panel: PanelDescriptor, + @IPanelService private panelService: IPanelService + ) { + super(id, panel.name, panel.cssClass); + } + + public run(): TPromise { + return this.panelService.openPanel(this.panel.id, true).then(() => this.activate()); + } +} 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/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 new file mode 100755 index 00000000000..906bb60cb40 --- /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/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 { 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; } } 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/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/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index d0d12a0a847..bf430840d75 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 = 'workbench.debug.action.toggleRepl'; + 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); 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; diff --git a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts index fa2ba4416e0..514fb267a9d 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts +++ b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts @@ -26,7 +26,7 @@ import Tree = require('vs/base/parts/tree/browser/tree'); export class ToggleMarkersPanelAction extends TogglePanelAction { - public static ID:string = 'workbench.actions.view.problems'; + public static ID = 'workbench.actions.view.problems'; constructor(id: string, label: string, @IPartService partService: IPartService, diff --git a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts index f0c71e08d01..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({ @@ -41,12 +81,14 @@ 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 } + 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. 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 + ); +} 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 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