@@ -24,9 +24,13 @@ use crate::kurbo::{BezPath, Rect, RoundedRect};
24
24
use crate :: piet:: { LinearGradient , RenderContext , UnitPoint } ;
25
25
26
26
use crate :: theme;
27
- use crate :: widget:: Align ;
28
27
use crate :: Point ;
29
28
29
+ // Delay until stepper starts automatically changing valued when one of the button is held down.
30
+ const STEPPER_REPEAT_DELAY : Duration = Duration :: from_millis ( 500 ) ;
31
+ // Delay between value changes when one of the button is held down.
32
+ const STEPPER_REPEAT : Duration = Duration :: from_millis ( 200 ) ;
33
+
30
34
/// A stepper widget for step-wise increasing and decreasing a value.
31
35
pub struct Stepper {
32
36
max : f64 ,
@@ -42,26 +46,37 @@ pub struct Stepper {
42
46
}
43
47
44
48
impl Stepper {
45
- pub fn new (
46
- max : f64 ,
47
- min : f64 ,
48
- step : f64 ,
49
- wrap : bool ,
50
- value_changed : impl Fn ( & mut EventCtx , & mut f64 , & Env ) + ' static ,
51
- ) -> impl Widget < f64 > {
52
- Align :: vertical (
53
- UnitPoint :: CENTER ,
54
- Stepper {
55
- max,
56
- min,
57
- step,
58
- wrap,
59
- value_changed : Box :: new ( value_changed) ,
60
- increase_active : false ,
61
- decrease_active : false ,
62
- timer_id : TimerToken :: INVALID ,
63
- } ,
64
- )
49
+ pub fn new ( value_changed : impl Fn ( & mut EventCtx , & mut f64 , & Env ) + ' static ) -> Self {
50
+ Stepper {
51
+ max : std:: f64:: MAX ,
52
+ min : std:: f64:: MIN ,
53
+ step : 1.0 ,
54
+ wrap : false ,
55
+ value_changed : Box :: new ( value_changed) ,
56
+ increase_active : false ,
57
+ decrease_active : false ,
58
+ timer_id : TimerToken :: INVALID ,
59
+ }
60
+ }
61
+
62
+ pub fn max ( mut self , max : f64 ) -> Self {
63
+ self . max = max;
64
+ self
65
+ }
66
+
67
+ pub fn min ( mut self , min : f64 ) -> Self {
68
+ self . min = min;
69
+ self
70
+ }
71
+
72
+ pub fn step ( mut self , step : f64 ) -> Self {
73
+ self . step = step;
74
+ self
75
+ }
76
+
77
+ pub fn wrap ( mut self , wrap : bool ) -> Self {
78
+ self . wrap = wrap;
79
+ self
65
80
}
66
81
67
82
fn change_value ( & mut self , ctx : & mut EventCtx , data : & mut f64 , env : & Env ) {
@@ -75,7 +90,7 @@ impl Stepper {
75
90
} ;
76
91
77
92
let old_data = * data;
78
- * data = ( * data + delta) . min ( self . min ) . max ( self . max ) ;
93
+ * data = ( * data + delta) . max ( self . min ) . min ( self . max ) ;
79
94
80
95
if ( * data - old_data) . abs ( ) > EPSILON {
81
96
// callback
@@ -136,19 +151,18 @@ impl Widget<f64> for Stepper {
136
151
} ;
137
152
138
153
// draw up and down triangles
139
- let mut increase_button_arrow = BezPath :: new ( ) ;
140
- increase_button_arrow. move_to ( Point :: new ( 4. , height / 2. - 4. ) ) ;
141
- increase_button_arrow. line_to ( Point :: new ( width - 4. , height / 2. - 4. ) ) ;
142
- increase_button_arrow. line_to ( Point :: new ( width / 2. , 4. ) ) ;
143
- increase_button_arrow. close_path ( ) ;
144
- paint_ctx. fill ( increase_button_arrow, & env. get ( theme:: LABEL_COLOR ) ) ;
145
-
146
- let mut decrease_button_arrow = BezPath :: new ( ) ;
147
- decrease_button_arrow. move_to ( Point :: new ( 4. , height / 2. + 4. ) ) ;
148
- decrease_button_arrow. line_to ( Point :: new ( width - 4. , height / 2. + 4. ) ) ;
149
- decrease_button_arrow. line_to ( Point :: new ( width / 2. , height - 4. ) ) ;
150
- decrease_button_arrow. close_path ( ) ;
151
- paint_ctx. fill ( decrease_button_arrow, & env. get ( theme:: LABEL_COLOR ) ) ;
154
+ let mut arrows = BezPath :: new ( ) ;
155
+ arrows. move_to ( Point :: new ( 4. , height / 2. - 4. ) ) ;
156
+ arrows. line_to ( Point :: new ( width - 4. , height / 2. - 4. ) ) ;
157
+ arrows. line_to ( Point :: new ( width / 2. , 4. ) ) ;
158
+ arrows. close_path ( ) ;
159
+
160
+ arrows. move_to ( Point :: new ( 4. , height / 2. + 4. ) ) ;
161
+ arrows. line_to ( Point :: new ( width - 4. , height / 2. + 4. ) ) ;
162
+ arrows. line_to ( Point :: new ( width / 2. , height - 4. ) ) ;
163
+ arrows. close_path ( ) ;
164
+
165
+ paint_ctx. fill ( arrows, & env. get ( theme:: LABEL_COLOR ) ) ;
152
166
}
153
167
154
168
fn layout (
@@ -179,7 +193,7 @@ impl Widget<f64> for Stepper {
179
193
180
194
self . change_value ( ctx, data, env) ;
181
195
182
- let delay = Instant :: now ( ) + Duration :: from_millis ( 500 ) ;
196
+ let delay = Instant :: now ( ) + STEPPER_REPEAT_DELAY ;
183
197
self . timer_id = ctx. request_timer ( delay) ;
184
198
185
199
ctx. invalidate ( ) ;
@@ -195,14 +209,19 @@ impl Widget<f64> for Stepper {
195
209
}
196
210
Event :: Timer ( id) if * id == self . timer_id => {
197
211
self . change_value ( ctx, data, env) ;
198
- let delay = Instant :: now ( ) + Duration :: from_millis ( 200 ) ;
212
+ let delay = Instant :: now ( ) + STEPPER_REPEAT ;
199
213
self . timer_id = ctx. request_timer ( delay) ;
200
214
}
201
215
_ => ( ) ,
202
216
}
203
217
}
204
218
205
- fn update ( & mut self , ctx : & mut UpdateCtx , _old_data : Option < & f64 > , _data : & f64 , _env : & Env ) {
206
- ctx. invalidate ( ) ;
219
+ fn update ( & mut self , ctx : & mut UpdateCtx , old_data : Option < & f64 > , data : & f64 , _env : & Env ) {
220
+ if old_data
221
+ . map ( |old_data| ( * data - old_data) . abs ( ) > EPSILON )
222
+ . unwrap_or ( true )
223
+ {
224
+ ctx. invalidate ( ) ;
225
+ }
207
226
}
208
227
}
0 commit comments