gooey/
utils.rs

1//! Utility functions
2
3use std::collections::VecDeque;
4use crate::interface;
5use crate::Tree;
6use crate::tree::{self, NodeId};
7
8/// Utility functions to extend the Tree interface for common operations.
9pub trait TreeHelper {
10  fn get_element (&self, node_id : &NodeId) -> &interface::Element;
11  fn get_element_mut (&mut self, node_id : &NodeId) -> &mut interface::Element;
12  fn get_parent (&self, child : &NodeId) -> &interface::Element;
13  fn get_parent_mut (&mut self, child : &NodeId) -> &mut interface::Element;
14  fn get_parent_id (&self, child : &NodeId) -> &NodeId;
15  /// Splice the subtree of `other` rooted at `other_id` into `tree` under
16  /// `parent_id` with the given `order`
17  fn splice_subtree (
18    &mut self,
19    parent_id : &NodeId,
20    other     : &Tree <interface::Element>,
21    other_id  : &NodeId,
22    order     : interface::CreateOrder
23  ) -> NodeId;
24  /// Write formatted tree representation showing only the names of the nodes
25  /// (as opposed to the default `Tree::write_formatted` method).
26  fn write_formatted_names <W : std::fmt::Write> (&self, w : &mut W)
27    -> std::fmt::Result;
28}
29
30/// Map a function over the nodes of a tree returning a new tree
31pub fn map_tree <T, U, F> (tree : &Tree <T>, f : F) -> Tree <U> where
32  F : Fn (&T) -> U
33{
34  use tree::{InsertBehavior, Node};
35  let mut out = Tree::new();
36  if let Some (root_id) = tree.root_node_id() {
37    let root = tree.get (root_id).unwrap();
38    let new_root_id = out
39      .insert (Node::new (f (root.data())), InsertBehavior::AsRoot).unwrap();
40    let mut parent_child_ids = root.children().iter()
41      .map (|child_id| (new_root_id.clone(), child_id.clone()))
42      .collect::<VecDeque <_>>();
43    while let Some ((new_parent_id, old_child_id)) =
44      parent_child_ids.pop_front()
45    {
46      let child = tree.get (&old_child_id).unwrap();
47      let new_child_id = out.insert (
48        Node::new (f (child.data())),
49        InsertBehavior::UnderNode (&new_parent_id)
50      ).unwrap();
51      for child_id in child.children().iter() {
52        parent_child_ids.push_back ((new_child_id.clone(), child_id.clone()));
53      }
54    }
55  }
56  out
57}
58
59impl TreeHelper for Tree <interface::Element> {
60  /// Unwraps and gets the underlying Element reference.
61  ///
62  /// &#9888; Panics if `node_id` does not exist.
63  #[inline]
64  fn get_element (&self, node_id : &NodeId) -> &interface::Element {
65    self.get (node_id).unwrap().data()
66  }
67
68  /// Unwraps and gets the underlying Element reference.
69  ///
70  /// &#9888; Panics if `node_id` does not exist.
71  #[inline]
72  fn get_element_mut (&mut self, node_id : &NodeId) -> &mut interface::Element {
73    self.get_mut (node_id).unwrap().data_mut()
74  }
75
76  /// Unwraps and gets the parent of the referenced NodeId.
77  ///
78  /// &#9888; Panics if `child` does not exist or if `child` does not have a
79  /// parent.
80  #[inline]
81  fn get_parent (&self, child : &NodeId) -> &interface::Element {
82    self.get_element (self.get_parent_id (child))
83  }
84
85  /// Unwraps and gets the parent of the referenced NodeId.
86  ///
87  /// &#9888; Panics if `child` does not exist or if `child` does not have a
88  /// parent.
89  #[inline]
90  fn get_parent_mut (&mut self, child : &NodeId) -> &mut interface::Element {
91    let parent_id = self.get_parent_id (child).clone();
92    self.get_element_mut (&parent_id)
93  }
94
95  /// Unwraps and gets the parent ID of the referenced NodeId.
96  ///
97  /// &#9888; Panics if `child` does not exist or if `child` does not have a
98  /// parent.
99  #[inline]
100  fn get_parent_id (&self, child : &NodeId) -> &NodeId {
101    self.get (child).unwrap().parent().unwrap()
102  }
103
104  /// Splice the subtree of `other` rooted at `other_id` into `tree` under
105  /// `parent_id` with the given `order`
106  fn splice_subtree (
107    &mut self,
108    parent_id : &NodeId,
109    other     : &Tree <interface::Element>,
110    other_id  : &NodeId,
111    order     : interface::CreateOrder
112  ) -> NodeId {
113    use tree::Node;
114    use interface::CreateOrder;
115    let subtree_root = Node::new (other.get_element (&other_id).clone());
116    let subtree_id   = self.insert (
117      subtree_root, tree::InsertBehavior::UnderNode (parent_id)
118    ).unwrap();
119    match order {
120      CreateOrder::Append  => {}
121      CreateOrder::Prepend => {
122        let _ = self.make_first_sibling (&subtree_id).unwrap();
123      }
124      CreateOrder::NthSibling (n) => {
125        let _ = self.make_nth_sibling (&subtree_id, n as usize).unwrap();
126      }
127    }
128    for child_id in other.children_ids (other_id).unwrap() {
129      self.splice_subtree (&subtree_id, other, child_id, CreateOrder::Append);
130    }
131    subtree_id
132  }
133
134  fn write_formatted_names<W: std::fmt::Write>(&self, w: &mut W)
135    -> std::fmt::Result
136  {
137    if let Some(node_id) = self.root_node_id() {
138      let childn = 0;
139      let level = 0;
140      let last = vec![];
141      let mut stack = vec![(node_id, childn, level, last)];
142      while let Some((node_id, childn, level, last)) = stack.pop() {
143        debug_assert_eq!(
144          last.len(), level,
145          "each previous level should indicate whether it has reached the last node"
146        );
147        let node = self.get(node_id)
148          .expect("getting node of existing node ref id");
149        if childn == 0 {
150          for i in 1..level {
151            if last[i - 1] {
152              write!(w, "    ")?;
153            } else {
154              write!(w, "│   ")?;
155            }
156          }
157          if level > 0 {
158            if last[level - 1] {
159              write!(w, "└── ")?;
160            } else {
161              write!(w, "├── ")?;
162            }
163          }
164          let data  = node.data();
165          let state = match data.controller.state {
166            interface::controller::State::Focused  => "*",
167            interface::controller::State::Enabled  => "",
168            interface::controller::State::Disabled => "†"
169          };
170          writeln!(w, "{}{}", data.name, state)?;
171        }
172        let mut children = node.children().iter().skip(childn);
173        if let Some(child_id) = children.next() {
174          let mut next_last = last.clone();
175          if children.next().is_some() {
176            stack.push((node_id, childn + 1, level, last));
177            next_last.push(false);
178          } else {
179            next_last.push(true);
180          }
181          stack.push((child_id, 0, level + 1, next_last));
182        }
183      }
184    }
185    Ok(())
186  }
187}
188
189#[cfg(test)]
190mod tests {
191  use crate::tree::{InsertBehavior, Node};
192  use super::*;
193  #[test]
194  fn test_map_tree() {
195    let mut tree = Tree::new();
196    let root_id = tree.insert (Node::new (0u32), InsertBehavior::AsRoot)
197      .unwrap();
198    let child_id = tree
199      .insert (Node::new (1), InsertBehavior::UnderNode (&root_id)).unwrap();
200    tree.insert (Node::new (2), InsertBehavior::UnderNode (&root_id)).unwrap();
201    tree.insert (Node::new (3), InsertBehavior::UnderNode (&child_id)).unwrap();
202    tree.insert (Node::new (4), InsertBehavior::UnderNode (&child_id)).unwrap();
203    let mut s = String::new();
204    tree.write_formatted (&mut s).unwrap();
205    println!("old tree:\n{}", s);
206    let new_tree : Tree <String> = map_tree (&tree, |i| (*i).to_string());
207    let mut s = String::new();
208    new_tree.write_formatted (&mut s).unwrap();
209    println!("new tree:\n{}", s);
210  }
211}