diff options
| author | 2024-03-04 19:32:20 +0100 | |
|---|---|---|
| committer | 2024-03-04 19:32:20 +0100 | |
| commit | db92e1c942154bee474fee5e2c187f8a52a1bb96 (patch) | |
| tree | f88b7c39e27a4ff86504c47bd9c475bd49022db8 /widget/src | |
| parent | 4130ae4be95ce850263fbc55f490b68a95361d58 (diff) | |
| download | iced-db92e1c942154bee474fee5e2c187f8a52a1bb96.tar.gz iced-db92e1c942154bee474fee5e2c187f8a52a1bb96.tar.bz2 iced-db92e1c942154bee474fee5e2c187f8a52a1bb96.zip  | |
Enhnace `Themer` to allow derivation from current `Theme`
Diffstat (limited to '')
| -rw-r--r-- | widget/src/helpers.rs | 13 | ||||
| -rw-r--r-- | widget/src/themer.rs | 133 | 
2 files changed, 80 insertions, 66 deletions
diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index ed385ea5..e6322926 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -15,7 +15,6 @@ use crate::rule::{self, Rule};  use crate::runtime::Command;  use crate::scrollable::{self, Scrollable};  use crate::slider::{self, Slider}; -use crate::style::application;  use crate::text::{self, Text};  use crate::text_editor::{self, TextEditor};  use crate::text_input::{self, TextInput}; @@ -440,13 +439,13 @@ where  }  /// A widget that applies any `Theme` to its contents. -pub fn themer<'a, Message, Theme, Renderer>( -    theme: Theme, -    content: impl Into<Element<'a, Message, Theme, Renderer>>, -) -> Themer<'a, Message, Theme, Renderer> +pub fn themer<'a, Message, OldTheme, NewTheme, F, Renderer>( +    to_theme: F, +    content: impl Into<Element<'a, Message, NewTheme, Renderer>>, +) -> Themer<'a, Message, OldTheme, NewTheme, F, Renderer>  where +    F: Fn(&OldTheme) -> NewTheme,      Renderer: core::Renderer, -    Theme: application::StyleSheet,  { -    Themer::new(theme, content) +    Themer::new(to_theme, content)  } diff --git a/widget/src/themer.rs b/widget/src/themer.rs index 3a5fd823..a7eabd2c 100644 --- a/widget/src/themer.rs +++ b/widget/src/themer.rs @@ -7,58 +7,68 @@ use crate::core::renderer;  use crate::core::widget::tree::{self, Tree};  use crate::core::widget::Operation;  use crate::core::{ -    Background, Clipboard, Element, Layout, Length, Point, Rectangle, Shell, -    Size, Vector, Widget, +    Background, Clipboard, Color, Element, Layout, Length, Point, Rectangle, +    Shell, Size, Vector, Widget,  }; -use crate::style::application; + +use std::marker::PhantomData;  /// A widget that applies any `Theme` to its contents.  ///  /// This widget can be useful to leverage multiple `Theme`  /// types in an application.  #[allow(missing_debug_implementations)] -pub struct Themer<'a, Message, Theme, Renderer> +pub struct Themer<'a, Message, Theme, NewTheme, F, Renderer = crate::Renderer>  where +    F: Fn(&Theme) -> NewTheme,      Renderer: crate::core::Renderer, -    Theme: application::StyleSheet,  { -    content: Element<'a, Message, Theme, Renderer>, -    theme: Theme, -    style: Theme::Style, -    show_background: bool, +    content: Element<'a, Message, NewTheme, Renderer>, +    to_theme: F, +    text_color: Option<fn(&NewTheme) -> Color>, +    background: Option<fn(&NewTheme) -> Background>, +    old_theme: PhantomData<Theme>,  } -impl<'a, Message, Theme, Renderer> Themer<'a, Message, Theme, Renderer> +impl<'a, Message, Theme, NewTheme, F, Renderer> +    Themer<'a, Message, Theme, NewTheme, F, Renderer>  where +    F: Fn(&Theme) -> NewTheme,      Renderer: crate::core::Renderer, -    Theme: application::StyleSheet,  {      /// Creates an empty [`Themer`] that applies the given `Theme`      /// to the provided `content`. -    pub fn new<T>(theme: Theme, content: T) -> Self +    pub fn new<T>(to_theme: F, content: T) -> Self      where -        T: Into<Element<'a, Message, Theme, Renderer>>, +        T: Into<Element<'a, Message, NewTheme, Renderer>>,      {          Self {              content: content.into(), -            theme, -            style: Theme::Style::default(), -            show_background: false, +            to_theme, +            text_color: None, +            background: None, +            old_theme: PhantomData,          }      } -    /// Sets whether to draw the background color of the `Theme`. -    pub fn background(mut self, background: bool) -> Self { -        self.show_background = background; +    /// Sets the default text [`Color`] of the [`Themer`]. +    pub fn text_color(mut self, f: fn(&NewTheme) -> Color) -> Self { +        self.text_color = Some(f); +        self +    } + +    /// Sets the [`Background`] of the [`Themer`]. +    pub fn background(mut self, f: fn(&NewTheme) -> Background) -> Self { +        self.background = Some(f);          self      }  } -impl<'a, AnyTheme, Message, Theme, Renderer> Widget<Message, AnyTheme, Renderer> -    for Themer<'a, Message, Theme, Renderer> +impl<'a, Message, Theme, NewTheme, F, Renderer> Widget<Message, Theme, Renderer> +    for Themer<'a, Message, Theme, NewTheme, F, Renderer>  where +    F: Fn(&Theme) -> NewTheme,      Renderer: crate::core::Renderer, -    Theme: application::StyleSheet,  {      fn tag(&self) -> tree::Tag {          self.content.as_widget().tag() @@ -134,38 +144,36 @@ where          &self,          tree: &Tree,          renderer: &mut Renderer, -        _theme: &AnyTheme, -        _style: &renderer::Style, +        theme: &Theme, +        style: &renderer::Style,          layout: Layout<'_>,          cursor: mouse::Cursor,          viewport: &Rectangle,      ) { -        let appearance = self.theme.appearance(&self.style); +        let theme = (self.to_theme)(theme); -        if self.show_background { +        if let Some(background) = self.background {              container::draw_background(                  renderer,                  &container::Appearance { -                    background: Some(Background::Color( -                        appearance.background_color, -                    )), +                    background: Some(background(&theme)),                      ..container::Appearance::default()                  },                  layout.bounds(),              );          } -        self.content.as_widget().draw( -            tree, -            renderer, -            &self.theme, -            &renderer::Style { -                text_color: appearance.text_color, -            }, -            layout, -            cursor, -            viewport, -        ); +        let style = if let Some(text_color) = self.text_color { +            renderer::Style { +                text_color: text_color(&theme), +            } +        } else { +            *style +        }; + +        self.content +            .as_widget() +            .draw(tree, renderer, &theme, &style, layout, cursor, viewport);      }      fn overlay<'b>( @@ -174,15 +182,15 @@ where          layout: Layout<'_>,          renderer: &Renderer,          translation: Vector, -    ) -> Option<overlay::Element<'b, Message, AnyTheme, Renderer>> { -        struct Overlay<'a, Message, Theme, Renderer> { -            theme: &'a Theme, -            content: overlay::Element<'a, Message, Theme, Renderer>, +    ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> { +        struct Overlay<'a, Message, Theme, NewTheme, Renderer> { +            to_theme: &'a dyn Fn(&Theme) -> NewTheme, +            content: overlay::Element<'a, Message, NewTheme, Renderer>,          } -        impl<'a, AnyTheme, Message, Theme, Renderer> -            overlay::Overlay<Message, AnyTheme, Renderer> -            for Overlay<'a, Message, Theme, Renderer> +        impl<'a, Message, Theme, NewTheme, Renderer> +            overlay::Overlay<Message, Theme, Renderer> +            for Overlay<'a, Message, Theme, NewTheme, Renderer>          where              Renderer: crate::core::Renderer,          { @@ -197,13 +205,18 @@ where              fn draw(                  &self,                  renderer: &mut Renderer, -                _theme: &AnyTheme, +                theme: &Theme,                  style: &renderer::Style,                  layout: Layout<'_>,                  cursor: mouse::Cursor,              ) { -                self.content -                    .draw(renderer, self.theme, style, layout, cursor); +                self.content.draw( +                    renderer, +                    &(self.to_theme)(theme), +                    style, +                    layout, +                    cursor, +                );              }              fn on_event( @@ -252,12 +265,12 @@ where                  &'b mut self,                  layout: Layout<'_>,                  renderer: &Renderer, -            ) -> Option<overlay::Element<'b, Message, AnyTheme, Renderer>> +            ) -> Option<overlay::Element<'b, Message, Theme, Renderer>>              {                  self.content                      .overlay(layout, renderer)                      .map(|content| Overlay { -                        theme: self.theme, +                        to_theme: &self.to_theme,                          content,                      })                      .map(|overlay| overlay::Element::new(Box::new(overlay))) @@ -268,24 +281,26 @@ where              .as_widget_mut()              .overlay(tree, layout, renderer, translation)              .map(|content| Overlay { -                theme: &self.theme, +                to_theme: &self.to_theme,                  content,              })              .map(|overlay| overlay::Element::new(Box::new(overlay)))      }  } -impl<'a, AnyTheme, Message, Theme, Renderer> -    From<Themer<'a, Message, Theme, Renderer>> -    for Element<'a, Message, AnyTheme, Renderer> +impl<'a, Message, Theme, NewTheme, F, Renderer> +    From<Themer<'a, Message, Theme, NewTheme, F, Renderer>> +    for Element<'a, Message, Theme, Renderer>  where      Message: 'a, -    Theme: 'a + application::StyleSheet, +    Theme: 'a, +    NewTheme: 'a, +    F: Fn(&Theme) -> NewTheme + 'a,      Renderer: 'a + crate::core::Renderer,  {      fn from( -        themer: Themer<'a, Message, Theme, Renderer>, -    ) -> Element<'a, Message, AnyTheme, Renderer> { +        themer: Themer<'a, Message, Theme, NewTheme, F, Renderer>, +    ) -> Element<'a, Message, Theme, Renderer> {          Element::new(themer)      }  }  | 
