feat(svg-editor): implement interactive SVG node editor with parsing and editing capabilities
feat(debug-logger): add DebugSignalLogger plugin for event logging and inspection feat(plugins): introduce built-in plugins module and integrate debug logger feat(plugin-integration): create integration layer for mapping Iced Messages to CoreEvents feat(plugin-registry): establish PluginRegistry for managing plugins and event dispatching
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
# ICED GUI Migration Plan — EGUI Full Parity
|
||||
|
||||
## Hedef
|
||||
|
||||
EGUI (`hcie-egui-app`) üzerindeki tüm özellik, panel, menü, dialog ve fonksiyonların ICED (`hcie-iced-app`) tarafına taşınarak %100 görsel ve işlevsel paritenin sağlanması.
|
||||
|
||||
## Kararlar
|
||||
|
||||
| Karar | Seçim |
|
||||
|-------|-------|
|
||||
| Panel crate yapısı | Gömülü kal (mevcut `hcie-iced-gui/src/panels/` içinde) |
|
||||
| Plugin sistemi | Kapsama al — EGUI'deki PluginHost ICED'e taşınacak |
|
||||
| SVG Editor | Kapsama al — yeni panel olarak eklenecek |
|
||||
| Menü placeholder'ları | Tümü aktifleştirilecek (full parity) |
|
||||
|
||||
---
|
||||
|
||||
## Faz 1: Kritik Eksik Yapılar (Temel)
|
||||
|
||||
### 1.1 Plugin Sistemi (`hcie-iced-gui/src/plugins/`)
|
||||
- [ ] **Kaynak:** `hcie-egui-app/crates/hcie-gui-egui/src/plugins/`
|
||||
- [ ] **Hedef:** `hcie-iced-app/crates/hcie-iced-gui/src/plugins/`
|
||||
- [ ] **Dosyalar:**
|
||||
- `mod.rs` — PluginHost struct, `dispatch_app_event()`, plugin lifecycle
|
||||
- `registry.rs` — PluginRegistry, kayıtlı plugin yönetimi
|
||||
- `integration.rs` — EGUI plugin UI'dan EventBus olay dağıtımı
|
||||
- `built_in/` — Built-in plugin örnekleri (debug_logger)
|
||||
- [ ] **Bağımlılık:** PluginHost `HcieApp` yerine `IcedDocument`+`ToolState` kullanacak şekilde adapte edilmeli
|
||||
- [ ] **Integration:** `app.rs` update() içinde `message` döngüsüne plugin dispatch eklenmeli
|
||||
|
||||
### 1.2 SVG Editor Panel
|
||||
- [ ] **Kaynak:** `hcie-egui-app/crates/hcie-gui-egui/src/app/panels/svg_editor_panel.rs`
|
||||
- [ ] **Hedef:** `hcie-iced-app/crates/hcie-iced-gui/src/panels/svg_editor.rs`
|
||||
- [ ] **Durum:** EGUI'de `SvgEditorState` struct + `show_svg_editor()` fonksiyonu. ICED'e `SvgEditorState` + view/update olarak taşınacak
|
||||
- [ ] **App state:** `HcieIcedApp` içine `svg_editor_state: Option<SvgEditorState>` eklenecek
|
||||
- [ ] **Panel:** view fonksiyonu normal panel gibi `panels/mod.rs` üzerinden erişilebilir
|
||||
|
||||
### 1.3 Save Error Dialog
|
||||
- [ ] **Kaynak:** EGUI `SaveErrorState` + error dialog render
|
||||
- [ ] **Hedef:** ICED `ActiveDialog::SaveError` varyantı + dialog view
|
||||
- [ ] **Özellik:** Kaydetme hatasında alternatif yol önerisi gösteren modal
|
||||
|
||||
### 1.4 Canvas Expand Dialog
|
||||
- [ ] **Kaynak:** EGUI `show_expand_dialog` + paste overflow handling
|
||||
- [ ] **Hedef:** ICED `ActiveDialog::ExpandCanvas` varyantı
|
||||
- [ ] **Özellik:** Clipboard paste sırasında tuval boyutunu aşan içerik için genişletme onayı
|
||||
|
||||
---
|
||||
|
||||
## Faz 2: Menü Eksikleri (Full Parity)
|
||||
|
||||
### 2.1 File Menüsü Eksikleri
|
||||
|
||||
| EGUI Öğesi | ICED Task |
|
||||
|---|---|
|
||||
| Import… | `MenuCommand::ImportFile` — `rfd::FileDialog` ile dosya seç, engine'e yükle |
|
||||
| Import SVG… | `MenuCommand::ImportSvg` — SVG dosyası aç, engine.import_svg() çağır |
|
||||
| Import Brushes… | `MenuCommand::ImportBrushes` — ABR/KPP parser, brush_presets'e ekle |
|
||||
| Export… | `MenuCommand::Export` — Save As ile aynı akış, farklı etiket |
|
||||
|
||||
### 2.2 Edit Menüsü Eksikleri
|
||||
|
||||
| EGUI Öğesi | ICED Task |
|
||||
|---|---|
|
||||
| Paste Special (Ctrl+Shift+V) | `MenuCommand::PasteSpecial` — Paste internal clipboard (transform olarak) |
|
||||
| Fill… (Shift+F5) | `MenuCommand::Fill` — Primary color ile seçim/layer doldurma |
|
||||
| Stroke… | `MenuCommand::Stroke` — Placeholder dialog (EGUI'de de placeholder) |
|
||||
| Free Transform (Ctrl+T) | `MenuCommand::FreeTransform` — `TransformStart` event'i, selection transform başlatma |
|
||||
| Preferences (Ctrl+K) | `MenuCommand::Preferences` — `ActiveDialog::Settings` dialog'u |
|
||||
|
||||
### 2.3 Tools Menüsü
|
||||
|
||||
- [ ] EGUI `tools` menüsündeki tüm tool'lar için `MenuCommand::SelectTool(Tool)` eklenecek
|
||||
- [ ] **Tool listesi:** Eyedropper, Pen, Brush, Eraser, Spray, FloodFill, MagicWand, Select, Lasso, PolygonSelect, Move, Crop, Text, Gradient
|
||||
- [ ] **Retouch alt menüsü:** `MenuCommand::SelectTool(Tool::RedEyeRemoval)`, `SpotRemoval`, `SmartPatch`
|
||||
- [ ] **AI alt menüsü:** `MenuCommand::SelectTool(Tool::AiObjectRemoval)`, `SmartSelect`, `VisionSelect`
|
||||
|
||||
### 2.4 Image Menüsü Eksikleri
|
||||
|
||||
| EGUI Öğesi | ICED Task |
|
||||
|---|---|
|
||||
| Image Rotation > 90° CW | `MenuCommand::Rotate90CW` → engine.rotate_canvas(90) |
|
||||
| Image Rotation > 90° CCW | `MenuCommand::Rotate90CCW` → engine.rotate_canvas(-90) |
|
||||
| Image Rotation > 180° | `MenuCommand::Rotate180` → engine.rotate_canvas(180) |
|
||||
| Flip Horizontal | `MenuCommand::FlipHorizontal` → engine.flip_horizontal() |
|
||||
| Flip Vertical | `MenuCommand::FlipVertical` → engine.flip_vertical() |
|
||||
| Crop | `MenuCommand::ImageCrop` → selection_rect varsa engine.crop() |
|
||||
| Invert / Negative | `MenuCommand::InvertNegative` → apply_filter("invert") |
|
||||
|
||||
### 2.5 Filter Menüsü Eksikleri
|
||||
|
||||
- [ ] **Distort:** `MenuCommand::FilterDistort(Pinch)`, `FilterDistort(Twirl)` — parametre dialog'u
|
||||
- [ ] **Noise:** `MenuCommand::FilterNoise(AddNoise)`, `FilterNoise(NoisePattern)`
|
||||
- [ ] **Pixelate:** `MenuCommand::FilterPixelate(Crystallize)`, `FilterPixelate(Mosaic)`
|
||||
- [ ] **Render:** `MenuCommand::FilterRender(Clouds)` — procedural texture
|
||||
- [ ] **Restore:** `MenuCommand::FilterRestore(Dehaze)`
|
||||
- [ ] **Stylize:** `FilterStylize(Emboss)`, `FilterStylize(FindEdges)`, `FilterStylize(OilPaint)`
|
||||
- [ ] **Procedural Textures (14 tür):** `FilterTexture(Grass)`, `FilterTexture(Sand)`, `FilterTexture(Dirt)`, `FilterTexture(Water)`, `FilterTexture(Rain)`, `FilterTexture(Stone)`, `FilterTexture(Bricks)`, `FilterTexture(Oak)`, `FilterTexture(Pine)`, `FilterTexture(DarkWood)`, `FilterTexture(Steel)`, `FilterTexture(Gold)`, `FilterTexture(Copper)`, `FilterTexture(Linen)`, `FilterTexture(Glass)`, `FilterTexture(SkyReplacement)`
|
||||
- [ ] **Kaynak:** EGUI `shell/menus.rs:ui_filter_menu()` fonksiyonundaki tüm filtre çağrıları
|
||||
|
||||
### 2.6 Select Menüsü Eksikleri
|
||||
|
||||
- [ ] **Erode Border:** `MenuCommand::ErodeBorder` → engine.selection_erode()
|
||||
- [ ] **Fade Border:** `MenuCommand::FadeBorder` → engine.selection_fade()
|
||||
|
||||
### 2.7 View Menüsü Eksikleri
|
||||
|
||||
- [ ] **Reset Pan:** `MenuCommand::ResetPan` → `doc.pan_offset = Vector::ZERO`
|
||||
|
||||
### 2.8 Window Menüsü Eksikleri
|
||||
|
||||
- [ ] **Open Documents list:** Aktif doküman listesi gösterimi, seçili olana focus
|
||||
- [ ] **Reset Layout:** Varsayılan dock düzenine dön
|
||||
|
||||
### 2.9 Layer Menüsü Eksikleri
|
||||
|
||||
- [ ] **Align:** `MenuCommand::AlignLayer(AlignAxis)` — tüm axis'ler için engine.align_active_layer()
|
||||
|
||||
### 2.10 Help Menüsü
|
||||
|
||||
- [ ] **About:** `ActiveDialog::About` — `dialogs/about.rs` mevcut, menü bağlantısı eklenecek
|
||||
|
||||
---
|
||||
|
||||
## Faz 3: Panel İçerik İyileştirmeleri
|
||||
|
||||
### 3.1 AI Assistant — ComfyUI Sekmesi
|
||||
- [ ] EGUI'de AI paneli 2 sekme: ComfyUI + AI Chat
|
||||
- [ ] ICED'de sadece AI Chat var
|
||||
- [ ] **Task:** ComfyUI pipeline görüntüleyici sekmesi eklenecek
|
||||
|
||||
### 3.2 Title Bar Özellikleri
|
||||
- [ ] **Search box:** EGUI title bar'da `title_search` alanı + TextEdit
|
||||
- [ ] **Panel list popup:** EGUI'de hamburger menü ikonu ile panel list toggle
|
||||
- [ ] **Window controls:** EGUI kendi minimize/maximize/close çiziyor. ICED'de `decorations(false)` ile aynı pattern
|
||||
|
||||
### 3.3 Thumbnails Panel
|
||||
- [ ] `panels/thumbnails.rs` mevcut — EGUI layers panel içinde thumbnail gösterimi ile uyum kontrolü
|
||||
- [ ] Layer thumbnail boyutları, badge'ler, efekt ikonları EGUI ile eşleştirilecek
|
||||
|
||||
---
|
||||
|
||||
## Faz 4: Dialog İyileştirmeleri
|
||||
|
||||
### 4.1 Filter Dialogları
|
||||
- [ ] EGUI'de her filter kategorisi için ayrı dialog flag'leri: `show_blur_dialog`, `show_sharpen_dialog`, `show_distort_dialog`, `show_stylize_dialog`, `show_color_light_dialog`, `show_restore_dialog`, `show_noise_pattern_dialog`, `show_procedural_textures_dialog`
|
||||
- [ ] ICED'de `ActiveDialog::FilterParams(FilterType)` ile tek dialog — yeterli mi kontrol et
|
||||
- [ ] EGUI `filter_dialogs.rs` ve `modern_dialogs.rs`'deki parametre UI'ları incelenmeli
|
||||
|
||||
### 4.2 Selection Op Dialog
|
||||
- [ ] EGUI `SelectionOpDialogState` ile Grow/Shrink/Feather/Erode/Fade için değer girişi
|
||||
- [ ] ICED `ActiveDialog::SelectionOp` mevcut ama Erode/Fade eklenmeli
|
||||
|
||||
---
|
||||
|
||||
## Faz 5: Viewer Mode Parity
|
||||
|
||||
### 5.1 Viewer Mode (FastStone-like)
|
||||
- [ ] EGUI viewer (`shell/viewer.rs`): `ViewerState`, thumbnail grid, directory tree, fullscreen
|
||||
- [ ] ICED viewer (`viewer/`): Mevcut, EGUI ile karşılaştırılmalı
|
||||
- [ ] **Eksik olabilir:** Önceki/Sonraki navigasyon, fullscreen toggle, thumbnail cache
|
||||
|
||||
---
|
||||
|
||||
## Faz 6: Görsel Tutarlılık
|
||||
|
||||
### 6.1 gui_layout.json Sistemi
|
||||
- [ ] EGUI'de `shell/gui_layout.rs` ile tüm panel boyut/padding/renk override'ları
|
||||
- [ ] ICED'de benzer bir sistem yok
|
||||
- [ ] **Task:** ICED için basitleştirilmiş layout override mekanizması
|
||||
|
||||
### 6.2 Tema Paletleri
|
||||
- [ ] EGUI'de 5 tema: Photoshop, PhotoshopLight, Amoled, ProDark, ProLight
|
||||
- [ ] ICED'de `ThemePreset` aynı seti kapsıyor mu kontrol et
|
||||
- [ ] `iced-panel-adapter` içindeki renk token'ları EGUI `ThemeColors` ile eşleştirilmeli
|
||||
|
||||
---
|
||||
|
||||
## Faz 7: Kod Temizliği ve Doğrulama
|
||||
|
||||
### 7.1 Dead Code Temizliği
|
||||
- [ ] EGUI `_dead_code_candidates_/` klasöründeki dosyalar incelenmeli
|
||||
- [ ] `panel_layout.rs`, `dock_controller.rs`, `dock_engine.rs`, `history.rs`
|
||||
|
||||
### 7.2 Test ve Doğrulama
|
||||
- [ ] `cargo test -p hcie-iced-gui` — mevcut testler
|
||||
- [ ] Görsel screenshot karşılaştırması
|
||||
- [ ] Her Faz sonunda `cargo check -p hcie-iced-gui` ile derleme kontrolü
|
||||
|
||||
---
|
||||
|
||||
## Faz Sıralaması ve Bağımlılıklar
|
||||
|
||||
```
|
||||
Faz 1 (Kritik Yapılar) ──→ Faz 2 (Menüler) ──→ Faz 3 (Paneller) ──→ Faz 4 (Dialoglar) ──→ Faz 5 (Viewer) ──→ Faz 6 (Görsel)
|
||||
│ │
|
||||
└── Plugin sistemi └── Tüm menü komutları aktif
|
||||
└── SVG Editor └── Import/Export
|
||||
└── Save Error Dialog
|
||||
└── Expand Canvas Dialog
|
||||
```
|
||||
|
||||
Her faz kendi içinde bağımsız çalışabilir. Faz 1 ön koşuldur çünkü yeni state alanları ve dialog varyantları sonraki fazlarda kullanılır.
|
||||
|
||||
---
|
||||
|
||||
## Riskler
|
||||
|
||||
1. **Plugin sistemi:** EGUI `EventBus` tabanlı, ICED Message tabanlı. Uyumlama sırasında event→message dönüşümü dikkatli yapılmalı
|
||||
2. **SVG Editor:** EGUI'de `hcie_engine_api::SvgEditable` kullanılıyor. Aynı API ICED'de de mevcut
|
||||
3. **Procedural Textures (14 adet):** Her biri ayrı filter_id + parametre seti. EGUI'deki parametre isimleri birebir korunmalı (örn. `"texture_grass"`, `"scale": 1.0, "roughness": 0.5`)
|
||||
4. **ComfyUI sekmesi:** EGUI'de AI paneli içinde iki sekme var. ICED'de AI panel widget'ının tab desteği eklenmeli
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notları
|
||||
|
||||
- **Yeni dosyalar eklenirken mevcut değiştirilmez** kuralı: Menü komutları `panels/menus.rs`'e, dialoglar `dialogs/`'a, yeni paneller `panels/`'e ek dosya olarak
|
||||
- `app.rs` `update()` fonksiyonuna yeni Message varyantları eklenecek
|
||||
- `app.rs` `view()` fonksiyonuna yeni panel/dialog view'ları bağlanacak
|
||||
- Engine API çağrıları EGUI ile birebir aynı (`hcie_engine_api::Engine`)
|
||||
- Görsel stiller `iced-panel-adapter::theme::ThemeColors` üzerinden
|
||||
@@ -0,0 +1,195 @@
|
||||
# ICED GUI — Advanced SVG Editor and UI/Color Fixes
|
||||
|
||||
## Scope
|
||||
|
||||
Implement the requested ICED improvements:
|
||||
|
||||
1. Replace the SVG coordinate-list dialog with an interactive visual node editor.
|
||||
2. Make filter-history behavior explicit and regression-tested.
|
||||
3. Widen filter sliders.
|
||||
4. Open Brushes when Brush is selected.
|
||||
5. Open Filters when a filter is selected from the menu.
|
||||
6. Add secondary-color selection by right-click in the color picker.
|
||||
|
||||
The following requests are already implemented and require verification rather than duplicate code:
|
||||
|
||||
- Recent colors persist in `~/.config/hcie-iced/colors.json`.
|
||||
- Foreground/background colors persist in the same file.
|
||||
- Recent color swatches already use `.on_right_press(Message::BgColorChanged(c))`.
|
||||
- Committed filters already enter history through `Engine::apply_filter()` and `push_draw_snapshot("Filter: <id>")`; only live preview uses `apply_filter_preview()` and correctly avoids history entries.
|
||||
|
||||
## Decisions
|
||||
|
||||
| Area | Decision |
|
||||
|---|---|
|
||||
| SVG geometry | Support polygon/line paths represented by existing `SvgEditable`; bezier/curve SVGs remain unsupported because the locked engine API rejects them. |
|
||||
| SVG live editing | Update the visible canvas preview and engine SVG on every node drag; create one logical edit session. Cancel restores the original SVG; Save keeps the current SVG. Do not create per-mouse-move history entries. |
|
||||
| SVG editor interaction | Add node drag, node hit testing, edge-midpoint node insertion, node deletion, polygon selection, numeric X/Y editing, zoom/pan, fit-to-view, grid/background, selection highlighting, keyboard Delete/Backspace, and Save/Cancel. |
|
||||
| SVG rendering | Use an `iced::widget::canvas::Canvas`/`canvas::Program`, following `canvas/viewport.rs` event and coordinate-mapping patterns. Keep the existing modal overlay and `Message`-driven app state. |
|
||||
| SVG engine history | Out of scope for GUI-only changes because `set_vector_shape_svg()` does not expose a vector-history snapshot API. Record this as a residual limitation; do not modify locked engine crates. |
|
||||
| Filter history | No behavior rewrite. Add regression coverage or an auditable helper around the existing `apply_filter()` path to prove committed filters are undoable and previews are not committed. |
|
||||
| Filter slider width | Make filter parameter sliders fill the available Filters pane width and ensure the Filters pane has a minimum width that leaves at least approximately 150px for the track. Use the existing responsive pane sizing rather than a hard-coded global width. |
|
||||
| Brush auto-open | On `Message::ToolSelected(Tool::Brush)`, reopen the Brushes pane only if it is closed. Never toggle an already-open pane closed. |
|
||||
| Filter auto-open | In the central `Message::FilterSelect` handler, reopen the Filters pane only if it is closed. This covers menu commands and other filter entry points consistently. |
|
||||
| Right-click secondary color | Add right-click handling to the HSL/color-picker canvas. Keep the main canvas right-click context menu unchanged. Recent swatch right-click behavior remains as-is. |
|
||||
|
||||
## Current Findings
|
||||
|
||||
- `panels/svg_editor.rs` currently displays polygon buttons and a coordinate list only; it has no visual canvas, no drag state, and no numeric editing.
|
||||
- EGUI’s reference editor has `svg_to_screen`, `screen_to_svg`, polygon rendering, node circles, midpoint hit testing, node dragging, add/remove controls, and a resizable canvas.
|
||||
- `SvgEditable` exposes `view_box`, `polygons`, `add_node`, `remove_node`, `move_node`, `from_svg`, and `to_svg`.
|
||||
- ICED already has interactive Canvas examples in `canvas/viewport.rs` and color picker programs in `color_picker.rs`.
|
||||
- `set_vector_shape_svg()` marks the vector layer/composite dirty and modified but does not push a vector history snapshot.
|
||||
- `Engine::apply_filter()` already snapshots the pre-filter pixels with description `Filter: <id>`; `apply_filter_preview()` intentionally does not.
|
||||
- `plain_slider()` uses `Length::Fill` internally, but filter content/pane sizing can leave its parent too narrow. The fix should make the filter slider row explicitly fill the panel and increase Filters sizing minimum if needed.
|
||||
- `Message::ToolSelected` currently changes the active tool but does not reopen Brushes.
|
||||
- `Message::FilterSelect` currently selects/preview-starts a filter but does not reopen Filters.
|
||||
- `recent_colors`/`fg_color`/`bg_color` load from and save to `colors.json`; recent swatches already support right-click secondary selection.
|
||||
|
||||
## Affected Files
|
||||
|
||||
### Advanced SVG editor
|
||||
|
||||
- `hcie-iced-app/crates/hcie-iced-gui/src/panels/svg_editor.rs`
|
||||
- Replace list-only layout with a visual editor canvas.
|
||||
- Extend editor state with drag state, original SVG/session state, zoom, pan, hover/selection state, and any fit/grid state needed by the canvas program.
|
||||
- Add coordinate conversion using `SvgEditable.view_box`, preserving aspect ratio and centering the viewBox.
|
||||
- Draw polygon fills/outlines, node handles, edge midpoint handles, grid/background, and selected-node styling.
|
||||
- Handle primary click/drag for node selection and movement, midpoint click for insertion, and wheel/secondary gestures for zoom/pan without interfering with modal buttons.
|
||||
- Keep controls for polygon selection, Add Node, Remove Node, X/Y numeric editing, Fit, Zoom +/- or reset, Save, and Cancel.
|
||||
|
||||
- `hcie-iced-app/crates/hcie-iced-gui/src/app.rs`
|
||||
- Add SVG canvas messages for pointer press/move/release, zoom/pan/fit, numeric X/Y changes, and any explicit node action needed by the new Program.
|
||||
- Update existing SVG editor handlers to mutate `SvgEditable` and immediately call `set_vector_shape_svg()` for live engine preview.
|
||||
- Capture the original SVG when opening; restore it on Cancel.
|
||||
- Keep Save/Cancel dialog lifecycle intact and ensure editor drag sessions do not create per-event history entries.
|
||||
|
||||
- `hcie-iced-app/crates/hcie-iced-gui/src/dock/view.rs` or editor call site only if required by the new state/signature.
|
||||
|
||||
### Filter and panel behavior
|
||||
|
||||
- `hcie-iced-app/crates/hcie-iced-gui/src/app.rs`
|
||||
- In `Message::ToolSelected`, call a new local helper or `dock.reopen_pane(PaneType::Brushes)` only when `!dock.is_pane_open(PaneType::Brushes)` and the selected tool is `Tool::Brush`.
|
||||
- In `Message::FilterSelect`, ensure `PaneType::Filters` is open before starting the preview.
|
||||
- Preserve the existing filter preview/commit lifecycle.
|
||||
- Add focused tests or testable helper coverage proving `apply_filter()` creates a history entry and `apply_filter_preview()` does not create a committed entry, if the current test architecture permits without engine changes.
|
||||
- Keep existing persistence code; add tests only if needed to prove colors/recent colors survive serialization/deserialization.
|
||||
|
||||
- `hcie-iced-app/crates/hcie-iced-gui/src/panels/filter_params.rs`
|
||||
- Make `float_slider()` and `int_slider()` return a control wrapped with `Length::Fill` at the row/container level so the track consumes the available panel width.
|
||||
- Avoid changing numeric behavior, labels, ranges, or parameter messages.
|
||||
|
||||
- `hcie-iced-app/crates/hcie-iced-gui/src/dock/sizing.rs`
|
||||
- Increase the Filters pane minimum/preferred width enough for a roughly 150px slider after label/value columns, while preserving responsive resizing and existing other-pane policies.
|
||||
|
||||
### Color picker
|
||||
|
||||
- `hcie-iced-app/crates/hcie-iced-gui/src/color_picker.rs`
|
||||
- Extend the interactive color wheel/picker Canvas program so right-click emits `Message::BgColorChanged` while left-click/drag continues emitting foreground changes.
|
||||
- Keep current color calculations and alpha behavior.
|
||||
- Ensure the picker’s displayed source color remains stable and right-click does not alter foreground.
|
||||
- Preserve existing recent-swatch `.on_right_press(Message::BgColorChanged(c))` behavior.
|
||||
|
||||
- `hcie-iced-app/crates/hcie-iced-gui/src/app.rs`
|
||||
- Confirm `BgColorChanged` updates secondary color, shape synchronization, and persistence state as appropriate.
|
||||
- Do not change main canvas right-click context-menu behavior.
|
||||
|
||||
## Ordered Implementation Tasks
|
||||
|
||||
### 1. SVG editor state and messages
|
||||
|
||||
1. Extend `SvgEditorState` with:
|
||||
- `original_svg: String` for Cancel restoration.
|
||||
- `drag_node: Option<(usize, usize)>`.
|
||||
- `zoom: f32` and `pan: Vector` or equivalent.
|
||||
- `hovered_node`/`hovered_midpoint` and fit/grid state if needed.
|
||||
2. Add `Message` variants for:
|
||||
- canvas pointer pressed/moved/released;
|
||||
- node X/Y field changes;
|
||||
- zoom/pan/fit/reset;
|
||||
- retain existing polygon/node/add/remove/save/cancel messages where reusable.
|
||||
3. On SVG editor open, store the original SVG alongside the parsed editable state.
|
||||
|
||||
### 2. SVG coordinate and rendering model
|
||||
|
||||
4. Implement `svg_to_screen()` and `screen_to_svg()` using the viewBox, canvas bounds, margin, zoom, and pan. Preserve aspect ratio so nodes are not distorted.
|
||||
5. Implement a Canvas Program that:
|
||||
- draws the viewBox background/grid;
|
||||
- draws each polygon/path fill and outline;
|
||||
- draws node handles with selected/hovered styles;
|
||||
- draws smaller edge midpoint handles;
|
||||
- uses `Cursor::position_in(bounds)` for hit testing;
|
||||
- maps drag positions back to SVG coordinates.
|
||||
6. Implement hit testing for nearest node and edge midpoint with screen-space thresholds that remain usable at different zoom levels.
|
||||
|
||||
### 3. SVG live editing behavior
|
||||
|
||||
7. On node press, select the polygon/node and begin drag.
|
||||
8. On node drag, call `editable.move_node(...)`, update the numeric fields, and immediately emit/apply the current `to_svg()` to the active vector shape for live canvas preview.
|
||||
9. On midpoint click, call `editable.add_node(...)` and update selection/live preview.
|
||||
10. On Delete/Backspace or Remove button, remove the selected node when valid and update/live-preview.
|
||||
11. Numeric X/Y edits update the selected node and live-preview.
|
||||
12. Save keeps the current SVG, clears the original/session state, closes the editor, and requests composite refresh.
|
||||
13. Cancel calls `set_vector_shape_svg()` with `original_svg`, refreshes the composite, clears session state, and closes without retaining edits.
|
||||
14. Handle empty polygons, invalid selection indices, unsupported bezier SVGs, and zero-sized viewBoxes without panics.
|
||||
|
||||
### 4. Filter/panel behavior
|
||||
|
||||
15. Add a small `ensure_pane_open(PaneType)` helper if repeated logic is useful; otherwise use `is_pane_open` + `reopen_pane` directly.
|
||||
16. Call it for Brush selection and Filter selection as specified above.
|
||||
17. Widen filter slider rows and increase Filters pane minimum sizing. Verify at narrow and wide pane widths.
|
||||
18. Verify committed filter history by applying a filter, checking the history description, undoing, and redoing. Do not add history entries during preview slider movement.
|
||||
|
||||
### 5. Color behavior
|
||||
|
||||
19. Add right-click output support to the color-wheel/picker Canvas Program.
|
||||
20. Verify left-click changes foreground, right-click changes background, recent swatch right-click changes background, and both colors/recent colors persist across restart.
|
||||
|
||||
## Risks and Edge Cases
|
||||
|
||||
1. **SVG curve limitation:** `SvgEditable::from_svg()` rejects QuadTo/CubicTo. Show/retain a clear parse failure path; do not silently flatten curves.
|
||||
2. **Live SVG update cost:** Updating the full SVG string on every drag is acceptable for the small vector shape payload, but avoid cloning unrelated document pixels.
|
||||
3. **Cancel correctness:** Capture the original SVG before the first live update. Cancel must restore it exactly, including after multiple node additions/removals.
|
||||
4. **SVG history limitation:** The public GUI-facing API has no vector snapshot method for `set_vector_shape_svg()`. Do not modify locked engine crates in this scope; document that SVG edits are not currently represented as a dedicated undo entry.
|
||||
5. **Filter history semantics:** Do not push history from slider-preview events. Only the final `FilterApply`/direct `apply_filter` call should be undoable.
|
||||
6. **Pane reopening:** Use `reopen_pane` only when closed; calling `toggle_pane` would incorrectly close an already visible pane.
|
||||
7. **Color picker right-click:** Keep canvas context-menu right-click untouched; limit the new behavior to color picker surfaces.
|
||||
8. **Color persistence:** Avoid resetting `recent_colors`, `fg_color`, or `bg_color` during app initialization after `load_colors()`.
|
||||
|
||||
## Validation
|
||||
|
||||
1. `cargo check -p hcie-iced-gui`.
|
||||
2. `cargo test -p hcie-iced-gui` and existing menu tests.
|
||||
3. SVG manual flow:
|
||||
- Open a supported polygon SVG.
|
||||
- Select a node and drag it; verify the SVG and main canvas update during the drag.
|
||||
- Insert a node through an edge midpoint and move it.
|
||||
- Edit X/Y numerically.
|
||||
- Delete a node and verify minimum-node safeguards.
|
||||
- Cancel after several edits and verify exact original restoration.
|
||||
- Reopen, edit, Save, close, and verify the updated SVG persists.
|
||||
- Try a bezier SVG and verify a controlled unsupported-geometry failure.
|
||||
4. Filter history flow:
|
||||
- Select a filter and change sliders; verify preview movement does not create multiple history records.
|
||||
- Apply the filter; verify one `Filter: <id>` history entry.
|
||||
- Undo and redo; verify pixels restore/reapply.
|
||||
5. Panel flow:
|
||||
- Close Brushes, select Brush via sidebar/shortcut/menu, verify Brushes opens.
|
||||
- Close Filters, choose a filter from the Filter menu, verify Filters opens and the selected filter is shown.
|
||||
6. Slider flow:
|
||||
- Test Filters pane at minimum and expanded widths; verify slider track is at least approximately 150px or consumes the available panel width.
|
||||
7. Color flow:
|
||||
- Left-click picker changes foreground only.
|
||||
- Right-click picker changes background only.
|
||||
- Right-click recent swatch changes background only.
|
||||
- Restart app and verify foreground, background, and recent colors persist.
|
||||
8. Capture a focused Filters panel and SVG editor screenshot after the UI changes for visual verification.
|
||||
|
||||
## Explicitly Unchanged / Already Satisfied
|
||||
|
||||
- No engine crate modifications.
|
||||
- No replacement of the main canvas context menu.
|
||||
- No per-mouse-move SVG history entries.
|
||||
- No duplicate recent-color persistence implementation.
|
||||
- No duplicate filter-history implementation; existing engine snapshot behavior is retained and verified.
|
||||
- Bezier/curve SVG editing remains a separate engine/API scope.
|
||||
Reference in New Issue
Block a user