Closed point-source closed 2 years ago
It would be really nice to have a policy inside the package that could be able to make these kind of connections. However, it's not an easy task to compute a path of the lines in all cases. And I can't think of an easy way how to add it to the package.
It's still possible to achieve the required behaviour. I recommend you to compute the position of the points after creating the connection between two components. And compute the same while moving any component.
I created a code sample just for one of the cases (x-y-x). Please try to replace these functions in the example and play with it a little. Hopefully it will help you to make all the cases to work.
@override
onComponentScaleUpdate(componentId, details) {
Offset positionDelta = details.localFocalPoint - lastFocalPoint;
canvasWriter.model.moveComponent(componentId, positionDelta);
final c1 = canvasReader.model.getComponent(componentId);
for (final connection in c1.connections) {
final c2 = canvasReader.model.getComponent(connection.otherComponentId);
late final Offset p1;
late final Offset p2;
if (connection is ConnectionOut) {
p1 = c1.position + c1.getPointOnComponent(Alignment.center);
p2 = c2.position + c2.getPointOnComponent(Alignment.center);
} else {
p2 = c1.position + c1.getPointOnComponent(Alignment.center);
p1 = c2.position + c2.getPointOnComponent(Alignment.center);
}
canvasWriter.model.setLinkMiddlePointPosition(connection.connectionId, Offset((p1.dx + p2.dx) / 2, p1.dy), 1);
canvasWriter.model.setLinkMiddlePointPosition(connection.connectionId, Offset((p1.dx + p2.dx) / 2, p2.dy), 2);
}
canvasWriter.model.updateComponentLinks(componentId);
lastFocalPoint = details.localFocalPoint;
}
// This function tests if it's possible to connect the components and if yes, connects them
bool connectComponents(String? sourceComponentId, String? targetComponentId) {
if (sourceComponentId == null || targetComponentId == null) {
return false;
}
// tests if the ids are not same (the same component)
if (sourceComponentId == targetComponentId) {
return false;
}
// tests if the connection between two components already exists (one way)
if (canvasReader.model
.getComponent(sourceComponentId)
.connections
.any((connection) => (connection is ConnectionOut) && (connection.otherComponentId == targetComponentId))) {
return false;
}
// This connects two components (creates a link between), you can define the design of the link with LinkStyle.
String linkId = canvasWriter.model.connectTwoComponents(
sourceComponentId: sourceComponentId,
targetComponentId: targetComponentId,
linkStyle: LinkStyle(
arrowType: ArrowType.pointedArrow,
lineWidth: 1.5,
backArrowType: ArrowType.centerCircle,
),
);
final c1 = canvasReader.model.getComponent(sourceComponentId);
final c2 = canvasReader.model.getComponent(targetComponentId);
final p1 = c1.position + c1.getPointOnComponent(Alignment.center);
final p2 = c2.position + c2.getPointOnComponent(Alignment.center);
canvasWriter.model.insertLinkMiddlePoint(linkId, Offset((p1.dx + p2.dx) / 2, p1.dy), 1);
canvasWriter.model.insertLinkMiddlePoint(linkId, Offset((p1.dx + p2.dx) / 2, p2.dy), 2);
canvasWriter.model.updateLink(linkId);
return true;
}
That actually turned out to be perfect for what I needed. Thank you for the really quick help with this!
Is it possible to create a type of policy or feature which would force lines to be either vertical or horizontal and add 90 degree joints as necessary to reach a linked object? Similar to the default behavior of draw.io / lucidchart.
Something like this:
Instead of this:
Here are the draw.io pathfinding/line structure options for reference:
I realize this could be accomplished by the user manually long-pressing the line to add a joint but the application I am building shouldn't require the user to manually route, if possible. How hard would this be to do?