use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use super::algorithm::{Algorithm, Flexbox, Node};
use crate::geometry::{Dimension, Point, Size};
use crate::styles::ViewStyle;
#[derive(Clone)]
pub enum MeasureFunc {
Boxed(Arc<dyn Fn(Size<Dimension<f32>>) -> Size<f32> + Send + Sync>),
}
impl std::fmt::Debug for MeasureFunc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("MeasureFunc").finish()
}
}
pub struct Layout {
pub origin: Point<f32>,
pub size: Size<f32>,
}
pub struct LayoutTree {
flexbox: Flexbox,
parents: HashMap<Node, Node>,
roots: Vec<Node>,
}
impl LayoutTree {
pub fn new() -> LayoutTree {
LayoutTree {
flexbox: Flexbox::new(),
parents: HashMap::new(),
roots: vec![],
}
}
pub fn flexbox(&self) -> &Flexbox {
&self.flexbox
}
pub fn flexbox_mut(&mut self) -> &mut Flexbox {
&mut self.flexbox
}
pub fn roots(&self) -> &[Node] {
self.roots.as_slice()
}
pub fn roots_mut(&mut self) -> &mut Vec<Node> {
&mut self.roots
}
pub fn add_child(&mut self, parent: Node, child: Node) {
self.parents.insert(child, parent);
self.flexbox.add_child(parent, child);
}
pub fn remove(&mut self, node: Node) {
if let Some(parent) = self.parents.remove(&node) {
self.flexbox.remove_child(parent, node);
}
assert_eq!(self.flexbox.child_count(node), 0);
self.flexbox.remove(node);
}
pub fn recompute_roots(&mut self) {
for node in self.roots().to_owned() {
let size = self.flexbox().layout(node).size;
self.flexbox_mut().compute_layout(
node,
Size {
width: Dimension::Points(size.width),
height: Dimension::Points(size.height),
},
);
}
}
}
#[derive(Clone)]
pub struct LayoutNode {
layouter: Arc<RwLock<LayoutTree>>,
node: Node,
}
impl LayoutNode {
pub fn new(layouter: Arc<RwLock<LayoutTree>>) -> LayoutNode {
let node = layouter
.write()
.unwrap()
.flexbox_mut()
.new_node(Default::default(), &[]);
LayoutNode { layouter, node }
}
pub fn leaf(layouter: Arc<RwLock<LayoutTree>>) -> LayoutNode {
let node = layouter.write().unwrap().flexbox_mut().new_leaf(
Default::default(),
MeasureFunc::Boxed(Arc::new(|_| Size {
width: 0.0,
height: 0.0,
})),
);
LayoutNode { layouter, node }
}
pub fn layouter(&self) -> &Arc<RwLock<LayoutTree>> {
&self.layouter
}
pub fn node(&self) -> Node {
self.node
}
pub fn set_measure(&self, measure: MeasureFunc) {
self.layouter
.write()
.unwrap()
.flexbox_mut()
.set_measure(self.node, measure);
}
pub fn set_style(&self, style: ViewStyle) {
self.layouter
.write()
.unwrap()
.flexbox_mut()
.set_style(self.node, style)
}
pub fn compute(&mut self, size: Option<(f32, f32)>) {
let size = match size {
Some((width, height)) => Size {
width: Dimension::Points(width),
height: Dimension::Points(height),
},
None => Size {
width: Dimension::Undefined,
height: Dimension::Undefined,
},
};
self.layouter
.write()
.unwrap()
.flexbox_mut()
.compute_layout(self.node, size);
}
pub fn current(&self) -> Layout {
self.layouter.read().unwrap().flexbox().layout(self.node)
}
}