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