Improvements on flex layout positioning

This commit is contained in:
alonso.torres 2025-03-18 16:08:21 +01:00
parent 4c12af957c
commit a830c27ceb
6 changed files with 175 additions and 72 deletions

View file

@ -1,5 +1,4 @@
use std::collections::{HashMap, HashSet, VecDeque};
mod common;
mod constraints;
mod flex_layout;
@ -9,7 +8,7 @@ use uuid::Uuid;
use common::GetBounds;
use crate::math::{Bounds, Matrix, Point};
use crate::math::{identitish, Bounds, Matrix, Point};
use crate::shapes::{
ConstraintH, ConstraintV, Frame, Group, Layout, Modifier, Shape, TransformEntry, Type,
};
@ -23,7 +22,7 @@ fn propagate_children(
transform: Matrix,
bounds: &HashMap<Uuid, Bounds>,
) -> VecDeque<Modifier> {
if shape.children.len() == 0 {
if shape.children.len() == 0 || identitish(transform) {
return VecDeque::new();
}
@ -39,7 +38,13 @@ fn propagate_children(
let constraint_h = match &shape.shape_type {
Type::Frame(Frame {
layout: Some(_), ..
}) => ConstraintH::Left,
}) => {
if child.is_absolute() {
child.constraint_h(ConstraintH::Left)
} else {
ConstraintH::Left
}
}
Type::Frame(_) => child.constraint_h(ConstraintH::Left),
_ => child.constraint_h(ConstraintH::Scale),
};
@ -47,7 +52,13 @@ fn propagate_children(
let constraint_v = match &shape.shape_type {
Type::Frame(Frame {
layout: Some(_), ..
}) => ConstraintV::Top,
}) => {
if child.is_absolute() {
child.constraint_v(ConstraintV::Top)
} else {
ConstraintV::Top
}
}
Type::Frame(_) => child.constraint_v(ConstraintV::Top),
_ => child.constraint_v(ConstraintV::Scale),
};
@ -108,7 +119,6 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
while let Some(modifier) = entries.pop_front() {
match modifier {
Modifier::Transform(entry) => {
// println!("Transform {}", entry.id);
let Some(shape) = state.shapes.get(&entry.id) else {
continue;
};
@ -154,8 +164,22 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
layout: Some(_), ..
}) => {
if !reflown.contains(&id) {
layout_reflows.push(id);
reflown.insert(id);
let mut skip_reflow = false;
if shape.is_layout_horizontal_fill()
|| shape.is_layout_vertical_fill()
{
if let Some(parent_id) = shape.parent_id {
if !reflown.contains(&parent_id) {
// If this is a fill layout but the parent has not been reflown yet
// we wait for the next iteration for reflow
skip_reflow = true;
}
}
}
if !skip_reflow {
layout_reflows.push(id);
}
}
}
Type::Group(Group { masked: true }) => {
@ -196,6 +220,10 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
}
for id in layout_reflows.iter() {
if reflown.contains(&id) {
continue;
}
let Some(shape) = state.shapes.get(&id) else {
continue;
};
@ -203,10 +231,14 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
let Type::Frame(frame_data) = &shape.shape_type else {
continue;
};
if let Some(Layout::FlexLayout(layout_data, flex_data)) = &frame_data.layout {
let mut children =
flex_layout::reflow_flex_layout(shape, layout_data, flex_data, shapes, &bounds);
let mut children = flex_layout::reflow_flex_layout(
shape,
layout_data,
flex_data,
shapes,
&mut bounds,
);
entries.append(&mut children);
}
@ -215,6 +247,7 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
grid_layout::reflow_grid_layout(shape, layout_data, grid_data, shapes, &bounds);
entries.append(&mut children);
}
reflown.insert(*id);
}
layout_reflows = Vec::new();
}