calc.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. use crate::geom::{IRect, IVector};
  2. use super::{cache::LayoutCacheKey, Layer, LayoutNode, LayoutNodeAccess, NodeBehaviour, NodeState};
  3. pub fn recalculate(node: &dyn LayoutNodeAccess) {
  4. if let NodeBehaviour::Fixed { rect } = node.behaviour() {
  5. let layer = Layer::default();
  6. // propagate relayout flags up to the root
  7. node.cache.propagate_relayouts();
  8. arrangement_pass(None, node, layer);
  9. println!("invoking layout_step with rect {rect:?}");
  10. node.child_arrangement.layout_step(node, rect);
  11. } else {
  12. log::warn!("Layout root node does not have Fixed mode");
  13. }
  14. }
  15. fn arrangement_pass(parent: Option<LayoutCacheKey>, node: &dyn LayoutNodeAccess, layer: Layer) {
  16. println!(
  17. "arrangement_pass({:?}, {:?}, {:?})",
  18. parent, node.cache_key, layer
  19. );
  20. // early-out check
  21. if node.cache.with_state(node.cache_key, |st| st.needs_update) == Some(false) {
  22. return;
  23. }
  24. for child in node.child_iter() {
  25. arrangement_pass(Some(node.cache_key), child, layer.nest());
  26. }
  27. // construct net size policy
  28. let child_policies = node
  29. .child_iter()
  30. .map(|child| {
  31. node.cache
  32. .with_state(child.cache_key, |s| s.net_policy)
  33. .unwrap()
  34. })
  35. .collect::<Vec<_>>();
  36. let (wpol, hpol) = node.child_arrangement.arrange_step(node, child_policies);
  37. if node.cache.has_state_for(node.cache_key) {
  38. node.cache.with_state(node.cache_key, |ns| {
  39. ns.net_policy = (wpol, hpol);
  40. });
  41. } else {
  42. node.cache.store(
  43. node.cache_key,
  44. parent,
  45. NodeState {
  46. needs_update: false,
  47. net_policy: (wpol, hpol),
  48. rect: None,
  49. layer,
  50. children: vec![],
  51. },
  52. );
  53. }
  54. }
  55. #[cfg(test)]
  56. mod test {
  57. use std::ops::{Deref, DerefMut};
  58. use crate::{
  59. geom::{IPoint, IRect, IVector},
  60. layout::{
  61. cache::LayoutCache, ChildArrangement, LayoutChildIter, LayoutNode, LayoutNodeAccess,
  62. NodeBehaviour, SizePolicy,
  63. },
  64. };
  65. use super::recalculate;
  66. struct LayoutTree {
  67. children: Vec<LayoutTree>,
  68. node: LayoutNode,
  69. }
  70. impl Deref for LayoutTree {
  71. type Target = LayoutNode;
  72. fn deref(&self) -> &Self::Target {
  73. &self.node
  74. }
  75. }
  76. impl DerefMut for LayoutTree {
  77. fn deref_mut(&mut self) -> &mut Self::Target {
  78. &mut self.node
  79. }
  80. }
  81. impl<'l> LayoutNodeAccess for LayoutTree {
  82. fn child(&self, ndx: usize) -> Option<&dyn LayoutNodeAccess> {
  83. self.children.get(ndx).map(|v| v as &dyn LayoutNodeAccess)
  84. }
  85. fn child_iter(&self) -> crate::layout::LayoutChildIter {
  86. LayoutChildIter::new(self)
  87. }
  88. fn child_count(&self) -> usize {
  89. self.children.len()
  90. }
  91. }
  92. #[test]
  93. fn simple_test() {
  94. let cache = LayoutCache::new();
  95. let mut root = LayoutTree {
  96. children: vec![
  97. {
  98. let mut lt = LayoutTree {
  99. children: vec![],
  100. node: LayoutNode::new(cache.clone()),
  101. };
  102. lt.set_height_policy(SizePolicy {
  103. minimum: 1,
  104. desired: 1,
  105. slack_weight: 1,
  106. });
  107. lt
  108. },
  109. {
  110. let mut lt = LayoutTree {
  111. children: vec![],
  112. node: LayoutNode::new(cache.clone()),
  113. };
  114. lt.set_height_policy(SizePolicy {
  115. minimum: 2,
  116. desired: 3,
  117. slack_weight: 0,
  118. });
  119. lt
  120. },
  121. ],
  122. node: LayoutNode::new(cache.clone()),
  123. };
  124. root.set_behaviour(NodeBehaviour::Fixed {
  125. rect: IRect::new_from_size(IPoint { x: 1, y: 1 }, IVector { x: 2, y: 5 }),
  126. });
  127. root.child_arrangement = ChildArrangement::Column;
  128. recalculate(&root);
  129. // check that final rects match expectations
  130. assert_eq!(
  131. cache.with_state(root.cache_key, |ns| ns.rect).flatten(),
  132. Some(IRect::new_from_size(
  133. IPoint { x: 1, y: 1 },
  134. IVector { x: 2, y: 5 }
  135. ))
  136. );
  137. assert_eq!(
  138. cache
  139. .with_state(root.children[0].cache_key, |ns| ns.rect)
  140. .flatten(),
  141. Some(IRect::new_from_size(
  142. IPoint { x: 1, y: 1 },
  143. IVector { x: 2, y: 2 }
  144. ))
  145. );
  146. println!("cache: {:?}", cache);
  147. }
  148. }