64 lines
1.8 KiB
JavaScript
64 lines
1.8 KiB
JavaScript
const STATIC_KEYS = ["bgcolor", "color", "boxcolor", "titlecolor", "titletext", "shape"];
|
|
|
|
export class ThemeEngine {
|
|
#originals = new WeakMap();
|
|
|
|
constructor({ themeApi } = {}) {
|
|
this.themeApi = themeApi ?? { motionAllowed: () => true };
|
|
}
|
|
|
|
applyTheme(node, theme) {
|
|
this.#restoreOriginals(node);
|
|
|
|
if (!theme || theme.id === "default") return;
|
|
|
|
this.#snapshotOriginals(node);
|
|
|
|
if (theme.staticConfig) {
|
|
for (const key of STATIC_KEYS) {
|
|
if (theme.staticConfig[key] !== undefined) {
|
|
node[key] = theme.staticConfig[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
const origFg = node.onDrawForeground;
|
|
if (theme.drawForeground) {
|
|
node.onDrawForeground = function (ctx) {
|
|
if (origFg) origFg.call(this, ctx);
|
|
theme.drawForeground.call(this, ctx, this, theme.themeApi);
|
|
};
|
|
}
|
|
|
|
const origBg = node.onDrawBackground;
|
|
if (theme.drawBackground) {
|
|
node.onDrawBackground = function (ctx) {
|
|
if (origBg) origBg.call(this, ctx);
|
|
theme.drawBackground.call(this, ctx, this, theme.themeApi);
|
|
};
|
|
}
|
|
|
|
if (node.setDirtyCanvas) node.setDirtyCanvas(true, true);
|
|
}
|
|
|
|
#snapshotOriginals(node) {
|
|
if (this.#originals.has(node)) return;
|
|
const snap = {
|
|
onDrawForeground: node.onDrawForeground,
|
|
onDrawBackground: node.onDrawBackground,
|
|
};
|
|
for (const key of STATIC_KEYS) snap[key] = node[key];
|
|
this.#originals.set(node, snap);
|
|
}
|
|
|
|
#restoreOriginals(node) {
|
|
const snap = this.#originals.get(node);
|
|
if (!snap) return;
|
|
for (const key of STATIC_KEYS) node[key] = snap[key];
|
|
node.onDrawForeground = snap.onDrawForeground;
|
|
node.onDrawBackground = snap.onDrawBackground;
|
|
this.#originals.delete(node);
|
|
if (node.setDirtyCanvas) node.setDirtyCanvas(true, true);
|
|
}
|
|
}
|