summaryrefslogtreecommitdiffstats
path: root/native/src/layout
diff options
context:
space:
mode:
Diffstat (limited to 'native/src/layout')
-rw-r--r--native/src/layout/debugger.rs26
-rw-r--r--native/src/layout/flex.rs28
-rw-r--r--native/src/layout/limits.rs12
-rw-r--r--native/src/layout/node.rs17
4 files changed, 64 insertions, 19 deletions
diff --git a/native/src/layout/debugger.rs b/native/src/layout/debugger.rs
new file mode 100644
index 00000000..e4b21609
--- /dev/null
+++ b/native/src/layout/debugger.rs
@@ -0,0 +1,26 @@
+use crate::{Color, Layout, Point, Renderer, Widget};
+
+/// A renderer able to graphically explain a [`Layout`].
+///
+/// [`Layout`]: struct.Layout.html
+pub trait Debugger: Renderer {
+ /// Explains the [`Layout`] of an [`Element`] for debugging purposes.
+ ///
+ /// This will be called when [`Element::explain`] has been used. It should
+ /// _explain_ the given [`Layout`] graphically.
+ ///
+ /// A common approach consists in recursively rendering the bounds of the
+ /// [`Layout`] and its children.
+ ///
+ /// [`Layout`]: struct.Layout.html
+ /// [`Element`]: ../struct.Element.html
+ /// [`Element::explain`]: ../struct.Element.html#method.explain
+ fn explain<Message>(
+ &mut self,
+ defaults: &Self::Defaults,
+ widget: &dyn Widget<Message, Self>,
+ layout: Layout<'_>,
+ cursor_position: Point,
+ color: Color,
+ ) -> Self::Output;
+}
diff --git a/native/src/layout/flex.rs b/native/src/layout/flex.rs
index bc90553e..2f65f1c1 100644
--- a/native/src/layout/flex.rs
+++ b/native/src/layout/flex.rs
@@ -18,7 +18,7 @@
// limitations under the License.
use crate::{
layout::{Limits, Node},
- Align, Element, Size,
+ Align, Element, Point, Size,
};
/// The main axis of a flex layout.
@@ -73,11 +73,12 @@ where
Renderer: crate::Renderer,
{
let limits = limits.pad(padding);
+ let total_spacing = spacing * items.len().saturating_sub(1) as f32;
+ let max_cross = axis.cross(limits.max());
- let mut total_non_fill =
- spacing as f32 * (items.len() as i32 - 1).max(0) as f32;
let mut fill_sum = 0;
- let mut cross = axis.cross(limits.min());
+ let mut cross = axis.cross(limits.min()).max(axis.cross(limits.fill()));
+ let mut available = axis.main(limits.max()) - total_spacing;
let mut nodes: Vec<Node> = Vec::with_capacity(items.len());
nodes.resize(items.len(), Node::default());
@@ -90,12 +91,15 @@ where
.fill_factor();
if fill_factor == 0 {
- let child_limits = Limits::new(Size::ZERO, limits.max());
+ let (max_width, max_height) = axis.pack(available, max_cross);
+
+ let child_limits =
+ Limits::new(Size::ZERO, Size::new(max_width, max_height));
let layout = child.layout(renderer, &child_limits);
let size = layout.size();
- total_non_fill += axis.main(size);
+ available -= axis.main(size);
cross = cross.max(axis.cross(size));
nodes[i] = layout;
@@ -104,8 +108,7 @@ where
}
}
- let available = axis.main(limits.max());
- let remaining = (available - total_non_fill).max(0.0);
+ let remaining = available.max(0.0);
for (i, child) in items.iter().enumerate() {
let fill_factor = match axis {
@@ -149,8 +152,7 @@ where
let (x, y) = axis.pack(main, padding);
- node.bounds.x = x;
- node.bounds.y = y;
+ node.move_to(Point::new(x, y));
match axis {
Axis::Horizontal => {
@@ -166,13 +168,11 @@ where
main += axis.main(size);
}
- let (width, height) = axis.pack(main, cross);
+ let (width, height) = axis.pack(main - padding, cross);
let size = limits.resolve(Size::new(width, height));
- let (padding_x, padding_y) = axis.pack(padding, padding * 2.0);
-
Node::with_children(
- Size::new(size.width + padding_x, size.height + padding_y),
+ Size::new(size.width + padding * 2.0, size.height + padding * 2.0),
nodes,
)
}
diff --git a/native/src/layout/limits.rs b/native/src/layout/limits.rs
index 740417d4..664c881a 100644
--- a/native/src/layout/limits.rs
+++ b/native/src/layout/limits.rs
@@ -44,6 +44,14 @@ impl Limits {
self.max
}
+ /// Returns the fill [`Size`] of the [`Limits`].
+ ///
+ /// [`Limits`]: struct.Limits.html
+ /// [`Size`]: ../struct.Size.html
+ pub fn fill(&self) -> Size {
+ self.fill
+ }
+
/// Applies a width constraint to the current [`Limits`].
///
/// [`Limits`]: struct.Limits.html
@@ -52,7 +60,7 @@ impl Limits {
Length::Shrink => {
self.fill.width = self.min.width;
}
- Length::Fill => {
+ Length::Fill | Length::FillPortion(_) => {
self.fill.width = self.fill.width.min(self.max.width);
}
Length::Units(units) => {
@@ -76,7 +84,7 @@ impl Limits {
Length::Shrink => {
self.fill.height = self.min.height;
}
- Length::Fill => {
+ Length::Fill | Length::FillPortion(_) => {
self.fill.height = self.fill.height.min(self.max.height);
}
Length::Units(units) => {
diff --git a/native/src/layout/node.rs b/native/src/layout/node.rs
index acfd33bd..a265c46a 100644
--- a/native/src/layout/node.rs
+++ b/native/src/layout/node.rs
@@ -1,9 +1,9 @@
-use crate::{Align, Rectangle, Size};
+use crate::{Align, Point, Rectangle, Size};
/// The bounds of an element and its children.
#[derive(Debug, Clone, Default)]
pub struct Node {
- pub(crate) bounds: Rectangle,
+ bounds: Rectangle,
children: Vec<Node>,
}
@@ -54,7 +54,10 @@ impl Node {
&self.children
}
- pub(crate) fn align(
+ /// Aligns the [`Node`] in the given space.
+ ///
+ /// [`Node`]: struct.Node.html
+ pub fn align(
&mut self,
horizontal_alignment: Align,
vertical_alignment: Align,
@@ -80,4 +83,12 @@ impl Node {
}
}
}
+
+ /// Moves the [`Node`] to the given position.
+ ///
+ /// [`Node`]: struct.Node.html
+ pub fn move_to(&mut self, position: Point) {
+ self.bounds.x = position.x;
+ self.bounds.y = position.y;
+ }
}