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