Skip to main content

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