Files
hcie-rust-v3.05/.kilo/plans/1784456713003-iced-svg-editor-trigger.md
phantom 2fb47520b3 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
2026-07-20 01:43:22 +03:00

14 KiB
Raw Permalink Blame History

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.
  • EGUIs 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 pickers 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

  1. 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.
  2. 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.
  3. 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

  1. On node press, select the polygon/node and begin drag.
  2. 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.
  3. On midpoint click, call editable.add_node(...) and update selection/live preview.
  4. On Delete/Backspace or Remove button, remove the selected node when valid and update/live-preview.
  5. Numeric X/Y edits update the selected node and live-preview.
  6. Save keeps the current SVG, clears the original/session state, closes the editor, and requests composite refresh.
  7. Cancel calls set_vector_shape_svg() with original_svg, refreshes the composite, clears session state, and closes without retaining edits.
  8. Handle empty polygons, invalid selection indices, unsupported bezier SVGs, and zero-sized viewBoxes without panics.

4. Filter/panel behavior

  1. Add a small ensure_pane_open(PaneType) helper if repeated logic is useful; otherwise use is_pane_open + reopen_pane directly.
  2. Call it for Brush selection and Filter selection as specified above.
  3. Widen filter slider rows and increase Filters pane minimum sizing. Verify at narrow and wide pane widths.
  4. 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

  1. Add right-click output support to the color-wheel/picker Canvas Program.
  2. 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.