mirror of
https://github.com/penpot/penpot.git
synced 2025-08-07 14:38:33 +02:00
Merge pull request #6794 from penpot/alotor-wasm-fix-grid-fr
🐛 Fix problem with fr allocation
This commit is contained in:
commit
29016cef49
2 changed files with 93 additions and 72 deletions
|
@ -467,15 +467,15 @@
|
||||||
row-tracks (set-flex-multi-span parent row-tracks children-map shape-cells bounds objects :row)
|
row-tracks (set-flex-multi-span parent row-tracks children-map shape-cells bounds objects :row)
|
||||||
|
|
||||||
;; Once auto sizes have been calculated we get calculate the `fr` unit with the remainining size and adjust the size
|
;; Once auto sizes have been calculated we get calculate the `fr` unit with the remainining size and adjust the size
|
||||||
free-column-space (max 0 (- bound-width (+ column-total-size-nofr column-total-gap)))
|
fr-column-space (max 0 (- bound-width (+ column-total-size-nofr column-total-gap)))
|
||||||
free-row-space (max 0 (- bound-height (+ row-total-size-nofr row-total-gap)))
|
fr-row-space (max 0 (- bound-height (+ row-total-size-nofr row-total-gap)))
|
||||||
|
|
||||||
;; Get the minimum values for fr's
|
;; Get the minimum values for fr's
|
||||||
min-column-fr (min-fr-value column-tracks)
|
min-column-fr (min-fr-value column-tracks)
|
||||||
min-row-fr (min-fr-value row-tracks)
|
min-row-fr (min-fr-value row-tracks)
|
||||||
|
|
||||||
column-fr (if auto-width? min-column-fr (mth/finite (/ free-column-space column-frs) 0))
|
column-fr (if auto-width? min-column-fr (mth/finite (/ fr-column-space column-frs) 0))
|
||||||
row-fr (if auto-height? min-row-fr (mth/finite (/ free-row-space row-frs) 0))
|
row-fr (if auto-height? min-row-fr (mth/finite (/ fr-row-space row-frs) 0))
|
||||||
|
|
||||||
column-tracks (set-fr-value column-tracks column-fr auto-width?)
|
column-tracks (set-fr-value column-tracks column-fr auto-width?)
|
||||||
row-tracks (set-fr-value row-tracks row-fr auto-height?)
|
row-tracks (set-fr-value row-tracks row-fr auto-height?)
|
||||||
|
@ -484,13 +484,13 @@
|
||||||
column-total-size (tracks-total-size column-tracks)
|
column-total-size (tracks-total-size column-tracks)
|
||||||
row-total-size (tracks-total-size row-tracks)
|
row-total-size (tracks-total-size row-tracks)
|
||||||
|
|
||||||
free-column-space (max 0 (if auto-width? 0 (- bound-width (+ column-total-size column-total-gap))))
|
auto-column-space (max 0 (if auto-width? 0 (- bound-width (+ column-total-size column-total-gap))))
|
||||||
free-row-space (max 0 (if auto-height? 0 (- bound-height (+ row-total-size row-total-gap))))
|
auto-row-space (max 0 (if auto-height? 0 (- bound-height (+ row-total-size row-total-gap))))
|
||||||
column-autos (tracks-total-autos column-tracks)
|
column-autos (tracks-total-autos column-tracks)
|
||||||
row-autos (tracks-total-autos row-tracks)
|
row-autos (tracks-total-autos row-tracks)
|
||||||
|
|
||||||
column-add-auto (/ free-column-space column-autos)
|
column-add-auto (/ auto-column-space column-autos)
|
||||||
row-add-auto (/ free-row-space row-autos)
|
row-add-auto (/ auto-row-space row-autos)
|
||||||
|
|
||||||
column-tracks (cond-> column-tracks
|
column-tracks (cond-> column-tracks
|
||||||
(= :stretch (:layout-justify-content parent))
|
(= :stretch (:layout-justify-content parent))
|
||||||
|
|
|
@ -51,6 +51,12 @@ pub fn calculate_tracks(
|
||||||
layout_bounds.height() - layout_data.padding_top - layout_data.padding_bottom
|
layout_bounds.height() - layout_data.padding_top - layout_data.padding_bottom
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let auto_layout = if is_column {
|
||||||
|
shape.is_layout_horizontal_auto()
|
||||||
|
} else {
|
||||||
|
shape.is_layout_vertical_auto()
|
||||||
|
};
|
||||||
|
|
||||||
let grid_tracks = if is_column {
|
let grid_tracks = if is_column {
|
||||||
&grid_data.columns
|
&grid_data.columns
|
||||||
} else {
|
} else {
|
||||||
|
@ -60,8 +66,14 @@ pub fn calculate_tracks(
|
||||||
let mut tracks = init_tracks(grid_tracks, layout_size);
|
let mut tracks = init_tracks(grid_tracks, layout_size);
|
||||||
set_auto_base_size(is_column, &mut tracks, cells, shapes, bounds);
|
set_auto_base_size(is_column, &mut tracks, cells, shapes, bounds);
|
||||||
set_auto_multi_span(is_column, &mut tracks, cells, shapes, bounds);
|
set_auto_multi_span(is_column, &mut tracks, cells, shapes, bounds);
|
||||||
set_flex_multi_span(is_column, &mut tracks, cells, shapes, bounds);
|
set_flex_multi_span(is_column, layout_data, &mut tracks, cells, shapes, bounds);
|
||||||
set_fr_value(is_column, shape, layout_data, &mut tracks, layout_size);
|
set_fr_value(
|
||||||
|
is_column,
|
||||||
|
layout_data,
|
||||||
|
&mut tracks,
|
||||||
|
layout_size,
|
||||||
|
auto_layout,
|
||||||
|
);
|
||||||
stretch_tracks(is_column, shape, layout_data, &mut tracks, layout_size);
|
stretch_tracks(is_column, shape, layout_data, &mut tracks, layout_size);
|
||||||
assign_anchors(is_column, layout_data, layout_bounds, &mut tracks);
|
assign_anchors(is_column, layout_data, layout_bounds, &mut tracks);
|
||||||
tracks
|
tracks
|
||||||
|
@ -230,6 +242,7 @@ fn set_auto_multi_span(
|
||||||
// Adjust multi-spaned cells with flex columns
|
// Adjust multi-spaned cells with flex columns
|
||||||
fn set_flex_multi_span(
|
fn set_flex_multi_span(
|
||||||
column: bool,
|
column: bool,
|
||||||
|
layout_data: &LayoutData,
|
||||||
tracks: &mut [TrackData],
|
tracks: &mut [TrackData],
|
||||||
cells: &[GridCell],
|
cells: &[GridCell],
|
||||||
shapes: &HashMap<Uuid, &mut Shape>,
|
shapes: &HashMap<Uuid, &mut Shape>,
|
||||||
|
@ -257,6 +270,12 @@ fn set_flex_multi_span(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let gap_value = if column {
|
||||||
|
layout_data.column_gap
|
||||||
|
} else {
|
||||||
|
layout_data.row_gap
|
||||||
|
};
|
||||||
|
|
||||||
// Retrieve the value that we need to distribute and the number of frs
|
// Retrieve the value that we need to distribute and the number of frs
|
||||||
for cell in selected_cells {
|
for cell in selected_cells {
|
||||||
let Some(child) = cell.shape.and_then(|id| shapes.get(&id)) else {
|
let Some(child) = cell.shape.and_then(|id| shapes.get(&id)) else {
|
||||||
|
@ -264,25 +283,20 @@ fn set_flex_multi_span(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retrieve the value we need to distribute (fixed cell size minus gaps)
|
// Retrieve the value we need to distribute (fixed cell size minus gaps)
|
||||||
let mut dist = min_size(column, child, bounds);
|
|
||||||
let mut num_flex = 0.0;
|
|
||||||
let mut num_auto = 0;
|
|
||||||
|
|
||||||
let (start, end) = track_index(column, cell);
|
let (start, end) = track_index(column, cell);
|
||||||
|
let gaps = (end - start - 1) as f32 * gap_value;
|
||||||
|
let mut dist = min_size(column, child, bounds) - gaps;
|
||||||
|
let mut num_flex = 0.0;
|
||||||
|
|
||||||
// Distribute the size between the tracks that already have a set value
|
// Distribute the size between the tracks that already have a set value
|
||||||
for track in tracks[start..end].iter() {
|
for track in tracks[start..end].iter() {
|
||||||
dist -= track.size;
|
|
||||||
|
|
||||||
match track.track_type {
|
match track.track_type {
|
||||||
GridTrackType::Flex => {
|
GridTrackType::Flex => {
|
||||||
num_flex += track.value;
|
num_flex += track.value;
|
||||||
num_auto += 1;
|
|
||||||
}
|
}
|
||||||
GridTrackType::Auto => {
|
_ => {
|
||||||
num_auto += 1;
|
dist -= track.size;
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,37 +305,15 @@ fn set_flex_multi_span(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rest = dist / num_flex;
|
let alloc = dist / num_flex;
|
||||||
|
|
||||||
// Distribute the space between flex tracks in proportion to the division
|
// Distribute the space between flex tracks in proportion to the division
|
||||||
for track in tracks[start..end].iter_mut() {
|
for track in tracks[start..end].iter_mut() {
|
||||||
if track.track_type == GridTrackType::Flex {
|
if track.track_type == GridTrackType::Flex {
|
||||||
let new_size = f32::min(track.size + rest, track.max_size);
|
let new_size = alloc.clamp(track.size, track.max_size);
|
||||||
let aloc = new_size - track.size;
|
let aloc = new_size - track.size;
|
||||||
dist -= aloc;
|
dist -= aloc;
|
||||||
track.size += aloc;
|
track.size = new_size;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Distribute the space between auto tracks if any
|
|
||||||
while dist > MIN_SIZE && num_auto > 0 {
|
|
||||||
let rest = dist / num_auto as f32;
|
|
||||||
|
|
||||||
for track in tracks[start..end].iter_mut() {
|
|
||||||
if track.track_type == GridTrackType::Auto
|
|
||||||
|| track.track_type == GridTrackType::Flex
|
|
||||||
{
|
|
||||||
let new_size = if track.size + rest < track.max_size {
|
|
||||||
track.size + rest
|
|
||||||
} else {
|
|
||||||
num_auto -= 1;
|
|
||||||
track.max_size
|
|
||||||
};
|
|
||||||
|
|
||||||
let aloc = new_size - track.size;
|
|
||||||
dist -= aloc;
|
|
||||||
track.size += aloc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,10 +322,10 @@ fn set_flex_multi_span(
|
||||||
// Calculate the `fr` unit and adjust the size
|
// Calculate the `fr` unit and adjust the size
|
||||||
fn set_fr_value(
|
fn set_fr_value(
|
||||||
column: bool,
|
column: bool,
|
||||||
shape: &Shape,
|
|
||||||
layout_data: &LayoutData,
|
layout_data: &LayoutData,
|
||||||
tracks: &mut [TrackData],
|
tracks: &mut [TrackData],
|
||||||
layout_size: f32,
|
layout_size: f32,
|
||||||
|
auto_layout: bool,
|
||||||
) {
|
) {
|
||||||
let tot_gap: f32 = if column {
|
let tot_gap: f32 = if column {
|
||||||
layout_data.column_gap * (tracks.len() as f32 - 1.0)
|
layout_data.column_gap * (tracks.len() as f32 - 1.0)
|
||||||
|
@ -341,41 +333,65 @@ fn set_fr_value(
|
||||||
layout_data.row_gap * (tracks.len() as f32 - 1.0)
|
layout_data.row_gap * (tracks.len() as f32 - 1.0)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Total size already used
|
let mut tot_size_nofr = tot_gap;
|
||||||
let tot_size: f32 = tracks
|
let mut tot_frs = 0.0;
|
||||||
.iter()
|
let mut cur_fr_value = 0.0;
|
||||||
.filter(|t| t.track_type != GridTrackType::Flex)
|
|
||||||
.map(|t| t.size)
|
|
||||||
.sum::<f32>()
|
|
||||||
+ tot_gap;
|
|
||||||
|
|
||||||
let tot_frs: f32 = tracks
|
for t in tracks.iter() {
|
||||||
.iter()
|
if t.track_type == GridTrackType::Flex {
|
||||||
.filter(|t| t.track_type == GridTrackType::Flex)
|
tot_frs += t.value;
|
||||||
.map(|t| t.value)
|
cur_fr_value = f32::max(t.size / t.value, cur_fr_value);
|
||||||
.sum();
|
} else {
|
||||||
|
tot_size_nofr += t.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let cur_fr_size = tracks
|
let fr_space = f32::max(0.0, layout_size - tot_size_nofr);
|
||||||
.iter()
|
|
||||||
.filter(|t| t.track_type == GridTrackType::Flex)
|
|
||||||
.map(|t| t.size / t.value)
|
|
||||||
.reduce(f32::max)
|
|
||||||
.unwrap_or(0.0);
|
|
||||||
|
|
||||||
// Divide the space between FRS
|
let mut fr_value = if auto_layout {
|
||||||
let fr = if column && shape.is_layout_horizontal_auto()
|
// If auto_layout we assign the max fr
|
||||||
|| !column && shape.is_layout_vertical_auto()
|
cur_fr_value
|
||||||
{
|
|
||||||
cur_fr_size
|
|
||||||
} else {
|
} else {
|
||||||
f32::max(cur_fr_size, (layout_size - tot_size) / tot_frs)
|
fr_space / tot_frs
|
||||||
};
|
};
|
||||||
|
|
||||||
// Assign the space to the FRS
|
if !auto_layout {
|
||||||
|
loop {
|
||||||
|
// While there is still tracks that can take more size
|
||||||
|
let mut pending = fr_space;
|
||||||
|
let mut free_frs = 0;
|
||||||
|
|
||||||
|
for t in tracks.iter() {
|
||||||
|
if t.track_type == GridTrackType::Flex {
|
||||||
|
// Use the current fr size
|
||||||
|
let current = t.value * fr_value;
|
||||||
|
|
||||||
|
if t.size > current {
|
||||||
|
// If it's not enough psace to allocate, this is full. Cannot grow anymore.
|
||||||
|
pending -= t.size;
|
||||||
|
} else {
|
||||||
|
// Otherwise, this track can still grow
|
||||||
|
free_frs += 1;
|
||||||
|
pending -= current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We finish when we cannot reduce the tracks more or we've allocated all
|
||||||
|
// the space
|
||||||
|
if free_frs == 0 || pending >= 0.0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fr_value += pending / free_frs as f32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign the fr_value to the flex tracks
|
||||||
tracks
|
tracks
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.filter(|t| t.track_type == GridTrackType::Flex)
|
.filter(|t| t.track_type == GridTrackType::Flex)
|
||||||
.for_each(|t| t.size = f32::min(fr * t.value, t.max_size));
|
.for_each(|t| t.size = (fr_value * t.value).clamp(t.size, t.max_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stretch_tracks(
|
fn stretch_tracks(
|
||||||
|
@ -411,6 +427,11 @@ fn stretch_tracks(
|
||||||
.count() as f32;
|
.count() as f32;
|
||||||
|
|
||||||
let free_space = layout_size - tot_size;
|
let free_space = layout_size - tot_size;
|
||||||
|
|
||||||
|
if free_space <= 0.0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let add_size = free_space / auto_tracks;
|
let add_size = free_space / auto_tracks;
|
||||||
|
|
||||||
// Assign the space to the FRS
|
// Assign the space to the FRS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue