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