1use crate::{
2 element::{Element, ElementMetadata},
3 frame,
4 themes::rose_pine,
5};
6use gpui::ViewContext;
7use playground_macros::Element;
8use std::{borrow::Cow, marker::PhantomData, rc::Rc};
9
10struct ButtonHandlers<V, D> {
11 click: Option<Rc<dyn Fn(&mut V, &D)>>,
12}
13
14impl<V, D> Default for ButtonHandlers<V, D> {
15 fn default() -> Self {
16 Self { click: None }
17 }
18}
19
20#[derive(Element)]
21#[element_crate = "crate"]
22pub struct Button<V: 'static, D: 'static> {
23 metadata: ElementMetadata<V>,
24 handlers: ButtonHandlers<V, D>,
25 label: Option<Cow<'static, str>>,
26 icon: Option<Cow<'static, str>>,
27 data: Rc<D>,
28 view_type: PhantomData<V>,
29}
30
31// Impl block for buttons without data.
32// See below for an impl block for any button.
33impl<V: 'static> Button<V, ()> {
34 fn new() -> Self {
35 Self {
36 metadata: Default::default(),
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 metadata: Default::default(),
48 handlers: ButtonHandlers::default(),
49 label: self.label,
50 icon: self.icon,
51 data: Rc::new(data),
52 view_type: PhantomData,
53 }
54 }
55}
56
57// Impl block for *any* button.
58impl<V: 'static, D: 'static> Button<V, D> {
59 fn label(mut self, label: impl Into<Cow<'static, str>>) -> Self {
60 self.label = Some(label.into());
61 self
62 }
63
64 fn icon(mut self, icon: impl Into<Cow<'static, str>>) -> Self {
65 self.icon = Some(icon.into());
66 self
67 }
68
69 fn click(self, handler: impl Fn(&mut V, &D) + 'static) -> Self {
70 let data = self.data.clone();
71 Element::click(self, move |view, _| {
72 handler(view, data.as_ref());
73 })
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(&mut self, view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
83 // TODO: Drive from the context
84 let button = frame().fill(rose_pine::dawn().error(0.5)).h_5().w_9();
85
86 if let Some(handler) = self.handlers.click.clone() {
87 let data = self.data.clone();
88 button.click(move |view, event| handler(view, data.as_ref()))
89 } else {
90 button
91 }
92 }
93}
94
95// impl<V: 'static, D> Element<V> for Button<V, D> {
96// type Layout = AnyElement<V>;
97
98// fn style_mut(&mut self) -> &mut crate::style::ElementStyle {
99// &mut self.metadata.style
100// }
101
102// fn handlers_mut(&mut self) -> &mut crate::element::ElementHandlers<V> {
103// &mut self.metadata.handlers
104// }
105
106// fn layout(
107// &mut self,
108// view: &mut V,
109// cx: &mut crate::element::LayoutContext<V>,
110// ) -> anyhow::Result<(taffy::tree::NodeId, Self::Layout)> {
111// let mut element = self.render(view, cx).into_any();
112// let node_id = element.layout(view, cx)?;
113// Ok((node_id, element))
114// }
115
116// fn paint<'a>(
117// &mut self,
118// layout: crate::element::Layout<'a, Self::Layout>,
119// view: &mut V,
120// cx: &mut crate::element::PaintContext<V>,
121// ) -> anyhow::Result<()> {
122// layout.from_element.paint(view, cx)?;
123// Ok(())
124// }
125// }