Introduce Custom variants for every style in the built-in Theme

This commit is contained in:
Héctor Ramón Jiménez 2022-11-09 04:05:31 +01:00
parent 8102f96f12
commit 18fb74f200
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
34 changed files with 576 additions and 286 deletions

View file

@ -1,9 +1,9 @@
use iced_core::Color;
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
fn appearance(&self, style: Self::Style) -> Appearance;
fn appearance(&self, style: &Self::Style) -> Appearance;
}
#[derive(Debug, Clone, Copy, PartialEq)]

View file

@ -27,11 +27,11 @@ impl std::default::Default for Appearance {
/// A set of rules that dictate the style of a button.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
fn active(&self, style: Self::Style) -> Appearance;
fn active(&self, style: &Self::Style) -> Appearance;
fn hovered(&self, style: Self::Style) -> Appearance {
fn hovered(&self, style: &Self::Style) -> Appearance {
let active = self.active(style);
Appearance {
@ -40,14 +40,14 @@ pub trait StyleSheet {
}
}
fn pressed(&self, style: Self::Style) -> Appearance {
fn pressed(&self, style: &Self::Style) -> Appearance {
Appearance {
shadow_offset: Vector::default(),
..self.active(style)
}
}
fn disabled(&self, style: Self::Style) -> Appearance {
fn disabled(&self, style: &Self::Style) -> Appearance {
let active = self.active(style);
Appearance {

View file

@ -14,9 +14,9 @@ pub struct Appearance {
/// A set of rules that dictate the style of a checkbox.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
fn active(&self, style: Self::Style, is_checked: bool) -> Appearance;
fn active(&self, style: &Self::Style, is_checked: bool) -> Appearance;
fn hovered(&self, style: Self::Style, is_checked: bool) -> Appearance;
fn hovered(&self, style: &Self::Style, is_checked: bool) -> Appearance;
}

View file

@ -25,8 +25,8 @@ impl std::default::Default for Appearance {
/// A set of rules that dictate the [`Appearance`] of a container.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
/// Produces the [`Appearance`] of a container.
fn appearance(&self, style: Self::Style) -> Appearance;
fn appearance(&self, style: &Self::Style) -> Appearance;
}

View file

@ -13,7 +13,7 @@ pub struct Appearance {
}
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default + Clone;
fn appearance(&self, style: Self::Style) -> Appearance;
fn appearance(&self, style: &Self::Style) -> Appearance;
}

View file

@ -4,13 +4,13 @@ use iced_core::Color;
/// A set of rules that dictate the style of a container.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
/// The [`Line`] to draw when a split is picked.
fn picked_split(&self, style: Self::Style) -> Option<Line>;
fn picked_split(&self, style: &Self::Style) -> Option<Line>;
/// The [`Line`] to draw when a split is hovered.
fn hovered_split(&self, style: Self::Style) -> Option<Line>;
fn hovered_split(&self, style: &Self::Style) -> Option<Line>;
}
/// A line.

View file

@ -1,9 +1,5 @@
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 Appearance {
@ -17,13 +13,10 @@ pub struct Appearance {
}
/// A set of rules that dictate the style of a container.
pub trait StyleSheet:
container::StyleSheet + menu::StyleSheet + scrollable::StyleSheet
{
type Style: Default + Copy + Into<<Self as menu::StyleSheet>::Style>;
pub trait StyleSheet {
type Style: Default + Clone;
fn active(&self, style: <Self as StyleSheet>::Style) -> Appearance;
fn active(&self, style: &<Self as StyleSheet>::Style) -> Appearance;
/// Produces the style of a container.
fn hovered(&self, style: <Self as StyleSheet>::Style) -> Appearance;
fn hovered(&self, style: &<Self as StyleSheet>::Style) -> Appearance;
}

View file

@ -11,7 +11,7 @@ pub struct Appearance {
/// A set of rules that dictate the style of a progress bar.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
fn appearance(&self, style: Self::Style) -> Appearance;
fn appearance(&self, style: &Self::Style) -> Appearance;
}

View file

@ -13,9 +13,9 @@ pub struct Appearance {
/// A set of rules that dictate the style of a radio button.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
fn active(&self, style: Self::Style, is_selected: bool) -> Appearance;
fn active(&self, style: &Self::Style, is_selected: bool) -> Appearance;
fn hovered(&self, style: Self::Style, is_selected: bool) -> Appearance;
fn hovered(&self, style: &Self::Style, is_selected: bool) -> Appearance;
}

View file

@ -16,10 +16,10 @@ pub struct Appearance {
/// A set of rules that dictate the style of a rule.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
/// Produces the style of a rule.
fn style(&self, style: Self::Style) -> Appearance;
fn appearance(&self, style: &Self::Style) -> Appearance;
}
/// The fill mode of a rule.

View file

@ -22,16 +22,16 @@ pub struct Scroller {
/// A set of rules that dictate the style of a scrollable.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
/// Produces the style of an active scrollbar.
fn active(&self, style: Self::Style) -> Scrollbar;
fn active(&self, style: &Self::Style) -> Scrollbar;
/// Produces the style of an hovered scrollbar.
fn hovered(&self, style: Self::Style) -> Scrollbar;
fn hovered(&self, style: &Self::Style) -> Scrollbar;
/// Produces the style of a scrollbar that is being dragged.
fn dragging(&self, style: Self::Style) -> Scrollbar {
fn dragging(&self, style: &Self::Style) -> Scrollbar {
self.hovered(style)
}
}

View file

@ -26,14 +26,14 @@ pub enum HandleShape {
/// A set of rules that dictate the style of a slider.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
/// Produces the style of an active slider.
fn active(&self, style: Self::Style) -> Appearance;
fn active(&self, style: &Self::Style) -> Appearance;
/// Produces the style of an hovered slider.
fn hovered(&self, style: Self::Style) -> Appearance;
fn hovered(&self, style: &Self::Style) -> Appearance;
/// Produces the style of a slider that is being dragged.
fn dragging(&self, style: Self::Style) -> Appearance;
fn dragging(&self, style: &Self::Style) -> Appearance;
}

View file

@ -12,22 +12,22 @@ pub struct Appearance {
/// A set of rules that dictate the style of a text input.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
/// Produces the style of an active text input.
fn active(&self, style: Self::Style) -> Appearance;
fn active(&self, style: &Self::Style) -> Appearance;
/// Produces the style of a focused text input.
fn focused(&self, style: Self::Style) -> Appearance;
fn focused(&self, style: &Self::Style) -> Appearance;
fn placeholder_color(&self, style: Self::Style) -> Color;
fn placeholder_color(&self, style: &Self::Style) -> Color;
fn value_color(&self, style: Self::Style) -> Color;
fn value_color(&self, style: &Self::Style) -> Color;
fn selection_color(&self, style: Self::Style) -> Color;
fn selection_color(&self, style: &Self::Style) -> Color;
/// Produces the style of an hovered text input.
fn hovered(&self, style: Self::Style) -> Appearance {
fn hovered(&self, style: &Self::Style) -> Appearance {
self.focused(style)
}
}

View file

@ -19,7 +19,9 @@ use crate::text;
use crate::text_input;
use crate::toggler;
use iced_core::{Background, Color};
use iced_core::{Background, Color, Vector};
use std::rc::Rc;
#[derive(Debug, Clone, PartialEq)]
pub enum Theme {
@ -71,10 +73,9 @@ impl Custom {
}
}
#[derive(Debug, Clone, Copy)]
pub enum Application {
Default,
Custom(fn(Theme) -> application::Appearance),
Custom(Box<dyn application::StyleSheet<Style = Theme>>),
}
impl Default for Application {
@ -86,7 +87,7 @@ impl Default for Application {
impl application::StyleSheet for Theme {
type Style = Application;
fn appearance(&self, style: Self::Style) -> application::Appearance {
fn appearance(&self, style: &Self::Style) -> application::Appearance {
let palette = self.extended_palette();
match style {
@ -94,21 +95,35 @@ impl application::StyleSheet for Theme {
background_color: palette.background.base.color,
text_color: palette.background.base.text,
},
Application::Custom(f) => f(self.clone()),
Application::Custom(custom) => custom.appearance(self),
}
}
}
impl application::StyleSheet for fn(&Theme) -> application::Appearance {
type Style = Theme;
fn appearance(&self, style: &Self::Style) -> application::Appearance {
(self)(style)
}
}
impl From<fn(&Theme) -> application::Appearance> for Application {
fn from(f: fn(&Theme) -> application::Appearance) -> Self {
Self::Custom(Box::new(f))
}
}
/*
* Button
*/
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Button {
Primary,
Secondary,
Positive,
Destructive,
Text,
Custom(Box<dyn button::StyleSheet<Style = Theme>>),
}
impl Default for Button {
@ -120,7 +135,7 @@ impl Default for Button {
impl button::StyleSheet for Theme {
type Style = Button;
fn active(&self, style: Self::Style) -> button::Appearance {
fn active(&self, style: &Self::Style) -> button::Appearance {
let palette = self.extended_palette();
let appearance = button::Appearance {
@ -143,19 +158,25 @@ impl button::StyleSheet for Theme {
text_color: palette.background.base.text,
..appearance
},
Button::Custom(custom) => custom.active(self),
}
}
fn hovered(&self, style: Self::Style) -> button::Appearance {
let active = self.active(style);
fn hovered(&self, style: &Self::Style) -> button::Appearance {
let palette = self.extended_palette();
if let Button::Custom(custom) = style {
return custom.hovered(self);
}
let active = self.active(style);
let background = match style {
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,
Button::Text | Button::Custom(_) => None,
};
button::Appearance {
@ -163,17 +184,51 @@ impl button::StyleSheet for Theme {
..active
}
}
fn pressed(&self, style: &Self::Style) -> button::Appearance {
if let Button::Custom(custom) = style {
return custom.pressed(self);
}
button::Appearance {
shadow_offset: Vector::default(),
..self.active(style)
}
}
fn disabled(&self, style: &Self::Style) -> button::Appearance {
if let Button::Custom(custom) = style {
return custom.disabled(self);
}
let active = self.active(style);
button::Appearance {
shadow_offset: Vector::default(),
background: active.background.map(|background| match background {
Background::Color(color) => Background::Color(Color {
a: color.a * 0.5,
..color
}),
}),
text_color: Color {
a: active.text_color.a * 0.5,
..active.text_color
},
..active
}
}
}
/*
* Checkbox
*/
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Checkbox {
Primary,
Secondary,
Success,
Danger,
Custom(Box<dyn checkbox::StyleSheet<Style = Theme>>),
}
impl Default for Checkbox {
@ -187,7 +242,7 @@ impl checkbox::StyleSheet for Theme {
fn active(
&self,
style: Self::Style,
style: &Self::Style,
is_checked: bool,
) -> checkbox::Appearance {
let palette = self.extended_palette();
@ -217,12 +272,13 @@ impl checkbox::StyleSheet for Theme {
palette.danger.base,
is_checked,
),
Checkbox::Custom(custom) => custom.active(self, is_checked),
}
}
fn hovered(
&self,
style: Self::Style,
style: &Self::Style,
is_checked: bool,
) -> checkbox::Appearance {
let palette = self.extended_palette();
@ -252,6 +308,7 @@ impl checkbox::StyleSheet for Theme {
palette.danger.base,
is_checked,
),
Checkbox::Custom(custom) => custom.hovered(self, is_checked),
}
}
}
@ -279,11 +336,10 @@ fn checkbox_appearance(
/*
* Container
*/
#[derive(Clone, Copy)]
pub enum Container {
Transparent,
Box,
Custom(fn(&Theme) -> container::Appearance),
Custom(Box<dyn container::StyleSheet<Style = Theme>>),
}
impl Default for Container {
@ -294,14 +350,14 @@ impl Default for Container {
impl From<fn(&Theme) -> container::Appearance> for Container {
fn from(f: fn(&Theme) -> container::Appearance) -> Self {
Self::Custom(f)
Self::Custom(Box::new(f))
}
}
impl container::StyleSheet for Theme {
type Style = Container;
fn appearance(&self, style: Self::Style) -> container::Appearance {
fn appearance(&self, style: &Self::Style) -> container::Appearance {
match style {
Container::Transparent => Default::default(),
Container::Box => {
@ -315,63 +371,96 @@ impl container::StyleSheet for Theme {
border_color: Color::TRANSPARENT,
}
}
Container::Custom(f) => f(self),
Container::Custom(custom) => custom.appearance(self),
}
}
}
impl container::StyleSheet for fn(&Theme) -> container::Appearance {
type Style = Theme;
fn appearance(&self, style: &Self::Style) -> container::Appearance {
(self)(style)
}
}
/*
* Slider
*/
#[derive(Default)]
pub enum Slider {
#[default]
Default,
Custom(Box<dyn slider::StyleSheet<Style = Theme>>),
}
impl slider::StyleSheet for Theme {
type Style = ();
type Style = Slider;
fn active(&self, _style: Self::Style) -> slider::Appearance {
let palette = self.extended_palette();
fn active(&self, style: &Self::Style) -> slider::Appearance {
match style {
Slider::Default => {
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,
};
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::Appearance {
rail_colors: (palette.primary.base.color, Color::TRANSPARENT),
handle: slider::Handle {
color: palette.background.base.color,
border_color: palette.primary.base.color,
..handle
},
slider::Appearance {
rail_colors: (
palette.primary.base.color,
Color::TRANSPARENT,
),
handle: slider::Handle {
color: palette.background.base.color,
border_color: palette.primary.base.color,
..handle
},
}
}
Slider::Custom(custom) => custom.active(self),
}
}
fn hovered(&self, style: Self::Style) -> slider::Appearance {
let active = self.active(style);
let palette = self.extended_palette();
fn hovered(&self, style: &Self::Style) -> slider::Appearance {
match style {
Slider::Default => {
let active = self.active(style);
let palette = self.extended_palette();
slider::Appearance {
handle: slider::Handle {
color: palette.primary.weak.color,
..active.handle
},
..active
slider::Appearance {
handle: slider::Handle {
color: palette.primary.weak.color,
..active.handle
},
..active
}
}
Slider::Custom(custom) => custom.hovered(self),
}
}
fn dragging(&self, style: Self::Style) -> slider::Appearance {
let active = self.active(style);
let palette = self.extended_palette();
fn dragging(&self, style: &Self::Style) -> slider::Appearance {
match style {
Slider::Default => {
let active = self.active(style);
let palette = self.extended_palette();
slider::Appearance {
handle: slider::Handle {
color: palette.primary.base.color,
..active.handle
},
..active
slider::Appearance {
handle: slider::Handle {
color: palette.primary.base.color,
..active.handle
},
..active
}
}
Slider::Custom(custom) => custom.dragging(self),
}
}
}
@ -379,20 +468,41 @@ impl slider::StyleSheet for Theme {
/*
* Menu
*/
#[derive(Clone, Default)]
pub enum Menu {
#[default]
Default,
Custom(Rc<dyn menu::StyleSheet<Style = Theme>>),
}
impl menu::StyleSheet for Theme {
type Style = ();
type Style = Menu;
fn appearance(&self, _style: Self::Style) -> menu::Appearance {
let palette = self.extended_palette();
fn appearance(&self, style: &Self::Style) -> menu::Appearance {
match style {
Menu::Default => {
let palette = self.extended_palette();
menu::Appearance {
text_color: palette.background.weak.text,
background: palette.background.weak.color.into(),
border_width: 1.0,
border_radius: 0.0,
border_color: palette.background.strong.color,
selected_text_color: palette.primary.strong.text,
selected_background: palette.primary.strong.color.into(),
menu::Appearance {
text_color: palette.background.weak.text,
background: palette.background.weak.color.into(),
border_width: 1.0,
border_radius: 0.0,
border_color: palette.background.strong.color,
selected_text_color: palette.primary.strong.text,
selected_background: palette.primary.strong.color.into(),
}
}
Menu::Custom(custom) => custom.appearance(self),
}
}
}
impl From<PickList> for Menu {
fn from(pick_list: PickList) -> Self {
match pick_list {
PickList::Default => Self::Default,
PickList::Custom(_, menu) => Self::Custom(menu),
}
}
}
@ -400,34 +510,54 @@ impl menu::StyleSheet for Theme {
/*
* Pick List
*/
#[derive(Clone, Default)]
pub enum PickList {
#[default]
Default,
Custom(
Rc<dyn pick_list::StyleSheet<Style = Theme>>,
Rc<dyn menu::StyleSheet<Style = Theme>>,
),
}
impl pick_list::StyleSheet for Theme {
type Style = ();
type Style = PickList;
fn active(&self, _style: ()) -> pick_list::Appearance {
let palette = self.extended_palette();
fn active(&self, style: &Self::Style) -> pick_list::Appearance {
match style {
PickList::Default => {
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,
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,
}
}
PickList::Custom(custom, _) => custom.active(self),
}
}
fn hovered(&self, _style: ()) -> pick_list::Appearance {
let palette = self.extended_palette();
fn hovered(&self, style: &Self::Style) -> pick_list::Appearance {
match style {
PickList::Default => {
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,
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,
}
}
PickList::Custom(custom, _) => custom.active(self),
}
}
}
@ -435,37 +565,54 @@ impl pick_list::StyleSheet for Theme {
/*
* Radio
*/
#[derive(Default)]
pub enum Radio {
#[default]
Default,
Custom(Box<dyn radio::StyleSheet<Style = Theme>>),
}
impl radio::StyleSheet for Theme {
type Style = ();
type Style = Radio;
fn active(
&self,
_style: Self::Style,
_is_selected: bool,
style: &Self::Style,
is_selected: bool,
) -> radio::Appearance {
let palette = self.extended_palette();
match style {
Radio::Default => {
let palette = self.extended_palette();
radio::Appearance {
background: Color::TRANSPARENT.into(),
dot_color: palette.primary.strong.color,
border_width: 1.0,
border_color: palette.primary.strong.color,
text_color: None,
radio::Appearance {
background: Color::TRANSPARENT.into(),
dot_color: palette.primary.strong.color,
border_width: 1.0,
border_color: palette.primary.strong.color,
text_color: None,
}
}
Radio::Custom(custom) => custom.active(self, is_selected),
}
}
fn hovered(
&self,
style: Self::Style,
style: &Self::Style,
is_selected: bool,
) -> radio::Appearance {
let active = self.active(style, is_selected);
let palette = self.extended_palette();
match style {
Radio::Default => {
let active = self.active(style, is_selected);
let palette = self.extended_palette();
radio::Appearance {
dot_color: palette.primary.strong.color,
background: palette.primary.weak.color.into(),
..active
radio::Appearance {
dot_color: palette.primary.strong.color,
background: palette.primary.weak.color.into(),
..active
}
}
Radio::Custom(custom) => custom.hovered(self, is_selected),
}
}
}
@ -473,49 +620,66 @@ impl radio::StyleSheet for Theme {
/*
* Toggler
*/
#[derive(Default)]
pub enum Toggler {
#[default]
Default,
Custom(Box<dyn toggler::StyleSheet<Style = Theme>>),
}
impl toggler::StyleSheet for Theme {
type Style = ();
type Style = Toggler;
fn active(
&self,
_style: Self::Style,
style: &Self::Style,
is_active: bool,
) -> toggler::Appearance {
let palette = self.extended_palette();
match style {
Toggler::Default => {
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,
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,
}
}
Toggler::Custom(custom) => custom.active(self, is_active),
}
}
fn hovered(
&self,
style: Self::Style,
style: &Self::Style,
is_active: bool,
) -> toggler::Appearance {
let palette = self.extended_palette();
match style {
Toggler::Default => {
let palette = self.extended_palette();
toggler::Appearance {
foreground: if is_active {
Color {
a: 0.5,
..palette.primary.strong.text
toggler::Appearance {
foreground: if is_active {
Color {
a: 0.5,
..palette.primary.strong.text
}
} else {
palette.background.weak.color
},
..self.active(style, is_active)
}
} else {
palette.background.weak.color
},
..self.active(style, is_active)
}
Toggler::Custom(custom) => custom.hovered(self, is_active),
}
}
}
@ -523,37 +687,53 @@ impl toggler::StyleSheet for Theme {
/*
* Pane Grid
*/
#[derive(Default)]
pub enum PaneGrid {
#[default]
Default,
Custom(Box<dyn pane_grid::StyleSheet<Style = Theme>>),
}
impl pane_grid::StyleSheet for Theme {
type Style = ();
type Style = PaneGrid;
fn picked_split(&self, _style: Self::Style) -> Option<pane_grid::Line> {
let palette = self.extended_palette();
fn picked_split(&self, style: &Self::Style) -> Option<pane_grid::Line> {
match style {
PaneGrid::Default => {
let palette = self.extended_palette();
Some(pane_grid::Line {
color: palette.primary.strong.color,
width: 2.0,
})
Some(pane_grid::Line {
color: palette.primary.strong.color,
width: 2.0,
})
}
PaneGrid::Custom(custom) => custom.picked_split(self),
}
}
fn hovered_split(&self, _style: Self::Style) -> Option<pane_grid::Line> {
let palette = self.extended_palette();
fn hovered_split(&self, style: &Self::Style) -> Option<pane_grid::Line> {
match style {
PaneGrid::Default => {
let palette = self.extended_palette();
Some(pane_grid::Line {
color: palette.primary.base.color,
width: 2.0,
})
Some(pane_grid::Line {
color: palette.primary.base.color,
width: 2.0,
})
}
PaneGrid::Custom(custom) => custom.hovered_split(self),
}
}
}
/*
* Progress Bar
*/
#[derive(Clone, Copy)]
pub enum ProgressBar {
Primary,
Success,
Danger,
Custom(fn(&Theme) -> progress_bar::Appearance),
Custom(Box<dyn progress_bar::StyleSheet<Style = Theme>>),
}
impl Default for ProgressBar {
@ -562,10 +742,20 @@ impl Default for ProgressBar {
}
}
impl From<fn(&Theme) -> progress_bar::Appearance> for ProgressBar {
fn from(f: fn(&Theme) -> progress_bar::Appearance) -> Self {
Self::Custom(Box::new(f))
}
}
impl progress_bar::StyleSheet for Theme {
type Style = ProgressBar;
fn appearance(&self, style: Self::Style) -> progress_bar::Appearance {
fn appearance(&self, style: &Self::Style) -> progress_bar::Appearance {
if let ProgressBar::Custom(custom) = style {
return custom.appearance(self);
}
let palette = self.extended_palette();
let from_palette = |bar: Color| progress_bar::Appearance {
@ -578,18 +768,25 @@ impl progress_bar::StyleSheet for Theme {
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),
ProgressBar::Custom(custom) => custom.appearance(self),
}
}
}
impl progress_bar::StyleSheet for fn(&Theme) -> progress_bar::Appearance {
type Style = Theme;
fn appearance(&self, style: &Self::Style) -> progress_bar::Appearance {
(self)(style)
}
}
/*
* Rule
*/
#[derive(Clone, Copy)]
pub enum Rule {
Default,
Custom(fn(&Theme) -> rule::Appearance),
Custom(Box<dyn rule::StyleSheet<Style = Theme>>),
}
impl Default for Rule {
@ -598,10 +795,16 @@ impl Default for Rule {
}
}
impl From<fn(&Theme) -> rule::Appearance> for Rule {
fn from(f: fn(&Theme) -> rule::Appearance) -> Self {
Self::Custom(Box::new(f))
}
}
impl rule::StyleSheet for Theme {
type Style = Rule;
fn style(&self, style: Self::Style) -> rule::Appearance {
fn appearance(&self, style: &Self::Style) -> rule::Appearance {
let palette = self.extended_palette();
match style {
@ -611,48 +814,80 @@ impl rule::StyleSheet for Theme {
radius: 0.0,
fill_mode: rule::FillMode::Full,
},
Rule::Custom(f) => f(self),
Rule::Custom(custom) => custom.appearance(self),
}
}
}
impl rule::StyleSheet for fn(&Theme) -> rule::Appearance {
type Style = Theme;
fn appearance(&self, style: &Self::Style) -> rule::Appearance {
(self)(style)
}
}
/*
* Scrollable
*/
#[derive(Default)]
pub enum Scrollable {
#[default]
Default,
Custom(Box<dyn scrollable::StyleSheet<Style = Theme>>),
}
impl scrollable::StyleSheet for Theme {
type Style = ();
type Style = Scrollable;
fn active(&self, _style: Self::Style) -> scrollable::Scrollbar {
let palette = self.extended_palette();
fn active(&self, style: &Self::Style) -> scrollable::Scrollbar {
match style {
Scrollable::Default => {
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,
border_radius: 2.0,
border_width: 0.0,
border_color: Color::TRANSPARENT,
},
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,
border_radius: 2.0,
border_width: 0.0,
border_color: Color::TRANSPARENT,
},
}
}
Scrollable::Custom(custom) => custom.active(self),
}
}
fn hovered(&self, _style: Self::Style) -> scrollable::Scrollbar {
let palette = self.extended_palette();
fn hovered(&self, style: &Self::Style) -> scrollable::Scrollbar {
match style {
Scrollable::Default => {
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,
border_radius: 2.0,
border_width: 0.0,
border_color: Color::TRANSPARENT,
},
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,
border_radius: 2.0,
border_width: 0.0,
border_color: Color::TRANSPARENT,
},
}
}
Scrollable::Custom(custom) => custom.hovered(self),
}
}
fn dragging(&self, style: &Self::Style) -> scrollable::Scrollbar {
match style {
Scrollable::Default => self.hovered(style),
Scrollable::Custom(custom) => custom.dragging(self),
}
}
}
@ -664,7 +899,6 @@ impl scrollable::StyleSheet for Theme {
pub enum Text {
Default,
Color(Color),
Custom(fn(&Theme) -> text::Appearance),
}
impl Default for Text {
@ -686,7 +920,6 @@ impl text::StyleSheet for Theme {
match style {
Text::Default => Default::default(),
Text::Color(c) => text::Appearance { color: Some(c) },
Text::Custom(f) => f(self),
}
}
}
@ -694,10 +927,21 @@ impl text::StyleSheet for Theme {
/*
* Text Input
*/
impl text_input::StyleSheet for Theme {
type Style = ();
#[derive(Default)]
pub enum TextInput {
#[default]
Default,
Custom(Box<dyn text_input::StyleSheet<Style = Theme>>),
}
impl text_input::StyleSheet for Theme {
type Style = TextInput;
fn active(&self, style: &Self::Style) -> text_input::Appearance {
if let TextInput::Custom(custom) = style {
return custom.active(self);
}
fn active(&self, _style: Self::Style) -> text_input::Appearance {
let palette = self.extended_palette();
text_input::Appearance {
@ -708,7 +952,11 @@ impl text_input::StyleSheet for Theme {
}
}
fn hovered(&self, _style: Self::Style) -> text_input::Appearance {
fn hovered(&self, style: &Self::Style) -> text_input::Appearance {
if let TextInput::Custom(custom) = style {
return custom.hovered(self);
}
let palette = self.extended_palette();
text_input::Appearance {
@ -719,7 +967,11 @@ impl text_input::StyleSheet for Theme {
}
}
fn focused(&self, _style: Self::Style) -> text_input::Appearance {
fn focused(&self, style: &Self::Style) -> text_input::Appearance {
if let TextInput::Custom(custom) = style {
return custom.focused(self);
}
let palette = self.extended_palette();
text_input::Appearance {
@ -730,19 +982,31 @@ impl text_input::StyleSheet for Theme {
}
}
fn placeholder_color(&self, _style: Self::Style) -> Color {
fn placeholder_color(&self, style: &Self::Style) -> Color {
if let TextInput::Custom(custom) = style {
return custom.placeholder_color(self);
}
let palette = self.extended_palette();
palette.background.strong.color
}
fn value_color(&self, _style: Self::Style) -> Color {
fn value_color(&self, style: &Self::Style) -> Color {
if let TextInput::Custom(custom) = style {
return custom.value_color(self);
}
let palette = self.extended_palette();
palette.background.base.text
}
fn selection_color(&self, _style: Self::Style) -> Color {
fn selection_color(&self, style: &Self::Style) -> Color {
if let TextInput::Custom(custom) = style {
return custom.selection_color(self);
}
let palette = self.extended_palette();
palette.primary.weak.color

View file

@ -12,9 +12,9 @@ pub struct Appearance {
/// A set of rules that dictate the style of a toggler.
pub trait StyleSheet {
type Style: Default + Copy;
type Style: Default;
fn active(&self, style: Self::Style, is_active: bool) -> Appearance;
fn active(&self, style: &Self::Style, is_active: bool) -> Appearance;
fn hovered(&self, style: Self::Style, is_active: bool) -> Appearance;
fn hovered(&self, style: &Self::Style, is_active: bool) -> Appearance;
}