fix(layers): deleting a non-empty layer warns and removes its objects (#237)

Deleting a layer only dropped the layer record, leaving its objects in the
file still tagged with the (now-gone) layer name. Now:

- Empty layer → deleted straight away.
- Non-empty layer → a warning modal ("Layer X is not empty — N objects;
  deleting also removes them. Continue?") with Delete Objects / Cancel.
  Confirming erases every object on the layer, then removes the layer, as
  one undo step. The layer record is dropped before the erase so the
  locked-layer guard can't keep its objects.
- Layer "0" and the current layer can't be deleted (reported on the
  command line) instead of silently leaving a broken state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-07-01 17:23:32 +03:00
commit 2712bb80e4
5 changed files with 146 additions and 17 deletions

View file

@ -348,6 +348,10 @@ pub(super) struct OpenCADStudio {
aec_drop_count: usize,
/// Set once the user confirms overwriting an existing file on Save-As.
overwrite_acknowledged: bool,
/// Layer awaiting a "delete non-empty layer" confirmation: `(name, object
/// count)`. Set when the user deletes a layer that still has objects; the
/// warning modal reads it, and confirming erases those objects too.
layer_delete_pending: Option<(String, usize)>,
/// Pixel offset of the active modal from screen-centre (drag-to-move).
/// Reset to zero whenever a modal closes so each dialog opens centred.
modal_offset: iced::Vector,
@ -958,6 +962,7 @@ pub enum ModalKind {
AssocPrompt,
PointStyle,
AttributeEditor,
LayerDeleteWarning,
}
/// Identifies a DimStyle field that can be edited in the dialog.
@ -1180,6 +1185,8 @@ pub enum Message {
LayerToggleVpFreeze(usize, usize),
LayerNew,
LayerDelete,
/// Confirm deleting a non-empty layer (erases its objects too).
LayerDeleteConfirm,
LayerSetCurrent,
LayerSelect(usize),
LayerRenameStart(usize),
@ -1955,6 +1962,7 @@ impl OpenCADStudio {
aec_drop_acknowledged: false,
aec_drop_count: 0,
overwrite_acknowledged: false,
layer_delete_pending: None,
modal_offset: iced::Vector::ZERO,
modal_drag_last: None,
modal_dragging: false,