123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- use super::{cache::LayoutCacheKey, Layer, LayoutNodeAccess, NodeBehaviour, NodeState};
- pub fn recalculate(node: LayoutNodeAccess) {
- if let NodeBehaviour::Fixed { area } = node.behaviour() {
- let layer = Layer::default();
- // propagate relayout flags up to the root
- node.cache.propagate_relayouts();
- // propagate rerender flags down to the leaves
- node.cache.propagate_rerenders();
- arrangement_pass(None, node, layer);
- node.child_arrangement.layout_step(node, area);
- } else {
- log::warn!("Layout root node does not have Fixed mode");
- }
- }
- fn arrangement_pass(parent: Option<LayoutCacheKey>, node: LayoutNodeAccess, layer: Layer) {
- // early-out check
- if node.cache.with_state(node.cache_key, |st| st.needs_update) == Some(false) {
- return;
- }
- for child in node.child_iter() {
- arrangement_pass(Some(node.cache_key), child, layer.nest());
- }
- // construct net size policy
- let child_policies = node
- .child_iter()
- .map(|child| {
- node.cache
- .with_state(child.cache_key, |s| s.net_policy)
- .unwrap()
- })
- .collect::<Vec<_>>();
- let (wpol, hpol) = node.child_arrangement.arrange_step(node, child_policies);
- let child_ids = node.child_iter().map(|ch| ch.cache_key).collect();
- if node.cache.has_state_for(node.cache_key) {
- node.cache.with_state(node.cache_key, |ns| {
- ns.net_policy = (wpol, hpol);
- ns.children = child_ids;
- });
- } else {
- node.cache.store(
- node.cache_key,
- parent,
- NodeState {
- needs_update: false,
- needs_render: true,
- net_policy: (wpol, hpol),
- area: None,
- layer,
- children: child_ids,
- },
- );
- }
- }
- #[cfg(test)]
- mod test {
- use kahlo::math::{PixelBox, PixelPoint, PixelRect, PixelSize};
- use crate::layout::{
- cache::LayoutCache, ChildArrangement, LayoutNode, LayoutNodeAccess, LayoutNodeContainer,
- NodeBehaviour, SizePolicy,
- };
- use super::recalculate;
- struct LayoutTree {
- children: Vec<LayoutTree>,
- node: LayoutNode,
- }
- impl LayoutNodeContainer for LayoutTree {
- fn layout_node(&self) -> &LayoutNode {
- &self.node
- }
- fn layout_child(&self, ndx: usize) -> Option<LayoutNodeAccess<'_>> {
- self.children.get(ndx).map(|t| LayoutNodeAccess::new(t))
- }
- fn layout_child_count(&self) -> usize {
- self.children.len()
- }
- }
- #[test]
- fn simple_test() {
- let cache = LayoutCache::new();
- let mut root = LayoutTree {
- children: vec![
- {
- let mut lt = LayoutTree {
- children: vec![],
- node: LayoutNode::new(cache.clone()),
- };
- lt.node.set_height_policy(SizePolicy {
- minimum: 1,
- desired: 1,
- slack_weight: 1,
- });
- lt
- },
- {
- let mut lt = LayoutTree {
- children: vec![],
- node: LayoutNode::new(cache.clone()),
- };
- lt.node.set_height_policy(SizePolicy {
- minimum: 2,
- desired: 3,
- slack_weight: 0,
- });
- lt
- },
- ],
- node: LayoutNode::new(cache.clone()),
- };
- root.node.set_behaviour(NodeBehaviour::Fixed {
- area: PixelBox::from_origin_and_size(PixelPoint::new(1, 1), PixelSize::new(2, 5)),
- });
- root.node.child_arrangement = ChildArrangement::Column;
- recalculate(LayoutNodeAccess::new(&root));
- println!("cache: {:?}", cache);
- // check that final rects match expectations
- assert_eq!(
- cache
- .with_state(root.node.cache_key, |ns| ns.area)
- .flatten(),
- Some(PixelBox::from_origin_and_size(
- PixelPoint::new(1, 1),
- PixelSize::new(2, 5)
- ))
- );
- assert_eq!(
- cache
- .with_state(root.children[0].node.cache_key, |ns| ns.area)
- .flatten(),
- Some(PixelBox::from_origin_and_size(
- PixelPoint::new(1, 1),
- PixelSize::new(2, 2)
- ))
- );
- }
- }
|