1use crate::node::BspNode;
2use crate::node::NaryNode;
3use crate::rect::{LayoutError, LayoutRect, Orientation, SizeConstraints};
4use crate::snap::InsertPosition;
5
6pub trait LayoutEngine<Id: Copy + Eq + Ord> {
11 fn layout(&self, area: LayoutRect) -> Vec<(Id, LayoutRect)>;
12 fn insert_leaf(
13 &mut self,
14 target: Id,
15 insert: Id,
16 position: InsertPosition,
17 area: LayoutRect,
18 constraints: &SizeConstraints,
19 ) -> Result<(), LayoutError>;
20 fn remove_leaf(&mut self, id: Id) -> Result<(), LayoutError>;
21 fn all_leaf_ids(&self) -> Vec<Id>;
22 fn subtree_any(&self, predicate: &mut impl FnMut(Id) -> bool) -> bool;
23 fn apply_drag(
24 &mut self,
25 area: LayoutRect,
26 path: &[usize],
27 index: usize,
28 orientation: Orientation,
29 delta: i16,
30 constraints: &SizeConstraints,
31 ) -> bool;
32}
33
34impl<Id: Copy + Eq + Ord> LayoutEngine<Id> for BspNode<Id> {
35 fn layout(&self, area: LayoutRect) -> Vec<(Id, LayoutRect)> {
36 self.layout(area)
37 }
38
39 fn insert_leaf(
40 &mut self,
41 target: Id,
42 insert: Id,
43 position: InsertPosition,
44 area: LayoutRect,
45 constraints: &SizeConstraints,
46 ) -> Result<(), LayoutError> {
47 self.insert_leaf(target, insert, position, area, constraints)
48 }
49
50 fn remove_leaf(&mut self, id: Id) -> Result<(), LayoutError> {
51 self.remove_leaf(id)
52 }
53
54 fn all_leaf_ids(&self) -> Vec<Id> {
55 self.all_leaf_ids()
56 }
57
58 fn subtree_any(&self, predicate: &mut impl FnMut(Id) -> bool) -> bool {
59 self.subtree_any(predicate)
60 }
61
62 fn apply_drag(
63 &mut self,
64 area: LayoutRect,
65 path: &[usize],
66 _index: usize,
67 orientation: Orientation,
68 delta: i16,
69 constraints: &SizeConstraints,
70 ) -> bool {
71 let bool_path: Vec<bool> = path.iter().map(|&i| i != 0).collect();
72 self.apply_drag(area, &bool_path, orientation, delta, constraints)
73 }
74}
75
76impl<Id: Copy + Eq + Ord> LayoutEngine<Id> for NaryNode<Id> {
77 fn layout(&self, area: LayoutRect) -> Vec<(Id, LayoutRect)> {
78 self.layout(area)
79 }
80
81 fn insert_leaf(
82 &mut self,
83 target: Id,
84 insert: Id,
85 position: InsertPosition,
86 area: LayoutRect,
87 constraints: &SizeConstraints,
88 ) -> Result<(), LayoutError> {
89 self.insert_leaf(target, insert, position, area, constraints)
90 }
91
92 fn remove_leaf(&mut self, id: Id) -> Result<(), LayoutError> {
93 self.remove_leaf(id)
94 }
95
96 fn all_leaf_ids(&self) -> Vec<Id> {
97 self.all_leaf_ids()
98 }
99
100 fn subtree_any(&self, predicate: &mut impl FnMut(Id) -> bool) -> bool {
101 self.subtree_any(predicate)
102 }
103
104 fn apply_drag(
105 &mut self,
106 area: LayoutRect,
107 path: &[usize],
108 index: usize,
109 orientation: Orientation,
110 delta: i16,
111 constraints: &SizeConstraints,
112 ) -> bool {
113 self.apply_drag(area, path, index, orientation, delta, constraints)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::node::BspNode;
121 use crate::node::NaryNode;
122
123 #[test]
124 fn layout_engine_trait_works_with_bsp_node() {
125 let mut node: BspNode<u8> = BspNode::leaf(1);
126 let constraints = SizeConstraints {
127 min_width: 2,
128 min_height: 2,
129 };
130 let area = LayoutRect {
131 x: 0,
132 y: 0,
133 width: 80,
134 height: 24,
135 };
136
137 assert!(
138 LayoutEngine::insert_leaf(&mut node, 1, 2, InsertPosition::Right, area, &constraints)
139 .is_ok()
140 );
141
142 let regions = LayoutEngine::layout(&node, area);
143 assert_eq!(regions.len(), 2);
144 }
145
146 #[test]
147 fn layout_engine_trait_works_with_nary_node() {
148 let mut node: NaryNode<u8> = NaryNode::leaf(1);
149 let constraints = SizeConstraints {
150 min_width: 2,
151 min_height: 2,
152 };
153 let area = LayoutRect {
154 x: 0,
155 y: 0,
156 width: 80,
157 height: 24,
158 };
159
160 assert!(
161 LayoutEngine::insert_leaf(&mut node, 1, 2, InsertPosition::Right, area, &constraints)
162 .is_ok()
163 );
164
165 let regions = LayoutEngine::layout(&node, area);
166 assert_eq!(regions.len(), 2);
167 }
168}