Skip to main content

taffy/util/
print.rs

1//! Contains functions for printing a debug representation of the tree
2use crate::tree::{NodeId, PrintTree};
3use std::io;
4
5/// Prints a debug representation of the computed layout for a tree of nodes, starting with the passed root node.
6pub fn print_tree(tree: &impl PrintTree, root: NodeId) {
7    // Buffer into a string so that output can be captured in tests
8    let mut buffer = Vec::<u8>::new();
9    write_tree(&mut buffer, tree, root).expect("Wrote tree debug representation to Stdout");
10    println!("{}", std::str::from_utf8(&buffer).unwrap());
11}
12
13/// Writes a debug representation of the computed layout to the writer, starting with the passed root node.
14pub fn write_tree(mut writer: impl io::Write, tree: &impl PrintTree, root: NodeId) -> io::Result<()> {
15    writeln!(writer, "TREE")?;
16    write_node(&mut writer, tree, root, false, String::new())?;
17
18    /// Recursive function that writes each node in the tree
19    fn write_node(
20        writer: &mut impl io::Write,
21        tree: &impl PrintTree,
22        node_id: NodeId,
23        has_sibling: bool,
24        lines_string: String,
25    ) -> io::Result<()> {
26        let layout = &tree.get_final_layout(node_id);
27        let display = tree.get_debug_label(node_id);
28        let num_children = tree.child_count(node_id);
29
30        let fork_string = if has_sibling { "├── " } else { "└── " };
31        #[cfg(feature = "content_size")]
32        writeln!(
33                writer,
34                "{lines}{fork} {display} [x: {x:<4} y: {y:<4} w: {width:<4} h: {height:<4} overflow: l:{ol} r:{or} t:{ot} b:{ob}, border: l:{bl} r:{br} t:{bt} b:{bb}, padding: l:{pl} r:{pr} t:{pt} b:{pb}] ({key:?})",
35                lines = lines_string,
36                fork = fork_string,
37                display = display,
38                x = layout.location.x,
39                y = layout.location.y,
40                width = layout.size.width,
41                height = layout.size.height,
42                ol = layout.scrollable_overflow_rect.left,
43                or = layout.scrollable_overflow_rect.right,
44                ot = layout.scrollable_overflow_rect.top,
45                ob = layout.scrollable_overflow_rect.bottom,
46                bl = layout.border.left,
47                br = layout.border.right,
48                bt = layout.border.top,
49                bb = layout.border.bottom,
50                pl = layout.padding.left,
51                pr = layout.padding.right,
52                pt = layout.padding.top,
53                pb = layout.padding.bottom,
54                key = node_id,
55            )?;
56        #[cfg(not(feature = "content_size"))]
57        writeln!(
58            writer,
59            "{lines}{fork} {display} [x: {x:<4} y: {y:<4} width: {width:<4} height: {height:<4}] ({key:?})",
60            lines = lines_string,
61            fork = fork_string,
62            display = display,
63            x = layout.location.x,
64            y = layout.location.y,
65            width = layout.size.width,
66            height = layout.size.height,
67            key = node_id,
68        );
69        let bar = if has_sibling { "│   " } else { "    " };
70        let new_string = lines_string + bar;
71
72        // Recurse into children
73        for (index, child) in tree.child_ids(node_id).enumerate() {
74            let has_sibling = index < num_children - 1;
75            write_node(writer, tree, child, has_sibling, new_string.clone())?;
76        }
77        Ok(())
78    }
79    Ok(())
80}