2023-09-13 15:49:11 +02:00
|
|
|
// Copyright 2023 System76 <info@system76.com>
|
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
|
|
|
|
//! Contains stylesheet implementation for [`crate::widget::button`].
|
|
|
|
|
|
|
|
|
|
use cosmic_theme::Component;
|
|
|
|
|
use iced_core::{Background, Color};
|
|
|
|
|
use palette::{rgb::Rgb, Alpha};
|
|
|
|
|
|
2023-09-19 16:36:42 +02:00
|
|
|
use crate::{
|
|
|
|
|
theme::TRANSPARENT_COMPONENT,
|
|
|
|
|
widget::button::{Appearance, StyleSheet},
|
|
|
|
|
};
|
2023-09-13 15:49:11 +02:00
|
|
|
|
2023-09-13 17:26:19 +02:00
|
|
|
#[derive(Default)]
|
2023-09-13 15:49:11 +02:00
|
|
|
pub enum Button {
|
2023-09-13 17:26:19 +02:00
|
|
|
Custom {
|
|
|
|
|
active: Box<dyn Fn(bool, &crate::Theme) -> Appearance>,
|
|
|
|
|
disabled: Box<dyn Fn(&crate::Theme) -> Appearance>,
|
|
|
|
|
hovered: Box<dyn Fn(bool, &crate::Theme) -> Appearance>,
|
|
|
|
|
pressed: Box<dyn Fn(bool, &crate::Theme) -> Appearance>,
|
|
|
|
|
},
|
2023-09-13 15:49:11 +02:00
|
|
|
Destructive,
|
|
|
|
|
Link,
|
|
|
|
|
Icon,
|
|
|
|
|
IconVertical,
|
|
|
|
|
#[default]
|
|
|
|
|
Standard,
|
|
|
|
|
Suggested,
|
|
|
|
|
Text,
|
2023-09-19 16:36:42 +02:00
|
|
|
Transparent,
|
2023-09-13 15:49:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn appearance(
|
|
|
|
|
theme: &crate::Theme,
|
|
|
|
|
focused: bool,
|
|
|
|
|
style: &Button,
|
2023-09-18 08:28:51 +02:00
|
|
|
color: impl Fn(&Component<Alpha<Rgb, f32>>) -> (Color, Option<Color>, Option<Color>),
|
2023-09-13 15:49:11 +02:00
|
|
|
) -> Appearance {
|
|
|
|
|
let cosmic = theme.cosmic();
|
|
|
|
|
let mut corner_radii = &cosmic.corner_radii.radius_xl;
|
|
|
|
|
let mut appearance = Appearance::new();
|
|
|
|
|
|
|
|
|
|
match style {
|
2023-09-19 16:36:42 +02:00
|
|
|
Button::Standard
|
|
|
|
|
| Button::Text
|
|
|
|
|
| Button::Suggested
|
|
|
|
|
| Button::Destructive
|
|
|
|
|
| Button::Transparent => {
|
2023-09-13 15:49:11 +02:00
|
|
|
let style_component = match style {
|
|
|
|
|
Button::Standard => &cosmic.button,
|
|
|
|
|
Button::Text => &cosmic.text_button,
|
|
|
|
|
Button::Suggested => &cosmic.accent_button,
|
|
|
|
|
Button::Destructive => &cosmic.destructive_button,
|
2023-09-19 16:36:42 +02:00
|
|
|
Button::Transparent => &TRANSPARENT_COMPONENT,
|
2023-09-13 15:49:11 +02:00
|
|
|
_ => return appearance,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let (background, text, icon) = color(style_component);
|
|
|
|
|
appearance.background = Some(Background::Color(background));
|
|
|
|
|
appearance.text_color = text;
|
|
|
|
|
appearance.icon_color = icon;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-18 08:28:51 +02:00
|
|
|
Button::Icon | Button::IconVertical => {
|
2023-09-13 15:49:11 +02:00
|
|
|
if let Button::IconVertical = style {
|
|
|
|
|
corner_radii = &cosmic.corner_radii.radius_m;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-18 08:28:51 +02:00
|
|
|
let (background, _text, icon) = color(&cosmic.icon_button);
|
2023-09-13 15:49:11 +02:00
|
|
|
appearance.background = Some(Background::Color(background));
|
2023-09-18 08:28:51 +02:00
|
|
|
// appearance.text_color = text;
|
|
|
|
|
// appearance.icon_color = icon;
|
2023-09-13 17:37:45 +02:00
|
|
|
|
2023-09-18 08:28:51 +02:00
|
|
|
if focused {
|
|
|
|
|
appearance.text_color = Some(cosmic.accent.on.into());
|
2023-09-13 15:49:11 +02:00
|
|
|
appearance.icon_color = Some(cosmic.accent.on.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Button::Link => {
|
|
|
|
|
appearance.background = None;
|
|
|
|
|
appearance.icon_color = Some(cosmic.accent.base.into());
|
2023-09-18 08:28:51 +02:00
|
|
|
appearance.text_color = Some(cosmic.accent.base.into());
|
2023-09-13 15:49:11 +02:00
|
|
|
corner_radii = &cosmic.corner_radii.radius_0;
|
|
|
|
|
}
|
2023-09-13 17:26:19 +02:00
|
|
|
|
|
|
|
|
Button::Custom { .. } => (),
|
2023-09-13 15:49:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
appearance.border_radius = (*corner_radii).into();
|
|
|
|
|
|
|
|
|
|
if focused {
|
|
|
|
|
appearance.outline_width = 1.0;
|
|
|
|
|
appearance.outline_color = cosmic.accent.base.into();
|
|
|
|
|
appearance.border_width = 2.0;
|
|
|
|
|
appearance.border_color = Color::TRANSPARENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
appearance
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl StyleSheet for crate::Theme {
|
|
|
|
|
type Style = Button;
|
|
|
|
|
|
|
|
|
|
fn active(&self, focused: bool, style: &Self::Style) -> Appearance {
|
2023-09-13 17:26:19 +02:00
|
|
|
if let Button::Custom { active, .. } = style {
|
|
|
|
|
return active(focused, self);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-13 15:49:11 +02:00
|
|
|
appearance(self, focused, style, |component| {
|
|
|
|
|
(
|
|
|
|
|
component.base.into(),
|
2023-09-18 08:28:51 +02:00
|
|
|
Some(component.on.into()),
|
2023-09-13 15:49:11 +02:00
|
|
|
Some(component.on.into()),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn disabled(&self, style: &Self::Style) -> Appearance {
|
2023-09-13 17:26:19 +02:00
|
|
|
if let Button::Custom { disabled, .. } = style {
|
|
|
|
|
return disabled(self);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-13 15:49:11 +02:00
|
|
|
appearance(self, false, style, |component| {
|
|
|
|
|
let mut background = Color::from(component.base);
|
|
|
|
|
background.a *= 0.5;
|
|
|
|
|
(
|
|
|
|
|
background,
|
2023-09-18 08:28:51 +02:00
|
|
|
Some(component.on_disabled.into()),
|
2023-09-13 15:49:11 +02:00
|
|
|
Some(component.on_disabled.into()),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn drop_target(&self, style: &Self::Style) -> Appearance {
|
|
|
|
|
self.active(false, style)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn hovered(&self, focused: bool, style: &Self::Style) -> Appearance {
|
2023-09-13 17:26:19 +02:00
|
|
|
if let Button::Custom { hovered, .. } = style {
|
|
|
|
|
return hovered(focused, self);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-13 15:49:11 +02:00
|
|
|
appearance(self, focused, style, |component| {
|
|
|
|
|
(
|
|
|
|
|
component.hover.into(),
|
2023-09-18 08:28:51 +02:00
|
|
|
Some(component.on.into()),
|
2023-09-13 15:49:11 +02:00
|
|
|
Some(component.on.into()),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn pressed(&self, focused: bool, style: &Self::Style) -> Appearance {
|
2023-09-13 17:26:19 +02:00
|
|
|
if let Button::Custom { pressed, .. } = style {
|
|
|
|
|
return pressed(focused, self);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-13 15:49:11 +02:00
|
|
|
appearance(self, focused, style, |component| {
|
|
|
|
|
(
|
|
|
|
|
component.pressed.into(),
|
2023-09-18 08:28:51 +02:00
|
|
|
Some(component.on.into()),
|
2023-09-13 15:49:11 +02:00
|
|
|
Some(component.on.into()),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|