Files
hcie-rust-v3.05/.kilo/plans/1782611800353-document-expansion-plan.md
T
2026-07-09 02:59:53 +03:00

4.3 KiB

Document Expansion Plan for Pasted Panel Larger Than Canvas

Problem

When pasting a panel via Ctrl+V that is larger than the current canvas, the pasted content gets cropped instead of permanently expanding the document and all layers.

Discoveries

Paste Handler Location

hcie-egui-app/crates/hcie-gui-egui/src/app/mod.rs:1827-1898AppEvent::ClipboardPaste:

  • Gets clipboard image, centers it, creates new layer
  • Line 1871: if dst_x >= 0 && dst_x < canvas_w as i32 && dst_y >= 0 && dst_y < canvas_h as i32 — silently clips pixels outside canvas

Engine API — resize_canvas Already Exists

hcie-engine-api/src/lib.rs:504-507:

pub fn resize_canvas(&mut self, w: u32, h: u32) {
    self.document.resize_canvas(w, h);
    self.pre_tile_all_layers();
}

Document Resize Implementation

hcie-document/src/lib.rs:384-407 — Resizes all layer pixel buffers, copies existing content, zeroes new areas. Already handles all layers.

Dialog System

dialogs.rsshow_new_image_dialog pattern exists. modern_dialogs.rs — ready button/frame helpers.

No locked crate changes neededresize_canvas is already exposed in hcie-engine-api.

Implementation Tasks

Task 1: Add ExpandCanvas event variant

File: hcie-egui-app/crates/hcie-gui-egui/src/event_bus.rs

Add to AppEvent enum:

ExpandCanvas { w: u32, h: u32 },

Task 2: Add show_expand_dialog state field

File: hcie-egui-app/crates/hcie-gui-egui/src/app/mod.rs

Add field to HcieApp:

pub show_expand_dialog: Option<(u32, u32, u32, u32)>,
// (paste_width, paste_height, canvas_width, canvas_height)

Initialize in HcieApp::new:

show_expand_dialog: None,

Task 3: Modify paste handler to detect oversized paste

File: hcie-egui-app/crates/hcie-gui-egui/src/app/mod.rsClipboardPaste handler (lines 1827-1898)

After clipboard data is resolved (after line 1856), before creating the layer:

  • If clip.width > canvas_w || clip.height > canvas_h:
    • Set self.show_expand_dialog = Some((clip.width, clip.height, canvas_w, canvas_h))
    • Store clipboard data in self.internal_clipboard for later use
    • Skip the paste (don't create layer, don't write pixels)
  • Else: proceed with existing paste flow unchanged

Task 4: Add ExpandCanvas event handler

File: hcie-egui-app/crates/hcie-gui-egui/src/app/mod.rs — event loop

AppEvent::ExpandCanvas { w, h } => {
    if let Some(doc) = self.active_doc_mut() {
        doc.engine.resize_canvas(w, h);
        doc.engine.set_modified(true);
        self.event_bus.push(AppEvent::RenderRequested);
    }
}

Task 5: Create expand confirmation dialog

File: hcie-egui-app/crates/hcie-gui-egui/src/app/dialogs.rs

New function show_expand_dialog(app: &mut HcieApp, ctx: &egui::Context):

  • Follow show_new_image_dialog pattern (dim background, centered area, modern_dialog_frame)
  • Show: "Pasted image (WxH) exceeds canvas (WxH). Expand document to fit?"
  • Two buttons:
    • Expand (accent_button): Push AppEvent::ExpandCanvas { w: paste_w, h: paste_h }, then push AppEvent::ClipboardPaste (to retry paste on expanded canvas), close dialog
    • Cancel (ghost_button): Close dialog, paste proceeds as-is (will be cropped)

Task 6: Render expand dialog in update loop

File: hcie-egui-app/crates/hcie-gui-egui/src/app/mod.rsupdate method

Add alongside existing dialog calls:

if self.show_expand_dialog.is_some() {
    dialogs::show_expand_dialog(self, ctx);
}

Validation Plan

  1. Paste smaller image: 100x100 into 800x600 → no dialog, normal paste
  2. Paste larger image + Cancel: 1920x1080 into 800x600 → dialog appears, Cancel → image is cropped to canvas
  3. Paste larger image + Expand: 1920x1080 into 800x600 → dialog appears, Expand → canvas resizes to 1920x1080, all layers expand, pasted image fits perfectly

Risks

  • Performance: resize_canvas reallocates all layer pixel buffers. For very large documents this may cause a frame drop. Acceptable for user-initiated paste.
  • Retrigger loop: After Expand, pushing ClipboardPaste again re-reads clipboard. Ensure internal_clipboard is still set so it doesn't re-prompt. The second paste will see canvas is now large enough and proceed normally.