gtk_ui_builder/ast/entries/
root.rs

1use crate::ast::entry::Entry;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum Requirement {
5    Gtk(String),
6    Libadwaita(String),
7    Other(String, String)
8}
9
10impl Requirement {
11    pub fn new<T: ToString>(lib: T, version: T) -> Self {
12        let version = version.to_string();
13
14        match lib.to_string().as_str() {
15            "gtk" => Self::Gtk(version),
16            "Gtk" => Self::Gtk(version),
17            "GTK" => Self::Gtk(version),
18
19            "adw" => Self::Libadwaita(version),
20            "Adw" => Self::Libadwaita(version),
21            "ADW" => Self::Libadwaita(version),
22            "libadwaita" => Self::Libadwaita(version),
23            "Libadwaita" => Self::Libadwaita(version),
24
25            lib => Self::Other(lib.to_string(), version)
26        }
27    }
28
29    pub fn get_xml(&self) -> Option<String> {
30        let (lib, version) = match self {
31            Requirement::Gtk(version) => ("gtk", version),
32            Requirement::Other(lib, version) => (lib.as_str(), version),
33
34            Requirement::Libadwaita(_) => return None // ("libadwaita", version)
35        };
36
37        Some(format!("<requires lib=\"{}\" version=\"{}\"/>", lib, version))
38    }
39}
40
41#[derive(Default, Debug, Clone, PartialEq, Eq)]
42pub struct Root {
43    pub requirements: Vec<Requirement>,
44    pub children: Vec<Entry>
45}
46
47impl Root {
48    pub fn add_child(&mut self, child: Entry) {
49        self.children.push(child);
50    }
51
52    pub fn require(&mut self, requirement: Requirement) {
53        self.requirements.push(requirement);
54    }
55
56    /// Get pretty string description of this entry
57    pub fn dbg(&self) -> String {
58        format!(
59            "Root {{\n  requirements: {:?},\n  children: [\n{}  ]\n}}",
60            self.requirements,
61            (&self.children).into_iter().map(|child| {
62                let text = child.dbg().lines()
63                    .map(|line| String::from("      ") + line + "\n")
64                    .collect::<String>();
65
66                text.trim_end().to_string() + ",\n"
67            }).collect::<String>()
68        )
69    }
70
71    /// Get XML description of this entry
72    pub fn get_xml(&self) -> String {
73        format!(
74            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><interface>{}{}</interface>",
75            (&self.requirements).into_iter().map(|item| item.get_xml()).filter_map(|item| item).collect::<String>(),
76            (&self.children).into_iter().map(|item| item.get_xml()).collect::<String>()
77        )
78    }
79
80    pub fn filter<T: Fn(&Entry) -> Option<F>, F>(&self, filter: &T) -> Vec<F> {
81        fn filter_entries<T: Fn(&Entry) -> Option<F>, F>(entries: &Vec<Entry>, filter: &T) -> Vec<F> {
82            let mut filtered = Vec::new();
83
84            for entry in entries {
85                if let Some(found) = filter(entry) {
86                    filtered.push(found);
87                }
88
89                match entry {
90                    Entry::Object(obj) => filtered.append(&mut filter_entries(&obj.children, filter)),
91                    Entry::Property(prop) => {
92                        if let super::property::PropertyValue::Entry(obj) = &prop.value {
93                            if let Some(found) = filter(&Entry::Object(obj.clone())) {
94                                filtered.push(found);
95                            }
96
97                            filtered.append(&mut filter_entries(&obj.children, filter));
98                        }
99                    }
100                    _ => ()
101                }
102            }
103
104            filtered
105        }
106
107        filter_entries(&self.children, filter)
108    }
109
110    pub fn get_named_objects(&self) -> Vec<(String, super::object::Object)> {
111        self.filter(&|entry| {
112            match entry {
113                Entry::Object(obj) => {
114                    if let Some(name) = &obj.name {
115                        Some((name.clone(), obj.clone()))
116                    }
117
118                    else {
119                        None
120                    }
121                },
122                _ => None
123            }
124        })
125    }
126
127    #[cfg(feature = "rhai-events")]
128    pub fn get_rhai_events(&self) -> Vec<super::rhai_event::RhaiEvent> {
129        self.filter(&|entry| {
130            match entry {
131                Entry::RhaiEvent(event) => Some(event.clone()),
132                _ => None
133            }
134        })
135    }
136}