Skip to main content

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}