use crate::core::{MessageContext, Mut, ViewMarker};
use crate::{MessageResult, Pod, View, ViewCtx};
use masonry::core::ArcStr;
use masonry::widgets::{self, CheckboxToggled};
pub fn checkbox<F, State, Action>(
label: impl Into<ArcStr>,
checked: bool,
callback: F,
) -> Checkbox<F>
where
F: Fn(&mut State, bool) -> Action + Send + 'static,
{
Checkbox {
label: label.into(),
callback,
checked,
disabled: false,
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Checkbox<F> {
label: ArcStr,
checked: bool,
callback: F,
disabled: bool,
}
impl<F> Checkbox<F> {
pub fn disabled(mut self, disabled: bool) -> Self {
self.disabled = disabled;
self
}
}
impl<F> ViewMarker for Checkbox<F> {}
impl<F, State, Action> View<State, Action, ViewCtx> for Checkbox<F>
where
F: Fn(&mut State, bool) -> Action + Send + Sync + 'static,
{
type Element = Pod<widgets::Checkbox>;
type ViewState = ();
fn build(&self, ctx: &mut ViewCtx, _: &mut State) -> (Self::Element, Self::ViewState) {
ctx.with_leaf_action_widget(|ctx| {
let mut pod = ctx.create_pod(widgets::Checkbox::new(self.checked, self.label.clone()));
pod.new_widget.options.disabled = self.disabled;
pod
})
}
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'_, Self::Element>,
_: &mut State,
) {
if prev.disabled != self.disabled {
element.ctx.set_disabled(self.disabled);
}
if prev.label != self.label {
widgets::Checkbox::set_text(&mut element, self.label.clone());
}
if prev.checked != self.checked {
widgets::Checkbox::set_checked(&mut element, self.checked);
}
}
fn teardown(
&self,
(): &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
) {
ctx.teardown_leaf(element);
}
fn message(
&self,
(): &mut Self::ViewState,
message: &mut MessageContext,
_element: Mut<'_, Self::Element>,
app_state: &mut State,
) -> MessageResult<Action> {
debug_assert!(
message.remaining_path().is_empty(),
"id path should be empty in Checkbox::message"
);
match message.take_message::<CheckboxToggled>() {
Some(checked) => MessageResult::Action((self.callback)(app_state, checked.0)),
None => {
tracing::error!("Wrong message type in Checkbox::message, got {message:?}.");
MessageResult::Stale
}
}
}
}