diff options
Diffstat (limited to 'widget/src/radio.rs')
-rw-r--r-- | widget/src/radio.rs | 106 |
1 files changed, 85 insertions, 21 deletions
diff --git a/widget/src/radio.rs b/widget/src/radio.rs index 68e9bc7e..c4283af8 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -9,11 +9,10 @@ use crate::core::touch; use crate::core::widget; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Border, Clipboard, Element, Layout, Length, Pixels, Rectangle, Shell, Size, - Widget, + Background, Border, Clipboard, Color, Element, Layout, Length, Pixels, + Rectangle, Shell, Size, Widget, }; - -pub use iced_style::radio::{Appearance, StyleSheet}; +use crate::style::Theme; /// A circular button representing a choice. /// @@ -71,7 +70,6 @@ pub use iced_style::radio::{Appearance, StyleSheet}; #[allow(missing_debug_implementations)] pub struct Radio<Message, Theme = crate::Theme, Renderer = crate::Renderer> where - Theme: StyleSheet, Renderer: text::Renderer, { is_selected: bool, @@ -84,20 +82,19 @@ where text_line_height: text::LineHeight, text_shaping: text::Shaping, font: Option<Renderer::Font>, - style: Theme::Style, + style: fn(&Theme, Status) -> Appearance, } impl<Message, Theme, Renderer> Radio<Message, Theme, Renderer> where Message: Clone, - Theme: StyleSheet, Renderer: text::Renderer, { /// The default size of a [`Radio`] button. - pub const DEFAULT_SIZE: f32 = 28.0; + pub const DEFAULT_SIZE: f32 = 14.0; /// The default spacing of a [`Radio`] button. - pub const DEFAULT_SPACING: f32 = 15.0; + pub const DEFAULT_SPACING: f32 = 10.0; /// Creates a new [`Radio`] button. /// @@ -114,6 +111,7 @@ where f: F, ) -> Self where + Theme: Style, V: Eq + Copy, F: FnOnce(V) -> Message, { @@ -128,7 +126,7 @@ where text_line_height: text::LineHeight::default(), text_shaping: text::Shaping::Basic, font: None, - style: Default::default(), + style: Theme::style(), } } @@ -178,7 +176,7 @@ where } /// Sets the style of the [`Radio`] button. - pub fn style(mut self, style: impl Into<Theme::Style>) -> Self { + pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { self.style = style.into(); self } @@ -188,7 +186,6 @@ impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer> for Radio<Message, Theme, Renderer> where Message: Clone, - Theme: StyleSheet + crate::text::StyleSheet, Renderer: text::Renderer, { fn tag(&self) -> tree::Tag { @@ -291,15 +288,18 @@ where viewport: &Rectangle, ) { let is_mouse_over = cursor.is_over(layout.bounds()); + let is_selected = self.is_selected; let mut children = layout.children(); - let custom_style = if is_mouse_over { - theme.hovered(&self.style, self.is_selected) + let status = if is_mouse_over { + Status::Hovered { is_selected } } else { - theme.active(&self.style, self.is_selected) + Status::Active { is_selected } }; + let appearance = (self.style)(theme, status); + { let layout = children.next().unwrap(); let bounds = layout.bounds(); @@ -312,12 +312,12 @@ where bounds, border: Border { radius: (size / 2.0).into(), - width: custom_style.border_width, - color: custom_style.border_color, + width: appearance.border_width, + color: appearance.border_color, }, ..renderer::Quad::default() }, - custom_style.background, + appearance.background, ); if self.is_selected { @@ -332,7 +332,7 @@ where border: Border::with_radius(dot_size / 2.0), ..renderer::Quad::default() }, - custom_style.dot_color, + appearance.dot_color, ); } } @@ -346,7 +346,7 @@ where label_layout, tree.state.downcast_ref(), crate::text::Appearance { - color: custom_style.text_color, + color: appearance.text_color, }, viewport, ); @@ -358,7 +358,7 @@ impl<'a, Message, Theme, Renderer> From<Radio<Message, Theme, Renderer>> for Element<'a, Message, Theme, Renderer> where Message: 'a + Clone, - Theme: StyleSheet + crate::text::StyleSheet + 'a, + Theme: 'a, Renderer: 'a + text::Renderer, { fn from( @@ -367,3 +367,67 @@ where Element::new(radio) } } + +/// The possible status of a [`TextInput`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Status { + /// The [`Radio`] button can be interacted with. + Active { + /// Indicates whether the [`Radio`] button is currently selected. + is_selected: bool, + }, + /// The [`Radio`] button is being hovered. + Hovered { + /// Indicates whether the [`Radio`] button is currently selected. + is_selected: bool, + }, +} + +/// The appearance of a radio button. +#[derive(Debug, Clone, Copy)] +pub struct Appearance { + /// The [`Background`] of the radio button. + pub background: Background, + /// The [`Color`] of the dot of the radio button. + pub dot_color: Color, + /// The border width of the radio button. + pub border_width: f32, + /// The border [`Color`] of the radio button. + pub border_color: Color, + /// The text [`Color`] of the radio button. + pub text_color: Option<Color>, +} + +/// The definiton of the default style of a [`Radio`] button. +pub trait Style { + /// Returns the default style of a [`Radio`] button. + fn style() -> fn(&Self, Status) -> Appearance; +} + +impl Style for Theme { + fn style() -> fn(&Self, Status) -> Appearance { + default + } +} + +/// The default style of a [`Radio`] button. +pub fn default(theme: &Theme, status: Status) -> Appearance { + let palette = theme.extended_palette(); + + let active = Appearance { + background: Color::TRANSPARENT.into(), + dot_color: palette.primary.strong.color, + border_width: 1.0, + border_color: palette.primary.strong.color, + text_color: None, + }; + + match status { + Status::Active { .. } => active, + Status::Hovered { .. } => Appearance { + dot_color: palette.primary.strong.color, + background: palette.primary.weak.color.into(), + ..active + }, + } +} |