提交 1c20475f 编写于 作者: B Benjamin Pasero

theming - introduce and use colors for notifications box

上级 5aaa268c
......@@ -162,6 +162,9 @@ export const listHoverOutline = registerColor('listHoverOutline', { dark: null,
export const pickerGroupForeground = registerColor('pickerGroupForeground', { dark: Color.fromHex('#0097FB').transparent(0.6), light: Color.fromHex('#007ACC').transparent(0.6), hc: Color.white }, nls.localize('pickerGroupForeground', "Quick picker color for grouping labels."));
export const pickerGroupBorder = registerColor('pickerGroupBorder', { dark: '#3F3F46', light: '#CCCEDB', hc: Color.white }, nls.localize('pickerGroupBorder', "Quick picker color for grouping borders."));
export const buttonBackground = registerColor('buttonBackground', { dark: '#0E639C', light: '#007ACC', hc: null }, nls.localize('buttonBackground', "Button background color."));
export const buttonHoverBackground = registerColor('buttonHoverBackground', { dark: '#007ACC', light: '#006BB3', hc: null }, nls.localize('buttonHoverBackground', "Button background color when hovering."));
/**
* Editor background color.
* Because of bug https://monacotools.visualstudio.com/DefaultCollection/Monaco/_workitems/edit/13254
......
......@@ -250,6 +250,38 @@ export const TITLE_BAR_INACTIVE_BACKGROUND = registerColor('titleBarInactiveBack
hc: null
}, nls.localize('titleBarInactiveBackground', "Title bar background when the window is inactive. Note that this color is currently only supported on macOS."));
// < --- Notifications --- >
export const NOTIFICATIONS_FOREGROUND = registerColor('notificationsForeground', {
dark: '#EEEEEE',
light: '#EEEEEE',
hc: '#FFFFFF'
}, nls.localize('notificationsForeground', "Notifications foreground color. Notifications slide in from the top of the window."));
export const NOTIFICATIONS_BACKGROUND = registerColor('notificationsBackground', {
dark: '#333333',
light: '#2C2C2C',
hc: '#000000'
}, nls.localize('notificationsBackground', "Notifications background color. Notifications slide in from the top of the window."));
export const NOTIFICATIONS_ERROR_BACKGROUND = registerColor('notificationsErrorBackground', {
dark: '#BE1100',
light: '#BE1100',
hc: null
}, nls.localize('notificationsErrorBackground', "Notifications error background color. Notifications slide in from the top of the window."));
export const NOTIFICATIONS_WARNING_BACKGROUND = registerColor('notificationsWarningBackground', {
dark: '#B89500',
light: '#B89500',
hc: null
}, nls.localize('notificationsWarningBackground', "Notifications background color. Notifications slide in from the top of the window."));
export const NOTIFICATIONS_INFO_BACKGROUND = registerColor('notificationsInfoBackground', {
dark: '#007ACC',
light: '#007ACC',
hc: null
}, nls.localize('notificationsInfoBackground', "Notifications background color. Notifications slide in from the top of the window."));
/**
* Base class for all themable workbench components.
*/
......
......@@ -111,20 +111,6 @@
/* TODO@theme */
.vs .global-message-list,
.vs-dark .global-message-list,
.hc-black .global-message-list {
color: #eee;
}
.vs .global-message-list {
background-color: #2C2C2C;
}
.vs-dark .global-message-list {
background-color: #333;
}
.vs .global-message-list {
box-shadow: 0 5px 8px #A8A8A8;
}
......@@ -133,60 +119,7 @@
box-shadow: 0 5px 8px #000;
}
.hc-black .global-message-list {
background-color: #000;
outline-color: #6FC3DF;
}
.hc-black .global-message-list li.message-list-entry .message-left-side.severity {
border-color: #6FC3DF;
}
.hc-black .global-message-list li.message-list-entry .actions-container .message-action .action-button {
border-color: #6FC3DF;
}
.vs .global-message-list li.message-list-entry .actions-container .message-action .action-button:focus,
.vs-dark .global-message-list li.message-list-entry .actions-container .message-action .action-button:focus {
outline-color: rgba(255, 255, 255, .5); /* buttons have a blue color, so focus indication needs to be different */
}
.vs .global-message-list li.message-list-entry .message-left-side.severity.app-error {
background-color: #BE1100;
}
.vs-dark .global-message-list li.message-list-entry .message-left-side.severity.app-error {
background-color: #BE1100;
}
.vs .global-message-list li.message-list-entry .message-left-side.severity.app-warning {
background-color: #B89500;
}
.vs-dark .global-message-list li.message-list-entry .message-left-side.severity.app-warning {
background-color: #B89500;
}
.vs .global-message-list li.message-list-entry .message-left-side.severity.app-info {
background-color: #007ACC;
}
.vs-dark .global-message-list li.message-list-entry .message-left-side.severity.app-info {
background-color: #007ACC;
}
.vs .global-message-list li.message-list-entry .actions-container .message-action {
background-color: #1382CE;
}
.vs .global-message-list li.message-list-entry .actions-container .message-action:hover {
background-color: #006bb3;
}
.vs-dark .global-message-list li.message-list-entry .actions-container .message-action {
background-color: #0E639C;
}
.vs-dark .global-message-list li.message-list-entry .actions-container .message-action:hover {
background-color: #007ACC;
}
\ No newline at end of file
......@@ -19,6 +19,12 @@ import { Action } from 'vs/base/common/actions';
import htmlRenderer = require('vs/base/browser/htmlContentRenderer');
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { NOTIFICATIONS_FOREGROUND, NOTIFICATIONS_BACKGROUND, NOTIFICATIONS_INFO_BACKGROUND, NOTIFICATIONS_ERROR_BACKGROUND, NOTIFICATIONS_WARNING_BACKGROUND } from "vs/workbench/common/theme";
import { ITelemetryService } from "vs/platform/telemetry/common/telemetry";
import { registerThemingParticipant } from "vs/platform/theme/common/themeService";
import { highContrastBorder, buttonBackground, buttonHoverBackground } from "vs/platform/theme/common/colorRegistry";
import { IDisposable, dispose } from "vs/base/common/lifecycle";
import { Color } from "vs/base/common/color";
export enum Severity {
Info,
......@@ -47,32 +53,42 @@ export class IMessageListOptions {
maxMessageLength: number;
}
export interface IUsageLogger {
publicLog(eventName: string, data?: any): void;
}
const DEFAULT_MESSAGE_LIST_OPTIONS = {
purgeInterval: 10000,
maxMessages: 5,
maxMessageLength: 500
};
export class MessageList {
private static DEFAULT_MESSAGE_PURGER_INTERVAL = 10000;
private static DEFAULT_MAX_MESSAGES = 5;
private static DEFAULT_MAX_MESSAGE_LENGTH = 500;
private messages: IMessageEntry[];
private messageListPurger: TPromise<void>;
private messageListContainer: Builder;
private container: HTMLElement;
private options: IMessageListOptions;
private usageLogger: IUsageLogger;
private _onMessagesShowing: Emitter<void>;
private _onMessagesCleared: Emitter<void>;
constructor(container: HTMLElement, usageLogger?: IUsageLogger, options: IMessageListOptions = { purgeInterval: MessageList.DEFAULT_MESSAGE_PURGER_INTERVAL, maxMessages: MessageList.DEFAULT_MAX_MESSAGES, maxMessageLength: MessageList.DEFAULT_MAX_MESSAGE_LENGTH }) {
private toDispose: IDisposable[];
private background = Color.fromHex('#333333');
private foreground = Color.fromHex('#EEEEEE');
private outlineBorder: Color;
private buttonBackground = Color.fromHex('#0E639C');
private infoBackground = Color.fromHex('#007ACC');
private warningBackground = Color.fromHex('#B89500');
private errorBackground = Color.fromHex('#BE1100');
constructor(
container: HTMLElement,
private telemetryService: ITelemetryService,
options: IMessageListOptions = DEFAULT_MESSAGE_LIST_OPTIONS
) {
this.toDispose = [];
this.messages = [];
this.messageListPurger = null;
this.container = container;
this.usageLogger = usageLogger;
this.options = options;
this._onMessagesShowing = new Emitter<void>();
......@@ -82,8 +98,21 @@ export class MessageList {
}
private registerListeners(): void {
browser.onDidChangeFullscreen(() => this.positionMessageList());
browser.onDidChangeZoomLevel(() => this.positionMessageList());
this.toDispose.push(browser.onDidChangeFullscreen(() => this.positionMessageList()));
this.toDispose.push(browser.onDidChangeZoomLevel(() => this.positionMessageList()));
this.toDispose.push(registerThemingParticipant((theme, collector) => {
this.background = theme.getColor(NOTIFICATIONS_BACKGROUND);
this.foreground = theme.getColor(NOTIFICATIONS_FOREGROUND);
this.outlineBorder = theme.getColor(highContrastBorder);
this.buttonBackground = theme.getColor(buttonBackground);
this.infoBackground = theme.getColor(NOTIFICATIONS_INFO_BACKGROUND);
this.warningBackground = theme.getColor(NOTIFICATIONS_WARNING_BACKGROUND);
this.errorBackground = theme.getColor(NOTIFICATIONS_ERROR_BACKGROUND);
collector.addRule(`.global-message-list li.message-list-entry .actions-container .message-action .action-button:hover { background-color: ${theme.getColor(buttonHoverBackground)} !important; }`);
this.updateStyles();
}));
}
public get onMessagesShowing(): Event<void> {
......@@ -94,6 +123,14 @@ export class MessageList {
return this._onMessagesCleared.event;
}
public updateStyles(): void {
if (this.messageListContainer) {
this.messageListContainer.style('background-color', this.background ? this.background.toString() : null);
this.messageListContainer.style('color', this.foreground ? this.foreground.toString() : null);
this.messageListContainer.style('outline-color', this.outlineBorder ? this.outlineBorder.toString() : null);
}
}
public showMessage(severity: Severity, message: string, onHide?: () => void): () => void;
public showMessage(severity: Severity, message: Error, onHide?: () => void): () => void;
public showMessage(severity: Severity, message: string[], onHide?: () => void): () => void;
......@@ -206,6 +243,9 @@ export class MessageList {
}, 50 /* Need this delay to reliably get the animation on some browsers */);
}
});
// Styles
this.updateStyles();
}
private positionMessageList(animate?: boolean): void {
......@@ -232,30 +272,32 @@ export class MessageList {
for (let i = 0; i < messageActions.length; i++) {
const action = messageActions[i];
actionContainer.div({ class: 'message-action' }, div => {
div.a({ class: 'action-button', tabindex: '0', role: 'button' }).text(action.label).on([DOM.EventType.CLICK, DOM.EventType.KEY_DOWN], e => {
if (e instanceof KeyboardEvent) {
const event = new StandardKeyboardEvent(e);
if (!event.equals(KeyCode.Enter) && !event.equals(KeyCode.Space)) {
return; // Only handle Enter/Escape for keyboard access
div.a({ class: 'action-button', tabindex: '0', role: 'button' })
.style('border-color', this.outlineBorder ? this.outlineBorder.toString() : null)
.style('background-color', this.buttonBackground ? this.buttonBackground.toString() : null)
.text(action.label)
.on([DOM.EventType.CLICK, DOM.EventType.KEY_DOWN], e => {
if (e instanceof KeyboardEvent) {
const event = new StandardKeyboardEvent(e);
if (!event.equals(KeyCode.Enter) && !event.equals(KeyCode.Space)) {
return; // Only handle Enter/Escape for keyboard access
}
}
}
DOM.EventHelper.stop(e, true);
DOM.EventHelper.stop(e, true);
if (this.usageLogger) {
this.usageLogger.publicLog('workbenchActionExecuted', { id: action.id, from: 'message' });
}
this.telemetryService.publicLog('workbenchActionExecuted', { id: action.id, from: 'message' });
(action.run() || TPromise.as(null))
.then(null, error => this.showMessage(Severity.Error, error))
.done(r => {
if (typeof r === 'boolean' && r === false) {
return;
}
(action.run() || TPromise.as(null))
.then(null, error => this.showMessage(Severity.Error, error))
.done(r => {
if (typeof r === 'boolean' && r === false) {
return;
}
this.hideMessage(message.text); // hide all matching the text since there may be duplicates
});
});
this.hideMessage(message.text); // hide all matching the text since there may be duplicates
});
});
});
}
});
......@@ -268,7 +310,11 @@ export class MessageList {
// Severity indicator
const sev = message.severity;
const label = (sev === Severity.Error) ? nls.localize('error', "Error") : (sev === Severity.Warning) ? nls.localize('warning', "Warn") : nls.localize('info', "Info");
$().span({ class: 'message-left-side severity ' + ((sev === Severity.Error) ? 'app-error' : (sev === Severity.Warning) ? 'app-warning' : 'app-info'), text: label }).appendTo(div);
const color = (sev === Severity.Error) ? this.errorBackground : (sev === Severity.Warning) ? this.warningBackground : this.infoBackground;
const sevLabel = $().span({ class: `message-left-side severity ${sev === Severity.Error ? 'app-error' : sev === Severity.Warning ? 'app-warning' : 'app-info'}`, text: label });
sevLabel.style('border-color', this.outlineBorder ? this.outlineBorder.toString() : null);
sevLabel.style('background-color', color ? color.toString() : null);
sevLabel.appendTo(div);
// Error message
const messageContentElement = htmlRenderer.renderHtml({
......@@ -413,4 +459,8 @@ export class MessageList {
}
});
}
public dispose(): void {
this.toDispose = dispose(this.toDispose);
}
}
\ No newline at end of file
......@@ -8,7 +8,7 @@ import errors = require('vs/base/common/errors');
import { toErrorMessage } from 'vs/base/common/errorMessage';
import types = require('vs/base/common/types');
import { MessageList, Severity as BaseSeverity } from 'vs/workbench/services/message/browser/messageList';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IMessageService, IMessageWithAction, IConfirmation, Severity } from 'vs/platform/message/common/message';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import Event from 'vs/base/common/event';
......@@ -25,7 +25,7 @@ export class WorkbenchMessageService implements IMessageService {
public _serviceBrand: any;
private handler: MessageList;
private disposeables: IDisposable[];
private toDispose: IDisposable[];
private canShowMessages: boolean;
private messageBuffer: IBufferedMessage[];
......@@ -35,10 +35,9 @@ export class WorkbenchMessageService implements IMessageService {
telemetryService: ITelemetryService
) {
this.handler = new MessageList(container, telemetryService);
this.messageBuffer = [];
this.canShowMessages = true;
this.disposeables = [];
this.toDispose = [this.handler];
}
public get onMessagesShowing(): Event<void> {
......@@ -146,8 +145,6 @@ export class WorkbenchMessageService implements IMessageService {
}
public dispose(): void {
while (this.disposeables.length) {
this.disposeables.pop().dispose();
}
this.toDispose = dispose(this.toDispose);
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册