autorouter: keep track of clicked pins

Pin names provide us stable references that we can use to replay actions
later. We'll use this information to serialize the selection.
This commit is contained in:
Mikolaj Wielgus 2024-05-19 04:37:26 +02:00
parent 530f81557a
commit f03545124f
5 changed files with 87 additions and 26 deletions

View File

@ -183,7 +183,7 @@ impl<R: RulesTrait> Autorouter<R> {
.unwrap() .unwrap()
.vertex_index(); .vertex_index();
selection.contains(&source_vertex.into()) && selection.contains(&to_vertex.into()) selection.contains(source_vertex.into()) && selection.contains(to_vertex.into())
}) })
.collect() .collect()
} }

View File

@ -1,26 +1,83 @@
use std::collections::HashSet; use std::collections::HashSet;
use crate::layout::NodeIndex; use crate::{
drawing::{graph::PrimitiveIndex, rules::RulesTrait},
graph::GenericIndex,
layout::{zone::ZoneWeight, Layout, NodeIndex},
};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Selection { pub struct Selection {
set: HashSet<NodeIndex>, pins: HashSet<String>,
primitives: HashSet<PrimitiveIndex>,
zones: HashSet<GenericIndex<ZoneWeight>>,
} }
impl Selection { impl Selection {
pub fn new() -> Selection { pub fn new() -> Selection {
Self { Self {
set: HashSet::new(), pins: HashSet::new(),
primitives: HashSet::new(),
zones: HashSet::new(),
} }
} }
pub fn toggle_at_node(&mut self, node: NodeIndex) { pub fn toggle_at_node(&mut self, layout: &Layout<impl RulesTrait>, node: NodeIndex) {
if !self.set.insert(node) { let maybe_pin = layout.node_pin(node);
self.set.remove(&node);
if let Some(ref pin) = maybe_pin {
if self.contains(node) {
self.remove_pin(layout, pin);
} else {
self.add_pin(layout, pin);
}
} }
} }
pub fn contains(&self, node: &NodeIndex) -> bool { fn add_pin(&mut self, layout: &Layout<impl RulesTrait>, pin: &String) {
self.set.contains(node) for primitive in layout.drawing().primitive_nodes().filter(|primitive| {
layout
.node_pin(NodeIndex::Primitive(*primitive))
.is_some_and(|p| p == pin)
}) {
self.primitives.insert(primitive);
}
for zone in layout.zone_nodes().filter(|zone| {
layout
.node_pin(NodeIndex::Compound(*zone))
.is_some_and(|p| p == pin)
}) {
self.zones.insert(zone);
}
self.pins.insert(pin.clone());
}
fn remove_pin(&mut self, layout: &Layout<impl RulesTrait>, pin: &String) {
for primitive in layout.drawing().primitive_nodes().filter(|primitive| {
layout
.node_pin(NodeIndex::Primitive(*primitive))
.is_some_and(|p| p == pin)
}) {
self.primitives.remove(&primitive);
}
for zone in layout.zone_nodes().filter(|zone| {
layout
.node_pin(NodeIndex::Compound(*zone))
.is_some_and(|p| p == pin)
}) {
self.zones.remove(&zone);
}
self.pins.remove(pin);
}
pub fn contains(&self, node: NodeIndex) -> bool {
match node {
NodeIndex::Primitive(primitive) => self.primitives.contains(&primitive),
NodeIndex::Compound(zone) => self.zones.contains(&zone),
}
} }
} }

View File

@ -323,7 +323,7 @@ impl eframe::App for App {
let color = if shared_data.highlighteds.contains(&primitive) let color = if shared_data.highlighteds.contains(&primitive)
|| overlay || overlay
.selection() .selection()
.contains(&GenericNode::Primitive(primitive)) .contains(GenericNode::Primitive(primitive))
{ {
egui::Color32::from_rgb(100, 100, 255) egui::Color32::from_rgb(100, 100, 255)
} else { } else {
@ -333,8 +333,8 @@ impl eframe::App for App {
} }
for zone in layout.layer_zone_nodes(1) { for zone in layout.layer_zone_nodes(1) {
let color = let color = if overlay.selection().contains(GenericNode::Compound(zone))
if overlay.selection().contains(&GenericNode::Compound(zone)) { {
egui::Color32::from_rgb(100, 100, 255) egui::Color32::from_rgb(100, 100, 255)
} else { } else {
egui::Color32::from_rgb(52, 52, 200) egui::Color32::from_rgb(52, 52, 200)
@ -348,7 +348,7 @@ impl eframe::App for App {
let color = if shared_data.highlighteds.contains(&primitive) let color = if shared_data.highlighteds.contains(&primitive)
|| overlay || overlay
.selection() .selection()
.contains(&GenericNode::Primitive(primitive)) .contains(GenericNode::Primitive(primitive))
{ {
egui::Color32::from_rgb(255, 100, 100) egui::Color32::from_rgb(255, 100, 100)
} else { } else {
@ -358,8 +358,8 @@ impl eframe::App for App {
} }
for zone in layout.layer_zone_nodes(0) { for zone in layout.layer_zone_nodes(0) {
let color = let color = if overlay.selection().contains(GenericNode::Compound(zone))
if overlay.selection().contains(&GenericNode::Compound(zone)) { {
egui::Color32::from_rgb(255, 100, 100) egui::Color32::from_rgb(255, 100, 100)
} else { } else {
egui::Color32::from_rgb(200, 52, 52) egui::Color32::from_rgb(200, 52, 52)

View File

@ -73,7 +73,7 @@ impl Overlay {
}; };
if shape.contains_point(p) { if shape.contains_point(p) {
self.selection.toggle_at_node(node); self.selection.toggle_at_node(layout, node);
return true; return true;
} }
false false

View File

@ -85,7 +85,7 @@ impl<R: RulesTrait> Layout<R> {
weight: FixedDotWeight, weight: FixedDotWeight,
zone: GenericIndex<ZoneWeight>, zone: GenericIndex<ZoneWeight>,
) -> Result<FixedDotIndex, Infringement> { ) -> Result<FixedDotIndex, Infringement> {
let pin = self.node_to_pin.get(&GenericNode::Compound(zone)); let pin = self.node_pin(GenericNode::Compound(zone));
let maybe_dot = self.drawing.add_fixed_dot(weight); let maybe_dot = self.drawing.add_fixed_dot(weight);
if let Ok(dot) = maybe_dot { if let Ok(dot) = maybe_dot {
@ -119,7 +119,7 @@ impl<R: RulesTrait> Layout<R> {
weight: FixedSegWeight, weight: FixedSegWeight,
zone: GenericIndex<ZoneWeight>, zone: GenericIndex<ZoneWeight>,
) -> Result<FixedSegIndex, Infringement> { ) -> Result<FixedSegIndex, Infringement> {
let pin = self.node_to_pin.get(&GenericNode::Compound(zone)); let pin = self.node_pin(GenericNode::Compound(zone));
let maybe_seg = self.add_fixed_seg(from, to, weight, pin.cloned()); let maybe_seg = self.add_fixed_seg(from, to, weight, pin.cloned());
if let Ok(seg) = maybe_seg { if let Ok(seg) = maybe_seg {
@ -173,6 +173,10 @@ impl<R: RulesTrait> Layout<R> {
self.drawing.compounds(node) self.drawing.compounds(node)
} }
pub fn node_pin(&self, node: NodeIndex) -> Option<&String> {
self.node_to_pin.get(&node)
}
pub fn band_length(&self, face: DotIndex) -> f64 { pub fn band_length(&self, face: DotIndex) -> f64 {
// TODO. // TODO.
0.0 0.0