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