tidy_tree/layout/
basic_layout.rs1use num::Float;
2
3use super::Layout;
4use crate::{geometry::Coord, node::Node};
5use std::cmp::{max, min};
6
7pub struct BasicLayout {
11 pub parent_child_margin: Coord,
12 pub peer_margin: Coord,
13}
14
15#[derive(Debug, Clone)]
19pub struct BoundingBox {
20 pub total_width: Coord,
21 pub total_height: Coord,
22}
23
24impl Default for BoundingBox {
25 fn default() -> Self {
26 Self {
27 total_height: 0.,
28 total_width: 0.,
29 }
30 }
31}
32
33impl Layout for BasicLayout {
34 fn layout(&mut self, root: &mut Node) {
35 root.pre_order_traversal_mut(|node| {
36 node.tidy = None;
37 node.x = 0.;
38 node.y = 0.;
39 node.relative_x = 0.;
40 node.relative_y = 0.;
41 });
42 root.post_order_traversal_mut(|node| {
43 self.update_meta(node);
44 });
45 root.pre_order_traversal_mut(|node| {
46 if let Some(mut parent) = node.parent {
47 let parent = unsafe { parent.as_mut() };
48 node.x = parent.x + node.relative_x;
49 node.y = parent.y + node.relative_y;
50 }
51 });
52 }
53
54 fn partial_layout(&mut self, root: &mut Node, changed: &[std::ptr::NonNull<Node>]) {
55 todo!()
56 }
57
58 fn parent_child_margin(&self) -> Coord {
59 self.parent_child_margin
60 }
61
62 fn peer_margin(&self) -> Coord {
63 self.peer_margin
64 }
65}
66
67impl BasicLayout {
68 fn update_meta(&mut self, node: &mut Node) {
69 node.bbox = BoundingBox {
70 total_height: node.height,
71 total_width: node.width,
72 };
73 let children: *mut _ = &mut node.children;
74 let children = unsafe { &mut *children };
75 let n = children.len() as Coord;
76 if n > 0. {
77 let mut temp_x = 0.;
78 let mut max_height = 0.;
79 let n = children.len();
80 for (i, child) in children.iter_mut().enumerate() {
81 child.relative_y = node.height + self.parent_child_margin;
82 child.relative_x = temp_x + child.bbox.total_width / 2.;
83 temp_x += child.bbox.total_width + self.peer_margin;
84 max_height = Float::max(child.bbox.total_height, max_height);
85 }
86
87 let children_width = temp_x - self.peer_margin;
88 let shift_x = -children_width / 2.;
89 for child in children.iter_mut() {
90 child.relative_x += shift_x;
91 }
92
93 node.bbox.total_width = Float::max(children_width, node.width);
94 node.bbox.total_height = node.height + self.parent_child_margin + max_height;
95 }
96 }
97}
98
99#[cfg(test)]
100mod basic_layout_test {
101 use super::{BasicLayout, BoundingBox};
102 use crate::{layout::Layout, Node};
103
104 #[test]
105 fn easy_test_0() {
106 let mut root = Node::new(0, 10., 10.);
107 root.append_child(Node::new(1, 10., 10.));
108 let mut second = Node::new(2, 10., 10.);
109 second.append_child(Node::new(3, 10., 10.));
110 root.append_child(second);
111 root.append_child(Node::new(4, 10., 10.));
112 let mut layout = BasicLayout {
113 parent_child_margin: 10.,
114 peer_margin: 5.,
115 };
116 layout.layout(&mut root);
117 println!("{:#?}", root);
118 }
119}