Fix findUsages/undo/node-lookup bugs, split Viewport and Editor, share command and inspector helpers

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Opus 5 committed 2026-09-08 09:22:49 +02:00
1 parent 1eb28314cf
commit f140c2fd77
58 files changed
+1969 -1171

No files matched your search

+44
View File
@@ -0,0 +1,44 @@
import { type PropertyBag, type PropertyValue, setBagValue } from '../model/Properties';
import type { Project } from '../model/Project';
import type { Command } from './Command';
/**
* The skeleton every "write one key into a property bag" edit shares: remember what the bag
* held, write the new value, put the old one back on undo. A key that is not in the bag is
* `undefined` on both ends – as a `computeNext` result it removes the key (this is how
* clearing an override works), and as remembered value it makes undo remove it again.
*
* Subclasses look their target up on every call instead of holding on to it, so an undo whose
* target is gone fails with a `CommandError` instead of writing into an orphaned object.
*/
export abstract class SetBagValueCommand<T> implements Command {
readonly label: string;
private previous: PropertyValue | undefined;
protected constructor(protected readonly key: string, label: string) {
this.label = label;
}
/** Throws a `CommandError` when the target does not exist. */
protected abstract resolveTarget(project: Project): T;
protected abstract bagOf(target: T): PropertyBag;
/**
* The value to write, `undefined` to remove the key. Called before anything is mutated, so
* this is where a subclass rejects an invalid edit (an unknown property key, say).
*/
protected abstract computeNext(target: T, project: Project): PropertyValue | undefined;
execute(project: Project): void {
const target = this.resolveTarget(project);
const bag = this.bagOf(target);
const next = this.computeNext(target, project);
this.previous = bag[this.key];
setBagValue(bag, this.key, next);
}
undo(project: Project): void {
setBagValue(this.bagOf(this.resolveTarget(project)), this.key, this.previous);
}
}