components.rs

  1use gpui2::{
  2    elements::div, interactive::Interactive, platform::MouseButton, style::StyleHelpers, ArcCow,
  3    Element, EventContext, IntoElement, ParentElement, ViewContext,
  4};
  5use std::{marker::PhantomData, rc::Rc};
  6
  7mod icon_button;
  8mod tab;
  9
 10pub(crate) use icon_button::{icon_button, ButtonVariant};
 11pub(crate) use tab::tab;
 12
 13struct ButtonHandlers<V, D> {
 14    click: Option<Rc<dyn Fn(&mut V, &D, &mut EventContext<V>)>>,
 15}
 16
 17impl<V, D> Default for ButtonHandlers<V, D> {
 18    fn default() -> Self {
 19        Self { click: None }
 20    }
 21}
 22
 23#[derive(Element)]
 24pub struct Button<V: 'static, D: 'static> {
 25    handlers: ButtonHandlers<V, D>,
 26    label: Option<ArcCow<'static, str>>,
 27    icon: Option<ArcCow<'static, str>>,
 28    data: Rc<D>,
 29    view_type: PhantomData<V>,
 30}
 31
 32// Impl block for buttons without data.
 33// See below for an impl block for any button.
 34impl<V: 'static> Button<V, ()> {
 35    fn new() -> Self {
 36        Self {
 37            handlers: ButtonHandlers::default(),
 38            label: None,
 39            icon: None,
 40            data: Rc::new(()),
 41            view_type: PhantomData,
 42        }
 43    }
 44
 45    pub fn data<D: 'static>(self, data: D) -> Button<V, D> {
 46        Button {
 47            handlers: ButtonHandlers::default(),
 48            label: self.label,
 49            icon: self.icon,
 50            data: Rc::new(data),
 51            view_type: PhantomData,
 52        }
 53    }
 54}
 55
 56// Impl block for button regardless of its data type.
 57impl<V: 'static, D: 'static> Button<V, D> {
 58    pub fn label(mut self, label: impl Into<ArcCow<'static, str>>) -> Self {
 59        self.label = Some(label.into());
 60        self
 61    }
 62
 63    pub fn icon(mut self, icon: impl Into<ArcCow<'static, str>>) -> Self {
 64        self.icon = Some(icon.into());
 65        self
 66    }
 67
 68    pub fn on_click(
 69        mut self,
 70        handler: impl Fn(&mut V, &D, &mut EventContext<V>) + 'static,
 71    ) -> Self {
 72        self.handlers.click = Some(Rc::new(handler));
 73        self
 74    }
 75}
 76
 77pub fn button<V>() -> Button<V, ()> {
 78    Button::new()
 79}
 80
 81impl<V: 'static, D: 'static> Button<V, D> {
 82    fn render(
 83        &mut self,
 84        view: &mut V,
 85        cx: &mut ViewContext<V>,
 86    ) -> impl IntoElement<V> + Interactive<V> {
 87        // let colors = &cx.theme::<Theme>().colors;
 88
 89        let button = div()
 90            // .fill(colors.error(0.5))
 91            .h_4()
 92            .children(self.label.clone());
 93
 94        if let Some(handler) = self.handlers.click.clone() {
 95            let data = self.data.clone();
 96            button.on_mouse_down(MouseButton::Left, move |view, event, cx| {
 97                handler(view, data.as_ref(), cx)
 98            })
 99        } else {
100            button
101        }
102    }
103}