Skip to main content

ferroui_base/controls/
name_scope_extensions.rs

1use super::{INameScope, NameScope, NameScopeRef};
2use crate::{ObjectType, Ref, StyledElement};
3
4impl dyn INameScope + '_ {
5    /// Finds a named element in the name scope and casts it to class `T`.
6    ///
7    /// Returns `None` if the name is not registered; panics if the element is
8    /// of a different class.
9    pub fn find_as<T: ObjectType>(&self, name: &str) -> Option<Ref<T>> {
10        let result = self.find(name)?;
11        match result.cast::<T>() {
12            Some(typed) => Some(typed),
13            None => panic!(
14                "Expected control '{name}' to be '{}' but it was '{}'.",
15                T::TYPE.name(),
16                result.get_type().name()
17            ),
18        }
19    }
20
21    /// Gets a named element from the name scope and casts it to class `T`.
22    ///
23    /// Panics if the name is not registered or the element is of a different
24    /// class.
25    pub fn get_as<T: ObjectType>(&self, name: &str) -> Ref<T> {
26        match self.find_as::<T>(name) {
27            Some(result) => result,
28            None => panic!("Could not find control '{name}'."),
29        }
30    }
31}
32
33/// Name scope lookups anchored at a styled element.
34pub struct NameScopeExtensions;
35
36impl NameScopeExtensions {
37    /// Finds a named element in the name scope attached to `anchor`.
38    pub fn find<T: ObjectType>(anchor: &StyledElement, name: &str) -> Option<Ref<T>> {
39        NameScope::get_name_scope(anchor)?.find_as::<T>(name)
40    }
41
42    /// Gets a named element from the name scope attached to `anchor`.
43    ///
44    /// Panics if the element has no name scope, the name is not registered or
45    /// the named element is of a different class.
46    pub fn get<T: ObjectType>(anchor: &StyledElement, name: &str) -> Ref<T> {
47        match NameScope::get_name_scope(anchor) {
48            Some(scope) => scope.get_as::<T>(name),
49            None => panic!(
50                "The control doesn't have an associated name scope, probably no registrations has been done yet"
51            ),
52        }
53    }
54
55    /// Finds the name scope of `control` by walking up its logical ancestors.
56    pub fn find_name_scope(control: &StyledElement) -> Option<NameScopeRef> {
57        let mut current = Some(control.to_ref());
58        while let Some(element) = current {
59            if let Some(scope) = NameScope::get_name_scope(&element) {
60                return Some(scope);
61            }
62            current = element.parent();
63        }
64        None
65    }
66}