Add Context::set_debug_on_hover and egui::trace!(ui)

This commit is contained in:
Emil Ernerfeldt 2021-05-27 19:30:08 +02:00
parent 8623909d82
commit 3b807e1ad6
13 changed files with 117 additions and 41 deletions

View file

@ -17,6 +17,7 @@ NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md) and [
* Add support for [cint](https://crates.io/crates/cint) under `cint` feature.
* Add features `extra_asserts` and `extra_debug_asserts` to enable additional checks.
* `TextEdit` now supports edits on a generic buffer using `TextBuffer`.
* Add `Context::set_debug_on_hover` and `egui::trace!(ui)`
### Changed 🔧
* Plot: Changed `Curve` to `Line`.

View file

@ -726,6 +726,20 @@ impl Context {
false
}
}
// ---------------------------------------------------------------------
/// Wether or not to debug widget layout on hover.
pub fn debug_on_hover(&self) -> bool {
self.memory().options.style.debug.debug_on_hover
}
/// Turn on/off wether or not to debug widget layout on hover.
pub fn set_debug_on_hover(&self, debug_on_hover: bool) {
let mut style = (*self.memory().options.style).clone();
style.debug.debug_on_hover = debug_on_hover;
self.set_style(style);
}
}
/// ## Animation
@ -780,12 +794,14 @@ impl Context {
.show(ui, |ui| {
let mut tessellation_options = self.memory().options.tessellation_options;
tessellation_options.ui(ui);
ui.vertical_centered(|ui| reset_button(ui, &mut tessellation_options));
self.memory().options.tessellation_options = tessellation_options;
});
}
pub fn inspection_ui(&self, ui: &mut Ui) {
use crate::containers::*;
crate::trace!(ui);
ui.label(format!("Is using pointer: {}", self.is_using_pointer()))
.on_hover_text(

View file

@ -731,14 +731,13 @@ impl Layout {
/// ## Debug stuff
impl Layout {
/// Shows where the next widget is going to be placed
pub(crate) fn debug_paint_cursor(
pub(crate) fn paint_text_at_cursor(
&self,
painter: &crate::Painter,
region: &Region,
stroke: epaint::Stroke,
painter: &crate::Painter,
text: impl ToString,
) {
use epaint::*;
let cursor = region.cursor;
let next_pos = self.next_widget_position(region);
@ -769,12 +768,6 @@ impl Layout {
}
}
painter.text(
next_pos,
align,
"cursor",
TextStyle::Monospace,
Color32::WHITE,
);
painter.debug_text(next_pos, align, stroke.color, text);
}
}

View file

@ -416,6 +416,31 @@ macro_rules! github_link_file {
// ----------------------------------------------------------------------------
/// Show debug info on hover when [`Context::set_debug_on_hover`] has been turned on.
///
/// ```
/// # let ui = &mut egui::Ui::__test();
/// // Turn on tracing of widgets
/// ui.ctx().set_debug_on_hover(true);
///
/// /// Show [`std::file`], [`std::line`] and argument on hover
/// egui::trace!(ui, "MyWindow");
///
/// /// Show [`std::file`] and [`std::line`] on hover
/// egui::trace!(ui);
/// ```
#[macro_export]
macro_rules! trace {
($ui:expr) => {{
$ui.trace_location(format!("{}:{}", file!(), line!()))
}};
($ui:expr, $label:expr) => {{
$ui.trace_location(format!("{} - {}:{}", $label, file!(), line!()))
}};
}
// ----------------------------------------------------------------------------
/// An assert that is only active when `egui` is compiled with the `egui_assert` feature
/// or with the `debug_egui_assert` feature in debug builds.
#[macro_export]

View file

@ -83,6 +83,7 @@ pub struct Options {
/// The default style for new `Ui`:s.
#[cfg_attr(feature = "persistence", serde(skip))]
pub(crate) style: std::sync::Arc<Style>,
/// Controls the tessellator.
pub(crate) tessellation_options: epaint::TessellationOptions,

View file

@ -187,20 +187,31 @@ impl Painter {
}
pub fn error(&self, pos: Pos2, text: impl std::fmt::Display) -> Rect {
let galley = self.fonts().layout_multiline(
TextStyle::Monospace,
format!("🔥 {}", text),
f32::INFINITY,
);
let rect = Rect::from_min_size(pos, galley.size);
self.debug_text(pos, Align2::LEFT_TOP, Color32::RED, format!("🔥 {}", text))
}
/// text with a background
#[allow(clippy::needless_pass_by_value)]
pub fn debug_text(
&self,
pos: Pos2,
anchor: Align2,
color: Color32,
text: impl ToString,
) -> Rect {
let galley = self
.fonts()
.layout_no_wrap(TextStyle::Monospace, text.to_string());
let rect = anchor.anchor_rect(Rect::from_min_size(pos, galley.size));
let frame_rect = rect.expand(2.0);
self.add(Shape::Rect {
rect: frame_rect,
corner_radius: 0.0,
fill: Color32::from_black_alpha(240),
stroke: Stroke::new(1.0, Color32::RED),
// stroke: Stroke::new(1.0, color),
stroke: Default::default(),
});
self.galley(rect.min, galley, Color32::RED);
self.galley(rect.min, galley, color);
frame_rect
}
}

View file

@ -248,15 +248,17 @@ impl Placer {
}
impl Placer {
pub(crate) fn debug_paint_cursor(&self, painter: &crate::Painter) {
let color = Color32::GREEN.linear_multiply(0.5);
let stroke = Stroke::new(2.0, color);
pub(crate) fn debug_paint_cursor(&self, painter: &crate::Painter, text: impl ToString) {
let stroke = Stroke::new(1.0, Color32::DEBUG_COLOR);
if let Some(grid) = &self.grid {
painter.rect_stroke(grid.next_cell(self.cursor(), Vec2::splat(0.0)), 1.0, stroke)
let rect = grid.next_cell(self.cursor(), Vec2::splat(0.0));
painter.rect_stroke(rect, 1.0, stroke);
let align = Align2::CENTER_CENTER;
painter.debug_text(align.pos_in_rect(&rect), align, stroke.color, text);
} else {
self.layout
.debug_paint_cursor(&self.region, stroke, painter)
.paint_text_at_cursor(painter, &self.region, stroke, text)
}
}
}

View file

@ -313,7 +313,7 @@ impl WidgetVisuals {
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
pub struct DebugOptions {
/// However over widgets to see their rectangles
pub show_widgets: bool,
pub debug_on_hover: bool,
/// Show which widgets make their parent wider
pub show_expand_width: bool,
/// Show which widgets make their parent higher
@ -548,7 +548,7 @@ impl Style {
ui.collapsing("📏 Spacing", |ui| spacing.ui(ui));
ui.collapsing("☝ Interaction", |ui| interaction.ui(ui));
ui.collapsing("🎨 Visuals", |ui| visuals.ui(ui));
ui.collapsing(" Debug", |ui| debug.ui(ui));
ui.collapsing("🐛 Debug", |ui| debug.ui(ui));
ui.vertical_centered(|ui| reset_button(ui, self));
}
@ -746,13 +746,13 @@ impl Visuals {
impl DebugOptions {
pub fn ui(&mut self, ui: &mut crate::Ui) {
let Self {
show_widgets: debug_widgets,
debug_on_hover,
show_expand_width: debug_expand_width,
show_expand_height: debug_expand_height,
show_resize: debug_resize,
} = self;
ui.checkbox(debug_widgets, "Show widget bounds on hover");
ui.checkbox(debug_on_hover, "Show debug info on hover");
ui.checkbox(
debug_expand_width,
"Show which widgets make their parent wider",

View file

@ -601,10 +601,10 @@ impl Ui {
let rect = self.allocate_space_impl(desired_size);
if self.style().debug.show_widgets && self.rect_contains_pointer(rect) {
if self.style().debug.debug_on_hover && 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.placer.debug_paint_cursor(&painter, "next");
}
let debug_expand_width = self.style().debug.show_expand_width;
@ -666,10 +666,10 @@ impl Ui {
let item_spacing = self.spacing().item_spacing;
self.placer.advance_after_rects(rect, rect, item_spacing);
if self.style().debug.show_widgets && self.rect_contains_pointer(rect) {
if self.style().debug.debug_on_hover && 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.placer.debug_paint_cursor(&painter, "next");
}
let id = Id::new(self.next_auto_id_source);
@ -735,11 +735,11 @@ impl Ui {
self.placer
.advance_after_rects(final_child_rect, final_child_rect, item_spacing);
if self.style().debug.show_widgets && self.rect_contains_pointer(final_child_rect) {
if self.style().debug.debug_on_hover && self.rect_contains_pointer(final_child_rect) {
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);
self.placer.debug_paint_cursor(&painter, "next");
}
let response = self.interact(final_child_rect, child_ui.id, Sense::hover());
@ -1523,10 +1523,10 @@ impl Ui {
let item_spacing = self.spacing().item_spacing;
self.placer.advance_after_rects(rect, rect, item_spacing);
if self.style().debug.show_widgets && self.rect_contains_pointer(rect) {
if self.style().debug.debug_on_hover && 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.placer.debug_paint_cursor(&painter, "next");
}
InnerResponse::new(inner, self.interact(rect, child_ui.id, Sense::hover()))
@ -1628,6 +1628,16 @@ impl Ui {
impl Ui {
/// Shows where the next widget is going to be placed
pub fn debug_paint_cursor(&self) {
self.placer.debug_paint_cursor(&self.painter);
self.placer.debug_paint_cursor(&self.painter, "next");
}
/// Shows the given text where the next widget is to be placed
/// if when [`Context::set_debug_on_hover`] has been turned on and the mouse is hovering the Ui.
pub fn trace_location(&self, text: impl ToString) {
let rect = self.max_rect_finite();
if self.style().debug.debug_on_hover && self.rect_contains_pointer(rect) {
self.placer
.debug_paint_cursor(&self.ctx().debug_painter(), text);
}
}
}

View file

@ -156,6 +156,7 @@ impl DemoWindows {
.min_width(150.0)
.default_width(190.0)
.show(ctx, |ui| {
egui::trace!(ui);
ui.vertical_centered(|ui| {
ui.heading("✒ egui demos");
});
@ -296,6 +297,7 @@ impl EguiWindows {
}
fn show_menu_bar(ui: &mut Ui) {
trace!(ui);
use egui::*;
menu::bar(ui, |ui| {

View file

@ -75,6 +75,7 @@ impl epi::App for WrapApp {
}
egui::TopBottomPanel::top("wrap_app_top_bar").show(ctx, |ui| {
egui::trace!(ui);
self.bar_contents(ui, frame);
});
@ -262,6 +263,7 @@ impl BackendPanel {
}
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut epi::Frame<'_>) {
egui::trace!(ui);
ui.vertical_centered(|ui| {
ui.heading("💻 Backend");
});
@ -327,9 +329,20 @@ impl BackendPanel {
}
}
{
let mut debug_on_hover = ui.ctx().debug_on_hover();
ui.checkbox(&mut debug_on_hover, "🐛 Debug on hover")
.on_hover_text("Show structure of the ui when you hover with the mouse");
ui.ctx().set_debug_on_hover(debug_on_hover);
}
ui.separator();
{
let mut screen_reader = ui.ctx().memory().options.screen_reader;
ui.checkbox(&mut screen_reader, "Screen reader").on_hover_text("Experimental feature: checking this will turn on the screen reader on supported platforms");
ui.ctx().memory().options.screen_reader = screen_reader;
}
ui.collapsing("Output events", |ui| {
ui.set_max_width(450.0);

View file

@ -49,6 +49,8 @@ impl Color32 {
pub const LIGHT_BLUE: Color32 = Color32::from_rgb(140, 160, 255);
pub const GOLD: Color32 = Color32::from_rgb(255, 215, 0);
pub const DEBUG_COLOR: Color32 = Color32::from_rgba_premultiplied(0, 200, 0, 128);
#[inline(always)]
pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self {
Self([r, g, b, 255])

View file

@ -229,7 +229,7 @@ pub enum PathType {
use self::PathType::{Closed, Open};
/// Tessellation quality options
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
pub struct TessellationOptions {