use crate::{prelude::*, *};
use std::sync::Arc;
#[derive(IntoElement)]
pub struct Toggle {
label: SharedString,
pressed: bool,
on_change: Option<Arc<dyn Fn(bool, &mut Window, &mut App) + Send + Sync + 'static>>,
style: StyleRefinement,
}
impl Toggle {
pub fn new(label: impl Into<SharedString>) -> Self {
Self {
label: label.into(),
pressed: false,
on_change: None,
style: StyleRefinement::default(),
}
}
pub fn pressed(mut self, pressed: bool) -> Self {
self.pressed = pressed;
self
}
pub fn on_change<F>(mut self, f: F) -> Self
where
F: Fn(bool, &mut Window, &mut App) + Send + Sync + 'static,
{
self.on_change = Some(Arc::new(f));
self
}
}
impl Styled for Toggle {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.style
}
}
impl RenderOnce for Toggle {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let accent = cx.theme().tokens.accent.color;
let pressed = self.pressed;
let user_style = self.style;
Button::new(self.label.clone())
.label(self.label)
.map(|mut this| {
if pressed {
this.style()
.refine(&StyleRefinement::default().bg(accent.opacity(0.15)));
}
this.style().refine(&user_style);
this
})
.on_click(move |_, window, cx| {
if let Some(ref cb) = self.on_change {
cb(!pressed, window, cx);
}
})
}
}
#[derive(IntoElement)]
pub struct ToggleGroup {
options: Vec<SharedString>,
selected: Option<usize>,
on_change: Option<Arc<dyn Fn(usize, &mut Window, &mut App) + Send + Sync + 'static>>,
}
impl ToggleGroup {
pub fn new(options: Vec<SharedString>) -> Self {
Self {
options,
selected: None,
on_change: None,
}
}
pub fn selected(mut self, index: Option<usize>) -> Self {
self.selected = index;
self
}
pub fn on_change<F>(mut self, f: F) -> Self
where
F: Fn(usize, &mut Window, &mut App) + Send + Sync + 'static,
{
self.on_change = Some(Arc::new(f));
self
}
}
impl RenderOnce for ToggleGroup {
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let selected = self.selected;
let on_change = self.on_change;
div()
.flex()
.flex_row()
.gap(px(4.0))
.children(self.options.into_iter().enumerate().map(|(ix, label)| {
let on_change = on_change.clone();
Toggle::new(label)
.pressed(Some(ix) == selected)
.on_change(move |_, window, cx| {
if let Some(ref cb) = on_change {
cb(ix, window, cx);
}
})
.into_any_element()
}))
}
}