cosmic/widget/button/
text.rs1use super::{Builder, ButtonClass};
5use crate::widget::{icon, row, tooltip};
6use crate::{Apply, Element};
7use iced_core::font::Weight;
8use iced_core::text::LineHeight;
9use iced_core::widget::Id;
10use iced_core::{Alignment, Length, Padding};
11use std::borrow::Cow;
12
13pub type Button<'a, Message> = Builder<'a, Message, Text>;
14
15pub fn destructive<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
17 Button::new(Text::new())
18 .label(label)
19 .class(ButtonClass::Destructive)
20}
21
22pub fn suggested<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
24 Button::new(Text::new())
25 .label(label)
26 .class(ButtonClass::Suggested)
27}
28
29pub fn standard<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
31 Button::new(Text::new()).label(label)
32}
33
34pub fn text<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
36 Button::new(Text::new())
37 .label(label)
38 .class(ButtonClass::Text)
39}
40
41pub struct Text {
43 pub(super) leading_icon: Option<icon::Handle>,
44 pub(super) trailing_icon: Option<icon::Handle>,
45}
46
47impl Default for Text {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53impl Text {
54 pub const fn new() -> Self {
55 Self {
56 leading_icon: None,
57 trailing_icon: None,
58 }
59 }
60}
61
62impl<Message> Button<'_, Message> {
63 pub fn new(text: Text) -> Self {
64 let guard = crate::theme::THEME.lock().unwrap();
65 let theme = guard.cosmic();
66 Self {
67 id: Id::unique(),
68 label: Cow::Borrowed(""),
69 #[cfg(feature = "a11y")]
70 name: Cow::Borrowed(""),
71 #[cfg(feature = "a11y")]
72 description: Cow::Borrowed(""),
73 tooltip: Cow::Borrowed(""),
74 on_press: None,
75 width: Length::Shrink,
76 height: Length::Fixed(theme.space_l().into()),
77 padding: Padding::from([0, theme.space_s()]),
78 spacing: theme.space_xxxs(),
79 icon_size: 16,
80 line_height: 20,
81 font_size: 14,
82 font_weight: Weight::Normal,
83 class: ButtonClass::Standard,
84 variant: text,
85 }
86 }
87
88 pub fn leading_icon(mut self, icon: impl Into<icon::Handle>) -> Self {
89 self.variant.leading_icon = Some(icon.into());
90 self
91 }
92
93 pub fn trailing_icon(mut self, icon: impl Into<icon::Handle>) -> Self {
94 self.variant.trailing_icon = Some(icon.into());
95 self
96 }
97}
98
99impl<'a, Message: Clone + 'static> From<Button<'a, Message>> for Element<'a, Message> {
100 fn from(mut builder: Button<'a, Message>) -> Element<'a, Message> {
101 let trailing_icon = builder
102 .variant
103 .trailing_icon
104 .map(crate::widget::icon::Handle::icon);
105
106 let leading_icon = builder
107 .variant
108 .leading_icon
109 .map(crate::widget::icon::Handle::icon);
110
111 let label: Option<Element<'_, _>> = (!builder.label.is_empty()).then(|| {
112 let font = crate::font::Font {
113 weight: builder.font_weight,
114 ..crate::font::default()
115 };
116
117 crate::widget::text(builder.label.to_string())
119 .size(builder.font_size)
120 .line_height(LineHeight::Absolute(builder.line_height.into()))
121 .font(font)
122 .into()
123 });
124
125 let mut button: super::Button<'a, Message> = row::with_capacity(3)
126 .push_maybe(leading_icon)
128 .push_maybe(label)
130 .push_maybe(trailing_icon)
132 .padding(builder.padding)
133 .width(builder.width)
134 .height(builder.height)
135 .spacing(builder.spacing)
136 .align_y(Alignment::Center)
137 .apply(super::custom)
138 .padding(0)
139 .id(builder.id)
140 .on_press_maybe(builder.on_press.take())
141 .class(builder.class);
142
143 #[cfg(feature = "a11y")]
144 {
145 if !builder.label.is_empty() {
146 button = button.name(builder.label)
147 }
148
149 button = button.description(builder.description);
150 }
151
152 if builder.tooltip.is_empty() {
153 button.into()
154 } else {
155 tooltip(
156 button,
157 crate::widget::text(builder.tooltip)
158 .size(builder.font_size)
159 .font(crate::font::Font {
160 weight: builder.font_weight,
161 ..crate::font::default()
162 }),
163 tooltip::Position::Top,
164 )
165 .into()
166 }
167 }
168}