Mark overrides in gold instead of bold, and up the hierarchy

An inspector label whose value deviates from its base was drawn bold, which is
easy to miss next to the regular labels and says nothing in the hierarchy, where
a folded subtree could hide a change entirely.

The colour now lives as a theme token (`override`, #f2c84b) used by both the
inspector labels and the hierarchy rows. Whether a row deviates is decided by
`src/core/properties/deviation.ts`: `objectDeviates` compares an object against
what it follows -- the container template for content, the asset otherwise --
and `deviationMarks` carries the mark up to every ancestor, so a folded subtree
still shows that something inside was changed.

`deviationMarks` takes the stored holder, not the resolved one: in the resolved
view container content looks like an ordinary object and `instanceTargetOf`
would compare against the asset, marking every instance.

Covered by 3 unit tests and 5 e2e checks, including one that strips an object's
own overrides to prove the row stays gold for a deviating child and restores
them byte for byte. Full suite remote on the RTX 4070: 275 checks, all passed.
This commit is contained in:
root committed 2026-09-09 10:54:25 +02:00
1 parent 37e1450fca
commit b87fcdfbad
13 files changed
+197 -14

No files matched your search

+7 -1
View File
@@ -1,4 +1,4 @@
import { Graphics, Text } from 'pixi.js';
import { Color, type ColorSource, Graphics, Text } from 'pixi.js';
import { drawControlBox } from '../draw';
import { centreY } from '../math';
import { Theme, textStyle } from '../Theme';
@@ -25,6 +25,7 @@ export class ListRow extends Widget {
super();
this.cursor = 'pointer';
this.minHeight = height;
if (item.overridden) this.labelText.style = textStyle('override');
this.addChild(this.bg, this.labelText, this.hint);
this.trackHover();
}
@@ -37,6 +38,11 @@ export class ListRow extends Widget {
this.invalidate();
}
/** Fill of the label as `#rrggbb` – tells a marked row from a plain one (test hook). */
get labelColor(): string {
return new Color(this.labelText.style.fill as ColorSource).toHex();
}
/** Left edge of the chevron slot (or of the content itself in a flat list). */
private get indent(): number {
return Theme.padding + (this.item.depth ?? 0) * Theme.treeIndent;
+7
View File
@@ -16,6 +16,8 @@ export interface ListItem {
swatch?: number;
/** Whether the subtree is shown; such rows get a chevron. Left undefined for leaves. */
expanded?: boolean;
/** Draws the label in the override colour – the row, or something inside it, deviates. */
overridden?: boolean;
}
/** Pixels of travel before a press turns into a drag. */
@@ -129,6 +131,11 @@ export class ListView extends Widget {
this.redraw();
}
/** Label colour of a row as `#rrggbb`; null when no such row is shown (test hook). */
rowColor(id: string): string | null {
return this.rows.find((r) => r.item.id === id)?.labelColor ?? null;
}
/** Global centre of a row's chevron; null when the row has none. */
chevronGlobal(id: string): { x: number; y: number } | null {
return this.rows.find((r) => r.item.id === id)?.chevronGlobal() ?? null;