Skip to main content

ferroui_base/controls/
i_resource_host.rs

1use super::{IResourceNode, ResourcesChangedEventArgs};
2use crate::reactive::IDisposable;
3use crate::styling::{IStyleHost, IThemeVariantHost};
4use crate::{ObjectType, Ref, StyledElement, Upcast, WeakRef};
5use std::ops::Deref;
6use std::rc::{Rc, Weak};
7
8/// Represents an element which hosts resources.
9///
10/// Implemented by [`StyledElement`] and by the application object, the root
11/// of the styling-parent chain.
12pub trait IResourceHost: IResourceNode {
13    /// Raised when the resources change on the element or an ancestor of the
14    /// element. Disposing the returned handle unsubscribes.
15    fn resources_changed(&self, handler: Rc<dyn Fn(&ResourcesChangedEventArgs)>) -> Rc<dyn IDisposable>;
16
17    /// Notifies the resource host that one or more of its hosted resources
18    /// has changed.
19    ///
20    /// This method will be called automatically by the framework, you should
21    /// not need to call this method yourself. It is called when the resources
22    /// hosted by this element have changed, and is usually called by a
23    /// resource dictionary or style hosted by the element in response to a
24    /// resource being added or removed.
25    fn notify_hosted_resources_changed(&self, e: ResourcesChangedEventArgs);
26
27    /// The host as a style host, if it is one.
28    fn as_style_host(&self) -> Option<&dyn IStyleHost> {
29        None
30    }
31
32    /// The host as a theme variant host, if it is one.
33    fn as_theme_variant_host(&self) -> Option<&dyn IThemeVariantHost> {
34        None
35    }
36}
37
38/// A strong reference to a resource host: a styled element, or another host
39/// such as the application object.
40#[derive(Clone)]
41pub enum ResourceHostRef {
42    Element(Ref<StyledElement>),
43    Other(Rc<dyn IResourceHost>),
44}
45
46impl ResourceHostRef {
47    /// Creates a weak reference to the host.
48    pub fn downgrade(&self) -> WeakResourceHost {
49        match self {
50            ResourceHostRef::Element(e) => WeakResourceHost::Element(e.downgrade()),
51            ResourceHostRef::Other(h) => WeakResourceHost::Other(Rc::downgrade(h)),
52        }
53    }
54
55    /// The host as a styled element, if it is one.
56    pub fn as_element(&self) -> Option<&Ref<StyledElement>> {
57        match self {
58            ResourceHostRef::Element(e) => Some(e),
59            ResourceHostRef::Other(_) => None,
60        }
61    }
62}
63
64impl Deref for ResourceHostRef {
65    type Target = dyn IResourceHost;
66
67    #[inline]
68    fn deref(&self) -> &(dyn IResourceHost + 'static) {
69        match self {
70            ResourceHostRef::Element(e) => {
71                let element: &StyledElement = e;
72                element
73            }
74            ResourceHostRef::Other(h) => &**h,
75        }
76    }
77}
78
79impl PartialEq for ResourceHostRef {
80    fn eq(&self, other: &Self) -> bool {
81        match (self, other) {
82            (ResourceHostRef::Element(a), ResourceHostRef::Element(b)) => a.ptr_eq(b),
83            (ResourceHostRef::Other(a), ResourceHostRef::Other(b)) => std::ptr::addr_eq(Rc::as_ptr(a), Rc::as_ptr(b)),
84            _ => false,
85        }
86    }
87}
88
89impl<T: ObjectType + Upcast<StyledElement>> From<Ref<T>> for ResourceHostRef {
90    fn from(value: Ref<T>) -> Self {
91        ResourceHostRef::Element(value.upcast())
92    }
93}
94
95impl<T: ObjectType + Upcast<StyledElement>> From<&Ref<T>> for ResourceHostRef {
96    fn from(value: &Ref<T>) -> Self {
97        ResourceHostRef::Element(value.clone().upcast())
98    }
99}
100
101impl From<Rc<dyn IResourceHost>> for ResourceHostRef {
102    fn from(value: Rc<dyn IResourceHost>) -> Self {
103        ResourceHostRef::Other(value)
104    }
105}
106
107impl<T: IResourceHost + 'static> From<Rc<T>> for ResourceHostRef {
108    fn from(value: Rc<T>) -> Self {
109        ResourceHostRef::Other(value)
110    }
111}
112
113/// A weak reference to a resource host.
114#[derive(Clone)]
115pub enum WeakResourceHost {
116    Element(WeakRef<StyledElement>),
117    Other(Weak<dyn IResourceHost>),
118}
119
120impl WeakResourceHost {
121    /// Returns a strong reference if the host is still alive.
122    pub fn upgrade(&self) -> Option<ResourceHostRef> {
123        match self {
124            WeakResourceHost::Element(e) => e.upgrade().map(ResourceHostRef::Element),
125            WeakResourceHost::Other(h) => h.upgrade().map(ResourceHostRef::Other),
126        }
127    }
128}
129
130/// Handles compare by identity (reference equality): two handles are equal
131/// when they refer to the same host.
132impl PartialEq for dyn IResourceHost {
133    #[inline]
134    fn eq(&self, other: &Self) -> bool {
135        self.reference_id() == other.reference_id()
136    }
137}