From ebb6a9980b11c4d4df2f7e413c6b135a337f6f6d Mon Sep 17 00:00:00 2001 From: "sorokin.oleg.edu" Date: Thu, 1 Oct 2026 19:24:39 -0700 Subject: [PATCH] Reproduce wrapped geometry retained after foreign label preview refusal --- crates/oa-desktop/src/diagram.rs | 18 +++- .../src/diagram/label_layout_experiment.rs | 90 +++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/crates/oa-desktop/src/diagram.rs b/crates/oa-desktop/src/diagram.rs index fa704632..acba1501 100644 --- a/crates/oa-desktop/src/diagram.rs +++ b/crates/oa-desktop/src/diagram.rs @@ -642,7 +642,23 @@ impl DiagramCanvas<'_> { scene } fn begin_route(&self, state: &mut State, world: Point, handle: Handle, route: EdgeRoute) { - let baseline = self.scene(state).routed.clone(); + self.begin_route_with_profile( + state, + world, + handle, + route, + label_layout_experiment::profile(), + ); + } + fn begin_route_with_profile( + &self, + state: &mut State, + world: Point, + handle: Handle, + route: EdgeRoute, + profile: label_layout_experiment::Profile, + ) { + let baseline = self.scene_with_profile(state, profile).routed.clone(); state.route_drag = Some(Gesture { context: self.context, start: world, diff --git a/crates/oa-desktop/src/diagram/label_layout_experiment.rs b/crates/oa-desktop/src/diagram/label_layout_experiment.rs index cc5bdc63..db50772f 100644 --- a/crates/oa-desktop/src/diagram/label_layout_experiment.rs +++ b/crates/oa-desktop/src/diagram/label_layout_experiment.rs @@ -576,6 +576,8 @@ mod tests { }; p.diagrams.get_mut(&id).unwrap().routes = vec![EdgeRoute { edge: edge_id(), + source_attachment: None, + target_attachment: None, waypoints: vec![], label: Some(EdgeLabel { fraction: initial.geometry.fraction, @@ -633,6 +635,94 @@ mod tests { } } #[test] + fn different_edge_preview_guard_rejection_restores_complete_core_geometry() { + // Exercise the actual gesture capture and core preview, with a pure + // explicit profile. Moving another label onto the wrapped target must + // reject wrapping, leaving the full original one-line target geometry. + // All twelve point arrays and every other frozen label remain exact. + let (p, id) = fixture(); + let view = project_view(&p, id); + let core = route_diagram(&p, &p.diagrams[&id], &view); + let foreign = core + .edges + .values() + .find(|edge| edge.id != edge_id() && !edge.label.text.is_empty()) + .unwrap(); + let original_offset = Position { + x: foreign.label.center.x - foreign.label.anchor.x, + y: foreign.label.center.y - foreign.label.anchor.y, + }; + let c = DiagramCanvas { + selected: foreign.id, + ..canvas(&p, id) + }; + for profile in [Profile::E, Profile::F] { + let mut state = State { + context: Some(c.context), + ..State::default() + }; + let initial = c.scene_with_profile(&state, profile); + let target = initial + .label_layout + .as_ref() + .expect("Initial witness must wrap"); + c.begin_route_with_profile( + &mut state, + point(foreign.label.center), + Handle::Label { + original: original_offset, + }, + EdgeRoute { + edge: foreign.id, + source_attachment: None, + target_attachment: None, + waypoints: vec![], + label: Some(EdgeLabel { + fraction: foreign.label.fraction, + offset: original_offset, + }), + }, + profile, + ); + state + .route_drag + .as_mut() + .unwrap() + .move_to(point(target.geometry.center), 1.); + let diagram = c.preview_diagram(&state); + let expected = routing::route_edge_preview(&p, &diagram, &view, &core, foreign.id); + let mut guard_probe = expected.clone(); + assert!( + apply(&p, &diagram, &view, &mut guard_probe, profile).is_none(), + "Foreign label now overlaps target: wrapping must be refused" + ); + assert_eq!(guard_probe, expected); + let actual = c.scene_with_profile(&state, profile); + assert!(actual.label_layout.is_none()); + for (edge, before) in &core.edges { + assert_eq!( + actual.routed.edges[edge].points, before.points, + "Label drag must not reroute" + ); + if *edge != foreign.id && *edge != edge_id() { + assert_eq!( + actual.routed.edges[edge].label, before.label, + "Other labels remain frozen" + ); + } + } + assert_eq!( + actual.routed.edges[&edge_id()].label, + core.edges[&edge_id()].label, + "No Layout means original complete one-line target geometry, never stale wrapped hit bounds" + ); + assert_eq!( + *actual.routed, expected, + "Fallback is the complete core preview result" + ); + } + } + #[test] fn scene_and_measurement_cache_reuse_and_geometry_invalidation() { let (p, id) = fixture(); let c = canvas(&p, id);