Files
ARCADIA-Studio/crates/oa-desktop/src/diagram/port_hit_tests.rs
T

171 lines
5.5 KiB
Rust

use super::*;
fn canvas(project: &Project, diagram: Id, zoom: f32) -> DiagramCanvas<'_> {
DiagramCanvas {
project,
view_index: None,
diagram,
selected: Id::nil(),
navigation_focus: None,
zoom,
pan: Vector::new(17., 23.),
context: Context {
document: project.id,
diagram,
revision: 0,
epoch: 0,
},
selected_bend: None,
editable: true,
placing: false,
connection: None,
}
}
fn local(canvas: &DiagramCanvas<'_>, position: Position) -> Point {
Point::new(
canvas.pan.x + position.x * canvas.zoom,
canvas.pan.y + position.y * canvas.zoom,
)
}
#[test]
fn nearest_port_center_wins_on_all_borders_and_zoom_levels() {
let project = Project::empty();
let diagram = Id::new_v4();
for side in [
PortAnchorSide::Left,
PortAnchorSide::Right,
PortAnchorSide::Top,
PortAnchorSide::Bottom,
] {
let horizontal = matches!(side, PortAnchorSide::Top | PortAnchorSide::Bottom);
let mut view = ProjectedView {
ports: (0..2)
.map(|i| projection::ProjectedPort {
element: Id::from_u128(i + 10),
owner: diagram,
position: Position {
x: 100. + if horizontal { i as f32 * 28. } else { 0. },
y: 100. + if horizontal { 0. } else { i as f32 * 28. },
},
side,
})
.collect(),
..Default::default()
};
for zoom in [0.0001, 0.35, 1., 3.] {
let canvas = canvas(&project, diagram, zoom);
for _ in 0..2 {
for port in &view.ports {
assert_eq!(
canvas.endpoint_at(&view, local(&canvas, port.position)),
Some(port.element),
"Exact port center must win at zoom {zoom} on {side:?}"
);
}
view.ports.reverse();
}
}
}
}
#[test]
fn coincident_ports_keep_selection_then_use_stable_identity() {
let project = Project::empty();
let diagram = Id::new_v4();
let a = Id::from_u128(10);
let b = Id::from_u128(20);
let mut view = ProjectedView {
ports: [b, a]
.into_iter()
.map(|element| projection::ProjectedPort {
element,
owner: diagram,
position: Position { x: 100., y: 100. },
side: PortAnchorSide::Right,
})
.collect(),
..Default::default()
};
let mut canvas = canvas(&project, diagram, 0.35);
let at = local(&canvas, view.ports[0].position);
for _ in 0..2 {
canvas.selected = Id::nil();
assert_eq!(canvas.endpoint_at(&view, at), Some(a));
canvas.selected = b;
assert_eq!(canvas.endpoint_at(&view, at), Some(b));
view.ports.reverse();
}
assert!(canvas.hit_port(&view, Point::new(-100., -100.)).is_none());
}
#[test]
fn nested_owner_palette_selection_drag_and_context_menu_pick_the_same_port() {
let mut project = Project::empty();
let group = project
.add_element(Kind::Function, Layer::Sa, "Response", None)
.unwrap();
let owner = project
.add_element(Kind::Function, Layer::Sa, "Send report", Some(group))
.unwrap();
let ports = [Id::from_u128(10), Id::from_u128(20)];
for (i, id) in ports.into_iter().enumerate() {
let port = make_port(
&project,
id,
owner,
&format!("Output {i}"),
PortContract::FunctionOutput {
outgoing_items: vec![],
},
)
.unwrap();
project.elements.insert(id, port);
}
let diagram = project.ensure_diagram(Layer::Sa);
project.diagrams.get_mut(&diagram).unwrap().projection = ProjectionKind::FunctionalDataflow;
project.place(diagram, group, Position { x: 60., y: 60. });
let node = project.place(diagram, owner, Position { x: 100., y: 140. });
project
.diagrams
.get_mut(&diagram)
.unwrap()
.nodes
.get_mut(&node)
.unwrap()
.port_anchors = ports
.into_iter()
.enumerate()
.map(|(i, port)| PortAnchor {
port,
side: PortAnchorSide::Right,
offset: 0.4 + i as f32 * 0.1,
})
.collect();
validate_candidate(&project).unwrap();
let canvas = canvas(&project, diagram, 0.35);
let view = project_view(&project, diagram);
let bounds = Rectangle::new(Point::new(200., 80.), Size::new(800., 600.));
for port in &view.ports {
let at = local(&canvas, port.position);
assert_eq!(canvas.endpoint_at(&view, at), Some(port.element));
let mut state = State::default();
let cursor = mouse::Cursor::Available(Point::new(bounds.x + at.x, bounds.y + at.y));
let press = canvas::Program::update(
&canvas,
&mut state,
&canvas::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)),
bounds,
cursor,
)
.unwrap()
.into_inner()
.0;
assert!(matches!(press, Some(Message::Select(id)) if id == port.element));
assert_eq!(state.port_drag.as_ref().unwrap().anchor.port, port.element);
let menu = canvas.context_request(&state, at, bounds);
assert_eq!(menu.object, port.element);
}
}