1use crate::{
8 Align, Align2, Color32, Context, FontFamily, FontId, Plugin, Rect, Shape, Vec2, WidgetText,
9 text,
10};
11
12#[track_caller]
24pub fn print(ctx: &Context, text: impl Into<WidgetText>) {
25 if !cfg!(debug_assertions) {
26 return;
27 }
28
29 let location = std::panic::Location::caller();
30 let location = format!("{}:{}", location.file(), location.line());
31
32 let plugin = ctx.plugin::<DebugTextPlugin>();
33 let mut state = plugin.lock();
34 state.entries.push(Entry {
35 location,
36 text: text.into(),
37 });
38}
39
40#[derive(Clone)]
41struct Entry {
42 location: String,
43 text: WidgetText,
44}
45
46#[derive(Clone, Default)]
50pub struct DebugTextPlugin {
51 entries: Vec<Entry>,
53}
54
55impl Plugin for DebugTextPlugin {
56 fn debug_name(&self) -> &'static str {
57 "DebugTextPlugin"
58 }
59
60 fn on_end_pass(&mut self, ctx: &Context) {
61 let entries = std::mem::take(&mut self.entries);
62 Self::paint_entries(ctx, entries);
63 }
64}
65
66impl DebugTextPlugin {
67 fn paint_entries(ctx: &Context, entries: Vec<Entry>) {
68 if entries.is_empty() {
69 return;
70 }
71
72 let mut pos = ctx
74 .input(|i| i.pointer.latest_pos())
75 .unwrap_or_else(|| ctx.content_rect().center())
76 + 8.0 * Vec2::Y;
77
78 let painter = ctx.debug_painter();
79 let where_to_put_background = painter.add(Shape::Noop);
80
81 let mut bounding_rect = Rect::from_points(&[pos]);
82
83 let color = Color32::GRAY;
84 let font_id = FontId::new(10.0, FontFamily::Proportional);
85
86 for Entry { location, text } in entries {
87 {
88 let location_galley =
90 ctx.fonts_mut(|f| f.layout(location, font_id.clone(), color, f32::INFINITY));
91 let location_rect =
92 Align2::RIGHT_TOP.anchor_size(pos - 4.0 * Vec2::X, location_galley.size());
93 painter.galley(location_rect.min, location_galley, color);
94 bounding_rect |= location_rect;
95 }
96
97 {
98 let available_width = ctx.content_rect().max.x - pos.x;
100 let galley = text.into_galley_impl(
101 ctx,
102 &ctx.style(),
103 text::TextWrapping::wrap_at_width(available_width),
104 font_id.clone().into(),
105 Align::TOP,
106 );
107 let rect = Align2::LEFT_TOP.anchor_size(pos, galley.size());
108 painter.galley(rect.min, galley, color);
109 bounding_rect |= rect;
110 }
111
112 pos.y = bounding_rect.max.y + 4.0;
113 }
114
115 painter.set(
116 where_to_put_background,
117 Shape::rect_filled(
118 bounding_rect.expand(4.0),
119 2.0,
120 Color32::from_black_alpha(192),
121 ),
122 );
123 }
124}