git.lucas.co / cce-designer
graphic design tool
git clone https://git.lucas.co/cce-designer.git

commit183d064097aa010c68b59dde9185b87f071e4bc4
parent72bf6bb7b5
authorLucas Galante <[email protected]>
date2026-07-18 15:24
refactor: rename the graph grid's skipped_* keys to gap_*

`skipped_row_h`/`skipped_col_w` are the gap between grid cells, so call them
`gap_row_h`/`gap_col_w` — across the GraphSettings keys that land in state.kdl,
the State fields, and their use sites.

Serde aliases keep a state.kdl written under the old names loading; the next
save rewrites it. Checked against a real pre-rename file: the grid still renders
at its saved 71 + 14 pitch rather than falling back to the 80 + 20 defaults.

The step from one node slot to the next stays derived at the use sites as
cell + gap — there is no key for it, and the struct now says so.

cce-ui's `set_skipped_sizes` keeps its name: it is a shared toolkit API rather
than a key, and lives in another repo.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

 src/app.rs    | 77 ++++++++++++++++++++++++++++++++---------------------------
 src/main.rs   | 26 ++++++++++++++++++--
 src/render.rs |  4 ++--
 src/window.rs |  4 ++--
 4 files changed, 70 insertions(+), 41 deletions(-)

diff --git a/src/app.rs b/src/app.rs
index 665c97b..0c1a644 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -496,12 +496,19 @@ impl Default for ViewportSettings {
     }
 }
 
+/// The node grid's cell size and the gap between cells. The step from one node slot to the
+/// next is the two added up — there is no separate key for it.
+///
+/// The gaps were `skipped_row_h`/`skipped_col_w`; the aliases keep state.kdl files written
+/// under the old names loading, and the next save rewrites them.
 #[derive(Serialize, Deserialize, Clone, Debug)]
 pub struct GraphSettings {
     pub grid_size_x: f32,
     pub grid_size_y: f32,
-    pub skipped_row_h: f32,
-    pub skipped_col_w: f32,
+    #[serde(alias = "skipped_row_h")]
+    pub gap_row_h: f32,
+    #[serde(alias = "skipped_col_w")]
+    pub gap_col_w: f32,
 }
 
 impl Default for GraphSettings {
@@ -509,8 +516,8 @@ impl Default for GraphSettings {
         Self {
             grid_size_x: 80.0,
             grid_size_y: 40.0,
-            skipped_row_h: 20.0,
-            skipped_col_w: 20.0,
+            gap_row_h: 20.0,
+            gap_col_w: 20.0,
         }
     }
 }
@@ -957,8 +964,8 @@ pub struct State {
     pub network_grid_visible: bool,
     pub grid_size_x: f32,
     pub grid_size_y: f32,
-    pub skipped_row_h: f32,
-    pub skipped_col_w: f32,
+    pub gap_row_h: f32,
+    pub gap_col_w: f32,
 
     pub pan_x: f32,
     pub pan_y: f32,
@@ -1196,8 +1203,8 @@ impl State {
             graph: GraphSettings {
                 grid_size_x: self.grid_size_x,
                 grid_size_y: self.grid_size_y,
-                skipped_row_h: self.skipped_row_h,
-                skipped_col_w: self.skipped_col_w,
+                gap_row_h: self.gap_row_h,
+                gap_col_w: self.gap_col_w,
             },
         };
         settings.save();
@@ -1609,8 +1616,8 @@ impl State {
             "Reset Zoom" => {
                 self.grid_size_x = 150.0;
                 self.grid_size_y = 75.0;
-                self.skipped_col_w = 37.5;
-                self.skipped_row_h = 37.5;
+                self.gap_col_w = 37.5;
+                self.gap_row_h = 37.5;
                 self.sync_grid_settings();
             }
             "Detach Circular Window" | "Detach Pane" => {
@@ -2635,8 +2642,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
             network_grid_visible: true,
             grid_size_x: settings.graph.grid_size_x,
             grid_size_y: settings.graph.grid_size_y,
-            skipped_row_h: settings.graph.skipped_row_h,
-            skipped_col_w: settings.graph.skipped_col_w,
+            gap_row_h: settings.graph.gap_row_h,
+            gap_col_w: settings.graph.gap_col_w,
             pan_x,
             pan_y,
             pan_velocity_x: 0.0,
@@ -2795,15 +2802,15 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
         let network_grid_visible = self.network_grid_visible;
         let grid_size_x = self.grid_size_x;
         let grid_size_y = self.grid_size_y;
-        let skipped_row_h = self.skipped_row_h;
-        let skipped_col_w = self.skipped_col_w;
+        let gap_row_h = self.gap_row_h;
+        let gap_col_w = self.gap_col_w;
         let pan_x = self.pan_x;
         let pan_y = self.pan_y;
         let grid_snap_enabled = self.grid_snap_enabled;
         let graph = self.graph_mut();
         graph.set_show_network_grid(network_grid_visible);
         graph.set_grid_sizes(grid_size_x, grid_size_y);
-        graph.set_skipped_sizes(skipped_row_h, skipped_col_w);
+        graph.set_skipped_sizes(gap_row_h, gap_col_w);
         graph.set_grid_origin(active_node_area_x + pan_x, active_node_area_y + pan_y);
         graph.set_grid_snap_enabled(grid_snap_enabled);
         if let Some(graph) = self.slots.content.as_any_mut().downcast_mut::<cce_ui::widget::Graph>() {
@@ -2916,8 +2923,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
             return;
         }
 
-        let old_row_h = self.skipped_row_h;
-        let old_col_w = self.skipped_col_w;
+        let old_row_h = self.gap_row_h;
+        let old_col_w = self.gap_col_w;
 
         let node_area_y = self.positions[CONTENT_IDX].1;
         let (cx, cy) = match center {
@@ -2940,8 +2947,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
 
         self.grid_size_x = new_gx;
         self.grid_size_y = new_gy;
-        self.skipped_row_h = old_row_h * (new_gy / old_gy);
-        self.skipped_col_w = old_col_w * (new_gx / old_gx);
+        self.gap_row_h = old_row_h * (new_gy / old_gy);
+        self.gap_col_w = old_col_w * (new_gx / old_gx);
 
         self.sync_grid_settings();
     }
@@ -2950,8 +2957,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
     pub fn keep_cursor_in_view(&mut self) {
         let (px, py, pw, ph) = self.positions[CONTENT_IDX];
 
-        let cx = px + self.grid_cursor_col as f32 * (self.grid_size_x + self.skipped_col_w) + self.pan_x;
-        let cy = py + self.grid_cursor_row as f32 * (self.grid_size_y + self.skipped_row_h) + self.pan_y;
+        let cx = px + self.grid_cursor_col as f32 * (self.grid_size_x + self.gap_col_w) + self.pan_x;
+        let cy = py + self.grid_cursor_row as f32 * (self.grid_size_y + self.gap_row_h) + self.pan_y;
         let cw = self.grid_size_x;
         let ch = self.grid_size_y;
 
@@ -4148,8 +4155,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
 
                         if *button == MouseButton::Right {
                             if !dialog_open && in_circle_network_pane {
-                                let col = ((self.cursor_x - node_area_x - self.pan_x) / (self.grid_size_x + self.skipped_col_w)).floor() as i32;
-                                let row = ((self.cursor_y - node_area_y - self.pan_y) / (self.grid_size_y + self.skipped_row_h)).floor() as i32;
+                                let col = ((self.cursor_x - node_area_x - self.pan_x) / (self.grid_size_x + self.gap_col_w)).floor() as i32;
+                                let row = ((self.cursor_y - node_area_y - self.pan_y) / (self.grid_size_y + self.gap_row_h)).floor() as i32;
                                 self.grid_cursor_col = col;
                                 self.grid_cursor_row = row;
                                 self.open_node_palette();
@@ -4251,8 +4258,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
                             self.sync_parameters_to_project();
                         }
                         if click_target.is_none() && !dialog_open && in_circle_network_pane {
-                            let col = ((self.cursor_x - node_area_x - self.pan_x) / (self.grid_size_x + self.skipped_col_w)).floor() as i32;
-                            let row = ((self.cursor_y - node_area_y - self.pan_y) / (self.grid_size_y + self.skipped_row_h)).floor() as i32;
+                            let col = ((self.cursor_x - node_area_x - self.pan_x) / (self.grid_size_x + self.gap_col_w)).floor() as i32;
+                            let row = ((self.cursor_y - node_area_y - self.pan_y) / (self.grid_size_y + self.gap_row_h)).floor() as i32;
                             self.grid_cursor_col = col;
                             self.grid_cursor_row = row;
                             changed = true;
@@ -4299,8 +4306,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
                                         self.grid_cursor_row = pos.1 as i32;
                                     }
                                 } else {
-                                    let col = ((self.cursor_x - node_area_x - self.pan_x) / (self.grid_size_x + self.skipped_col_w)).floor() as i32;
-                                    let row = ((self.cursor_y - node_area_y - self.pan_y) / (self.grid_size_y + self.skipped_row_h)).floor() as i32;
+                                    let col = ((self.cursor_x - node_area_x - self.pan_x) / (self.grid_size_x + self.gap_col_w)).floor() as i32;
+                                    let row = ((self.cursor_y - node_area_y - self.pan_y) / (self.grid_size_y + self.gap_row_h)).floor() as i32;
                                     self.grid_cursor_col = col;
                                     self.grid_cursor_row = row;
                                     changed = true;
@@ -4595,8 +4602,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
                                                 if active_nodes == 0 {
                                                     self.grid_size_x = 80.0;
                                                     self.grid_size_y = 40.0;
-                                                    self.skipped_col_w = 20.0;
-                                                    self.skipped_row_h = 20.0;
+                                                    self.gap_col_w = 20.0;
+                                                    self.gap_row_h = 20.0;
                                                     self.pan_x = 20.0;
                                                     self.pan_y = 20.0;
                                                 } else {
@@ -4642,8 +4649,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
 
                                                     self.grid_size_x = (base_gx * f).clamp(30.0, 500.0);
                                                     self.grid_size_y = (base_gy * f).clamp(15.0, 250.0);
-                                                    self.skipped_col_w = base_col_w * f;
-                                                    self.skipped_row_h = base_row_h * f;
+                                                    self.gap_col_w = base_col_w * f;
+                                                    self.gap_row_h = base_row_h * f;
 
                                                     let mut actual_xmin = f32::MAX;
                                                     let mut actual_xmax = f32::MIN;
@@ -4652,9 +4659,9 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
 
                                                     for slot_idx in 0..active_nodes {
                                                         let (col, row) = self.current_dir().children[slot_idx].position;
-                                                        let x_min = col * (self.grid_size_x + self.skipped_col_w);
+                                                        let x_min = col * (self.grid_size_x + self.gap_col_w);
                                                         let x_max = x_min + self.grid_size_x;
-                                                        let y_min = row * (self.grid_size_y + self.skipped_row_h);
+                                                        let y_min = row * (self.grid_size_y + self.gap_row_h);
                                                         let y_max = y_min + self.grid_size_y;
 
                                                         if x_min < actual_xmin { actual_xmin = x_min; }
@@ -4801,8 +4808,8 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
                          self.square_viewport = settings.viewport.square;
                          self.grid_size_x = settings.graph.grid_size_x;
                          self.grid_size_y = settings.graph.grid_size_y;
-                         self.skipped_row_h = settings.graph.skipped_row_h;
-                         self.skipped_col_w = settings.graph.skipped_col_w;
+                         self.gap_row_h = settings.graph.gap_row_h;
+                         self.gap_col_w = settings.graph.gap_col_w;
                          self.grid_thickness = settings.viewport.grid_thickness;
                          self.viewport_mut().show_grid = settings.viewport.show_grid_enabled;
                          self.viewport_mut().show_cube = settings.viewport.show_cube_enabled;
diff --git a/src/main.rs b/src/main.rs
index b9e455d..0497c1a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -433,8 +433,8 @@ mod tests {
             "graph": {
                 "grid_size_x": 80.0,
                 "grid_size_y": 40.0,
-                "skipped_row_h": 20.0,
-                "skipped_col_w": 20.0
+                "gap_row_h": 20.0,
+                "gap_col_w": 20.0
             }
         }
         "#;
@@ -444,6 +444,28 @@ mod tests {
         assert_eq!(settings.viewport.camera_pivot_size, 1.0);
         assert_eq!(settings.viewport.grid_color, [0.35, 0.35, 0.40]);
         
+        assert_eq!(settings.graph.gap_row_h, 20.0);
+        assert_eq!(settings.graph.gap_col_w, 20.0);
+
+        // A state.kdl written before the rename still loads: the gaps were skipped_row_h /
+        // skipped_col_w, and the aliases carry those onto the new fields.
+        let legacy = r#"
+        {
+            "graph": {
+                "grid_size_x": 71.0,
+                "grid_size_y": 31.0,
+                "skipped_row_h": 12.0,
+                "skipped_col_w": 14.0
+            }
+        }
+        "#;
+        let migrated: DesignSettings = serde_json::from_str(legacy).unwrap();
+        assert_eq!(migrated.graph.gap_row_h, 12.0);
+        assert_eq!(migrated.graph.gap_col_w, 14.0);
+        // ...and saving writes the new names back out.
+        let rewritten = serde_json::to_string(&migrated).unwrap();
+        assert!(rewritten.contains("gap_row_h") && !rewritten.contains("skipped_row_h"));
+
         let serialized = serde_json::to_string(&settings).unwrap();
         let settings_roundtrip: DesignSettings = serde_json::from_str(&serialized).unwrap();
         assert_eq!(settings_roundtrip.viewport.show_camera_pivot_enabled, false);
diff --git a/src/render.rs b/src/render.rs
index ee34fde..f36ca5b 100644
--- a/src/render.rs
+++ b/src/render.rs
@@ -194,8 +194,8 @@ impl State {
             if show_cursor {
                 let px = self.positions[CONTENT_IDX].0;
                 let py = self.positions[CONTENT_IDX].1;
-                let cx = px + self.grid_cursor_col as f32 * (self.grid_size_x + self.skipped_col_w) + self.pan_x;
-                let cy = py + self.grid_cursor_row as f32 * (self.grid_size_y + self.skipped_row_h) + self.pan_y;
+                let cx = px + self.grid_cursor_col as f32 * (self.grid_size_x + self.gap_col_w) + self.pan_x;
+                let cy = py + self.grid_cursor_row as f32 * (self.grid_size_y + self.gap_row_h) + self.pan_y;
                 let cw = self.grid_size_x;
                 let ch = self.grid_size_y;
                 let thickness = 2.0;
diff --git a/src/window.rs b/src/window.rs
index 4345606..9052872 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -172,8 +172,8 @@ impl State {
                         2 => { // Reset Zoom
                             state.grid_size_x = 150.0;
                             state.grid_size_y = 75.0;
-                            state.skipped_col_w = 37.5;
-                            state.skipped_row_h = 37.5;
+                            state.gap_col_w = 37.5;
+                            state.gap_row_h = 37.5;
                             state.sync_grid_settings();
                             changed = true;
                         }