use super::types::*;
use super::util::add_border_node;
use crate::graph::Graph;
pub(crate) fn add_border_segments(g: &mut Graph<NodeLabel, EdgeLabel>) {
let subgraph_nodes: Vec<(String, i32, i32)> = g
.nodes()
.into_iter()
.filter_map(|v| {
let node = g.node(&v)?;
let min_rank = node.min_rank?;
let max_rank = node.max_rank?;
if g.children(Some(&v)).is_empty() {
return None;
}
Some((v, min_rank, max_rank))
})
.collect();
for (v, min_rank, max_rank) in subgraph_nodes {
for rank in min_rank..=max_rank {
add_border_node_for(g, &v, BorderType::Left, "_bl", rank);
add_border_node_for(g, &v, BorderType::Right, "_br", rank);
}
}
}
fn add_border_node_for(
g: &mut Graph<NodeLabel, EdgeLabel>,
v: &str,
border_type: BorderType,
prefix: &str,
rank: i32,
) {
let node_id = add_border_node(g, prefix, Some(rank), None);
if let Some(node) = g.node_mut(&node_id) {
node.border_type = Some(border_type);
}
g.set_parent(&node_id, Some(v));
let rank_idx = rank as usize;
let prev_border = {
let node = g.node(v);
node.and_then(|n| {
let list = match border_type {
BorderType::Left => &n.border_left,
BorderType::Right => &n.border_right,
};
if rank_idx == 0 {
None
} else {
list.get(rank_idx - 1).filter(|s| !s.is_empty()).cloned()
}
})
};
if let Some(node) = g.node_mut(v) {
let list = match border_type {
BorderType::Left => &mut node.border_left,
BorderType::Right => &mut node.border_right,
};
while list.len() <= rank_idx {
list.push(String::new());
}
list[rank_idx] = node_id.clone();
}
if let Some(prev) = prev_border {
g.set_edge(prev, node_id, Some(EdgeLabel::default()), None);
}
}