1use gpui::{Action, AnyView};
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 ButtonCommon for IconButton {
64 fn id(&self) -> &ElementId {
65 self.base.id()
66 }
67
68 fn style(mut self, style: ButtonStyle) -> Self {
69 self.base = self.base.style(style);
70 self
71 }
72
73 fn size(mut self, size: ButtonSize) -> Self {
74 self.base = self.base.size(size);
75 self
76 }
77
78 fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
79 self.base = self.base.tooltip(tooltip);
80 self
81 }
82}
83
84impl RenderOnce for IconButton {
85 type Rendered = ButtonLike;
86
87 fn render(self, _cx: &mut WindowContext) -> Self::Rendered {
88 let icon_color = if self.base.disabled {
89 Color::Disabled
90 } else if self.base.selected {
91 Color::Selected
92 } else {
93 self.icon_color
94 };
95
96 self.base.child(
97 IconElement::new(self.icon)
98 .size(self.icon_size)
99 .color(icon_color),
100 )
101 }
102}