cosmic/widget/button/
text.rsuse super::{Builder, ButtonClass, Style};
use crate::widget::{icon, row, tooltip};
use crate::{ext::CollectionWidget, Element};
use apply::Apply;
use iced_core::{font::Weight, text::LineHeight, widget::Id, Alignment, Length, Padding};
use std::borrow::Cow;
pub type Button<'a, Message> = Builder<'a, Message, Text>;
pub fn destructive<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
Button::new(Text::new())
.label(label)
.class(ButtonClass::Destructive)
}
pub fn suggested<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
Button::new(Text::new())
.label(label)
.class(ButtonClass::Suggested)
}
pub fn standard<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
Button::new(Text::new()).label(label)
}
pub fn text<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
Button::new(Text::new())
.label(label)
.class(ButtonClass::Text)
}
pub struct Text {
pub(super) leading_icon: Option<icon::Handle>,
pub(super) trailing_icon: Option<icon::Handle>,
}
impl Text {
pub const fn new() -> Self {
Self {
leading_icon: None,
trailing_icon: None,
}
}
}
impl<'a, Message> Button<'a, Message> {
pub fn new(text: Text) -> Self {
let guard = crate::theme::THEME.lock().unwrap();
let theme = guard.cosmic();
Self {
id: Id::unique(),
label: Cow::Borrowed(""),
tooltip: Cow::Borrowed(""),
on_press: None,
width: Length::Shrink,
height: Length::Fixed(theme.space_l().into()),
padding: Padding::from([0, theme.space_s()]),
spacing: theme.space_xxxs(),
icon_size: 16,
line_height: 20,
font_size: 14,
font_weight: Weight::Normal,
class: ButtonClass::Standard,
variant: text,
}
}
pub fn leading_icon(mut self, icon: impl Into<icon::Handle>) -> Self {
self.variant.leading_icon = Some(icon.into());
self
}
pub fn trailing_icon(mut self, icon: impl Into<icon::Handle>) -> Self {
self.variant.trailing_icon = Some(icon.into());
self
}
}
impl<'a, Message: Clone + 'static> From<Button<'a, Message>> for Element<'a, Message> {
fn from(mut builder: Button<'a, Message>) -> Element<'a, Message> {
let trailing_icon = builder.variant.trailing_icon.map(|mut i| {
if let icon::Data::Name(ref mut named) = i.data {
named.size = Some(builder.icon_size);
}
i.icon()
});
let leading_icon = builder.variant.leading_icon.map(|mut i| {
if let icon::Data::Name(ref mut named) = i.data {
named.size = Some(builder.icon_size);
}
i.icon()
});
let label: Option<Element<'_, _>> = (!builder.label.is_empty()).then(|| {
let font = crate::font::Font {
weight: builder.font_weight,
..crate::font::default()
};
crate::widget::text(builder.label.to_string())
.size(builder.font_size)
.line_height(LineHeight::Absolute(builder.line_height.into()))
.font(font)
.into()
});
let mut button: super::Button<'a, Message> = row::with_capacity(3)
.push_maybe(leading_icon)
.push_maybe(label)
.push_maybe(trailing_icon)
.padding(builder.padding)
.width(builder.width)
.height(builder.height)
.spacing(builder.spacing)
.align_y(Alignment::Center)
.apply(super::custom)
.padding(0)
.id(builder.id)
.on_press_maybe(builder.on_press.take())
.class(builder.class);
#[cfg(feature = "a11y")]
{
if !builder.label.is_empty() {
button = button.name(builder.label);
}
}
if builder.tooltip.is_empty() {
button.into()
} else {
tooltip(
button,
crate::widget::text(builder.tooltip)
.size(builder.font_size)
.font(crate::font::Font {
weight: builder.font_weight,
..crate::font::default()
}),
tooltip::Position::Top,
)
.into()
}
}
}