Add `Context::debug_text` (#3864)
This is a very easy way to show some text under the mouse pointer:
```rs
ctx.debug_text("foo");
```
This commit is contained in:
parent
31cc31a67b
commit
aa67d3180b
|
|
@ -351,8 +351,6 @@ pub fn popup_above_or_below_widget<R>(
|
||||||
.fixed_pos(pos)
|
.fixed_pos(pos)
|
||||||
.pivot(pivot)
|
.pivot(pivot)
|
||||||
.show(ui.ctx(), |ui| {
|
.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 = Frame::popup(ui.style());
|
||||||
let frame_margin = frame.total_margin();
|
let frame_margin = frame.total_margin();
|
||||||
frame
|
frame
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,11 @@ impl ViewportRepaintInfo {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct DebugText {
|
||||||
|
location: String,
|
||||||
|
text: WidgetText,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ContextImpl {
|
struct ContextImpl {
|
||||||
/// Since we could have multiple viewport across multiple monitors with
|
/// Since we could have multiple viewport across multiple monitors with
|
||||||
|
|
@ -278,6 +283,8 @@ struct ContextImpl {
|
||||||
accesskit_node_classes: accesskit::NodeClassSet,
|
accesskit_node_classes: accesskit::NodeClassSet,
|
||||||
|
|
||||||
loaders: Arc<Loaders>,
|
loaders: Arc<Loaders>,
|
||||||
|
|
||||||
|
debug_texts: Vec<DebugText>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContextImpl {
|
impl ContextImpl {
|
||||||
|
|
@ -1060,6 +1067,31 @@ impl Context {
|
||||||
Self::layer_painter(self, LayerId::debug())
|
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?
|
/// What operating system are we running on?
|
||||||
///
|
///
|
||||||
/// When compiling natively, this is
|
/// When compiling natively, this is
|
||||||
|
|
@ -1578,6 +1610,63 @@ impl Context {
|
||||||
crate::gui_zoom::zoom_with_keyboard(self);
|
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())
|
self.write(|ctx| ctx.end_frame())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,9 @@ impl Painter {
|
||||||
self.debug_text(pos, Align2::LEFT_TOP, color, format!("🔥 {text}"))
|
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)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn debug_text(
|
pub fn debug_text(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -649,18 +649,39 @@ impl WidgetText {
|
||||||
fallback_font: impl Into<FontSelection>,
|
fallback_font: impl Into<FontSelection>,
|
||||||
) -> Arc<Galley> {
|
) -> Arc<Galley> {
|
||||||
let wrap = wrap.unwrap_or_else(|| ui.wrap_text());
|
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 };
|
let wrap_width = if wrap { available_width } else { f32::INFINITY };
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::RichText(text) => {
|
Self::RichText(text) => {
|
||||||
let valign = ui.layout().vertical_align();
|
let mut layout_job = text.into_layout_job(style, fallback_font, default_valign);
|
||||||
let mut layout_job = text.into_layout_job(ui.style(), fallback_font.into(), valign);
|
|
||||||
layout_job.wrap.max_width = wrap_width;
|
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) => {
|
Self::LayoutJob(mut job) => {
|
||||||
job.wrap.max_width = wrap_width;
|
job.wrap.max_width = wrap_width;
|
||||||
ui.fonts(|f| f.layout_job(job))
|
ctx.fonts(|f| f.layout_job(job))
|
||||||
}
|
}
|
||||||
Self::Galley(galley) => galley,
|
Self::Galley(galley) => galley,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue