From e232264b5352c7facdd710c8633da5382f004e97 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 21 Mar 2021 10:33:10 +0100 Subject: [PATCH] Add Visuals::debug_widgets to debug layouting by hovering widgets --- egui/src/layout.rs | 31 +++++++++++++++++++++---------- egui/src/placer.rs | 3 ++- egui/src/style.rs | 5 +++++ egui/src/ui.rs | 37 +++++++++++++++++++++++++++++++------ 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/egui/src/layout.rs b/egui/src/layout.rs index 82203102..e93f9279 100644 --- a/egui/src/layout.rs +++ b/egui/src/layout.rs @@ -689,7 +689,8 @@ impl Layout { ) { use epaint::*; - let cursor = self.next_widget_position(region); + let cursor = region.cursor; + let next_pos = self.next_widget_position(region); let align; @@ -697,23 +698,33 @@ impl Layout { match self.main_dir { Direction::LeftToRight => { - painter.arrow(cursor, vec2(l, 0.0), stroke); - align = Align2::LEFT_TOP; + painter.line_segment([cursor.left_top(), cursor.left_bottom()], stroke); + painter.arrow(next_pos, vec2(l, 0.0), stroke); + align = Align2([Align::LEFT, self.vertical_align()]); } Direction::RightToLeft => { - painter.arrow(cursor, vec2(-l, 0.0), stroke); - align = Align2::RIGHT_TOP; + painter.line_segment([cursor.right_top(), cursor.right_bottom()], stroke); + painter.arrow(next_pos, vec2(-l, 0.0), stroke); + align = Align2([Align::RIGHT, self.vertical_align()]); } Direction::TopDown => { - painter.arrow(cursor, vec2(0.0, l), stroke); - align = Align2::LEFT_TOP; + painter.line_segment([cursor.left_top(), cursor.right_top()], stroke); + painter.arrow(next_pos, vec2(0.0, l), stroke); + align = Align2([self.horizontal_align(), Align::TOP]); } Direction::BottomUp => { - painter.arrow(cursor, vec2(0.0, -l), stroke); - align = Align2::LEFT_BOTTOM; + painter.line_segment([cursor.left_bottom(), cursor.right_bottom()], stroke); + painter.arrow(next_pos, vec2(0.0, -l), stroke); + align = Align2([self.horizontal_align(), Align::BOTTOM]); } } - painter.text(cursor, align, "cursor", TextStyle::Monospace, stroke.color); + painter.text( + next_pos, + align, + "cursor", + TextStyle::Monospace, + Color32::WHITE, + ); } } diff --git a/egui/src/placer.rs b/egui/src/placer.rs index babba0be..2500572d 100644 --- a/egui/src/placer.rs +++ b/egui/src/placer.rs @@ -164,6 +164,7 @@ impl Placer { item_spacing, ) } + self.region.expand_to_include_rect(frame_rect); // e.g. for centered layouts: pretend we used whole frame } @@ -233,7 +234,7 @@ impl Placer { impl Placer { pub(crate) fn debug_paint_cursor(&self, painter: &crate::Painter) { - let color = Color32::GREEN; + let color = Color32::GREEN.linear_multiply(0.5); let stroke = Stroke::new(2.0, color); if let Some(grid) = &self.grid { diff --git a/egui/src/style.rs b/egui/src/style.rs index 446cc3d1..9c723574 100644 --- a/egui/src/style.rs +++ b/egui/src/style.rs @@ -181,6 +181,8 @@ pub struct Visuals { // ----------------------------------------------- // Debug rendering: + /// however over widgets to see their rectangles + pub debug_widgets: bool, /// Show which widgets make their parent wider pub debug_expand_width: bool, /// Show which widgets make their parent higher @@ -340,6 +342,7 @@ impl Visuals { text_cursor_width: 2.0, text_cursor_preview: false, clip_rect_margin: 3.0, // should be at least half the size of the widest frame stroke + max WidgetVisuals::expansion + debug_widgets: false, debug_expand_width: false, debug_expand_height: false, debug_resize: false, @@ -652,6 +655,7 @@ impl Visuals { text_cursor_width, text_cursor_preview, clip_rect_margin, + debug_widgets, debug_expand_width, debug_expand_height, debug_resize, @@ -684,6 +688,7 @@ impl Visuals { ui.group(|ui| { ui.label("DEBUG:"); + ui.checkbox(debug_widgets, "Show widget bounds on hover"); ui.checkbox( debug_expand_width, "Show which widgets make their parent wider", diff --git a/egui/src/ui.rs b/egui/src/ui.rs index 548be78e..96afd660 100644 --- a/egui/src/ui.rs +++ b/egui/src/ui.rs @@ -599,6 +599,12 @@ impl Ui { let rect = self.allocate_space_impl(desired_size); + if self.visuals().debug_widgets && self.rect_contains_pointer(rect) { + let painter = self.ctx().debug_painter(); + painter.rect_stroke(rect, 4.0, (1.0, Color32::LIGHT_BLUE)); + self.placer.debug_paint_cursor(&painter); + } + let debug_expand_width = self.visuals().debug_expand_width; let debug_expand_height = self.visuals().debug_expand_height; @@ -649,7 +655,7 @@ impl Ui { /// /// Ignore the layout of the `Ui‘: just put my widget here! /// The layout cursor will advance to past this `rect`. - pub(crate) fn allocate_rect(&mut self, rect: Rect, sense: Sense) -> Response { + pub fn allocate_rect(&mut self, rect: Rect, sense: Sense) -> Response { let id = self.advance_cursor_after_rect(rect); self.interact(rect, id, sense) } @@ -658,6 +664,12 @@ impl Ui { let item_spacing = self.spacing().item_spacing; self.placer.advance_after_rects(rect, rect, item_spacing); + if self.visuals().debug_widgets && self.rect_contains_pointer(rect) { + let painter = self.ctx().debug_painter(); + painter.rect_stroke(rect, 4.0, (1.0, Color32::LIGHT_BLUE)); + self.placer.debug_paint_cursor(&painter); + } + self.next_auto_id = self.next_auto_id.wrapping_add(1); Id::new(self.next_auto_id) } @@ -684,6 +696,7 @@ impl Ui { desired_size: Vec2, add_contents: impl FnOnce(&mut Self) -> R, ) -> InnerResponse { + debug_assert!(desired_size.x >= 0.0 && desired_size.y >= 0.0); let item_spacing = self.spacing().item_spacing; let frame_rect = self.placer.next_space(desired_size, item_spacing); let child_rect = self.placer.justify_and_align(frame_rect, desired_size); @@ -692,11 +705,16 @@ impl Ui { let ret = add_contents(&mut child_ui); let final_child_rect = child_ui.min_rect(); - self.placer.advance_after_rects( - frame_rect.union(final_child_rect), - final_child_rect, - item_spacing, - ); + let final_frame = frame_rect.union(final_child_rect); + self.placer + .advance_after_rects(final_frame, final_child_rect, item_spacing); + + if self.visuals().debug_widgets && self.rect_contains_pointer(final_frame) { + let painter = self.ctx().debug_painter(); + painter.rect_stroke(frame_rect, 4.0, (1.0, Color32::LIGHT_BLUE)); + painter.rect_stroke(final_child_rect, 4.0, (1.0, Color32::LIGHT_BLUE)); + self.placer.debug_paint_cursor(&painter); + } let response = self.interact(final_child_rect, child_ui.id, Sense::hover()); InnerResponse::new(ret, response) @@ -1324,6 +1342,13 @@ impl Ui { let rect = child_ui.min_rect(); let item_spacing = self.spacing().item_spacing; self.placer.advance_after_rects(rect, rect, item_spacing); + + if self.visuals().debug_widgets && self.rect_contains_pointer(rect) { + let painter = self.ctx().debug_painter(); + painter.rect_stroke(rect, 4.0, (1.0, Color32::LIGHT_BLUE)); + self.placer.debug_paint_cursor(&painter); + } + InnerResponse::new(inner, self.interact(rect, child_ui.id, Sense::hover())) }