flow_rs_core/layout/algorithms/
grid.rs

1//! Grid layout algorithm implementation
2
3use crate::error::Result;
4use crate::graph::Graph;
5use crate::layout::LayoutAlgorithm;
6use crate::types::Position;
7
8/// Simple grid layout
9#[derive(Debug, Clone)]
10pub struct GridLayout {
11    pub columns: Option<usize>,
12    pub cell_width: f64,
13    pub cell_height: f64,
14    pub margin: f64,
15}
16
17impl Default for GridLayout {
18    fn default() -> Self {
19        Self {
20            columns: None, // Auto-calculate based on sqrt
21            cell_width: 120.0,
22            cell_height: 80.0,
23            margin: 20.0,
24        }
25    }
26}
27
28impl GridLayout {
29    /// Create a new grid layout
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    /// Set the number of columns (None for auto)
35    pub fn columns(mut self, columns: Option<usize>) -> Self {
36        self.columns = columns;
37        self
38    }
39
40    /// Set cell dimensions
41    pub fn cell_size(mut self, width: f64, height: f64) -> Self {
42        self.cell_width = width;
43        self.cell_height = height;
44        self
45    }
46
47    /// Set margin between cells
48    pub fn margin(mut self, margin: f64) -> Self {
49        self.margin = margin;
50        self
51    }
52}
53
54impl<N, E> LayoutAlgorithm<N, E> for GridLayout {
55    fn name(&self) -> &str {
56        "Grid"
57    }
58
59    fn apply(&mut self, graph: &mut Graph<N, E>) -> Result<()> {
60        let nodes: Vec<_> = graph.nodes_mut().collect();
61        let node_count = nodes.len();
62
63        if node_count == 0 {
64            return Ok(());
65        }
66
67        // Calculate columns
68        let columns = self
69            .columns
70            .unwrap_or_else(|| (node_count as f64).sqrt().ceil() as usize);
71
72        // Ensure columns is at least 1 to avoid division by zero
73        let columns = columns.max(1);
74
75        // Position nodes in grid
76        for (i, node) in nodes.into_iter().enumerate() {
77            let row = i / columns;
78            let col = i % columns;
79
80            let x = col as f64 * (self.cell_width + self.margin);
81            let y = row as f64 * (self.cell_height + self.margin);
82
83            node.position = Position::new(x, y);
84        }
85
86        Ok(())
87    }
88}