@@ -63,16 +63,16 @@ enum DragTrackInput {
6363/// changes, like [MotionModel] ); dragging it writes the variable, so
6464/// everything bound to the variable follows, and changing the variable
6565/// elsewhere moves the node. Double tap resets to [defaultValue] , the mouse
66- /// wheel steps the value.
66+ /// wheel and the arrow keys (see [keyboard] ) step the value.
6767///
6868/// Positions are in logical pixels relative to where the node is laid out:
6969/// a fader cap laid out at the bottom of its slot has `y2: -250` for a
7070/// 250px throw. Angles are in degrees, clockwise, 0 pointing up.
7171///
7272/// While dragged, the node and its children read `${track.value}` ,
73- /// `${track.progress}` (0 to 1) and `${track.dragging}` . Each change runs
74- /// the node's `changed` reactions with `${result.value}` ; letting go runs
75- /// its `dragEnd` reactions.
73+ /// `${track.progress}` (0 to 1), `${track.dragging}` and
74+ /// `${track.focused}` . Each change runs the node's `changed` reactions with
75+ /// `${result.value}` ; letting go runs its `dragEnd` reactions.
7676@JsonSerializable ()
7777class DragTrackModel with Equatable , SerializableMixin {
7878 /// The track's geometry.
@@ -140,8 +140,11 @@ class DragTrackModel with Equatable, SerializableMixin {
140140 /// For a path: turn the node to follow the path's direction.
141141 final bool orientToPath;
142142
143- /// Tapping the node's parent anywhere along the track moves the node
144- /// there (a fader cap jumps to where its slot was tapped). Only for
143+ /// Tapping anywhere along the track moves the node there, then the drag
144+ /// goes on from there: a fader cap jumps to where its slot was tapped
145+ /// (the nearest point of a line or path), a dial to the angle tapped
146+ /// around its pivot, anywhere within the circle the node sweeps (the
147+ /// nearest valid value, snapped to [step] ). Only for
145148 /// [DragTrackInput.follow] .
146149 final bool jumpOnTap;
147150
@@ -172,6 +175,28 @@ class DragTrackModel with Equatable, SerializableMixin {
172175 /// physics and ignores [settleMs] for its length.
173176 final MotionCurve settleCurve;
174177
178+ /// Where the node is parked while the variable is outside the range
179+ /// (below [min] , above [max] ) or empty or not a number, as a progress
180+ /// along the track that may lie outside 0 to 1: an unrated 1 to 5 dial
181+ /// over -120..120 degrees parks its knob at -150 degrees with -0.125.
182+ /// Lines and arcs go on past their ends; a path stops at its ends. Null
183+ /// (the default) draws such a value at the nearest end.
184+ ///
185+ /// Dragging a parked node starts from the nearest end, and the node
186+ /// glides ([settleMs] ) between its parked place and the track. While
187+ /// parked, `${track.progress}` reads this progress.
188+ final double ? parkedProgress;
189+
190+ /// Whether the track takes keyboard focus (tapping or dragging it
191+ /// focuses it, Tab reaches it) and the keys move it while focused: the
192+ /// right and up arrows step the value up by [step] (1% of the range
193+ /// without one), left and down step it down, Page Up and Page Down by 10
194+ /// steps, Home to [min] and End to [max] . Each key runs the node's
195+ /// `changed` reactions like a drag. On by default; `${track.focused}`
196+ /// tells whether it has focus, for a node to draw its own focus ring.
197+ /// The track is a slider to screen readers either way.
198+ final bool keyboard;
199+
175200 /// Creates a [DragTrackModel] .
176201 const DragTrackModel ({
177202 this .shape = DragTrackShape .line,
@@ -199,10 +224,17 @@ class DragTrackModel with Equatable, SerializableMixin {
199224 this .overscroll = 0 ,
200225 this .settleMs = 0 ,
201226 this .settleCurve = MotionCurve .easeOutCubic,
227+ this .parkedProgress,
228+ this .keyboard = true ,
202229 });
203230
204231 /// The names of the live values the `track` variable has.
205- static const List <String > liveValues = ['value' , 'progress' , 'dragging' ];
232+ static const List <String > liveValues = [
233+ 'value' ,
234+ 'progress' ,
235+ 'dragging' ,
236+ 'focused' ,
237+ ];
206238
207239 /// The names of the values a `dragEnd` reaction gets in `${result}` :
208240 /// the final `value` , the `startValue` the drag began at, and the
@@ -217,8 +249,24 @@ class DragTrackModel with Equatable, SerializableMixin {
217249 return ((value - min) / (max - min)).clamp (0.0 , 1.0 );
218250 }
219251
252+ /// Whether [value] is drawn at [parkedProgress] : outside the range or not
253+ /// a number (NaN stands for an empty variable), when the track has one.
254+ bool isParked (double value) {
255+ if (parkedProgress == null ) return false ;
256+ if (value.isNaN) return true ;
257+ final double lo = min < max ? min : max;
258+ final double hi = min < max ? max : min;
259+ return value < lo || value > hi;
260+ }
261+
262+ /// Where the node is drawn for [value] : its [progressOf] , or
263+ /// [parkedProgress] when [isParked] .
264+ double restProgressOf (double value) =>
265+ isParked (value) ? parkedProgress! : (value.isNaN ? 0 : progressOf (value));
266+
220267 /// The value at [progress] along the track, snapped to [step] .
221- double valueAt (double progress) => snap (min + (max - min) * progress.clamp (0.0 , 1.0 ));
268+ double valueAt (double progress) =>
269+ snap (min + (max - min) * progress.clamp (0.0 , 1.0 ));
222270
223271 /// [value] snapped to [step] (counted from [min] ) and kept in range.
224272 double snap (double value) {
@@ -234,7 +282,7 @@ class DragTrackModel with Equatable, SerializableMixin {
234282 return v;
235283 }
236284
237- /// How far one wheel notch moves the value.
285+ /// How far one wheel notch (or one arrow key) moves the value.
238286 double get wheelStep => step > 0 ? step : (max - min).abs () / 100 ;
239287
240288 /// The rotation of an arc at [progress] , in degrees.
@@ -269,6 +317,9 @@ class DragTrackModel with Equatable, SerializableMixin {
269317 double ? overscroll,
270318 int ? settleMs,
271319 MotionCurve ? settleCurve,
320+ double ? parkedProgress,
321+ bool clearParked = false ,
322+ bool ? keyboard,
272323 }) => DragTrackModel (
273324 shape: shape ?? this .shape,
274325 variable: variable ?? this .variable,
@@ -295,6 +346,10 @@ class DragTrackModel with Equatable, SerializableMixin {
295346 overscroll: overscroll ?? this .overscroll,
296347 settleMs: settleMs ?? this .settleMs,
297348 settleCurve: settleCurve ?? this .settleCurve,
349+ parkedProgress: clearParked
350+ ? null
351+ : (parkedProgress ?? this .parkedProgress),
352+ keyboard: keyboard ?? this .keyboard,
298353 );
299354
300355 @override
@@ -324,6 +379,8 @@ class DragTrackModel with Equatable, SerializableMixin {
324379 overscroll,
325380 settleMs,
326381 settleCurve,
382+ parkedProgress,
383+ keyboard,
327384 ];
328385
329386 /// Creates a [DragTrackModel] from JSON.
0 commit comments