diff --git a/crates/oa-desktop/src/app/diagram_removal.rs b/crates/oa-desktop/src/app/diagram_removal.rs index 292e3f70..39df546e 100644 --- a/crates/oa-desktop/src/app/diagram_removal.rs +++ b/crates/oa-desktop/src/app/diagram_removal.rs @@ -47,6 +47,27 @@ fn placement(app: &App) -> Option { /// The derived canvases remove semantic occurrences, not reusable definitions. /// Kept beside target capture so confirmation rendering uses the same meaning. pub(crate) fn explanation(app: &App, object: Id) -> &'static str { + if app + .project() + .diagrams + .values() + .any(|diagram| diagram.nodes.contains_key(&object)) + { + return "Remove only this diagram placement. The model element and its placements in other diagrams remain. Undo restores this placement."; + } + if app + .project() + .relations + .get(&object) + .is_some_and(|relation| { + matches!( + relation.kind(), + RelationKind::StateAction | RelationKind::StateTransition + ) + }) + { + return "Remove this state relation. Its states and referenced activities or functions remain. Undo restores the relation."; + } if app .project() .relations diff --git a/crates/oa-desktop/src/app/diagram_removal_tests.rs b/crates/oa-desktop/src/app/diagram_removal_tests.rs index 784af1ec..f47e892f 100644 --- a/crates/oa-desktop/src/app/diagram_removal_tests.rs +++ b/crates/oa-desktop/src/app/diagram_removal_tests.rs @@ -331,8 +331,8 @@ async fn mounted_shift_delete_captures_target_cancel_escape_and_confirmation_rep let target = f.app.delete_target.as_ref().unwrap(); assert_eq!(target.snapshot.request.object, f.object); let stale_token = target.snapshot.token; - let task = f.app.update(Message::CancelDelete); - mounted.perform(&mut f.app, task).await; + let cancel = mounted.geometry(&f.app).bounds("delete-cancel").center(); + mounted.click(&mut f.app, cancel).await; let task = f.app.update(Message::ConfirmDelete(stale_token)); mounted.perform(&mut f.app, task).await; assert_eq!(f.app.document.bundle(), &before.bundle); @@ -345,8 +345,9 @@ async fn mounted_shift_delete_captures_target_cancel_escape_and_confirmation_rep f.app.delete_pending, "old dialog must not accept a new confirmation" ); - let task = f.app.update(Message::ConfirmDelete(token)); - mounted.perform(&mut f.app, task).await; + assert_eq!(f.app.delete_target.as_ref().unwrap().snapshot.token, token); + let confirm = mounted.geometry(&f.app).bounds("delete-confirm").center(); + mounted.click(&mut f.app, confirm).await; assert!(!f.app.project().contains(f.object)); assert!(f.app.project().contains(f.other)); consistent(&f.app); diff --git a/crates/oa-desktop/src/views.rs b/crates/oa-desktop/src/views.rs index e0444c04..22b63a83 100644 --- a/crates/oa-desktop/src/views.rs +++ b/crates/oa-desktop/src/views.rs @@ -344,7 +344,31 @@ pub fn view(app: &App) -> View<'_, Message> { ); } if let Some(target) = app.delete_target.as_ref().filter(|_| app.delete_pending) { - return modal(root,column![text("Delete from model?").size(21),text(format!("{} and its owned elements will be removed. Incident relationships, occurrences and view placements are updated together. Counterparts in the other layer remain.",p.named(target.snapshot.request.object))).size(13),label("Undo restores the complete change. Use Hide for diagram-only removal."),row![action("Cancel",Message::CancelDelete),button("Delete from model").style(button::danger).padding(10).on_press(Message::ConfirmDelete(target.snapshot.token))].spacing(10)].spacing(16).into()); + return modal( + root, + column![ + text("Delete from model?").size(21), + text(p.named(target.snapshot.request.object)).size(16), + text(crate::app::diagram_removal::explanation( + app, + target.snapshot.request.object + )) + .size(13), + row![ + widget::container(action("Cancel", Message::CancelDelete)).id("delete-cancel"), + widget::container( + button("Delete from model") + .style(button::danger) + .padding(10) + .on_press(Message::ConfirmDelete(target.snapshot.token)) + ) + .id("delete-confirm") + ] + .spacing(10) + ] + .spacing(16) + .into(), + ); } if app.pending.is_some() { return modal(root,column![text("Keep your changes?").size(21),text("Save the model and pending edits before continuing. Invalid drafts stay available for correction.").size(13),row![action("Cancel",Message::Cancel),action("Discard changes",Message::Discard),button("Save & continue").padding(10).on_press(Message::SaveAndContinue)].spacing(8)].spacing(16).into());