Show `WidgetInfo` for each widget if `debug.show_interactive_widgets`
This was useful during debugging
This commit is contained in:
parent
aa2f87e0ff
commit
95b62ce144
|
|
@ -1202,6 +1202,19 @@ impl Context {
|
|||
res
|
||||
}
|
||||
|
||||
/// This is called by [`Response::widget_info`], but can also be called directly.
|
||||
///
|
||||
/// With some debug flags it will store the widget info in [`WidgetRects`] for later display.
|
||||
#[inline]
|
||||
pub fn register_widget_info(&self, id: Id, make_info: impl Fn() -> crate::WidgetInfo) {
|
||||
#[cfg(debug_assertions)]
|
||||
self.write(|ctx| {
|
||||
if ctx.memory.options.style.debug.show_interactive_widgets {
|
||||
ctx.viewport().widgets_this_frame.set_info(id, make_info());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Get a full-screen painter for a new or existing layer
|
||||
pub fn layer_painter(&self, layer_id: LayerId) -> Painter {
|
||||
let screen_rect = self.screen_rect();
|
||||
|
|
@ -1807,6 +1820,7 @@ impl Context {
|
|||
self.write(|ctx| ctx.end_frame())
|
||||
}
|
||||
|
||||
/// Called at the end of the frame.
|
||||
#[cfg(debug_assertions)]
|
||||
fn debug_painting(&self) {
|
||||
let paint_widget = |widget: &WidgetRect, text: &str, color: Color32| {
|
||||
|
|
@ -1839,8 +1853,8 @@ impl Context {
|
|||
} else if rect.sense.drag {
|
||||
(Color32::from_rgb(0, 0, 0x88), "drag")
|
||||
} else {
|
||||
continue;
|
||||
// (Color32::from_rgb(0, 0, 0x88), "hover")
|
||||
// unreachable since we only show interactive
|
||||
(Color32::from_rgb(0, 0, 0x88), "hover")
|
||||
};
|
||||
painter.debug_rect(rect.interact_rect, color, text);
|
||||
}
|
||||
|
|
@ -1860,10 +1874,32 @@ impl Context {
|
|||
hovered,
|
||||
} = interact_widgets;
|
||||
|
||||
if false {
|
||||
for widget in contains_pointer {
|
||||
paint_widget_id(widget, "contains_pointer", Color32::BLUE);
|
||||
if true {
|
||||
for &id in &contains_pointer {
|
||||
paint_widget_id(id, "contains_pointer", Color32::BLUE);
|
||||
}
|
||||
|
||||
let widget_rects = self.write(|w| w.viewport().widgets_this_frame.clone());
|
||||
|
||||
let mut contains_pointer: Vec<Id> = contains_pointer.iter().copied().collect();
|
||||
contains_pointer.sort_by_key(|&id| {
|
||||
widget_rects
|
||||
.order(id)
|
||||
.map(|(layer_id, order_in_layer)| (layer_id.order, order_in_layer))
|
||||
});
|
||||
|
||||
let mut debug_text = "Widgets in order:\n".to_owned();
|
||||
for id in contains_pointer {
|
||||
let mut widget_text = format!("{id:?}");
|
||||
if let Some(rect) = widget_rects.get(id) {
|
||||
widget_text += &format!(" {:?} {:?}", rect.rect, rect.sense);
|
||||
}
|
||||
if let Some(info) = widget_rects.info(id) {
|
||||
widget_text += &format!(" {info:?}");
|
||||
}
|
||||
debug_text += &format!("{widget_text}\n");
|
||||
}
|
||||
self.debug_text(debug_text);
|
||||
}
|
||||
if true {
|
||||
for widget in hovered {
|
||||
|
|
@ -1887,7 +1923,7 @@ impl Context {
|
|||
drag,
|
||||
} = hits;
|
||||
|
||||
if false {
|
||||
if true {
|
||||
for widget in &contains_pointer {
|
||||
paint_widget(widget, "contains_pointer", Color32::BLUE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -745,6 +745,7 @@ impl Response {
|
|||
/// Call after interacting and potential calls to [`Self::mark_changed`].
|
||||
pub fn widget_info(&self, make_info: impl Fn() -> crate::WidgetInfo) {
|
||||
use crate::output::OutputEvent;
|
||||
|
||||
let event = if self.clicked() {
|
||||
Some(OutputEvent::Clicked(make_info()))
|
||||
} else if self.double_clicked() {
|
||||
|
|
@ -758,6 +759,7 @@ impl Response {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(event) = event {
|
||||
self.output_event(event);
|
||||
} else {
|
||||
|
|
@ -765,6 +767,8 @@ impl Response {
|
|||
self.ctx.accesskit_node_builder(self.id, |builder| {
|
||||
self.fill_accesskit_node_from_widget_info(builder, make_info());
|
||||
});
|
||||
|
||||
self.ctx.register_widget_info(self.id, make_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -773,6 +777,10 @@ impl Response {
|
|||
self.ctx.accesskit_node_builder(self.id, |builder| {
|
||||
self.fill_accesskit_node_from_widget_info(builder, event.widget_info().clone());
|
||||
});
|
||||
|
||||
self.ctx
|
||||
.register_widget_info(self.id, || event.widget_info().clone());
|
||||
|
||||
self.ctx.output_mut(|o| o.events.push(event));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,13 +46,25 @@ pub struct WidgetRect {
|
|||
///
|
||||
/// All [`Ui`]s have a [`WidgetRects`], but whether or not their rects are correct
|
||||
/// depends on if [`Ui::interact_bg`] was ever called.
|
||||
#[derive(Default, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct WidgetRects {
|
||||
/// All widgets, in painting order.
|
||||
by_layer: HashMap<LayerId, Vec<WidgetRect>>,
|
||||
|
||||
/// All widgets, by id, and their order in their respective layer
|
||||
by_id: IdMap<(usize, WidgetRect)>,
|
||||
|
||||
/// Info about some widgets.
|
||||
///
|
||||
/// Only filled in if the widget is interacted with,
|
||||
/// or if this is a debug build.
|
||||
infos: IdMap<WidgetInfo>,
|
||||
}
|
||||
|
||||
impl PartialEq for WidgetRects {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.by_layer == other.by_layer
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetRects {
|
||||
|
|
@ -90,18 +102,28 @@ impl WidgetRects {
|
|||
|
||||
/// Clear the contents while retaining allocated memory.
|
||||
pub fn clear(&mut self) {
|
||||
let Self { by_layer, by_id } = self;
|
||||
let Self {
|
||||
by_layer,
|
||||
by_id,
|
||||
infos,
|
||||
} = self;
|
||||
|
||||
for rects in by_layer.values_mut() {
|
||||
rects.clear();
|
||||
}
|
||||
|
||||
by_id.clear();
|
||||
|
||||
infos.clear();
|
||||
}
|
||||
|
||||
/// Insert the given widget rect in the given layer.
|
||||
pub fn insert(&mut self, layer_id: LayerId, widget_rect: WidgetRect) {
|
||||
let Self { by_layer, by_id } = self;
|
||||
let Self {
|
||||
by_layer,
|
||||
by_id,
|
||||
infos: _,
|
||||
} = self;
|
||||
|
||||
let layer_widgets = by_layer.entry(layer_id).or_default();
|
||||
|
||||
|
|
@ -134,4 +156,12 @@ impl WidgetRects {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_info(&mut self, id: Id, info: WidgetInfo) {
|
||||
self.infos.insert(id, info);
|
||||
}
|
||||
|
||||
pub fn info(&self, id: Id) -> Option<&WidgetInfo> {
|
||||
self.infos.get(&id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue