use crate::graph::{Edge, EdgeLabel, Graph, NodeLabel, Point};
use crate::util::add_dummy_node;
pub fn run(graph: &mut Graph) {
graph.graph_mut().dummy_chains = Some(Vec::new());
let edges: Vec<Edge> = graph.edges();
for edge in edges {
normalize_edge(graph, &edge);
}
}
fn normalize_edge(graph: &mut Graph, e: &Edge) {
let v = e.v.clone();
let w = e.w.clone();
let name = e.name.clone();
let v_rank = graph.node(&v).rank.unwrap_or(0);
let w_rank = graph.node(&w).rank.unwrap_or(0);
if w_rank == v_rank + 1 {
return;
}
let edge_label = graph.edge(e).cloned().unwrap_or_default();
let label_rank = edge_label.label_rank;
graph.remove_edge_obj(e);
let mut current_v = v.clone();
let mut current_rank = v_rank + 1;
let mut i = 0i32;
while current_rank < w_rank {
let mut attrs = NodeLabel {
width: 0.0,
height: 0.0,
edge_label: Some(Box::new(edge_label.clone())),
edge_obj: Some(e.clone()),
rank: Some(current_rank),
..Default::default()
};
let mut el = edge_label.clone();
el.points = Some(Vec::new());
attrs.edge_label = Some(Box::new(el));
let node_type = if Some(current_rank) == label_rank {
attrs.width = edge_label.width.unwrap_or(0.0);
attrs.height = edge_label.height.unwrap_or(0.0);
attrs.labelpos = edge_label.labelpos.clone();
"edge-label"
} else {
"edge"
};
let dummy = add_dummy_node(graph, node_type, attrs, "_d");
if i == 0 {
graph
.graph_mut()
.dummy_chains
.as_mut()
.unwrap()
.push(dummy.clone());
}
graph.set_edge(
¤t_v,
&dummy,
EdgeLabel {
weight: edge_label.weight,
..Default::default()
},
name.as_deref(),
);
current_v = dummy;
current_rank += 1;
i += 1;
}
graph.set_edge(
¤t_v,
&w,
EdgeLabel {
weight: edge_label.weight,
..Default::default()
},
name.as_deref(),
);
}
pub fn undo(graph: &mut Graph) {
let dummy_chains = graph.graph().dummy_chains.clone().unwrap_or_default();
for start_v in dummy_chains {
let v = start_v.clone();
let node = graph.node(&v).clone();
if let (Some(orig_label), Some(orig_edge_obj)) = (
node.edge_label.as_ref().map(|l| *l.clone()),
node.edge_obj.as_ref().cloned(),
) {
let final_label = orig_label.clone();
graph.set_edge_obj(&orig_edge_obj, final_label.clone());
let mut cur_v = v.clone();
loop {
let cur_node = graph.node(&cur_v).clone();
if cur_node.dummy.is_none() {
break;
}
let successors = graph.successors(&cur_v).unwrap_or_default();
let next_v = match successors.into_iter().next() {
Some(s) => s,
None => break,
};
let x = cur_node.x.unwrap_or(0.0);
let y = cur_node.y.unwrap_or(0.0);
if let Some(el) = graph.edge_mut(&orig_edge_obj) {
el.points.get_or_insert_with(Vec::new).push(Point { x, y });
if cur_node.dummy.as_deref() == Some("edge-label") {
el.x = Some(x);
el.y = Some(y);
el.width = Some(cur_node.width);
el.height = Some(cur_node.height);
}
}
graph.remove_node(&cur_v);
cur_v = next_v;
}
}
}
}