swayipc-types 1.4.3

A library containing Type defintions from sway's IPC interface
Documentation
use crate::reply::Node;

impl Node {
    pub fn find_as_ref<F>(&self, predicate: F) -> Option<&Node>
    where
        F: Copy + Fn(&Node) -> bool,
    {
        if predicate(self) {
            return Some(self);
        }
        for node in &self.nodes {
            let node = node.find_as_ref(predicate);
            if node.is_some() {
                return node;
            }
        }
        for node in &self.floating_nodes {
            let node = node.find_as_ref(predicate);
            if node.is_some() {
                return node;
            }
        }
        None
    }

    pub fn find<F>(self, predicate: F) -> Option<Node>
    where
        F: Copy + Fn(&Node) -> bool,
    {
        if predicate(&self) {
            return Some(self);
        }
        let Node {
            nodes,
            floating_nodes,
            ..
        } = self;
        for node in nodes {
            let node = node.find(predicate);
            if node.is_some() {
                return node;
            }
        }
        for node in floating_nodes {
            let node = node.find(predicate);
            if node.is_some() {
                return node;
            }
        }
        None
    }

    pub fn find_focused_as_ref<F>(&self, predicate: F) -> Option<&Node>
    where
        F: Copy + Fn(&Node) -> bool,
    {
        if predicate(self) {
            return Some(self);
        }
        if self.focus.is_empty() {
            return None;
        }
        let first = self.focus[0];
        for node in &self.nodes {
            if node.id == first {
                return node.find_focused_as_ref(predicate);
            }
        }
        for node in &self.floating_nodes {
            if node.id == first {
                return node.find_focused_as_ref(predicate);
            }
        }
        None
    }

    pub fn find_focused<F>(self, predicate: F) -> Option<Node>
    where
        F: Copy + Fn(&Node) -> bool,
    {
        if predicate(&self) {
            return Some(self);
        }
        let Node {
            nodes,
            floating_nodes,
            focus,
            ..
        } = self;
        if focus.is_empty() {
            return None;
        }
        let first = focus[0];
        for node in nodes {
            if node.id == first {
                return node.find_focused(predicate);
            }
        }
        for node in floating_nodes {
            if node.id == first {
                return node.find_focused(predicate);
            }
        }
        None
    }

    pub fn iter(&self) -> NodeIterator<'_> {
        NodeIterator { queue: vec![self] }
    }
}

pub struct NodeIterator<'a> {
    queue: Vec<&'a Node>,
}

impl<'a> Iterator for NodeIterator<'a> {
    type Item = &'a Node;

    fn next(&mut self) -> Option<&'a Node> {
        match self.queue.pop() {
            None => None,
            Some(result) => {
                self.queue
                    .extend(result.nodes.iter().chain(result.floating_nodes.iter()));
                Some(result)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::NodeBorder;
    use crate::NodeLayout;
    use crate::NodeType;
    use crate::Rect;

    fn rect() -> Rect {
        Rect {
            x: 0,
            y: 0,
            width: 10,
            height: 10,
        }
    }

    fn mk_node(name: Option<String>, node_type: NodeType, nodes: Vec<Node>) -> Node {
        Node {
            id: 1,
            name,
            node_type,
            border: NodeBorder::Normal,
            current_border_width: 0,
            layout: NodeLayout::Tabbed,
            percent: None,
            rect: rect(),
            window_rect: rect(),
            deco_rect: rect(),
            geometry: rect(),
            urgent: false,
            focused: false,
            focus: Vec::new(),
            nodes,
            floating_nodes: Vec::new(),
            sticky: false,
            representation: None,
            fullscreen_mode: None,
            floating: None,
            scratchpad_state: None,
            app_id: None,
            pid: None,
            window: None,
            num: None,
            window_properties: None,
            marks: Vec::new(),
            inhibit_idle: None,
            idle_inhibitors: None,
            shell: None,
            visible: None,
            output: None,
            sandbox_engine: None,
            sandbox_app_id: None,
            sandbox_instance_id: None,
            tag: None,
            foreign_toplevel_identifier: None,
        }
    }

    #[test]
    fn returns_the_given_root_node_first() {
        let root = mk_node(Some(String::from("root")), NodeType::Root, vec![]);
        let mut iterator = root.iter();
        assert_eq!(iterator.next().unwrap().name, Some("root".to_string()));
    }

    #[test]
    fn returns_children_of_the_given_node() {
        let root = mk_node(
            Some("root".to_string()),
            NodeType::Root,
            vec![mk_node(Some("child".to_string()), NodeType::Con, vec![])],
        );
        let mut iterator = root.iter();
        iterator.next();
        assert_eq!(iterator.next().unwrap().name, Some("child".to_string()));
    }

    #[test]
    fn returns_transitive_children_of_the_given_node() {
        let root = mk_node(
            Some("root".to_string()),
            NodeType::Root,
            vec![mk_node(
                Some("child".to_string()),
                NodeType::Con,
                vec![mk_node(
                    Some("grandchild".to_string()),
                    NodeType::Con,
                    vec![],
                )],
            )],
        );
        let mut iterator = root.iter();
        iterator.next();
        iterator.next();
        assert_eq!(
            iterator.next().unwrap().name,
            Some("grandchild".to_string())
        );
    }

    #[test]
    fn returns_none_at_the_end() {
        let root = mk_node(Some("root".to_string()), NodeType::Root, vec![]);
        let mut iterator = root.iter();
        iterator.next();
        assert_eq!(iterator.next(), None);
    }
}