10 KiB
ICED GUI Migration — Work Handoff (2026-07-15)
Status: IN PROGRESS (build green, 5/5 tests pass)
The 14-task migration plan (docs/compose/plans/2025-07-15-iced-full-gui-migration.md)
was already committed by prior sessions. This session focused on closing the
functional quality gap vs egui identified by deep comparison of both GUIs.
What this session completed (uncommitted working-tree changes)
All changes are in hcie-iced-app/crates/hcie-iced-gui/src/. Build: cargo build -p hcie-iced-gui (0 errors, 32 warnings).
HIGH priority (functional regressions vs egui — FIXED)
-
TransformApply TODO stub (
app.rs) — theMessage::TransformApplyhandler was a no-op stub. Addedapply_transform_to_layer()that composites the floating selection back onto the active layer with scale + rotation support (egui only had scale). Uses public API:get_active_layer_pixels+set_active_layer_pixels. -
~20 missing canvas tool interactions (
app.rsCanvasPointerPressed/Moved/Released) — only 8 tools were wired; the rest hit_ => {}. Now wired: MagicWand (enginecreate_selection_magic_wand), Lasso (freehand point accumulation →create_selection_lasso), PolygonSelect (vertex accumulation + close-on-near-start), SmartSelect (magic-wand fallback), VisionSelect (bbox drag → rect selection), Move (cut selection → floating transform), Gradient (endpoint drag → stroke fill), Text (draft begin), and all 12 vector shape tools (Star/Polygon/Arrow/Rhombus/Cylinder/Heart/Bubble/Gear/Cross/Crescent/Bolt/Arrow4 viaadd_vector_shape). FloodFill tolerance now reads from settings instead of hardcoded 32. -
Touch/pen pressure feed (
app.rssubscription) — iced 0.13 touch events carry no pressure, but position feed totablet_statewas missing entirely. Added aTabletTouchmessage handlingiced::Event::Touch(finger press/move →set_screen_pos, lift →reset_pressure), plus screen-size feed inCanvasSizehandler. evdev listener (already started in main.rs) remains the pressure source. -
Tool option controls were all NoOp (
panels/tool_settings.rs,panels/toolbar.rs) — Flow/Spacing/Density/Tolerance/vector-stroke/fill/gradient-type/text-font/size/angle/alignment all emittedMessage::NoOp. Rewrote both panels to emit real messages wired to settings persistence. Added settings fields:vector_fill/radius/points/sides,spray_particle_size/density,gradient_type,selection_contiguous/anti_alias,text_font/angle,tool_apply_to_new_layer. Added Message variants:BrushFlowChanged/BrushSpacingChanged/SelectionToleranceChanged/SelectionContiguousToggled/ SelectionFeatherChanged/SprayParticleSizeChanged/SprayDensityChanged/GradientTypeChanged/ VectorStrokeChanged/VectorOpacityChanged/VectorFillToggled/VectorRadiusChanged/ VectorPointsChanged/VectorSidesChanged/TextFontChanged/TextAngleChanged/ TextOrientationChanged/TextContentChanged/TextCommit/ToolApplyToNewLayerToggled. -
Color picker broken (
color_picker.rs,app.rs) — alpha was force-stripped to 255, recent colors never populated, colors not persisted. Fixed: hex input preserves alpha, added an alpha slider (0-255), swatches/recent render RGBA,FgColorChangednow callsadd_recent_color, colors persist to~/.config/hcie-iced/colors.jsonviaPersistedColors(load on startup, save on change viacolors_dirtyflag).
MEDIUM priority (UX parity improvements — DONE)
-
Missing keyboard shortcuts (
app.rssubscription) — added P/F/G/C/I/J tools, X swap,[/]brush-size-relative, Tab (dock dialog), F12 (repaint). Enter/Escape now contextual (crop/transform/text-commit confirmation; viewer/crop/transform/selection/dialog cancel) via newEscapePressed/EnterPressedmessages (theon_key_pressclosure must be a non-capturing fn, so resolution happens inupdate()). Note:[/]useBrushSizeRelativesince the closure can't captureself. -
Sidebar improvements (
sidebar/mod.rs,app.rs) — added per-slot last-used sub-tool memory (slot_last_usedfield,slot_for_tool/tool_slots/last_used_toolhelpers); slot buttons now show the last-used tool's icon. Background swatch is now clickable (promotes bg→fg). Added "D" reset-colors button (ResetColors→ fg=black/bg=white).ToolSlotis nowpub;TOOL_SLOTSispub const. -
Canvas overlays (
canvas/mod.rs) — selection now has a semi-transparent purple fill overlay over the selection bounds (egui has fill over actual mask pixels; this is a bounds approximation since the overlaycanvas::Programhas no mask access). Vector shape previews now draw actual geometry (ellipse/line/5-star/6-polygon) instead of just a bounding box, driven byactive_toolfield. Added gradient endpoint preview line + markers.OverlayProgramgainedactive_toolandgradient_dragfields. -
On-canvas text editor (
canvas/mod.rs) — when atext_draftis active, a positionedtext_input+ Commit/Cancel buttons overlay the canvas at the draft's screen position (eguitext_overlay.rs). Uses icedStack+ padding offset. Enter commits, Escape cancels.
Supporting changes
IcedDocumentgained fields:lasso_points,polygon_points,gradient_drag,vision_rect,text_draft. AddedTextDraftstruct +Default.app.rsnew()restored after an accidental deletion during editing (app construction + load_path handling + init_task were re-added from git HEAD).- 3 IcedDocument construction sites updated with the new fields.
- New Message variants also added:
LassoDragMove/LassoDragEnd/PolygonAddPoint/PolygonClose/ GradientDragStart/GradientDragMove/GradientDragEnd/BrushSizeRelative/TabletTouch/ EscapePressed/EnterPressed/ResetColors.
What REMAINS to be done (prioritized)
HIGH (functional gaps still open)
-
Marching ants only for rect selections. iced draws marching ants around the selection bounding box (
canvas/mod.rsmarching-ants section). egui follows the actual irregular selection edge via edge-extraction (render.rs:58-96). Fix requires passing the selection mask to the overlaycanvas::Programand rendering an edge outline. The selection-fill overlay added this session is bounds-only for the same reason. -
Shift+drag brush resize & Ctrl+click eyedropper during strokes (egui
mod.rs:271-292). iced shader_canvas event handling has no modifier-key awareness for brush resize, and no Ctrl+click eyedropper shortcut. Requires extendingCanvasShaderProgram::updateto read modifiers (may need passing modifiers into the shader program or handling at app level). -
Pen tool distinct path. egui uses
draw_pen_segmentfor vector-like pen strokes (mod.rs:916-933); iced treats Pen identically to Brush (app.rs:1021). Needs an engine API check for a pen-segment method. -
VectorSelect tool has no canvas interaction. Selecting/moving/rotating existing vector shapes (egui
mod.rs:651-739) is unimplemented. Needsfind_vector_shape_at+modify_vector_shapeengine calls + handle hit-testing in the overlay. -
History for transform apply. egui's transform also doesn't push a dedicated snapshot, so this matches egui, but ideally
TransformApplyshould be undoable. The engine'spush_draw_snapshotis private (locked engine-api); needs an unlock + public wrapper or routing throughbegin_stroke/end_stroke.
MEDIUM (polish / parity)
-
SmartSelect/VisionSelect real AI backend. Currently SmartSelect falls back to magic-wand and VisionSelect makes a rect selection. egui runs SAM/vision pipelines via AppEvent. Needs the
hcie-visionAPI wired (configurable model path, run buttons in a panel). -
AI/vision tool option panels (SmartSelect model-path UI, VisionSelect task/backend/run UI — egui
panels.rs:1837-1997). Tools are selectable but not configurable from the GUI. -
Brush stamp cursor (egui
mod.rs:1444-1645cached footprint). iced only draws a simple 10px crosshair. Needs the actual brush-size circle cursor on the canvas overlay. -
Right-click context menu on canvas (egui
mod.rs:2027-2089: copy/cut/paste/new layer/ deselect/crop/quick filters). Not implemented in iced. -
Double-click to edit existing text layer (egui
mod.rs:2013-2025). Not implemented. -
Layer-not-editable guard + auto-create layer by tool type (egui
mod.rs:232-267). iced doesn't guard locked layers or auto-create vector/text layers on tool use. -
dock_profile dialog toggle on Tab is a stop-in (egui Tab hides panels). A proper panel-visibility toggle is better.
LOW (both GUIs lack these — future work)
Rulers, canvas grid/snap, guides, navigator/minimap, pixel grid at high zoom, scrubby zoom, true fit-to-screen, space-drag pan, scrollbars, pinch zoom, tilt input.
Verification performed
cargo build -p hcie-iced-gui→ 0 errors, 32 warnings (all unused/dead-code, no logic errors).cargo test -p hcie-iced-gui→ 5/5 pass.- No manual app launch / screenshot verification done this session (no display available).
Files changed this session
hcie-iced-app/crates/hcie-iced-gui/src/app.rs(main logic, ~+400 lines)hcie-iced-app/crates/hcie-iced-gui/src/settings.rs(+13 settings fields + defaults)hcie-iced-app/crates/hcie-iced-gui/src/color_picker.rs(alpha + recent + persistence)hcie-iced-app/crates/hcie-iced-gui/src/panels/tool_settings.rs(full rewrite, NoOp→real)hcie-iced-app/crates/hcie-iced-gui/src/panels/toolbar.rs(flow/tolerance/feather/stroke wired)hcie-iced-app/crates/hcie-iced-gui/src/sidebar/mod.rs(last-used memory, bg-click, reset)hcie-iced-app/crates/hcie-iced-gui/src/canvas/mod.rs(selection fill, shape previews, text overlay)hcie-iced-app/crates/hcie-iced-gui/src/dock/view.rs(tool_settings + toolbar arg wiring)
Note for next session
The uncommitted pressure-indicator work from the prior session (panels/pressure_indicator.rs
- its canvas wiring) is included in the working tree and builds. Nothing has been committed this session — the next step is to review the diff and commit in logical chunks, then continue with the HIGH-priority remaining items above (marching-ants-for-irregular-selections and Shift/Ctrl modifier handling are the highest-value next steps).