1#![allow(dead_code, unused_imports, unused_variables)]
2pub mod geometry;
3mod iter;
4mod layout;
5mod node;
6mod utils;
7pub use iter::Iter;
8use std::{any::Any, collections::HashMap, ptr::NonNull};
9
10use geometry::Coord;
11use layout::BoundingBox;
12pub use layout::{BasicLayout, Layout, TidyLayout};
13pub use node::Node;
14
15#[derive(PartialEq, Eq)]
16pub enum LayoutType {
17 Basic,
18 Tidy,
19 LayeredTidy,
20}
21
22pub struct TidyTree {
23 root: Node,
24 layout_type: LayoutType,
25 layout: Box<dyn Layout>,
26 map: HashMap<usize, NonNull<Node>>,
27}
28
29impl TidyTree {
30 pub fn with_basic_layout(parent_child_margin: Coord, peer_margin: Coord) -> Self {
31 TidyTree {
32 layout_type: LayoutType::Basic,
33 root: Default::default(),
34 layout: Box::new(BasicLayout {
35 parent_child_margin,
36 peer_margin,
37 }),
38 map: HashMap::new(),
39 }
40 }
41
42 pub fn with_tidy_layout(parent_child_margin: Coord, peer_margin: Coord) -> Self {
43 TidyTree {
44 layout_type: LayoutType::Tidy,
45 root: Default::default(),
46 layout: Box::new(TidyLayout::new(parent_child_margin, peer_margin)),
47 map: HashMap::new(),
48 }
49 }
50
51 pub fn with_layered_tidy(parent_child_margin: Coord, peer_margin: Coord) -> Self {
52 TidyTree {
53 layout_type: LayoutType::Tidy,
54 root: Default::default(),
55 layout: Box::new(TidyLayout::new_layered(parent_child_margin, peer_margin)),
56 map: HashMap::new(),
57 }
58 }
59
60 pub fn change_layout(&mut self, layout_type: LayoutType) {
61 if layout_type == self.layout_type {
62 return;
63 }
64
65 let parent_child_margin = self.layout.parent_child_margin();
66 let peer_margin = self.layout.peer_margin();
67 match layout_type {
68 LayoutType::Basic => {
69 self.layout = Box::new(BasicLayout {
70 parent_child_margin,
71 peer_margin,
72 });
73 }
74 LayoutType::Tidy => {
75 self.layout = Box::new(TidyLayout::new(parent_child_margin, peer_margin));
76 }
77 LayoutType::LayeredTidy => {
78 self.layout = Box::new(TidyLayout::new_layered(parent_child_margin, peer_margin))
79 }
80 }
81
82 self.layout_type = layout_type;
83 }
84
85 pub fn is_empty(&self) -> bool {
86 self.root.id == usize::MAX
87 }
88
89 pub fn add_node(&mut self, id: usize, width: Coord, height: Coord, parent_id: usize) {
90 let node = Node::new(id, width, height);
91 if self.is_empty() || parent_id == usize::MAX {
92 self.root = node;
93 self.map.insert(id, (&self.root).into());
94 return;
95 }
96
97 let mut parent = *self.map.get(&parent_id).unwrap();
98 let parent = unsafe { parent.as_mut() };
99
100 let ptr = parent.append_child(node);
101 self.map.insert(id, ptr);
102 }
103
104 pub fn remove_node(&mut self, id: usize) {
105 if self.is_empty() {
106 return;
107 }
108
109 if let Some(node) = self.map.get(&id) {
110 let node = unsafe { &mut *node.as_ptr() };
111 node.pre_order_traversal(|node| {
112 self.map.remove(&node.id);
113 });
114 node.parent_mut().unwrap().remove_child(id);
115 }
116 }
117
118 pub fn data(&mut self, id: &[usize], width: &[Coord], height: &[Coord], parent_id: &[usize]) {
119 for (i, &id) in id.iter().enumerate() {
120 let width = width[i];
121 let height = height[i];
122 let parent_id = parent_id[i];
123 self.add_node(id, width, height, parent_id);
124 }
125 }
126
127 pub fn layout(&mut self) {
128 if self.is_empty() {
129 return;
130 }
131
132 self.layout.layout(&mut self.root);
133 }
134
135 pub fn get_pos(&self) -> Vec<Coord> {
136 let mut ans = vec![];
137 for (id, node) in self.map.iter() {
138 let node = unsafe { node.as_ref() };
139 ans.push((*id) as Coord);
140 ans.push(node.x);
141 ans.push(node.y);
142 }
143
144 ans
145 }
146}
147
148pub const NULL_ID: usize = usize::MAX;