Bug-fixes related to recent layout rewrite

This commit is contained in:
Emil Ernerfeldt 2021-03-21 14:31:55 +01:00
parent e232264b53
commit e20e3baa98
3 changed files with 64 additions and 28 deletions

View file

@ -395,26 +395,49 @@ impl Layout {
/// Given the cursor in the region, how much space is available
/// for the next widget?
fn available_from_cursor_max_rect(&self, cursor: Rect, mut max_rect: Rect) -> Rect {
fn available_from_cursor_max_rect(&self, cursor: Rect, max_rect: Rect) -> Rect {
// NOTE: in normal top-down layout the cursor has moved below the current max_rect,
// but the available shouldn't be negative.
// ALSO: with wrapping layouts, cursor jumps to new row before expanding max_rect
let mut avail = max_rect;
match self.main_dir {
Direction::LeftToRight => {
max_rect.max.x = max_rect.max.x.max(cursor.min.x);
avail.min.x = cursor.min.x;
avail.max.x = avail.max.x.max(cursor.min.x);
if self.main_wrap {
avail.min.y = cursor.min.y;
avail.max.y = cursor.max.y;
}
}
Direction::RightToLeft => {
max_rect.min.x = max_rect.min.x.min(cursor.max.x);
avail.max.x = cursor.max.x;
avail.min.x = avail.min.x.min(cursor.max.x);
if self.main_wrap {
avail.min.y = cursor.min.y;
avail.max.y = cursor.max.y;
}
}
Direction::TopDown => {
max_rect.max.y = max_rect.max.y.max(cursor.min.y);
avail.min.y = cursor.min.y;
avail.max.y = avail.max.y.max(cursor.min.y);
if self.main_wrap {
avail.min.x = cursor.min.x;
avail.max.x = cursor.max.x;
}
}
Direction::BottomUp => {
max_rect.min.y = max_rect.min.y.min(cursor.max.y);
avail.min.y = avail.min.y.min(cursor.max.y);
if self.main_wrap {
avail.min.x = cursor.min.x;
avail.max.x = cursor.max.x;
}
}
}
max_rect.intersect(cursor)
avail
}
/// Returns where to put the next widget that is of the given size.
@ -438,9 +461,11 @@ impl Layout {
if available_size.x < child_size.x && max_rect.left() < cursor.left() {
// New row
let new_row_height = cursor.height().max(child_size.y);
// let new_top = cursor.bottom() + spacing.y;
let new_top = min_rect.bottom() + spacing.y; // tighter packing
cursor = Rect::from_min_max(
pos2(max_rect.left(), cursor.bottom() + spacing.y),
pos2(INFINITY, cursor.bottom() + spacing.y + new_row_height),
pos2(max_rect.left(), new_top),
pos2(INFINITY, new_top + new_row_height),
);
max_rect.max.y = max_rect.max.y.max(cursor.max.y);
}
@ -449,12 +474,11 @@ impl Layout {
if available_size.x < child_size.x && cursor.right() < max_rect.right() {
// New row
let new_row_height = cursor.height().max(child_size.y);
// let new_top = cursor.bottom() + spacing.y;
let new_top = min_rect.bottom() + spacing.y; // tighter packing
cursor = Rect::from_min_max(
pos2(-INFINITY, cursor.bottom() + spacing.y),
pos2(
max_rect.right(),
cursor.bottom() + spacing.y + new_row_height,
),
pos2(-INFINITY, new_top),
pos2(max_rect.right(), new_top + new_row_height),
);
max_rect.max.y = max_rect.max.y.max(cursor.max.y);
}
@ -601,7 +625,7 @@ impl Layout {
item_spacing: Vec2,
) {
if self.main_wrap {
if cursor.intersects(frame_rect) {
if cursor.intersects(frame_rect.shrink(1.0)) {
// make row/column larger if necessary
*cursor = cursor.union(frame_rect);
} else {

View file

@ -249,9 +249,10 @@ impl Widget for Label {
&& ui.layout().main_dir() == Direction::LeftToRight
&& ui.layout().main_wrap()
{
// On a wrapping horizontal layout we want text to start after the last widget,
// On a wrapping horizontal layout we want text to start after the previous widget,
// then continue on the line below! This will take some extra work:
let cursor = ui.cursor();
let max_width = ui.available_width();
let first_row_indentation = max_width - ui.available_size_before_wrap().x;
@ -263,25 +264,30 @@ impl Widget for Label {
max_width,
);
let pos = pos2(ui.min_rect().left(), ui.cursor().top());
let pos = pos2(ui.max_rect().left(), ui.cursor().top());
assert!(!galley.rows.is_empty(), "Galleys are never empty");
let rect = galley.rows[0].rect().translate(vec2(pos.x, pos.y));
let id = ui.advance_cursor_after_rect(rect);
let mut response = ui.interact(rect, id, sense);
let mut y_translation = 0.0;
if let Some(row) = galley.rows.get(1) {
// We could be sharing the first row with e.g. a button, that is higher than text.
// Center first row within the cursor:
let dy = 0.5 * (cursor.height() - galley.rows[0].height());
galley.rows[0].translate_y(dy);
// We could be sharing the first row with e.g. a button which is higher than text.
// So we need to compensate for that:
if pos.y + row.y_min < ui.min_rect().bottom() {
y_translation = ui.min_rect().bottom() - row.y_min - pos.y;
if let Some(row) = galley.rows.get_mut(1) {
if pos.y + row.y_min < cursor.bottom() {
let y_translation = cursor.bottom() - row.y_min - pos.y;
if y_translation != 0.0 {
for row in galley.rows.iter_mut().skip(1) {
row.translate_y(y_translation);
}
}
}
}
for row in galley.rows.iter_mut().skip(1) {
row.y_min += y_translation;
row.y_max += y_translation;
let rect = galley.rows[0].rect().translate(vec2(pos.x, pos.y));
let mut response = ui.allocate_rect(rect, sense);
for row in galley.rows.iter().skip(1) {
let rect = row.rect().translate(vec2(pos.x, pos.y));
response |= ui.allocate_rect(rect, sense);
}

View file

@ -115,6 +115,12 @@ impl Row {
pub fn x_offset(&self, column: usize) -> f32 {
self.x_offsets[column.min(self.x_offsets.len() - 1)]
}
// Move down this much
pub fn translate_y(&mut self, dy: f32) {
self.y_min += dy;
self.y_max += dy;
}
}
impl Galley {