suzy/widget/
anon.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 crate::dims::{Dim, Rect};
6use crate::platform::{DefaultRenderPlatform, RenderPlatform};
7
8use super::WidgetContent;
9use super::{Widget, WidgetId};
10
11mod private {
12    use super::super::FindWidgetCallback;
13    use super::{WidgetContent, WidgetId};
14    use crate::dims::DynRect;
15    use crate::graphics::DrawContext;
16    use crate::platform::RenderPlatform;
17    use crate::pointer::PointerEvent;
18
19    pub trait Widget<P: RenderPlatform + ?Sized>: DynRect {
20        fn id(&self) -> WidgetId;
21        fn draw(&mut self, ctx: &mut DrawContext<P>);
22        fn pointer_event(&mut self, event: &mut PointerEvent) -> bool;
23        fn pointer_event_self(&mut self, event: &mut PointerEvent) -> bool;
24        fn find_widget(
25            &mut self,
26            id: &WidgetId,
27            func: &mut FindWidgetCallback<P>,
28        );
29        fn as_any(self: Box<Self>) -> Box<dyn std::any::Any>;
30        fn as_any_ref(&self) -> &dyn std::any::Any;
31        fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
32    }
33
34    impl<P, T> Widget<P> for super::Widget<T, P>
35    where
36        P: RenderPlatform + ?Sized,
37        T: WidgetContent<P>,
38    {
39        fn id(&self) -> WidgetId {
40            super::Widget::id(self)
41        }
42
43        fn draw(&mut self, ctx: &mut DrawContext<P>) {
44            super::Widget::draw(self, ctx);
45        }
46
47        fn pointer_event(&mut self, event: &mut PointerEvent) -> bool {
48            super::Widget::pointer_event(self, event)
49        }
50
51        fn pointer_event_self(&mut self, event: &mut PointerEvent) -> bool {
52            super::Widget::pointer_event_self(self, event)
53        }
54
55        fn find_widget(
56            &mut self,
57            id: &WidgetId,
58            func: &mut FindWidgetCallback<P>,
59        ) {
60            super::Widget::find_widget(self, id, func);
61        }
62
63        fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> {
64            self
65        }
66        fn as_any_ref(&self) -> &dyn std::any::Any {
67            self
68        }
69        fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
70            self
71        }
72    }
73}
74
75/// A trait which represents a Widget with an unknown content type.
76///
77/// This can be used for the same patterns trait-objects usually are, e.g.
78/// a heterogeneous collection of Widgets.
79pub trait AnonWidget<P = DefaultRenderPlatform>: private::Widget<P>
80where
81    P: RenderPlatform + ?Sized,
82{
83    /// Get this widget's id.
84    fn id(&self) -> WidgetId {
85        private::Widget::id(self)
86    }
87}
88
89impl<P, T> AnonWidget<P> for Widget<T, P>
90where
91    P: RenderPlatform + ?Sized,
92    T: WidgetContent<P>,
93{
94}
95
96impl<P: RenderPlatform + ?Sized> dyn AnonWidget<P> {
97    /// Returns the widget if its content is of type `T`.
98    pub fn downcast_widget<T>(self: Box<Self>) -> Option<Widget<T, P>>
99    where
100        T: WidgetContent<P>,
101    {
102        self.as_any().downcast().ok().map(|w| *w)
103    }
104
105    /// Returns a reference to the widget if its content is of type `T`.
106    pub fn downcast_widget_ref<T>(&self) -> Option<&Widget<T, P>>
107    where
108        T: WidgetContent<P>,
109    {
110        self.as_any_ref().downcast_ref()
111    }
112
113    /// Returns a mutable reference to the widget if its content is of
114    /// type `T`.
115    pub fn downcast_widget_mut<T>(&mut self) -> Option<&mut Widget<T, P>>
116    where
117        T: WidgetContent<P>,
118    {
119        self.as_any_mut().downcast_mut()
120    }
121}
122
123impl<P: RenderPlatform> Rect for dyn AnonWidget<P> {
124    fn x(&self) -> Dim {
125        (*self).x()
126    }
127    fn y(&self) -> Dim {
128        (*self).y()
129    }
130
131    fn x_mut<F, R>(&mut self, f: F) -> R
132    where
133        F: FnOnce(&mut Dim) -> R,
134    {
135        let mut res = None;
136        (*self).x_mut(Box::new(|dim| {
137            res = Some(f(dim));
138        }));
139        res.expect(
140            "DynRect implementation did not call the closure passed to x_mut",
141        )
142    }
143    fn y_mut<F, R>(&mut self, f: F) -> R
144    where
145        F: FnOnce(&mut Dim) -> R,
146    {
147        let mut res = None;
148        (*self).y_mut(Box::new(|dim| {
149            res = Some(f(dim));
150        }));
151        res.expect(
152            "DynRect implementation did not call the closure passed to y_mut",
153        )
154    }
155
156    fn set_left(&mut self, value: f32) {
157        (*self).set_left(value)
158    }
159    fn set_right(&mut self, value: f32) {
160        (*self).set_right(value)
161    }
162    fn set_bottom(&mut self, value: f32) {
163        (*self).set_bottom(value)
164    }
165    fn set_top(&mut self, value: f32) {
166        (*self).set_top(value)
167    }
168    fn set_center_x(&mut self, value: f32) {
169        (*self).set_center_x(value)
170    }
171    fn set_center_y(&mut self, value: f32) {
172        (*self).set_center_y(value)
173    }
174    fn set_center(&mut self, value: (f32, f32)) {
175        (*self).set_center(value)
176    }
177    fn set_width(&mut self, value: f32) {
178        (*self).set_width(value)
179    }
180    fn set_height(&mut self, value: f32) {
181        (*self).set_height(value)
182    }
183    fn set_pivot(&mut self, value: (f32, f32)) {
184        (*self).set_pivot(value)
185    }
186    fn set_pivot_pos(&mut self, value: (f32, f32)) {
187        (*self).set_pivot_pos(value)
188    }
189    fn shrink_to_aspect(&mut self, aspect: f32) {
190        (*self).shrink_to_aspect(aspect)
191    }
192    fn grow_to_aspect(&mut self, aspect: f32) {
193        (*self).grow_to_aspect(aspect)
194    }
195}