1use std::any::Any;
9use std::borrow::Cow;
10use std::ops::{Deref, DerefMut};
11
12use super::{Theme, Window};
13use kas::draw::{color, DrawIface, DrawSharedImpl, SharedState};
14use kas::event::EventState;
15use kas::theme::{ThemeControl, ThemeDraw, ThemeSize};
16use kas::TkAction;
17
18pub enum MaybeBoxed<'a, B: 'a + ?Sized> {
22 Borrowed(&'a B),
23 Boxed(Box<B>),
24}
25
26impl<T: ?Sized> AsRef<T> for MaybeBoxed<'_, T> {
27 fn as_ref(&self) -> &T {
28 match self {
29 MaybeBoxed::Borrowed(r) => r,
30 MaybeBoxed::Boxed(b) => b.as_ref(),
31 }
32 }
33}
34
35pub trait ThemeDst<DS: DrawSharedImpl>: ThemeControl {
41 fn config(&self) -> MaybeBoxed<dyn Any>;
43
44 fn apply_config(&mut self, config: &dyn Any) -> TkAction;
46
47 fn init(&mut self, shared: &mut SharedState<DS>);
51
52 fn new_window(&self, dpi_factor: f32) -> Box<dyn Window>;
56
57 fn update_window(&self, window: &mut dyn Window, dpi_factor: f32);
61
62 fn draw<'a>(
63 &'a self,
64 draw: DrawIface<'a, DS>,
65 ev: &'a mut EventState,
66 window: &'a mut dyn Window,
67 ) -> Box<dyn ThemeDraw + 'a>;
68
69 fn clear_color(&self) -> color::Rgba;
73}
74
75impl<DS: DrawSharedImpl, T: Theme<DS>> ThemeDst<DS> for T {
76 fn config(&self) -> MaybeBoxed<dyn Any> {
77 match self.config() {
78 Cow::Borrowed(config) => MaybeBoxed::Borrowed(config),
79 Cow::Owned(config) => MaybeBoxed::Boxed(Box::new(config)),
80 }
81 }
82
83 fn apply_config(&mut self, config: &dyn Any) -> TkAction {
84 self.apply_config(config.downcast_ref().unwrap())
85 }
86
87 fn init(&mut self, shared: &mut SharedState<DS>) {
88 self.init(shared);
89 }
90
91 fn new_window(&self, dpi_factor: f32) -> Box<dyn Window> {
92 let window = <T as Theme<DS>>::new_window(self, dpi_factor);
93 Box::new(window)
94 }
95
96 fn update_window(&self, window: &mut dyn Window, dpi_factor: f32) {
97 let window = window.as_any_mut().downcast_mut().unwrap();
98 self.update_window(window, dpi_factor);
99 }
100
101 fn draw<'b>(
102 &'b self,
103 draw: DrawIface<'b, DS>,
104 ev: &'b mut EventState,
105 window: &'b mut dyn Window,
106 ) -> Box<dyn ThemeDraw + 'b> {
107 let window = window.as_any_mut().downcast_mut().unwrap();
108 Box::new(<T as Theme<DS>>::draw(self, draw, ev, window))
109 }
110
111 fn clear_color(&self) -> color::Rgba {
112 self.clear_color()
113 }
114}
115
116impl Window for Box<dyn Window> {
117 fn size(&self) -> &dyn ThemeSize {
118 self.deref().size()
119 }
120
121 fn as_any_mut(&mut self) -> &mut dyn Any {
122 self.deref_mut().as_any_mut()
123 }
124}