use crate::icons::ICON_CHECK;
use crate::prelude::*;
pub struct Checkbox {
on_toggle: Option<Box<dyn Fn(&mut EventContext)>>,
}
impl Checkbox {
pub fn new(cx: &mut Context, checked: impl Res<bool> + Copy + 'static) -> Handle<Self> {
Self { on_toggle: None }
.build(cx, move |cx| {
checked.set_or_bind(cx, |cx, checked| {
if checked.get_value(cx) {
Svg::new(cx, ICON_CHECK);
}
});
})
.checked(checked)
.role(Role::CheckBox)
.navigable(true)
}
pub fn with_icons<T>(
cx: &mut Context,
checked: impl Res<bool> + Copy + 'static,
icon_default: Option<impl Res<T> + Copy + 'static>,
icon_checked: Option<impl Res<T> + Copy + 'static>,
) -> Handle<Self>
where
T: AsRef<[u8]> + 'static,
{
Self { on_toggle: None }
.build(cx, move |cx| {
checked.set_or_bind(cx, move |cx, checked| {
if checked.get_value(cx) {
if let Some(icon) = icon_checked {
Svg::new(cx, icon);
}
} else if let Some(icon) = icon_default {
Svg::new(cx, icon);
}
});
})
.checked(checked)
.role(Role::CheckBox)
.navigable(true)
}
pub fn intermediate(
cx: &mut Context,
checked: impl Res<bool> + Clone + 'static,
intermediate: impl Res<bool> + Clone + 'static,
) -> Handle<Self> {
let checked_state = checked.clone().to_signal(cx);
let intermediate_state = intermediate.to_signal(cx);
let text_memo = Memo::new(move |_| {
if checked_state.get() {
ICON_CHECK
} else if intermediate_state.get() {
"-"
} else {
""
}
});
let is_intermediate_memo =
Memo::new(move |_| !checked_state.get() && intermediate_state.get());
Self { on_toggle: None }
.build(cx, |_| {})
.text(text_memo)
.toggle_class("intermediate", is_intermediate_memo)
.checked(checked)
.navigable(true)
}
}
impl Handle<'_, Checkbox> {
pub fn on_toggle<F>(self, callback: F) -> Self
where
F: 'static + Fn(&mut EventContext),
{
self.modify(|checkbox| checkbox.on_toggle = Some(Box::new(callback)))
}
}
impl View for Checkbox {
fn element(&self) -> Option<&'static str> {
Some("checkbox")
}
fn event(&mut self, cx: &mut EventContext, event: &mut Event) {
event.map(|window_event, meta| match window_event {
WindowEvent::PressDown { mouse: _ } => {
if meta.target == cx.current {
cx.focus();
}
}
WindowEvent::Press { mouse: _ } => {
if meta.target == cx.current {
if let Some(callback) = &self.on_toggle {
(callback)(cx);
}
}
}
WindowEvent::ActionRequest(action) => match action.action {
Action::Click => {
if let Some(callback) = &self.on_toggle {
(callback)(cx);
}
}
_ => {}
},
_ => {}
});
}
}