diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 07501f589e2..850dc4c4993 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -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()); + private readonly styleOverrides = new Set(); 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 diff --git a/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts b/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts index e26f8e64bf9..cb45dbc86de 100644 --- a/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts +++ b/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts @@ -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(); } } diff --git a/src/vs/workbench/services/statusbar/browser/statusbar.ts b/src/vs/workbench/services/statusbar/browser/statusbar.ts index 206c7809cbc..0cd27174bf4 100644 --- a/src/vs/workbench/services/statusbar/browser/statusbar.ts +++ b/src/vs/workbench/services/statusbar/browser/statusbar.ts @@ -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('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 {