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 /// Given the cursor in the region, how much space is available
/// for the next widget? /// 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, // NOTE: in normal top-down layout the cursor has moved below the current max_rect,
// but the available shouldn't be negative. // 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 { match self.main_dir {
Direction::LeftToRight => { 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 => { 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 => { 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 => { 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. /// 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() { if available_size.x < child_size.x && max_rect.left() < cursor.left() {
// New row // New row
let new_row_height = cursor.height().max(child_size.y); 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( cursor = Rect::from_min_max(
pos2(max_rect.left(), cursor.bottom() + spacing.y), pos2(max_rect.left(), new_top),
pos2(INFINITY, cursor.bottom() + spacing.y + new_row_height), pos2(INFINITY, new_top + new_row_height),
); );
max_rect.max.y = max_rect.max.y.max(cursor.max.y); 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() { if available_size.x < child_size.x && cursor.right() < max_rect.right() {
// New row // New row
let new_row_height = cursor.height().max(child_size.y); 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( cursor = Rect::from_min_max(
pos2(-INFINITY, cursor.bottom() + spacing.y), pos2(-INFINITY, new_top),
pos2( pos2(max_rect.right(), new_top + new_row_height),
max_rect.right(),
cursor.bottom() + spacing.y + new_row_height,
),
); );
max_rect.max.y = max_rect.max.y.max(cursor.max.y); max_rect.max.y = max_rect.max.y.max(cursor.max.y);
} }
@ -601,7 +625,7 @@ impl Layout {
item_spacing: Vec2, item_spacing: Vec2,
) { ) {
if self.main_wrap { if self.main_wrap {
if cursor.intersects(frame_rect) { if cursor.intersects(frame_rect.shrink(1.0)) {
// make row/column larger if necessary // make row/column larger if necessary
*cursor = cursor.union(frame_rect); *cursor = cursor.union(frame_rect);
} else { } else {

View file

@ -249,9 +249,10 @@ impl Widget for Label {
&& ui.layout().main_dir() == Direction::LeftToRight && ui.layout().main_dir() == Direction::LeftToRight
&& ui.layout().main_wrap() && 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: // then continue on the line below! This will take some extra work:
let cursor = ui.cursor();
let max_width = ui.available_width(); let max_width = ui.available_width();
let first_row_indentation = max_width - ui.available_size_before_wrap().x; let first_row_indentation = max_width - ui.available_size_before_wrap().x;
@ -263,25 +264,30 @@ impl Widget for Label {
max_width, 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"); 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; // Center first row within the cursor:
if let Some(row) = galley.rows.get(1) { let dy = 0.5 * (cursor.height() - galley.rows[0].height());
// We could be sharing the first row with e.g. a button, that is higher than text. galley.rows[0].translate_y(dy);
// So we need to compensate for that:
if pos.y + row.y_min < ui.min_rect().bottom() { // We could be sharing the first row with e.g. a button which is higher than text.
y_translation = ui.min_rect().bottom() - row.y_min - pos.y; // So we need to compensate for that:
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) { let rect = galley.rows[0].rect().translate(vec2(pos.x, pos.y));
row.y_min += y_translation; let mut response = ui.allocate_rect(rect, sense);
row.y_max += y_translation; for row in galley.rows.iter().skip(1) {
let rect = row.rect().translate(vec2(pos.x, pos.y)); let rect = row.rect().translate(vec2(pos.x, pos.y));
response |= ui.allocate_rect(rect, sense); response |= ui.allocate_rect(rect, sense);
} }

View file

@ -115,6 +115,12 @@ impl Row {
pub fn x_offset(&self, column: usize) -> f32 { pub fn x_offset(&self, column: usize) -> f32 {
self.x_offsets[column.min(self.x_offsets.len() - 1)] 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 { impl Galley {