diff options
author | 2024-03-06 17:08:28 +0100 | |
---|---|---|
committer | 2024-03-06 17:08:57 +0100 | |
commit | 597a41cea73f078eda04eb3ff40cfda5d37d6135 (patch) | |
tree | 216779f151b68952fd5d668065dc900be08e3e99 /widget/src/overlay | |
parent | 9b2fd6416775cb27af69e34fb20063d28b4314eb (diff) | |
download | iced-597a41cea73f078eda04eb3ff40cfda5d37d6135.tar.gz iced-597a41cea73f078eda04eb3ff40cfda5d37d6135.tar.bz2 iced-597a41cea73f078eda04eb3ff40cfda5d37d6135.zip |
Simplify theming for `PickList`, `ComboBox`, and `Menu` widgets
Diffstat (limited to 'widget/src/overlay')
-rw-r--r-- | widget/src/overlay/menu.rs | 143 |
1 files changed, 110 insertions, 33 deletions
diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index d820592d..bb8ad0e0 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -10,12 +10,12 @@ use crate::core::text::{self, Text}; use crate::core::touch; use crate::core::widget::Tree; use crate::core::{ - Border, Clipboard, Length, Padding, Pixels, Point, Rectangle, Size, Vector, + Background, Border, Clipboard, Color, Length, Padding, Pixels, Point, + Rectangle, Size, Vector, }; use crate::core::{Element, Shell, Widget}; use crate::scrollable::{self, Scrollable}; - -pub use iced_style::menu::{Appearance, StyleSheet}; +use crate::style::Theme; /// A list of selectable options. #[allow(missing_debug_implementations)] @@ -26,7 +26,6 @@ pub struct Menu< Theme = crate::Theme, Renderer = crate::Renderer, > where - Theme: StyleSheet, Renderer: text::Renderer, { state: &'a mut State, @@ -40,14 +39,14 @@ pub struct Menu< text_line_height: text::LineHeight, text_shaping: text::Shaping, font: Option<Renderer::Font>, - style: Theme::Style, + style: Style<Theme>, } impl<'a, T, Message, Theme, Renderer> Menu<'a, T, Message, Theme, Renderer> where T: ToString + Clone, Message: 'a, - Theme: StyleSheet + container::Style + scrollable::Style + 'a, + Theme: container::Style + scrollable::Style + 'a, Renderer: text::Renderer + 'a, { /// Creates a new [`Menu`] with the given [`State`], a list of options, and @@ -58,6 +57,29 @@ where hovered_option: &'a mut Option<usize>, on_selected: impl FnMut(T) -> Message + 'a, on_option_hovered: Option<&'a dyn Fn(T) -> Message>, + ) -> Self + where + Style<Theme>: Default, + { + Self::with_style( + state, + options, + hovered_option, + on_selected, + on_option_hovered, + Style::default(), + ) + } + + /// Creates a new [`Menu`] with the given [`State`], a list of options, + /// the message to produced when an option is selected, and its [`Style`]. + pub fn with_style( + state: &'a mut State, + options: &'a [T], + hovered_option: &'a mut Option<usize>, + on_selected: impl FnMut(T) -> Message + 'a, + on_option_hovered: Option<&'a dyn Fn(T) -> Message>, + style: Style<Theme>, ) -> Self { Menu { state, @@ -71,7 +93,7 @@ where text_line_height: text::LineHeight::default(), text_shaping: text::Shaping::Basic, font: None, - style: Default::default(), + style, } } @@ -115,10 +137,7 @@ where } /// Sets the style of the [`Menu`]. - pub fn style( - mut self, - style: impl Into<<Theme as StyleSheet>::Style>, - ) -> Self { + pub fn style(mut self, style: impl Into<Style<Theme>>) -> Self { self.style = style.into(); self } @@ -165,7 +184,6 @@ impl Default for State { struct Overlay<'a, Message, Theme, Renderer> where - Theme: StyleSheet + container::Style, Renderer: crate::core::Renderer, { position: Point, @@ -173,13 +191,13 @@ where container: Container<'a, Message, Theme, Renderer>, width: f32, target_height: f32, - style: <Theme as StyleSheet>::Style, + style: Style<Theme>, } impl<'a, Message, Theme, Renderer> Overlay<'a, Message, Theme, Renderer> where Message: 'a, - Theme: StyleSheet + container::Style + scrollable::Style + 'a, + Theme: container::Style + scrollable::Style + 'a, Renderer: text::Renderer + 'a, { pub fn new<T>( @@ -205,18 +223,21 @@ where style, } = menu; - let container = Container::new(Scrollable::new(List { - options, - hovered_option, - on_selected, - on_option_hovered, - font, - text_size, - text_line_height, - text_shaping, - padding, - style: style.clone(), - })); + let container = Container::new( + Scrollable::new(List { + options, + hovered_option, + on_selected, + on_option_hovered, + font, + text_size, + text_line_height, + text_shaping, + padding, + style: style.menu, + }) + .style(style.scrollable), + ); state.tree.diff(&container as &dyn Widget<_, _, _>); @@ -235,7 +256,6 @@ impl<'a, Message, Theme, Renderer> crate::core::Overlay<Message, Theme, Renderer> for Overlay<'a, Message, Theme, Renderer> where - Theme: StyleSheet + container::Style, Renderer: text::Renderer, { fn layout(&mut self, renderer: &Renderer, bounds: Size) -> layout::Node { @@ -302,9 +322,10 @@ where layout: Layout<'_>, cursor: mouse::Cursor, ) { - let appearance = StyleSheet::appearance(theme, &self.style); let bounds = layout.bounds(); + let appearance = (self.style.menu)(theme); + renderer.fill_quad( renderer::Quad { bounds, @@ -321,7 +342,6 @@ where struct List<'a, T, Message, Theme, Renderer> where - Theme: StyleSheet, Renderer: text::Renderer, { options: &'a [T], @@ -333,14 +353,13 @@ where text_line_height: text::LineHeight, text_shaping: text::Shaping, font: Option<Renderer::Font>, - style: Theme::Style, + style: fn(&Theme) -> Appearance, } impl<'a, T, Message, Theme, Renderer> Widget<Message, Theme, Renderer> for List<'a, T, Message, Theme, Renderer> where T: Clone + ToString, - Theme: StyleSheet, Renderer: text::Renderer, { fn size(&self) -> Size<Length> { @@ -483,7 +502,7 @@ where _cursor: mouse::Cursor, viewport: &Rectangle, ) { - let appearance = theme.appearance(&self.style); + let appearance = (self.style)(theme); let bounds = layout.bounds(); let text_size = @@ -553,10 +572,68 @@ impl<'a, T, Message, Theme, Renderer> where T: ToString + Clone, Message: 'a, - Theme: StyleSheet + 'a, + Theme: 'a, Renderer: 'a + text::Renderer, { fn from(list: List<'a, T, Message, Theme, Renderer>) -> Self { Element::new(list) } } + +/// The appearance of a [`Menu`]. +#[derive(Debug, Clone, Copy)] +pub struct Appearance { + /// The [`Background`] of the menu. + pub background: Background, + /// The [`Border`] of the menu. + pub border: Border, + /// The text [`Color`] of the menu. + pub text_color: Color, + /// The text [`Color`] of a selected option in the menu. + pub selected_text_color: Color, + /// The background [`Color`] of a selected option in the menu. + pub selected_background: Background, +} + +/// The definiton of the default style of a [`Menu`]. +#[derive(Debug, PartialEq, Eq)] +pub struct Style<Theme> { + /// The style of the [`Menu`]. + menu: fn(&Theme) -> Appearance, + /// The style of the [`Scrollable`] of the [`Menu`]. + scrollable: fn(&Theme, scrollable::Status) -> scrollable::Appearance, +} + +impl<Theme> Clone for Style<Theme> { + fn clone(&self) -> Self { + *self + } +} + +impl<Theme> Copy for Style<Theme> {} + +impl Default for Style<Theme> { + fn default() -> Self { + Self { + menu: default, + scrollable: scrollable::default, + } + } +} + +/// The default style of a [`Menu`]. +pub fn default(theme: &Theme) -> Appearance { + let palette = theme.extended_palette(); + + Appearance { + background: palette.background.weak.color.into(), + border: Border { + width: 1.0, + radius: 0.0.into(), + color: palette.background.strong.color, + }, + text_color: palette.background.weak.text, + selected_text_color: palette.primary.strong.text, + selected_background: palette.primary.strong.color.into(), + } +} |