ferroui_diagnostics/diagnostics/
visual_tree_debug.rs1use ferroui_base::data::core::ValueTypes;
4use ferroui_base::data::BindingPriority;
5use ferroui_base::diagnostics::FerroObjectDiagnosticExtensions;
6use ferroui_base::{BoxedValue, FerroPropertyRegistry, Visual};
7use ferroui_controls::Control;
8use std::fmt::Write;
9use std::rc::Rc;
10
11pub struct VisualTreeDebug;
13
14impl VisualTreeDebug {
15 pub fn print_visual_tree(visual: &Visual) -> String {
19 let mut result = String::new();
20 Self::print_visual_tree_into(visual, &mut result, 0);
21 result
22 }
23
24 fn print_visual_tree_into(visual: &Visual, builder: &mut String, indent: i32) {
25 let control = visual.to_ref().cast::<Control>();
26
27 builder.push_str(&Self::indent(indent - 1));
28
29 if indent > 0 {
30 builder.push_str(" +- ");
31 }
32
33 builder.push_str(visual.get_type().name());
34
35 if let Some(control) = &control {
36 builder.push(' ');
37 let classes: BoxedValue = Rc::new(control.classes());
39 builder.push_str(&ValueTypes::to_display_string(Some(&classes)));
40 builder.push('\n');
41
42 for &property in FerroPropertyRegistry::instance().get_registered(control.get_type()).iter() {
43 let value = control.get_diagnostic(property);
44
45 if value.priority() != BindingPriority::Unset {
46 builder.push_str(&Self::indent(indent));
47 builder.push_str(" | ");
48 builder.push_str(value.property().name());
49 builder.push_str(" = ");
50 let shown = ValueTypes::normalize(value.value().clone());
51 builder.push_str(&ValueTypes::to_display_string(shown.as_ref()));
52 builder.push_str(" [");
53 let _ = write!(builder, "{:?}", value.priority());
54 builder.push_str("]\n");
55 }
56 }
57 } else {
58 builder.push('\n');
59 }
60
61 for child in visual.visual_children().snapshot().iter() {
62 Self::print_visual_tree_into(child, builder, indent + 1);
63 }
64 }
65
66 fn indent(indent: i32) -> String {
67 " ".repeat(indent.max(0) as usize * 4)
68 }
69}