use std::{
collections::{HashMap, HashSet},
rc::Rc,
sync::Arc,
};
use crate::{
layout::Layout,
unit::LayoutType,
widget::{Widget, WidgetId},
Ref, WidgetManager,
};
use super::Modify;
const RESET: &str = "\u{001b}[0m";
const GRAY: &str = "\u{001b}[30;1m";
const RED: &str = "\u{001b}[31;1m";
const GREEN: &str = "\u{001b}[32;1m";
const YELLOW: &str = "\u{001b}[33;1m";
const CYAN: &str = "\u{001b}[36;1m";
const WHITE: &str = "\u{001b}[37;1m";
pub fn print_tree(manager: &WidgetManager) {
println!("Tree:");
for widget_id in manager.get_tree().iter() {
let depth = manager
.get_tree()
.get(&widget_id)
.expect("broken tree")
.depth;
let layer = manager.get_node(&widget_id).layer;
let node = manager.get_node(&widget_id);
print_node(
depth,
layer,
Some(&widget_id),
&node.widget.get(),
WHITE,
&format!(
"{} {:?} {:?}",
if matches!(node.layout, Ref::None) {
GRAY
} else {
CYAN
},
node.layout_type
.try_get()
.unwrap_or_else(|| Arc::new(LayoutType::default())),
if matches!(node.layout, Ref::None) {
Ref::new(Layout::default())
} else {
Ref::clone(&node.layout)
}
),
);
}
}
pub fn print_tree_modifications(manager: &WidgetManager) {
println!("Tree:");
let mods = &manager.modifications;
let mut new_root = None;
let mut spawns = HashMap::new();
let mut rebuilds = HashSet::new();
let mut destroys = HashSet::new();
for modify in mods {
match modify {
Modify::Spawn(parent_id, widget) => match parent_id {
Some(parent_id) => {
if !spawns.contains_key(parent_id) {
spawns.insert(*parent_id, Vec::new());
}
spawns.get_mut(parent_id).unwrap().push(widget.get());
}
None => {
new_root = Some(widget);
}
},
Modify::Rebuild(widget_id) => {
rebuilds.insert(*widget_id);
}
Modify::Destroy(widget_id) => {
destroys.insert(*widget_id);
}
}
}
if manager.get_tree().get_root().is_none() {
if let Some(widget) = new_root {
print_node(0, 0, None, &widget.get(), GREEN, "");
}
return;
}
for widget_id in manager.get_tree().iter() {
let depth = manager
.get_tree()
.get(&widget_id)
.expect("broken tree")
.depth;
let layer = manager.get_node(&widget_id).layer;
let is_rebuild_queued = rebuilds.contains(&widget_id);
let is_destroy_queued = if depth == 0 && new_root.is_some() {
true
} else {
destroys.contains(&widget_id)
};
let node = manager.get_node(&widget_id);
print_node(
depth,
layer,
Some(&widget_id),
&node.widget.get(),
if is_destroy_queued {
RED
} else if is_rebuild_queued {
YELLOW
} else {
WHITE
},
&format!(
"{} {:?} {:?}",
if matches!(node.layout, Ref::None) {
GRAY
} else {
CYAN
},
node.layout_type
.try_get()
.unwrap_or_else(|| Arc::new(LayoutType::default())),
if matches!(node.layout, Ref::None) {
Ref::new(Layout::default())
} else {
Ref::clone(&node.layout)
}
),
);
for to_spawn in spawns.get(&widget_id).unwrap_or(&Vec::new()) {
print_node(depth + 1, layer, None, to_spawn, GREEN, "");
}
}
}
fn print_node(
depth: usize,
layer: u32,
widget_id: Option<&WidgetId>,
widget: &Rc<dyn Widget>,
color: &'static str,
suffix: &str,
) {
print!("{}", GRAY);
if depth > 0 {
print!("{}", "| ".repeat(depth / 3));
if depth % 3 == 1 {
print!("| ");
} else if depth % 3 == 2 {
print!("| ");
}
}
print!("{}", RESET);
print!("{}", color);
print!("{}", widget.get_type_name());
print!("{}", GRAY);
if let Some(widget_id) = widget_id {
print!(" (#{})", widget_id);
}
print!(" [{}]", layer);
println!(" {}", suffix);
print!("{}", RESET);
}