#[non_exhaustive]pub enum ItemChange {
Show 18 variants
LocalPosChanged {
id: ItemId,
old: Point,
new: Point,
},
LocalBoundsChanged {
id: ItemId,
old: Rect,
new: Rect,
},
MeasuredSizeChanged {
id: ItemId,
old: Rect,
new: Rect,
},
SizePolicyChanged {
id: ItemId,
old: SizePolicy,
new: SizePolicy,
},
TransformChanged {
id: ItemId,
old: Transform2D,
new: Transform2D,
},
VisibilityChanged {
id: ItemId,
visible: bool,
},
FlagsChanged {
id: ItemId,
old: ItemFlags,
new: ItemFlags,
},
OpacityChanged {
id: ItemId,
old: f32,
new: f32,
},
ZChanged {
id: ItemId,
old: f32,
new: f32,
},
LayerChanged {
id: ItemId,
old: SceneLayer,
new: SceneLayer,
},
ParentChanged {
id: ItemId,
old: Option<ItemId>,
new: Option<ItemId>,
},
Removed {
id: ItemId,
},
Added {
id: ItemId,
},
PayloadChanged {
id: ItemId,
old: ItemPayload,
new: ItemPayload,
},
AppearanceChanged {
id: ItemId,
change: AppearanceChange,
},
ItemReplaced {
id: ItemId,
old_bounds: Rect,
new_bounds: Rect,
},
PlacementChanged {
id: ItemId,
old: Placement,
new: Placement,
},
HandlersChanged {
id: ItemId,
replaced: Option<Box<HandlerReplacement>>,
},
}Expand description
A change to an item’s state, fired through
Scene::item_change_signal for every mutation. Apps observe to wire
validation, persistence, telemetry, mirroring to a data layer, and other
side effects. The model is “fire after the change has been applied” — by
the time the observer sees the event, the Scene already reflects it, and
(when the mutation came through a SceneModel) the
observer may freely read and write the scene back.
§Edits and derived notifications
Most variants are edits: one mutation, one variant, both sides of the
value it replaced, and SceneTransactionRecord::edits
carries them so a data layer can invert the transaction by walking them in
reverse.
VisibilityChanged is not one. It is a
derived notification — a convenience beside the
FlagsChanged that actually describes the mutation,
emitted by both flag doors whenever IS_VISIBLE flips so a consumer need
not diff two bitsets. It rides the signal and stays out of the record, so
hiding a card is one edit whichever door hid it.
is_edit is the test, for a consumer that counts changes
off the signal and wants the same number the record has.
#[non_exhaustive]: this is the crate’s outbound event vocabulary, matched
by every observer, and it grows whenever the scene learns to report
something new — MeasuredSizeChanged and SizePolicyChanged are the most
recent. Without the attribute each such addition would stop a downstream
match from compiling; with it, a consumer’s wildcard arm keeps meaning
“a change I do not act on”.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
LocalPosChanged
set_local_pos: position in parent coords moved.
LocalBoundsChanged
set_local_bounds: AABB in local coords changed.
MeasuredSizeChanged
set_measured_size: a derived geometry write — the size an entry
under a non-Fixed
SizePolicy measured from its widget, or one an
app computed from content it already owns.
Separate from LocalBoundsChanged because
it means something different to every consumer of the channel:
- It is not an edit.
is_editisfalseand the change is stampedephemeral, so a history above the scene does not gain an undo step because a paragraph re-wrapped. A reflow is a function of content the document already holds; undoing it would mean undoing the width or the words. - It is not structural. It is counted out of
Scene::structural_version, the wayrefresh_dynamic_bounds’s per-frame churn is, so a line wrap does not buy an AccessKit re-walk. - The observing
SceneViewanswers it with a relayout, not a rebuild: the geometry moved, nothing was materialised or reaped, and the delegate does not need re-running.
An app mirroring scene geometry into its document should match
LocalBoundsChanged and ignore this one. An app that wants the measured
height persisted anyway (so a cold start opens at the right size without
waiting for a measurement) can read it and store it as a hint.
Fields
old: RectIts AABB in local coordinates before the write.
new: RectIts AABB now. Same origin; the size is what moved.
SizePolicyChanged
set_size_policy: who decides this entry’s box changed.
An edit, unlike the MeasuredSizeChanged
that follows it: “this note’s height follows its words” is a decision
someone made about the document, the way a flag change is, and a history
above the scene should be able to put it back.
It carries no geometry — the policy decides how the next layout pass computes one. It exists at all because nothing else would tell a view that the answer to a question it asks every pass has changed: a policy written silently would take effect whenever something unrelated happened to dirty the view, which in a test is never and in an app is worse — unpredictable.
TransformChanged
set_transform: local→parent transform changed.
Fields
old: Transform2DIts local→parent transform before the write.
new: Transform2DIts local→parent transform now.
VisibilityChanged
IS_VISIBLE flipped, by whichever door flipped it — set_visible,
set_flag or a wholesale set_flags.
A derived notification, always emitted immediately before the
FlagsChanged that describes the same mutation.
It exists so a consumer that only cares about visibility need not diff
two ItemFlags bitsets, and it is deliberately not an edit:
is_edit is false for it and it never reaches a
transaction record, so one mutation is one recorded edit no matter which
door made it. (It used to be emitted by set_flag and not by
set_flags, which made hiding a card two recorded changes through one
door and one through the other.)
Fields
visible: boolThe bit’s new value. Its own value, not the inherited one —
Scene::is_effectively_visible chains the parents.
FlagsChanged
set_flags / set_flag changed the bitset. The edit that describes a
flag change, visibility included.
Fields
OpacityChanged
set_opacity: local opacity multiplier changed.
Fields
ZChanged
set_z: paint z-order changed.
Fields
LayerChanged
set_layer: the Under/Over paint band changed.
ParentChanged
set_item_parent: logical parent changed.
Fields
Removed
remove: item is gone.
Fields
id: ItemIdThe item that is gone. Its contents travel the owning channel:
Scene::take hands the caller a RemovedItem,
and Scene::remove routes one to the edit sink.
Added
add_item / add_widget: item was inserted.
PayloadChanged
set_payload: the type-erased payload of a Delegated heavyweight
entry was replaced. A SceneView rebuilds that entry’s widget
(re-invokes its delegate) on the next build. Routed through
emit_item_change, so mutation_seq advances and the AT-walk gate
notices.
Fields
old: ItemPayloadThe payload every view built its widget from until now.
new: ItemPayloadThe payload every view will rebuild from.
AppearanceChanged
set_item_fill / set_item_stroke / clear_item_*: a lightweight
item’s paint-only appearance (fill / stroke colour or style) changed.
Never moves geometry, so the observing SceneView evicts the item’s
cached frame and repaints without relayout or rebuild.
It can move the item’s hit shape, though: a stroked
PathItem derives its hit band from the stroke it
draws, so a view caching hit geometry must re-read this item’s shape
even while skipping relayout.
Fields
change: AppearanceChangeWhich of fill or stroke moved, and to what.
ItemReplaced
replace_item: the lightweight item box at this id was swapped for a
different one, keeping the entry — position, transform, z, layer,
parent, flags, opacity, handlers, magnets and logical-AT decorations
all survive, and so does the ItemId.
One change, not Removed + Added, because nothing about the item’s
identity changed. Consumers must treat it as a geometry change: the
new item carries its own local_bounds and its own hit shape.
old_bounds / new_bounds are the entry’s AABB either side of the
swap; the replaced box itself is returned to whoever called
Scene::replace_item.
Fields
old_bounds: RectThe entry’s AABB before the swap.
new_bounds: RectThe entry’s AABB after it, carried by the new box.
PlacementChanged
set_placement: parent, z, local position and transform written
together as one property.
The atomic form of the four separate mutators. A visually-stable
reparent (“drag this card into that group”) is one edit here, where
set_item_parent + set_local_pos + set_transform is three edits,
three undo steps, and two intermediate states in which the item is
visibly in the wrong place.
Fields
HandlersChanged
set_item_handlers / handlers_mut: the item’s handler set was
replaced or handed out for mutation.
Always means at least “this item’s handlers are no longer what you last
read”, which is what a consumer caching them — the SceneView’s
dispatch snapshot — needs. Without it, the two handler mutators were the
only doors in the model that changed observable state silently.
Whether it also describes the change is
replaced; see
HandlerReplacement.
Fields
replaced: Option<Box<HandlerReplacement>>Both sides, when the door that fired this knew them.
Some from Scene::set_item_handlers, which is handed the new
set and can clone the old one out — so that door produces a
reversible edit like every other mutator.
None from Scene::handlers_mut, which fires on the way in: a
&mut borrow cannot report what the caller will do with it, and
there is no later moment the scene is told about. That call is an
invalidation notice and nothing finer, so it is not recorded as
an edit — a record claiming to carry both sides must not carry an
entry that carries neither. An app that wants its handler edits in
the history makes them through set_item_handlers.
Boxed because a SceneItemHandlerSet is a wide struct and this is
the rarest variant: inline, two of them would set the size of every
ItemChange, every SceneChange and every
queued notification — a per-pointer-sample cost for a setup-time
call.
Implementations§
Source§impl ItemChange
impl ItemChange
Sourcepub fn id(&self) -> ItemId
pub fn id(&self) -> ItemId
The item this change is about.
Every variant names exactly one item, so an observer that only needs
which item moved need not match the whole enum. The fan-out’s runaway
detector reads it too: it charges each delivery to the subject it is
about, so it needs that subject without caring what kind of change it
is. (Those per-subject counts name the culprit in the panic; the bound
that trips is a flat total — see CascadeBudget.)
Sourcepub fn is_edit(&self) -> bool
pub fn is_edit(&self) -> bool
Whether this change is an edit — a mutation a transaction record carries — rather than a derived notification the scene emits beside one for a consumer’s convenience.
Three variants are not edits:
VisibilityChanged, which always accompanies theFlagsChangedthat describes the same mutation.HandlersChangedwith noreplaced— thehandlers_mutdoor, which cannot say what the handlers became.MeasuredSizeChanged, which is a size derived from content the document already holds, not a change to it.
Filtering the change signal by this gives the same count the
transaction record has, which is what an app showing “N changes in this
edit” needs: hiding a card is one change through
Scene::set_visible and one through Scene::set_flags.
Trait Implementations§
Source§impl Clone for ItemChange
impl Clone for ItemChange
Source§fn clone(&self) -> ItemChange
fn clone(&self) -> ItemChange
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for ItemChange
impl !Send for ItemChange
impl !Sync for ItemChange
impl !UnwindSafe for ItemChange
impl Freeze for ItemChange
impl Unpin for ItemChange
impl UnsafeUnpin for ItemChange
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.impl<T> ErasedDestructor for Twhere
T: 'static,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more