1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
use crate::{
    core::{
        algebra::Vector2, pool::Handle, reflect::Reflect, scope_profile, uuid::Uuid, visitor::Visit,
    },
    draw::DrawingContext,
    message::{OsEvent, UiMessage},
    widget::Widget,
    NodeHandleMapping, UiNode, UserInterface,
};
use fyrox_core::{ComponentProvider, TypeUuidProvider};
use std::{
    any::Any,
    ops::{Deref, DerefMut},
    sync::mpsc::Sender,
};

/// Base trait for all UI widgets. It has auto-impl and you don't need to implement it manually. Your widget
/// must implement [`Clone`] and [`Control`] traits for impl to be generated for you, also your widget must
/// not contain any references (due to `'static` lifetime requirement).
pub trait BaseControl: Send + 'static {
    /// Returns `self` as `&dyn Any`.
    fn as_any(&self) -> &dyn Any;

    /// Returns `self` as `&mut dyn Any`.
    fn as_any_mut(&mut self) -> &mut dyn Any;

    /// Returns the exact copy of the widget in "type-erased" form.
    fn clone_boxed(&self) -> Box<dyn Control>;

    /// Returns type name of the widget.
    fn type_name(&self) -> &'static str;

    fn id(&self) -> Uuid;
}

impl<T> BaseControl for T
where
    T: Any + Clone + 'static + Control + TypeUuidProvider,
{
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }

    fn clone_boxed(&self) -> Box<dyn Control> {
        Box::new(self.clone())
    }

    fn type_name(&self) -> &'static str {
        std::any::type_name::<T>()
    }

    fn id(&self) -> Uuid {
        Self::type_uuid()
    }
}

/// Trait for all UI controls in library.
pub trait Control:
    BaseControl + Deref<Target = Widget> + DerefMut + Reflect + Visit + ComponentProvider
{
    /// This method will be called right after the widget was cloned. It is used remap handles in the widgets
    /// to their respective copies from the copied hierarchy.
    fn resolve(&mut self, #[allow(unused_variables)] node_map: &NodeHandleMapping) {}

    /// This method will be called before the widget is destroyed (dropped). At the moment, when this
    /// method is called, the widget is still in the widget graph and can be accessed via handles. It
    /// is guaranteed to be called once, and only if the widget is deleted via [`crate::widget::WidgetMessage::remove`].
    fn on_remove(&self, #[allow(unused_variables)] sender: &Sender<UiMessage>) {}

    /// This method is used to override measurement step of the layout system. It should return desired size of
    /// the widget (how many space it wants to occupy).
    ///
    /// ## Example
    ///
    /// ```rust
    /// # use fyrox_ui::{
    /// #     core::algebra::Vector2, define_widget_deref, message::UiMessage, Control, UserInterface,
    /// #     core::{visitor::prelude::*, reflect::prelude::*, type_traits::prelude::*,},
    /// #     widget::Widget,
    /// # };
    /// # use std::{
    /// #     any::{Any, TypeId},
    /// #     ops::{Deref, DerefMut},
    /// # };
    /// # use fyrox_core::uuid_provider;
    /// #
    /// #[derive(Clone, Visit, Reflect, Debug, ComponentProvider)]
    /// struct MyWidget {
    ///     widget: Widget,
    /// }
    /// #
    /// # define_widget_deref!(MyWidget);
    /// # uuid_provider!(MyWidget = "a93ec1b5-e7c8-4919-ac19-687d8c99f6bd");
    /// impl Control for MyWidget {
    ///     fn measure_override(
    ///         &self,
    ///         ui: &UserInterface,
    ///         available_size: Vector2<f32>,
    ///     ) -> Vector2<f32> {
    ///         let mut size: Vector2<f32> = Vector2::default();
    ///
    ///         // Measure children nodes and find the largest size of them.
    ///         for &child in self.children.iter() {
    ///             // Recursively measure children nodes. Measured size will be put in `desired_size`
    ///             // of the widget.
    ///             ui.measure_node(child, available_size);
    ///
    ///             // Find max size across all the children widgets.
    ///             size = size.sup(&ui.node(child).desired_size());
    ///         }
    ///
    ///         size
    ///     }
    ///     #
    ///     # fn handle_routed_message(&mut self, _ui: &mut UserInterface, _message: &mut UiMessage) {
    ///     #     todo!()
    ///     # }
    /// }
    /// ```
    ///
    /// The goal of this method is to supply the UI system with the size requirements of all descendants
    /// of the widget. In this example we measure all descendants recursively and finding the max desired
    /// size of across all the children widgets. This effectively does the following: size of this widget
    /// will be the max size of children widgets. Some widgets (like [`crate::canvas::Canvas`]), can provide infinite
    /// constraints to children nodes, to fetch unconstrained desired size.
    ///
    /// It is recommended to check implementation of this method of built-in widgets (such as [`crate::canvas::Canvas`],
    /// [`crate::stack_panel::StackPanel`], [`crate::wrap_panel::WrapPanel`], [`crate::grid::Grid`]). It should help you to
    /// understand measurement step better.
    fn measure_override(&self, ui: &UserInterface, available_size: Vector2<f32>) -> Vector2<f32> {
        scope_profile!();

        self.deref().measure_override(ui, available_size)
    }

    /// This method is used to override arrangement step of the layout system. Arrangement step is used to
    /// commit the final location and size of the widget in local coordinates. It is done after the measurement
    /// step; when all desired sizes of every widget is known. This fact allows you to calculate final location
    /// and size of every child widget, based in their desired size. Usually this method is used in some panel
    /// widgets, that takes their children and arranges them in some specific way. For example, it may stack
    /// widgets on top of each other, or put them in a line with wrapping, etc.
    ///
    /// ## Example
    ///
    /// ```rust
    /// # use fyrox_ui::{
    /// #     core::{algebra::Vector2, math::Rect},
    /// #     core::{visitor::prelude::*, reflect::prelude::*, type_traits::prelude::*,},
    /// #     define_widget_deref,
    /// #     message::UiMessage,
    /// #     Control, UserInterface, widget::Widget,
    /// # };
    /// # use std::{
    /// #     any::{Any, TypeId},
    /// #     ops::{Deref, DerefMut},
    /// # };
    /// # use fyrox_core::uuid_provider;
    /// #
    /// #[derive(Clone, Visit, Reflect, Debug, ComponentProvider)]
    /// struct MyWidget {
    ///     widget: Widget,
    /// }
    /// #
    /// # define_widget_deref!(MyWidget);
    /// # uuid_provider!(MyWidget = "a93ec1b5-e7c8-4919-ac19-687d8c99f6bd");
    /// impl Control for MyWidget {
    ///     fn arrange_override(&self, ui: &UserInterface, final_size: Vector2<f32>) -> Vector2<f32> {
    ///         let final_rect = Rect::new(0.0, 0.0, final_size.x, final_size.y);
    ///
    ///         // Commit final locations and size for each child node.
    ///         for &child in self.children.iter() {
    ///             ui.arrange_node(child, &final_rect);
    ///         }
    ///
    ///         final_size
    ///     }
    ///     #
    ///     # fn handle_routed_message(&mut self, _ui: &mut UserInterface, _message: &mut UiMessage) {
    ///     #     todo!()
    ///     # }
    /// }
    /// ```
    ///
    /// This example arranges all the children widgets using the given `final_size`, that comes from the
    /// parent widget, so all children will have exactly the same size as the parent and be located at (0;0)
    /// point in local coordinates.
    ///
    /// It is recommended to check implementation of this method of built-in widgets (such as [`crate::canvas::Canvas`],
    /// [`crate::stack_panel::StackPanel`], [`crate::wrap_panel::WrapPanel`], [`crate::grid::Grid`]). It should help you to
    /// understand arrangement step better.
    fn arrange_override(&self, ui: &UserInterface, final_size: Vector2<f32>) -> Vector2<f32> {
        scope_profile!();

        self.deref().arrange_override(ui, final_size)
    }

    /// This method is used to emit drawing commands that will be used later to draw your widget on screen.
    /// Keep in mind that any emitted geometry (quads, lines, text, etc), will be used to perform hit test.
    /// In other words, all the emitted geometry will make your widget "clickable". Widgets with no geometry
    /// emitted by this method are mouse input transparent.
    ///
    /// ## Example
    ///
    /// ```rust
    /// # use fyrox_ui::{
    /// #     define_widget_deref,
    /// #     draw::{CommandTexture, Draw, DrawingContext},
    /// #     core::{visitor::prelude::*, reflect::prelude::*, type_traits::prelude::*,},
    /// #     message::UiMessage,
    /// #     Control, UserInterface, widget::Widget,
    /// # };
    /// # use std::{
    /// #     any::{Any, TypeId},
    /// #     ops::{Deref, DerefMut},
    /// # };
    /// # use fyrox_core::uuid_provider;
    /// #
    /// #[derive(Clone, Visit, Reflect, Debug, ComponentProvider)]
    /// struct MyWidget {
    ///     widget: Widget,
    /// }
    /// #
    /// # define_widget_deref!(MyWidget);
    /// # uuid_provider!(MyWidget = "a93ec1b5-e7c8-4919-ac19-687d8c99f6bd");
    /// impl Control for MyWidget {
    /// fn draw(&self, drawing_context: &mut DrawingContext) {
    ///     let bounds = self.widget.bounding_rect();
    ///
    ///     // Push a rect.
    ///     drawing_context.push_rect_filled(&bounds, None);
    ///
    ///     // Commit the geometry, it is mandatory step, otherwise your widget's geometry
    ///     // will be "attached" to some other widget that will call `commit`.
    ///     drawing_context.commit(
    ///         self.clip_bounds(),
    ///         self.widget.background(),
    ///         CommandTexture::None,
    ///         None,
    ///     );
    /// }
    ///     #
    ///     # fn handle_routed_message(&mut self, _ui: &mut UserInterface, _message: &mut UiMessage) {
    ///     #     todo!()
    ///     # }
    /// }
    /// ```
    ///
    /// This example shows how to draw a simple quad using the background brush of the widget. See docs
    /// for [`DrawingContext`] for more info.
    fn draw(&self, #[allow(unused_variables)] drawing_context: &mut DrawingContext) {}

    /// This method is called every frame and can be used to update internal variables of the widget, that
    /// can be used to animated your widget. Its main difference from other methods, is that it does **not**
    /// provide access to any other widget in the UI. Instead, you can only send messages to widgets to
    /// force them to change their state.
    fn update(
        &mut self,
        #[allow(unused_variables)] dt: f32,
        #[allow(unused_variables)] sender: &Sender<UiMessage>,
        #[allow(unused_variables)] screen_size: Vector2<f32>,
    ) {
    }

    /// Performs event-specific actions. Must call widget.handle_message()!
    ///
    /// # Notes
    ///
    /// Do *not* try to borrow node by `self_handle` in UI - at this moment node has been moved
    /// out of pool and attempt of borrowing will cause panic! `self_handle` should be used only
    /// to check if event came from/for this node or to capture input on node.
    fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage);

    /// Used to react to a message (by producing another message) that was posted outside of current
    /// hierarchy. In other words this method is used when you need to "peek" a message before it'll
    /// be passed into bubbling router. Most common use case is to catch messages from popups: popup
    /// in 99.9% cases is a child of root canvas and it **won't** receive a message from a its *logical*
    /// parent during bubbling message routing. For example `preview_message` used in a dropdown list:
    /// dropdown list has two separate parts - a field with selected value and a popup for all possible
    /// options. Visual parent of the popup in this case is the root canvas, but logical parent is the
    /// dropdown list. Because of this fact, the field won't receive any messages from popup, to solve
    /// this we use `preview_message`. This method is much more restrictive - it does not allow you to
    /// modify a node and ui, you can either *request* changes by sending a message or use internal
    /// mutability (`Cell`, `RefCell`, etc).
    ///
    /// ## Important notes
    ///
    /// Due to performance reasons, you **must** set `.with_preview_messages(true)` in widget builder to
    /// force library to call `preview_message`!
    ///
    /// The order of execution of this method is undefined! There is no guarantee that it will be called
    /// hierarchically as widgets connected.
    fn preview_message(
        &self,
        #[allow(unused_variables)] ui: &UserInterface,
        #[allow(unused_variables)] message: &mut UiMessage,
    ) {
        // This method is optional.
    }

    /// Provides a way to respond to OS specific events. Can be useful to detect if a key or mouse
    /// button was pressed. This method significantly differs from `handle_message` because os events
    /// are not dispatched - they'll be passed to this method in any case.
    ///
    /// ## Important notes
    ///
    /// Due to performance reasons, you **must** set `.with_handle_os_messages(true)` in widget builder to
    /// force library to call `handle_os_event`!
    fn handle_os_event(
        &mut self,
        #[allow(unused_variables)] self_handle: Handle<UiNode>,
        #[allow(unused_variables)] ui: &mut UserInterface,
        #[allow(unused_variables)] event: &OsEvent,
    ) {
    }
}