vizia_core/views/
spinbox.rs
1use crate::icons::{
2 ICON_CHEVRON_DOWN, ICON_CHEVRON_LEFT, ICON_CHEVRON_RIGHT, ICON_CHEVRON_UP, ICON_MINUS,
3 ICON_PLUS,
4};
5use crate::prelude::*;
6
7pub(crate) enum SpinboxEvent {
8 Increment,
9 Decrement,
10}
11
12#[derive(Lens)]
14pub struct Spinbox {
15 orientation: Orientation,
16 icons: SpinboxIcons,
17
18 on_decrement: Option<Box<dyn Fn(&mut EventContext) + Send + Sync>>,
19 on_increment: Option<Box<dyn Fn(&mut EventContext) + Send + Sync>>,
20}
21
22#[derive(Clone, Copy, Debug, PartialEq, Data)]
24pub enum SpinboxIcons {
25 PlusMinus,
27 Chevrons,
29}
30
31impl_res_simple!(SpinboxIcons);
32
33impl Spinbox {
34 pub fn new<L>(cx: &mut Context, lens: L) -> Handle<Spinbox>
36 where
37 L: Lens<Target: Data + ToStringLocalized>,
38 {
39 Self::custom(cx, move |cx| Label::new(cx, lens))
40 }
41
42 pub fn custom<F, V>(cx: &mut Context, content: F) -> Handle<Spinbox>
44 where
45 F: Fn(&mut Context) -> Handle<V>,
46 V: 'static + View,
47 {
48 Self {
49 orientation: Orientation::Horizontal,
50 icons: SpinboxIcons::Chevrons,
51 on_decrement: None,
52 on_increment: None,
53 }
54 .build(cx, move |cx| {
55 Binding::new(cx, Spinbox::orientation, move |cx, spinbox_kind| {
56 match spinbox_kind.get(cx) {
57 Orientation::Horizontal => {
58 Button::new(cx, |cx| {
59 Svg::new(
60 cx,
61 Spinbox::icons.map(|icons| match icons {
62 SpinboxIcons::PlusMinus => ICON_MINUS,
63 SpinboxIcons::Chevrons => ICON_CHEVRON_LEFT,
64 }),
65 )
66 })
67 .on_press(|ex| ex.emit(SpinboxEvent::Decrement))
68 .navigable(true)
69 .class("spinbox-button");
70 }
71
72 Orientation::Vertical => {
73 Button::new(cx, |cx| {
74 Svg::new(
75 cx,
76 Spinbox::icons.map(|icons| match icons {
77 SpinboxIcons::PlusMinus => ICON_PLUS,
78 SpinboxIcons::Chevrons => ICON_CHEVRON_UP,
79 }),
80 )
81 })
82 .on_press(|ex| ex.emit(SpinboxEvent::Increment))
83 .navigable(true)
84 .class("spinbox-button");
85 }
86 }
87 });
88 (content)(cx).class("spinbox-value");
89 Binding::new(cx, Spinbox::orientation, move |cx, spinbox_kind| {
90 match spinbox_kind.get(cx) {
91 Orientation::Horizontal => {
92 Button::new(cx, |cx| {
93 Svg::new(
94 cx,
95 Spinbox::icons.map(|icons| match icons {
96 SpinboxIcons::PlusMinus => ICON_PLUS,
97 SpinboxIcons::Chevrons => ICON_CHEVRON_RIGHT,
98 }),
99 )
100 })
101 .on_press(|ex| ex.emit(SpinboxEvent::Increment))
102 .navigable(true)
103 .class("spinbox-button");
104 }
105
106 Orientation::Vertical => {
107 Button::new(cx, |cx| {
108 Svg::new(
109 cx,
110 Spinbox::icons.map(|icons| match icons {
111 SpinboxIcons::PlusMinus => ICON_MINUS,
112 SpinboxIcons::Chevrons => ICON_CHEVRON_DOWN,
113 }),
114 )
115 })
116 .on_press(|ex| ex.emit(SpinboxEvent::Decrement))
117 .navigable(true)
118 .class("spinbox-button");
119 }
120 }
121 });
122 })
123 .toggle_class("horizontal", Spinbox::orientation.map(|o| o == &Orientation::Horizontal))
124 .toggle_class("vertical", Spinbox::orientation.map(|o| o == &Orientation::Vertical))
125 .navigable(true)
126 }
127}
128
129impl Handle<'_, Spinbox> {
130 pub fn on_increment<F>(self, callback: F) -> Self
132 where
133 F: 'static + Fn(&mut EventContext) + Send + Sync,
134 {
135 self.modify(|spinbox: &mut Spinbox| spinbox.on_increment = Some(Box::new(callback)))
136 }
137
138 pub fn on_decrement<F>(self, callback: F) -> Self
140 where
141 F: 'static + Fn(&mut EventContext) + Send + Sync,
142 {
143 self.modify(|spinbox: &mut Spinbox| spinbox.on_decrement = Some(Box::new(callback)))
144 }
145
146 pub fn orientation(self, orientation: impl Res<Orientation>) -> Self {
148 self.bind(orientation, move |handle, orientation| {
149 let orientation = orientation.get(&handle);
150 handle.modify(move |spinbox| spinbox.orientation = orientation);
151 })
152 }
153
154 pub fn icons(self, icons: impl Res<SpinboxIcons>) -> Self {
156 self.bind(icons, move |handle, icons| {
157 let icons = icons.get(&handle);
158 handle.modify(move |spinbox| spinbox.icons = icons);
159 })
160 }
161}
162
163impl View for Spinbox {
164 fn element(&self) -> Option<&'static str> {
165 Some("spinbox")
166 }
167
168 fn event(&mut self, cx: &mut EventContext, event: &mut Event) {
169 event.map(|spinbox_event, _| match spinbox_event {
170 SpinboxEvent::Increment => {
171 if let Some(callback) = &self.on_increment {
172 (callback)(cx)
173 }
174 }
175
176 SpinboxEvent::Decrement => {
177 if let Some(callback) = &self.on_decrement {
178 (callback)(cx)
179 }
180 }
181 });
182 }
183}