flow_rs_core/layout/algorithms/
grid.rs1use crate::error::Result;
4use crate::graph::Graph;
5use crate::layout::LayoutAlgorithm;
6use crate::types::Position;
7
8#[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, cell_width: 120.0,
22 cell_height: 80.0,
23 margin: 20.0,
24 }
25 }
26}
27
28impl GridLayout {
29 pub fn new() -> Self {
31 Self::default()
32 }
33
34 pub fn columns(mut self, columns: Option<usize>) -> Self {
36 self.columns = columns;
37 self
38 }
39
40 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 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 let columns = self
69 .columns
70 .unwrap_or_else(|| (node_count as f64).sqrt().ceil() as usize);
71
72 let columns = columns.max(1);
74
75 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}