polyhorn_ui/layout/
tree.rs1use std::collections::HashMap;
2use std::sync::{Arc, RwLock};
3
4use super::algorithm::{Algorithm, Flexbox, Node};
5use crate::geometry::{Dimension, Point, Size};
6use crate::styles::ViewStyle;
7
8#[derive(Clone)]
11pub enum MeasureFunc {
12 Boxed(Arc<dyn Fn(Size<Dimension<f32>>) -> Size<f32> + Send + Sync>),
14}
15
16impl std::fmt::Debug for MeasureFunc {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_tuple("MeasureFunc").finish()
19 }
20}
21
22pub struct Layout {
24 pub origin: Point<f32>,
26
27 pub size: Size<f32>,
29}
30
31pub struct LayoutTree {
34 flexbox: Flexbox,
35 parents: HashMap<Node, Node>,
36 roots: Vec<Node>,
37}
38
39impl LayoutTree {
40 pub fn new() -> LayoutTree {
42 LayoutTree {
43 flexbox: Flexbox::new(),
44 parents: HashMap::new(),
45 roots: vec![],
46 }
47 }
48
49 pub fn flexbox(&self) -> &Flexbox {
51 &self.flexbox
52 }
53
54 pub fn flexbox_mut(&mut self) -> &mut Flexbox {
56 &mut self.flexbox
57 }
58
59 pub fn roots(&self) -> &[Node] {
61 self.roots.as_slice()
62 }
63
64 pub fn roots_mut(&mut self) -> &mut Vec<Node> {
66 &mut self.roots
67 }
68
69 pub fn add_child(&mut self, parent: Node, child: Node) {
73 self.parents.insert(child, parent);
74 self.flexbox.add_child(parent, child);
75 }
76
77 pub fn remove(&mut self, node: Node) {
81 if let Some(parent) = self.parents.remove(&node) {
82 self.flexbox.remove_child(parent, node);
83 }
84
85 assert_eq!(self.flexbox.child_count(node), 0);
86
87 self.flexbox.remove(node);
88 }
89
90 pub fn recompute_roots(&mut self) {
92 for node in self.roots().to_owned() {
93 let size = self.flexbox().layout(node).size;
94
95 self.flexbox_mut().compute_layout(
96 node,
97 Size {
98 width: Dimension::Points(size.width),
99 height: Dimension::Points(size.height),
100 },
101 );
102 }
103 }
104}
105
106#[derive(Clone)]
108pub struct LayoutNode {
109 layouter: Arc<RwLock<LayoutTree>>,
110 node: Node,
111}
112
113impl LayoutNode {
114 pub fn new(layouter: Arc<RwLock<LayoutTree>>) -> LayoutNode {
116 let node = layouter
117 .write()
118 .unwrap()
119 .flexbox_mut()
120 .new_node(Default::default(), &[]);
121
122 LayoutNode { layouter, node }
123 }
124
125 pub fn leaf(layouter: Arc<RwLock<LayoutTree>>) -> LayoutNode {
127 let node = layouter.write().unwrap().flexbox_mut().new_leaf(
128 Default::default(),
129 MeasureFunc::Boxed(Arc::new(|_| Size {
130 width: 0.0,
131 height: 0.0,
132 })),
133 );
134
135 LayoutNode { layouter, node }
136 }
137
138 pub fn layouter(&self) -> &Arc<RwLock<LayoutTree>> {
140 &self.layouter
141 }
142
143 pub fn node(&self) -> Node {
145 self.node
146 }
147
148 pub fn set_measure(&self, measure: MeasureFunc) {
151 self.layouter
152 .write()
153 .unwrap()
154 .flexbox_mut()
155 .set_measure(self.node, measure);
156 }
157
158 pub fn set_style(&self, style: ViewStyle) {
161 self.layouter
162 .write()
163 .unwrap()
164 .flexbox_mut()
165 .set_style(self.node, style)
166 }
167
168 pub fn compute(&mut self, size: Option<(f32, f32)>) {
170 let size = match size {
171 Some((width, height)) => Size {
172 width: Dimension::Points(width),
173 height: Dimension::Points(height),
174 },
175 None => Size {
176 width: Dimension::Undefined,
177 height: Dimension::Undefined,
178 },
179 };
180
181 self.layouter
182 .write()
183 .unwrap()
184 .flexbox_mut()
185 .compute_layout(self.node, size);
186 }
187
188 pub fn current(&self) -> Layout {
190 self.layouter.read().unwrap().flexbox().layout(self.node)
191 }
192}