use crate::prelude::*;
pub struct Button {
pub(crate) action: Option<Box<dyn Fn(&mut EventContext)>>,
}
impl Button {
pub fn new<C, V>(cx: &mut Context, content: C) -> Handle<Self>
where
C: FnOnce(&mut Context) -> Handle<V>,
V: View,
{
Self { action: None }
.build(cx, move |cx| {
(content)(cx).hoverable(false);
})
.role(Role::Button)
.navigable(true)
}
}
impl View for Button {
fn element(&self) -> Option<&'static str> {
Some("button")
}
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 { .. } => {
if meta.target == cx.current {
if let Some(action) = &self.action {
(action)(cx);
}
}
}
WindowEvent::ActionRequest(action) => match action.action {
Action::Click => {
if let Some(action) = &self.action {
(action)(cx);
}
}
_ => {}
},
_ => {}
});
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ButtonVariant {
Primary,
Secondary,
Outline,
Text,
}
pub trait ButtonModifiers {
fn variant<U: Into<ButtonVariant> + Clone + 'static>(
self,
variant: impl Res<U> + 'static,
) -> Self;
}
impl ButtonModifiers for Handle<'_, Button> {
fn variant<U: Into<ButtonVariant> + Clone + 'static>(
self,
variant: impl Res<U> + 'static,
) -> Self {
let variant = variant.to_signal(self.cx);
self.bind(variant, move |handle| {
let val = variant.get();
let var: ButtonVariant = val.into();
match var {
ButtonVariant::Primary => {
handle
.toggle_class("secondary", false)
.toggle_class("outline", false)
.toggle_class("text", false);
}
ButtonVariant::Secondary => {
handle
.toggle_class("secondary", true)
.toggle_class("outline", false)
.toggle_class("text", false);
}
ButtonVariant::Outline => {
handle
.toggle_class("secondary", false)
.toggle_class("outline", true)
.toggle_class("text", false);
}
ButtonVariant::Text => {
handle
.toggle_class("secondary", false)
.toggle_class("outline", false)
.toggle_class("text", true);
}
}
})
}
}
pub struct ButtonGroup {}
impl ButtonGroup {
pub fn new<C>(cx: &mut Context, content: C) -> Handle<Self>
where
C: FnOnce(&mut Context),
{
Self {}.build(cx, |cx| {
(content)(cx);
})
}
}
impl View for ButtonGroup {
fn element(&self) -> Option<&'static str> {
Some("button-group")
}
}
impl Handle<'_, ButtonGroup> {
pub fn vertical(self, is_vertical: impl Res<bool>) -> Self {
self.toggle_class("vertical", is_vertical)
}
}
impl ButtonModifiers for Handle<'_, ButtonGroup> {
fn variant<U: Into<ButtonVariant> + Clone + 'static>(
self,
variant: impl Res<U> + 'static,
) -> Self {
let variant = variant.to_signal(self.cx);
self.bind(variant, move |handle| {
let val = variant.get();
let var: ButtonVariant = val.into();
match var {
ButtonVariant::Primary => {
handle
.toggle_class("secondary", false)
.toggle_class("outline", false)
.toggle_class("text", false);
}
ButtonVariant::Secondary => {
handle
.toggle_class("secondary", true)
.toggle_class("outline", false)
.toggle_class("text", false);
}
ButtonVariant::Outline => {
handle
.toggle_class("secondary", false)
.toggle_class("outline", true)
.toggle_class("text", false);
}
ButtonVariant::Text => {
handle
.toggle_class("secondary", false)
.toggle_class("outline", false)
.toggle_class("text", true);
}
}
})
}
}