1use drying_paint::{WatcherInit, WatcherMeta};
6
7use crate::platform::{DefaultRenderPlatform, RenderPlatform};
8
9use super::{layout, WidgetContent, WidgetId, WidgetInternal, WidgetRect};
10
11pub trait WidgetInit<T, P = DefaultRenderPlatform>
17where
18 P: RenderPlatform + ?Sized,
19 T: WidgetContent<P> + ?Sized,
20{
21 fn widget_id(&self) -> WidgetId;
26
27 fn watch<F>(&mut self, func: F)
30 where
31 F: Fn(&mut T, &mut WidgetRect) + 'static;
32
33 fn create_layout_group(&mut self) -> layout::LayoutTypes<Self, T, P> {
36 layout::LayoutTypes::new(self)
37 }
38
39 #[doc(hidden)]
40 fn init_child_inline<F, C>(&mut self, getter: F)
41 where
42 C: WidgetContent<P>,
43 F: 'static + Clone + Fn(&mut T) -> &mut C;
44}
45
46struct WidgetInitImpl<'a, 'b, O, T, G, P>
47where
48 P: RenderPlatform + ?Sized,
49 G: 'static + Clone + Fn(&mut O) -> &mut T,
50 O: WidgetContent<P>,
51 T: WidgetContent<P>,
52{
53 watcher: &'a mut WatcherMeta<'b, WidgetInternal<P, O>>,
54 getter: G,
55}
56
57impl<O, T, G, P> WidgetInit<T, P> for WidgetInitImpl<'_, '_, O, T, G, P>
58where
59 P: RenderPlatform + ?Sized,
60 G: 'static + Clone + Fn(&mut O) -> &mut T,
61 O: WidgetContent<P>,
62 T: WidgetContent<P>,
63{
64 fn widget_id(&self) -> WidgetId {
65 WidgetId {
66 id: self.watcher.id(),
67 }
68 }
69
70 fn watch<F>(&mut self, func: F)
71 where
72 F: Fn(&mut T, &mut WidgetRect) + 'static,
73 {
74 let getter = self.getter.clone();
75 self.watcher.watch(move |wid_int| {
76 let content = getter(&mut wid_int.content);
77 (func)(content, &mut wid_int.rect);
78 });
79 }
80
81 fn init_child_inline<F, C>(&mut self, getter: F)
82 where
83 C: WidgetContent<P>,
84 F: 'static + Clone + Fn(&mut T) -> &mut C,
85 {
86 let current_getter = self.getter.clone();
87 WidgetContent::init(WidgetInitImpl {
88 watcher: self.watcher,
89 getter: move |base| getter(current_getter(base)),
90 });
91 }
92}
93
94impl<P, T> WatcherInit for WidgetInternal<P, T>
95where
96 P: RenderPlatform + ?Sized,
97 T: WidgetContent<P>,
98{
99 fn init(watcher: &mut WatcherMeta<Self>) {
100 WidgetContent::init(WidgetInitImpl {
101 watcher,
102 getter: |x| x,
103 });
104 }
105}