summaryrefslogtreecommitdiff
path: root/material_theme/src
diff options
context:
space:
mode:
Diffstat (limited to 'material_theme/src')
-rw-r--r--material_theme/src/lib.rs49
-rw-r--r--material_theme/src/menu.rs16
-rw-r--r--material_theme/src/pick_list.rs40
-rw-r--r--material_theme/src/utils.rs38
4 files changed, 98 insertions, 45 deletions
diff --git a/material_theme/src/lib.rs b/material_theme/src/lib.rs
index ba9d478..521af2c 100644
--- a/material_theme/src/lib.rs
+++ b/material_theme/src/lib.rs
@@ -9,6 +9,7 @@ pub mod container;
#[cfg(feature = "dialog")]
pub mod dialog;
pub mod menu;
+pub mod pick_list;
pub mod scrollable;
pub mod text;
pub mod utils;
@@ -62,6 +63,12 @@ impl Default for Theme {
}
}
+impl std::fmt::Display for Theme {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.name)
+ }
+}
+
impl Base for Theme {
fn base(&self) -> Style {
Style {
@@ -121,6 +128,8 @@ pub struct ColorScheme {
pub outline: Outline,
#[serde(with = "color_serde")]
pub shadow: Color,
+ #[serde(with = "color_serde")]
+ pub scrim: Color,
}
#[derive(Debug, Clone, Copy, PartialEq, Deserialize)]
@@ -222,49 +231,11 @@ pub struct Outline {
pub variant: Color,
}
-pub fn parse_argb(s: &str) -> Option<Color> {
- let hex = s.strip_prefix('#').unwrap_or(s);
-
- let parse_channel = |from: usize, to: usize| {
- let num =
- usize::from_str_radix(&hex[from..=to], 16).ok()? as f32 / 255.0;
-
- // If we only got half a byte (one letter), expand it into a full byte (two letters)
- Some(if from == to { num + num * 16.0 } else { num })
- };
-
- Some(match hex.len() {
- 3 => Color::from_rgb(
- parse_channel(0, 0)?,
- parse_channel(1, 1)?,
- parse_channel(2, 2)?,
- ),
- 4 => Color::from_rgba(
- parse_channel(1, 1)?,
- parse_channel(2, 2)?,
- parse_channel(3, 3)?,
- parse_channel(0, 0)?,
- ),
- 6 => Color::from_rgb(
- parse_channel(0, 1)?,
- parse_channel(2, 3)?,
- parse_channel(4, 5)?,
- ),
- 8 => Color::from_rgba(
- parse_channel(2, 3)?,
- parse_channel(4, 5)?,
- parse_channel(6, 7)?,
- parse_channel(0, 1)?,
- ),
- _ => None?,
- })
-}
-
mod color_serde {
use iced_widget::core::Color;
use serde::{Deserialize, Deserializer};
- use super::parse_argb;
+ use super::utils::parse_argb;
pub fn deserialize<'de, D>(deserializer: D) -> Result<Color, D::Error>
where
diff --git a/material_theme/src/menu.rs b/material_theme/src/menu.rs
index d1bebec..9f43c72 100644
--- a/material_theme/src/menu.rs
+++ b/material_theme/src/menu.rs
@@ -2,6 +2,7 @@ use iced_widget::core::{Background, border};
use iced_widget::overlay::menu::{Catalog, Style, StyleFn};
use super::Theme;
+use crate::utils::{HOVERED_LAYER_OPACITY, mix};
impl Catalog for Theme {
type Class<'a> = StyleFn<'a, Self>;
@@ -16,14 +17,17 @@ impl Catalog for Theme {
}
pub fn default(theme: &Theme) -> Style {
- let surface = theme.colorscheme.surface;
- let secondary = theme.colorscheme.secondary;
+ let colors = theme.colorscheme.surface;
Style {
border: border::rounded(4),
- background: Background::Color(surface.surface_container.base),
- text_color: surface.on_surface,
- selected_background: Background::Color(secondary.secondary_container),
- selected_text_color: secondary.on_secondary_container,
+ background: Background::Color(colors.surface_container.base),
+ text_color: colors.on_surface,
+ selected_background: Background::Color(mix(
+ colors.surface_container.base,
+ colors.on_surface,
+ HOVERED_LAYER_OPACITY,
+ )),
+ selected_text_color: colors.on_surface,
}
}
diff --git a/material_theme/src/pick_list.rs b/material_theme/src/pick_list.rs
new file mode 100644
index 0000000..c589100
--- /dev/null
+++ b/material_theme/src/pick_list.rs
@@ -0,0 +1,40 @@
+use iced_widget::core::{Background, border};
+use iced_widget::pick_list::{Catalog, Status, Style, StyleFn};
+
+use super::Theme;
+
+impl Catalog for Theme {
+ type Class<'a> = StyleFn<'a, Self>;
+
+ fn default<'a>() -> <Self as Catalog>::Class<'a> {
+ Box::new(default)
+ }
+
+ fn style(
+ &self,
+ class: &<Self as Catalog>::Class<'_>,
+ status: Status,
+ ) -> Style {
+ class(self, status)
+ }
+}
+
+pub fn default(theme: &Theme, status: Status) -> Style {
+ let surface = theme.colorscheme.surface;
+
+ let active = Style {
+ text_color: surface.on_surface,
+ placeholder_color: surface.on_surface_variant,
+ handle_color: surface.on_surface_variant,
+ background: Background::Color(surface.surface_container.highest),
+ border: border::rounded(4),
+ };
+
+ match status {
+ Status::Active => active,
+ Status::Hovered | Status::Opened { .. } => Style {
+ background: Background::Color(surface.surface_container.highest),
+ ..active
+ },
+ }
+}
diff --git a/material_theme/src/utils.rs b/material_theme/src/utils.rs
index 7efec9b..a05bc62 100644
--- a/material_theme/src/utils.rs
+++ b/material_theme/src/utils.rs
@@ -28,6 +28,44 @@ pub fn shadow_from_elevation(elevation: f32, color: Color) -> Shadow {
}
}
+pub fn parse_argb(s: &str) -> Option<Color> {
+ let hex = s.strip_prefix('#').unwrap_or(s);
+
+ let parse_channel = |from: usize, to: usize| {
+ let num =
+ usize::from_str_radix(&hex[from..=to], 16).ok()? as f32 / 255.0;
+
+ // If we only got half a byte (one letter), expand it into a full byte (two letters)
+ Some(if from == to { num + num * 16.0 } else { num })
+ };
+
+ Some(match hex.len() {
+ 3 => Color::from_rgb(
+ parse_channel(0, 0)?,
+ parse_channel(1, 1)?,
+ parse_channel(2, 2)?,
+ ),
+ 4 => Color::from_rgba(
+ parse_channel(1, 1)?,
+ parse_channel(2, 2)?,
+ parse_channel(3, 3)?,
+ parse_channel(0, 0)?,
+ ),
+ 6 => Color::from_rgb(
+ parse_channel(0, 1)?,
+ parse_channel(2, 3)?,
+ parse_channel(4, 5)?,
+ ),
+ 8 => Color::from_rgba(
+ parse_channel(2, 3)?,
+ parse_channel(4, 5)?,
+ parse_channel(6, 7)?,
+ parse_channel(0, 1)?,
+ ),
+ _ => None?,
+ })
+}
+
pub fn mix(color1: Color, color2: Color, p2: f32) -> Color {
if p2 <= 0.0 {
return color1;