Tryst::UI::Var
A reactive Tcl variable, wrapped for Crystal - Tk's own native -textvariable/-variable machinery, done properly instead of a hand-rolled "constant name + manual set/get_variable" pattern. Widgets bound to the same Var stay in sync with each other for free (entirely Tk's own doing); this class adds typed Crystal access and an on_change callback on top.
Its Tcl variable name is allocated at build time (see WidgetDSL#var) - a plain string, no interpreter needed - so widgets can capture it as a bind_option (-variable/-textvariable) before realize even happens. The variable itself, its initial value, and its change trace only become real at #realize.
Holds @app as the concrete Tryst::App, not AppContract - unlike Realizer/Handle, nothing routes Var construction through a FakeApp-substitutable path (Session#realize calls #realize with its own freshly-constructed real App directly), and get_variable/ set_variable/register_callback/tcl_eval have no other AppContract consumer to justify widening that interface for.
Constructors
Instance methods
Remove every #on_change handler at once - the counterpart to #on_change accumulating one entry per call, for a Var that's re-subscribed without ever being destroyed and rebuilt.
Register a callback fired whenever the value changes, regardless of whether Crystal (#value=) or a bound widget caused it. Queues regardless of build/realize phase - there's only ever one underlying Tcl trace per Var, wired once at realize, so callbacks added later just join the same list.
Create the backing Tcl variable, set its initial value, and wire the change trace. Called once by Session#realize, before the widget tree realizes, so bound widgets display the initial value from the moment they're created rather than starting blank.
Tear down the backing Tcl variable, its write trace, and the callback that trace fires - called by Handle#destroy! for a subtree that owns this var (see Node#vars). Safe to call more than once, and safe to call before #realize (nothing to tear down yet).
The current value, coerced to match the initial value's type (Int32/Float64/Bool pass through typed; anything else is a String). Raises NotRealizedError before realize.