gtk_ui_builder/ast/entries/
root.rs1use 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 };
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 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 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}