1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! Keeping animation state in step with the signals it mirrors.
//!
//! An [`AnimationState`] is a **cache of signal-derived state**: it holds a
//! target computed from a signal (plus whatever the active state layer
//! overrides) and interpolates toward it. A cache like that is only correct if
//! it is both
//!
//! 1. **subscribed from the moment it exists**, so no write can slip past
//! before anyone is listening, and
//! 2. **reconciled against the live value at every use**, so a target reached
//! through a branch nobody tracked still converges.
//!
//! Neither half is sufficient on its own, and both failure modes have been
//! shipped: a menu whose open-flip timer fired between its first layout and a
//! heavy first paint stayed collapsed forever (no subscription yet), and a
//! transform whose target moved through a conditional closure branch sat on
//! the stale value (subscribed, but to the branch not taken).
//!
//! Three passes are where that invariant lives, and two of them are emitted
//! from the table in `animated_properties.rs`, a row at a time:
//!
//! - [`seed_animations`] is (1): at the first layout, every declared animation
//! is read under Animation tracking so its subscription starts *now*. Widget
//! creation and first layout run in one synchronous block — for popups, the
//! measure-before-spawn — so nothing can land in between. It runs *before*
//! the measurement, not after: padding is a property a layout reads, and one
//! placed after `read_box_lengths` is a value that layout never saw. On the
//! popup path there is no later pass to repair that — the size is a return
//! value.
//! - [`resync_animation_targets`] is (2): every paint re-reads the targets
//! under tracking and asks for an Animation job when one has drifted, so
//! `advance_animations` adopts whatever the subscription missed.
//!
//! What is left here is the third, which is neither, and that is the point:
//! [`update_size_targets`] follows the measured content rather than a signal,
//! so a size's target is simply recomputed at every layout — by the one
//! formula that is the sizes' own. [`seed_or_enter`] is beside it, called from
//! the arm the table generates for each property, where the type it animates
//! is known.
//!
//! [`seed_animations`]: Container::seed_animations
//! [`resync_animation_targets`]: Container::resync_animation_targets
//! [`update_size_targets`]: Container::update_size_targets
use BoxLengths;
use *;
use crateLayoutCtx;
/// Start one animated property at the target just read for it, or begin the
/// enter it declared. Returns whether this frame started something, which is
/// what needs another frame after it.
///
/// Called from the arm the table generates for each property, which is where
/// the type it animates is known.
pub