+ use crate::Annotations;
+
+ use charming::{
+ element::{ItemStyle, Label},
+ series::{TreemapData, TreemapLevel},
+ };
+ use guppy::graph::PackageMetadata;
+
+ // TODO: reference
+ const COLORS: [&str; 9] = [
+ "#5470c6", "#91cc75", "#fac858", "#ee6666", "#73c0de", "#3ba272", "#fc8452", "#9a60b4",
+ "#ea7ccc",
+ ];
+
+ pub fn color() -> Vec<String> {
+ COLORS
+ .iter()
+ .map(|color| color.to_string())
+ .collect::<Vec<String>>()
+ }
+
+ pub fn data<'graph>(
+ annotations: &Annotations,
+ packages: &[PackageMetadata<'graph>],
+ ) -> Vec<TreemapData> {
+ let mut treemap_items = Vec::new();
+
+ for pkg in packages {
+ // Recursively call this function for all direct dependencies
+ let direct_dependencies = pkg.direct_links().map(|link| link.to()).collect::<Vec<_>>();
+
+ let empty_vec = Vec::new();
+ let self_times = annotations
+ .pkg(pkg.id())
+ .map(|node| node.timings().unwrap_or(&empty_vec))
+ .unwrap_or(&empty_vec)
+ .iter()
+ .map(|message| TreemapData {
+ value: message.duration,
+ id: None,
+ name: Some(format!("{:?} {:?}", message.mode, message.target.kind)),
+ upper_label: None,
+ visual_dimension: None,
+ children: vec![],
+ children_visible_min: None,
+ });
+
+ let mut children = data(annotations, &direct_dependencies);
+ children.extend(self_times);
+
+ let mut total_duration = 0_f64;
+ for child in &children {
+ total_duration += child.value;
+ }
+
+ let dependent_count = pkg.reverse_direct_links().count();
+ let relative_duration = if dependent_count == 0 {
+ total_duration
+ } else {
+ total_duration / (dependent_count as f64)
+ };
+
+ treemap_items.push(TreemapData {
+ value: relative_duration,
+ id: None,
+ name: Some(pkg.name().to_string()),
+ upper_label: Some(Label::new().show(true)),
+ visual_dimension: None,
+ children,
+ children_visible_min: Some(200_000),
+ })
+ }
+
+ treemap_items
+ }
+
+ pub fn levels(depth: usize) -> Vec<TreemapLevel> {
+ let mut levels = Vec::with_capacity(depth);
+
+ levels.extend([
+ TreemapLevel {
+ item_style: Some(ItemStyle::new().border_width(1).gap_width(0)),
+ upper_label: Some(Label::new().show(false)),
+ },
+ TreemapLevel {
+ item_style: Some(
+ ItemStyle::new()
+ .border_color("#777")
+ .border_width(1)
+ .gap_width(0),
+ ),
+ upper_label: Some(Label::new().show(false)),
+ },
+ ]);
+
+ while levels.len() < depth {
+ levels.push(TreemapLevel {
+ item_style: Some(
+ ItemStyle::new()
+ .border_width(5)
+ .gap_width(1)
+ .border_color_saturation(0.6),
+ ),
+ upper_label: None,
+ });
+ }
+
+ levels
+ }