Files
ARCADIA-Studio/harness/experiments/navigation-validation-20261002/objects/0dde2c155af1dae63d612bc4a85dd9fe65d10e193ecbf306d0aabf3c5a67f4df
T

156 lines
6.8 KiB
Plaintext

--- a/crates/oa-desktop/src/connection_edit.rs
+++ b/crates/oa-desktop/src/connection_edit.rs
@@ -37,6 +37,26 @@
let compatible = self.tool.targets(project, source);
self.candidates = visible(view).filter(|id| compatible.contains(id)).collect();
}
+}
+
+/// Contextual drawing follows the visible semantic source, not the palette layer.
+/// The caller separately validates the menu/context lifetime and pending drafts.
+pub fn can_begin(project: &Project, diagram: Id, tool: Tool, source: Id) -> bool {
+ let Some(diagram) = project.diagrams.get(&diagram) else {
+ return false;
+ };
+ let Some(element) = project.elements.get(&source) else {
+ return false;
+ };
+ diagram.projection.is_architecture()
+ && (element.layer() == diagram.layer
+ || diagram.projection == oa_core::ProjectionKind::Traceability)
+ && Tool::for_layer(element.layer()).contains(&tool)
+ && tool.can_start(project, source)
+ && (tool != Tool::Allocation
+ || tool.available_in(element.layer(), diagram.projection))
+ && visible(&oa_core::projection::project_view(project, diagram.id))
+ .any(|id| id == source)
}
pub fn visible(view: &ProjectedView) -> impl Iterator<Item = Id> + '_ {
--- a/crates/oa-desktop/src/model_menu.rs
+++ b/crates/oa-desktop/src/model_menu.rs
@@ -557,10 +557,7 @@
&format!("Draw {}", tool.label().to_lowercase()),
Message::Connection(crate::connection_edit::Event::Begin(*tool, id)),
app.active_diagram.is_some_and(|diagram| {
- crate::connection_edit::visible(&projection::project_view(
- p, diagram,
- ))
- .any(|element| element == id)
+ crate::connection_edit::can_begin(p, diagram, *tool, id)
}),
));
}
--- a/crates/oa-desktop/src/app.rs
+++ b/crates/oa-desktop/src/app.rs
@@ -2751,7 +2751,23 @@
e.kind() != Kind::Port && d.projection.includes(e.kind())
})
});
- if show_in_mixed_view || menu.request.canvas.is_some() {
+ // Draw acts on the visible current view even when opened from
+ // Explorer; explicit Select/Open actions still navigate.
+ let draw_in_current_view = match &*action {
+ Message::Connection(crate::connection_edit::Event::Begin(tool, source)) => {
+ *source == menu.request.object
+ && self.active_diagram.is_some_and(|diagram| {
+ crate::connection_edit::can_begin(
+ self.project(),
+ diagram,
+ *tool,
+ *source,
+ )
+ })
+ }
+ _ => false,
+ };
+ if show_in_mixed_view || draw_in_current_view || menu.request.canvas.is_some() {
if !self.inspect_canvas_target(menu.request.object) {
return Task::none();
}
@@ -5042,8 +5042,30 @@
epoch: self.canvas_epoch,
})
}
+ // Admission belongs to the caller: palette choice, contextual source, or
+ // an already admitted session whose complete context is still current.
+ fn arm_connection(
+ &mut self,
+ context: crate::route_edit::Context,
+ tool: crate::connection_tool::Tool,
+ ) -> crate::route_edit::Context {
+ self.canvas_epoch = self.canvas_epoch.wrapping_add(1);
+ let context = crate::route_edit::Context {
+ epoch: self.canvas_epoch,
+ ..context
+ };
+ self.connection = Some(crate::connection_edit::Session::new(
+ self.project(),
+ &project_view(self.project(), context.diagram),
+ context,
+ tool,
+ ));
+ self.selected_bend = None;
+ self.status = tool.hint().into();
+ context
+ }
fn edit_connection(&mut self, event: crate::connection_edit::Event) {
- use crate::connection_edit::{Event, Session};
+ use crate::connection_edit::Event;
let Some(context) = self.route_context() else {
return;
};
@@ -5059,10 +5081,17 @@
}
match event {
Event::Begin(tool, source) => {
- self.edit_connection(Event::Choose(Some(tool)));
- if let Some(context) = self.route_context() {
- self.edit_connection(Event::Endpoint(context, source));
- }
+ if !crate::connection_edit::can_begin(
+ self.project(),
+ context.diagram,
+ tool,
+ source,
+ ) {
+ self.status = "Choose a visible compatible source in this diagram.".into();
+ return;
+ }
+ let context = self.arm_connection(context, tool);
+ self.edit_connection(Event::Endpoint(context, source));
}
Event::Choose(Some(tool)) => {
if !crate::connection_tool::Tool::for_layer(self.layer).contains(&tool) {
@@ -5076,16 +5105,7 @@
{
return;
}
- self.canvas_epoch = self.canvas_epoch.wrapping_add(1);
- let context = self.route_context().unwrap();
- self.connection = Some(Session::new(
- self.project(),
- &project_view(self.project(), context.diagram),
- context,
- tool,
- ));
- self.selected_bend = None;
- self.status = tool.hint().into();
+ self.arm_connection(context, tool);
}
Event::Endpoint(captured, id) => {
if captured != context {
@@ -5164,8 +5184,11 @@
Event::Restart(captured) => {
if captured == context
&& let Some(session) = &self.connection
+ && session.context == context
{
- self.edit_connection(Event::Choose(Some(session.tool)));
+ // A contextual mixed-layer tool need not be in this layer's
+ // palette. Its unchanged session context retains admission.
+ self.arm_connection(context, session.tool);
}
}
Event::Choose(None) => {}