openquiver_graph/layout.rs
1//! Node positions on the canvas.
2
3use std::collections::BTreeMap;
4
5use crate::NodeName;
6
7/// Node positions on the canvas.
8///
9/// Coordinates live beside the graph, not inside `Node`, for the same reason
10/// comments do: they are keyed by identity and must move when a node is
11/// renamed. They are kept in the same *file* as the logic, though — a separate
12/// file would drift silently, and a drifted layout scatters the canvas exactly
13/// when the graph most needs reading.
14///
15/// Integers, not floats: canvas positions snap to a grid, and exact values
16/// round-trip without formatting decisions.
17#[derive(Debug, Clone, Default, PartialEq, Eq)]
18pub struct Layout(pub(crate) BTreeMap<NodeName, (i32, i32)>);
19
20impl Layout {
21 pub fn get(&self, name: &str) -> Option<(i32, i32)> {
22 if name.is_ascii() {
23 return self.0.get(name).copied();
24 }
25 self.0.get(&NodeName::new(name)).copied()
26 }
27
28 pub fn set(&mut self, name: NodeName, at: (i32, i32)) {
29 self.0.insert(name, at);
30 }
31
32 /// Positions in canonical order, by node name.
33 pub fn iter(&self) -> impl Iterator<Item = (&NodeName, (i32, i32))> {
34 self.0.iter().map(|(name, at)| (name, *at))
35 }
36
37 pub fn is_empty(&self) -> bool {
38 self.0.is_empty()
39 }
40}