From 6dd41982ba97c42253f8e3fce06fd9869731622b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 25 Apr 2020 23:07:03 +0200 Subject: [PATCH] Expand Region when child overflows desired_rect --- emigui/README.md | 5 +++++ emigui/src/containers/resize.rs | 13 ++++++++++++ emigui/src/region.rs | 36 ++++++++++++++++++++------------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/emigui/README.md b/emigui/README.md index cd5d7b49..7c67167f 100644 --- a/emigui/README.md +++ b/emigui/README.md @@ -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 diff --git a/emigui/src/containers/resize.rs b/emigui/src/containers/resize.rs index 2f5d0982..bb73c18a 100644 --- a/emigui/src/containers/resize.rs +++ b/emigui/src/containers/resize.rs @@ -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() }; diff --git a/emigui/src/region.rs b/emigui/src/region.rs index 6c5fb533..3aac818e 100644 --- a/emigui/src/region.rs +++ b/emigui/src/region.rs @@ -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)),