Skip to main content

ferroui_base/
element_ref.rs

1use crate::{ObjectType, Ref, Upcast, WeakRef};
2use std::fmt;
3
4/// A reference to an element that the holder does not own: the value type
5/// of properties such as a placement target, the target of a label or the
6/// element an adorner adorns.
7///
8/// Such a property points sideways or up the tree — often at an ancestor of
9/// the element it is set on — so holding the element strongly would make
10/// the two keep each other alive. An `ElementRef` holds it weakly and
11/// compares by identity. Classes expose these properties with getters that
12/// return `Option<Ref<T>>` and setters that take `impl Into<Nullable<T>>`;
13/// untyped access and bindings convert to and from `Ref<T>` (see
14/// `ValueTypes::register_element_ref`).
15///
16/// When the referenced element is dropped the reference reads as nothing;
17/// no change notification is raised for that.
18pub struct ElementRef<T: ObjectType>(WeakRef<T>);
19
20impl<T: ObjectType> ElementRef<T> {
21    /// Creates a reference to `element`.
22    #[inline]
23    pub fn new<U: ObjectType + Upcast<T>>(element: &Ref<U>) -> Self {
24        ElementRef(element.downgrade().upcast())
25    }
26
27    /// Creates a reference to an element of exactly class `T`.
28    #[inline]
29    pub fn of(element: &Ref<T>) -> Self {
30        ElementRef(element.downgrade())
31    }
32
33    /// The property value for an optional element.
34    #[inline]
35    pub fn from_nullable(element: Option<Ref<T>>) -> Option<Self> {
36        element.map(|element| ElementRef(element.downgrade()))
37    }
38
39    /// The referenced element, if it is still alive.
40    #[inline]
41    pub fn get(&self) -> Option<Ref<T>> {
42        self.0.upgrade()
43    }
44
45    /// The element referenced by a property value.
46    #[inline]
47    pub fn resolve(value: &Option<Self>) -> Option<Ref<T>> {
48        value.as_ref().and_then(ElementRef::get)
49    }
50
51    /// Whether the reference points at `element`.
52    #[inline]
53    pub fn points_to<U: ObjectType>(&self, element: &Ref<U>) -> bool {
54        self.0.points_to(element)
55    }
56}
57
58impl<T: ObjectType> Clone for ElementRef<T> {
59    #[inline]
60    fn clone(&self) -> Self {
61        ElementRef(self.0.clone())
62    }
63}
64
65/// Identity: two references are equal when they point at the same element,
66/// whether or not it is still alive.
67impl<T: ObjectType> PartialEq for ElementRef<T> {
68    #[inline]
69    fn eq(&self, other: &Self) -> bool {
70        self.0.ptr_eq(&other.0)
71    }
72}
73
74impl<T: ObjectType> fmt::Debug for ElementRef<T> {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        match self.get() {
77            Some(_) => write!(f, "ElementRef<{}>", T::TYPE.name()),
78            None => write!(f, "ElementRef<{}>(dropped)", T::TYPE.name()),
79        }
80    }
81}
82
83impl<T: ObjectType + Upcast<U>, U: ObjectType> From<&Ref<T>> for ElementRef<U> {
84    #[inline]
85    fn from(value: &Ref<T>) -> Self {
86        ElementRef::new(value)
87    }
88}