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