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
//! UI node is a type-agnostic wrapper for any widget type. See [`UiNode`] docs for more info.
use crate::Control;
use std::{
any::TypeId,
ops::{Deref, DerefMut},
};
/// UI node is a type-agnostic wrapper for any widget type. Internally, it is just a trait object
/// that provides common widget interface. Its main use is to reduce code bloat (no need to type
/// `Box<dyn Control>` everywhere, just `UiNode`) and to provide some useful methods such as type
/// casting, component querying, etc. You could also be interested in [`Control`] docs, since it
/// contains all the interesting stuff and detailed description for each method.
pub struct UiNode(pub Box<dyn Control>);
impl Deref for UiNode {
type Target = dyn Control;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl DerefMut for UiNode {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.deref_mut()
}
}
impl UiNode {
/// Creates a new UI node from any object that implements [`Control`] trait. Its main use
/// is to finish widget creation like so:
///
/// ```rust
/// # use fyrox_ui::{
/// # core::pool::Handle,
/// # define_widget_deref,
/// # message::UiMessage,
/// # widget::{Widget, WidgetBuilder},
/// # BuildContext, Control, UiNode, UserInterface,
/// # };
/// # use std::{
/// # any::{Any, TypeId},
/// # ops::{Deref, DerefMut},
/// # };
/// #
/// #[derive(Clone)]
/// struct MyWidget {
/// widget: Widget,
/// }
/// #
/// # define_widget_deref!(MyWidget);
/// #
/// # impl Control for MyWidget {
/// # fn query_component(&self, type_id: TypeId) -> Option<&dyn Any> {
/// # todo!()
/// # }
/// #
/// # fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
/// # todo!()
/// # }
/// # }
///
/// struct MyWidgetBuilder {
/// widget_builder: WidgetBuilder,
/// }
///
/// impl MyWidgetBuilder {
/// pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
/// let my_widget = MyWidget {
/// widget: self.widget_builder.build(),
/// };
///
/// // Wrap your widget in the type-agnostic wrapper so it can be placed in the UI.
/// let node = UiNode::new(my_widget);
///
/// ctx.add_node(node)
/// }
/// }
/// ```
pub fn new<T>(widget: T) -> Self
where
T: Control,
{
Self(Box::new(widget))
}
/// Tries to perform **direct** downcasting to a particular widget type. It is just a simple wrapper
/// for `Any::downcast_ref`.
pub fn cast<T>(&self) -> Option<&T>
where
T: Control,
{
self.0.as_any().downcast_ref::<T>()
}
/// Tries to perform **direct** downcasting to a particular widget type. It is just a simple wrapper
/// for `Any::downcast_mut`.
pub fn cast_mut<T>(&mut self) -> Option<&mut T>
where
T: Control,
{
self.0.as_any_mut().downcast_mut::<T>()
}
/// Tries to fetch a component of the given type `T`. At very basis it mimics [`Self::cast`] behaviour, but
/// also allows you to fetch components of other types as well. For example, your widget may be built on
/// top of existing one (via composition) and you have it as a field inside your widget. In this case, you
/// can fetch it by using this method with the appropriate type. See docs for [`Control::query_component`]
/// for more info.
pub fn query_component<T>(&self) -> Option<&T>
where
T: 'static,
{
self.0
.query_component(TypeId::of::<T>())
.and_then(|c| c.downcast_ref::<T>())
}
/// This method checks if the widget has a component of the given type `T`. Internally, it queries the component
/// of the given type and checks if it exists.
pub fn has_component<T>(&self) -> bool
where
T: 'static,
{
self.query_component::<T>().is_some()
}
}