Use theme service in more places

This commit is contained in:
Daniel Imms
2022-10-08 13:55:23 -07:00
parent 80e474c6ad
commit 6e35bcd767
18 changed files with 160 additions and 169 deletions
+23 -27
View File
@@ -8,7 +8,7 @@ import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSO
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
import { Disposable, toDisposable } from 'common/Lifecycle';
import { IColorSet, ILinkifierEvent, ILinkifier2, ReadonlyColorSet } from 'browser/Types';
import { ICharSizeService, ICoreBrowserService } from 'browser/services/Services';
import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
import { IOptionsService, IBufferService, IInstantiationService } from 'common/services/Services';
import { EventEmitter, IEvent } from 'common/EventEmitter';
import { color } from 'common/Color';
@@ -43,7 +43,6 @@ export class DomRenderer extends Disposable implements IRenderer {
public readonly onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>()).event;
constructor(
private _colors: ReadonlyColorSet,
private readonly _element: HTMLElement,
private readonly _screenElement: HTMLElement,
private readonly _viewportElement: HTMLElement,
@@ -52,7 +51,8 @@ export class DomRenderer extends Disposable implements IRenderer {
@ICharSizeService private readonly _charSizeService: ICharSizeService,
@IOptionsService private readonly _optionsService: IOptionsService,
@IBufferService private readonly _bufferService: IBufferService,
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
@IThemeService themeService: IThemeService
) {
super();
this._rowContainer = document.createElement('div');
@@ -79,9 +79,11 @@ export class DomRenderer extends Disposable implements IRenderer {
actualCellHeight: 0
};
this._updateDimensions();
this._injectCss();
this._rowFactory = instantiationService.createInstance(DomRendererRowFactory, document, this._colors);
this.register(themeService.onChangeColors(e => this._injectCss(e)));
this._injectCss(themeService.colors);
this._rowFactory = instantiationService.createInstance(DomRendererRowFactory, document);
this._element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass);
this._screenElement.appendChild(this._rowContainer);
@@ -142,12 +144,7 @@ export class DomRenderer extends Disposable implements IRenderer {
this._screenElement.style.height = `${this.dimensions.canvasHeight}px`;
}
public setColors(colors: IColorSet): void {
this._colors = colors;
this._injectCss();
}
private _injectCss(): void {
private _injectCss(colors: ReadonlyColorSet): void {
if (!this._themeStyleElement) {
this._themeStyleElement = document.createElement('style');
this._screenElement.appendChild(this._themeStyleElement);
@@ -156,7 +153,7 @@ export class DomRenderer extends Disposable implements IRenderer {
// Base CSS
let styles =
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} {` +
` color: ${this._colors.foreground.css};` +
` color: ${colors.foreground.css};` +
` font-family: ${this._optionsService.rawOptions.fontFamily};` +
` font-size: ${this._optionsService.rawOptions.fontSize}px;` +
`}`;
@@ -181,18 +178,18 @@ export class DomRenderer extends Disposable implements IRenderer {
styles +=
`@keyframes blink_block` + `_` + this._terminalClass + ` {` +
` 0% {` +
` background-color: ${this._colors.cursor.css};` +
` color: ${this._colors.cursorAccent.css};` +
` background-color: ${colors.cursor.css};` +
` color: ${colors.cursorAccent.css};` +
` }` +
` 50% {` +
` background-color: ${this._colors.cursorAccent.css};` +
` color: ${this._colors.cursor.css};` +
` background-color: ${colors.cursorAccent.css};` +
` color: ${colors.cursor.css};` +
` }` +
`}`;
// Cursor
styles +=
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${CURSOR_CLASS}.${CURSOR_STYLE_BLOCK_CLASS} {` +
` outline: 1px solid ${this._colors.cursor.css};` +
` outline: 1px solid ${colors.cursor.css};` +
` outline-offset: -1px;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS}.${CURSOR_BLINK_CLASS}:not(.${CURSOR_STYLE_BLOCK_CLASS}) {` +
@@ -202,14 +199,14 @@ export class DomRenderer extends Disposable implements IRenderer {
` animation: blink_block` + `_` + this._terminalClass + ` 1s step-end infinite;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_BLOCK_CLASS} {` +
` background-color: ${this._colors.cursor.css};` +
` color: ${this._colors.cursorAccent.css};` +
` background-color: ${colors.cursor.css};` +
` color: ${colors.cursorAccent.css};` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_BAR_CLASS} {` +
` box-shadow: ${this._optionsService.rawOptions.cursorWidth}px 0 0 ${this._colors.cursor.css} inset;` +
` box-shadow: ${this._optionsService.rawOptions.cursorWidth}px 0 0 ${colors.cursor.css} inset;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_UNDERLINE_CLASS} {` +
` box-shadow: 0 -1px 0 ${this._colors.cursor.css} inset;` +
` box-shadow: 0 -1px 0 ${colors.cursor.css} inset;` +
`}`;
// Selection
styles +=
@@ -222,21 +219,21 @@ export class DomRenderer extends Disposable implements IRenderer {
`}` +
`${this._terminalSelector}.focus .${SELECTION_CLASS} div {` +
` position: absolute;` +
` background-color: ${this._colors.selectionBackgroundOpaque.css};` +
` background-color: ${colors.selectionBackgroundOpaque.css};` +
`}` +
`${this._terminalSelector} .${SELECTION_CLASS} div {` +
` position: absolute;` +
` background-color: ${this._colors.selectionInactiveBackgroundOpaque.css};` +
` background-color: ${colors.selectionInactiveBackgroundOpaque.css};` +
`}`;
// Colors
for (const [i, c] of this._colors.ansi.entries()) {
for (const [i, c] of colors.ansi.entries()) {
styles +=
`${this._terminalSelector} .${FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +
`${this._terminalSelector} .${BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;
}
styles +=
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${color.opaque(this._colors.background).css}; }` +
`${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${this._colors.foreground.css}; }`;
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${color.opaque(colors.background).css}; }` +
`${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${colors.foreground.css}; }`;
this._themeStyleElement.textContent = styles;
}
@@ -348,7 +345,6 @@ export class DomRenderer extends Disposable implements IRenderer {
public handleOptionsChanged(): void {
// Force a refresh
this._updateDimensions();
this._injectCss();
}
public clear(): void {
@@ -12,7 +12,7 @@ import { IBufferLine } from 'common/Types';
import { CellData } from 'common/buffer/CellData';
import { MockCoreService, MockDecorationService, MockOptionsService } from 'common/TestUtils.test';
import { css } from 'common/Color';
import { MockCharacterJoinerService, MockCoreBrowserService } from 'browser/TestUtils.test';
import { MockCharacterJoinerService, MockCoreBrowserService, MockThemeService } from 'browser/TestUtils.test';
describe('DomRendererRowFactory', () => {
let dom: jsdom.JSDOM;
@@ -23,35 +23,12 @@ describe('DomRendererRowFactory', () => {
dom = new jsdom.JSDOM('');
rowFactory = new DomRendererRowFactory(
dom.window.document,
{
background: css.toColor('#010101'),
foreground: css.toColor('#020202'),
ansi: [
// dark:
css.toColor('#2e3436'),
css.toColor('#cc0000'),
css.toColor('#4e9a06'),
css.toColor('#c4a000'),
css.toColor('#3465a4'),
css.toColor('#75507b'),
css.toColor('#06989a'),
css.toColor('#d3d7cf'),
// bright:
css.toColor('#555753'),
css.toColor('#ef2929'),
css.toColor('#8ae234'),
css.toColor('#fce94f'),
css.toColor('#729fcf'),
css.toColor('#ad7fa8'),
css.toColor('#34e2e2'),
css.toColor('#eeeeec')
]
} as any,
new MockCharacterJoinerService(),
new MockOptionsService({ drawBoldTextInBrightColors: true }),
new MockCoreBrowserService(),
new MockCoreService(),
new MockDecorationService()
new MockDecorationService(),
new MockThemeService()
);
lineData = createEmptyLineData(2);
});
@@ -10,7 +10,7 @@ import { CellData } from 'common/buffer/CellData';
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
import { color, rgba } from 'common/Color';
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
import { ICharacterJoinerService, ICoreBrowserService } from 'browser/services/Services';
import { ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
import { JoinedCellData } from 'browser/services/CharacterJoinerService';
import { excludeFromContrastRatioDemands } from 'browser/renderer/shared/RendererUtils';
import { AttributeData } from 'common/buffer/AttributeData';
@@ -35,19 +35,15 @@ export class DomRendererRowFactory {
constructor(
private readonly _document: Document,
private _colors: ReadonlyColorSet,
@ICharacterJoinerService private readonly _characterJoinerService: ICharacterJoinerService,
@IOptionsService private readonly _optionsService: IOptionsService,
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
@ICoreService private readonly _coreService: ICoreService,
@IDecorationService private readonly _decorationService: IDecorationService
@IDecorationService private readonly _decorationService: IDecorationService,
@IThemeService private readonly _themeService: IThemeService
) {
}
public setColors(colors: IColorSet): void {
this._colors = colors;
}
public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void {
this._selectionStart = start;
this._selectionEnd = end;
@@ -71,6 +67,8 @@ export class DomRendererRowFactory {
}
}
const colors = this._themeService.colors;
for (let x = 0; x < lineLength; x++) {
lineData.loadCell(x, this._workCell);
let width = this._workCell.getWidth();
@@ -176,7 +174,7 @@ export class DomRendererRowFactory {
if (this._optionsService.rawOptions.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {
fg += 8;
}
charElement.style.textDecorationColor = this._colors.ansi[fg].css;
charElement.style.textDecorationColor = colors.ansi[fg].css;
}
}
}
@@ -224,17 +222,17 @@ export class DomRendererRowFactory {
// Apply selection foreground if applicable
const isInSelection = this._isCellInSelection(x, row);
if (!isTop) {
if (this._colors.selectionForeground && isInSelection) {
if (colors.selectionForeground && isInSelection) {
fgColorMode = Attributes.CM_RGB;
fg = this._colors.selectionForeground.rgba >> 8 & 0xFFFFFF;
fgOverride = this._colors.selectionForeground;
fg = colors.selectionForeground.rgba >> 8 & 0xFFFFFF;
fgOverride = colors.selectionForeground;
}
}
// If in the selection, force the element to be above the selection to improve contrast and
// support opaque selections
if (isInSelection) {
bgOverride = this._coreBrowserService.isFocused ? this._colors.selectionBackgroundOpaque : this._colors.selectionInactiveBackgroundOpaque;
bgOverride = this._coreBrowserService.isFocused ? colors.selectionBackgroundOpaque : colors.selectionInactiveBackgroundOpaque;
isTop = true;
}
@@ -248,7 +246,7 @@ export class DomRendererRowFactory {
switch (bgColorMode) {
case Attributes.CM_P16:
case Attributes.CM_P256:
resolvedBg = this._colors.ansi[bg];
resolvedBg = colors.ansi[bg];
charElement.classList.add(`xterm-bg-${bg}`);
break;
case Attributes.CM_RGB:
@@ -258,10 +256,10 @@ export class DomRendererRowFactory {
case Attributes.CM_DEFAULT:
default:
if (isInverse) {
resolvedBg = this._colors.foreground;
resolvedBg = colors.foreground;
charElement.classList.add(`xterm-bg-${INVERTED_DEFAULT_COLOR}`);
} else {
resolvedBg = this._colors.background;
resolvedBg = colors.background;
}
}
@@ -279,7 +277,7 @@ export class DomRendererRowFactory {
if (cell.isBold() && fg < 8 && this._optionsService.rawOptions.drawBoldTextInBrightColors) {
fg += 8;
}
if (!this._applyMinimumContrast(charElement, resolvedBg, this._colors.ansi[fg], cell, bgOverride, undefined)) {
if (!this._applyMinimumContrast(charElement, resolvedBg, colors.ansi[fg], cell, bgOverride, undefined)) {
charElement.classList.add(`xterm-fg-${fg}`);
}
break;
@@ -295,7 +293,7 @@ export class DomRendererRowFactory {
break;
case Attributes.CM_DEFAULT:
default:
if (!this._applyMinimumContrast(charElement, resolvedBg, this._colors.foreground, cell, bgOverride, undefined)) {
if (!this._applyMinimumContrast(charElement, resolvedBg, colors.foreground, cell, bgOverride, undefined)) {
if (isInverse) {
charElement.classList.add(`xterm-fg-${INVERTED_DEFAULT_COLOR}`);
}
@@ -317,13 +315,13 @@ export class DomRendererRowFactory {
// Try get from cache first, only use the cache when there are no decoration overrides
let adjustedColor: IColor | undefined | null = undefined;
if (!bgOverride && !fgOverride) {
adjustedColor = this._colors.contrastCache.getColor(bg.rgba, fg.rgba);
adjustedColor = this._themeService.colors.contrastCache.getColor(bg.rgba, fg.rgba);
}
// Calculate and store in cache
if (adjustedColor === undefined) {
adjustedColor = color.ensureContrastRatio(bgOverride || bg, fgOverride || fg, this._optionsService.rawOptions.minimumContrastRatio);
this._colors.contrastCache.setColor((bgOverride || bg).rgba, (fgOverride || fg).rgba, adjustedColor ?? null);
this._themeService.colors.contrastCache.setColor((bgOverride || bg).rgba, (fgOverride || fg).rgba, adjustedColor ?? null);
}
if (adjustedColor) {