Skip to main content

ferroui_base/data/
relative_source.rs

1use crate::TypeInfo;
2use std::cell::Cell;
3use std::rc::Rc;
4
5/// Defines the mode of a [`RelativeSource`].
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7pub enum RelativeSourceMode {
8    /// The binding will be to the element's data context.
9    DataContext,
10    /// The binding will be to the element's templated parent.
11    TemplatedParent,
12    /// The binding will be to the element itself.
13    SelfMode,
14    /// The binding will be to an ancestor of the element in the visual or
15    /// logical tree.
16    FindAncestor,
17}
18
19/// The type of tree via which to track an element.
20#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
21pub enum TreeType {
22    /// The visual tree.
23    Visual,
24    /// The logical tree.
25    Logical,
26}
27
28/// Describes the location of a binding source, relative to the binding
29/// target.
30///
31/// A relative source is a mutable reference object: it is created with
32/// [`RelativeSource::empty`] or [`RelativeSource::new`], configured property
33/// by property (or with the chaining `with_*` forms) and shared as
34/// `Rc<RelativeSource>`. Handles compare by identity. A binding reads it
35/// when it is instantiated on a target.
36#[derive(Debug)]
37pub struct RelativeSource {
38    ancestor_level: Cell<i32>,
39    ancestor_type: Cell<Option<&'static TypeInfo>>,
40    mode: Cell<RelativeSourceMode>,
41    tree: Cell<TreeType>,
42}
43
44impl Default for RelativeSource {
45    /// A relative source in find-ancestor mode.
46    fn default() -> Self {
47        Self {
48            ancestor_level: Cell::new(1),
49            ancestor_type: Cell::new(None),
50            mode: Cell::new(RelativeSourceMode::FindAncestor),
51            tree: Cell::new(TreeType::Visual),
52        }
53    }
54}
55
56/// Compares by identity (reference equality), as the reference type this
57/// mirrors.
58impl PartialEq for RelativeSource {
59    #[inline]
60    fn eq(&self, other: &Self) -> bool {
61        std::ptr::eq(self, other)
62    }
63}
64
65impl RelativeSource {
66    /// Creates a relative source in find-ancestor mode (the parameterless
67    /// constructor).
68    pub fn empty() -> Rc<Self> {
69        Rc::new(Self::default())
70    }
71
72    /// Creates a relative source with the given mode.
73    pub fn new(mode: RelativeSourceMode) -> Rc<Self> {
74        Self::empty().with_mode(mode)
75    }
76
77    /// The level of ancestor to look for when in find-ancestor mode. Use the
78    /// default value of 1 to look for the first ancestor of the specified
79    /// type.
80    pub fn ancestor_level(&self) -> i32 {
81        self.ancestor_level.get()
82    }
83
84    /// Sets the ancestor level. Panics if it is not positive.
85    pub fn set_ancestor_level(&self, value: i32) {
86        if value <= 0 {
87            panic!("AncestorLevel may not be set to less than 1.");
88        }
89        self.ancestor_level.set(value);
90    }
91
92    /// The chaining form of [`set_ancestor_level`](Self::set_ancestor_level).
93    pub fn with_ancestor_level(self: Rc<Self>, value: i32) -> Rc<Self> {
94        self.set_ancestor_level(value);
95        self
96    }
97
98    /// The type of ancestor to look for when in
99    /// [`RelativeSourceMode::FindAncestor`] mode.
100    pub fn ancestor_type(&self) -> Option<&'static TypeInfo> {
101        self.ancestor_type.get()
102    }
103
104    pub fn set_ancestor_type(&self, value: Option<&'static TypeInfo>) {
105        self.ancestor_type.set(value)
106    }
107
108    /// The chaining form of [`set_ancestor_type`](Self::set_ancestor_type).
109    pub fn with_ancestor_type(self: Rc<Self>, value: Option<&'static TypeInfo>) -> Rc<Self> {
110        self.set_ancestor_type(value);
111        self
112    }
113
114    /// A value that describes the type of relative source lookup.
115    pub fn mode(&self) -> RelativeSourceMode {
116        self.mode.get()
117    }
118
119    pub fn set_mode(&self, value: RelativeSourceMode) {
120        self.mode.set(value)
121    }
122
123    /// The chaining form of [`set_mode`](Self::set_mode).
124    pub fn with_mode(self: Rc<Self>, value: RelativeSourceMode) -> Rc<Self> {
125        self.set_mode(value);
126        self
127    }
128
129    /// The tree in which ancestors are looked up.
130    pub fn tree(&self) -> TreeType {
131        self.tree.get()
132    }
133
134    pub fn set_tree(&self, value: TreeType) {
135        self.tree.set(value)
136    }
137
138    /// The chaining form of [`set_tree`](Self::set_tree).
139    pub fn with_tree(self: Rc<Self>, value: TreeType) -> Rc<Self> {
140        self.set_tree(value);
141        self
142    }
143}