suzy/widget/
init.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use drying_paint::{WatcherInit, WatcherMeta};
6
7use crate::platform::{DefaultRenderPlatform, RenderPlatform};
8
9use super::{layout, WidgetContent, WidgetId, WidgetInternal, WidgetRect};
10
11/// Instances of this trait are provided to
12/// [`WidgetContent::init`](trait.WidgetContent.html#tymethod.init).
13///
14/// It's primary use is to provide the `watch` method, which custom widgets
15/// use to submit watch closures.
16pub trait WidgetInit<T, P = DefaultRenderPlatform>
17where
18    P: RenderPlatform + ?Sized,
19    T: WidgetContent<P> + ?Sized,
20{
21    /// Get a value representing a unique id for the widget this WidgetInit
22    /// was created for. This value may outlive the widget, and will never
23    /// compare equal to a value returned by the id method of a Widget other
24    /// than this one.
25    fn widget_id(&self) -> WidgetId;
26
27    /// Register a watch function associated with this widget.  See the
28    /// [watch](../watch/index.html) module for more information.
29    fn watch<F>(&mut self, func: F)
30    where
31        F: Fn(&mut T, &mut WidgetRect) + 'static;
32
33    /// Create a layout group which a provides a shorthand for organizing
34    /// widgets in common configurations.
35    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}