summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-03-05 02:08:19 +0100
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-03-05 02:08:19 +0100
commit1f0a0c235a7729cf2d5716efeecb9c4dc972fdfa (patch)
tree77118b43726c9321d05190cb2e7963594e0f80a3
parentf4a4845ddbdced81ae4ff60bfa19f0e602d84709 (diff)
downloadiced-1f0a0c235a7729cf2d5716efeecb9c4dc972fdfa.tar.gz
iced-1f0a0c235a7729cf2d5716efeecb9c4dc972fdfa.tar.bz2
iced-1f0a0c235a7729cf2d5716efeecb9c4dc972fdfa.zip
Simplify theming for `Checkbox` widget
-rw-r--r--examples/checkbox/src/main.rs9
-rw-r--r--style/src/button.rs1
-rw-r--r--style/src/checkbox.rs37
-rw-r--r--style/src/lib.rs2
-rw-r--r--style/src/theme.rs151
-rw-r--r--widget/src/checkbox.rs212
-rw-r--r--widget/src/helpers.rs2
7 files changed, 196 insertions, 218 deletions
diff --git a/examples/checkbox/src/main.rs b/examples/checkbox/src/main.rs
index 834a8f5c..121c99ea 100644
--- a/examples/checkbox/src/main.rs
+++ b/examples/checkbox/src/main.rs
@@ -1,6 +1,5 @@
use iced::executor;
use iced::font::{self, Font};
-use iced::theme;
use iced::widget::{checkbox, column, container, row, text};
use iced::{Application, Command, Element, Length, Settings, Theme};
@@ -71,10 +70,10 @@ impl Application for Example {
};
let checkboxes = row![
- styled_checkbox("Primary", theme::Checkbox::Primary),
- styled_checkbox("Secondary", theme::Checkbox::Secondary),
- styled_checkbox("Success", theme::Checkbox::Success),
- styled_checkbox("Danger", theme::Checkbox::Danger),
+ styled_checkbox("Primary", checkbox::primary),
+ styled_checkbox("Secondary", checkbox::secondary),
+ styled_checkbox("Success", checkbox::success),
+ styled_checkbox("Danger", checkbox::danger),
]
.spacing(20);
diff --git a/style/src/button.rs b/style/src/button.rs
deleted file mode 100644
index 8b137891..00000000
--- a/style/src/button.rs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/style/src/checkbox.rs b/style/src/checkbox.rs
deleted file mode 100644
index 5e1c8374..00000000
--- a/style/src/checkbox.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-//! Change the appearance of a checkbox.
-use iced_core::{Background, Border, Color};
-
-/// The appearance of a checkbox.
-#[derive(Debug, Clone, Copy)]
-pub struct Appearance {
- /// The [`Background`] of the checkbox.
- pub background: Background,
- /// The icon [`Color`] of the checkbox.
- pub icon_color: Color,
- /// The [`Border`] of hte checkbox.
- pub border: Border,
- /// The text [`Color`] of the checkbox.
- pub text_color: Option<Color>,
-}
-
-/// A set of rules that dictate the style of a checkbox.
-pub trait StyleSheet {
- /// The supported style of the [`StyleSheet`].
- type Style: Default;
-
- /// Produces the active [`Appearance`] of a checkbox.
- fn active(&self, style: &Self::Style, is_checked: bool) -> Appearance;
-
- /// Produces the hovered [`Appearance`] of a checkbox.
- fn hovered(&self, style: &Self::Style, is_checked: bool) -> Appearance;
-
- /// Produces the disabled [`Appearance`] of a checkbox.
- fn disabled(&self, style: &Self::Style, is_checked: bool) -> Appearance {
- let active = self.active(style, is_checked);
-
- Appearance {
- background: active.background.transparentize(0.5),
- ..active
- }
- }
-}
diff --git a/style/src/lib.rs b/style/src/lib.rs
index 17ba09c4..1b2ce444 100644
--- a/style/src/lib.rs
+++ b/style/src/lib.rs
@@ -17,8 +17,6 @@
pub use iced_core as core;
pub mod application;
-pub mod button;
-pub mod checkbox;
pub mod container;
pub mod menu;
pub mod pane_grid;
diff --git a/style/src/theme.rs b/style/src/theme.rs
index f967aebc..81303e68 100644
--- a/style/src/theme.rs
+++ b/style/src/theme.rs
@@ -4,7 +4,6 @@ pub mod palette;
pub use palette::Palette;
use crate::application;
-use crate::checkbox;
use crate::container;
use crate::core::widget::text;
use crate::menu;
@@ -284,156 +283,6 @@ impl<T: Fn(&Theme) -> application::Appearance> application::StyleSheet for T {
}
}
-/// The style of a checkbox.
-#[derive(Default)]
-pub enum Checkbox {
- /// The primary style.
- #[default]
- Primary,
- /// The secondary style.
- Secondary,
- /// The success style.
- Success,
- /// The danger style.
- Danger,
- /// A custom style.
- Custom(Box<dyn checkbox::StyleSheet<Style = Theme>>),
-}
-
-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.primary.strong.text,
- palette.background.base,
- palette.primary.strong,
- is_checked,
- ),
- Checkbox::Secondary => checkbox_appearance(
- palette.background.base.text,
- palette.background.base,
- palette.background.strong,
- 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,
- ),
- Checkbox::Custom(custom) => custom.active(self, 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.primary.strong.text,
- palette.background.weak,
- palette.primary.base,
- is_checked,
- ),
- Checkbox::Secondary => checkbox_appearance(
- palette.background.base.text,
- palette.background.weak,
- palette.background.strong,
- 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,
- ),
- Checkbox::Custom(custom) => custom.hovered(self, is_checked),
- }
- }
-
- fn disabled(
- &self,
- style: &Self::Style,
- is_checked: bool,
- ) -> checkbox::Appearance {
- let palette = self.extended_palette();
-
- match style {
- Checkbox::Primary => checkbox_appearance(
- palette.primary.strong.text,
- palette.background.weak,
- palette.background.strong,
- is_checked,
- ),
- Checkbox::Secondary => checkbox_appearance(
- palette.background.strong.color,
- palette.background.weak,
- palette.background.weak,
- is_checked,
- ),
- Checkbox::Success => checkbox_appearance(
- palette.success.base.text,
- palette.background.weak,
- palette.success.weak,
- is_checked,
- ),
- Checkbox::Danger => checkbox_appearance(
- palette.danger.base.text,
- palette.background.weak,
- palette.danger.weak,
- is_checked,
- ),
- Checkbox::Custom(custom) => custom.active(self, is_checked),
- }
- }
-}
-
-fn checkbox_appearance(
- icon_color: Color,
- base: palette::Pair,
- accent: palette::Pair,
- is_checked: bool,
-) -> checkbox::Appearance {
- checkbox::Appearance {
- background: Background::Color(if is_checked {
- accent.color
- } else {
- base.color
- }),
- icon_color,
- border: Border {
- radius: 2.0.into(),
- width: 1.0,
- color: accent.color,
- },
- text_color: None,
- }
-}
-
/// The style of a container.
#[derive(Default)]
pub enum Container {
diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs
index 3a192fba..54513b7d 100644
--- a/widget/src/checkbox.rs
+++ b/widget/src/checkbox.rs
@@ -9,10 +9,11 @@ use crate::core::touch;
use crate::core::widget;
use crate::core::widget::tree::{self, Tree};
use crate::core::{
- Clipboard, Element, Layout, Length, Pixels, Rectangle, Shell, Size, Widget,
+ Background, Border, Clipboard, Color, Element, Layout, Length, Pixels,
+ Rectangle, Shell, Size, Widget,
};
-
-pub use crate::style::checkbox::{Appearance, StyleSheet};
+use crate::style::theme::palette;
+use crate::style::Theme;
/// A box that can be checked.
///
@@ -39,7 +40,6 @@ pub struct Checkbox<
Theme = crate::Theme,
Renderer = crate::Renderer,
> where
- Theme: StyleSheet,
Renderer: text::Renderer,
{
is_checked: bool,
@@ -53,13 +53,13 @@ pub struct Checkbox<
text_shaping: text::Shaping,
font: Option<Renderer::Font>,
icon: Icon<Renderer::Font>,
- style: <Theme as StyleSheet>::Style,
+ style: fn(&Theme, Status) -> Appearance,
}
impl<'a, Message, Theme, Renderer> Checkbox<'a, Message, Theme, Renderer>
where
Renderer: text::Renderer,
- Theme: StyleSheet + crate::text::StyleSheet,
+ Theme: Style,
{
/// The default size of a [`Checkbox`].
const DEFAULT_SIZE: f32 = 20.0;
@@ -91,7 +91,7 @@ where
line_height: text::LineHeight::default(),
shaping: text::Shaping::Basic,
},
- style: Default::default(),
+ style: Theme::default(),
}
}
@@ -174,10 +174,7 @@ where
}
/// Sets the style of the [`Checkbox`].
- pub fn style(
- mut self,
- style: impl Into<<Theme as StyleSheet>::Style>,
- ) -> Self {
+ pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self {
self.style = style.into();
self
}
@@ -186,7 +183,6 @@ where
impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
for Checkbox<'a, Message, Theme, Renderer>
where
- Theme: StyleSheet + crate::text::StyleSheet,
Renderer: text::Renderer,
{
fn tag(&self) -> tree::Tag {
@@ -293,17 +289,20 @@ where
) {
let is_mouse_over = cursor.is_over(layout.bounds());
let is_disabled = self.on_toggle.is_none();
+ let is_checked = self.is_checked;
let mut children = layout.children();
- let custom_style = if is_disabled {
- theme.disabled(&self.style, self.is_checked)
+ let status = if is_disabled {
+ Status::Disabled { is_checked }
} else if is_mouse_over {
- theme.hovered(&self.style, self.is_checked)
+ Status::Hovered { is_checked }
} else {
- theme.active(&self.style, self.is_checked)
+ Status::Active { is_checked }
};
+ let appearance = (self.style)(theme, status);
+
{
let layout = children.next().unwrap();
let bounds = layout.bounds();
@@ -311,10 +310,10 @@ where
renderer.fill_quad(
renderer::Quad {
bounds,
- border: custom_style.border,
+ border: appearance.border,
..renderer::Quad::default()
},
- custom_style.background,
+ appearance.background,
);
let Icon {
@@ -339,7 +338,7 @@ where
shaping: *shaping,
},
bounds.center(),
- custom_style.icon_color,
+ appearance.icon_color,
*viewport,
);
}
@@ -354,7 +353,7 @@ where
label_layout,
tree.state.downcast_ref(),
crate::text::Appearance {
- color: custom_style.text_color,
+ color: appearance.text_color,
},
viewport,
);
@@ -366,7 +365,7 @@ impl<'a, Message, Theme, Renderer> From<Checkbox<'a, Message, Theme, Renderer>>
for Element<'a, Message, Theme, Renderer>
where
Message: 'a,
- Theme: 'a + StyleSheet + crate::text::StyleSheet,
+ Theme: 'a,
Renderer: 'a + text::Renderer,
{
fn from(
@@ -390,3 +389,174 @@ pub struct Icon<Font> {
/// The shaping strategy of the icon.
pub shaping: text::Shaping,
}
+
+/// The possible status of a [`Checkbox`].
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Status {
+ /// The [`Checkbox`] can be interacted with.
+ Active {
+ /// Indicates if the [`Checkbox`] is currently checked.
+ is_checked: bool,
+ },
+ /// The [`Checkbox`] can be interacted with and it is being hovered.
+ Hovered {
+ /// Indicates if the [`Checkbox`] is currently checked.
+ is_checked: bool,
+ },
+ /// The [`Checkbox`] cannot be interacted with.
+ Disabled {
+ /// Indicates if the [`Checkbox`] is currently checked.
+ is_checked: bool,
+ },
+}
+
+/// The appearance of a checkbox.
+#[derive(Debug, Clone, Copy)]
+pub struct Appearance {
+ /// The [`Background`] of the checkbox.
+ pub background: Background,
+ /// The icon [`Color`] of the checkbox.
+ pub icon_color: Color,
+ /// The [`Border`] of hte checkbox.
+ pub border: Border,
+ /// The text [`Color`] of the checkbox.
+ pub text_color: Option<Color>,
+}
+
+/// A set of rules that dictate the style of a checkbox.
+pub trait Style {
+ /// The supported style of the [`StyleSheet`].
+ fn default() -> fn(&Self, Status) -> Appearance;
+}
+
+impl Style for Theme {
+ fn default() -> fn(&Self, Status) -> Appearance {
+ primary
+ }
+}
+
+/// A primary checkbox; denoting a main toggle.
+pub fn primary(theme: &Theme, status: Status) -> Appearance {
+ let palette = theme.extended_palette();
+
+ match status {
+ Status::Active { is_checked } => styled(
+ palette.primary.strong.text,
+ palette.background.base,
+ palette.primary.strong,
+ is_checked,
+ ),
+ Status::Hovered { is_checked } => styled(
+ palette.primary.strong.text,
+ palette.background.weak,
+ palette.primary.base,
+ is_checked,
+ ),
+ Status::Disabled { is_checked } => styled(
+ palette.primary.strong.text,
+ palette.background.weak,
+ palette.background.strong,
+ is_checked,
+ ),
+ }
+}
+
+/// A secondary checkbox; denoting a complementary toggle.
+pub fn secondary(theme: &Theme, status: Status) -> Appearance {
+ let palette = theme.extended_palette();
+
+ match status {
+ Status::Active { is_checked } => styled(
+ palette.background.base.text,
+ palette.background.base,
+ palette.background.strong,
+ is_checked,
+ ),
+ Status::Hovered { is_checked } => styled(
+ palette.background.base.text,
+ palette.background.weak,
+ palette.background.strong,
+ is_checked,
+ ),
+ Status::Disabled { is_checked } => styled(
+ palette.background.strong.color,
+ palette.background.weak,
+ palette.background.weak,
+ is_checked,
+ ),
+ }
+}
+
+/// A success checkbox; denoting a positive toggle.
+pub fn success(theme: &Theme, status: Status) -> Appearance {
+ let palette = theme.extended_palette();
+
+ match status {
+ Status::Active { is_checked } => styled(
+ palette.success.base.text,
+ palette.background.base,
+ palette.success.base,
+ is_checked,
+ ),
+ Status::Hovered { is_checked } => styled(
+ palette.success.base.text,
+ palette.background.weak,
+ palette.success.base,
+ is_checked,
+ ),
+ Status::Disabled { is_checked } => styled(
+ palette.success.base.text,
+ palette.background.weak,
+ palette.success.weak,
+ is_checked,
+ ),
+ }
+}
+
+/// A danger checkbox; denoting a negaive toggle.
+pub fn danger(theme: &Theme, status: Status) -> Appearance {
+ let palette = theme.extended_palette();
+
+ match status {
+ Status::Active { is_checked } => styled(
+ palette.danger.base.text,
+ palette.background.base,
+ palette.danger.base,
+ is_checked,
+ ),
+ Status::Hovered { is_checked } => styled(
+ palette.danger.base.text,
+ palette.background.weak,
+ palette.danger.base,
+ is_checked,
+ ),
+ Status::Disabled { is_checked } => styled(
+ palette.danger.base.text,
+ palette.background.weak,
+ palette.danger.weak,
+ is_checked,
+ ),
+ }
+}
+
+fn styled(
+ icon_color: Color,
+ base: palette::Pair,
+ accent: palette::Pair,
+ is_checked: bool,
+) -> Appearance {
+ Appearance {
+ background: Background::Color(if is_checked {
+ accent.color
+ } else {
+ base.color
+ }),
+ icon_color,
+ border: Border {
+ radius: 2.0.into(),
+ width: 1.0,
+ color: accent.color,
+ },
+ text_color: None,
+ }
+}
diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs
index 86331e14..397cc452 100644
--- a/widget/src/helpers.rs
+++ b/widget/src/helpers.rs
@@ -161,7 +161,7 @@ pub fn checkbox<'a, Message, Theme, Renderer>(
is_checked: bool,
) -> Checkbox<'a, Message, Theme, Renderer>
where
- Theme: checkbox::StyleSheet + text::StyleSheet,
+ Theme: checkbox::Style,
Renderer: core::text::Renderer,
{
Checkbox::new(label, is_checked)