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}