2023-09-01 07:29:19 +02:00
|
|
|
// Copyright 2023 System76 <info@system76.com>
|
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2025-03-14 11:56:21 -04:00
|
|
|
use super::{Builder, ButtonClass};
|
2023-09-13 15:47:32 +02:00
|
|
|
use crate::widget::{icon, row, tooltip};
|
2023-09-01 07:29:19 +02:00
|
|
|
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>;
|
|
|
|
|
|
2024-05-20 20:01:47 +02:00
|
|
|
/// A text button with the destructive style
|
2023-09-01 07:29:19 +02:00
|
|
|
pub fn destructive<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
|
|
|
|
|
Button::new(Text::new())
|
|
|
|
|
.label(label)
|
2024-10-16 20:36:46 -04:00
|
|
|
.class(ButtonClass::Destructive)
|
2023-09-01 07:29:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 20:01:47 +02:00
|
|
|
/// A text button with the suggested style
|
2023-09-01 07:29:19 +02:00
|
|
|
pub fn suggested<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
|
|
|
|
|
Button::new(Text::new())
|
|
|
|
|
.label(label)
|
2024-10-16 20:36:46 -04:00
|
|
|
.class(ButtonClass::Suggested)
|
2023-09-01 07:29:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 20:01:47 +02:00
|
|
|
/// A text button with the standard style
|
2023-09-01 07:29:19 +02:00
|
|
|
pub fn standard<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
|
|
|
|
|
Button::new(Text::new()).label(label)
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-20 20:01:47 +02:00
|
|
|
/// A text button with the text style
|
2023-09-01 07:29:19 +02:00
|
|
|
pub fn text<'a, Message>(label: impl Into<Cow<'a, str>>) -> Button<'a, Message> {
|
2024-10-16 20:36:46 -04:00
|
|
|
Button::new(Text::new())
|
|
|
|
|
.label(label)
|
|
|
|
|
.class(ButtonClass::Text)
|
2023-09-01 07:29:19 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 20:01:47 +02:00
|
|
|
/// The text variant of a button.
|
2023-09-01 07:29:19 +02:00
|
|
|
pub struct Text {
|
2023-09-13 15:47:32 +02:00
|
|
|
pub(super) leading_icon: Option<icon::Handle>,
|
|
|
|
|
pub(super) trailing_icon: Option<icon::Handle>,
|
2023-09-01 07:29:19 +02:00
|
|
|
}
|
|
|
|
|
|
2025-03-14 11:56:21 -04:00
|
|
|
impl Default for Text {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::new()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-01 07:29:19 +02:00
|
|
|
impl Text {
|
|
|
|
|
pub const fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
leading_icon: None,
|
|
|
|
|
trailing_icon: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-14 11:56:21 -04:00
|
|
|
impl<Message> Button<'_, Message> {
|
2023-09-01 07:29:19 +02:00
|
|
|
pub fn new(text: Text) -> Self {
|
2024-08-02 20:00:16 +02:00
|
|
|
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,
|
2024-10-16 20:36:46 -04:00
|
|
|
class: ButtonClass::Standard,
|
2024-08-02 20:00:16 +02:00
|
|
|
variant: text,
|
|
|
|
|
}
|
2023-09-01 07:29:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-13 15:47:32 +02:00
|
|
|
pub fn leading_icon(mut self, icon: impl Into<icon::Handle>) -> Self {
|
2023-09-01 07:29:19 +02:00
|
|
|
self.variant.leading_icon = Some(icon.into());
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-13 15:47:32 +02:00
|
|
|
pub fn trailing_icon(mut self, icon: impl Into<icon::Handle>) -> Self {
|
2023-09-01 07:29:19 +02:00
|
|
|
self.variant.trailing_icon = Some(icon.into());
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, Message: Clone + 'static> From<Button<'a, Message>> for Element<'a, Message> {
|
2023-09-13 15:47:32 +02:00
|
|
|
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(|| {
|
2024-10-03 21:27:06 +02:00
|
|
|
let font = crate::font::Font {
|
|
|
|
|
weight: builder.font_weight,
|
|
|
|
|
..crate::font::default()
|
|
|
|
|
};
|
2023-09-13 15:47:32 +02:00
|
|
|
|
|
|
|
|
// TODO: Avoid allocation
|
|
|
|
|
crate::widget::text(builder.label.to_string())
|
|
|
|
|
.size(builder.font_size)
|
|
|
|
|
.line_height(LineHeight::Absolute(builder.line_height.into()))
|
|
|
|
|
.font(font)
|
|
|
|
|
.into()
|
|
|
|
|
});
|
|
|
|
|
|
2024-11-25 00:52:32 -05:00
|
|
|
let mut button: super::Button<'a, Message> = row::with_capacity(3)
|
2024-05-17 19:08:43 +02:00
|
|
|
// Optional icon to place before label.
|
|
|
|
|
.push_maybe(leading_icon)
|
|
|
|
|
// Optional label between icons.
|
|
|
|
|
.push_maybe(label)
|
|
|
|
|
// Optional icon to place behind the label.
|
|
|
|
|
.push_maybe(trailing_icon)
|
|
|
|
|
.padding(builder.padding)
|
|
|
|
|
.width(builder.width)
|
|
|
|
|
.height(builder.height)
|
|
|
|
|
.spacing(builder.spacing)
|
2024-10-16 20:36:46 -04:00
|
|
|
.align_y(Alignment::Center)
|
2024-09-16 19:11:29 +02:00
|
|
|
.apply(super::custom)
|
2024-05-17 19:08:43 +02:00
|
|
|
.padding(0)
|
|
|
|
|
.id(builder.id)
|
|
|
|
|
.on_press_maybe(builder.on_press.take())
|
2024-10-16 20:36:46 -04:00
|
|
|
.class(builder.class);
|
2023-09-13 15:47:32 +02:00
|
|
|
|
2024-11-25 00:52:32 -05:00
|
|
|
#[cfg(feature = "a11y")]
|
|
|
|
|
{
|
|
|
|
|
if !builder.label.is_empty() {
|
|
|
|
|
button = button.name(builder.label);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-13 15:47:32 +02:00
|
|
|
if builder.tooltip.is_empty() {
|
|
|
|
|
button.into()
|
|
|
|
|
} else {
|
2024-10-16 20:36:46 -04:00
|
|
|
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()
|
2023-09-13 15:47:32 +02:00
|
|
|
}
|
2023-09-01 07:29:19 +02:00
|
|
|
}
|
|
|
|
|
}
|