vizia_core/views/
toggle_button.rs

1use crate::prelude::*;
2
3/// A button which can be toggled between two states.
4pub struct ToggleButton {
5    on_toggle: Option<Box<dyn Fn(&mut EventContext)>>,
6}
7
8impl ToggleButton {
9    /// Create a new [ToggleButton] view.
10    pub fn new<V: View>(
11        cx: &mut Context,
12        lens: impl Lens<Target = bool>,
13        content: impl Fn(&mut Context) -> Handle<V> + 'static,
14    ) -> Handle<Self> {
15        Self { on_toggle: None }
16            .build(cx, |cx| {
17                (content)(cx).hoverable(false);
18            })
19            .role(Role::Button)
20            .navigable(true)
21            .checkable(true) // To let the accesskit know button is toggleable
22            .checked(lens)
23    }
24}
25
26impl View for ToggleButton {
27    fn element(&self) -> Option<&'static str> {
28        Some("toggle-button")
29    }
30
31    fn event(&mut self, cx: &mut EventContext, event: &mut Event) {
32        event.map(|window_event, meta| match window_event {
33            WindowEvent::PressDown { mouse } => {
34                if *mouse {
35                    cx.capture()
36                }
37                cx.focus();
38            }
39
40            WindowEvent::Press { mouse } => {
41                let over = if *mouse { cx.mouse().left.pressed } else { cx.focused() };
42                if over == cx.current() && meta.target == cx.current() && !cx.is_disabled() {
43                    if let Some(callback) = &self.on_toggle {
44                        (callback)(cx);
45                    }
46                }
47            }
48
49            WindowEvent::MouseUp(button) if *button == MouseButton::Left => {
50                cx.release();
51            }
52
53            WindowEvent::ActionRequest(action) => match action.action {
54                Action::Click => {
55                    if let Some(callback) = &self.on_toggle {
56                        (callback)(cx);
57                    }
58                }
59
60                _ => {}
61            },
62
63            _ => {}
64        });
65    }
66}
67
68impl Handle<'_, ToggleButton> {
69    /// Sets the callback triggered when the [ToggleButton] is toggled.
70    pub fn on_toggle(self, callback: impl Fn(&mut EventContext) + 'static) -> Self {
71        self.modify(|toggle_button| toggle_button.on_toggle = Some(Box::new(callback)))
72    }
73}