1use crate::{
9 text, Align, Align2, Color32, Context, FontFamily, FontId, Id, Rect, Shape, Vec2, WidgetText,
10};
11
12pub(crate) fn register(ctx: &Context) {
19 ctx.on_end_pass("debug_text", std::sync::Arc::new(State::end_pass));
20}
21
22#[track_caller]
34pub fn print(ctx: &Context, text: impl Into<WidgetText>) {
35 if !cfg!(debug_assertions) {
36 return;
37 }
38
39 let location = std::panic::Location::caller();
40 let location = format!("{}:{}", location.file(), location.line());
41 ctx.data_mut(|data| {
42 let state = data.get_temp_mut_or_default::<State>(Id::NULL);
46 state.entries.push(Entry {
47 location,
48 text: text.into(),
49 });
50 });
51}
52
53#[derive(Clone)]
54struct Entry {
55 location: String,
56 text: WidgetText,
57}
58
59#[derive(Clone, Default)]
63struct State {
64 entries: Vec<Entry>,
66}
67
68impl State {
69 fn end_pass(ctx: &Context) {
70 let state = ctx.data_mut(|data| data.remove_temp::<Self>(Id::NULL));
71 if let Some(state) = state {
72 state.paint(ctx);
73 }
74 }
75
76 fn paint(self, ctx: &Context) {
77 let Self { entries } = self;
78
79 if entries.is_empty() {
80 return;
81 }
82
83 let mut pos = ctx
85 .input(|i| i.pointer.latest_pos())
86 .unwrap_or_else(|| ctx.screen_rect().center())
87 + 8.0 * Vec2::Y;
88
89 let painter = ctx.debug_painter();
90 let where_to_put_background = painter.add(Shape::Noop);
91
92 let mut bounding_rect = Rect::from_points(&[pos]);
93
94 let color = Color32::GRAY;
95 let font_id = FontId::new(10.0, FontFamily::Proportional);
96
97 for Entry { location, text } in entries {
98 {
99 let location_galley =
101 ctx.fonts(|f| f.layout(location, font_id.clone(), color, f32::INFINITY));
102 let location_rect =
103 Align2::RIGHT_TOP.anchor_size(pos - 4.0 * Vec2::X, location_galley.size());
104 painter.galley(location_rect.min, location_galley, color);
105 bounding_rect = bounding_rect.union(location_rect);
106 }
107
108 {
109 let available_width = ctx.screen_rect().max.x - pos.x;
111 let galley = text.into_galley_impl(
112 ctx,
113 &ctx.style(),
114 text::TextWrapping::wrap_at_width(available_width),
115 font_id.clone().into(),
116 Align::TOP,
117 );
118 let rect = Align2::LEFT_TOP.anchor_size(pos, galley.size());
119 painter.galley(rect.min, galley, color);
120 bounding_rect = bounding_rect.union(rect);
121 }
122
123 pos.y = bounding_rect.max.y + 4.0;
124 }
125
126 painter.set(
127 where_to_put_background,
128 Shape::rect_filled(
129 bounding_rect.expand(4.0),
130 2.0,
131 Color32::from_black_alpha(192),
132 ),
133 );
134 }
135}