Skip to main content

truce_iced/widgets/
toggle.rs

1//! Toggle switch widget wrapping iced's toggler.
2
3use std::fmt::Debug;
4use std::marker::PhantomData;
5
6use iced::Element;
7use iced::widget::{column, text, toggler};
8
9use crate::param_cache::ParamCache;
10use crate::param_message::{Message, ParamMessage};
11use crate::theme;
12use truce_params::Params;
13
14/// Builder for a parameter-bound toggle switch.
15pub struct ToggleWidget<'a, M> {
16    id: u32,
17    value: bool,
18    label: Option<&'a str>,
19    _phantom: PhantomData<M>,
20}
21
22impl<'a, M: Clone + Debug + 'static> ToggleWidget<'a, M> {
23    pub fn new(id: impl Into<u32>, params: &'a ParamCache<impl Params>) -> Self {
24        let id = id.into();
25        Self {
26            id,
27            value: params.get(id) >= 0.5,
28            label: None,
29            _phantom: PhantomData,
30        }
31    }
32
33    #[must_use]
34    pub fn label(mut self, label: &'a str) -> Self {
35        self.label = Some(label);
36        self
37    }
38
39    #[must_use]
40    pub fn into_element(self) -> Element<'a, Message<M>> {
41        let id = self.id;
42
43        let t = toggler(self.value)
44            .on_toggle(move |on| {
45                Message::Param(ParamMessage::SetNormalized(id, if on { 1.0 } else { 0.0 }))
46            })
47            .size(18.0);
48
49        let mut col = column![t].spacing(4).align_x(iced::Alignment::Center);
50
51        if let Some(label) = self.label {
52            col = col.push(text(label).size(10).color(theme::TEXT_DIM));
53        }
54
55        col.into()
56    }
57}
58
59impl<'a, M: Clone + Debug + 'static> From<ToggleWidget<'a, M>> for Element<'a, Message<M>> {
60    fn from(t: ToggleWidget<'a, M>) -> Self {
61        t.into_element()
62    }
63}