cosmic/widget/button/
icon.rs1use super::{Builder, ButtonClass};
5use crate::Element;
6use crate::widget::{icon::Handle, tooltip};
7use apply::Apply;
8use iced_core::{Alignment, Length, Padding, font::Weight, text::LineHeight, widget::Id};
9use std::borrow::Cow;
10
11pub type Button<'a, Message> = Builder<'a, Message, Icon>;
12
13pub struct Icon {
15 handle: Handle,
16 vertical: bool,
17 selected: bool,
18}
19
20pub fn icon<'a, Message>(handle: impl Into<Handle>) -> Button<'a, Message> {
22 Button::new(Icon {
23 handle: handle.into(),
24 vertical: false,
25 selected: false,
26 })
27}
28
29impl<Message> Button<'_, Message> {
30 pub fn new(icon: Icon) -> Self {
31 let guard = crate::theme::THEME.lock().unwrap();
32 let theme = guard.cosmic();
33 let padding = theme.space_xxs();
34
35 Self {
36 id: Id::unique(),
37 label: Cow::Borrowed(""),
38 #[cfg(feature = "a11y")]
39 name: Cow::Borrowed(""),
40 #[cfg(feature = "a11y")]
41 description: Cow::Borrowed(""),
42 tooltip: Cow::Borrowed(""),
43 on_press: None,
44 width: Length::Shrink,
45 height: Length::Shrink,
46 padding: Padding::from(padding),
47 spacing: theme.space_xxxs(),
48 icon_size: if icon.handle.symbolic { 16 } else { 24 },
49 line_height: 20,
50 font_size: 14,
51 font_weight: Weight::Normal,
52 class: ButtonClass::Icon,
53 variant: icon,
54 }
55 }
56
57 pub fn extra_small(mut self) -> Self {
59 let guard = crate::theme::THEME.lock().unwrap();
60 let theme = guard.cosmic();
61
62 self.font_size = 14;
63 self.font_weight = Weight::Normal;
64 self.icon_size = 16;
65 self.line_height = 20;
66 self.padding = Padding::from(theme.space_xxs());
67 self.spacing = theme.space_xxxs();
68
69 self
70 }
71
72 pub fn medium(mut self) -> Self {
74 let guard = crate::theme::THEME.lock().unwrap();
75 let theme = guard.cosmic();
76
77 self.font_size = 24;
78 self.font_weight = Weight::Normal;
79 self.icon_size = 32;
80 self.line_height = 32;
81 self.padding = Padding::from(theme.space_xs());
82 self.spacing = theme.space_xxs();
83
84 self
85 }
86
87 pub fn large(mut self) -> Self {
89 let guard = crate::theme::THEME.lock().unwrap();
90 let theme = guard.cosmic();
91
92 self.font_size = 28;
93 self.font_weight = Weight::Normal;
94 self.icon_size = 40;
95 self.line_height = 36;
96 self.padding = Padding::from(theme.space_xs());
97 self.spacing = theme.space_xxs();
98
99 self
100 }
101
102 pub fn extra_large(mut self) -> Self {
104 let guard = crate::theme::THEME.lock().unwrap();
105 let theme = guard.cosmic();
106 let padding = theme.space_xs();
107
108 self.font_size = 32;
109 self.font_weight = Weight::Light;
110 self.icon_size = 56;
111 self.line_height = 44;
112 self.padding = Padding::from(padding);
113 self.spacing = theme.space_xxs();
114
115 self
116 }
117
118 #[inline]
119 pub fn selected(mut self, selected: bool) -> Self {
120 self.variant.selected = selected;
121 self
122 }
123
124 #[inline]
125 pub fn vertical(mut self, vertical: bool) -> Self {
126 self.variant.vertical = vertical;
127 self.class = ButtonClass::IconVertical;
128 self
129 }
130}
131
132impl<'a, Message: Clone + 'static> From<Button<'a, Message>> for Element<'a, Message> {
133 fn from(builder: Button<'a, Message>) -> Element<'a, Message> {
134 let mut content = Vec::with_capacity(2);
135
136 content.push(
137 crate::widget::icon(builder.variant.handle.clone())
138 .size(builder.icon_size)
139 .into(),
140 );
141
142 if !builder.label.is_empty() {
143 content.push(
144 crate::widget::text(builder.label)
145 .size(builder.font_size)
146 .line_height(LineHeight::Absolute(builder.line_height.into()))
147 .font(crate::font::Font {
148 weight: builder.font_weight,
149 ..crate::font::default()
150 })
151 .into(),
152 );
153 }
154
155 let mut button = if builder.variant.vertical {
156 crate::widget::column::with_children(content)
157 .padding(builder.padding)
158 .spacing(builder.spacing)
159 .align_x(Alignment::Center)
160 .apply(super::custom)
161 } else {
162 crate::widget::row::with_children(content)
163 .padding(builder.padding)
164 .width(builder.width)
165 .height(builder.height)
166 .spacing(builder.spacing)
167 .align_y(Alignment::Center)
168 .apply(super::custom)
169 };
170
171 #[cfg(feature = "a11y")]
172 {
173 button = button.name(builder.name).description(builder.description);
174 }
175
176 let button = button
177 .padding(0)
178 .id(builder.id)
179 .on_press_maybe(builder.on_press)
180 .selected(builder.variant.selected)
181 .class(builder.class);
182
183 if builder.tooltip.is_empty() {
184 button.into()
185 } else {
186 tooltip(
187 button,
188 crate::widget::text(builder.tooltip)
189 .size(builder.font_size)
190 .font(crate::font::Font {
191 weight: builder.font_weight,
192 ..crate::font::default()
193 }),
194 tooltip::Position::Top,
195 )
196 .into()
197 }
198 }
199}