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