simplify decoration rules and add trace assertion for when things go south...
This commit is contained in:
parent
75b075962a
commit
dca100feaa
2 changed files with 22 additions and 29 deletions
|
@ -795,7 +795,7 @@ function getSharedStyleSheet(): HTMLStyleElement {
|
||||||
return _sharedStyleSheet;
|
return _sharedStyleSheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDynamicStyleSheetRules(style: any) {
|
export function getDynamicStyleSheetRules(style: any): CSSStyleRule[] {
|
||||||
if (style && style.sheet && style.sheet.rules) {
|
if (style && style.sheet && style.sheet.rules) {
|
||||||
// Chrome, IE
|
// Chrome, IE
|
||||||
return style.sheet.rules;
|
return style.sheet.rules;
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { TernarySearchTree } from 'vs/base/common/map';
|
||||||
import { IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
import { IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||||
import { isThenable } from 'vs/base/common/async';
|
import { isThenable } from 'vs/base/common/async';
|
||||||
import { LinkedList } from 'vs/base/common/linkedList';
|
import { LinkedList } from 'vs/base/common/linkedList';
|
||||||
import { createStyleSheet, createCSSRule, removeCSSRulesContainingSelector } from 'vs/base/browser/dom';
|
import { createStyleSheet, createCSSRule, removeCSSRulesContainingSelector, getDynamicStyleSheetRules } from 'vs/base/browser/dom';
|
||||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||||
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||||
|
@ -22,25 +22,25 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||||
|
|
||||||
class DecorationRule {
|
class DecorationRule {
|
||||||
|
|
||||||
static keyOf(data: IDecorationData | IDecorationData[]): string {
|
static keyOf(data: IDecorationData[]): string {
|
||||||
if (Array.isArray(data)) {
|
let result = '';
|
||||||
return data.map(DecorationRule.keyOf).join(',');
|
for (const d of data) {
|
||||||
} else {
|
const { color, letter } = d;
|
||||||
const { color, letter } = data;
|
result += `${color}/${letter}`;
|
||||||
return `${color}/${letter}`;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly _classNames = new IdGenerator('monaco-decorations-style-');
|
private static readonly _classNames = new IdGenerator('monaco-decorations-style-');
|
||||||
|
|
||||||
readonly data: IDecorationData | IDecorationData[];
|
readonly data: IDecorationData[];
|
||||||
readonly itemColorClassName: string;
|
readonly itemColorClassName: string;
|
||||||
readonly itemBadgeClassName: string;
|
readonly itemBadgeClassName: string;
|
||||||
readonly bubbleBadgeClassName: string;
|
readonly bubbleBadgeClassName: string;
|
||||||
|
|
||||||
private _refCounter: number = 0;
|
private _refCounter: number = 0;
|
||||||
|
|
||||||
constructor(data: IDecorationData | IDecorationData[]) {
|
constructor(data: IDecorationData[]) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.itemColorClassName = DecorationRule._classNames.nextId();
|
this.itemColorClassName = DecorationRule._classNames.nextId();
|
||||||
this.itemBadgeClassName = DecorationRule._classNames.nextId();
|
this.itemBadgeClassName = DecorationRule._classNames.nextId();
|
||||||
|
@ -56,30 +56,13 @@ class DecorationRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
appendCSSRules(element: HTMLStyleElement, theme: ITheme): void {
|
appendCSSRules(element: HTMLStyleElement, theme: ITheme): void {
|
||||||
if (!Array.isArray(this.data)) {
|
|
||||||
this._appendForOne(this.data, element, theme);
|
|
||||||
} else {
|
|
||||||
this._appendForMany(this.data, element, theme);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _appendForOne(data: IDecorationData, element: HTMLStyleElement, theme: ITheme): void {
|
|
||||||
const { color, letter } = data;
|
|
||||||
// label
|
// label
|
||||||
createCSSRule(`.${this.itemColorClassName}`, `color: ${getColor(theme, color)};`, element);
|
const { color } = this.data[0];
|
||||||
// letter
|
|
||||||
if (letter) {
|
|
||||||
createCSSRule(`.${this.itemBadgeClassName}::after`, `content: "${letter}"; color: ${getColor(theme, color)};`, element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _appendForMany(data: IDecorationData[], element: HTMLStyleElement, theme: ITheme): void {
|
|
||||||
// label
|
|
||||||
const { color } = data[0];
|
|
||||||
createCSSRule(`.${this.itemColorClassName}`, `color: ${getColor(theme, color)};`, element);
|
createCSSRule(`.${this.itemColorClassName}`, `color: ${getColor(theme, color)};`, element);
|
||||||
|
|
||||||
// badge
|
// badge
|
||||||
const letters = data.filter(d => !isFalsyOrWhitespace(d.letter)).map(d => d.letter);
|
const letters = this.data.filter(d => !isFalsyOrWhitespace(d.letter)).map(d => d.letter);
|
||||||
if (letters.length) {
|
if (letters.length) {
|
||||||
createCSSRule(`.${this.itemBadgeClassName}::after`, `content: "${letters.join(', ')}"; color: ${getColor(theme, color)};`, element);
|
createCSSRule(`.${this.itemBadgeClassName}::after`, `content: "${letters.join(', ')}"; color: ${getColor(theme, color)};`, element);
|
||||||
}
|
}
|
||||||
|
@ -134,6 +117,8 @@ class DecorationStyles {
|
||||||
|
|
||||||
rule.acquire();
|
rule.acquire();
|
||||||
|
|
||||||
|
this._validate();
|
||||||
|
|
||||||
let labelClassName = rule.itemColorClassName;
|
let labelClassName = rule.itemColorClassName;
|
||||||
let badgeClassName = rule.itemBadgeClassName;
|
let badgeClassName = rule.itemBadgeClassName;
|
||||||
let tooltip = data.filter(d => !isFalsyOrWhitespace(d.tooltip)).map(d => d.tooltip).join(' • ');
|
let tooltip = data.filter(d => !isFalsyOrWhitespace(d.tooltip)).map(d => d.tooltip).join(' • ');
|
||||||
|
@ -153,6 +138,7 @@ class DecorationStyles {
|
||||||
this._decorationRules.delete(key);
|
this._decorationRules.delete(key);
|
||||||
rule.removeCSSRules(this._styleElement);
|
rule.removeCSSRules(this._styleElement);
|
||||||
rule = undefined;
|
rule = undefined;
|
||||||
|
this._validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -164,6 +150,13 @@ class DecorationStyles {
|
||||||
rule.appendCSSRules(this._styleElement, this._themeService.getTheme());
|
rule.appendCSSRules(this._styleElement, this._themeService.getTheme());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _validate(): void {
|
||||||
|
const ruleCount = getDynamicStyleSheetRules(this._styleElement).length;
|
||||||
|
if (this._decorationRules.size * 3 !== ruleCount) {
|
||||||
|
console.trace('THIS IS BAD - CHECK YOUR DECORATIONS SOMETHING IS OUT OF SYNC');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileDecorationChangeEvent implements IResourceDecorationChangeEvent {
|
class FileDecorationChangeEvent implements IResourceDecorationChangeEvent {
|
||||||
|
|
Loading…
Reference in a new issue