Add Theme selector to layout example

This commit is contained in:
Héctor Ramón Jiménez 2024-01-10 08:15:05 +01:00
parent d76705df29
commit 3850a46db6
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
5 changed files with 60 additions and 21 deletions

View file

@ -1,8 +1,8 @@
use iced::executor; use iced::executor;
use iced::keyboard; use iced::keyboard;
use iced::widget::{ use iced::widget::{
button, checkbox, column, container, horizontal_space, row, text, button, checkbox, column, container, horizontal_space, pick_list, row,
vertical_rule, text, vertical_rule,
}; };
use iced::{ use iced::{
color, Alignment, Application, Color, Command, Element, Font, Length, color, Alignment, Application, Color, Command, Element, Font, Length,
@ -17,13 +17,15 @@ pub fn main() -> iced::Result {
struct Layout { struct Layout {
example: Example, example: Example,
explain: bool, explain: bool,
theme: Theme,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone)]
enum Message { enum Message {
Next, Next,
Previous, Previous,
ExplainToggled(bool), ExplainToggled(bool),
ThemeSelected(Theme),
} }
impl Application for Layout { impl Application for Layout {
@ -37,6 +39,7 @@ impl Application for Layout {
Self { Self {
example: Example::default(), example: Example::default(),
explain: false, explain: false,
theme: Theme::Light,
}, },
Command::none(), Command::none(),
) )
@ -57,6 +60,9 @@ impl Application for Layout {
Message::ExplainToggled(explain) => { Message::ExplainToggled(explain) => {
self.explain = explain; self.explain = explain;
} }
Message::ThemeSelected(theme) => {
self.theme = theme;
}
} }
Command::none() Command::none()
@ -75,7 +81,13 @@ impl Application for Layout {
text(self.example.title).size(20).font(Font::MONOSPACE), text(self.example.title).size(20).font(Font::MONOSPACE),
horizontal_space(Length::Fill), horizontal_space(Length::Fill),
checkbox("Explain", self.explain, Message::ExplainToggled), checkbox("Explain", self.explain, Message::ExplainToggled),
pick_list(
Theme::ALL,
Some(self.theme.clone()),
Message::ThemeSelected
),
] ]
.spacing(20)
.align_items(Alignment::Center); .align_items(Alignment::Center);
let example = container(if self.explain { let example = container(if self.explain {
@ -115,7 +127,7 @@ impl Application for Layout {
} }
fn theme(&self) -> Theme { fn theme(&self) -> Theme {
Theme::Dark self.theme.clone()
} }
} }

View file

@ -53,13 +53,16 @@ impl Sandbox for Styling {
self.theme = match theme { self.theme = match theme {
ThemeType::Light => Theme::Light, ThemeType::Light => Theme::Light,
ThemeType::Dark => Theme::Dark, ThemeType::Dark => Theme::Dark,
ThemeType::Custom => Theme::custom(theme::Palette { ThemeType::Custom => Theme::custom(
background: Color::from_rgb(1.0, 0.9, 1.0), String::from("Custom"),
text: Color::BLACK, theme::Palette {
primary: Color::from_rgb(0.5, 0.5, 0.0), background: Color::from_rgb(1.0, 0.9, 1.0),
success: Color::from_rgb(0.0, 1.0, 0.0), text: Color::BLACK,
danger: Color::from_rgb(1.0, 0.0, 0.0), primary: Color::from_rgb(0.5, 0.5, 0.0),
}), success: Color::from_rgb(0.0, 1.0, 0.0),
danger: Color::from_rgb(1.0, 0.0, 0.0),
},
),
} }
} }
Message::InputChanged(value) => self.input_value = value, Message::InputChanged(value) => self.input_value = value,

View file

@ -23,6 +23,7 @@ use crate::toggler;
use iced_core::{Background, Color, Vector}; use iced_core::{Background, Color, Vector};
use std::fmt;
use std::rc::Rc; use std::rc::Rc;
/// A built-in theme. /// A built-in theme.
@ -38,18 +39,22 @@ pub enum Theme {
} }
impl Theme { impl Theme {
/// A list with all the defined themes.
pub const ALL: &'static [Self] = &[Self::Light, Self::Dark];
/// Creates a new custom [`Theme`] from the given [`Palette`]. /// Creates a new custom [`Theme`] from the given [`Palette`].
pub fn custom(palette: Palette) -> Self { pub fn custom(name: String, palette: Palette) -> Self {
Self::custom_with_fn(palette, palette::Extended::generate) Self::custom_with_fn(name, palette, palette::Extended::generate)
} }
/// Creates a new custom [`Theme`] from the given [`Palette`], with /// Creates a new custom [`Theme`] from the given [`Palette`], with
/// a custom generator of a [`palette::Extended`]. /// a custom generator of a [`palette::Extended`].
pub fn custom_with_fn( pub fn custom_with_fn(
name: String,
palette: Palette, palette: Palette,
generate: impl FnOnce(Palette) -> palette::Extended, generate: impl FnOnce(Palette) -> palette::Extended,
) -> Self { ) -> Self {
Self::Custom(Box::new(Custom::with_fn(palette, generate))) Self::Custom(Box::new(Custom::with_fn(name, palette, generate)))
} }
/// Returns the [`Palette`] of the [`Theme`]. /// Returns the [`Palette`] of the [`Theme`].
@ -71,32 +76,51 @@ impl Theme {
} }
} }
impl fmt::Display for Theme {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Light => write!(f, "Light"),
Self::Dark => write!(f, "Dark"),
Self::Custom(custom) => custom.fmt(f),
}
}
}
/// A [`Theme`] with a customized [`Palette`]. /// A [`Theme`] with a customized [`Palette`].
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Custom { pub struct Custom {
name: String,
palette: Palette, palette: Palette,
extended: palette::Extended, extended: palette::Extended,
} }
impl Custom { impl Custom {
/// Creates a [`Custom`] theme from the given [`Palette`]. /// Creates a [`Custom`] theme from the given [`Palette`].
pub fn new(palette: Palette) -> Self { pub fn new(name: String, palette: Palette) -> Self {
Self::with_fn(palette, palette::Extended::generate) Self::with_fn(name, palette, palette::Extended::generate)
} }
/// Creates a [`Custom`] theme from the given [`Palette`] with /// Creates a [`Custom`] theme from the given [`Palette`] with
/// a custom generator of a [`palette::Extended`]. /// a custom generator of a [`palette::Extended`].
pub fn with_fn( pub fn with_fn(
name: String,
palette: Palette, palette: Palette,
generate: impl FnOnce(Palette) -> palette::Extended, generate: impl FnOnce(Palette) -> palette::Extended,
) -> Self { ) -> Self {
Self { Self {
name,
palette, palette,
extended: generate(palette), extended: generate(palette),
} }
} }
} }
impl fmt::Display for Custom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name)
}
}
/// The style of an application. /// The style of an application.
#[derive(Default)] #[derive(Default)]
pub enum Application { pub enum Application {

View file

@ -271,7 +271,7 @@ pub fn pick_list<'a, Message, Renderer, T>(
on_selected: impl Fn(T) -> Message + 'a, on_selected: impl Fn(T) -> Message + 'a,
) -> PickList<'a, T, Message, Renderer> ) -> PickList<'a, T, Message, Renderer>
where where
T: ToString + Eq + 'static, T: ToString + PartialEq + 'static,
[T]: ToOwned<Owned = Vec<T>>, [T]: ToOwned<Owned = Vec<T>>,
Renderer: core::text::Renderer, Renderer: core::text::Renderer,
Renderer::Theme: pick_list::StyleSheet Renderer::Theme: pick_list::StyleSheet

View file

@ -45,7 +45,7 @@ where
impl<'a, T: 'a, Message, Renderer> PickList<'a, T, Message, Renderer> impl<'a, T: 'a, Message, Renderer> PickList<'a, T, Message, Renderer>
where where
T: ToString + Eq, T: ToString + PartialEq,
[T]: ToOwned<Owned = Vec<T>>, [T]: ToOwned<Owned = Vec<T>>,
Renderer: text::Renderer, Renderer: text::Renderer,
Renderer::Theme: StyleSheet Renderer::Theme: StyleSheet
@ -145,7 +145,7 @@ where
impl<'a, T: 'a, Message, Renderer> Widget<Message, Renderer> impl<'a, T: 'a, Message, Renderer> Widget<Message, Renderer>
for PickList<'a, T, Message, Renderer> for PickList<'a, T, Message, Renderer>
where where
T: Clone + ToString + Eq + 'static, T: Clone + ToString + PartialEq + 'static,
[T]: ToOwned<Owned = Vec<T>>, [T]: ToOwned<Owned = Vec<T>>,
Message: 'a, Message: 'a,
Renderer: text::Renderer + 'a, Renderer: text::Renderer + 'a,
@ -281,7 +281,7 @@ where
impl<'a, T: 'a, Message, Renderer> From<PickList<'a, T, Message, Renderer>> impl<'a, T: 'a, Message, Renderer> From<PickList<'a, T, Message, Renderer>>
for Element<'a, Message, Renderer> for Element<'a, Message, Renderer>
where where
T: Clone + ToString + Eq + 'static, T: Clone + ToString + PartialEq + 'static,
[T]: ToOwned<Owned = Vec<T>>, [T]: ToOwned<Owned = Vec<T>>,
Message: 'a, Message: 'a,
Renderer: text::Renderer + 'a, Renderer: text::Renderer + 'a,