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