123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- use crate::geom::{IRect, IVector};
- use super::{cache::LayoutCacheKey, Layer, LayoutNode, LayoutNodeAccess, NodeBehaviour, NodeState};
- pub fn recalculate(node: &dyn LayoutNodeAccess) {
- if let NodeBehaviour::Fixed { rect } = node.behaviour() {
- let layer = Layer::default();
- // propagate relayout flags up to the root
- node.cache.propagate_relayouts();
- arrangement_pass(None, node, layer);
- println!("invoking layout_step with rect {rect:?}");
- node.child_arrangement.layout_step(node, rect);
- } else {
- log::warn!("Layout root node does not have Fixed mode");
- }
- }
- fn arrangement_pass(parent: Option<LayoutCacheKey>, node: &dyn LayoutNodeAccess, layer: Layer) {
- println!(
- "arrangement_pass({:?}, {:?}, {:?})",
- parent, node.cache_key, 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);
- if node.cache.has_state_for(node.cache_key) {
- node.cache.with_state(node.cache_key, |ns| {
- ns.net_policy = (wpol, hpol);
- });
- } else {
- node.cache.store(
- node.cache_key,
- parent,
- NodeState {
- needs_update: false,
- net_policy: (wpol, hpol),
- rect: None,
- layer,
- children: vec![],
- },
- );
- }
- }
- #[cfg(test)]
- mod test {
- use std::ops::{Deref, DerefMut};
- use crate::{
- geom::{IPoint, IRect, IVector},
- layout::{
- cache::LayoutCache, ChildArrangement, LayoutChildIter, LayoutNode, LayoutNodeAccess,
- NodeBehaviour, SizePolicy,
- },
- };
- use super::recalculate;
- struct LayoutTree {
- children: Vec<LayoutTree>,
- node: LayoutNode,
- }
- impl Deref for LayoutTree {
- type Target = LayoutNode;
- fn deref(&self) -> &Self::Target {
- &self.node
- }
- }
- impl DerefMut for LayoutTree {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.node
- }
- }
- impl<'l> LayoutNodeAccess for LayoutTree {
- fn child(&self, ndx: usize) -> Option<&dyn LayoutNodeAccess> {
- self.children.get(ndx).map(|v| v as &dyn LayoutNodeAccess)
- }
- fn child_iter(&self) -> crate::layout::LayoutChildIter {
- LayoutChildIter::new(self)
- }
- fn 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.set_height_policy(SizePolicy {
- minimum: 1,
- desired: 1,
- slack_weight: 1,
- });
- lt
- },
- {
- let mut lt = LayoutTree {
- children: vec![],
- node: LayoutNode::new(cache.clone()),
- };
- lt.set_height_policy(SizePolicy {
- minimum: 2,
- desired: 3,
- slack_weight: 0,
- });
- lt
- },
- ],
- node: LayoutNode::new(cache.clone()),
- };
- root.set_behaviour(NodeBehaviour::Fixed {
- rect: IRect::new_from_size(IPoint { x: 1, y: 1 }, IVector { x: 2, y: 5 }),
- });
- root.child_arrangement = ChildArrangement::Column;
- recalculate(&root);
- // check that final rects match expectations
- assert_eq!(
- cache.with_state(root.cache_key, |ns| ns.rect).flatten(),
- Some(IRect::new_from_size(
- IPoint { x: 1, y: 1 },
- IVector { x: 2, y: 5 }
- ))
- );
- assert_eq!(
- cache
- .with_state(root.children[0].cache_key, |ns| ns.rect)
- .flatten(),
- Some(IRect::new_from_size(
- IPoint { x: 1, y: 1 },
- IVector { x: 2, y: 2 }
- ))
- );
- println!("cache: {:?}", cache);
- }
- }
|