1use gpui::AnyView;
2
3use crate::prelude::*;
4use crate::{
5 ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize, Label, LineHeightStyle,
6};
7
8use super::button_icon::ButtonIcon;
9
10#[derive(IntoElement)]
11pub struct Button {
12 base: ButtonLike,
13 label: SharedString,
14 label_color: Option<Color>,
15 selected_label: Option<SharedString>,
16 icon: Option<Icon>,
17 icon_size: Option<IconSize>,
18 icon_color: Option<Color>,
19 selected_icon: Option<Icon>,
20}
21
22impl Button {
23 pub fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
24 Self {
25 base: ButtonLike::new(id),
26 label: label.into(),
27 label_color: None,
28 selected_label: None,
29 icon: None,
30 icon_size: None,
31 icon_color: None,
32 selected_icon: None,
33 }
34 }
35
36 pub fn color(mut self, label_color: impl Into<Option<Color>>) -> Self {
37 self.label_color = label_color.into();
38 self
39 }
40
41 pub fn selected_label<L: Into<SharedString>>(mut self, label: impl Into<Option<L>>) -> Self {
42 self.selected_label = label.into().map(Into::into);
43 self
44 }
45
46 pub fn icon(mut self, icon: impl Into<Option<Icon>>) -> Self {
47 self.icon = icon.into();
48 self
49 }
50
51 pub fn icon_size(mut self, icon_size: impl Into<Option<IconSize>>) -> Self {
52 self.icon_size = icon_size.into();
53 self
54 }
55
56 pub fn icon_color(mut self, icon_color: impl Into<Option<Color>>) -> Self {
57 self.icon_color = icon_color.into();
58 self
59 }
60
61 pub fn selected_icon(mut self, icon: impl Into<Option<Icon>>) -> Self {
62 self.selected_icon = icon.into();
63 self
64 }
65}
66
67impl Selectable for Button {
68 fn selected(mut self, selected: bool) -> Self {
69 self.base = self.base.selected(selected);
70 self
71 }
72}
73
74impl Disableable for Button {
75 fn disabled(mut self, disabled: bool) -> Self {
76 self.base = self.base.disabled(disabled);
77 self
78 }
79}
80
81impl Clickable for Button {
82 fn on_click(
83 mut self,
84 handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
85 ) -> Self {
86 self.base = self.base.on_click(handler);
87 self
88 }
89}
90
91impl ButtonCommon for Button {
92 fn id(&self) -> &ElementId {
93 self.base.id()
94 }
95
96 fn style(mut self, style: ButtonStyle) -> Self {
97 self.base = self.base.style(style);
98 self
99 }
100
101 fn size(mut self, size: ButtonSize) -> Self {
102 self.base = self.base.size(size);
103 self
104 }
105
106 fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
107 self.base = self.base.tooltip(tooltip);
108 self
109 }
110}
111
112impl RenderOnce for Button {
113 type Rendered = ButtonLike;
114
115 fn render(self, _cx: &mut WindowContext) -> Self::Rendered {
116 let is_disabled = self.base.disabled;
117 let is_selected = self.base.selected;
118
119 let label = self
120 .selected_label
121 .filter(|_| is_selected)
122 .unwrap_or(self.label);
123
124 let label_color = if is_disabled {
125 Color::Disabled
126 } else if is_selected {
127 Color::Selected
128 } else {
129 self.label_color.unwrap_or_default()
130 };
131
132 self.base
133 .children(self.icon.map(|icon| {
134 ButtonIcon::new(icon)
135 .disabled(is_disabled)
136 .selected(is_selected)
137 .selected_icon(self.selected_icon)
138 .size(self.icon_size)
139 .color(self.icon_color)
140 }))
141 .child(
142 Label::new(label)
143 .color(label_color)
144 .line_height_style(LineHeightStyle::UILabel),
145 )
146 }
147}