cursive_multiplex/
path.rs

1use crate::{Id, Mux, Orientation};
2
3/// Path used to get the id of a specific pane in the mux.
4/// self can be directed by calling `.up()`, `.down()`, `.left()` and `.right()` on the instance.
5/// To get the final id of a pane `.build()`.
6pub struct Path<'a> {
7    mux: &'a Mux,
8    cur_id: Option<Id>,
9}
10
11#[derive(Debug, PartialEq)]
12pub(crate) enum SearchPath {
13    Left,
14    Right,
15    Up,
16    Down,
17}
18
19impl<'a> Path<'a> {
20    fn new(mux: &'a Mux, id: Id) -> Self {
21        Path {
22            mux,
23            cur_id: Some(id),
24        }
25    }
26
27    /// Finsihing of the path, Option contains the target Id
28    /// If Option None no Id could be found fitting to the path
29    /// Consumes the path
30    /// # Example
31    /// ```
32    /// # use cursive::views::DummyView;
33    /// # use cursive_multiplex::Mux;
34    /// let mut mux = Mux::new();
35    /// let node1 = mux.add_right_of(DummyView, mux.root().build().unwrap()).unwrap();
36    /// mux.add_below(DummyView, node1);
37    /// let path = mux.root().up().build();
38    /// assert_eq!(node1, path.unwrap());
39    /// ```
40    pub fn build(self) -> Option<Id> {
41        if let Some(node) = self.cur_id {
42            if self.mux.tree.get(node).unwrap().get().has_view() || node == self.mux.root {
43                self.cur_id
44            } else {
45                None
46            }
47        } else {
48            self.cur_id
49        }
50    }
51
52    /// Going up from the current position in the mux
53    /// Target can be get by calling `.build()`
54    pub fn up(self) -> Self {
55        self.next_node(SearchPath::Up, Orientation::Vertical)
56    }
57
58    /// Going down from the current position in the mux
59    /// Target can be get by calling `.build()`
60    pub fn down(self) -> Self {
61        self.next_node(SearchPath::Down, Orientation::Vertical)
62    }
63
64    /// Going left from the current position in the mux
65    /// Target can be get by calling `.build()`
66    pub fn left(self) -> Self {
67        self.next_node(SearchPath::Left, Orientation::Horizontal)
68    }
69
70    /// Going right from the current position in the mux
71    /// Target can be get by calling `.build()`
72    pub fn right(self) -> Self {
73        self.next_node(SearchPath::Right, Orientation::Horizontal)
74    }
75
76    fn next_node(mut self, direction: SearchPath, orit: Orientation) -> Self {
77        if let Some(node) = self.cur_id {
78            // Node can be passed
79            if node.children(&self.mux.tree).count() > 0 {
80                if let Some(node_content) = self.mux.tree.get(node) {
81                    match node_content.get().orientation {
82                        _ if node_content.get().orientation == orit => {
83                            if let Some(new) = node.children(&self.mux.tree).nth(match direction {
84                                SearchPath::Up | SearchPath::Left => 0,
85                                SearchPath::Right | SearchPath::Down => 1,
86                            }) {
87                                self.cur_id = Some(new);
88                            } else {
89                                // Invalid Path
90                                self.cur_id = None;
91                            }
92                        }
93                        _ => {
94                            // Invalid Path
95                            println!("ello");
96                            self.cur_id = None;
97                        }
98                    }
99                } else {
100                    // State corrupted, should not occur
101                    self.cur_id = None;
102                }
103            }
104        }
105        self
106    }
107}
108
109impl Mux {
110    /// Getter for the initial path to traverse the tree and find a specific Id.
111    /// Returns a Path which can be traversed.
112    pub fn root(&self) -> Path {
113        Path::new(self, self.root)
114    }
115}
116
117#[cfg(test)]
118mod test {
119    use super::Mux;
120    use cursive_core::views::DummyView;
121
122    #[test]
123    fn path_root() {
124        let mut mux = Mux::new();
125        let node1 = mux.add_right_of(DummyView, mux.root).unwrap();
126        mux.add_below(DummyView, node1).unwrap();
127        let upper_pane = mux.root().build();
128        assert!(upper_pane.is_some());
129    }
130
131    #[test]
132    fn path_up() {
133        let mut mux = Mux::new();
134        let node1 = mux.add_right_of(DummyView, mux.root).unwrap();
135        mux.add_below(DummyView, node1).unwrap();
136        let upper_pane = mux.root().up().build();
137        assert!(upper_pane.is_some());
138        assert_eq!(node1, upper_pane.unwrap());
139    }
140
141    #[test]
142    fn path_down() {
143        let mut mux = Mux::new();
144        let node1 = mux.add_right_of(DummyView, mux.root).unwrap();
145        let node2 = mux.add_below(DummyView, node1).unwrap();
146        let lower_pane = mux.root().down().build();
147        assert!(lower_pane.is_some());
148        assert_eq!(node2, lower_pane.unwrap());
149    }
150
151    #[test]
152    fn path_left() {
153        let mut mux = Mux::new();
154        let node1 = mux.add_right_of(DummyView, mux.root).unwrap();
155        mux.add_right_of(DummyView, node1).unwrap();
156        let left_pane = mux.root().left().build();
157        assert!(left_pane.is_some());
158        assert_eq!(node1, left_pane.unwrap());
159    }
160
161    #[test]
162    fn path_right() {
163        let mut mux = Mux::new();
164        let node1 = mux.add_right_of(DummyView, mux.root).unwrap();
165        let node2 = mux.add_right_of(DummyView, node1).unwrap();
166        let right_pane = mux.root().right().build();
167        assert!(right_pane.is_some());
168        assert_eq!(node2, right_pane.unwrap());
169    }
170
171    #[test]
172    fn path_invalid() {
173        let mut mux = Mux::new();
174        let node1 = mux.add_right_of(DummyView, mux.root).unwrap();
175        let _ = mux.add_right_of(DummyView, node1).unwrap();
176        let root_pane = mux.root().up().build();
177        assert!(root_pane.is_none());
178    }
179}