Support state relation row removal and verify F2 at widget focus boundary

This commit is contained in:
2026-09-12 05:13:55 -07:00
parent dc1506f2e8
commit 28e21a0ae8
8 changed files with 381 additions and 21 deletions
+46 -1
View File
@@ -402,6 +402,48 @@ fn state_action_rows<'a>(
.collect()
}
/// Action and internal-transition rows are selectable relations, not edges or
/// placements. Match the exact rows rendered in this dedicated machine view.
pub(crate) fn visible_row_relation(
project: &Project,
diagram: Id,
view: &ProjectedView,
id: Id,
) -> bool {
let Some(machine) = project
.diagrams
.get(&diagram)
.and_then(|d| d.projection.state_machine())
else {
return false;
};
let Some(relation) = project.relations.get(&id) else {
return false;
};
let source = match relation.body {
RelationBody::StateAction { source, .. } => source,
RelationBody::StateTransition {
source,
target,
transition_kind: TransitionKind::Internal,
..
} if projection::state_machine_contains(project, machine, target) => source,
_ => return false,
};
if !projection::state_machine_contains(project, machine, source) {
return false;
}
view.nodes
.iter()
.filter(|node| node.element == source)
.any(|node| {
state_action_rows(project, node)
.into_iter()
.chain(internal_rows(project, node))
.any(|(row, _)| row.id == id)
})
}
fn state_action_label(project: &Project, relation: &Relation) -> String {
let RelationBody::StateAction { target, phase, .. } = relation.body else {
return String::new();
@@ -798,7 +840,10 @@ impl canvas::Program<Event> for StateCanvas<'_> {
.iter()
.find(|node| node.element == self.selected || node.id == self.selected);
let object = placement.map_or(self.selected, |node| node.element);
if placement.is_none() && !scene.view.edges.iter().any(|edge| edge.id == object) {
if placement.is_none()
&& !scene.view.edges.iter().any(|edge| edge.id == object)
&& !visible_row_relation(self.project, self.diagram, &scene.view, object)
{
return None;
}
return Some(
+7 -1
View File
@@ -194,7 +194,13 @@ pub fn popup(app: &App, opened: &Opened, clean: bool) -> Option<Menu<Message>> {
|| projection::project_view(project, context.diagram)
.edges
.iter()
.any(|edge| edge.id == id))
.any(|edge| edge.id == id)
|| super::state_canvas::visible_row_relation(
project,
context.diagram,
&projection::project_view(project, context.diagram),
id,
))
}) {
if request.placement.is_some() {
"Shift+Delete"