Skip to main content

ferroui_controls/templates/
data_template_extensions.rs

1use super::IDataTemplate;
2use crate::{Control, IGlobalDataTemplates};
3use ferroui_base::{BoxedValue, FerroLocator, LocatorExtensions, Ref, StyledElement};
4use std::rc::Rc;
5
6impl Control {
7    /// Find a data template that matches a piece of data.
8    ///
9    /// `primary` is an optional primary template that can display the data.
10    /// Returns the data template or `None` if no matching data template was
11    /// found.
12    pub fn find_data_template(
13        &self,
14        data: Option<&BoxedValue>,
15        primary: Option<&Rc<dyn IDataTemplate>>,
16    ) -> Option<Rc<dyn IDataTemplate>> {
17        if let Some(primary) = primary {
18            if primary.match_(data) {
19                return Some(primary.clone());
20            }
21        }
22
23        let mut current_template_host: Option<Ref<StyledElement>> = Some(self.to_ref().upcast());
24
25        while let Some(current) = current_template_host {
26            if let Some(host_candidate) = current.downcast_ref::<Control>() {
27                if host_candidate.is_data_templates_initialized() {
28                    for dt in host_candidate.data_templates().snapshot().iter() {
29                        if dt.match_(data) {
30                            return Some(dt.clone());
31                        }
32                    }
33                }
34            }
35
36            current_template_host = current.parent();
37        }
38
39        let global = FerroLocator::current().get_service::<dyn IGlobalDataTemplates>();
40
41        if let Some(global) = global {
42            if global.is_data_templates_initialized() {
43                for dt in global.data_templates().snapshot().iter() {
44                    if dt.match_(data) {
45                        return Some(dt.clone());
46                    }
47                }
48            }
49        }
50
51        None
52    }
53}