提交 bdcb145d 编写于 作者: B Benjamin Pasero

notifications - status bar support

上级 329868aa
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
export const SHOW_NOTFICATIONS_CENTER_COMMAND_ID = 'notificationsCenter.show';
export const HIDE_NOTFICATIONS_CENTER_COMMAND_ID = 'notificationsCenter.hide';
export const TOGGLE_NOTFICATIONS_CENTER_COMMAND_ID = 'notificationsCenter.toggle';
export interface INotificationsCenterController {
isVisible: boolean;
show(): void;
hide(): void;
}
export function registerNotificationCommands(center: INotificationsCenterController): void {
// Show Center
CommandsRegistry.registerCommand(SHOW_NOTFICATIONS_CENTER_COMMAND_ID, () => center.show());
// Hide Center
CommandsRegistry.registerCommand(HIDE_NOTFICATIONS_CENTER_COMMAND_ID, () => center.hide());
// Toggle Center
CommandsRegistry.registerCommand(TOGGLE_NOTFICATIONS_CENTER_COMMAND_ID, () => center.isVisible ? center.hide() : center.show());
}
\ No newline at end of file
......@@ -5,7 +5,7 @@
'use strict';
import 'vs/css!./media/notificationActions';
import 'vs/css!./media/notificationsActions';
import { INotificationViewItem } from 'vs/workbench/common/notifications';
import { localize } from 'vs/nls';
import { Action, IAction, ActionRunner } from 'vs/base/common/actions';
......
......@@ -5,7 +5,7 @@
'use strict';
import 'vs/css!./media/notificationList';
import 'vs/css!./media/notificationsCenter';
import { addClass, removeClass } from 'vs/base/browser/dom';
import { WorkbenchList } from 'vs/platform/list/browser/listService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -19,10 +19,10 @@ import { NotificationsListDelegate, NotificationRenderer } from 'vs/workbench/br
import { NotificationActionRunner } from 'vs/workbench/browser/parts/notifications/notificationsActions';
export class NotificationsCenter extends Themable {
private listContainer: HTMLElement;
private list: WorkbenchList<INotificationViewItem>;
private viewModel: INotificationViewItem[];
private _isVisible: boolean;
constructor(
private container: HTMLElement,
......@@ -33,41 +33,36 @@ export class NotificationsCenter extends Themable {
super(themeService);
this.viewModel = [];
this.create();
// Show initial notifications if any
this.onNotificationsAdded(0, model.notifications);
this.registerListeners();
}
public get isVisible(): boolean {
return this._isVisible;
}
private registerListeners(): void {
this.toUnbind.push(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
switch (e.kind) {
case NotificationChangeType.ADD:
return this.onNotificationsAdded(e.index, [e.item]);
case NotificationChangeType.CHANGE:
return this.onNotificationChanged(e.index, e.item);
case NotificationChangeType.REMOVE:
return this.onNotificationRemoved(e.index, e.item);
public show(): void {
if (this._isVisible) {
return; // already visible
}
}
protected updateStyles(): void {
if (this.listContainer) {
const outlineColor = this.getColor(contrastBorder);
this.listContainer.style.outlineColor = outlineColor ? outlineColor.toString() : null;
const widgetShadowColor = this.getColor(widgetShadow);
this.listContainer.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : null;
// Lazily create if showing for the first time
if (!this.list) {
this.createNotificationsList();
}
// Make visible
this._isVisible = true;
addClass(this.listContainer, 'visible');
// Show all notifications that are present now
this.onNotificationsAdded(0, this.model.notifications);
}
private create(): void {
private createNotificationsList(): void {
// List Container
this.listContainer = document.createElement('div');
......@@ -95,6 +90,21 @@ export class NotificationsCenter extends Themable {
this.updateStyles();
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
if (!this._isVisible) {
return; // only if visible
}
switch (e.kind) {
case NotificationChangeType.ADD:
return this.onNotificationsAdded(e.index, [e.item]);
case NotificationChangeType.CHANGE:
return this.onNotificationChanged(e.index, e.item);
case NotificationChangeType.REMOVE:
return this.onNotificationRemoved(e.index, e.item);
}
}
private onNotificationsAdded(index: number, items: INotificationViewItem[]): void {
this.updateNotificationsList(index, 0, items);
}
......@@ -109,13 +119,6 @@ export class NotificationsCenter extends Themable {
private updateNotificationsList(start: number, deleteCount: number, items: INotificationViewItem[] = []) {
// Ensure visibility is proper
if (this.model.notifications.length > 0) {
this.show();
} else {
this.hide();
}
// Remember focus/selection
const selection = this.indexToItems(this.list.getSelection());
const focus = this.indexToItems(this.list.getFocus());
......@@ -136,12 +139,27 @@ export class NotificationsCenter extends Themable {
return indeces.map(index => this.viewModel[index]).filter(item => !!item);
}
private show(): void {
addClass(this.listContainer, 'visible');
}
public hide(): void {
private hide(): void {
// Hide
this._isVisible = false;
removeClass(this.listContainer, 'visible');
// Clear list
this.list.splice(0, this.viewModel.length);
// Clear view model
this.viewModel = [];
}
protected updateStyles(): void {
if (this.listContainer) {
const outlineColor = this.getColor(contrastBorder);
this.listContainer.style.outlineColor = outlineColor ? outlineColor.toString() : null;
const widgetShadowColor = this.getColor(widgetShadow);
this.listContainer.style.boxShadow = widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : null;
}
}
}
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { INotificationsModel, INotificationChangeEvent, NotificationChangeType } from 'vs/workbench/common/notifications';
import { IStatusbarService, StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { TOGGLE_NOTFICATIONS_CENTER_COMMAND_ID } from 'vs/workbench/browser/parts/notifications/notificationCommands';
import { localize } from 'vs/nls';
export class NotificationsStatus {
private statusItem: IDisposable;
private toDispose: IDisposable[];
constructor(
private model: INotificationsModel,
@IStatusbarService private statusbarService: IStatusbarService
) {
this.toDispose = [];
this.registerListeners();
}
private registerListeners(): void {
this.toDispose.push(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
if (e.kind === NotificationChangeType.CHANGE) {
return; // only interested in add or remove
}
this.updateNotificationsStatusItem();
}
private updateNotificationsStatusItem(): void {
// Dispose old first
if (this.statusItem) {
this.statusItem.dispose();
}
// Create new
const notificationsCount = this.model.notifications.length;
if (notificationsCount > 0) {
this.statusItem = this.statusbarService.addEntry({
text: `$(bell) ${notificationsCount}`,
command: TOGGLE_NOTFICATIONS_CENTER_COMMAND_ID,
tooltip: localize('notifications', "{0} notifications", notificationsCount)
}, StatusbarAlignment.RIGHT, Number.MIN_VALUE);
}
}
public dispose() {
this.toDispose = dispose(this.toDispose);
}
}
\ No newline at end of file
......@@ -5,7 +5,6 @@
'use strict';
import 'vs/css!./media/notificationList';
import { IDelegate, IRenderer } from 'vs/base/browser/ui/list/list';
import { renderMarkdown } from 'vs/base/browser/htmlContentRenderer';
import { clearNode, addClass, removeClass, toggleClass } from 'vs/base/browser/dom';
......
......@@ -103,6 +103,8 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/notificationsAlerts';
import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus';
import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationCommands';
export const MessagesVisibleContext = new RawContextKey<boolean>('globalMessageVisible', false);
export const EditorsVisibleContext = new RawContextKey<boolean>('editorIsOpen', false);
......@@ -1254,6 +1256,13 @@ export class Workbench implements IPartService {
// Notification Alerts
const notificationsAlerts = this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model);
this.toUnbind.push(notificationsAlerts);
// Notifications Status
const notificationsStatus = this.instantiationService.createInstance(NotificationsStatus, this.notificationService.model);
this.toUnbind.push(notificationsStatus);
// Register Commands
registerNotificationCommands(notificationsCenter);
}
public getInstantiationService(): IInstantiationService {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册