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