From 664251f3f5c7b76f69a97683af1468094bba887f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 14 May 2022 01:47:55 +0200 Subject: Draft first-class `Theme` support RFC: https://github.com/iced-rs/rfcs/pull/6 --- style/src/button.rs | 46 +++++++++------------------------------------- style/src/lib.rs | 3 +++ style/src/theme.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 37 deletions(-) create mode 100644 style/src/theme.rs (limited to 'style/src') diff --git a/style/src/button.rs b/style/src/button.rs index de2de4f4..9f00185c 100644 --- a/style/src/button.rs +++ b/style/src/button.rs @@ -27,10 +27,12 @@ impl std::default::Default for Style { /// A set of rules that dictate the style of a button. pub trait StyleSheet { - fn active(&self) -> Style; + type Variant; - fn hovered(&self) -> Style { - let active = self.active(); + fn active(&self, variant: Self::Variant) -> Style; + + fn hovered(&self, variant: Self::Variant) -> Style { + let active = self.active(variant); Style { shadow_offset: active.shadow_offset + Vector::new(0.0, 1.0), @@ -38,15 +40,15 @@ pub trait StyleSheet { } } - fn pressed(&self) -> Style { + fn pressed(&self, variant: Self::Variant) -> Style { Style { shadow_offset: Vector::default(), - ..self.active() + ..self.active(variant) } } - fn disabled(&self) -> Style { - let active = self.active(); + fn disabled(&self, variant: Self::Variant) -> Style { + let active = self.active(variant); Style { shadow_offset: Vector::default(), @@ -64,33 +66,3 @@ pub trait StyleSheet { } } } - -struct Default; - -impl StyleSheet for Default { - fn active(&self) -> Style { - Style { - shadow_offset: Vector::new(0.0, 0.0), - background: Some(Background::Color([0.87, 0.87, 0.87].into())), - border_radius: 2.0, - border_width: 1.0, - border_color: [0.7, 0.7, 0.7].into(), - text_color: Color::BLACK, - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} - -impl<'a, T> From for Box -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) - } -} diff --git a/style/src/lib.rs b/style/src/lib.rs index e4556f67..d9c3259e 100644 --- a/style/src/lib.rs +++ b/style/src/lib.rs @@ -21,4 +21,7 @@ pub mod rule; pub mod scrollable; pub mod slider; pub mod text_input; +pub mod theme; pub mod toggler; + +pub use theme::Theme; diff --git a/style/src/theme.rs b/style/src/theme.rs new file mode 100644 index 00000000..7d420c8a --- /dev/null +++ b/style/src/theme.rs @@ -0,0 +1,45 @@ +use crate::button; + +use iced_core::{Color, Vector}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Theme { + Light, + Dark, +} + +impl Default for Theme { + fn default() -> Self { + Self::Light + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Button { + Primary, + Secondary, + Positive, + Destructive, + Text, +} + +impl Default for Button { + fn default() -> Self { + Self::Primary + } +} + +impl button::StyleSheet for Theme { + type Variant = Button; + + fn active(&self, _variant: Self::Variant) -> button::Style { + button::Style { + shadow_offset: Vector::default(), + background: None, + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + text_color: Color::BLACK, + } + } +} -- cgit From 2cfb307f8c3927a0876c6b754a5d7d673b9edfee Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 21 May 2022 17:33:31 -0400 Subject: Implement basic theming `Palette` --- style/src/theme.rs | 79 ++++++++++++++++-- style/src/theme/palette.rs | 202 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 273 insertions(+), 8 deletions(-) create mode 100644 style/src/theme/palette.rs (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index 7d420c8a..91a9e921 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -1,6 +1,10 @@ +mod palette; + +pub use self::palette::Palette; + use crate::button; -use iced_core::{Color, Vector}; +use iced_core::Background; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Theme { @@ -8,6 +12,22 @@ pub enum Theme { Dark, } +impl Theme { + pub fn palette(self) -> Palette { + match self { + Self::Light => Palette::LIGHT, + Self::Dark => Palette::DARK, + } + } + + fn extended_palette(&self) -> &palette::Extended { + match self { + Self::Light => &palette::EXTENDED_LIGHT, + Self::Dark => &palette::EXTENDED_DARK, + } + } +} + impl Default for Theme { fn default() -> Self { Self::Light @@ -32,14 +52,57 @@ impl Default for Button { impl button::StyleSheet for Theme { type Variant = Button; - fn active(&self, _variant: Self::Variant) -> button::Style { + fn active(&self, variant: Self::Variant) -> button::Style { + let palette = self.extended_palette(); + + let style = button::Style { + border_radius: 2.0, + ..button::Style::default() + }; + + match variant { + Button::Primary => button::Style { + background: Some(palette.primary.strong.into()), + text_color: palette.primary.text, + ..style + }, + Button::Secondary => button::Style { + background: Some(palette.background.weak.into()), + text_color: palette.background.text, + ..style + }, + Button::Positive => button::Style { + background: Some(palette.success.base.into()), + text_color: palette.success.text, + ..style + }, + Button::Destructive => button::Style { + background: Some(palette.danger.base.into()), + text_color: palette.danger.text, + ..style + }, + Button::Text => button::Style { + text_color: palette.background.text, + ..style + }, + } + } + + fn hovered(&self, variant: Self::Variant) -> button::Style { + let active = self.active(variant); + let palette = self.extended_palette(); + + let background = match variant { + Button::Primary => Some(palette.primary.base), + Button::Secondary => Some(palette.background.strong), + Button::Positive => Some(palette.success.strong), + Button::Destructive => Some(palette.danger.strong), + Button::Text => None, + }; + button::Style { - shadow_offset: Vector::default(), - background: None, - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - text_color: Color::BLACK, + background: background.map(Background::from), + ..active } } } diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs new file mode 100644 index 00000000..74139e6b --- /dev/null +++ b/style/src/theme/palette.rs @@ -0,0 +1,202 @@ +use iced_core::Color; + +use lazy_static::lazy_static; +use palette::{FromColor, Hsl, Mix, RelativeContrast, Srgb}; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Palette { + background: Color, + text: Color, + primary: Color, + success: Color, + danger: Color, +} + +impl Palette { + pub const LIGHT: Self = Self { + background: Color::WHITE, + text: Color::BLACK, + primary: Color::from_rgb( + 0x5E as f32 / 255.0, + 0x7C as f32 / 255.0, + 0xE2 as f32 / 255.0, + ), + success: Color::from_rgb( + 0x12 as f32 / 255.0, + 0x66 as f32 / 255.0, + 0x4F as f32 / 255.0, + ), + danger: Color::from_rgb( + 0xC3 as f32 / 255.0, + 0x42 as f32 / 255.0, + 0x3F as f32 / 255.0, + ), + }; + + pub const DARK: Self = Self { + background: Color::WHITE, + text: Color::BLACK, + primary: Color::from_rgb( + 0x5E as f32 / 255.0, + 0x7C as f32 / 255.0, + 0xE2 as f32 / 255.0, + ), + success: Color::from_rgb( + 0x12 as f32 / 255.0, + 0x66 as f32 / 255.0, + 0x4F as f32 / 255.0, + ), + danger: Color::from_rgb( + 0xC3 as f32 / 255.0, + 0x42 as f32 / 255.0, + 0x3F as f32 / 255.0, + ), + }; +} + +pub struct Extended { + pub background: Background, + pub primary: Group, + pub success: Group, + pub danger: Group, +} + +lazy_static! { + pub static ref EXTENDED_LIGHT: Extended = + Extended::generate(Palette::LIGHT); + pub static ref EXTENDED_DARK: Extended = Extended::generate(Palette::DARK); +} + +impl Extended { + pub fn generate(palette: Palette) -> Self { + Self { + background: Background::new(palette.background, palette.text), + primary: Group::new( + palette.primary, + palette.background, + palette.text, + ), + success: Group::new( + palette.success, + palette.background, + palette.text, + ), + danger: Group::new( + palette.danger, + palette.background, + palette.text, + ), + } + } +} + +pub struct Background { + pub base: Color, + pub weak: Color, + pub strong: Color, + pub text: Color, +} + +impl Background { + pub fn new(base: Color, text: Color) -> Self { + Self { + base, + weak: muted(base, 0.1), + strong: muted(base, 0.2), + text, + } + } +} + +pub struct Group { + pub base: Color, + pub weak: Color, + pub strong: Color, + pub text: Color, +} + +impl Group { + pub fn new(base: Color, background: Color, text: Color) -> Self { + Self { + base, + weak: mix(base, background, 0.4), + strong: if is_dark(background) { + lighten(base, 0.1) + } else { + darken(base, 0.1) + }, + text: if is_readable(base, text) { + text + } else if is_dark(text) { + Color::WHITE + } else { + Color::BLACK + }, + } + } +} + +fn muted(color: Color, amount: f32) -> Color { + let mut hsl = to_hsl(color); + + hsl.lightness = if is_dark(color) { + let delta = amount * (1.0 - hsl.lightness).powi(7); + hsl.lightness + delta + } else { + let delta = amount * hsl.lightness.powi(5); + hsl.lightness - delta + }; + + from_hsl(hsl) +} + +fn darken(color: Color, amount: f32) -> Color { + let mut hsl = to_hsl(color); + + hsl.lightness = if hsl.lightness - amount < 0.0 { + 0.0 + } else { + hsl.lightness - amount + }; + + from_hsl(hsl) +} + +fn mix(a: Color, b: Color, factor: f32) -> Color { + let a_lin = Srgb::from(a).into_linear(); + let b_lin = Srgb::from(b).into_linear(); + + let mixed = a_lin.mix(&b_lin, factor); + Srgb::from_linear(mixed).into() +} + +fn lighten(color: Color, amount: f32) -> Color { + let mut hsl = to_hsl(color); + + hsl.lightness = if hsl.lightness + amount > 1.0 { + 1.0 + } else { + hsl.lightness + amount + }; + + from_hsl(hsl) +} + +fn is_dark(color: Color) -> bool { + to_hsl(color).lightness < 0.5 +} + +fn is_readable(a: Color, b: Color) -> bool { + let a_srgb = Srgb::from(a); + let b_srgb = Srgb::from(b); + + a_srgb.has_enhanced_contrast_text(&b_srgb) +} + +fn to_hsl(color: Color) -> Hsl { + Hsl::from_color(Srgb::from(color)) +} + +fn from_hsl(hsl: Hsl) -> Color { + Srgb::from_color(hsl).into() +} -- cgit From 03eda9b162012c503ead649e5ccb95b7ef1d10ed Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 25 May 2022 05:01:18 +0200 Subject: Let a `Theme` control the background color of an application ... and remove `Application::background_color` --- style/src/theme.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index 91a9e921..16f24923 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -4,7 +4,7 @@ pub use self::palette::Palette; use crate::button; -use iced_core::Background; +use iced_core::{Background, Color}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Theme { @@ -34,6 +34,18 @@ impl Default for Theme { } } +pub trait Definition { + fn background_color(&self) -> Color; +} + +impl Definition for Theme { + fn background_color(&self) -> Color { + let palette = self.extended_palette(); + + palette.background.base + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Button { Primary, -- cgit From 3a820b45f336398c48f8bedf7b8c4b8af876efff Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 26 May 2022 00:40:27 +0200 Subject: Implement theme styling for `Slider` --- style/src/slider.rs | 66 ++++------------------------------------------ style/src/theme.rs | 54 +++++++++++++++++++++++++++++++++++++ style/src/theme/palette.rs | 2 ++ 3 files changed, 61 insertions(+), 61 deletions(-) (limited to 'style/src') diff --git a/style/src/slider.rs b/style/src/slider.rs index 1bb28b09..2bf0de73 100644 --- a/style/src/slider.rs +++ b/style/src/slider.rs @@ -26,70 +26,14 @@ pub enum HandleShape { /// A set of rules that dictate the style of a slider. pub trait StyleSheet { + type Variant: Default + Copy; + /// Produces the style of an active slider. - fn active(&self) -> Style; + fn active(&self, variant: Self::Variant) -> Style; /// Produces the style of an hovered slider. - fn hovered(&self) -> Style; + fn hovered(&self, variant: Self::Variant) -> Style; /// Produces the style of a slider that is being dragged. - fn dragging(&self) -> Style; -} - -struct Default; - -impl StyleSheet for Default { - fn active(&self) -> Style { - Style { - rail_colors: ([0.6, 0.6, 0.6, 0.5].into(), Color::WHITE), - handle: Handle { - shape: HandleShape::Rectangle { - width: 8, - border_radius: 4.0, - }, - color: Color::from_rgb(0.95, 0.95, 0.95), - border_color: Color::from_rgb(0.6, 0.6, 0.6), - border_width: 1.0, - }, - } - } - - fn hovered(&self) -> Style { - let active = self.active(); - - Style { - handle: Handle { - color: Color::from_rgb(0.90, 0.90, 0.90), - ..active.handle - }, - ..active - } - } - - fn dragging(&self) -> Style { - let active = self.active(); - - Style { - handle: Handle { - color: Color::from_rgb(0.85, 0.85, 0.85), - ..active.handle - }, - ..active - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} - -impl<'a, T> From for Box -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) - } + fn dragging(&self, variant: Self::Variant) -> Style; } diff --git a/style/src/theme.rs b/style/src/theme.rs index 16f24923..e3c0efc6 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -3,6 +3,7 @@ mod palette; pub use self::palette::Palette; use crate::button; +use crate::slider; use iced_core::{Background, Color}; @@ -118,3 +119,56 @@ impl button::StyleSheet for Theme { } } } + +impl slider::StyleSheet for Theme { + type Variant = (); + + fn active(&self, _variant: Self::Variant) -> slider::Style { + let palette = self.extended_palette(); + + let handle = slider::Handle { + shape: slider::HandleShape::Rectangle { + width: 8, + border_radius: 4.0, + }, + color: Color::WHITE, + border_color: Color::WHITE, + border_width: 1.0, + }; + + slider::Style { + rail_colors: (palette.background.strong, palette.background.base), + handle: slider::Handle { + color: palette.background.base, + border_color: palette.border, + ..handle + }, + } + } + + fn hovered(&self, variant: Self::Variant) -> slider::Style { + let active = self.active(variant); + let palette = self.extended_palette(); + + slider::Style { + handle: slider::Handle { + color: palette.background.weak, + ..active.handle + }, + ..active + } + } + + fn dragging(&self, variant: Self::Variant) -> slider::Style { + let active = self.active(variant); + let palette = self.extended_palette(); + + slider::Style { + handle: slider::Handle { + color: palette.background.strong, + ..active.handle + }, + ..active + } + } +} diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs index 74139e6b..bbb122ef 100644 --- a/style/src/theme/palette.rs +++ b/style/src/theme/palette.rs @@ -59,6 +59,7 @@ pub struct Extended { pub primary: Group, pub success: Group, pub danger: Group, + pub border: Color, } lazy_static! { @@ -86,6 +87,7 @@ impl Extended { palette.background, palette.text, ), + border: mix(palette.background, palette.text, 0.7), } } } -- cgit From 822a3cd04f9edeb887d85164b0b3e556c3fde6bb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 26 May 2022 01:10:26 +0200 Subject: Let a `Theme` control the `text_color` of an application --- style/src/theme.rs | 10 +++++++++- style/src/theme/palette.rs | 40 +++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 16 deletions(-) (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index e3c0efc6..1ddf97c3 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -31,12 +31,14 @@ impl Theme { impl Default for Theme { fn default() -> Self { - Self::Light + Self::Dark } } pub trait Definition { fn background_color(&self) -> Color; + + fn text_color(&self) -> Color; } impl Definition for Theme { @@ -45,6 +47,12 @@ impl Definition for Theme { palette.background.base } + + fn text_color(&self) -> Color { + let palette = self.extended_palette(); + + palette.background.text + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs index bbb122ef..0394700b 100644 --- a/style/src/theme/palette.rs +++ b/style/src/theme/palette.rs @@ -34,8 +34,12 @@ impl Palette { }; pub const DARK: Self = Self { - background: Color::WHITE, - text: Color::BLACK, + background: Color::from_rgb( + 0x20 as f32 / 255.0, + 0x22 as f32 / 255.0, + 0x25 as f32 / 255.0, + ), + text: Color::from_rgb(0.90, 0.90, 0.90), primary: Color::from_rgb( 0x5E as f32 / 255.0, 0x7C as f32 / 255.0, @@ -119,21 +123,17 @@ pub struct Group { impl Group { pub fn new(base: Color, background: Color, text: Color) -> Self { + let strong = if is_dark(base) { + lighten(base, 0.1) + } else { + darken(base, 0.1) + }; + Self { base, weak: mix(base, background, 0.4), - strong: if is_dark(background) { - lighten(base, 0.1) - } else { - darken(base, 0.1) - }, - text: if is_readable(base, text) { - text - } else if is_dark(text) { - Color::WHITE - } else { - Color::BLACK - }, + strong, + text: readable(strong, text), } } } @@ -184,8 +184,18 @@ fn lighten(color: Color, amount: f32) -> Color { from_hsl(hsl) } +fn readable(background: Color, text: Color) -> Color { + if is_readable(background, text) { + text + } else if is_dark(background) { + Color::WHITE + } else { + Color::BLACK + } +} + fn is_dark(color: Color) -> bool { - to_hsl(color).lightness < 0.5 + to_hsl(color).lightness < 0.6 } fn is_readable(a: Color, b: Color) -> bool { -- cgit From 5a39dad506a1614fd0ccacb1f56e83acbaf4961a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 26 May 2022 05:31:25 +0200 Subject: Tweak styling of `Slider` and improve contrast of `Background` --- style/src/theme.rs | 10 +++++----- style/src/theme/palette.rs | 24 +++++++++++------------- 2 files changed, 16 insertions(+), 18 deletions(-) (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index 1ddf97c3..cf939824 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -31,7 +31,7 @@ impl Theme { impl Default for Theme { fn default() -> Self { - Self::Dark + Self::Light } } @@ -145,10 +145,10 @@ impl slider::StyleSheet for Theme { }; slider::Style { - rail_colors: (palette.background.strong, palette.background.base), + rail_colors: (palette.primary.base, palette.background.base), handle: slider::Handle { color: palette.background.base, - border_color: palette.border, + border_color: palette.primary.base, ..handle }, } @@ -160,7 +160,7 @@ impl slider::StyleSheet for Theme { slider::Style { handle: slider::Handle { - color: palette.background.weak, + color: palette.primary.weak, ..active.handle }, ..active @@ -173,7 +173,7 @@ impl slider::StyleSheet for Theme { slider::Style { handle: slider::Handle { - color: palette.background.strong, + color: palette.primary.base, ..active.handle }, ..active diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs index 0394700b..acc147ed 100644 --- a/style/src/theme/palette.rs +++ b/style/src/theme/palette.rs @@ -63,7 +63,6 @@ pub struct Extended { pub primary: Group, pub success: Group, pub danger: Group, - pub border: Color, } lazy_static! { @@ -91,7 +90,6 @@ impl Extended { palette.background, palette.text, ), - border: mix(palette.background, palette.text, 0.7), } } } @@ -107,8 +105,8 @@ impl Background { pub fn new(base: Color, text: Color) -> Self { Self { base, - weak: muted(base, 0.1), - strong: muted(base, 0.2), + weak: mix(base, text, 0.15), + strong: mix(base, text, 0.25), text, } } @@ -142,7 +140,7 @@ fn muted(color: Color, amount: f32) -> Color { let mut hsl = to_hsl(color); hsl.lightness = if is_dark(color) { - let delta = amount * (1.0 - hsl.lightness).powi(7); + let delta = amount * (1.0 - hsl.lightness).powi(5); hsl.lightness + delta } else { let delta = amount * hsl.lightness.powi(5); @@ -164,14 +162,6 @@ fn darken(color: Color, amount: f32) -> Color { from_hsl(hsl) } -fn mix(a: Color, b: Color, factor: f32) -> Color { - let a_lin = Srgb::from(a).into_linear(); - let b_lin = Srgb::from(b).into_linear(); - - let mixed = a_lin.mix(&b_lin, factor); - Srgb::from_linear(mixed).into() -} - fn lighten(color: Color, amount: f32) -> Color { let mut hsl = to_hsl(color); @@ -184,6 +174,14 @@ fn lighten(color: Color, amount: f32) -> Color { from_hsl(hsl) } +fn mix(a: Color, b: Color, factor: f32) -> Color { + let a_lin = Srgb::from(a).into_linear(); + let b_lin = Srgb::from(b).into_linear(); + + let mixed = a_lin.mix(&b_lin, factor); + Srgb::from_linear(mixed).into() +} + fn readable(background: Color, text: Color) -> Color { if is_readable(background, text) { text -- cgit From 7f3b7075db68a215f4331b4bfba1c8ddd1c4d7f3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 26 May 2022 19:02:15 +0200 Subject: Rename `theme::Definition` to `application::StyleSheet` --- style/src/application.rs | 7 +++++++ style/src/lib.rs | 1 + style/src/theme.rs | 9 ++------- 3 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 style/src/application.rs (limited to 'style/src') diff --git a/style/src/application.rs b/style/src/application.rs new file mode 100644 index 00000000..4aa950fb --- /dev/null +++ b/style/src/application.rs @@ -0,0 +1,7 @@ +use iced_core::Color; + +pub trait StyleSheet { + fn background_color(&self) -> Color; + + fn text_color(&self) -> Color; +} diff --git a/style/src/lib.rs b/style/src/lib.rs index d9c3259e..4a0a6a14 100644 --- a/style/src/lib.rs +++ b/style/src/lib.rs @@ -9,6 +9,7 @@ )] pub use iced_core::{Background, Color}; +pub mod application; pub mod button; pub mod checkbox; pub mod container; diff --git a/style/src/theme.rs b/style/src/theme.rs index cf939824..9cfbd1d5 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -2,6 +2,7 @@ mod palette; pub use self::palette::Palette; +use crate::application; use crate::button; use crate::slider; @@ -35,13 +36,7 @@ impl Default for Theme { } } -pub trait Definition { - fn background_color(&self) -> Color; - - fn text_color(&self) -> Color; -} - -impl Definition for Theme { +impl application::StyleSheet for Theme { fn background_color(&self) -> Color { let palette = self.extended_palette(); -- cgit From cf0230072c01ea9523f4d98a3656f5c975b3f347 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 26 May 2022 23:07:34 +0200 Subject: Rename `Variant` to `Style` and `Style` to `Appearance` --- style/src/button.rs | 26 ++++++++++++------------- style/src/slider.rs | 10 +++++----- style/src/theme.rs | 56 ++++++++++++++++++++++++++--------------------------- 3 files changed, 46 insertions(+), 46 deletions(-) (limited to 'style/src') diff --git a/style/src/button.rs b/style/src/button.rs index 9f00185c..c63a6b71 100644 --- a/style/src/button.rs +++ b/style/src/button.rs @@ -3,7 +3,7 @@ use iced_core::{Background, Color, Vector}; /// The appearance of a button. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub shadow_offset: Vector, pub background: Option, pub border_radius: f32, @@ -12,7 +12,7 @@ pub struct Style { pub text_color: Color, } -impl std::default::Default for Style { +impl std::default::Default for Appearance { fn default() -> Self { Self { shadow_offset: Vector::default(), @@ -27,30 +27,30 @@ impl std::default::Default for Style { /// A set of rules that dictate the style of a button. pub trait StyleSheet { - type Variant; + type Style: Default + Copy; - fn active(&self, variant: Self::Variant) -> Style; + fn active(&self, style: Self::Style) -> Appearance; - fn hovered(&self, variant: Self::Variant) -> Style { - let active = self.active(variant); + fn hovered(&self, style: Self::Style) -> Appearance { + let active = self.active(style); - Style { + Appearance { shadow_offset: active.shadow_offset + Vector::new(0.0, 1.0), ..active } } - fn pressed(&self, variant: Self::Variant) -> Style { - Style { + fn pressed(&self, style: Self::Style) -> Appearance { + Appearance { shadow_offset: Vector::default(), - ..self.active(variant) + ..self.active(style) } } - fn disabled(&self, variant: Self::Variant) -> Style { - let active = self.active(variant); + fn disabled(&self, style: Self::Style) -> Appearance { + let active = self.active(style); - Style { + Appearance { shadow_offset: Vector::default(), background: active.background.map(|background| match background { Background::Color(color) => Background::Color(Color { diff --git a/style/src/slider.rs b/style/src/slider.rs index 2bf0de73..0ff0449b 100644 --- a/style/src/slider.rs +++ b/style/src/slider.rs @@ -3,7 +3,7 @@ use iced_core::Color; /// The appearance of a slider. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub rail_colors: (Color, Color), pub handle: Handle, } @@ -26,14 +26,14 @@ pub enum HandleShape { /// A set of rules that dictate the style of a slider. pub trait StyleSheet { - type Variant: Default + Copy; + type Style: Default + Copy; /// Produces the style of an active slider. - fn active(&self, variant: Self::Variant) -> Style; + fn active(&self, style: Self::Style) -> Appearance; /// Produces the style of an hovered slider. - fn hovered(&self, variant: Self::Variant) -> Style; + fn hovered(&self, style: Self::Style) -> Appearance; /// Produces the style of a slider that is being dragged. - fn dragging(&self, variant: Self::Variant) -> Style; + fn dragging(&self, style: Self::Style) -> Appearance; } diff --git a/style/src/theme.rs b/style/src/theme.rs index 9cfbd1d5..df67f594 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -66,49 +66,49 @@ impl Default for Button { } impl button::StyleSheet for Theme { - type Variant = Button; + type Style = Button; - fn active(&self, variant: Self::Variant) -> button::Style { + fn active(&self, style: Self::Style) -> button::Appearance { let palette = self.extended_palette(); - let style = button::Style { + let appearance = button::Appearance { border_radius: 2.0, - ..button::Style::default() + ..button::Appearance::default() }; - match variant { - Button::Primary => button::Style { + match style { + Button::Primary => button::Appearance { background: Some(palette.primary.strong.into()), text_color: palette.primary.text, - ..style + ..appearance }, - Button::Secondary => button::Style { + Button::Secondary => button::Appearance { background: Some(palette.background.weak.into()), text_color: palette.background.text, - ..style + ..appearance }, - Button::Positive => button::Style { + Button::Positive => button::Appearance { background: Some(palette.success.base.into()), text_color: palette.success.text, - ..style + ..appearance }, - Button::Destructive => button::Style { + Button::Destructive => button::Appearance { background: Some(palette.danger.base.into()), text_color: palette.danger.text, - ..style + ..appearance }, - Button::Text => button::Style { + Button::Text => button::Appearance { text_color: palette.background.text, - ..style + ..appearance }, } } - fn hovered(&self, variant: Self::Variant) -> button::Style { - let active = self.active(variant); + fn hovered(&self, style: Self::Style) -> button::Appearance { + let active = self.active(style); let palette = self.extended_palette(); - let background = match variant { + let background = match style { Button::Primary => Some(palette.primary.base), Button::Secondary => Some(palette.background.strong), Button::Positive => Some(palette.success.strong), @@ -116,7 +116,7 @@ impl button::StyleSheet for Theme { Button::Text => None, }; - button::Style { + button::Appearance { background: background.map(Background::from), ..active } @@ -124,9 +124,9 @@ impl button::StyleSheet for Theme { } impl slider::StyleSheet for Theme { - type Variant = (); + type Style = (); - fn active(&self, _variant: Self::Variant) -> slider::Style { + fn active(&self, _style: Self::Style) -> slider::Appearance { let palette = self.extended_palette(); let handle = slider::Handle { @@ -139,7 +139,7 @@ impl slider::StyleSheet for Theme { border_width: 1.0, }; - slider::Style { + slider::Appearance { rail_colors: (palette.primary.base, palette.background.base), handle: slider::Handle { color: palette.background.base, @@ -149,11 +149,11 @@ impl slider::StyleSheet for Theme { } } - fn hovered(&self, variant: Self::Variant) -> slider::Style { - let active = self.active(variant); + fn hovered(&self, style: Self::Style) -> slider::Appearance { + let active = self.active(style); let palette = self.extended_palette(); - slider::Style { + slider::Appearance { handle: slider::Handle { color: palette.primary.weak, ..active.handle @@ -162,11 +162,11 @@ impl slider::StyleSheet for Theme { } } - fn dragging(&self, variant: Self::Variant) -> slider::Style { - let active = self.active(variant); + fn dragging(&self, style: Self::Style) -> slider::Appearance { + let active = self.active(style); let palette = self.extended_palette(); - slider::Style { + slider::Appearance { handle: slider::Handle { color: palette.primary.base, ..active.handle -- cgit From d988d813d77bc23147a179586206048e6cc42157 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 26 May 2022 23:58:56 +0200 Subject: Introduce specific types for each `palette::Extended` field We will have more control over color calculations for each semantic purpose this way. --- style/src/theme.rs | 54 +++++++----------- style/src/theme/palette.rs | 139 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 131 insertions(+), 62 deletions(-) (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index df67f594..c9fae3c2 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -40,13 +40,13 @@ impl application::StyleSheet for Theme { fn background_color(&self) -> Color { let palette = self.extended_palette(); - palette.background.base + palette.background.base.color } fn text_color(&self) -> Color { let palette = self.extended_palette(); - palette.background.text + palette.background.base.text } } @@ -76,29 +76,19 @@ impl button::StyleSheet for Theme { ..button::Appearance::default() }; + let from_pair = |pair: palette::Pair| button::Appearance { + background: Some(pair.color.into()), + text_color: pair.text, + ..appearance + }; + match style { - Button::Primary => button::Appearance { - background: Some(palette.primary.strong.into()), - text_color: palette.primary.text, - ..appearance - }, - Button::Secondary => button::Appearance { - background: Some(palette.background.weak.into()), - text_color: palette.background.text, - ..appearance - }, - Button::Positive => button::Appearance { - background: Some(palette.success.base.into()), - text_color: palette.success.text, - ..appearance - }, - Button::Destructive => button::Appearance { - background: Some(palette.danger.base.into()), - text_color: palette.danger.text, - ..appearance - }, + Button::Primary => from_pair(palette.primary.strong), + Button::Secondary => from_pair(palette.secondary.base), + Button::Positive => from_pair(palette.success.base), + Button::Destructive => from_pair(palette.danger.base), Button::Text => button::Appearance { - text_color: palette.background.text, + text_color: palette.background.base.text, ..appearance }, } @@ -109,10 +99,10 @@ impl button::StyleSheet for Theme { let palette = self.extended_palette(); let background = match style { - Button::Primary => Some(palette.primary.base), - Button::Secondary => Some(palette.background.strong), - Button::Positive => Some(palette.success.strong), - Button::Destructive => Some(palette.danger.strong), + Button::Primary => Some(palette.primary.base.color), + Button::Secondary => Some(palette.background.strong.color), + Button::Positive => Some(palette.success.strong.color), + Button::Destructive => Some(palette.danger.strong.color), Button::Text => None, }; @@ -140,10 +130,10 @@ impl slider::StyleSheet for Theme { }; slider::Appearance { - rail_colors: (palette.primary.base, palette.background.base), + rail_colors: (palette.primary.base.color, Color::TRANSPARENT), handle: slider::Handle { - color: palette.background.base, - border_color: palette.primary.base, + color: palette.background.base.color, + border_color: palette.primary.base.color, ..handle }, } @@ -155,7 +145,7 @@ impl slider::StyleSheet for Theme { slider::Appearance { handle: slider::Handle { - color: palette.primary.weak, + color: palette.primary.weak.color, ..active.handle }, ..active @@ -168,7 +158,7 @@ impl slider::StyleSheet for Theme { slider::Appearance { handle: slider::Handle { - color: palette.primary.base, + color: palette.primary.base.color, ..active.handle }, ..active diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs index acc147ed..3d1ca097 100644 --- a/style/src/theme/palette.rs +++ b/style/src/theme/palette.rs @@ -60,9 +60,10 @@ impl Palette { pub struct Extended { pub background: Background, - pub primary: Group, - pub success: Group, - pub danger: Group, + pub primary: Primary, + pub secondary: Secondary, + pub success: Success, + pub danger: Danger, } lazy_static! { @@ -75,17 +76,18 @@ impl Extended { pub fn generate(palette: Palette) -> Self { Self { background: Background::new(palette.background, palette.text), - primary: Group::new( + primary: Primary::generate( palette.primary, palette.background, palette.text, ), - success: Group::new( + secondary: Secondary::generate(palette.background, palette.text), + success: Success::generate( palette.success, palette.background, palette.text, ), - danger: Group::new( + danger: Danger::generate( palette.danger, palette.background, palette.text, @@ -94,44 +96,113 @@ impl Extended { } } -pub struct Background { - pub base: Color, - pub weak: Color, - pub strong: Color, +#[derive(Debug, Clone, Copy)] +pub struct Pair { + pub color: Color, pub text: Color, } +impl Pair { + pub fn new(color: Color, text: Color) -> Self { + Self { + color, + text: readable(color, text), + } + } +} + +pub struct Background { + pub base: Pair, + pub weak: Pair, + pub strong: Pair, +} + impl Background { pub fn new(base: Color, text: Color) -> Self { + let weak = mix(base, text, 0.15); + let strong = mix(base, text, 0.25); + Self { - base, - weak: mix(base, text, 0.15), - strong: mix(base, text, 0.25), - text, + base: Pair::new(base, text), + weak: Pair::new(weak, text), + strong: Pair::new(strong, text), } } } -pub struct Group { - pub base: Color, - pub weak: Color, - pub strong: Color, - pub text: Color, +pub struct Primary { + pub base: Pair, + pub weak: Pair, + pub strong: Pair, +} + +impl Primary { + pub fn generate(base: Color, background: Color, text: Color) -> Self { + let weak = mix(base, background, 0.4); + let strong = deviate(base, 0.1); + + Self { + base: Pair::new(base, text), + weak: Pair::new(weak, text), + strong: Pair::new(strong, text), + } + } } -impl Group { - pub fn new(base: Color, background: Color, text: Color) -> Self { - let strong = if is_dark(base) { - lighten(base, 0.1) - } else { - darken(base, 0.1) - }; +pub struct Secondary { + pub base: Pair, + pub weak: Pair, + pub strong: Pair, +} + +impl Secondary { + pub fn generate(base: Color, text: Color) -> Self { + let base = mix(base, text, 0.2); + let weak = mix(base, text, 0.1); + let strong = mix(base, text, 0.3); Self { - base, - weak: mix(base, background, 0.4), - strong, - text: readable(strong, text), + base: Pair::new(base, text), + weak: Pair::new(weak, text), + strong: Pair::new(strong, text), + } + } +} + +pub struct Success { + pub base: Pair, + pub weak: Pair, + pub strong: Pair, +} + +impl Success { + pub fn generate(base: Color, background: Color, text: Color) -> Self { + let weak = mix(base, background, 0.4); + let strong = deviate(base, 0.1); + + Self { + base: Pair::new(base, text), + weak: Pair::new(weak, text), + strong: Pair::new(strong, text), + } + } +} + +pub struct Danger { + pub base: Pair, + pub weak: Pair, + pub strong: Pair, +} + +impl Danger { + pub fn generate(base: Color, background: Color, text: Color) -> Self { + let weak = mix(base, background, 0.4); + let strong = deviate(base, 0.1); + + Self { + base: Pair::new(base, text), + weak: Pair::new(weak, text), + strong: Pair::new(strong, text), } } } @@ -174,6 +245,14 @@ fn lighten(color: Color, amount: f32) -> Color { from_hsl(hsl) } +fn deviate(color: Color, amount: f32) -> Color { + if is_dark(color) { + lighten(color, amount) + } else { + darken(color, amount) + } +} + fn mix(a: Color, b: Color, factor: f32) -> Color { let a_lin = Srgb::from(a).into_linear(); let b_lin = Srgb::from(b).into_linear(); -- cgit From 28d09bfff1dde55190986bab10d7aaeb0ceb49de Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 27 May 2022 01:26:57 +0200 Subject: Implement theme styling for `Radio` --- style/src/radio.rs | 42 ++++-------------------------------------- style/src/theme.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 38 deletions(-) (limited to 'style/src') diff --git a/style/src/radio.rs b/style/src/radio.rs index dab76ad8..a4d4a83b 100644 --- a/style/src/radio.rs +++ b/style/src/radio.rs @@ -3,7 +3,7 @@ use iced_core::{Background, Color}; /// The appearance of a radio button. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub background: Background, pub dot_color: Color, pub border_width: f32, @@ -13,43 +13,9 @@ pub struct Style { /// A set of rules that dictate the style of a radio button. pub trait StyleSheet { - fn active(&self) -> Style; + type Style: Default + Copy; - fn hovered(&self) -> Style; -} - -struct Default; - -impl StyleSheet for Default { - fn active(&self) -> Style { - Style { - background: Background::Color(Color::from_rgb(0.95, 0.95, 0.95)), - dot_color: Color::from_rgb(0.3, 0.3, 0.3), - border_width: 1.0, - border_color: Color::from_rgb(0.6, 0.6, 0.6), - text_color: None, - } - } - - fn hovered(&self) -> Style { - Style { - background: Background::Color(Color::from_rgb(0.90, 0.90, 0.90)), - ..self.active() - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} + fn active(&self, style: Self::Style) -> Appearance; -impl<'a, T> From for Box -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) - } + fn hovered(&self, style: Self::Style) -> Appearance; } diff --git a/style/src/theme.rs b/style/src/theme.rs index c9fae3c2..e3b151aa 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -4,6 +4,7 @@ pub use self::palette::Palette; use crate::application; use crate::button; +use crate::radio; use crate::slider; use iced_core::{Background, Color}; @@ -165,3 +166,30 @@ impl slider::StyleSheet for Theme { } } } + +impl radio::StyleSheet for Theme { + type Style = (); + + fn active(&self, _style: Self::Style) -> radio::Appearance { + let palette = self.extended_palette(); + + radio::Appearance { + background: Color::TRANSPARENT.into(), + dot_color: palette.primary.strong.color.into(), + border_width: 1.0, + border_color: palette.primary.strong.color, + text_color: None, + } + } + + fn hovered(&self, style: Self::Style) -> radio::Appearance { + let active = self.active(style); + let palette = self.extended_palette(); + + radio::Appearance { + dot_color: palette.primary.weak.text.into(), + background: palette.primary.weak.color.into(), + ..active + } + } +} -- cgit From 3e2b6247f72815b6e928237f242c2d66478cf15d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 31 May 2022 05:13:57 +0200 Subject: Implement theme styling for `Toggler` ... and wire up theming to the `styling` example. --- style/src/theme.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ style/src/toggler.rs | 45 ++++----------------------------------- 2 files changed, 64 insertions(+), 41 deletions(-) (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index e3b151aa..2f9fd4fa 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -6,6 +6,7 @@ use crate::application; use crate::button; use crate::radio; use crate::slider; +use crate::toggler; use iced_core::{Background, Color}; @@ -51,6 +52,9 @@ impl application::StyleSheet for Theme { } } +/* + * Button + */ #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Button { Primary, @@ -114,6 +118,9 @@ impl button::StyleSheet for Theme { } } +/* + * Slider + */ impl slider::StyleSheet for Theme { type Style = (); @@ -167,6 +174,9 @@ impl slider::StyleSheet for Theme { } } +/* + * Radio + */ impl radio::StyleSheet for Theme { type Style = (); @@ -193,3 +203,53 @@ impl radio::StyleSheet for Theme { } } } + +/* + * Toggler + */ +impl toggler::StyleSheet for Theme { + type Style = (); + + fn active( + &self, + _style: Self::Style, + is_active: bool, + ) -> toggler::Appearance { + let palette = self.extended_palette(); + + toggler::Appearance { + background: if is_active { + palette.primary.strong.color + } else { + palette.background.strong.color + }, + background_border: None, + foreground: if is_active { + palette.primary.strong.text + } else { + palette.background.base.color + }, + foreground_border: None, + } + } + + fn hovered( + &self, + style: Self::Style, + is_active: bool, + ) -> toggler::Appearance { + let palette = self.extended_palette(); + + toggler::Appearance { + foreground: if is_active { + Color { + a: 0.5, + ..palette.primary.strong.text + } + } else { + palette.background.weak.color + }, + ..self.active(style, is_active) + } + } +} diff --git a/style/src/toggler.rs b/style/src/toggler.rs index c06a8cd1..4ee7db46 100644 --- a/style/src/toggler.rs +++ b/style/src/toggler.rs @@ -3,7 +3,7 @@ use iced_core::Color; /// The appearance of a toggler. #[derive(Debug)] -pub struct Style { +pub struct Appearance { pub background: Color, pub background_border: Option, pub foreground: Color, @@ -12,46 +12,9 @@ pub struct Style { /// A set of rules that dictate the style of a toggler. pub trait StyleSheet { - fn active(&self, is_active: bool) -> Style; + type Style: Default + Copy; - fn hovered(&self, is_active: bool) -> Style; -} - -struct Default; - -impl StyleSheet for Default { - fn active(&self, is_active: bool) -> Style { - Style { - background: if is_active { - Color::from_rgb(0.0, 1.0, 0.0) - } else { - Color::from_rgb(0.7, 0.7, 0.7) - }, - background_border: None, - foreground: Color::WHITE, - foreground_border: None, - } - } - - fn hovered(&self, is_active: bool) -> Style { - Style { - foreground: Color::from_rgb(0.95, 0.95, 0.95), - ..self.active(is_active) - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} + fn active(&self, style: Self::Style, is_active: bool) -> Appearance; -impl<'a, T> From for Box -where - T: 'a + StyleSheet, -{ - fn from(style: T) -> Self { - Box::new(style) - } + fn hovered(&self, style: Self::Style, is_active: bool) -> Appearance; } -- cgit From 6f69df3d415bfc922ce15539746026843bd410e6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 1 Jun 2022 01:44:59 +0200 Subject: Implement theme styling for `PaneGrid` --- style/src/pane_grid.rs | 33 ++++----------------------------- style/src/theme.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 29 deletions(-) (limited to 'style/src') diff --git a/style/src/pane_grid.rs b/style/src/pane_grid.rs index a12ac3f5..5bae353f 100644 --- a/style/src/pane_grid.rs +++ b/style/src/pane_grid.rs @@ -4,11 +4,13 @@ use iced_core::Color; /// A set of rules that dictate the style of a container. pub trait StyleSheet { + type Style: Default + Copy; + /// The [`Line`] to draw when a split is picked. - fn picked_split(&self) -> Option; + fn picked_split(&self, style: Self::Style) -> Option; /// The [`Line`] to draw when a split is hovered. - fn hovered_split(&self) -> Option; + fn hovered_split(&self, style: Self::Style) -> Option; } /// A line. @@ -22,30 +24,3 @@ pub struct Line { /// The width of the [`Line`]. pub width: f32, } - -struct Default; - -impl StyleSheet for Default { - fn picked_split(&self) -> Option { - None - } - - fn hovered_split(&self) -> Option { - None - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} - -impl<'a, T> From for Box -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) - } -} diff --git a/style/src/theme.rs b/style/src/theme.rs index 2f9fd4fa..71330c2e 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -4,6 +4,7 @@ pub use self::palette::Palette; use crate::application; use crate::button; +use crate::pane_grid; use crate::radio; use crate::slider; use crate::toggler; @@ -253,3 +254,28 @@ impl toggler::StyleSheet for Theme { } } } + +/* + * Pane Grid + */ +impl pane_grid::StyleSheet for Theme { + type Style = (); + + fn picked_split(&self, _style: Self::Style) -> Option { + let palette = self.extended_palette(); + + Some(pane_grid::Line { + color: palette.primary.strong.color, + width: 2.0, + }) + } + + fn hovered_split(&self, _style: Self::Style) -> Option { + let palette = self.extended_palette(); + + Some(pane_grid::Line { + color: palette.primary.base.color, + width: 2.0, + }) + } +} -- cgit From c275fde67a7f5d1d5789540dc7905250a2f01fe7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 1 Jun 2022 01:56:46 +0200 Subject: Implement theme styling for `Rule` --- style/src/rule.rs | 74 ++++++++++++++++-------------------------------------- style/src/theme.rs | 19 ++++++++++++++ 2 files changed, 40 insertions(+), 53 deletions(-) (limited to 'style/src') diff --git a/style/src/rule.rs b/style/src/rule.rs index 12a40f7d..af334912 100644 --- a/style/src/rule.rs +++ b/style/src/rule.rs @@ -1,6 +1,27 @@ //! Display a horizontal or vertical rule for dividing content. use iced_core::Color; +/// The appearance of a rule. +#[derive(Debug, Clone, Copy)] +pub struct Appearance { + /// The color of the rule. + pub color: Color, + /// The width (thickness) of the rule line. + pub width: u16, + /// The radius of the line corners. + pub radius: f32, + /// The [`FillMode`] of the rule. + pub fill_mode: FillMode, +} + +/// A set of rules that dictate the style of a rule. +pub trait StyleSheet { + type Style: Default + Copy; + + /// Produces the style of a rule. + fn style(&self, style: Self::Style) -> Appearance; +} + /// The fill mode of a rule. #[derive(Debug, Clone, Copy)] pub enum FillMode { @@ -64,56 +85,3 @@ impl FillMode { } } } - -/// The appearance of a rule. -#[derive(Debug, Clone, Copy)] -pub struct Style { - /// The color of the rule. - pub color: Color, - /// The width (thickness) of the rule line. - pub width: u16, - /// The radius of the line corners. - pub radius: f32, - /// The [`FillMode`] of the rule. - pub fill_mode: FillMode, -} - -impl std::default::Default for Style { - fn default() -> Self { - Style { - color: [0.6, 0.6, 0.6, 0.6].into(), - width: 1, - radius: 0.0, - fill_mode: FillMode::Full, - } - } -} - -/// A set of rules that dictate the style of a rule. -pub trait StyleSheet { - /// Produces the style of a rule. - fn style(&self) -> Style; -} - -struct Default; - -impl StyleSheet for Default { - fn style(&self) -> Style { - Style::default() - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} - -impl<'a, T> From for Box -where - T: 'a + StyleSheet, -{ - fn from(style: T) -> Self { - Box::new(style) - } -} diff --git a/style/src/theme.rs b/style/src/theme.rs index 71330c2e..713225e1 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -6,6 +6,7 @@ use crate::application; use crate::button; use crate::pane_grid; use crate::radio; +use crate::rule; use crate::slider; use crate::toggler; @@ -279,3 +280,21 @@ impl pane_grid::StyleSheet for Theme { }) } } + +/* + * Rule + */ +impl rule::StyleSheet for Theme { + type Style = (); + + fn style(&self, _style: Self::Style) -> rule::Appearance { + let palette = self.extended_palette(); + + rule::Appearance { + color: palette.background.strong.color, + width: 1, + radius: 0.0, + fill_mode: rule::FillMode::Full, + } + } +} -- cgit From e4ca779e436561bf48e5d34cdf554292fd4761e4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 1 Jun 2022 02:04:23 +0200 Subject: Introduce `Custom` style variant for `Rule` --- style/src/theme.rs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index 713225e1..71a25dbe 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -284,17 +284,32 @@ impl pane_grid::StyleSheet for Theme { /* * Rule */ +#[derive(Clone, Copy)] +pub enum Rule { + Default, + Custom(fn(&Theme) -> rule::Appearance), +} + +impl Default for Rule { + fn default() -> Self { + Self::Default + } +} + impl rule::StyleSheet for Theme { - type Style = (); + type Style = Rule; - fn style(&self, _style: Self::Style) -> rule::Appearance { + fn style(&self, style: Self::Style) -> rule::Appearance { let palette = self.extended_palette(); - rule::Appearance { - color: palette.background.strong.color, - width: 1, - radius: 0.0, - fill_mode: rule::FillMode::Full, + match style { + Rule::Default => rule::Appearance { + color: palette.background.strong.color, + width: 1, + radius: 0.0, + fill_mode: rule::FillMode::Full, + }, + Rule::Custom(f) => f(self), } } } -- cgit From 77dc9dc2cb4ac092ce88c2700253fbfc54292e2b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 1 Jun 2022 02:40:42 +0200 Subject: Implement theme styling for `ProgressBar` --- style/src/progress_bar.rs | 33 ++++----------------------------- style/src/theme.rs | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 29 deletions(-) (limited to 'style/src') diff --git a/style/src/progress_bar.rs b/style/src/progress_bar.rs index a0195c7a..768e7c9c 100644 --- a/style/src/progress_bar.rs +++ b/style/src/progress_bar.rs @@ -1,9 +1,9 @@ //! Provide progress feedback to your users. -use iced_core::{Background, Color}; +use iced_core::Background; /// The appearance of a progress bar. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub background: Background, pub bar: Background, pub border_radius: f32, @@ -11,32 +11,7 @@ pub struct Style { /// A set of rules that dictate the style of a progress bar. pub trait StyleSheet { - fn style(&self) -> Style; -} - -struct Default; - -impl StyleSheet for Default { - fn style(&self) -> Style { - Style { - background: Background::Color(Color::from_rgb(0.6, 0.6, 0.6)), - bar: Background::Color(Color::from_rgb(0.3, 0.9, 0.3)), - border_radius: 5.0, - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} + type Style: Default + Copy; -impl<'a, T> From for Box -where - T: 'a + StyleSheet, -{ - fn from(style: T) -> Self { - Box::new(style) - } + fn appearance(&self, style: Self::Style) -> Appearance; } diff --git a/style/src/theme.rs b/style/src/theme.rs index 71a25dbe..ca780457 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -5,6 +5,7 @@ pub use self::palette::Palette; use crate::application; use crate::button; use crate::pane_grid; +use crate::progress_bar; use crate::radio; use crate::rule; use crate::slider; @@ -281,6 +282,44 @@ impl pane_grid::StyleSheet for Theme { } } +/* + * Progress Bar + */ +#[derive(Clone, Copy)] +pub enum ProgressBar { + Primary, + Success, + Danger, + Custom(fn(&Theme) -> progress_bar::Appearance), +} + +impl Default for ProgressBar { + fn default() -> Self { + Self::Primary + } +} + +impl progress_bar::StyleSheet for Theme { + type Style = ProgressBar; + + fn appearance(&self, style: Self::Style) -> progress_bar::Appearance { + let palette = self.extended_palette(); + + let from_palette = |bar: Color| progress_bar::Appearance { + background: palette.background.weak.color.into(), + bar: bar.into(), + border_radius: 2.0, + }; + + match style { + ProgressBar::Primary => from_palette(palette.primary.base.color), + ProgressBar::Success => from_palette(palette.success.base.color), + ProgressBar::Danger => from_palette(palette.danger.base.color), + ProgressBar::Custom(f) => f(self), + } + } +} + /* * Rule */ -- cgit From 1388d71f0368731e7efd799ee274ede9b8d3c690 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 4 Jun 2022 03:04:43 +0200 Subject: Expose `palette` module in `theme` --- style/src/theme.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index ca780457..305c5cc2 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -1,4 +1,4 @@ -mod palette; +pub mod palette; pub use self::palette::Palette; @@ -27,7 +27,7 @@ impl Theme { } } - fn extended_palette(&self) -> &palette::Extended { + pub fn extended_palette(&self) -> &palette::Extended { match self { Self::Light => &palette::EXTENDED_LIGHT, Self::Dark => &palette::EXTENDED_DARK, -- cgit From 835877fc636d71c1faaa4826cbfde8e09b3c82ba Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 4 Jun 2022 03:26:53 +0200 Subject: Implement theme styling for `Checkbox` --- style/src/checkbox.rs | 43 ++------------------- style/src/theme.rs | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 39 deletions(-) (limited to 'style/src') diff --git a/style/src/checkbox.rs b/style/src/checkbox.rs index de52e548..ba54b0a2 100644 --- a/style/src/checkbox.rs +++ b/style/src/checkbox.rs @@ -3,7 +3,7 @@ use iced_core::{Background, Color}; /// The appearance of a checkbox. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub background: Background, pub checkmark_color: Color, pub border_radius: f32, @@ -14,44 +14,9 @@ pub struct Style { /// A set of rules that dictate the style of a checkbox. pub trait StyleSheet { - fn active(&self, is_checked: bool) -> Style; + type Style: Default + Copy; - fn hovered(&self, is_checked: bool) -> Style; -} - -struct Default; - -impl StyleSheet for Default { - fn active(&self, _is_checked: bool) -> Style { - Style { - background: Background::Color(Color::from_rgb(0.95, 0.95, 0.95)), - checkmark_color: Color::from_rgb(0.3, 0.3, 0.3), - border_radius: 5.0, - border_width: 1.0, - border_color: Color::from_rgb(0.6, 0.6, 0.6), - text_color: None, - } - } - - fn hovered(&self, is_checked: bool) -> Style { - Style { - background: Background::Color(Color::from_rgb(0.90, 0.90, 0.90)), - ..self.active(is_checked) - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} + fn active(&self, style: Self::Style, is_checked: bool) -> Appearance; -impl<'a, T> From for Box -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) - } + fn hovered(&self, style: Self::Style, is_checked: bool) -> Appearance; } diff --git a/style/src/theme.rs b/style/src/theme.rs index 305c5cc2..b0846c0e 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -4,6 +4,7 @@ pub use self::palette::Palette; use crate::application; use crate::button; +use crate::checkbox; use crate::pane_grid; use crate::progress_bar; use crate::radio; @@ -121,6 +122,109 @@ impl button::StyleSheet for Theme { } } +/* + * 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; + + fn active( + &self, + style: Self::Style, + is_checked: bool, + ) -> checkbox::Appearance { + let palette = self.extended_palette(); + + match style { + Checkbox::Primary => checkbox_appearance( + palette.background.weak, + palette.primary.strong, + is_checked, + ), + Checkbox::Secondary => checkbox_appearance( + palette.background.weak, + palette.background.base, + is_checked, + ), + Checkbox::Success => checkbox_appearance( + palette.background.weak, + palette.success.base, + is_checked, + ), + Checkbox::Danger => checkbox_appearance( + palette.background.weak, + palette.danger.base, + is_checked, + ), + } + } + + fn hovered( + &self, + style: Self::Style, + is_checked: bool, + ) -> checkbox::Appearance { + let palette = self.extended_palette(); + + match style { + Checkbox::Primary => checkbox_appearance( + palette.background.strong, + palette.primary.strong, + is_checked, + ), + Checkbox::Secondary => checkbox_appearance( + palette.background.strong, + palette.background.strong, + is_checked, + ), + Checkbox::Success => checkbox_appearance( + palette.background.strong, + palette.success.strong, + is_checked, + ), + Checkbox::Danger => checkbox_appearance( + palette.background.strong, + palette.danger.strong, + is_checked, + ), + } + } +} + +fn checkbox_appearance( + base: palette::Pair, + accent: palette::Pair, + is_checked: bool, +) -> checkbox::Appearance { + checkbox::Appearance { + background: Background::Color(if is_checked { + accent.color + } else { + base.color + }), + checkmark_color: accent.text, + border_radius: 2.0, + border_width: 1.0, + border_color: accent.color, + text_color: None, + } +} + /* * Slider */ -- cgit From ce53d3933c860cd958636cce415ac97c04aee746 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 7 Jun 2022 01:11:35 +0200 Subject: Implement theme styling for `TextInput` --- style/src/text_input.rs | 76 ++++++----------------------------------- style/src/theme.rs | 85 +++++++++++++++++++++++++++++++++++++++------- style/src/theme/palette.rs | 2 +- 3 files changed, 83 insertions(+), 80 deletions(-) (limited to 'style/src') diff --git a/style/src/text_input.rs b/style/src/text_input.rs index 3d5817cc..af86617b 100644 --- a/style/src/text_input.rs +++ b/style/src/text_input.rs @@ -3,87 +3,31 @@ use iced_core::{Background, Color}; /// The appearance of a text input. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub background: Background, pub border_radius: f32, pub border_width: f32, pub border_color: Color, } -impl std::default::Default for Style { - fn default() -> Self { - Self { - background: Background::Color(Color::WHITE), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - } - } -} - /// A set of rules that dictate the style of a text input. pub trait StyleSheet { + type Style: Default + Copy; + /// Produces the style of an active text input. - fn active(&self) -> Style; + fn active(&self, style: Self::Style) -> Appearance; /// Produces the style of a focused text input. - fn focused(&self) -> Style; + fn focused(&self, style: Self::Style) -> Appearance; - fn placeholder_color(&self) -> Color; + fn placeholder_color(&self, style: Self::Style) -> Color; - fn value_color(&self) -> Color; + fn value_color(&self, style: Self::Style) -> Color; - fn selection_color(&self) -> Color; + fn selection_color(&self, style: Self::Style) -> Color; /// Produces the style of an hovered text input. - fn hovered(&self) -> Style { - self.focused() - } -} - -struct Default; - -impl StyleSheet for Default { - fn active(&self) -> Style { - Style { - background: Background::Color(Color::WHITE), - border_radius: 5.0, - border_width: 1.0, - border_color: Color::from_rgb(0.7, 0.7, 0.7), - } - } - - fn focused(&self) -> Style { - Style { - border_color: Color::from_rgb(0.5, 0.5, 0.5), - ..self.active() - } - } - - fn placeholder_color(&self) -> Color { - Color::from_rgb(0.7, 0.7, 0.7) - } - - fn value_color(&self) -> Color { - Color::from_rgb(0.3, 0.3, 0.3) - } - - fn selection_color(&self) -> Color { - Color::from_rgb(0.8, 0.8, 1.0) - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} - -impl<'a, T> From for Box -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) + fn hovered(&self, style: Self::Style) -> Appearance { + self.focused(style) } } diff --git a/style/src/theme.rs b/style/src/theme.rs index b0846c0e..e1ac719e 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -10,6 +10,7 @@ use crate::progress_bar; use crate::radio; use crate::rule; use crate::slider; +use crate::text_input; use crate::toggler; use iced_core::{Background, Color}; @@ -152,22 +153,22 @@ impl checkbox::StyleSheet for Theme { match style { Checkbox::Primary => checkbox_appearance( - palette.background.weak, + palette.background.base, palette.primary.strong, is_checked, ), Checkbox::Secondary => checkbox_appearance( - palette.background.weak, + palette.background.base, palette.background.base, is_checked, ), Checkbox::Success => checkbox_appearance( - palette.background.weak, + palette.background.base, palette.success.base, is_checked, ), Checkbox::Danger => checkbox_appearance( - palette.background.weak, + palette.background.base, palette.danger.base, is_checked, ), @@ -183,23 +184,23 @@ impl checkbox::StyleSheet for Theme { match style { Checkbox::Primary => checkbox_appearance( - palette.background.strong, - palette.primary.strong, + palette.background.weak, + palette.primary.base, is_checked, ), Checkbox::Secondary => checkbox_appearance( - palette.background.strong, - palette.background.strong, + palette.background.weak, + palette.background.base, is_checked, ), Checkbox::Success => checkbox_appearance( - palette.background.strong, - palette.success.strong, + palette.background.weak, + palette.success.base, is_checked, ), Checkbox::Danger => checkbox_appearance( - palette.background.strong, - palette.danger.strong, + palette.background.weak, + palette.danger.base, is_checked, ), } @@ -410,7 +411,7 @@ impl progress_bar::StyleSheet for Theme { let palette = self.extended_palette(); let from_palette = |bar: Color| progress_bar::Appearance { - background: palette.background.weak.color.into(), + background: palette.background.strong.color.into(), bar: bar.into(), border_radius: 2.0, }; @@ -456,3 +457,61 @@ impl rule::StyleSheet for Theme { } } } + +/* + * Text Input + */ +impl text_input::StyleSheet for Theme { + type Style = (); + + fn active(&self, _style: Self::Style) -> text_input::Appearance { + let palette = self.extended_palette(); + + text_input::Appearance { + background: palette.background.base.color.into(), + border_radius: 2.0, + border_width: 1.0, + border_color: palette.background.strong.color, + } + } + + fn hovered(&self, _style: Self::Style) -> text_input::Appearance { + let palette = self.extended_palette(); + + text_input::Appearance { + background: palette.background.base.color.into(), + border_radius: 2.0, + border_width: 1.0, + border_color: palette.background.base.text, + } + } + + fn focused(&self, _style: Self::Style) -> text_input::Appearance { + let palette = self.extended_palette(); + + text_input::Appearance { + background: palette.background.base.color.into(), + border_radius: 2.0, + border_width: 1.0, + border_color: palette.primary.strong.color, + } + } + + fn placeholder_color(&self, _style: Self::Style) -> Color { + let palette = self.extended_palette(); + + palette.background.strong.color + } + + fn value_color(&self, _style: Self::Style) -> Color { + let palette = self.extended_palette(); + + palette.background.base.text + } + + fn selection_color(&self, _style: Self::Style) -> Color { + let palette = self.extended_palette(); + + palette.primary.weak.color + } +} diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs index 3d1ca097..fb23bb42 100644 --- a/style/src/theme/palette.rs +++ b/style/src/theme/palette.rs @@ -120,7 +120,7 @@ pub struct Background { impl Background { pub fn new(base: Color, text: Color) -> Self { let weak = mix(base, text, 0.15); - let strong = mix(base, text, 0.25); + let strong = mix(base, text, 0.40); Self { base: Pair::new(base, text), -- cgit From de21a651c0616307bb6bfd36da1a06119e629b10 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 7 Jun 2022 03:26:48 +0200 Subject: Implement theme styling for `Scrollable` --- style/src/scrollable.rs | 51 ++++++------------------------------------------- style/src/theme.rs | 43 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 45 deletions(-) (limited to 'style/src') diff --git a/style/src/scrollable.rs b/style/src/scrollable.rs index 748ba888..8da7409c 100644 --- a/style/src/scrollable.rs +++ b/style/src/scrollable.rs @@ -22,55 +22,16 @@ pub struct Scroller { /// A set of rules that dictate the style of a scrollable. pub trait StyleSheet { + type Style: Default + Copy; + /// Produces the style of an active scrollbar. - fn active(&self) -> Scrollbar; + fn active(&self, style: Self::Style) -> Scrollbar; /// Produces the style of an hovered scrollbar. - fn hovered(&self) -> Scrollbar; + fn hovered(&self, style: Self::Style) -> Scrollbar; /// Produces the style of a scrollbar that is being dragged. - fn dragging(&self) -> Scrollbar { - self.hovered() - } -} - -struct Default; - -impl StyleSheet for Default { - fn active(&self) -> Scrollbar { - Scrollbar { - background: None, - border_radius: 5.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - scroller: Scroller { - color: [0.0, 0.0, 0.0, 0.7].into(), - border_radius: 5.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - } - } - - fn hovered(&self) -> Scrollbar { - Scrollbar { - background: Some(Background::Color([0.0, 0.0, 0.0, 0.3].into())), - ..self.active() - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} - -impl<'a, T> From for Box -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) + fn dragging(&self, style: Self::Style) -> Scrollbar { + self.hovered(style) } } diff --git a/style/src/theme.rs b/style/src/theme.rs index e1ac719e..3eb4ea70 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -9,6 +9,7 @@ use crate::pane_grid; use crate::progress_bar; use crate::radio; use crate::rule; +use crate::scrollable; use crate::slider; use crate::text_input; use crate::toggler; @@ -458,6 +459,48 @@ impl rule::StyleSheet for Theme { } } +/* + * Scrollable + */ + +impl scrollable::StyleSheet for Theme { + type Style = (); + + fn active(&self, _style: Self::Style) -> scrollable::Scrollbar { + let palette = self.extended_palette(); + + scrollable::Scrollbar { + background: palette.background.weak.color.into(), + border_radius: 2.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + scroller: scrollable::Scroller { + color: palette.background.strong.color.into(), + border_radius: 2.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + } + } + + fn hovered(&self, _style: Self::Style) -> scrollable::Scrollbar { + let palette = self.extended_palette(); + + scrollable::Scrollbar { + background: palette.background.weak.color.into(), + border_radius: 2.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + scroller: scrollable::Scroller { + color: palette.primary.strong.color.into(), + border_radius: 2.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + } + } +} + /* * Text Input */ -- cgit From 97555e67af8b4bcc77df69c5e72156e14948150e Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 7 Jun 2022 04:11:24 +0200 Subject: Implement theme styling for `Container` --- style/src/container.rs | 39 ++++++--------------------------------- style/src/theme.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 34 deletions(-) (limited to 'style/src') diff --git a/style/src/container.rs b/style/src/container.rs index 2f411611..184310fa 100644 --- a/style/src/container.rs +++ b/style/src/container.rs @@ -3,7 +3,7 @@ use iced_core::{Background, Color}; /// The appearance of a container. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub text_color: Option, pub background: Option, pub border_radius: f32, @@ -11,7 +11,7 @@ pub struct Style { pub border_color: Color, } -impl std::default::Default for Style { +impl std::default::Default for Appearance { fn default() -> Self { Self { text_color: None, @@ -23,37 +23,10 @@ impl std::default::Default for Style { } } -/// A set of rules that dictate the style of a container. +/// A set of rules that dictate the [`Appearance`] of a container. pub trait StyleSheet { - /// Produces the style of a container. - fn style(&self) -> Style; -} - -struct Default; - -impl StyleSheet for Default { - fn style(&self) -> Style { - Style { - text_color: None, - background: None, - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} + type Style: Default + Copy; -impl<'a, T> From for Box -where - T: StyleSheet + 'a, -{ - fn from(style_sheet: T) -> Self { - Box::new(style_sheet) - } + /// Produces the [`Appearance`] of a container. + fn appearance(&self, style: Self::Style) -> Appearance; } diff --git a/style/src/theme.rs b/style/src/theme.rs index 3eb4ea70..0e9a5964 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -5,6 +5,7 @@ pub use self::palette::Palette; use crate::application; use crate::button; use crate::checkbox; +use crate::container; use crate::pane_grid; use crate::progress_bar; use crate::radio; @@ -127,7 +128,6 @@ impl button::StyleSheet for Theme { /* * Checkbox */ - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Checkbox { Primary, @@ -227,6 +227,50 @@ fn checkbox_appearance( } } +/* + * Container + */ +#[derive(Clone, Copy)] +pub enum Container { + Transparent, + Box, + Custom(fn(&Theme) -> container::Appearance), +} + +impl Default for Container { + fn default() -> Self { + Self::Transparent + } +} + +impl From container::Appearance> for Container { + fn from(f: fn(&Theme) -> container::Appearance) -> Self { + Self::Custom(f) + } +} + +impl container::StyleSheet for Theme { + type Style = Container; + + fn appearance(&self, style: Self::Style) -> container::Appearance { + match style { + Container::Transparent => Default::default(), + Container::Box => { + let palette = self.extended_palette(); + + container::Appearance { + text_color: None, + background: palette.background.weak.color.into(), + border_radius: 2.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + } + } + Container::Custom(f) => f(self), + } + } +} + /* * Slider */ -- cgit From 396735b682433928f52ba777891e14f2fbc703c7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 7 Jun 2022 04:51:44 +0200 Subject: Implement theme styling for `PickList` and `Menu` --- style/src/menu.rs | 17 ++++--------- style/src/pick_list.rs | 65 +++++++++----------------------------------------- style/src/theme.rs | 58 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 67 deletions(-) (limited to 'style/src') diff --git a/style/src/menu.rs b/style/src/menu.rs index 90985b8f..b1dd5ea0 100644 --- a/style/src/menu.rs +++ b/style/src/menu.rs @@ -2,7 +2,7 @@ use iced_core::{Background, Color}; /// The appearance of a menu. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub text_color: Color, pub background: Background, pub border_width: f32, @@ -11,15 +11,8 @@ pub struct Style { pub selected_background: Background, } -impl std::default::Default for Style { - fn default() -> Self { - Self { - text_color: Color::BLACK, - background: Background::Color([0.87, 0.87, 0.87].into()), - border_width: 1.0, - border_color: [0.7, 0.7, 0.7].into(), - selected_text_color: Color::WHITE, - selected_background: Background::Color([0.4, 0.4, 1.0].into()), - } - } +pub trait StyleSheet { + type Style: Default + Copy; + + fn appearance(&self, style: Self::Style) -> Appearance; } diff --git a/style/src/pick_list.rs b/style/src/pick_list.rs index ad96b201..2bafe932 100644 --- a/style/src/pick_list.rs +++ b/style/src/pick_list.rs @@ -1,9 +1,12 @@ -use crate::menu; use iced_core::{Background, Color}; +use crate::container; +use crate::menu; +use crate::scrollable; + /// The appearance of a pick list. #[derive(Debug, Clone, Copy)] -pub struct Style { +pub struct Appearance { pub text_color: Color, pub placeholder_color: Color, pub background: Background, @@ -13,60 +16,14 @@ pub struct Style { pub icon_size: f32, } -impl std::default::Default for Style { - fn default() -> Self { - Self { - text_color: Color::BLACK, - placeholder_color: [0.4, 0.4, 0.4].into(), - background: Background::Color([0.87, 0.87, 0.87].into()), - border_radius: 0.0, - border_width: 1.0, - border_color: [0.7, 0.7, 0.7].into(), - icon_size: 0.7, - } - } -} - /// A set of rules that dictate the style of a container. -pub trait StyleSheet { - fn menu(&self) -> menu::Style; +pub trait StyleSheet: + container::StyleSheet + menu::StyleSheet + scrollable::StyleSheet +{ + type Style: Default + Copy + Into<::Style>; - fn active(&self) -> Style; + fn active(&self, style: ::Style) -> Appearance; /// Produces the style of a container. - fn hovered(&self) -> Style; -} - -struct Default; - -impl StyleSheet for Default { - fn menu(&self) -> menu::Style { - menu::Style::default() - } - - fn active(&self) -> Style { - Style::default() - } - - fn hovered(&self) -> Style { - Style { - border_color: Color::BLACK, - ..self.active() - } - } -} - -impl<'a> std::default::Default for Box { - fn default() -> Self { - Box::new(Default) - } -} - -impl<'a, T> From for Box -where - T: 'a + StyleSheet, -{ - fn from(style: T) -> Self { - Box::new(style) - } + fn hovered(&self, style: ::Style) -> Appearance; } diff --git a/style/src/theme.rs b/style/src/theme.rs index 0e9a5964..b1e18c55 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -6,7 +6,9 @@ use crate::application; use crate::button; use crate::checkbox; use crate::container; +use crate::menu; use crate::pane_grid; +use crate::pick_list; use crate::progress_bar; use crate::radio; use crate::rule; @@ -327,6 +329,61 @@ impl slider::StyleSheet for Theme { } } +/* + * Menu + */ +impl menu::StyleSheet for Theme { + type Style = (); + + fn appearance(&self, _style: Self::Style) -> menu::Appearance { + let palette = self.extended_palette(); + + menu::Appearance { + text_color: palette.background.weak.text, + background: palette.background.weak.color.into(), + border_width: 1.0, + border_color: palette.background.strong.color, + selected_text_color: palette.primary.strong.text, + selected_background: palette.primary.strong.color.into(), + } + } +} + +/* + * Pick List + */ +impl pick_list::StyleSheet for Theme { + type Style = (); + + fn active(&self, _style: ()) -> pick_list::Appearance { + let palette = self.extended_palette(); + + pick_list::Appearance { + text_color: palette.background.weak.text, + background: palette.background.weak.color.into(), + placeholder_color: palette.background.strong.color, + border_radius: 2.0, + border_width: 1.0, + border_color: palette.background.strong.color, + icon_size: 0.7, + } + } + + fn hovered(&self, _style: ()) -> pick_list::Appearance { + let palette = self.extended_palette(); + + pick_list::Appearance { + text_color: palette.background.weak.text, + background: palette.background.weak.color.into(), + placeholder_color: palette.background.strong.color, + border_radius: 2.0, + border_width: 1.0, + border_color: palette.primary.strong.color, + icon_size: 0.7, + } + } +} + /* * Radio */ @@ -506,7 +563,6 @@ impl rule::StyleSheet for Theme { /* * Scrollable */ - impl scrollable::StyleSheet for Theme { type Style = (); -- cgit From 3a22faaa204790126fc27a50d597fa7d069f8f8e Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 7 Jun 2022 04:55:46 +0200 Subject: Remove unused code warnings --- style/src/theme/palette.rs | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'style/src') diff --git a/style/src/theme/palette.rs b/style/src/theme/palette.rs index fb23bb42..cb8bb6e6 100644 --- a/style/src/theme/palette.rs +++ b/style/src/theme/palette.rs @@ -207,20 +207,6 @@ impl Danger { } } -fn muted(color: Color, amount: f32) -> Color { - let mut hsl = to_hsl(color); - - hsl.lightness = if is_dark(color) { - let delta = amount * (1.0 - hsl.lightness).powi(5); - hsl.lightness + delta - } else { - let delta = amount * hsl.lightness.powi(5); - hsl.lightness - delta - }; - - from_hsl(hsl) -} - fn darken(color: Color, amount: f32) -> Color { let mut hsl = to_hsl(color); -- cgit From 1dd1a2f97fc747e15e12b5188dad6c41b0d052ea Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 29 Jun 2022 10:51:01 +0200 Subject: Introduce `StyleSheet` for `Text` widget --- style/src/lib.rs | 1 + style/src/text.rs | 18 ++++++++++++++++++ style/src/theme.rs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 style/src/text.rs (limited to 'style/src') diff --git a/style/src/lib.rs b/style/src/lib.rs index 4a0a6a14..ee426e98 100644 --- a/style/src/lib.rs +++ b/style/src/lib.rs @@ -21,6 +21,7 @@ pub mod radio; pub mod rule; pub mod scrollable; pub mod slider; +pub mod text; pub mod text_input; pub mod theme; pub mod toggler; diff --git a/style/src/text.rs b/style/src/text.rs new file mode 100644 index 00000000..69a4ed85 --- /dev/null +++ b/style/src/text.rs @@ -0,0 +1,18 @@ +use iced_core::Color; + +pub trait StyleSheet { + type Style: Default + Copy; + + fn appearance(&self, style: Self::Style) -> Appearance; +} + +#[derive(Debug, Clone, Copy)] +pub struct Appearance { + pub color: Option, +} + +impl Default for Appearance { + fn default() -> Self { + Self { color: None } + } +} diff --git a/style/src/theme.rs b/style/src/theme.rs index b1e18c55..0bae671e 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -14,6 +14,7 @@ use crate::radio; use crate::rule; use crate::scrollable; use crate::slider; +use crate::text; use crate::text_input; use crate::toggler; @@ -601,6 +602,40 @@ impl scrollable::StyleSheet for Theme { } } +/* + * Text + */ +#[derive(Clone, Copy)] +pub enum Text { + Default, + Color(Color), + Custom(fn(&Theme) -> text::Appearance), +} + +impl Default for Text { + fn default() -> Self { + Self::Default + } +} + +impl From for Text { + fn from(color: Color) -> Self { + Text::Color(color) + } +} + +impl text::StyleSheet for Theme { + type Style = Text; + + fn appearance(&self, style: Self::Style) -> text::Appearance { + match style { + Text::Default => Default::default(), + Text::Color(c) => text::Appearance { color: Some(c) }, + Text::Custom(f) => f(self), + } + } +} + /* * Text Input */ -- cgit From bb07d017e8c8e43ac74f66bf649643bebdc5f71d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 8 Jul 2022 20:07:33 +0200 Subject: Add `Style` variant support to `application::StyleSheet` --- style/src/application.rs | 10 ++++++++-- style/src/theme.rs | 26 ++++++++++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) (limited to 'style/src') diff --git a/style/src/application.rs b/style/src/application.rs index 4aa950fb..d48c6a34 100644 --- a/style/src/application.rs +++ b/style/src/application.rs @@ -1,7 +1,13 @@ use iced_core::Color; pub trait StyleSheet { - fn background_color(&self) -> Color; + type Style: Default + Copy; - fn text_color(&self) -> Color; + fn appearance(&self, style: Self::Style) -> Appearance; +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Appearance { + pub background_color: Color, + pub text_color: Color, } diff --git a/style/src/theme.rs b/style/src/theme.rs index 0bae671e..70b32edf 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -48,17 +48,31 @@ impl Default for Theme { } } -impl application::StyleSheet for Theme { - fn background_color(&self) -> Color { - let palette = self.extended_palette(); +#[derive(Debug, Clone, Copy)] +pub enum Application { + Default, + Custom(fn(Theme) -> application::Appearance), +} - palette.background.base.color +impl Default for Application { + fn default() -> Self { + Self::Default } +} - fn text_color(&self) -> Color { +impl application::StyleSheet for Theme { + type Style = Application; + + fn appearance(&self, style: Self::Style) -> application::Appearance { let palette = self.extended_palette(); - palette.background.base.text + match style { + Application::Default => application::Appearance { + background_color: palette.background.base.color, + text_color: palette.background.base.text, + }, + Application::Custom(f) => f(*self), + } } } -- cgit From 3e643a9d6b904bcb46f94d2961d911deea915cf1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 8 Jul 2022 20:23:38 +0200 Subject: Fix inconsistent styling for `Radio` and `Checkbox` --- style/src/theme.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'style/src') diff --git a/style/src/theme.rs b/style/src/theme.rs index 70b32edf..d2de8a5d 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -171,21 +171,25 @@ impl checkbox::StyleSheet for Theme { match style { Checkbox::Primary => checkbox_appearance( + palette.primary.strong.text, palette.background.base, palette.primary.strong, is_checked, ), Checkbox::Secondary => checkbox_appearance( + palette.background.base.text, palette.background.base, palette.background.base, is_checked, ), Checkbox::Success => checkbox_appearance( + palette.success.base.text, palette.background.base, palette.success.base, is_checked, ), Checkbox::Danger => checkbox_appearance( + palette.danger.base.text, palette.background.base, palette.danger.base, is_checked, @@ -202,21 +206,25 @@ impl checkbox::StyleSheet for Theme { match style { Checkbox::Primary => checkbox_appearance( + palette.primary.strong.text, palette.background.weak, palette.primary.base, is_checked, ), Checkbox::Secondary => checkbox_appearance( + palette.background.base.text, palette.background.weak, palette.background.base, is_checked, ), Checkbox::Success => checkbox_appearance( + palette.success.base.text, palette.background.weak, palette.success.base, is_checked, ), Checkbox::Danger => checkbox_appearance( + palette.danger.base.text, palette.background.weak, palette.danger.base, is_checked, @@ -226,6 +234,7 @@ impl checkbox::StyleSheet for Theme { } fn checkbox_appearance( + checkmark_color: Color, base: palette::Pair, accent: palette::Pair, is_checked: bool, @@ -236,7 +245,7 @@ fn checkbox_appearance( } else { base.color }), - checkmark_color: accent.text, + checkmark_color, border_radius: 2.0, border_width: 1.0, border_color: accent.color, @@ -422,7 +431,7 @@ impl radio::StyleSheet for Theme { let palette = self.extended_palette(); radio::Appearance { - dot_color: palette.primary.weak.text.into(), + dot_color: palette.primary.strong.color.into(), background: palette.primary.weak.color.into(), ..active } -- cgit