swayipc_types/utils/
node.rs

1use crate::reply::Node;
2
3impl Node {
4    pub fn find_as_ref<F>(&self, predicate: F) -> Option<&Node>
5    where
6        F: Copy + Fn(&Node) -> bool,
7    {
8        if predicate(self) {
9            return Some(self);
10        }
11        for node in &self.nodes {
12            let node = node.find_as_ref(predicate);
13            if node.is_some() {
14                return node;
15            }
16        }
17        for node in &self.floating_nodes {
18            let node = node.find_as_ref(predicate);
19            if node.is_some() {
20                return node;
21            }
22        }
23        None
24    }
25
26    pub fn find<F>(self, predicate: F) -> Option<Node>
27    where
28        F: Copy + Fn(&Node) -> bool,
29    {
30        if predicate(&self) {
31            return Some(self);
32        }
33        let Node {
34            nodes,
35            floating_nodes,
36            ..
37        } = self;
38        for node in nodes {
39            let node = node.find(predicate);
40            if node.is_some() {
41                return node;
42            }
43        }
44        for node in floating_nodes {
45            let node = node.find(predicate);
46            if node.is_some() {
47                return node;
48            }
49        }
50        None
51    }
52
53    pub fn find_focused_as_ref<F>(&self, predicate: F) -> Option<&Node>
54    where
55        F: Copy + Fn(&Node) -> bool,
56    {
57        if predicate(self) {
58            return Some(self);
59        }
60        if self.focus.is_empty() {
61            return None;
62        }
63        let first = self.focus[0];
64        for node in &self.nodes {
65            if node.id == first {
66                return node.find_focused_as_ref(predicate);
67            }
68        }
69        for node in &self.floating_nodes {
70            if node.id == first {
71                return node.find_focused_as_ref(predicate);
72            }
73        }
74        None
75    }
76
77    pub fn find_focused<F>(self, predicate: F) -> Option<Node>
78    where
79        F: Copy + Fn(&Node) -> bool,
80    {
81        if predicate(&self) {
82            return Some(self);
83        }
84        let Node {
85            nodes,
86            floating_nodes,
87            focus,
88            ..
89        } = self;
90        if focus.is_empty() {
91            return None;
92        }
93        let first = focus[0];
94        for node in nodes {
95            if node.id == first {
96                return node.find_focused(predicate);
97            }
98        }
99        for node in floating_nodes {
100            if node.id == first {
101                return node.find_focused(predicate);
102            }
103        }
104        None
105    }
106
107    pub fn iter(&self) -> NodeIterator<'_> {
108        NodeIterator { queue: vec![self] }
109    }
110}
111
112pub struct NodeIterator<'a> {
113    queue: Vec<&'a Node>,
114}
115
116impl<'a> Iterator for NodeIterator<'a> {
117    type Item = &'a Node;
118
119    fn next(&mut self) -> Option<&'a Node> {
120        match self.queue.pop() {
121            None => None,
122            Some(result) => {
123                self.queue
124                    .extend(result.nodes.iter().chain(result.floating_nodes.iter()));
125                Some(result)
126            }
127        }
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134    use crate::NodeBorder;
135    use crate::NodeLayout;
136    use crate::NodeType;
137    use crate::Orientation;
138    use crate::Rect;
139
140    fn rect() -> Rect {
141        Rect {
142            x: 0,
143            y: 0,
144            width: 10,
145            height: 10,
146        }
147    }
148
149    fn mk_node(name: Option<String>, node_type: NodeType, nodes: Vec<Node>) -> Node {
150        Node {
151            id: 1,
152            name,
153            node_type,
154            border: NodeBorder::Normal,
155            current_border_width: 0,
156            layout: NodeLayout::Tabbed,
157            percent: None,
158            rect: rect(),
159            window_rect: rect(),
160            deco_rect: rect(),
161            geometry: rect(),
162            urgent: false,
163            focused: false,
164            focus: Vec::new(),
165            nodes,
166            floating_nodes: Vec::new(),
167            sticky: false,
168            representation: None,
169            fullscreen_mode: None,
170            floating: None,
171            scratchpad_state: None,
172            app_id: None,
173            pid: None,
174            window: None,
175            num: None,
176            window_properties: None,
177            marks: Vec::new(),
178            inhibit_idle: None,
179            idle_inhibitors: None,
180            shell: None,
181            visible: None,
182            output: None,
183            sandbox_engine: None,
184            sandbox_app_id: None,
185            sandbox_instance_id: None,
186            tag: None,
187            foreign_toplevel_identifier: None,
188            orientation: Orientation::None,
189        }
190    }
191
192    #[test]
193    fn returns_the_given_root_node_first() {
194        let root = mk_node(Some(String::from("root")), NodeType::Root, vec![]);
195        let mut iterator = root.iter();
196        assert_eq!(iterator.next().unwrap().name, Some("root".to_string()));
197    }
198
199    #[test]
200    fn returns_children_of_the_given_node() {
201        let root = mk_node(
202            Some("root".to_string()),
203            NodeType::Root,
204            vec![mk_node(Some("child".to_string()), NodeType::Con, vec![])],
205        );
206        let mut iterator = root.iter();
207        iterator.next();
208        assert_eq!(iterator.next().unwrap().name, Some("child".to_string()));
209    }
210
211    #[test]
212    fn returns_transitive_children_of_the_given_node() {
213        let root = mk_node(
214            Some("root".to_string()),
215            NodeType::Root,
216            vec![mk_node(
217                Some("child".to_string()),
218                NodeType::Con,
219                vec![mk_node(
220                    Some("grandchild".to_string()),
221                    NodeType::Con,
222                    vec![],
223                )],
224            )],
225        );
226        let mut iterator = root.iter();
227        iterator.next();
228        iterator.next();
229        assert_eq!(
230            iterator.next().unwrap().name,
231            Some("grandchild".to_string())
232        );
233    }
234
235    #[test]
236    fn returns_none_at_the_end() {
237        let root = mk_node(Some("root".to_string()), NodeType::Root, vec![]);
238        let mut iterator = root.iter();
239        iterator.next();
240        assert_eq!(iterator.next(), None);
241    }
242}