|
@@ -1,3 +1,11 @@
|
|
|
+//! Layout calculations for the widget tree.
|
|
|
+//!
|
|
|
+//! Layout calculations are done in two passes:
|
|
|
+//! - **Arrangement**: computes minimum sizes, net size policies, and records parent/child relationships between
|
|
|
+//! nodes.
|
|
|
+//! - **Layout**: given minimum sizes and net size policies from the arrangement step, computes
|
|
|
+//! exact pixel values for positions and sizes.
|
|
|
+
|
|
|
use std::{ops::Deref, rc::Rc};
|
|
|
|
|
|
use cache::{Layer, LayoutCacheKey, NodeState};
|
|
@@ -35,7 +43,7 @@ impl Default for SizePolicy {
|
|
|
}
|
|
|
|
|
|
impl SizePolicy {
|
|
|
- pub fn expands(weight: usize) -> Self {
|
|
|
+ pub fn expanding(weight: usize) -> Self {
|
|
|
Self {
|
|
|
minimum: 0,
|
|
|
desired: 0,
|
|
@@ -43,6 +51,14 @@ impl SizePolicy {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ pub fn fixed(size: usize) -> Self {
|
|
|
+ Self {
|
|
|
+ minimum: size,
|
|
|
+ desired: size,
|
|
|
+ slack_weight: 0,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
pub fn max(self, rhs: SizePolicy) -> SizePolicy {
|
|
|
Self {
|
|
|
minimum: self.minimum.max(rhs.minimum),
|
|
@@ -142,16 +158,25 @@ impl Deref for ChildArrangement {
|
|
|
}
|
|
|
|
|
|
pub struct LayoutNode {
|
|
|
+ /// Human-readable label for making layout tree dumps easier to read.
|
|
|
label: Option<String>,
|
|
|
+ /// Unique identifier for this LayoutNode
|
|
|
cache_key: LayoutCacheKey,
|
|
|
+ /// Reference to the global layout item cache.
|
|
|
cache: Rc<LayoutCache>,
|
|
|
+ /// Layout behaviour, or how this node behaves with respect to its parent.
|
|
|
behaviour: NodeBehaviour,
|
|
|
+ /// Child arrangement, or how this node arranges its children.
|
|
|
child_arrangement: ChildArrangement,
|
|
|
+ /// Width policy: how does this widget take up horizontal space?
|
|
|
width_policy: SizePolicy,
|
|
|
+ /// Height policy: how does this widget take up vertical space?
|
|
|
height_policy: SizePolicy,
|
|
|
+ /// Horizontal alignment of children inside this node.
|
|
|
halign: HorizontalAlignment,
|
|
|
+ /// Vertical alignment of children inside this node.
|
|
|
valign: VerticalAlignment,
|
|
|
-
|
|
|
+ /// User-exposed margins, or spacing between the parent and the render area of this node.
|
|
|
margin: PixelSideOffsets,
|
|
|
}
|
|
|
|
|
@@ -191,6 +216,16 @@ impl LayoutNode {
|
|
|
self.cache.update_queue.borrow_mut().push(self.cache_key);
|
|
|
}
|
|
|
|
|
|
+ pub fn relayout_tree(&self) {
|
|
|
+ let mut to_mark : Vec<LayoutCacheKey> = vec![self.cache_key];
|
|
|
+ while let Some(next) = to_mark.pop() {
|
|
|
+ self.cache.with_state(next, |ns| {
|
|
|
+ ns.needs_update = true;
|
|
|
+ to_mark.extend(ns.children.iter());
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
pub fn render_area(&self) -> Option<PixelBox> {
|
|
|
self.cache
|
|
|
.with_state(self.cache_key, |ns| ns.area)
|
|
@@ -198,6 +233,7 @@ impl LayoutNode {
|
|
|
.map(|pb| pb.inner_box(self.margin))
|
|
|
}
|
|
|
|
|
|
+ /// Checks if node needs to be rerendered, clearing the flag if so.
|
|
|
pub fn render_check(&self) -> bool {
|
|
|
self.cache.with_state(self.cache_key, |ns| {
|
|
|
let ret = ns.needs_render;
|
|
@@ -224,8 +260,10 @@ impl LayoutNode {
|
|
|
self.behaviour
|
|
|
}
|
|
|
pub fn set_behaviour(&mut self, mode: NodeBehaviour) -> &mut Self {
|
|
|
- self.behaviour = mode;
|
|
|
- self.relayout();
|
|
|
+ if self.behaviour != mode {
|
|
|
+ self.behaviour = mode;
|
|
|
+ self.relayout();
|
|
|
+ }
|
|
|
self
|
|
|
}
|
|
|
|
|
@@ -311,14 +349,16 @@ fn dump_node_tree_helper(lna: LayoutNodeAccess, indent: usize, out: &mut String)
|
|
|
});
|
|
|
out.push_str(
|
|
|
format!(
|
|
|
- ") [wpol: {}/{}/{} hpol: {}/{}/{} behaviour: {:?}]\n",
|
|
|
+ ") [wpol: {}/{}/{} hpol: {}/{}/{} behaviour: {:?} upd: {:?} rend: {:?}]\n",
|
|
|
lna.width_policy.minimum,
|
|
|
lna.width_policy.desired,
|
|
|
lna.width_policy.slack_weight,
|
|
|
lna.height_policy.minimum,
|
|
|
lna.height_policy.desired,
|
|
|
lna.height_policy.slack_weight,
|
|
|
- lna.behaviour
|
|
|
+ lna.behaviour,
|
|
|
+ lna.cache.with_state(lna.cache_key, |v| v.needs_update),
|
|
|
+ lna.cache.with_state(lna.cache_key, |v| v.needs_render),
|
|
|
)
|
|
|
.as_str(),
|
|
|
);
|