2022-12-06 16:12:59 +01:00
|
|
|
// Copyright 2022 System76 <info@system76.com>
|
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2022-10-28 21:59:41 -07:00
|
|
|
pub mod expander;
|
2023-01-03 19:35:34 +01:00
|
|
|
mod segmented_button;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-08-04 15:48:34 -04:00
|
|
|
use std::cell::RefCell;
|
2023-06-15 11:16:32 -04:00
|
|
|
use std::f32::consts::PI;
|
2022-12-06 16:12:59 +01:00
|
|
|
use std::hash::Hash;
|
|
|
|
|
use std::hash::Hasher;
|
2023-04-28 16:04:57 -07:00
|
|
|
use std::rc::Rc;
|
2023-05-30 12:03:15 -04:00
|
|
|
use std::sync::Arc;
|
2022-12-06 16:12:59 +01:00
|
|
|
|
2023-01-03 19:35:34 +01:00
|
|
|
pub use self::segmented_button::SegmentedButton;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-06-12 12:08:14 -04:00
|
|
|
use cosmic_config::config_subscription;
|
|
|
|
|
use cosmic_config::CosmicConfigEntry;
|
|
|
|
|
use cosmic_theme::util::CssColor;
|
2022-11-17 20:49:20 -05:00
|
|
|
use cosmic_theme::Component;
|
2023-02-27 17:42:17 -05:00
|
|
|
use cosmic_theme::LayeredTheme;
|
2023-06-15 11:16:32 -04:00
|
|
|
use iced_core::gradient::Linear;
|
|
|
|
|
use iced_core::BorderRadius;
|
|
|
|
|
use iced_core::Radians;
|
2023-06-12 12:08:14 -04:00
|
|
|
use iced_futures::Subscription;
|
2022-10-28 21:59:41 -07:00
|
|
|
use iced_style::application;
|
|
|
|
|
use iced_style::button;
|
|
|
|
|
use iced_style::checkbox;
|
|
|
|
|
use iced_style::container;
|
|
|
|
|
use iced_style::menu;
|
|
|
|
|
use iced_style::pane_grid;
|
|
|
|
|
use iced_style::pick_list;
|
|
|
|
|
use iced_style::progress_bar;
|
|
|
|
|
use iced_style::radio;
|
|
|
|
|
use iced_style::rule;
|
|
|
|
|
use iced_style::scrollable;
|
|
|
|
|
use iced_style::slider;
|
2023-05-30 12:03:15 -04:00
|
|
|
use iced_style::slider::Rail;
|
2022-11-01 13:06:00 +01:00
|
|
|
use iced_style::svg;
|
2022-10-28 21:59:41 -07:00
|
|
|
use iced_style::text_input;
|
|
|
|
|
use iced_style::toggler;
|
|
|
|
|
|
|
|
|
|
use iced_core::{Background, Color};
|
2023-02-27 17:42:17 -05:00
|
|
|
use palette::Srgba;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-05-30 12:03:15 -04:00
|
|
|
pub type CosmicColor = ::palette::rgb::Srgba;
|
|
|
|
|
pub type CosmicComponent = cosmic_theme::Component<CosmicColor>;
|
|
|
|
|
pub type CosmicTheme = cosmic_theme::Theme<CosmicColor>;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
lazy_static::lazy_static! {
|
2023-08-03 19:30:08 -04:00
|
|
|
pub static ref COSMIC_DARK: CosmicTheme = CosmicTheme::dark_default();
|
|
|
|
|
pub static ref COSMIC_HC_DARK: CosmicTheme = CosmicTheme::high_contrast_dark_default();
|
|
|
|
|
pub static ref COSMIC_LIGHT: CosmicTheme = CosmicTheme::light_default();
|
|
|
|
|
pub static ref COSMIC_HC_LIGHT: CosmicTheme = CosmicTheme::high_contrast_light_default();
|
2022-11-17 20:49:20 -05:00
|
|
|
pub static ref TRANSPARENT_COMPONENT: Component<CosmicColor> = Component {
|
|
|
|
|
base: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
|
|
|
|
hover: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
|
|
|
|
pressed: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
|
|
|
|
selected: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
|
|
|
|
selected_text: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
|
|
|
|
focus: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
|
|
|
|
disabled: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
2023-02-21 15:23:49 -05:00
|
|
|
on: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
2023-02-27 17:42:17 -05:00
|
|
|
on_disabled: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
|
|
|
|
divider: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
2023-08-07 13:48:01 -04:00
|
|
|
border: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
|
|
|
|
disabled_border: CosmicColor::new(0.0, 0.0, 0.0, 0.0),
|
2022-11-17 20:49:20 -05:00
|
|
|
};
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2023-08-04 15:48:34 -04:00
|
|
|
thread_local! {
|
|
|
|
|
pub(crate) static THEME: RefCell<Theme> = RefCell::new(Theme { theme_type: ThemeType::Dark, layer: cosmic_theme::Layer::Background });
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-09 17:13:01 -04:00
|
|
|
#[derive(Debug, Clone, PartialEq, Default)]
|
2023-02-27 19:56:53 -05:00
|
|
|
pub enum ThemeType {
|
|
|
|
|
#[default]
|
|
|
|
|
Dark,
|
|
|
|
|
Light,
|
|
|
|
|
HighContrastDark,
|
|
|
|
|
HighContrastLight,
|
2023-05-30 12:03:15 -04:00
|
|
|
Custom(Arc<CosmicTheme>),
|
2023-08-04 15:48:34 -04:00
|
|
|
System(Arc<CosmicTheme>),
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
|
2023-06-09 17:13:01 -04:00
|
|
|
#[derive(Debug, Clone, PartialEq, Default)]
|
2023-02-27 19:56:53 -05:00
|
|
|
pub struct Theme {
|
|
|
|
|
pub theme_type: ThemeType,
|
|
|
|
|
pub layer: cosmic_theme::Layer,
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Theme {
|
2022-12-06 16:12:59 +01:00
|
|
|
#[must_use]
|
2023-02-27 19:56:53 -05:00
|
|
|
pub fn cosmic(&self) -> &cosmic_theme::Theme<Srgba> {
|
|
|
|
|
match self.theme_type {
|
|
|
|
|
ThemeType::Dark => &COSMIC_DARK,
|
|
|
|
|
ThemeType::Light => &COSMIC_LIGHT,
|
|
|
|
|
ThemeType::HighContrastDark => &COSMIC_HC_DARK,
|
|
|
|
|
ThemeType::HighContrastLight => &COSMIC_HC_LIGHT,
|
2023-08-04 15:48:34 -04:00
|
|
|
ThemeType::Custom(ref t) | ThemeType::System(ref t) => t.as_ref(),
|
2023-02-27 19:56:53 -05:00
|
|
|
}
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[must_use]
|
2023-02-27 19:56:53 -05:00
|
|
|
pub fn dark() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
theme_type: ThemeType::Dark,
|
|
|
|
|
..Default::default()
|
|
|
|
|
}
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
|
2023-02-27 19:56:53 -05:00
|
|
|
#[must_use]
|
|
|
|
|
pub fn light() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
theme_type: ThemeType::Light,
|
|
|
|
|
..Default::default()
|
|
|
|
|
}
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
|
2023-02-27 19:56:53 -05:00
|
|
|
#[must_use]
|
|
|
|
|
pub fn dark_hc() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
theme_type: ThemeType::HighContrastDark,
|
|
|
|
|
..Default::default()
|
|
|
|
|
}
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[must_use]
|
2023-02-27 19:56:53 -05:00
|
|
|
pub fn light_hc() -> Self {
|
2023-02-27 17:42:17 -05:00
|
|
|
Self {
|
2023-02-27 19:56:53 -05:00
|
|
|
theme_type: ThemeType::HighContrastLight,
|
|
|
|
|
..Default::default()
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-30 12:03:15 -04:00
|
|
|
#[must_use]
|
|
|
|
|
pub fn custom(theme: Arc<CosmicTheme>) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
theme_type: ThemeType::Custom(theme),
|
|
|
|
|
..Default::default()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-04 15:48:34 -04:00
|
|
|
#[must_use]
|
|
|
|
|
pub fn system(theme: Arc<CosmicTheme>) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
theme_type: ThemeType::System(theme),
|
|
|
|
|
..Default::default()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-27 19:56:53 -05:00
|
|
|
/// get current container
|
|
|
|
|
/// can be used in a component that is intended to be a child of a `CosmicContainer`
|
2023-02-27 17:42:17 -05:00
|
|
|
#[must_use]
|
2023-02-27 19:56:53 -05:00
|
|
|
pub fn current_container(&self) -> &cosmic_theme::Container<Srgba> {
|
|
|
|
|
match self.layer {
|
|
|
|
|
cosmic_theme::Layer::Background => &self.cosmic().background,
|
|
|
|
|
cosmic_theme::Layer::Primary => &self.cosmic().primary,
|
|
|
|
|
cosmic_theme::Layer::Secondary => &self.cosmic().secondary,
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
2023-08-04 15:48:34 -04:00
|
|
|
|
|
|
|
|
/// set the theme
|
|
|
|
|
pub fn set_theme(&mut self, theme: ThemeType) {
|
|
|
|
|
self.theme_type = theme;
|
|
|
|
|
}
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2023-02-27 17:42:17 -05:00
|
|
|
impl LayeredTheme for Theme {
|
|
|
|
|
fn set_layer(&mut self, layer: cosmic_theme::Layer) {
|
2023-02-27 19:56:53 -05:00
|
|
|
self.layer = layer;
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
#[derive(Default)]
|
2022-10-28 21:59:41 -07:00
|
|
|
pub enum Application {
|
2023-04-28 16:04:57 -07:00
|
|
|
#[default]
|
2022-10-28 21:59:41 -07:00
|
|
|
Default,
|
2023-04-28 16:04:57 -07:00
|
|
|
Custom(Box<dyn Fn(&Theme) -> application::Appearance>),
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
impl Application {
|
|
|
|
|
pub fn custom<F: Fn(&Theme) -> application::Appearance + 'static>(f: F) -> Self {
|
|
|
|
|
Self::Custom(Box::new(f))
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl application::StyleSheet for Theme {
|
|
|
|
|
type Style = Application;
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn appearance(&self, style: &Self::Style) -> application::Appearance {
|
2022-10-28 21:59:41 -07:00
|
|
|
let cosmic = self.cosmic();
|
|
|
|
|
|
|
|
|
|
match style {
|
|
|
|
|
Application::Default => application::Appearance {
|
|
|
|
|
background_color: cosmic.bg_color().into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
text_color: cosmic.on_bg_color().into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
},
|
2023-02-27 17:42:17 -05:00
|
|
|
Application::Custom(f) => f(self),
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Button
|
|
|
|
|
*/
|
|
|
|
|
pub enum Button {
|
2022-12-06 16:12:59 +01:00
|
|
|
Deactivated,
|
|
|
|
|
Destructive,
|
|
|
|
|
Positive,
|
2022-10-28 21:59:41 -07:00
|
|
|
Primary,
|
|
|
|
|
Secondary,
|
|
|
|
|
Text,
|
2022-12-20 16:02:44 -07:00
|
|
|
Link,
|
|
|
|
|
LinkActive,
|
2022-11-17 20:49:20 -05:00
|
|
|
Transparent,
|
2023-07-17 11:44:57 -04:00
|
|
|
Card,
|
2022-12-17 18:15:24 -05:00
|
|
|
Custom {
|
2023-04-28 16:04:57 -07:00
|
|
|
active: Box<dyn Fn(&Theme) -> button::Appearance>,
|
|
|
|
|
hover: Box<dyn Fn(&Theme) -> button::Appearance>,
|
2022-12-17 18:15:24 -05:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for Button {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::Primary
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Button {
|
2022-12-23 15:10:13 +01:00
|
|
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
|
|
|
|
#[allow(clippy::match_same_arms)]
|
2023-02-27 17:42:17 -05:00
|
|
|
fn cosmic<'a>(&'a self, theme: &'a Theme) -> &CosmicComponent {
|
2022-10-28 21:59:41 -07:00
|
|
|
let cosmic = theme.cosmic();
|
|
|
|
|
match self {
|
|
|
|
|
Button::Primary => &cosmic.accent,
|
2023-02-27 19:56:53 -05:00
|
|
|
Button::Secondary => &theme.current_container().component,
|
2022-10-28 21:59:41 -07:00
|
|
|
Button::Positive => &cosmic.success,
|
|
|
|
|
Button::Destructive => &cosmic.destructive,
|
2023-02-27 19:56:53 -05:00
|
|
|
Button::Text => &theme.current_container().component,
|
2022-12-20 16:02:44 -07:00
|
|
|
Button::Link => &cosmic.accent,
|
2023-02-27 19:29:42 -05:00
|
|
|
Button::LinkActive => &cosmic.accent,
|
2022-11-17 20:49:20 -05:00
|
|
|
Button::Transparent => &TRANSPARENT_COMPONENT,
|
2023-02-27 19:56:53 -05:00
|
|
|
Button::Deactivated => &theme.current_container().component,
|
2023-07-17 11:44:57 -04:00
|
|
|
Button::Card => &theme.current_container().component,
|
2023-01-03 21:35:35 +01:00
|
|
|
Button::Custom { .. } => &TRANSPARENT_COMPONENT,
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl button::StyleSheet for Theme {
|
|
|
|
|
type Style = Button;
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn active(&self, style: &Self::Style) -> button::Appearance {
|
2023-01-03 21:35:35 +01:00
|
|
|
if let Button::Custom { active, .. } = style {
|
2022-12-17 18:15:24 -05:00
|
|
|
return active(self);
|
|
|
|
|
}
|
2022-12-19 17:03:13 +01:00
|
|
|
|
2023-08-04 17:19:30 -04:00
|
|
|
let corner_radii = &self.cosmic().corner_radii;
|
2023-02-21 15:23:49 -05:00
|
|
|
let component = style.cosmic(self);
|
2022-10-28 21:59:41 -07:00
|
|
|
button::Appearance {
|
2022-12-20 16:02:44 -07:00
|
|
|
border_radius: match style {
|
2023-08-04 17:19:30 -04:00
|
|
|
Button::Link => corner_radii.radius_0.into(),
|
|
|
|
|
Button::Card => corner_radii.radius_xs.into(),
|
|
|
|
|
_ => corner_radii.radius_xl.into(),
|
2022-12-20 16:02:44 -07:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
background: match style {
|
2022-12-23 15:10:13 +01:00
|
|
|
Button::Link | Button::Text => None,
|
2023-02-27 17:42:17 -05:00
|
|
|
Button::LinkActive => Some(Background::Color(component.divider.into())),
|
2023-02-21 15:23:49 -05:00
|
|
|
_ => Some(Background::Color(component.base.into())),
|
2022-10-28 21:59:41 -07:00
|
|
|
},
|
2022-12-20 16:02:44 -07:00
|
|
|
text_color: match style {
|
2023-02-27 19:29:42 -05:00
|
|
|
Button::Link | Button::LinkActive => component.base.into(),
|
2023-02-21 15:23:49 -05:00
|
|
|
_ => component.on.into(),
|
2022-12-20 16:02:44 -07:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
..button::Appearance::default()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn hovered(&self, style: &Self::Style) -> button::Appearance {
|
2023-01-03 21:35:35 +01:00
|
|
|
if let Button::Custom { hover, .. } = style {
|
2022-12-17 18:15:24 -05:00
|
|
|
return hover(self);
|
|
|
|
|
}
|
2022-12-19 17:03:13 +01:00
|
|
|
|
2022-12-23 15:10:13 +01:00
|
|
|
let active = self.active(style);
|
2023-02-21 15:23:49 -05:00
|
|
|
let component = style.cosmic(self);
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
button::Appearance {
|
2022-12-20 16:02:44 -07:00
|
|
|
background: match style {
|
|
|
|
|
Button::Link => None,
|
2023-02-27 17:42:17 -05:00
|
|
|
Button::LinkActive => Some(Background::Color(component.divider.into())),
|
2023-02-21 15:23:49 -05:00
|
|
|
_ => Some(Background::Color(component.hover.into())),
|
2022-12-20 16:02:44 -07:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
..active
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-05 11:29:14 -07:00
|
|
|
|
|
|
|
|
fn focused(&self, style: &Self::Style) -> button::Appearance {
|
|
|
|
|
if let Button::Custom { hover, .. } = style {
|
|
|
|
|
return hover(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let active = self.active(style);
|
2023-02-21 15:23:49 -05:00
|
|
|
let component = style.cosmic(self);
|
2023-01-05 11:29:14 -07:00
|
|
|
button::Appearance {
|
|
|
|
|
background: match style {
|
|
|
|
|
Button::Link => None,
|
2023-02-27 17:42:17 -05:00
|
|
|
Button::LinkActive => Some(Background::Color(component.divider.into())),
|
2023-02-21 15:23:49 -05:00
|
|
|
_ => Some(Background::Color(component.hover.into())),
|
2023-01-05 11:29:14 -07:00
|
|
|
},
|
|
|
|
|
..active
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-17 11:44:57 -04:00
|
|
|
|
|
|
|
|
fn disabled(&self, style: &Self::Style) -> button::Appearance {
|
|
|
|
|
let active = self.active(style);
|
|
|
|
|
|
|
|
|
|
if matches!(style, Button::Card) {
|
|
|
|
|
return active;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
button::Appearance {
|
|
|
|
|
shadow_offset: iced_core::Vector::default(),
|
|
|
|
|
background: active.background.map(|background| match background {
|
|
|
|
|
Background::Color(color) => Background::Color(Color {
|
|
|
|
|
a: color.a * 0.5,
|
|
|
|
|
..color
|
|
|
|
|
}),
|
|
|
|
|
Background::Gradient(gradient) => Background::Gradient(gradient.mul_alpha(0.5)),
|
|
|
|
|
}),
|
|
|
|
|
text_color: Color {
|
|
|
|
|
a: active.text_color.a * 0.5,
|
|
|
|
|
..active.text_color
|
|
|
|
|
},
|
|
|
|
|
..active
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Checkbox
|
|
|
|
|
*/
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum Checkbox {
|
|
|
|
|
Primary,
|
|
|
|
|
Secondary,
|
|
|
|
|
Success,
|
|
|
|
|
Danger,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for Checkbox {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::Primary
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl checkbox::StyleSheet for Theme {
|
|
|
|
|
type Style = Checkbox;
|
|
|
|
|
|
2023-01-03 21:35:35 +01:00
|
|
|
fn active(&self, style: &Self::Style, is_checked: bool) -> checkbox::Appearance {
|
2023-08-07 13:48:01 -04:00
|
|
|
let cosmic = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-08-07 13:48:01 -04:00
|
|
|
let corners = &cosmic.corner_radii;
|
2022-10-28 21:59:41 -07:00
|
|
|
match style {
|
2023-02-27 17:42:17 -05:00
|
|
|
Checkbox::Primary => checkbox::Appearance {
|
|
|
|
|
background: Background::Color(if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.accent.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
}),
|
2023-08-07 13:48:01 -04:00
|
|
|
icon_color: cosmic.accent.on.into(),
|
|
|
|
|
border_radius: corners.radius_xs.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
border_width: if is_checked { 0.0 } else { 1.0 },
|
|
|
|
|
border_color: if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.accent.base
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.border
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
text_color: None,
|
|
|
|
|
},
|
|
|
|
|
Checkbox::Secondary => checkbox::Appearance {
|
|
|
|
|
background: Background::Color(if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.background.component.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.background.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
}),
|
2023-08-07 13:48:01 -04:00
|
|
|
icon_color: cosmic.background.on.into(),
|
|
|
|
|
border_radius: corners.radius_xs.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
border_width: if is_checked { 0.0 } else { 1.0 },
|
2023-08-07 13:48:01 -04:00
|
|
|
border_color: cosmic.button.border.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
text_color: None,
|
|
|
|
|
},
|
|
|
|
|
Checkbox::Success => checkbox::Appearance {
|
|
|
|
|
background: Background::Color(if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.success.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
}),
|
2023-08-07 13:48:01 -04:00
|
|
|
icon_color: cosmic.success.on.into(),
|
|
|
|
|
border_radius: corners.radius_xs.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
border_width: if is_checked { 0.0 } else { 1.0 },
|
|
|
|
|
border_color: if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.success.base
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.border
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
text_color: None,
|
|
|
|
|
},
|
|
|
|
|
Checkbox::Danger => checkbox::Appearance {
|
|
|
|
|
background: Background::Color(if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.destructive.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
}),
|
2023-08-07 13:48:01 -04:00
|
|
|
icon_color: cosmic.destructive.on.into(),
|
|
|
|
|
border_radius: corners.radius_xs.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
border_width: if is_checked { 0.0 } else { 1.0 },
|
|
|
|
|
border_color: if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.destructive.base
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.border
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
text_color: None,
|
|
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-03 21:35:35 +01:00
|
|
|
fn hovered(&self, style: &Self::Style, is_checked: bool) -> checkbox::Appearance {
|
2023-08-07 13:48:01 -04:00
|
|
|
let cosmic = self.cosmic();
|
|
|
|
|
let corners = &cosmic.corner_radii;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
match style {
|
2023-02-27 17:42:17 -05:00
|
|
|
Checkbox::Primary => checkbox::Appearance {
|
|
|
|
|
background: Background::Color(if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.accent.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
}),
|
2023-08-07 13:48:01 -04:00
|
|
|
icon_color: cosmic.accent.on.into(),
|
|
|
|
|
border_radius: corners.radius_xs.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
border_width: if is_checked { 0.0 } else { 1.0 },
|
|
|
|
|
border_color: if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.accent.base
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.border
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
text_color: None,
|
|
|
|
|
},
|
|
|
|
|
Checkbox::Secondary => checkbox::Appearance {
|
|
|
|
|
background: Background::Color(if is_checked {
|
2023-02-27 19:56:53 -05:00
|
|
|
self.current_container().base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
}),
|
2023-05-30 12:03:15 -04:00
|
|
|
icon_color: self.current_container().on.into(),
|
2023-08-07 13:48:01 -04:00
|
|
|
border_radius: corners.radius_xs.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
border_width: if is_checked { 0.0 } else { 1.0 },
|
|
|
|
|
border_color: if is_checked {
|
2023-02-27 19:56:53 -05:00
|
|
|
self.current_container().base
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.border
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
text_color: None,
|
|
|
|
|
},
|
|
|
|
|
Checkbox::Success => checkbox::Appearance {
|
|
|
|
|
background: Background::Color(if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.success.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
}),
|
2023-08-07 13:48:01 -04:00
|
|
|
icon_color: cosmic.success.on.into(),
|
|
|
|
|
border_radius: corners.radius_xs.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
border_width: if is_checked { 0.0 } else { 1.0 },
|
|
|
|
|
border_color: if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.success.base
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.border
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
text_color: None,
|
|
|
|
|
},
|
|
|
|
|
Checkbox::Danger => checkbox::Appearance {
|
|
|
|
|
background: Background::Color(if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.destructive.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.base.into()
|
2023-02-27 17:42:17 -05:00
|
|
|
}),
|
2023-08-07 13:48:01 -04:00
|
|
|
icon_color: cosmic.destructive.on.into(),
|
|
|
|
|
border_radius: corners.radius_xs.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
border_width: if is_checked { 0.0 } else { 1.0 },
|
|
|
|
|
border_color: if is_checked {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.destructive.base
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
2023-08-07 13:48:01 -04:00
|
|
|
cosmic.button.border
|
2023-02-27 17:42:17 -05:00
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
text_color: None,
|
|
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
#[derive(Default)]
|
2022-10-28 21:59:41 -07:00
|
|
|
pub enum Expander {
|
2023-04-28 16:04:57 -07:00
|
|
|
#[default]
|
2022-10-28 21:59:41 -07:00
|
|
|
Default,
|
2023-04-28 16:04:57 -07:00
|
|
|
Custom(Box<dyn Fn(&Theme) -> expander::Appearance>),
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
impl Expander {
|
|
|
|
|
pub fn custom<F: Fn(&Theme) -> expander::Appearance + 'static>(f: F) -> Self {
|
|
|
|
|
Self::Custom(Box::new(f))
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl expander::StyleSheet for Theme {
|
|
|
|
|
type Style = Expander;
|
|
|
|
|
|
|
|
|
|
fn appearance(&self, style: Self::Style) -> expander::Appearance {
|
|
|
|
|
match style {
|
2022-12-06 16:12:59 +01:00
|
|
|
Expander::Default => expander::Appearance::default(),
|
2022-10-28 21:59:41 -07:00
|
|
|
Expander::Custom(f) => f(self),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Container
|
|
|
|
|
*/
|
2023-04-28 16:04:57 -07:00
|
|
|
#[derive(Default)]
|
2022-10-28 21:59:41 -07:00
|
|
|
pub enum Container {
|
2023-02-22 14:06:09 -05:00
|
|
|
Background,
|
|
|
|
|
Primary,
|
|
|
|
|
Secondary,
|
2023-04-28 16:04:57 -07:00
|
|
|
#[default]
|
2022-10-28 21:59:41 -07:00
|
|
|
Transparent,
|
2023-05-30 12:03:15 -04:00
|
|
|
HeaderBar,
|
2023-04-28 16:04:57 -07:00
|
|
|
Custom(Box<dyn Fn(&Theme) -> container::Appearance>),
|
2023-07-17 11:44:57 -04:00
|
|
|
Card,
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
impl Container {
|
|
|
|
|
pub fn custom<F: Fn(&Theme) -> container::Appearance + 'static>(f: F) -> Self {
|
|
|
|
|
Self::Custom(Box::new(f))
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl container::StyleSheet for Theme {
|
|
|
|
|
type Style = Container;
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn appearance(&self, style: &Self::Style) -> container::Appearance {
|
2022-10-28 21:59:41 -07:00
|
|
|
match style {
|
2022-12-06 16:12:59 +01:00
|
|
|
Container::Transparent => container::Appearance::default(),
|
2023-02-22 14:06:09 -05:00
|
|
|
Container::Custom(f) => f(self),
|
|
|
|
|
Container::Background => {
|
|
|
|
|
let palette = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
container::Appearance {
|
2023-02-27 19:23:02 -05:00
|
|
|
text_color: Some(Color::from(palette.background.on)),
|
2023-02-22 14:06:09 -05:00
|
|
|
background: Some(iced::Background::Color(palette.background.base.into())),
|
2023-05-30 12:03:15 -04:00
|
|
|
border_radius: 2.0.into(),
|
|
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Container::HeaderBar => {
|
|
|
|
|
let palette = self.cosmic();
|
2023-06-15 11:16:32 -04:00
|
|
|
let mut header_top = palette.background.base;
|
|
|
|
|
let header_bottom = palette.background.base;
|
|
|
|
|
header_top.alpha = 0.8;
|
2023-05-30 12:03:15 -04:00
|
|
|
|
|
|
|
|
container::Appearance {
|
|
|
|
|
text_color: Some(Color::from(palette.background.on)),
|
2023-06-15 11:16:32 -04:00
|
|
|
background: Some(iced::Background::Gradient(iced_core::Gradient::Linear(
|
|
|
|
|
Linear::new(Radians(3.0 * PI / 2.0))
|
|
|
|
|
.add_stop(0.0, header_top.into())
|
|
|
|
|
.add_stop(1.0, header_bottom.into()),
|
|
|
|
|
))),
|
2023-05-30 12:03:15 -04:00
|
|
|
border_radius: BorderRadius::from([16.0, 16.0, 0.0, 0.0]),
|
2023-02-22 14:06:09 -05:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Container::Primary => {
|
|
|
|
|
let palette = self.cosmic();
|
|
|
|
|
|
|
|
|
|
container::Appearance {
|
2023-02-27 19:23:02 -05:00
|
|
|
text_color: Some(Color::from(palette.primary.on)),
|
2023-02-22 14:06:09 -05:00
|
|
|
background: Some(iced::Background::Color(palette.primary.base.into())),
|
2023-05-30 12:03:15 -04:00
|
|
|
border_radius: 2.0.into(),
|
2023-02-22 14:06:09 -05:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Container::Secondary => {
|
|
|
|
|
let palette = self.cosmic();
|
|
|
|
|
|
|
|
|
|
container::Appearance {
|
2023-02-27 19:23:02 -05:00
|
|
|
text_color: Some(Color::from(palette.secondary.on)),
|
2023-02-22 14:06:09 -05:00
|
|
|
background: Some(iced::Background::Color(palette.secondary.base.into())),
|
2023-05-30 12:03:15 -04:00
|
|
|
border_radius: 2.0.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-17 11:44:57 -04:00
|
|
|
Container::Card => {
|
|
|
|
|
let palette = self.cosmic();
|
|
|
|
|
|
|
|
|
|
match self.layer {
|
|
|
|
|
cosmic_theme::Layer::Background => container::Appearance {
|
|
|
|
|
text_color: Some(Color::from(palette.background.component.on)),
|
|
|
|
|
background: Some(iced::Background::Color(
|
|
|
|
|
palette.background.component.base.into(),
|
|
|
|
|
)),
|
|
|
|
|
border_radius: 8.0.into(),
|
|
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
},
|
|
|
|
|
cosmic_theme::Layer::Primary => container::Appearance {
|
|
|
|
|
text_color: Some(Color::from(palette.primary.component.on)),
|
|
|
|
|
background: Some(iced::Background::Color(
|
|
|
|
|
palette.primary.component.base.into(),
|
|
|
|
|
)),
|
|
|
|
|
border_radius: 8.0.into(),
|
|
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
},
|
|
|
|
|
cosmic_theme::Layer::Secondary => container::Appearance {
|
|
|
|
|
text_color: Some(Color::from(palette.secondary.component.on)),
|
|
|
|
|
background: Some(iced::Background::Color(
|
|
|
|
|
palette.secondary.component.base.into(),
|
|
|
|
|
)),
|
|
|
|
|
border_radius: 8.0.into(),
|
|
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Slider
|
|
|
|
|
*/
|
|
|
|
|
impl slider::StyleSheet for Theme {
|
|
|
|
|
type Style = ();
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn active(&self, _style: &Self::Style) -> slider::Appearance {
|
2022-10-28 21:59:41 -07:00
|
|
|
let cosmic = self.cosmic();
|
|
|
|
|
|
|
|
|
|
//TODO: no way to set rail thickness
|
|
|
|
|
slider::Appearance {
|
2023-05-30 12:03:15 -04:00
|
|
|
rail: Rail {
|
|
|
|
|
colors: (
|
|
|
|
|
cosmic.accent.base.into(),
|
|
|
|
|
//TODO: no way to set color before/after slider
|
|
|
|
|
Color::TRANSPARENT,
|
|
|
|
|
),
|
|
|
|
|
width: 4.0,
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 2.0.into(),
|
2023-05-30 12:03:15 -04:00
|
|
|
},
|
|
|
|
|
|
2022-10-28 21:59:41 -07:00
|
|
|
handle: slider::Handle {
|
2022-11-11 05:06:54 +01:00
|
|
|
shape: slider::HandleShape::Circle { radius: 10.0 },
|
2022-10-28 21:59:41 -07:00
|
|
|
color: cosmic.accent.base.into(),
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
border_width: 0.0,
|
2022-11-11 05:06:54 +01:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn hovered(&self, style: &Self::Style) -> slider::Appearance {
|
2022-12-23 15:10:13 +01:00
|
|
|
let mut style = self.active(style);
|
2023-01-03 21:35:35 +01:00
|
|
|
style.handle.shape = slider::HandleShape::Circle { radius: 16.0 };
|
2022-10-28 21:59:41 -07:00
|
|
|
style.handle.border_width = 6.0;
|
2023-02-27 19:56:53 -05:00
|
|
|
let mut border_color = self.cosmic().palette.neutral_10;
|
2023-02-27 17:42:17 -05:00
|
|
|
border_color.alpha = 0.1;
|
|
|
|
|
style.handle.border_color = border_color.into();
|
2022-10-28 21:59:41 -07:00
|
|
|
style
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn dragging(&self, style: &Self::Style) -> slider::Appearance {
|
2022-12-23 15:10:13 +01:00
|
|
|
let mut style = self.hovered(style);
|
2023-02-27 19:56:53 -05:00
|
|
|
let mut border_color = self.cosmic().palette.neutral_10;
|
2023-02-27 17:42:17 -05:00
|
|
|
border_color.alpha = 0.2;
|
|
|
|
|
style.handle.border_color = border_color.into();
|
|
|
|
|
|
2022-10-28 21:59:41 -07:00
|
|
|
style
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Menu
|
|
|
|
|
*/
|
|
|
|
|
impl menu::StyleSheet for Theme {
|
|
|
|
|
type Style = ();
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn appearance(&self, _style: &Self::Style) -> menu::Appearance {
|
2022-10-28 21:59:41 -07:00
|
|
|
let cosmic = self.cosmic();
|
|
|
|
|
|
|
|
|
|
menu::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
text_color: cosmic.on_bg_color().into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
background: Background::Color(cosmic.background.base.into()),
|
|
|
|
|
border_width: 0.0,
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 16.0.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
border_color: Color::TRANSPARENT,
|
2023-02-27 17:42:17 -05:00
|
|
|
selected_text_color: cosmic.on_bg_color().into(),
|
|
|
|
|
// TODO doesn't seem to be specified
|
|
|
|
|
selected_background: Background::Color(cosmic.background.component.hover.into()),
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Pick List
|
|
|
|
|
*/
|
|
|
|
|
impl pick_list::StyleSheet for Theme {
|
|
|
|
|
type Style = ();
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn active(&self, _style: &()) -> pick_list::Appearance {
|
2023-02-21 15:23:49 -05:00
|
|
|
let cosmic = &self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
pick_list::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
text_color: cosmic.on_bg_color().into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
background: Color::TRANSPARENT.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
placeholder_color: cosmic.on_bg_color().into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 24.0.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
2023-05-30 12:03:15 -04:00
|
|
|
// icon_size: 0.7, // TODO: how to replace
|
|
|
|
|
handle_color: cosmic.on_bg_color().into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn hovered(&self, style: &()) -> pick_list::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
let cosmic = &self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
pick_list::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Background::Color(cosmic.background.base.into()),
|
2022-12-23 15:10:13 +01:00
|
|
|
..self.active(style)
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Radio
|
|
|
|
|
*/
|
|
|
|
|
impl radio::StyleSheet for Theme {
|
|
|
|
|
type Style = ();
|
|
|
|
|
|
2023-02-22 14:06:09 -05:00
|
|
|
fn active(&self, _style: &Self::Style, is_selected: bool) -> radio::Appearance {
|
|
|
|
|
let theme = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
radio::Appearance {
|
2023-02-22 14:06:09 -05:00
|
|
|
background: if is_selected {
|
|
|
|
|
Color::from(theme.accent.base).into()
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: this seems to be defined weirdly in FIGMA
|
2023-02-27 17:42:17 -05:00
|
|
|
Color::from(theme.background.base).into()
|
2023-02-22 14:06:09 -05:00
|
|
|
},
|
|
|
|
|
dot_color: theme.accent.on.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
border_width: 1.0,
|
2023-02-27 17:42:17 -05:00
|
|
|
border_color: if is_selected {
|
2023-02-27 18:45:54 -05:00
|
|
|
Color::from(theme.accent.base)
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
|
|
|
|
// TODO: this seems to be defined weirdly in FIGMA
|
2023-02-27 18:45:54 -05:00
|
|
|
Color::from(theme.palette.neutral_7)
|
2023-02-27 17:42:17 -05:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
text_color: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-27 18:45:54 -05:00
|
|
|
fn hovered(&self, _style: &Self::Style, is_selected: bool) -> radio::Appearance {
|
2023-02-22 14:06:09 -05:00
|
|
|
let theme = self.cosmic();
|
2023-02-27 18:45:54 -05:00
|
|
|
let mut neutral_10 = theme.palette.neutral_10;
|
2023-02-27 17:42:17 -05:00
|
|
|
neutral_10.alpha = 0.1;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
radio::Appearance {
|
2023-02-22 14:06:09 -05:00
|
|
|
background: if is_selected {
|
2023-02-27 17:42:17 -05:00
|
|
|
Color::from(theme.accent.base).into()
|
2023-02-22 14:06:09 -05:00
|
|
|
} else {
|
|
|
|
|
// TODO: this seems to be defined weirdly in FIGMA
|
2023-02-27 17:42:17 -05:00
|
|
|
Color::from(neutral_10).into()
|
2023-02-22 14:06:09 -05:00
|
|
|
},
|
2023-02-27 17:42:17 -05:00
|
|
|
dot_color: theme.accent.on.into(),
|
|
|
|
|
border_width: 1.0,
|
|
|
|
|
border_color: if is_selected {
|
2023-02-27 18:45:54 -05:00
|
|
|
Color::from(theme.accent.base)
|
2023-02-27 17:42:17 -05:00
|
|
|
} else {
|
|
|
|
|
// TODO: this seems to be defined weirdly in FIGMA
|
2023-02-27 18:45:54 -05:00
|
|
|
Color::from(theme.palette.neutral_7)
|
2023-02-27 17:42:17 -05:00
|
|
|
},
|
|
|
|
|
text_color: None,
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Toggler
|
|
|
|
|
*/
|
|
|
|
|
impl toggler::StyleSheet for Theme {
|
|
|
|
|
type Style = ();
|
|
|
|
|
|
2023-01-03 21:35:35 +01:00
|
|
|
fn active(&self, _style: &Self::Style, is_active: bool) -> toggler::Appearance {
|
2023-02-22 14:06:09 -05:00
|
|
|
let theme = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
toggler::Appearance {
|
|
|
|
|
background: if is_active {
|
2023-02-22 14:06:09 -05:00
|
|
|
theme.accent.base.into()
|
2022-10-28 21:59:41 -07:00
|
|
|
} else {
|
|
|
|
|
//TODO: Grab neutral from palette
|
2023-02-22 14:06:09 -05:00
|
|
|
theme.palette.neutral_5.into()
|
2022-10-28 21:59:41 -07:00
|
|
|
},
|
|
|
|
|
background_border: None,
|
|
|
|
|
//TODO: Grab neutral from palette
|
2023-02-22 14:06:09 -05:00
|
|
|
foreground: theme.palette.neutral_2.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
foreground_border: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-03 21:35:35 +01:00
|
|
|
fn hovered(&self, style: &Self::Style, is_active: bool) -> toggler::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
let cosmic = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
//TODO: grab colors from palette
|
2023-02-27 18:45:54 -05:00
|
|
|
let mut neutral_10 = cosmic.palette.neutral_10;
|
2023-02-27 17:42:17 -05:00
|
|
|
neutral_10.alpha = 0.1;
|
|
|
|
|
toggler::Appearance {
|
|
|
|
|
background: if is_active {
|
|
|
|
|
cosmic.accent.hover
|
|
|
|
|
} else {
|
|
|
|
|
neutral_10
|
|
|
|
|
}
|
|
|
|
|
.into(),
|
|
|
|
|
..self.active(style, is_active)
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Pane Grid
|
|
|
|
|
*/
|
|
|
|
|
impl pane_grid::StyleSheet for Theme {
|
|
|
|
|
type Style = ();
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn picked_split(&self, _style: &Self::Style) -> Option<pane_grid::Line> {
|
2023-02-22 14:06:09 -05:00
|
|
|
let theme = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
Some(pane_grid::Line {
|
2023-02-22 14:06:09 -05:00
|
|
|
color: theme.accent.base.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
width: 2.0,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn hovered_split(&self, _style: &Self::Style) -> Option<pane_grid::Line> {
|
2023-02-22 14:06:09 -05:00
|
|
|
let theme = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
Some(pane_grid::Line {
|
2023-02-22 14:06:09 -05:00
|
|
|
color: theme.accent.hover.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
width: 2.0,
|
|
|
|
|
})
|
|
|
|
|
}
|
2023-06-15 11:16:32 -04:00
|
|
|
|
2023-07-17 11:44:57 -04:00
|
|
|
fn hovered_region(&self, _style: &Self::Style) -> pane_grid::Appearance {
|
2023-06-15 11:16:32 -04:00
|
|
|
let theme = self.cosmic();
|
|
|
|
|
pane_grid::Appearance {
|
|
|
|
|
background: Background::Color(theme.bg_color().into()),
|
|
|
|
|
border_width: 2.0,
|
|
|
|
|
border_color: theme.bg_divider().into(),
|
|
|
|
|
border_radius: 0.0.into(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Progress Bar
|
|
|
|
|
*/
|
2023-04-28 16:04:57 -07:00
|
|
|
#[derive(Default)]
|
2022-10-28 21:59:41 -07:00
|
|
|
pub enum ProgressBar {
|
2023-04-28 16:04:57 -07:00
|
|
|
#[default]
|
2022-10-28 21:59:41 -07:00
|
|
|
Primary,
|
|
|
|
|
Success,
|
|
|
|
|
Danger,
|
2023-04-28 16:04:57 -07:00
|
|
|
Custom(Box<dyn Fn(&Theme) -> progress_bar::Appearance>),
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
impl ProgressBar {
|
|
|
|
|
pub fn custom<F: Fn(&Theme) -> progress_bar::Appearance + 'static>(f: F) -> Self {
|
|
|
|
|
Self::Custom(Box::new(f))
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl progress_bar::StyleSheet for Theme {
|
|
|
|
|
type Style = ProgressBar;
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn appearance(&self, style: &Self::Style) -> progress_bar::Appearance {
|
2023-02-22 14:06:09 -05:00
|
|
|
let theme = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
match style {
|
2023-02-22 15:08:43 -05:00
|
|
|
ProgressBar::Primary => progress_bar::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(theme.background.divider).into(),
|
2023-02-22 15:08:43 -05:00
|
|
|
bar: Color::from(theme.accent.base).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 2.0.into(),
|
2023-02-22 15:08:43 -05:00
|
|
|
},
|
|
|
|
|
ProgressBar::Success => progress_bar::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(theme.background.divider).into(),
|
2023-02-22 15:08:43 -05:00
|
|
|
bar: Color::from(theme.success.base).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 2.0.into(),
|
2023-02-22 15:08:43 -05:00
|
|
|
},
|
|
|
|
|
ProgressBar::Danger => progress_bar::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(theme.background.divider).into(),
|
2023-02-22 15:08:43 -05:00
|
|
|
bar: Color::from(theme.destructive.base).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 2.0.into(),
|
2023-02-22 15:08:43 -05:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
ProgressBar::Custom(f) => f(self),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Rule
|
|
|
|
|
*/
|
2023-04-28 16:04:57 -07:00
|
|
|
#[derive(Default)]
|
2022-10-28 21:59:41 -07:00
|
|
|
pub enum Rule {
|
2023-04-28 16:04:57 -07:00
|
|
|
#[default]
|
2022-10-28 21:59:41 -07:00
|
|
|
Default,
|
2023-01-24 21:13:50 +01:00
|
|
|
LightDivider,
|
|
|
|
|
HeavyDivider,
|
2023-04-28 16:04:57 -07:00
|
|
|
Custom(Box<dyn Fn(&Theme) -> rule::Appearance>),
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
impl Rule {
|
|
|
|
|
pub fn custom<F: Fn(&Theme) -> rule::Appearance + 'static>(f: F) -> Self {
|
|
|
|
|
Self::Custom(Box::new(f))
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl rule::StyleSheet for Theme {
|
|
|
|
|
type Style = Rule;
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn appearance(&self, style: &Self::Style) -> rule::Appearance {
|
2022-10-28 21:59:41 -07:00
|
|
|
match style {
|
|
|
|
|
Rule::Default => rule::Appearance {
|
2023-02-27 19:56:53 -05:00
|
|
|
color: self.current_container().divider.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
width: 1,
|
2023-06-15 11:16:32 -04:00
|
|
|
radius: 0.0.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
fill_mode: rule::FillMode::Full,
|
|
|
|
|
},
|
2023-02-27 19:56:53 -05:00
|
|
|
Rule::LightDivider => rule::Appearance {
|
|
|
|
|
color: self.current_container().divider.into(),
|
|
|
|
|
width: 1,
|
2023-06-15 11:16:32 -04:00
|
|
|
radius: 0.0.into(),
|
2023-02-27 19:56:53 -05:00
|
|
|
fill_mode: rule::FillMode::Padded(10),
|
|
|
|
|
},
|
|
|
|
|
Rule::HeavyDivider => rule::Appearance {
|
|
|
|
|
color: self.current_container().divider.into(),
|
|
|
|
|
width: 4,
|
2023-06-15 11:16:32 -04:00
|
|
|
radius: 4.0.into(),
|
2023-02-27 19:56:53 -05:00
|
|
|
fill_mode: rule::FillMode::Full,
|
|
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
Rule::Custom(f) => f(self),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: Scrollable
|
|
|
|
|
*/
|
|
|
|
|
impl scrollable::StyleSheet for Theme {
|
|
|
|
|
type Style = ();
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn active(&self, _style: &Self::Style) -> scrollable::Scrollbar {
|
2022-10-28 21:59:41 -07:00
|
|
|
scrollable::Scrollbar {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Some(Background::Color(
|
2023-02-27 19:56:53 -05:00
|
|
|
self.current_container().component.base.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
)),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 4.0.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
scroller: scrollable::Scroller {
|
2023-02-27 19:56:53 -05:00
|
|
|
color: self.current_container().component.divider.into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 4.0.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-30 12:03:15 -04:00
|
|
|
fn hovered(
|
|
|
|
|
&self,
|
|
|
|
|
_style: &Self::Style,
|
|
|
|
|
_is_mouse_over_scrollbar: bool,
|
|
|
|
|
) -> scrollable::Scrollbar {
|
2023-02-22 14:06:09 -05:00
|
|
|
let theme = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
|
|
|
|
scrollable::Scrollbar {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Some(Background::Color(
|
2023-02-27 19:56:53 -05:00
|
|
|
self.current_container().component.hover.into(),
|
2023-02-27 17:42:17 -05:00
|
|
|
)),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 4.0.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
scroller: scrollable::Scroller {
|
2023-02-22 14:06:09 -05:00
|
|
|
color: theme.accent.base.into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 4.0.into(),
|
2022-10-28 21:59:41 -07:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
#[derive(Clone, Default)]
|
2022-11-01 13:06:00 +01:00
|
|
|
pub enum Svg {
|
2022-12-06 16:12:59 +01:00
|
|
|
/// Apply a custom appearance filter
|
2023-04-28 16:04:57 -07:00
|
|
|
Custom(Rc<dyn Fn(&Theme) -> svg::Appearance>),
|
2022-12-06 16:12:59 +01:00
|
|
|
/// No filtering is applied
|
2022-11-01 13:06:00 +01:00
|
|
|
#[default]
|
|
|
|
|
Default,
|
2022-12-06 16:12:59 +01:00
|
|
|
/// Icon fill color will match text color
|
|
|
|
|
Symbolic,
|
|
|
|
|
/// Icon fill color will match accent color
|
|
|
|
|
SymbolicActive,
|
2022-12-19 15:42:31 -07:00
|
|
|
/// Icon fill color will match on primary color
|
|
|
|
|
SymbolicPrimary,
|
2022-12-20 16:02:44 -07:00
|
|
|
/// Icon fill color will use accent color
|
|
|
|
|
SymbolicLink,
|
2022-12-06 16:12:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Hash for Svg {
|
|
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
|
|
|
let id = match self {
|
|
|
|
|
Svg::Custom(_) => 0,
|
|
|
|
|
Svg::Default => 1,
|
|
|
|
|
Svg::Symbolic => 2,
|
2022-12-19 15:42:31 -07:00
|
|
|
Svg::SymbolicActive => 3,
|
|
|
|
|
Svg::SymbolicPrimary => 4,
|
2022-12-20 16:02:44 -07:00
|
|
|
Svg::SymbolicLink => 5,
|
2022-12-06 16:12:59 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
id.hash(state);
|
|
|
|
|
}
|
2022-11-01 13:06:00 +01:00
|
|
|
}
|
|
|
|
|
|
2023-04-28 16:04:57 -07:00
|
|
|
impl Svg {
|
|
|
|
|
pub fn custom<F: Fn(&Theme) -> svg::Appearance + 'static>(f: F) -> Self {
|
|
|
|
|
Self::Custom(Rc::new(f))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-01 13:06:00 +01:00
|
|
|
impl svg::StyleSheet for Theme {
|
|
|
|
|
type Style = Svg;
|
|
|
|
|
|
2022-12-19 17:03:13 +01:00
|
|
|
fn appearance(&self, style: &Self::Style) -> svg::Appearance {
|
2022-12-23 15:10:13 +01:00
|
|
|
#[allow(clippy::match_same_arms)]
|
2022-11-01 13:06:00 +01:00
|
|
|
match style {
|
2022-12-06 16:12:59 +01:00
|
|
|
Svg::Default => svg::Appearance::default(),
|
2022-11-01 13:06:00 +01:00
|
|
|
Svg::Custom(appearance) => appearance(self),
|
2022-12-06 16:12:59 +01:00
|
|
|
Svg::Symbolic => svg::Appearance {
|
2023-02-27 19:56:53 -05:00
|
|
|
color: Some(self.current_container().on.into()),
|
2022-12-06 16:12:59 +01:00
|
|
|
},
|
|
|
|
|
Svg::SymbolicActive => svg::Appearance {
|
2022-12-19 17:03:13 +01:00
|
|
|
color: Some(self.cosmic().accent.base.into()),
|
2022-11-01 13:06:00 +01:00
|
|
|
},
|
2022-12-19 15:42:31 -07:00
|
|
|
Svg::SymbolicPrimary => svg::Appearance {
|
|
|
|
|
color: Some(self.cosmic().accent.on.into()),
|
|
|
|
|
},
|
2022-12-20 16:02:44 -07:00
|
|
|
Svg::SymbolicLink => svg::Appearance {
|
|
|
|
|
color: Some(self.cosmic().accent.base.into()),
|
|
|
|
|
},
|
2022-11-01 13:06:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 21:59:41 -07:00
|
|
|
/*
|
|
|
|
|
* TODO: Text
|
|
|
|
|
*/
|
2022-11-01 18:13:00 +01:00
|
|
|
#[derive(Clone, Copy, Default)]
|
2022-10-28 21:59:41 -07:00
|
|
|
pub enum Text {
|
2022-11-01 18:13:00 +01:00
|
|
|
Accent,
|
|
|
|
|
#[default]
|
2022-10-28 21:59:41 -07:00
|
|
|
Default,
|
|
|
|
|
Color(Color),
|
2023-04-28 16:04:57 -07:00
|
|
|
// TODO: Can't use dyn Fn since this must be copy
|
2023-05-30 12:03:15 -04:00
|
|
|
Custom(fn(&Theme) -> iced_widget::text::Appearance),
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<Color> for Text {
|
|
|
|
|
fn from(color: Color) -> Self {
|
|
|
|
|
Text::Color(color)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-30 12:03:15 -04:00
|
|
|
impl iced_widget::text::StyleSheet for Theme {
|
2022-10-28 21:59:41 -07:00
|
|
|
type Style = Text;
|
|
|
|
|
|
2023-05-30 12:03:15 -04:00
|
|
|
fn appearance(&self, style: Self::Style) -> iced_widget::text::Appearance {
|
2022-10-28 21:59:41 -07:00
|
|
|
match style {
|
2023-05-30 12:03:15 -04:00
|
|
|
Text::Accent => iced_widget::text::Appearance {
|
2022-11-11 05:06:54 +01:00
|
|
|
color: Some(self.cosmic().accent.base.into()),
|
2022-11-01 18:13:00 +01:00
|
|
|
},
|
2023-05-30 12:03:15 -04:00
|
|
|
Text::Default => iced_widget::text::Appearance { color: None },
|
|
|
|
|
Text::Color(c) => iced_widget::text::Appearance { color: Some(c) },
|
2022-10-28 21:59:41 -07:00
|
|
|
Text::Custom(f) => f(self),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-25 04:12:56 +01:00
|
|
|
#[derive(Copy, Clone, Default)]
|
|
|
|
|
pub enum TextInput {
|
|
|
|
|
#[default]
|
|
|
|
|
Default,
|
|
|
|
|
Search,
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 21:59:41 -07:00
|
|
|
/*
|
|
|
|
|
* TODO: Text Input
|
|
|
|
|
*/
|
|
|
|
|
impl text_input::StyleSheet for Theme {
|
2023-01-25 04:12:56 +01:00
|
|
|
type Style = TextInput;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-01-25 04:12:56 +01:00
|
|
|
fn active(&self, style: &Self::Style) -> text_input::Appearance {
|
2023-02-22 14:06:09 -05:00
|
|
|
let palette = self.cosmic();
|
2023-02-27 17:42:17 -05:00
|
|
|
let mut bg = palette.palette.neutral_7;
|
2023-03-02 16:51:32 -05:00
|
|
|
bg.alpha = 0.25;
|
2023-01-25 04:12:56 +01:00
|
|
|
match style {
|
|
|
|
|
TextInput::Default => text_input::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(bg).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 8.0.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
border_width: 1.0,
|
2023-02-27 19:56:53 -05:00
|
|
|
border_color: self.current_container().component.divider.into(),
|
2023-05-30 12:03:15 -04:00
|
|
|
icon_color: self.current_container().on.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
},
|
|
|
|
|
TextInput::Search => text_input::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(bg).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 24.0.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
2023-05-30 12:03:15 -04:00
|
|
|
icon_color: self.current_container().on.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-25 04:12:56 +01:00
|
|
|
fn hovered(&self, style: &Self::Style) -> text_input::Appearance {
|
2023-02-22 14:06:09 -05:00
|
|
|
let palette = self.cosmic();
|
2023-02-27 17:42:17 -05:00
|
|
|
let mut bg = palette.palette.neutral_7;
|
2023-03-02 16:51:32 -05:00
|
|
|
bg.alpha = 0.25;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-01-25 04:12:56 +01:00
|
|
|
match style {
|
|
|
|
|
TextInput::Default => text_input::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(bg).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 8.0.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
border_width: 1.0,
|
2023-02-27 17:42:17 -05:00
|
|
|
border_color: palette.accent.base.into(),
|
2023-05-30 12:03:15 -04:00
|
|
|
icon_color: self.current_container().on.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
},
|
|
|
|
|
TextInput::Search => text_input::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(bg).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 24.0.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
2023-05-30 12:03:15 -04:00
|
|
|
icon_color: self.current_container().on.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-25 04:12:56 +01:00
|
|
|
fn focused(&self, style: &Self::Style) -> text_input::Appearance {
|
2023-02-22 14:06:09 -05:00
|
|
|
let palette = self.cosmic();
|
2023-02-27 17:42:17 -05:00
|
|
|
let mut bg = palette.palette.neutral_7;
|
2023-03-02 16:51:32 -05:00
|
|
|
bg.alpha = 0.25;
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-01-25 04:12:56 +01:00
|
|
|
match style {
|
|
|
|
|
TextInput::Default => text_input::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(bg).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 8.0.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
border_width: 1.0,
|
2023-02-22 14:06:09 -05:00
|
|
|
border_color: palette.accent.base.into(),
|
2023-05-30 12:03:15 -04:00
|
|
|
icon_color: self.current_container().on.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
},
|
|
|
|
|
TextInput::Search => text_input::Appearance {
|
2023-02-27 17:42:17 -05:00
|
|
|
background: Color::from(bg).into(),
|
2023-06-15 11:16:32 -04:00
|
|
|
border_radius: 24.0.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
border_width: 0.0,
|
|
|
|
|
border_color: Color::TRANSPARENT,
|
2023-05-30 12:03:15 -04:00
|
|
|
icon_color: self.current_container().on.into(),
|
2023-01-25 04:12:56 +01:00
|
|
|
},
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn placeholder_color(&self, _style: &Self::Style) -> Color {
|
2023-02-22 14:06:09 -05:00
|
|
|
let palette = self.cosmic();
|
2023-02-27 17:42:17 -05:00
|
|
|
let mut neutral_9 = palette.palette.neutral_9;
|
|
|
|
|
neutral_9.alpha = 0.7;
|
|
|
|
|
neutral_9.into()
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn value_color(&self, _style: &Self::Style) -> Color {
|
2023-02-22 14:06:09 -05:00
|
|
|
let palette = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-02-27 17:42:17 -05:00
|
|
|
palette.palette.neutral_9.into()
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:19:13 +01:00
|
|
|
fn selection_color(&self, _style: &Self::Style) -> Color {
|
2023-02-22 14:06:09 -05:00
|
|
|
let palette = self.cosmic();
|
2022-10-28 21:59:41 -07:00
|
|
|
|
2023-02-27 17:42:17 -05:00
|
|
|
palette.accent.base.into()
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
2023-05-30 12:03:15 -04:00
|
|
|
|
|
|
|
|
fn disabled_color(&self, _style: &Self::Style) -> Color {
|
2023-07-25 18:56:01 -07:00
|
|
|
let palette = self.cosmic();
|
|
|
|
|
let mut neutral_9 = palette.palette.neutral_9;
|
|
|
|
|
neutral_9.alpha = 0.5;
|
|
|
|
|
neutral_9.into()
|
2023-05-30 12:03:15 -04:00
|
|
|
}
|
|
|
|
|
|
2023-07-25 18:56:01 -07:00
|
|
|
fn disabled(&self, style: &Self::Style) -> text_input::Appearance {
|
|
|
|
|
self.active(style)
|
2023-05-30 12:03:15 -04:00
|
|
|
}
|
2022-10-28 21:59:41 -07:00
|
|
|
}
|
2023-06-12 12:08:14 -04:00
|
|
|
|
2023-08-03 19:30:08 -04:00
|
|
|
#[must_use]
|
2023-06-12 12:08:14 -04:00
|
|
|
pub fn theme() -> Theme {
|
|
|
|
|
let Ok(helper) = crate::cosmic_config::Config::new(
|
|
|
|
|
crate::cosmic_theme::NAME,
|
|
|
|
|
crate::cosmic_theme::Theme::<CssColor>::version(),
|
|
|
|
|
) else {
|
|
|
|
|
return crate::theme::Theme::dark();
|
|
|
|
|
};
|
2023-08-03 19:30:08 -04:00
|
|
|
let t = crate::cosmic_theme::Theme::get_entry(&helper).unwrap_or_else(|(errors, theme)| {
|
|
|
|
|
for err in errors {
|
|
|
|
|
tracing::error!("{:?}", err);
|
|
|
|
|
}
|
|
|
|
|
theme
|
|
|
|
|
});
|
2023-08-04 15:48:34 -04:00
|
|
|
crate::theme::Theme::system(Arc::new(t))
|
2023-06-12 12:08:14 -04:00
|
|
|
}
|
|
|
|
|
|
2023-08-02 11:54:07 +02:00
|
|
|
pub fn subscription(id: u64) -> Subscription<crate::theme::Theme> {
|
2023-08-03 19:30:08 -04:00
|
|
|
config_subscription::<u64, crate::cosmic_theme::Theme<Srgba>>(
|
2023-06-12 12:08:14 -04:00
|
|
|
id,
|
|
|
|
|
crate::cosmic_theme::NAME.into(),
|
2023-08-03 19:30:08 -04:00
|
|
|
crate::cosmic_theme::Theme::<Srgba>::version(),
|
2023-06-12 12:08:14 -04:00
|
|
|
)
|
|
|
|
|
.map(|(_, res)| {
|
2023-08-03 19:30:08 -04:00
|
|
|
let theme = res.unwrap_or_else(|(errors, theme)| {
|
|
|
|
|
for err in errors {
|
|
|
|
|
tracing::error!("{:?}", err);
|
|
|
|
|
}
|
|
|
|
|
theme
|
|
|
|
|
});
|
2023-08-04 15:48:34 -04:00
|
|
|
|
|
|
|
|
crate::theme::Theme::system(Arc::new(theme))
|
2023-06-12 12:08:14 -04:00
|
|
|
})
|
|
|
|
|
}
|
2023-07-17 11:44:57 -04:00
|
|
|
|
|
|
|
|
impl crate::widget::card::style::StyleSheet for Theme {
|
|
|
|
|
fn default(&self) -> crate::widget::card::style::Appearance {
|
|
|
|
|
let cosmic = self.cosmic();
|
|
|
|
|
|
|
|
|
|
match self.layer {
|
|
|
|
|
cosmic_theme::Layer::Background => crate::widget::card::style::Appearance {
|
|
|
|
|
card_1: Background::Color(cosmic.background.component.hover.into()),
|
|
|
|
|
card_2: Background::Color(cosmic.background.component.pressed.into()),
|
|
|
|
|
},
|
|
|
|
|
cosmic_theme::Layer::Primary => crate::widget::card::style::Appearance {
|
|
|
|
|
card_1: Background::Color(cosmic.primary.component.hover.into()),
|
|
|
|
|
card_2: Background::Color(cosmic.primary.component.pressed.into()),
|
|
|
|
|
},
|
|
|
|
|
cosmic_theme::Layer::Secondary => crate::widget::card::style::Appearance {
|
|
|
|
|
card_1: Background::Color(cosmic.secondary.component.hover.into()),
|
|
|
|
|
card_2: Background::Color(cosmic.secondary.component.pressed.into()),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|