use ribir_core::prelude::*;
use crate::prelude::*;
#[derive(Clone, Copy, Declare, PartialEq, Eq)]
pub struct Switch {
#[declare(default, event = Switch.checked)]
pub checked: bool,
}
pub type SwitchChanged = CustomEvent<Switch>;
class_names! {
SWITCH_CHECKED,
SWITCH_UNCHECKED,
SWITCH,
SWITCH_THUMB,
SWITCH_THUMB_CHECKED,
SWITCH_THUMB_UNCHECKED,
}
impl Switch {
fn state_class_name(&self) -> ClassName {
if self.checked { SWITCH_CHECKED } else { SWITCH_UNCHECKED }
}
fn thumb_class_name(&self) -> ClassName {
if self.checked { SWITCH_THUMB_CHECKED } else { SWITCH_THUMB_UNCHECKED }
}
fn request_toggle(&self, e: &CommonEvent) {
let mut new_state = *self;
new_state.switch_check();
e.window()
.bubble_custom_event(e.target(), new_state);
}
pub fn switch_check(&mut self) { self.checked = !self.checked; }
}
impl ComposeChild<'static> for Switch {
type Child = Option<PositionChild<TextValue>>;
fn compose_child(this: impl StateWriter<Value = Self>, child: Self::Child) -> Widget<'static> {
fn_widget! {
let switch_widget = @Stack {
class: distinct_pipe!([SWITCH, $read(this).state_class_name()]),
@Container {
hint_size: Size::new(40., 20.),
class: distinct_pipe!([SWITCH_THUMB, $read(this).thumb_class_name()]),
}
};
@FatObj {
cursor: CursorIcon::Pointer,
on_action: move |e| $read(this).request_toggle(e),
@ { icon_with_label(switch_widget.into_widget(), child) }
}
}
.into_widget()
}
}
#[cfg(test)]
mod tests {
use ribir_core::test_helper::*;
use ribir_dev_helper::*;
use super::*;
widget_image_tests!(
switch,
WidgetTester::new(self::column! {
@Switch { checked: true, @ { "checked" } }
@Switch { @Trailing::new("unchecked") }
})
.with_wnd_size(Size::new(240., 160.)),
);
}