|
@@ -1,7 +1,7 @@
|
|
|
use std::{ops::Deref, rc::Rc};
|
|
|
|
|
|
use cache::{Layer, LayoutCacheKey, NodeState};
|
|
|
-use kahlo::math::{PixelBox, PixelRect};
|
|
|
+use kahlo::math::{PixelBox, PixelSideOffsets};
|
|
|
|
|
|
mod arr;
|
|
|
mod cache;
|
|
@@ -10,8 +10,9 @@ mod calc;
|
|
|
pub use cache::LayoutCache;
|
|
|
pub use calc::recalculate;
|
|
|
|
|
|
-/// Sizing policy for a layout dimension
|
|
|
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
|
|
|
+/// Sizing policy for a layout dimension. Defaults to no minimum or desired size and a low-weighted
|
|
|
+/// desire to take up slack space.
|
|
|
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
|
|
pub struct SizePolicy {
|
|
|
/// The minimum number of pixels required along this dimension to avoid overlap and other
|
|
|
/// issues.
|
|
@@ -23,6 +24,16 @@ pub struct SizePolicy {
|
|
|
pub slack_weight: usize,
|
|
|
}
|
|
|
|
|
|
+impl Default for SizePolicy {
|
|
|
+ fn default() -> Self {
|
|
|
+ Self {
|
|
|
+ minimum: 0,
|
|
|
+ desired: 0,
|
|
|
+ slack_weight: 1,
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
impl SizePolicy {
|
|
|
pub fn expands(weight: usize) -> Self {
|
|
|
Self {
|
|
@@ -60,28 +71,30 @@ impl std::ops::Add<Self> for SizePolicy {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
|
|
|
-pub struct BoxMeasure {
|
|
|
- pub left: usize,
|
|
|
- pub right: usize,
|
|
|
- pub top: usize,
|
|
|
- pub bottom: usize,
|
|
|
+/// How to horizontally align a smaller node inside a larger node.
|
|
|
+#[derive(Clone, Copy, PartialEq, Debug)]
|
|
|
+pub enum HorizontalAlignment {
|
|
|
+ Left,
|
|
|
+ Centre,
|
|
|
+ Right,
|
|
|
}
|
|
|
|
|
|
-impl From<usize> for BoxMeasure {
|
|
|
- fn from(value: usize) -> Self {
|
|
|
- Self::new_from_value(value)
|
|
|
+impl Default for HorizontalAlignment {
|
|
|
+ fn default() -> Self {
|
|
|
+ Self::Centre
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl BoxMeasure {
|
|
|
- pub fn new_from_value(value: usize) -> Self {
|
|
|
- Self {
|
|
|
- left: value,
|
|
|
- right: value,
|
|
|
- top: value,
|
|
|
- bottom: value,
|
|
|
- }
|
|
|
+#[derive(Clone, Copy, PartialEq, Debug)]
|
|
|
+pub enum VerticalAlignment {
|
|
|
+ Top,
|
|
|
+ Centre,
|
|
|
+ Bottom,
|
|
|
+}
|
|
|
+
|
|
|
+impl Default for VerticalAlignment {
|
|
|
+ fn default() -> Self {
|
|
|
+ Self::Centre
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -89,7 +102,7 @@ impl BoxMeasure {
|
|
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
|
|
pub enum NodeBehaviour {
|
|
|
/// A fixed rendering area, probably a root node.
|
|
|
- Fixed { rect: PixelRect },
|
|
|
+ Fixed { area: PixelBox },
|
|
|
/// An ordinary box sitting inside another node, hinting its size and receiving a final
|
|
|
/// size assignment from its parent.
|
|
|
Element,
|
|
@@ -136,9 +149,10 @@ pub struct LayoutNode {
|
|
|
child_arrangement: ChildArrangement,
|
|
|
width_policy: SizePolicy,
|
|
|
height_policy: SizePolicy,
|
|
|
+ halign: HorizontalAlignment,
|
|
|
+ valign: VerticalAlignment,
|
|
|
|
|
|
- padding: BoxMeasure,
|
|
|
- margin: BoxMeasure,
|
|
|
+ margin: PixelSideOffsets,
|
|
|
}
|
|
|
|
|
|
impl std::fmt::Debug for LayoutNode {
|
|
@@ -150,7 +164,6 @@ impl std::fmt::Debug for LayoutNode {
|
|
|
.field("child_arrangement", &self.child_arrangement)
|
|
|
.field("width_policy", &self.width_policy)
|
|
|
.field("height_policy", &self.height_policy)
|
|
|
- .field("padding", &self.padding)
|
|
|
.field("margin", &self.margin)
|
|
|
.finish()
|
|
|
}
|
|
@@ -168,8 +181,9 @@ impl LayoutNode {
|
|
|
child_arrangement: ChildArrangement::Column,
|
|
|
width_policy: SizePolicy::default(),
|
|
|
height_policy: SizePolicy::default(),
|
|
|
- padding: 0.into(),
|
|
|
- margin: 0.into(),
|
|
|
+ halign: HorizontalAlignment::default(),
|
|
|
+ valign: VerticalAlignment::default(),
|
|
|
+ margin: PixelSideOffsets::new_all_same(0),
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -177,14 +191,15 @@ impl LayoutNode {
|
|
|
self.cache.update_queue.borrow_mut().push(self.cache_key);
|
|
|
}
|
|
|
|
|
|
- pub fn cached_rect(&self) -> Option<PixelRect> {
|
|
|
+ pub fn render_area(&self) -> Option<PixelBox> {
|
|
|
self.cache
|
|
|
- .with_state(self.cache_key, |ns| ns.rect)
|
|
|
+ .with_state(self.cache_key, |ns| ns.area)
|
|
|
.flatten()
|
|
|
+ .map(|pb| pb.inner_box(self.margin))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// accessors
|
|
|
+/// Accessors
|
|
|
impl LayoutNode {
|
|
|
pub fn label(&self) -> Option<&str> {
|
|
|
self.label.as_ref().map(String::as_str)
|
|
@@ -228,16 +243,25 @@ impl LayoutNode {
|
|
|
self
|
|
|
}
|
|
|
|
|
|
- pub fn padding(&self) -> BoxMeasure {
|
|
|
- self.padding
|
|
|
+ pub fn halign(&self) -> HorizontalAlignment {
|
|
|
+ self.halign
|
|
|
}
|
|
|
- pub fn padding_mut(&mut self) -> &mut BoxMeasure {
|
|
|
- &mut self.padding
|
|
|
+ pub fn set_halign(&mut self, halign: HorizontalAlignment) -> &mut Self {
|
|
|
+ self.halign = halign;
|
|
|
+ self
|
|
|
}
|
|
|
- pub fn margin(&self) -> BoxMeasure {
|
|
|
+ pub fn valign(&self) -> VerticalAlignment {
|
|
|
+ self.valign
|
|
|
+ }
|
|
|
+ pub fn set_valign(&mut self, valign: VerticalAlignment) -> &mut Self {
|
|
|
+ self.valign = valign;
|
|
|
+ self
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn margin(&self) -> PixelSideOffsets {
|
|
|
self.margin
|
|
|
}
|
|
|
- pub fn margin_mut(&mut self) -> &mut BoxMeasure {
|
|
|
+ pub fn margin_mut(&mut self) -> &mut PixelSideOffsets {
|
|
|
&mut self.margin
|
|
|
}
|
|
|
}
|
|
@@ -252,7 +276,8 @@ impl Clone for LayoutNode {
|
|
|
child_arrangement: self.child_arrangement.clone(),
|
|
|
width_policy: self.width_policy,
|
|
|
height_policy: self.height_policy,
|
|
|
- padding: self.padding,
|
|
|
+ halign: self.halign,
|
|
|
+ valign: self.valign,
|
|
|
margin: self.margin,
|
|
|
}
|
|
|
}
|
|
@@ -287,7 +312,7 @@ fn dump_node_tree_helper(lna: LayoutNodeAccess, indent: usize, out: &mut String)
|
|
|
);
|
|
|
out.push_str(ind.as_str());
|
|
|
out.push_str(" ");
|
|
|
- out.push_str(format!("cached rect: {:?}\n", lna.cached_rect()).as_str());
|
|
|
+ out.push_str(format!("render area: {:?}\n", lna.render_area()).as_str());
|
|
|
|
|
|
for child in lna.child_iter() {
|
|
|
dump_node_tree_helper(child, indent + 1, out);
|
|
@@ -326,6 +351,7 @@ impl<'l> Iterator for LayoutChildIter<'l> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/// Wrapper struct to access a [`LayoutNodeContainer`].
|
|
|
#[derive(Clone, Copy)]
|
|
|
pub struct LayoutNodeAccess<'l> {
|
|
|
lnc: &'l dyn LayoutNodeContainer,
|