fyrox_ui/node/
mod.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! UI node is a type-agnostic wrapper for any widget type. See [`UiNode`] docs for more info.
22
23use crate::{
24    core::{
25        pool::Handle, reflect::prelude::*, uuid_provider, variable, visitor::prelude::*,
26        ComponentProvider, Downcast, NameProvider,
27    },
28    widget::Widget,
29    Control, UserInterface,
30};
31use fyrox_graph::SceneGraphNode;
32use fyrox_resource::{untyped::UntypedResource, Resource};
33use std::{
34    any::{Any, TypeId},
35    fmt::{Debug, Formatter},
36    ops::{Deref, DerefMut},
37};
38
39pub mod constructor;
40pub mod container;
41
42/// UI node is a type-agnostic wrapper for any widget type. Internally, it is just a trait object
43/// that provides common widget interface. Its main use is to reduce code bloat (no need to type
44/// `Box<dyn Control>` everywhere, just `UiNode`) and to provide some useful methods such as type
45/// casting, component querying, etc. You could also be interested in [`Control`] docs, since it
46/// contains all the interesting stuff and detailed description for each method.
47pub struct UiNode(pub Box<dyn Control>);
48
49impl<T: Control> From<T> for UiNode {
50    fn from(value: T) -> Self {
51        Self(Box::new(value))
52    }
53}
54
55uuid_provider!(UiNode = "d9b45ecc-91b0-40ea-a92a-4a7dee4667c9");
56
57impl ComponentProvider for UiNode {
58    #[inline]
59    fn query_component_ref(&self, type_id: TypeId) -> Option<&dyn Any> {
60        self.0.query_component_ref(type_id)
61    }
62
63    #[inline]
64    fn query_component_mut(&mut self, type_id: TypeId) -> Option<&mut dyn Any> {
65        self.0.query_component_mut(type_id)
66    }
67}
68
69impl Clone for UiNode {
70    #[inline]
71    fn clone(&self) -> Self {
72        Self(self.0.clone_boxed())
73    }
74}
75
76impl SceneGraphNode for UiNode {
77    type Base = Widget;
78    type SceneGraph = UserInterface;
79    type ResourceData = UserInterface;
80
81    fn base(&self) -> &Self::Base {
82        self.0.deref()
83    }
84
85    fn set_base(&mut self, base: Self::Base) {
86        ***self = base;
87    }
88
89    fn is_resource_instance_root(&self) -> bool {
90        self.is_resource_instance_root
91    }
92
93    fn original_handle_in_resource(&self) -> Handle<Self> {
94        self.original_handle_in_resource
95    }
96
97    fn set_original_handle_in_resource(&mut self, handle: Handle<Self>) {
98        self.original_handle_in_resource = handle;
99    }
100
101    fn resource(&self) -> Option<Resource<Self::ResourceData>> {
102        self.resource.clone()
103    }
104
105    fn self_handle(&self) -> Handle<Self> {
106        self.handle
107    }
108
109    fn parent(&self) -> Handle<Self> {
110        self.parent
111    }
112
113    fn children(&self) -> &[Handle<Self>] {
114        &self.children
115    }
116
117    fn children_mut(&mut self) -> &mut [Handle<Self>] {
118        &mut self.children
119    }
120}
121
122impl NameProvider for UiNode {
123    fn name(&self) -> &str {
124        &self.0.name
125    }
126}
127
128impl Debug for UiNode {
129    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
130        self.0.fmt(f)
131    }
132}
133
134impl Deref for UiNode {
135    type Target = dyn Control;
136
137    fn deref(&self) -> &Self::Target {
138        self.0.deref()
139    }
140}
141
142impl DerefMut for UiNode {
143    fn deref_mut(&mut self) -> &mut Self::Target {
144        self.0.deref_mut()
145    }
146}
147
148impl UiNode {
149    /// Creates a new UI node from any object that implements [`Control`] trait. Its main use
150    /// is to finish widget creation like so:
151    ///
152    /// ```rust
153    /// # use fyrox_ui::{
154    /// #     core::pool::Handle,
155    /// #     define_widget_deref,
156    /// #     core::{visitor::prelude::*, reflect::prelude::*, type_traits::prelude::*,},
157    /// #     message::UiMessage,
158    /// #     widget::{Widget, WidgetBuilder},
159    /// #     BuildContext, Control, UiNode, UserInterface,
160    /// # };
161    /// # use std::{
162    /// #     any::{Any, TypeId},
163    /// #     ops::{Deref, DerefMut},
164    /// # };
165    /// # use fyrox_core::uuid_provider;
166    /// #
167    /// #[derive(Clone, Visit, Reflect, Debug, ComponentProvider)]
168    /// struct MyWidget {
169    ///     widget: Widget,
170    /// }
171    /// #
172    /// # define_widget_deref!(MyWidget);
173    /// #
174    /// # uuid_provider!(MyWidget = "a93ec1b5-e7c8-4919-ac19-687d8c99f6bd");
175    /// #
176    /// # impl Control for MyWidget {
177    /// #     fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
178    /// #         todo!()
179    /// #     }
180    /// # }
181    ///
182    /// struct MyWidgetBuilder {
183    ///     widget_builder: WidgetBuilder,
184    /// }
185    ///
186    /// impl MyWidgetBuilder {
187    ///     pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
188    ///         let my_widget = MyWidget {
189    ///             widget: self.widget_builder.build(ctx),
190    ///         };
191    ///
192    ///         // Wrap your widget in the type-agnostic wrapper so it can be placed in the UI.
193    ///         let node = UiNode::new(my_widget);
194    ///
195    ///         ctx.add_node(node)
196    ///     }
197    /// }
198    /// ```
199    pub fn new<T>(widget: T) -> Self
200    where
201        T: Control,
202    {
203        Self(Box::new(widget))
204    }
205
206    /// Tries to perform **direct** downcasting to a particular widget type. It is just a simple wrapper
207    /// for `Any::downcast_ref`.
208    pub fn cast<T>(&self) -> Option<&T>
209    where
210        T: Control,
211    {
212        Downcast::as_any(&*self.0).downcast_ref::<T>()
213    }
214
215    /// Tries to perform **direct** downcasting to a particular widget type. It is just a simple wrapper
216    /// for `Any::downcast_mut`.
217    pub fn cast_mut<T>(&mut self) -> Option<&mut T>
218    where
219        T: Control,
220    {
221        Downcast::as_any_mut(&mut *self.0).downcast_mut::<T>()
222    }
223
224    /// Tries to fetch a component of the given type `T`. At very basis it mimics [`Self::cast`] behaviour, but
225    /// also allows you to fetch components of other types as well. For example, your widget may be built on
226    /// top of existing one (via composition) and you have it as a field inside your widget. In this case, you
227    /// can fetch it by using this method with the appropriate type. See docs for [`fyrox_core::type_traits::ComponentProvider::query_component_ref`]
228    /// for more info.
229    pub fn query_component<T>(&self) -> Option<&T>
230    where
231        T: 'static,
232    {
233        self.0
234            .query_component_ref(TypeId::of::<T>())
235            .and_then(|c| c.downcast_ref::<T>())
236    }
237
238    /// This method checks if the widget has a component of the given type `T`. Internally, it queries the component
239    /// of the given type and checks if it exists.
240    pub fn has_component<T>(&self) -> bool
241    where
242        T: 'static,
243    {
244        self.query_component::<T>().is_some()
245    }
246
247    pub(crate) fn set_inheritance_data(
248        &mut self,
249        original_handle: Handle<UiNode>,
250        model: Resource<UserInterface>,
251    ) {
252        // Notify instantiated node about resource it was created from.
253        self.resource = Some(model.clone());
254
255        // Reset resource instance root flag, this is needed because a node after instantiation cannot
256        // be a root anymore.
257        self.is_resource_instance_root = false;
258
259        // Reset inheritable properties, so property inheritance system will take properties
260        // from parent objects on resolve stage.
261        self.as_reflect_mut(&mut |reflect| {
262            variable::mark_inheritable_properties_non_modified(
263                reflect,
264                &[TypeId::of::<UntypedResource>()],
265            )
266        });
267
268        // Fill original handles to instances.
269        self.original_handle_in_resource = original_handle;
270    }
271}
272
273impl Visit for UiNode {
274    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
275        self.0.visit(name, visitor)
276    }
277}
278
279impl Reflect for UiNode {
280    fn source_path() -> &'static str {
281        file!()
282    }
283
284    fn type_name(&self) -> &'static str {
285        Reflect::type_name(self.0.deref())
286    }
287
288    fn doc(&self) -> &'static str {
289        self.0.deref().doc()
290    }
291
292    fn assembly_name(&self) -> &'static str {
293        self.0.deref().assembly_name()
294    }
295
296    fn type_assembly_name() -> &'static str {
297        env!("CARGO_PKG_NAME")
298    }
299
300    fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
301        self.0.deref().fields_info(func)
302    }
303
304    fn into_any(self: Box<Self>) -> Box<dyn Any> {
305        Reflect::into_any(self.0)
306    }
307
308    fn as_any(&self, func: &mut dyn FnMut(&dyn Any)) {
309        Reflect::as_any(self.0.deref(), func)
310    }
311
312    fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any)) {
313        Reflect::as_any_mut(self.0.deref_mut(), func)
314    }
315
316    fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
317        self.0.deref().as_reflect(func)
318    }
319
320    fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
321        self.0.deref_mut().as_reflect_mut(func)
322    }
323
324    fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
325        self.0.deref_mut().set(value)
326    }
327
328    fn set_field(
329        &mut self,
330        field: &str,
331        value: Box<dyn Reflect>,
332        func: &mut dyn FnMut(Result<Box<dyn Reflect>, Box<dyn Reflect>>),
333    ) {
334        self.0.deref_mut().set_field(field, value, func)
335    }
336
337    fn fields(&self, func: &mut dyn FnMut(&[&dyn Reflect])) {
338        self.0.deref().fields(func)
339    }
340
341    fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [&mut dyn Reflect])) {
342        self.0.deref_mut().fields_mut(func)
343    }
344
345    fn field(&self, name: &str, func: &mut dyn FnMut(Option<&dyn Reflect>)) {
346        self.0.deref().field(name, func)
347    }
348
349    fn field_mut(&mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>)) {
350        self.0.deref_mut().field_mut(name, func)
351    }
352}