numeric_stepper.rs

 1use gpui::ClickEvent;
 2
 3use crate::{prelude::*, IconButtonShape};
 4
 5#[derive(IntoElement)]
 6pub struct NumericStepper {
 7    value: SharedString,
 8    on_decrement: Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
 9    on_increment: Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
10    on_reset: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
11}
12
13impl NumericStepper {
14    pub fn new(
15        value: impl Into<SharedString>,
16        on_decrement: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
17        on_increment: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
18    ) -> Self {
19        Self {
20            value: value.into(),
21            on_decrement: Box::new(on_decrement),
22            on_increment: Box::new(on_increment),
23            on_reset: None,
24        }
25    }
26
27    pub fn on_reset(
28        mut self,
29        on_reset: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
30    ) -> Self {
31        self.on_reset = Some(Box::new(on_reset));
32        self
33    }
34}
35
36impl RenderOnce for NumericStepper {
37    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
38        let shape = IconButtonShape::Square;
39        let icon_size = IconSize::Small;
40
41        h_flex()
42            .gap_1()
43            .map(|element| {
44                if let Some(on_reset) = self.on_reset {
45                    element.child(
46                        IconButton::new("reset", IconName::RotateCcw)
47                            .shape(shape)
48                            .icon_size(icon_size)
49                            .on_click(on_reset),
50                    )
51                } else {
52                    element.child(
53                        h_flex()
54                            .size(icon_size.square(cx))
55                            .flex_none()
56                            .into_any_element(),
57                    )
58                }
59            })
60            .child(
61                h_flex()
62                    .gap_1()
63                    .px_1()
64                    .rounded_sm()
65                    .bg(cx.theme().colors().editor_background)
66                    .child(
67                        IconButton::new("decrement", IconName::Dash)
68                            .shape(shape)
69                            .icon_size(icon_size)
70                            .on_click(self.on_decrement),
71                    )
72                    .child(Label::new(self.value))
73                    .child(
74                        IconButton::new("increment", IconName::Plus)
75                            .shape(shape)
76                            .icon_size(icon_size)
77                            .on_click(self.on_increment),
78                    ),
79            )
80    }
81}