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