use gpui2::{ div, ArcCow, Element, EventContext, Interactive, IntoElement, MouseButton, ParentElement, StyleHelpers, ViewContext, }; use std::{marker::PhantomData, rc::Rc}; struct ButtonHandlers { click: Option)>>, } impl Default for ButtonHandlers { fn default() -> Self { Self { click: None } } } #[derive(Element)] pub struct Button { handlers: ButtonHandlers, label: Option>, icon: Option>, data: Rc, view_type: PhantomData, } // Impl block for buttons without data. // See below for an impl block for any button. impl Button { fn new() -> Self { Self { handlers: ButtonHandlers::default(), label: None, icon: None, data: Rc::new(()), view_type: PhantomData, } } pub fn data(self, data: D) -> Button { Button { handlers: ButtonHandlers::default(), label: self.label, icon: self.icon, data: Rc::new(data), view_type: PhantomData, } } } // Impl block for button regardless of its data type. impl Button { pub fn label(mut self, label: impl Into>) -> Self { self.label = Some(label.into()); self } pub fn icon(mut self, icon: impl Into>) -> Self { self.icon = Some(icon.into()); self } pub fn on_click( mut self, handler: impl Fn(&mut V, &D, &mut EventContext) + 'static, ) -> Self { self.handlers.click = Some(Rc::new(handler)); self } } pub fn button() -> Button { Button::new() } impl Button { fn render( &mut self, view: &mut V, cx: &mut ViewContext, ) -> impl IntoElement + Interactive { // let colors = &cx.theme::().colors; let button = div() // .fill(colors.error(0.5)) .h_4() .children(self.label.clone()); if let Some(handler) = self.handlers.click.clone() { let data = self.data.clone(); button.on_mouse_down(MouseButton::Left, move |view, event, cx| { handler(view, data.as_ref(), cx) }) } else { button } } }