mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-24 00:05:46 +01:00
statusbar: generalize style overrides
cc @bpasero @isidorn
This commit is contained in:
@@ -5,11 +5,11 @@
|
||||
|
||||
import 'vs/css!./media/statusbarpart';
|
||||
import { localize } from 'vs/nls';
|
||||
import { DisposableStore, dispose, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore, dispose, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Part } from 'vs/workbench/browser/part';
|
||||
import { EventType as TouchEventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarStyleOverride } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IAction, Separator, toAction } from 'vs/base/common/actions';
|
||||
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
@@ -96,6 +96,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
}(this.configurationService, this.hoverService);
|
||||
|
||||
private readonly compactEntriesDisposable = this._register(new MutableDisposable<DisposableStore>());
|
||||
private readonly styleOverrides = new Set<IStatusbarStyleOverride>();
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@@ -498,14 +499,15 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
super.updateStyles();
|
||||
|
||||
const container = assertIsDefined(this.getContainer());
|
||||
const styleOverride: IStatusbarStyleOverride | undefined = [...this.styleOverrides].sort((a, b) => a.priority - b.priority)[0];
|
||||
|
||||
// Background colors
|
||||
const backgroundColor = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND) || '';
|
||||
const backgroundColor = this.getColor(styleOverride?.background ?? (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND)) || '';
|
||||
container.style.backgroundColor = backgroundColor;
|
||||
container.style.color = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND) || '';
|
||||
container.style.color = this.getColor(styleOverride?.foreground ?? (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)) || '';
|
||||
|
||||
// Border color
|
||||
const borderColor = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BORDER : STATUS_BAR_NO_FOLDER_BORDER) || this.getColor(contrastBorder);
|
||||
const borderColor = this.getColor(styleOverride?.border ?? (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BORDER : STATUS_BAR_NO_FOLDER_BORDER)) || this.getColor(contrastBorder);
|
||||
if (borderColor) {
|
||||
container.classList.add('status-border-top');
|
||||
container.style.setProperty('--status-border-top-color', borderColor.toString());
|
||||
@@ -527,6 +529,16 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
super.layoutContents(width, height);
|
||||
}
|
||||
|
||||
overrideStyle(style: IStatusbarStyleOverride): IDisposable {
|
||||
this.styleOverrides.add(style);
|
||||
this.updateStyles();
|
||||
|
||||
return toDisposable(() => {
|
||||
this.styleOverrides.delete(style);
|
||||
this.updateStyles();
|
||||
});
|
||||
}
|
||||
|
||||
toJSON(): object {
|
||||
return {
|
||||
type: Parts.STATUSBAR_PART
|
||||
|
||||
@@ -3,16 +3,14 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IThemeService, Themable } from 'vs/platform/theme/common/themeService';
|
||||
import { localize } from 'vs/nls';
|
||||
import { registerColor, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerColor } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IDebugService, State, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER, STATUS_BAR_BORDER } from 'vs/workbench/common/theme';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { createStyleSheet } from 'vs/base/browser/dom';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { STATUS_BAR_FOREGROUND, STATUS_BAR_BORDER } from 'vs/workbench/common/theme';
|
||||
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IStatusbarService } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
|
||||
// colors for theming
|
||||
|
||||
@@ -34,72 +32,46 @@ export const STATUS_BAR_DEBUGGING_BORDER = registerColor('statusBar.debuggingBor
|
||||
hc: STATUS_BAR_BORDER
|
||||
}, localize('statusBarDebuggingBorder', "Status bar border color separating to the sidebar and editor when a program is being debugged. The status bar is shown in the bottom of the window"));
|
||||
|
||||
export class StatusBarColorProvider extends Themable implements IWorkbenchContribution {
|
||||
private styleElement: HTMLStyleElement | undefined;
|
||||
export class StatusBarColorProvider implements IWorkbenchContribution {
|
||||
|
||||
private readonly disposables = new DisposableStore();
|
||||
private disposable: IDisposable | undefined;
|
||||
|
||||
private set enabled(enabled: boolean) {
|
||||
if (enabled === !!this.disposable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
this.disposable = this.statusbarService.overrideStyle({
|
||||
priority: 100,
|
||||
foreground: STATUS_BAR_DEBUGGING_FOREGROUND,
|
||||
background: STATUS_BAR_DEBUGGING_BACKGROUND,
|
||||
border: STATUS_BAR_DEBUGGING_BORDER,
|
||||
});
|
||||
} else {
|
||||
this.disposable!.dispose();
|
||||
this.disposable = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IDebugService private readonly debugService: IDebugService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
this.registerListeners();
|
||||
this.updateStyles();
|
||||
this.debugService.onDidChangeState(this.update, this, this.disposables);
|
||||
this.contextService.onDidChangeWorkbenchState(this.update, this, this.disposables);
|
||||
this.update();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.debugService.onDidChangeState(state => this.updateStyles()));
|
||||
this._register(this.contextService.onDidChangeWorkbenchState(state => this.updateStyles()));
|
||||
protected update(): void {
|
||||
this.enabled = isStatusbarInDebugMode(this.debugService.state, this.debugService.getViewModel().focusedSession);
|
||||
}
|
||||
|
||||
protected override updateStyles(): void {
|
||||
super.updateStyles();
|
||||
|
||||
const container = assertIsDefined(this.layoutService.getContainer(Parts.STATUSBAR_PART));
|
||||
if (isStatusbarInDebugMode(this.debugService.state, this.debugService.getViewModel().focusedSession)) {
|
||||
container.classList.add('debugging');
|
||||
} else {
|
||||
container.classList.remove('debugging');
|
||||
}
|
||||
|
||||
// Container Colors
|
||||
const backgroundColor = this.getColor(this.getColorKey(STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_DEBUGGING_BACKGROUND, STATUS_BAR_BACKGROUND));
|
||||
container.style.backgroundColor = backgroundColor || '';
|
||||
container.style.color = this.getColor(this.getColorKey(STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_DEBUGGING_FOREGROUND, STATUS_BAR_FOREGROUND)) || '';
|
||||
|
||||
// Border Color
|
||||
const borderColor = this.getColor(this.getColorKey(STATUS_BAR_NO_FOLDER_BORDER, STATUS_BAR_DEBUGGING_BORDER, STATUS_BAR_BORDER)) || this.getColor(contrastBorder);
|
||||
if (borderColor) {
|
||||
container.classList.add('status-border-top');
|
||||
container.style.setProperty('--status-border-top-color', borderColor.toString());
|
||||
} else {
|
||||
container.classList.remove('status-border-top');
|
||||
container.style.removeProperty('--status-border-top-color');
|
||||
}
|
||||
|
||||
// Notification Beak
|
||||
if (!this.styleElement) {
|
||||
this.styleElement = createStyleSheet(container);
|
||||
}
|
||||
|
||||
this.styleElement.textContent = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor} !important; }`;
|
||||
}
|
||||
|
||||
private getColorKey(noFolderColor: string, debuggingColor: string, normalColor: string): string {
|
||||
|
||||
// Not debugging
|
||||
if (!isStatusbarInDebugMode(this.debugService.state, this.debugService.getViewModel().focusedSession)) {
|
||||
if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) {
|
||||
return normalColor;
|
||||
}
|
||||
|
||||
return noFolderColor;
|
||||
}
|
||||
|
||||
// Debugging
|
||||
return debuggingColor;
|
||||
dispose(): void {
|
||||
this.disposable?.dispose();
|
||||
this.disposables.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Event } from 'vs/base/common/event';
|
||||
import { Command } from 'vs/editor/common/languages';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IStatusbarEntryLocation } from 'vs/workbench/browser/parts/statusbar/statusbarModel';
|
||||
import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
export const IStatusbarService = createDecorator<IStatusbarService>('statusbarService');
|
||||
|
||||
@@ -23,6 +24,13 @@ export const ShowTooltipCommand: Command = {
|
||||
title: ''
|
||||
};
|
||||
|
||||
export interface IStatusbarStyleOverride {
|
||||
readonly priority: number; // lower has higher priority
|
||||
readonly foreground?: ColorIdentifier;
|
||||
readonly background?: ColorIdentifier;
|
||||
readonly border?: ColorIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* A declarative way of describing a status bar entry
|
||||
*/
|
||||
@@ -145,6 +153,11 @@ export interface IStatusbarService {
|
||||
* Returns true if a status bar entry is focused.
|
||||
*/
|
||||
isEntryFocused(): boolean;
|
||||
|
||||
/**
|
||||
* Temporarily override statusbar style.
|
||||
*/
|
||||
overrideStyle(style: IStatusbarStyleOverride): IDisposable;
|
||||
}
|
||||
|
||||
export interface IStatusbarEntryAccessor extends IDisposable {
|
||||
|
||||
Reference in New Issue
Block a user