Resolve diagram Delete target after placement properties selection
This commit is contained in:
@@ -43,7 +43,13 @@ impl App {
|
|||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if current != Some(intent.context) || self.selected != intent.object {
|
let selected_object = self
|
||||||
|
.project()
|
||||||
|
.diagrams
|
||||||
|
.get(&intent.context.diagram)
|
||||||
|
.and_then(|diagram| diagram.nodes.get(&self.selected))
|
||||||
|
.map_or(self.selected, |node| node.element);
|
||||||
|
if current != Some(intent.context) || selected_object != intent.object {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let view = projection::project_view(self.project(), intent.context.diagram);
|
let view = projection::project_view(self.project(), intent.context.diagram);
|
||||||
@@ -81,15 +87,19 @@ impl App {
|
|||||||
self.status = "Hidden from this diagram · Model element preserved · Undo restores the placement".into();
|
self.status = "Hidden from this diagram · Model element preserved · Undo restores the placement".into();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.begin_model_delete(Some(intent.context));
|
self.begin_model_delete_target(intent.object, Some(intent.context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn begin_model_delete(&mut self, canvas: Option<Context>) {
|
pub(super) fn begin_model_delete(&mut self, canvas: Option<Context>) {
|
||||||
if self.selected == self.project().id || self.behavior.has_pending() {
|
self.begin_model_delete_target(self.selected, canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn begin_model_delete_target(&mut self, object: Id, canvas: Option<Context>) {
|
||||||
|
if object == self.project().id || self.behavior.has_pending() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut request = model_menu::Request::object(self.selected, iced::Point::ORIGIN);
|
let mut request = model_menu::Request::object(object, iced::Point::ORIGIN);
|
||||||
request.canvas = canvas;
|
request.canvas = canvas;
|
||||||
request.placement = if self.page == Page::Behavior {
|
request.placement = if self.page == Page::Behavior {
|
||||||
self.behavior.diagram.placement
|
self.behavior.diagram.placement
|
||||||
|
|||||||
@@ -205,6 +205,86 @@ async fn mounted_shift_delete_captures_target_cancel_escape_and_confirmation_rep
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct FocusField(Rectangle);
|
struct FocusField(Rectangle);
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn mounted_placement_properties_selection_supports_hide_and_model_delete() {
|
||||||
|
for layer in [Layer::Oa, Layer::Sa] {
|
||||||
|
for model in [false, true] {
|
||||||
|
let (mut f, mut mounted) = mount(layer).await;
|
||||||
|
let before = f.app.document.snapshot();
|
||||||
|
let mut request = crate::model_menu::Request::object(f.object, Point::ORIGIN);
|
||||||
|
request.placement = Some(f.node);
|
||||||
|
request.canvas = f.app.route_context();
|
||||||
|
let task = f
|
||||||
|
.app
|
||||||
|
.update(Message::Menu(crate::model_menu::Event::Open(request)));
|
||||||
|
mounted.perform(&mut f.app, task).await;
|
||||||
|
let action = crate::model_menu::popup(&f.app)
|
||||||
|
.unwrap()
|
||||||
|
.entries
|
||||||
|
.into_iter()
|
||||||
|
.find_map(|entry| match entry {
|
||||||
|
crate::context_menu::Entry::Action { label, message, .. }
|
||||||
|
if label == "Placement properties" =>
|
||||||
|
{
|
||||||
|
message
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let task = f.app.update(action);
|
||||||
|
mounted.perform(&mut f.app, task).await;
|
||||||
|
assert_eq!(f.app.selected, f.node);
|
||||||
|
assert_eq!(f.app.selected_node, Some(f.node));
|
||||||
|
let bounds = mounted
|
||||||
|
.geometry(&f.app)
|
||||||
|
.bounds(crate::allocation_input::CANVAS_ID);
|
||||||
|
mounted
|
||||||
|
.click(&mut f.app, Point::new(bounds.x + 20., bounds.y + 20.))
|
||||||
|
.await;
|
||||||
|
assert_eq!(
|
||||||
|
f.app.selected, f.node,
|
||||||
|
"blank canvas preserves placement selection"
|
||||||
|
);
|
||||||
|
delete(&mut mounted, &mut f.app, model).await;
|
||||||
|
if model {
|
||||||
|
let target = f
|
||||||
|
.app
|
||||||
|
.delete_target
|
||||||
|
.as_ref()
|
||||||
|
.expect("model confirmation opens");
|
||||||
|
assert_eq!(target.snapshot.request.object, f.object);
|
||||||
|
assert_eq!(target.selection, f.node);
|
||||||
|
let token = target.snapshot.token;
|
||||||
|
let task = f.app.update(Message::ConfirmDelete(token));
|
||||||
|
mounted.perform(&mut f.app, task).await;
|
||||||
|
assert!(!f.app.project().contains(f.object));
|
||||||
|
assert!(
|
||||||
|
!f.app.project().diagrams[&f.copy]
|
||||||
|
.nodes
|
||||||
|
.values()
|
||||||
|
.any(|n| n.element == f.object)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
assert!(f.app.project().contains(f.object));
|
||||||
|
assert!(!f.app.project().contains(f.node));
|
||||||
|
assert!(
|
||||||
|
f.app.project().diagrams[&f.copy]
|
||||||
|
.nodes
|
||||||
|
.values()
|
||||||
|
.any(|n| n.element == f.object)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
consistent(&f.app);
|
||||||
|
let task = f.app.update(Message::Undo);
|
||||||
|
mounted.perform(&mut f.app, task).await;
|
||||||
|
assert_eq!(f.app.document.bundle(), &before.bundle);
|
||||||
|
assert_eq!(f.app.project(), &before.decoded.project);
|
||||||
|
assert!(!f.app.document.can_undo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Operation for FocusField {
|
impl Operation for FocusField {
|
||||||
fn traverse(&mut self, visit: &mut dyn FnMut(&mut dyn Operation)) {
|
fn traverse(&mut self, visit: &mut dyn FnMut(&mut dyn Operation)) {
|
||||||
visit(self);
|
visit(self);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# Usage-limit pause — 2026-09-12
|
# Historical source checkpoint — 2026-09-12
|
||||||
|
|
||||||
Superseded historical record: its stop interpretation does not apply. The user's current instruction is to continue. See [saved verification checkpoint](handoff-usage-pause-20260912-final.md) for preserved evidence and Gitea for current coordination. Do not infer a live pause from the historical text below.
|
Superseded historical record: its stop interpretation does not apply. The user's current instruction is to continue. See [saved verification checkpoint](handoff-usage-pause-20260912-final.md) for preserved evidence and Gitea for current coordination. Do not infer a live pause from the historical text below.
|
||||||
|
|
||||||
The user requested saving all work and stopping. Root session Codex-956atf stopped the allocation worker and started no further builds or checks. Resume only when requested. Linux/WSL setup, networking, builds and checks remain paused pending the user's explicit instruction; Computer Use is also paused.
|
This record describes the earlier saved allocation source before its subsequent toolbar correction and combined verification. It does not impose a stop or resume condition. The separate Linux/WSL networking deferral remains applicable.
|
||||||
|
|
||||||
This is a saved handoff, not a replacement for live coordination in Gitea issue #3. Branch: `codex/behavior-authoring-20260910`; publication branch: `codex/release1-956atf`.
|
This is a saved handoff, not a replacement for live coordination in Gitea issue #3. Branch: `codex/behavior-authoring-20260910`; publication branch: `codex/release1-956atf`.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user