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

commit483095dc1c8b5b8706125ead80ebd2c3d3ca922d
parent8112c63590
authorLucas Galante <lsgalante12@gmail.com>
date2026-10-07 00:46
fix(network): a second editor hidden behind the network loads closed

Taking the network out of the docks made the next tab in the dock it
fronted come to the front. In a save where the second network editor
waited behind the network, that put a second graph where the network's
plate had been. A second editor waiting behind the network now loads
closed, as it was hidden; one that was in front stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

 CLAUDE.md      |  5 ++++-
 src/main.rs    | 34 ++++++++++++++++++++++++++++++++++
 src/project.rs | 16 ++++++++++++++++
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/CLAUDE.md b/CLAUDE.md
index c6282a6..9c02e12 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -2797,7 +2797,10 @@ no menu: the network menu's Plate page went the next day, Detach being the
 palette's `detach_circular_window` — and
 `set_pane_collapsed` refuses it; the pane-state load takes it out of an
 older save's tab lists, the dock it fronted fronting its next tab or
-emptying (`the_params_hud_is_under_the_plates_and_stops_above_the_bottom_ones`
+emptying — except a second editor that waited behind it, which loads
+CLOSED: it was hidden, and fronting it put a second graph where the
+network's plate had been (`a_second_editor_hidden_behind_the_network_loads_closed`;
+the user's own project did exactly that the day the network left the docks) (`the_params_hud_is_under_the_plates_and_stops_above_the_bottom_ones`
 loads one). `plate_at` never answers the network. The left dock's right edge
 resizes whatever plate is docked there (`on_left_dock_resize_edge`,
 `AppDrag::LeftDockResize`, writing `floating_network_layout.2`, which kept
diff --git a/src/main.rs b/src/main.rs
index 397e5f8..3819b28 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1655,6 +1655,40 @@ mod tests {
         assert_eq!(state.positions[NETWORK_PANEL2_IDX].2, state.left_dock_width());
     }
 
+    /// An older save docked the network, the second editor sometimes waiting
+    /// behind it as a tab. Both load out of sight: the network in no dock,
+    /// and the second editor CLOSED, since it was hidden — fronting it would
+    /// put a second graph where the network's plate was. A second editor
+    /// that was in front stays where it was.
+    #[test]
+    fn a_second_editor_hidden_behind_the_network_loads_closed() {
+        use crate::app::{Dock, NO_PANE};
+        use crate::slots::{NETWORK_PANEL2_IDX, SPREADSHEET_IDX};
+        let dir = std::env::temp_dir().join(format!("cce-designer-hidden-editor-test-{}", std::process::id()));
+        let _ = fs::remove_dir_all(&dir);
+        let mut a = State::new(false);
+        a.save_to_file(&dir).expect("save");
+        let file = dir.join("state.json");
+        let load_with = |tabs: serde_json::Value| {
+            let mut json: serde_json::Value = serde_json::from_str(&fs::read_to_string(&file).unwrap()).unwrap();
+            json["view_state"]["dock_tabs"] = tabs;
+            fs::write(&file, serde_json::to_string(&json).unwrap()).unwrap();
+            let mut b = State::new(false);
+            b.load_from_file(&dir).expect("load");
+            b
+        };
+
+        let b = load_with(serde_json::json!([["network", "network2"], [], ["spreadsheet"]]));
+        assert_eq!(b.tab_dock_of_pane(NETWORK_PANEL2_IDX), None, "the hidden editor loads closed");
+        assert_eq!(b.pane_in_dock(Dock::Left), NO_PANE);
+        assert_eq!(b.pane_in_dock(Dock::Bottom), SPREADSHEET_IDX);
+
+        let b = load_with(serde_json::json!([["network2", "network"], [], ["spreadsheet"]]));
+        assert_eq!(b.pane_in_dock(Dock::Left), NETWORK_PANEL2_IDX, "a fronted editor stays");
+
+        let _ = fs::remove_dir_all(&dir);
+    }
+
     /// Move To Own Plate is offered only on a dock holding more than one
     /// tab. With neither the params pane nor the network in the docks, the
     /// two tab candidates share three docks, so a dock holding both always
diff --git a/src/project.rs b/src/project.rs
index a63e67d..32c56af 100644
--- a/src/project.rs
+++ b/src/project.rs
@@ -380,6 +380,22 @@ impl State {
             // taken out — a dock one fronted fronts its next tab, or is
             // empty.
             let undocked = |s: usize| s == crate::slots::PARAM_IDX || s == crate::slots::NETWORK_PANEL_IDX;
+            // A dock the network FRONTED showed the network alone: what
+            // waited behind it was hidden. The second editor waiting there
+            // is closed, not brought to the front where the network's plate
+            // was — it would appear as a second graph in the old dock's
+            // place, which is what a save of 2026-10-06 did on 2026-10-07.
+            // (The spreadsheet cannot be closed, and fronts.)
+            let resolved: Vec<Vec<usize>> = resolved
+                .into_iter()
+                .map(|tabs| {
+                    if tabs.first() == Some(&crate::slots::NETWORK_PANEL_IDX) {
+                        tabs.into_iter().filter(|&s| s != n2).collect()
+                    } else {
+                        tabs
+                    }
+                })
+                .collect();
             let resolved: Vec<Vec<usize>> = resolved
                 .into_iter()
                 .map(|tabs| tabs.into_iter().filter(|&s| !undocked(s)).collect())