1use gpui::{Action, AnyView, DefiniteLength};
2
3use crate::prelude::*;
4use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconElement, IconSize};
5
6#[derive(IntoElement)]
7pub struct IconButton {
8 base: ButtonLike,
9 icon: Icon,
10 icon_size: IconSize,
11 icon_color: Color,
12}
13
14impl IconButton {
15 pub fn new(id: impl Into<ElementId>, icon: Icon) -> Self {
16 Self {
17 base: ButtonLike::new(id),
18 icon,
19 icon_size: IconSize::default(),
20 icon_color: Color::Default,
21 }
22 }
23
24 pub fn icon_size(mut self, icon_size: IconSize) -> Self {
25 self.icon_size = icon_size;
26 self
27 }
28
29 pub fn icon_color(mut self, icon_color: Color) -> Self {
30 self.icon_color = icon_color;
31 self
32 }
33
34 pub fn action(self, action: Box<dyn Action>) -> Self {
35 self.on_click(move |_event, cx| cx.dispatch_action(action.boxed_clone()))
36 }
37}
38
39impl Disableable for IconButton {
40 fn disabled(mut self, disabled: bool) -> Self {
41 self.base = self.base.disabled(disabled);
42 self
43 }
44}
45
46impl Selectable for IconButton {
47 fn selected(mut self, selected: bool) -> Self {
48 self.base = self.base.selected(selected);
49 self
50 }
51}
52
53impl Clickable for IconButton {
54 fn on_click(
55 mut self,
56 handler: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
57 ) -> Self {
58 self.base = self.base.on_click(handler);
59 self
60 }
61}
62
63impl FixedWidth for IconButton {
64 fn width(mut self, width: DefiniteLength) -> Self {
65 self.base = self.base.width(width);
66 self
67 }
68
69 fn full_width(mut self) -> Self {
70 self.base = self.base.full_width();
71 self
72 }
73}
74
75impl ButtonCommon for IconButton {
76 fn id(&self) -> &ElementId {
77 self.base.id()
78 }
79
80 fn style(mut self, style: ButtonStyle) -> Self {
81 self.base = self.base.style(style);
82 self
83 }
84
85 fn size(mut self, size: ButtonSize) -> Self {
86 self.base = self.base.size(size);
87 self
88 }
89
90 fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
91 self.base = self.base.tooltip(tooltip);
92 self
93 }
94}
95
96impl RenderOnce for IconButton {
97 type Rendered = ButtonLike;
98
99 fn render(self, _cx: &mut WindowContext) -> Self::Rendered {
100 let icon_color = if self.base.disabled {
101 Color::Disabled
102 } else if self.base.selected {
103 Color::Selected
104 } else {
105 self.icon_color
106 };
107
108 self.base.child(
109 IconElement::new(self.icon)
110 .size(self.icon_size)
111 .color(icon_color),
112 )
113 }
114}