# Color Palette Panel — Persistence & Layout Fixes ## Problem Statement The iced GUI color palette panel has several issues: 1. **Colors don't persist between sessions** — bg color changes are never saved (bug in `BgColorChanged` handler), and save failures are silently ignored 2. **Reset button** should return to black/white (already works correctly) 3. **Recent colors don't persist** — same root cause as #1 (dirty flag issue) 4. **Panel minimum height** is too low (180px) — contents get clipped, especially the color wheel (220px canvas) ## Root Cause Analysis ### Bug 1: BgColorChanged never persists (PRIMARY ISSUE) In `app.rs:2352-2356`, the `BgColorChanged` handler does NOT set `self.colors_dirty = true`: ```rust Message::BgColorChanged(color) => { self.bg_color = color; // MISSING: self.colors_dirty = true; crate::shape_sync::sync_shape_from_tool(self); self.refresh_composite_if_needed(); } ``` Compare with `FgColorChanged` (line 2347) which DOES set it. This means background color changes are never written to disk. ### Bug 2: Save order issue In `app.rs:8845-8848`, the dirty flag is cleared BEFORE the save: ```rust if self.colors_dirty { self.colors_dirty = false; // cleared first save_colors(...); // save second — if this fails, flag is already cleared } ``` If `save_colors` fails (e.g., directory doesn't exist), the flag is already cleared and the save won't retry. ### Bug 3: Silent save failures `save_colors()` uses `let _ = std::fs::write(...)` which discards errors. If `~/.config/hcie-iced/` doesn't exist, writes fail silently. ## Implementation Plan ### Step 1: Fix BgColorChanged persistence **File:** `hcie-iced-app/crates/hcie-iced-gui/src/app.rs` (line ~2354) Add `self.colors_dirty = true;` to the handler. ### Step 2: Fix save order **File:** `hcie-iced-app/crates/hcie-iced-gui/src/app.rs` (line 8845-8848) Swap the order — save first, then clear the flag: ```rust if self.colors_dirty { save_colors(self.fg_color, self.bg_color, &self.recent_colors); self.colors_dirty = false; } ``` ### Step 3: Add directory creation in save_colors **File:** `hcie-iced-app/crates/hcie-iced-gui/src/app.rs` (line 93-101) Add `create_dir_all` before writing: ```rust fn save_colors(fg: [u8; 4], bg: [u8; 4], recent: &[[u8; 4]]) { let path = colors_path(); if let Some(parent) = path.parent() { let _ = std::fs::create_dir_all(parent); } // ... rest unchanged } ``` ### Step 4: Increase panel minimum height **File:** `hcie-iced-app/crates/hcie-iced-gui/src/dock/sizing.rs` (line 70-73) Change ColorPicker policy: ```rust PaneType::ColorPicker => PaneSizePolicy { width: axis(180.0, 280.0, 380.0, 1), height: axis(300.0, 420.0, 500.0, 1), } ``` Rationale for values: - **Min 300px**: Shows swatch row, hex input, alpha slider, tab bar, and start of color wheel - **Preferred 420px**: Shows full color wheel (220px canvas) + header + recent colors without scrolling - **Max 500px**: Bounded to prevent stealing vertical space from sibling panels (Layers has grow_priority=35 vs color's 1) ### Step 5: Update test assertions **File:** `hcie-iced-app/crates/hcie-iced-gui/src/dock/sizing.rs` Tests to update: 1. `policy_values_prioritize_canvas_and_bound_color_picker` (line 437-441): Update preferred/max values 2. `subtree_constraints_follow_split_axis` (line 453): Update `height.max` assertion (Layers has INFINITY max, so shared axis max becomes INFINITY) 3. `color_picker_does_not_receive_vertical_surplus_with_list_sibling` (line 494): Update max bound check ## Files to Modify 1. `hcie-iced-app/crates/hcie-iced-gui/src/app.rs` — 3 changes (BgColorChanged fix, save order, create_dir_all) 2. `hcie-iced-app/crates/hcie-iced-gui/src/dock/sizing.rs` — policy update + 3 test updates ## Verification 1. Launch app, change both fg and bg colors, close and reopen — both should be restored 2. Click "D" button — fg=black, bg=white 3. Select several colors, close/reopen — recent colors preserved 4. Resize color palette pane to minimum — color wheel and recent colors visible 5. `cargo test -p hcie-iced-gui` — all tests pass