Skip to content

Commit

Permalink
Add Context::debug_text (#3864)
Browse files Browse the repository at this point in the history
This is a very easy way to show some text under the mouse pointer:

```rs
ctx.debug_text("foo");
```
  • Loading branch information
emilk authored Jan 22, 2024
1 parent 31cc31a commit aa67d31
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 7 deletions.
2 changes: 0 additions & 2 deletions crates/egui/src/containers/popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,6 @@ pub fn popup_above_or_below_widget<R>(
.fixed_pos(pos)
.pivot(pivot)
.show(ui.ctx(), |ui| {
// Note: we use a separate clip-rect for this area, so the popup can be outside the parent.
// See https://github.com/emilk/egui/issues/825
let frame = Frame::popup(ui.style());
let frame_margin = frame.total_margin();
frame
Expand Down
89 changes: 89 additions & 0 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ impl ViewportRepaintInfo {

// ----------------------------------------------------------------------------

struct DebugText {
location: String,
text: WidgetText,
}

#[derive(Default)]
struct ContextImpl {
/// Since we could have multiple viewport across multiple monitors with
Expand Down Expand Up @@ -278,6 +283,8 @@ struct ContextImpl {
accesskit_node_classes: accesskit::NodeClassSet,

loaders: Arc<Loaders>,

debug_texts: Vec<DebugText>,
}

impl ContextImpl {
Expand Down Expand Up @@ -1060,6 +1067,31 @@ impl Context {
Self::layer_painter(self, LayerId::debug())
}

/// Print this text next to the cursor at the end of the frame.
///
/// If you call this multiple times, the text will be appended.
///
/// This only works if compiled with `debug_assertions`.
///
/// ```
/// # let ctx = egui::Context::default();
/// # let state = true;
/// ctx.debug_text(format!("State: {state:?}"));
/// ```
#[track_caller]
pub fn debug_text(&self, text: impl Into<WidgetText>) {
if cfg!(debug_assertions) {
let location = std::panic::Location::caller();
let location = format!("{}:{}", location.file(), location.line());
self.write(|c| {
c.debug_texts.push(DebugText {
location,
text: text.into(),
});
});
}
}

/// What operating system are we running on?
///
/// When compiling natively, this is
Expand Down Expand Up @@ -1578,6 +1610,63 @@ impl Context {
crate::gui_zoom::zoom_with_keyboard(self);
}

let debug_texts = self.write(|ctx| std::mem::take(&mut ctx.debug_texts));
if !debug_texts.is_empty() {
// Show debug-text next to the cursor.
let mut pos = self
.input(|i| i.pointer.latest_pos())
.unwrap_or_else(|| self.screen_rect().center())
+ 8.0 * Vec2::Y;

let painter = self.debug_painter();
let where_to_put_background = painter.add(Shape::Noop);

let mut bounding_rect = Rect::from_points(&[pos]);

let color = Color32::GRAY;
let font_id = FontId::new(10.0, FontFamily::Proportional);

for DebugText { location, text } in debug_texts {
{
// Paint location to left of `pos`:
let location_galley =
self.fonts(|f| f.layout(location, font_id.clone(), color, f32::INFINITY));
let location_rect =
Align2::RIGHT_TOP.anchor_size(pos - 4.0 * Vec2::X, location_galley.size());
painter.galley(location_rect.min, location_galley, color);
bounding_rect = bounding_rect.union(location_rect);
}

{
// Paint `text` to right of `pos`:
let wrap = true;
let available_width = self.screen_rect().max.x - pos.x;
let galley = text.into_galley_impl(
self,
&self.style(),
wrap,
available_width,
font_id.clone().into(),
Align::TOP,
);
let rect = Align2::LEFT_TOP.anchor_size(pos, galley.size());
painter.galley(rect.min, galley, color);
bounding_rect = bounding_rect.union(rect);
}

pos.y = bounding_rect.max.y + 4.0;
}

painter.set(
where_to_put_background,
Shape::rect_filled(
bounding_rect.expand(4.0),
2.0,
Color32::from_black_alpha(192),
),
);
}

self.write(|ctx| ctx.end_frame())
}
}
Expand Down
4 changes: 3 additions & 1 deletion crates/egui/src/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ impl Painter {
self.debug_text(pos, Align2::LEFT_TOP, color, format!("🔥 {text}"))
}

/// text with a background
/// Text with a background.
///
/// See also [`Context::debug_text`].
#[allow(clippy::needless_pass_by_value)]
pub fn debug_text(
&self,
Expand Down
29 changes: 25 additions & 4 deletions crates/egui/src/widget_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,18 +649,39 @@ impl WidgetText {
fallback_font: impl Into<FontSelection>,
) -> Arc<Galley> {
let wrap = wrap.unwrap_or_else(|| ui.wrap_text());
let valign = ui.layout().vertical_align();
let style = ui.style();

self.into_galley_impl(
ui.ctx(),
style,
wrap,
available_width,
fallback_font.into(),
valign,
)
}

pub fn into_galley_impl(
self,
ctx: &crate::Context,
style: &Style,
wrap: bool,
available_width: f32,
fallback_font: FontSelection,
default_valign: Align,
) -> Arc<Galley> {
let wrap_width = if wrap { available_width } else { f32::INFINITY };

match self {
Self::RichText(text) => {
let valign = ui.layout().vertical_align();
let mut layout_job = text.into_layout_job(ui.style(), fallback_font.into(), valign);
let mut layout_job = text.into_layout_job(style, fallback_font, default_valign);
layout_job.wrap.max_width = wrap_width;
ui.fonts(|f| f.layout_job(layout_job))
ctx.fonts(|f| f.layout_job(layout_job))
}
Self::LayoutJob(mut job) => {
job.wrap.max_width = wrap_width;
ui.fonts(|f| f.layout_job(job))
ctx.fonts(|f| f.layout_job(job))
}
Self::Galley(galley) => galley,
}
Expand Down

0 comments on commit aa67d31

Please sign in to comment.