1use crate::container;
2use crate::core::layout;
3use crate::core::mouse;
4use crate::core::overlay;
5use crate::core::renderer;
6use crate::core::theme;
7use crate::core::widget::tree::{self, Tree};
8use crate::core::widget::{Meta, Operation};
9use crate::core::{
10 Background, Color, Element, Event, Layout, Length, Rectangle, Shell, Size, Vector, Widget,
11};
12
13pub struct Themer<'a, Message, Theme, Renderer = crate::Renderer>
18where
19 Renderer: crate::core::Renderer,
20{
21 content: Element<'a, Message, Theme, Renderer>,
22 theme: Option<Theme>,
23 text_color: Option<fn(&Theme) -> Color>,
24 background: Option<fn(&Theme) -> Background>,
25}
26
27impl<'a, Message, Theme, Renderer> Themer<'a, Message, Theme, Renderer>
28where
29 Renderer: crate::core::Renderer,
30{
31 pub fn new(theme: Option<Theme>, content: impl Widget<Message, Theme, Renderer> + 'a) -> Self {
34 Self {
35 content: content._boxed(),
36 theme,
37 text_color: None,
38 background: None,
39 }
40 }
41
42 pub fn text_color(mut self, f: fn(&Theme) -> Color) -> Self {
44 self.text_color = Some(f);
45 self
46 }
47
48 pub fn background(mut self, f: fn(&Theme) -> Background) -> Self {
50 self.background = Some(f);
51 self
52 }
53}
54
55impl<Message, Theme, Renderer> Meta for Themer<'_, Message, Theme, Renderer> where
56 Renderer: crate::core::Renderer
57{
58}
59
60impl<Message, Theme, Renderer, AnyTheme> Widget<Message, AnyTheme, Renderer>
61 for Themer<'_, Message, Theme, Renderer>
62where
63 Theme: theme::Base,
64 AnyTheme: theme::Base,
65 Renderer: crate::core::Renderer,
66{
67 fn tag(&self) -> tree::Tag {
68 self.content.tag()
69 }
70
71 fn state(&self) -> tree::State {
72 self.content.state()
73 }
74
75 fn diff(&mut self, tree: &mut Tree) {
76 self.content.diff(tree);
77 }
78
79 fn size(&self) -> Size<Length> {
80 self.content.size()
81 }
82
83 fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits) {
84 self.content.layout(tree, renderer, limits);
85 }
86
87 fn operate(
88 &mut self,
89 tree: &mut Tree,
90 layout: Layout,
91 viewport: &Rectangle,
92 renderer: &Renderer,
93 operation: &mut dyn Operation,
94 ) {
95 self.content
96 .operate(tree, layout, viewport, renderer, operation);
97 }
98
99 fn update(
100 &mut self,
101 tree: &mut Tree,
102 event: &Event,
103 layout: Layout,
104 cursor: mouse::Cursor,
105 renderer: &Renderer,
106 shell: &mut Shell<'_, Message>,
107 viewport: &Rectangle,
108 ) {
109 self.content
110 .update(tree, event, layout, cursor, renderer, shell, viewport);
111 }
112
113 fn mouse_interaction(
114 &self,
115 tree: &Tree,
116 layout: Layout,
117 cursor: mouse::Cursor,
118 viewport: &Rectangle,
119 renderer: &Renderer,
120 ) -> mouse::Interaction {
121 self.content
122 .mouse_interaction(tree, layout, cursor, viewport, renderer)
123 }
124
125 fn draw(
126 &self,
127 tree: &Tree,
128 renderer: &mut Renderer,
129 theme: &AnyTheme,
130 style: &renderer::Style,
131 layout: Layout,
132 cursor: mouse::Cursor,
133 viewport: &Rectangle,
134 ) {
135 let default_theme = theme::Base::default(theme.mode());
136 let theme = self.theme.as_ref().unwrap_or(&default_theme);
137
138 if let Some(background) = self.background {
139 container::draw_background(
140 renderer,
141 &container::Style {
142 background: Some(background(theme)),
143 ..container::Style::default()
144 },
145 layout.bounds(),
146 );
147 }
148
149 let style = if let Some(text_color) = self.text_color {
150 renderer::Style {
151 text_color: text_color(theme),
152 }
153 } else {
154 *style
155 };
156
157 self.content
158 .draw(tree, renderer, theme, &style, layout, cursor, viewport);
159 }
160
161 fn overlay<'b>(
162 &'b mut self,
163 tree: &'b mut Tree,
164 layout: Layout,
165 renderer: &Renderer,
166 viewport: &Rectangle,
167 translation: Vector,
168 window: Size,
169 ) -> Vec<overlay::Element<'b, Message, AnyTheme, Renderer>> {
170 struct Overlay<'a, Message, Theme, Renderer> {
171 theme: &'a Option<Theme>,
172 content: overlay::Element<'a, Message, Theme, Renderer>,
173 }
174
175 impl<Message, Theme, Renderer, AnyTheme> overlay::Overlay<Message, AnyTheme, Renderer>
176 for Overlay<'_, Message, Theme, Renderer>
177 where
178 Theme: theme::Base,
179 AnyTheme: theme::Base,
180 Renderer: crate::core::Renderer,
181 {
182 fn draw(
183 &self,
184 renderer: &mut Renderer,
185 theme: &AnyTheme,
186 style: &renderer::Style,
187 cursor: mouse::Cursor,
188 ) {
189 let default_theme = theme::Base::default(theme.mode());
190 let theme = self.theme.as_ref().unwrap_or(&default_theme);
191
192 self.content
193 .as_overlay()
194 .draw(renderer, theme, style, cursor);
195 }
196
197 fn update(
198 &mut self,
199 event: &Event,
200 cursor: mouse::Cursor,
201 renderer: &Renderer,
202 shell: &mut Shell<'_, Message>,
203 ) {
204 self.content
205 .as_overlay_mut()
206 .update(event, cursor, renderer, shell);
207 }
208
209 fn operate(&mut self, renderer: &Renderer, operation: &mut dyn Operation) {
210 self.content.as_overlay_mut().operate(renderer, operation);
211 }
212
213 fn mouse_interaction(
214 &self,
215 cursor: mouse::Cursor,
216 renderer: &Renderer,
217 ) -> mouse::Interaction {
218 self.content
219 .as_overlay()
220 .mouse_interaction(cursor, renderer)
221 }
222
223 fn index(&self) -> f32 {
224 self.content.as_overlay().index()
225 }
226
227 fn overlay<'c>(
228 &'c mut self,
229 renderer: &Renderer,
230 ) -> Vec<overlay::Element<'c, Message, AnyTheme, Renderer>> {
231 let theme = self.theme;
232
233 self.content
234 .as_overlay_mut()
235 .overlay(renderer)
236 .into_iter()
237 .map(|content| overlay::Element::new(Box::new(Overlay { theme, content })))
238 .collect()
239 }
240 }
241
242 self.content
243 .overlay(tree, layout, renderer, viewport, translation, window)
244 .into_iter()
245 .map(|content| {
246 overlay::Element::new(Box::new(Overlay {
247 theme: &self.theme,
248 content,
249 }))
250 })
251 .collect()
252 }
253}