1use crate::{prelude::*, Icon, IconName, IconSize};
2
3/// An icon that appears within a button.
4///
5/// Can be used as either an icon alongside a label, like in [`Button`](crate::Button),
6/// or as a standalone icon, like in [`IconButton`](crate::IconButton).
7#[derive(IntoElement)]
8pub(super) struct ButtonIcon {
9 icon: IconName,
10 size: IconSize,
11 color: Color,
12 disabled: bool,
13 selected: bool,
14 selected_icon: Option<IconName>,
15 selected_style: Option<ButtonStyle>,
16}
17
18impl ButtonIcon {
19 pub fn new(icon: IconName) -> Self {
20 Self {
21 icon,
22 size: IconSize::default(),
23 color: Color::default(),
24 disabled: false,
25 selected: false,
26 selected_icon: None,
27 selected_style: None,
28 }
29 }
30
31 pub fn size(mut self, size: impl Into<Option<IconSize>>) -> Self {
32 if let Some(size) = size.into() {
33 self.size = size;
34 }
35
36 self
37 }
38
39 pub fn color(mut self, color: impl Into<Option<Color>>) -> Self {
40 if let Some(color) = color.into() {
41 self.color = color;
42 }
43
44 self
45 }
46
47 pub fn selected_icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
48 self.selected_icon = icon.into();
49 self
50 }
51}
52
53impl Disableable for ButtonIcon {
54 fn disabled(mut self, disabled: bool) -> Self {
55 self.disabled = disabled;
56 self
57 }
58}
59
60impl Selectable for ButtonIcon {
61 fn selected(mut self, selected: bool) -> Self {
62 self.selected = selected;
63 self
64 }
65}
66
67impl SelectableButton for ButtonIcon {
68 fn selected_style(mut self, style: ButtonStyle) -> Self {
69 self.selected_style = Some(style);
70 self
71 }
72}
73
74impl RenderOnce for ButtonIcon {
75 fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
76 let icon = self
77 .selected_icon
78 .filter(|_| self.selected)
79 .unwrap_or(self.icon);
80
81 let icon_color = if self.disabled {
82 Color::Disabled
83 } else if self.selected_style.is_some() && self.selected {
84 self.selected_style.unwrap().into()
85 } else if self.selected {
86 Color::Selected
87 } else {
88 self.color
89 };
90
91 Icon::new(icon).size(self.size).color(icon_color)
92 }
93}