Expand Region when child overflows desired_rect

This commit is contained in:
Emil Ernerfeldt 2020-04-25 23:07:03 +02:00
parent 154424384f
commit 6dd41982ba
3 changed files with 40 additions and 14 deletions

View file

@ -48,6 +48,11 @@ Add extremely quick animations for some things, maybe 2-3 frames. For instance:
* [ ] Easily chain `Container`s without nested closures.
* e.g. `region.containers((Frame::new(), Resize::new(), ScrollArea::new()), |ui| ...)`
### Input
* [ ] Distinguish between clicks and drags
* [ ] Double-click
* [ ] Text
### Other
* [ ] Generalize Layout so we can create grid layouts etc
* [ ] Persist UI state in external storage

View file

@ -135,6 +135,7 @@ impl Resize {
};
state.size = state.size.clamp(self.min_size..=self.max_size);
let last_frame_size = state.size;
let position = region.cursor();
@ -148,6 +149,8 @@ impl Resize {
if corner_interact.active {
if let Some(mouse_pos) = region.input().mouse_pos {
// This is the desired size. We may not be able to achieve it.
state.size = mouse_pos - position + 0.5 * corner_interact.rect.size();
// We don't clamp to max size, because we want to be able to push against outer bounds.
// For instance, if we are inside a bigger Resize region, we want to expand that.
@ -161,6 +164,16 @@ impl Resize {
let inner_rect = Rect::from_min_size(region.cursor(), state.size);
let desired_size = {
let mut contents_region = region.child_region(inner_rect);
// If we pull the resize handle to shrink, we want to TRY to shink it.
// After laying out the contents, we might be much bigger.
// In those cases we don't want the clip_rect too be smaller, because
// then we will clip the contents of the region even thought the result gets larger. This is simply ugly!
contents_region.clip_rect.max = contents_region
.clip_rect
.max
.max(contents_region.clip_rect.min + last_frame_size);
add_contents(&mut contents_region);
contents_region.bounding_size()
};

View file

@ -29,8 +29,8 @@ pub struct Region {
/// and its max size (original available_space).
/// Note that the size may be infinite in one or both dimensions.
/// The widgets will TRY to fit within the rect,
/// but may overflow (which you will see in bounding_size).
pub(crate) desired_rect: Rect, // TODO: rename
/// but may overflow (which you will see in child_bounds).
pub(crate) desired_rect: Rect, // TODO: rename?
/// Bounding box of children.
/// Initially set to Rect::nothing().
@ -154,18 +154,26 @@ impl Region {
self.clip_rect
}
pub fn available_width(&self) -> f32 {
self.desired_rect.right() - self.cursor.x
}
pub fn available_height(&self) -> f32 {
self.desired_rect.bottom() - self.cursor.y
}
/// This how much more space we can take up without overflowing our parent.
/// Shrinks as cursor increments.
pub fn available_space(&self) -> Vec2 {
self.desired_rect.max - self.cursor
// self.desired_rect.max - self.cursor
// If a child doesn't fit in desired_rect, we have effectively expanded:
self.bottom_right() - self.cursor
}
pub fn bottom_right(&self) -> Pos2 {
// If a child doesn't fit in desired_rect, we have effectively expanded:
self.desired_rect.max.max(self.child_bounds.max)
}
pub fn available_width(&self) -> f32 {
self.available_space().x
}
pub fn available_height(&self) -> f32 {
self.available_space().y
}
/// Size of content
@ -212,7 +220,7 @@ impl Region {
"You can only indent vertical layouts"
);
let indent = vec2(self.style.indent, 0.0);
let child_rect = Rect::from_min_max(self.cursor + indent, self.desired_rect.max);
let child_rect = Rect::from_min_max(self.cursor + indent, self.bottom_right());
let mut child_region = Region {
id: self.id.with(id_source),
align: Align::Min,
@ -265,7 +273,7 @@ impl Region {
align: Align,
add_contents: impl FnOnce(&mut Region),
) {
let child_rect = Rect::from_min_max(self.cursor, self.desired_rect.max);
let child_rect = Rect::from_min_max(self.cursor, self.bottom_right());
let mut child_region = Region {
dir,
align,
@ -305,7 +313,7 @@ impl Region {
.map(|col_idx| {
let pos = self.cursor + vec2((col_idx as f32) * (column_width + padding), 0.0);
let child_rect =
Rect::from_min_max(pos, pos2(pos.x + column_width, self.desired_rect.bottom()));
Rect::from_min_max(pos, pos2(pos.x + column_width, self.bottom_right().y));
Region {
id: self.make_child_id(&("column", col_idx)),