Skip to content

Commit 8797365

Browse files
committed
Incroporate review feedback into stepper widget
1 parent 3b64ecf commit 8797365

File tree

2 files changed

+65
-42
lines changed

2 files changed

+65
-42
lines changed

druid/examples/switch.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use druid::widget::{Flex, Label, Padding, Parse, Stepper, Switch, TextBox};
15+
use druid::widget::{Align, Flex, Label, Padding, Parse, Stepper, Switch, TextBox};
1616
use druid::{AppLauncher, Data, Lens, LensExt, LensWrap, Widget, WindowDesc};
1717

1818
#[derive(Clone, Data, Lens)]
@@ -31,7 +31,11 @@ fn build_widget() -> impl Widget<DemoState> {
3131
row.add_child(Padding::new(5.0, switch), 0.0);
3232

3333
let stepper = LensWrap::new(
34-
Stepper::new(0.0, 10.0, 0.25, true, |_ctx, _data, _env| {}),
34+
Stepper::new(|_ctx, _data, _env| {})
35+
.max(10.0)
36+
.min(0.0)
37+
.step(0.5)
38+
.wrap(false),
3539
DemoState::stepper_value,
3640
);
3741

@@ -41,7 +45,7 @@ fn build_widget() -> impl Widget<DemoState> {
4145
DemoState::stepper_value.map(|x| Some(*x), |x, y| *x = y.unwrap_or(0.0)),
4246
);
4347
textbox_row.add_child(Padding::new(5.0, textbox), 0.0);
44-
textbox_row.add_child(Padding::new(5.0, stepper), 0.0);
48+
textbox_row.add_child(Padding::new(5.0, Align::centered(stepper)), 0.0);
4549

4650
let mut label_row = Flex::row();
4751

druid/src/widget/stepper.rs

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ use crate::kurbo::{BezPath, Rect, RoundedRect};
2424
use crate::piet::{LinearGradient, RenderContext, UnitPoint};
2525

2626
use crate::theme;
27-
use crate::widget::Align;
2827
use crate::Point;
2928

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+
3034
/// A stepper widget for step-wise increasing and decreasing a value.
3135
pub struct Stepper {
3236
max: f64,
@@ -42,26 +46,37 @@ pub struct Stepper {
4246
}
4347

4448
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
6580
}
6681

6782
fn change_value(&mut self, ctx: &mut EventCtx, data: &mut f64, env: &Env) {
@@ -75,7 +90,7 @@ impl Stepper {
7590
};
7691

7792
let old_data = *data;
78-
*data = (*data + delta).min(self.min).max(self.max);
93+
*data = (*data + delta).max(self.min).min(self.max);
7994

8095
if (*data - old_data).abs() > EPSILON {
8196
// callback
@@ -136,19 +151,18 @@ impl Widget<f64> for Stepper {
136151
};
137152

138153
// 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));
152166
}
153167

154168
fn layout(
@@ -179,7 +193,7 @@ impl Widget<f64> for Stepper {
179193

180194
self.change_value(ctx, data, env);
181195

182-
let delay = Instant::now() + Duration::from_millis(500);
196+
let delay = Instant::now() + STEPPER_REPEAT_DELAY;
183197
self.timer_id = ctx.request_timer(delay);
184198

185199
ctx.invalidate();
@@ -195,14 +209,19 @@ impl Widget<f64> for Stepper {
195209
}
196210
Event::Timer(id) if *id == self.timer_id => {
197211
self.change_value(ctx, data, env);
198-
let delay = Instant::now() + Duration::from_millis(200);
212+
let delay = Instant::now() + STEPPER_REPEAT;
199213
self.timer_id = ctx.request_timer(delay);
200214
}
201215
_ => (),
202216
}
203217
}
204218

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+
}
207226
}
208227
}

0 commit comments

Comments
 (0)