Search in sources :

Example 26 with MultiPath

use of com.ait.lienzo.client.core.shape.MultiPath in project lienzo-core by ahome-it.

the class ShapeControlUtils method checkForAndApplyLineSplice.

public static boolean checkForAndApplyLineSplice(final WiresManager wiresManager, final WiresShape shape) {
    if (!wiresManager.isSpliceEnabled() || (shape.getMagnets() == null)) {
        // cannot connect to a shape with no magnets.
        return true;
    }
    boolean accept = true;
    for (final WiresConnector c : wiresManager.getConnectorList()) {
        final Point2DArray linePoints = ((OrthogonalPolyLine) c.getLine()).getComputedPoint2DArray();
        final MultiPath path = shape.getPath();
        Point2DArray intersectPoints = null;
        final Point2D absLoc = path.getComputedLocation();
        intersectPoints = getIntersections(linePoints, path, intersectPoints, absLoc);
        if (((c.getHeadConnection().getMagnet() != null) && (c.getHeadConnection().getMagnet().getMagnets().getWiresShape() == shape)) || ((c.getTailConnection().getMagnet() != null) && (c.getTailConnection().getMagnet().getMagnets().getWiresShape() == shape))) {
            // don't split yourself
            return accept;
        }
        if (intersectPoints != null) {
            final WiresConnection headCon = c.getHeadConnection();
            final WiresConnection tailCon = c.getTailConnection();
            if (intersectPoints.size() == 1) {
                // one arrow end is enclosed in the shape, we can only splice/connect if that connection is not already connected.
                final BoundingBox bbox = shape.getContainer().getComputedBoundingPoints().getBoundingBox();
                if (bbox.contains(headCon.getPoint()) && (headCon.getMagnet() != null)) {
                    return accept;
                } else if (bbox.contains(tailCon.getPoint()) && (headCon.getMagnet() != null)) {
                    return accept;
                } else {
                    throw new RuntimeException("Defensive programming: should not be possible if there is a single intersection.");
                }
            }
            c.getWiresConnectorHandler().getControl().hideControlPoints();
            final Point2DArray oldPoints = c.getLine().getPoint2DArray();
            int firstSegmentIndex = Integer.MAX_VALUE;
            int lastSegmentIndex = 0;
            for (final Point2D p : intersectPoints) {
                final double x = p.getX() + absLoc.getX();
                final double y = p.getY() + absLoc.getY();
                // get first and last segment, this can happen if shape straddles multiple segments of the line
                final int pointIndex = WiresConnectorControlImpl.getIndexForSelectedSegment(c, (int) x, (int) y, oldPoints);
                if (pointIndex < firstSegmentIndex) {
                    firstSegmentIndex = pointIndex;
                }
                if (pointIndex > lastSegmentIndex) {
                    lastSegmentIndex = pointIndex;
                }
            }
            WiresConnector c2 = null;
            // record these, as they may need restoring later.
            double tailXOffset = 0;
            double tailYOffset = 0;
            boolean tailAutoConnection = false;
            Point2D tailPoint = null;
            WiresMagnet tailMagnet = null;
            if (tailCon != null) {
                tailXOffset = tailCon.getXOffset();
                tailYOffset = tailCon.getYOffset();
                tailAutoConnection = tailCon.isAutoConnection();
                tailMagnet = tailCon.getMagnet();
                tailPoint = tailCon.getPoint();
            }
            if (firstSegmentIndex > 0) {
                final Point2DArray newPoints1 = new Point2DArray();
                final Point2DArray newPoints2 = new Point2DArray();
                newPoints1.push(oldPoints.get(0));
                for (int i = 1; i < firstSegmentIndex; i++) {
                    newPoints1.push(oldPoints.get(i));
                }
                final WiresMagnet cmagnet = shape.getMagnets().getMagnet(1);
                // check if isAllowed
                WiresConnectionControlImpl.allowedMagnetAndUpdateAutoConnections(headCon, true, shape, cmagnet, false);
                accept = accept && WiresConnectionControlImpl.allowedMagnetAndUpdateAutoConnections(tailCon, false, shape, cmagnet, false);
                if (!accept) {
                    return accept;
                }
                if (intersectPoints.size() > 1) {
                    final Point2D startPoint = new Point2D(cmagnet.getControl().getX(), cmagnet.getControl().getY());
                    newPoints2.push(startPoint);
                    // will skip any segments between first and last. this happens if a shape straddles multiple segments.
                    for (int i = lastSegmentIndex; i < oldPoints.size(); i++) {
                        newPoints2.push(oldPoints.get(i));
                    }
                    final AbstractDirectionalMultiPointShape<?> line = c.getLine().copy();
                    line.setPoint2DArray(newPoints2);
                    c2 = new WiresConnector(line, c.getHeadDecorator().copy(), c.getTailDecorator().copy());
                    wiresManager.register(c2);
                    final WiresConnection headCon2 = c2.getHeadConnection();
                    headCon2.setAutoConnection(true);
                    // reset, if not already 0
                    headCon2.setXOffset(0);
                    headCon2.setYOffset(0);
                    final WiresConnection tailCon2 = c2.getTailConnection();
                    // preserve tail auto connection
                    tailCon2.setAutoConnection(tailCon.isAutoConnection());
                    tailCon2.setMagnet(tailCon.getMagnet());
                    // reset, if not already 0
                    tailCon2.setXOffset(tailCon.getXOffset());
                    tailCon2.setYOffset(tailCon.getYOffset());
                    tailCon2.setPoint(tailCon.getPoint());
                    accept = accept && WiresConnectionControlImpl.allowedMagnetAndUpdateAutoConnections(headCon2, true, shape, cmagnet, true);
                    if (!accept) {
                        // we already checked isAllowed before mutation, so this in theory should not be needed. Adding for future proofing and completeness - in
                        // case a future version doesn't require identical behavioural logic for allowed and accept.
                        tailCon2.setMagnet(null);
                        wiresManager.deregister(c2);
                        return accept;
                    }
                }
                // this is done after the potential newPoitns2, as it reads values from the original connector.
                final Point2D endPoint = new Point2D(cmagnet.getControl().getX(), cmagnet.getControl().getY());
                newPoints1.push(endPoint);
                tailCon.setAutoConnection(true);
                // reset, if not already 0
                tailCon.setXOffset(0);
                tailCon.setYOffset(0);
                tailCon.setPoint(endPoint);
                c.getLine().setPoint2DArray(newPoints1);
                accept = accept && WiresConnectionControlImpl.allowedMagnetAndUpdateAutoConnections(tailCon, false, shape, cmagnet, true);
                if (!accept) {
                    // case a future version doesn't require identical behavioural logic for allowed and accept.
                    if (c2 != null) {
                        c2.getTailConnection().setMagnet(null);
                        c2.getHeadConnection().setMagnet(null);
                        wiresManager.deregister(c2);
                    }
                    tailCon.setAutoConnection(tailAutoConnection);
                    // reset, if not already 0
                    tailCon.setXOffset(tailXOffset);
                    tailCon.setYOffset(tailYOffset);
                    tailCon.setMagnet(tailMagnet);
                    tailCon.setPoint(tailPoint);
                    return accept;
                }
            }
        }
    }
    return accept;
}
Also used : MultiPath(com.ait.lienzo.client.core.shape.MultiPath) WiresConnector(com.ait.lienzo.client.core.shape.wires.WiresConnector) WiresConnection(com.ait.lienzo.client.core.shape.wires.WiresConnection) Point2DArray(com.ait.lienzo.client.core.types.Point2DArray) Point2D(com.ait.lienzo.client.core.types.Point2D) OrthogonalPolyLine(com.ait.lienzo.client.core.shape.OrthogonalPolyLine) BoundingBox(com.ait.lienzo.client.core.types.BoundingBox) WiresMagnet(com.ait.lienzo.client.core.shape.wires.WiresMagnet)

Example 27 with MultiPath

use of com.ait.lienzo.client.core.shape.MultiPath in project lienzo-core by ahome-it.

the class SelectionManager method getItemsInBoundingBox.

public void getItemsInBoundingBox(final BoundingBox selectionBox) {
    m_selected.setSelectionGroup(true);
    final BoundingBox box = m_selected.getBoundingBox();
    BoundingBox nodeBox = null;
    final List<WiresShape> shapesList = new ArrayList<>();
    final List<WiresShape> toBeRemoved = new ArrayList<>();
    final Map<String, WiresShape> shapesMap = new HashMap<>();
    final Map<String, BoundingBox> uuidMap = new HashMap<>();
    // first build a map of all shapes that intersect with teh selection rectangle. Nested shapes will be used later.
    for (final WiresShape shape : m_wiresManager.getShapesMap().values()) {
        if (shape.getDockedTo() != null) {
            // docked items cannot be added to a selection, only their parent they are docked to
            continue;
        }
        nodeBox = shape.getContainer().getComputedBoundingPoints().getBoundingBox();
        if (selectionBox.intersects(nodeBox)) {
            shapesList.add(shape);
            shapesMap.put(shape.getContainer().uuid(), shape);
            uuidMap.put(shape.getContainer().uuid(), nodeBox);
        }
    }
    // add to removal list any shape whose parent is also in the selection
    for (final WiresShape shape : shapesMap.values()) {
        if ((null != shape.getParent()) && shapesMap.containsKey(shape.getParent().getContainer().uuid())) {
            // can't remove yet, as it may have selected children itself, which will also need to be removed
            toBeRemoved.add(shape);
        }
    }
    // now the list is built, safely remove the shapes
    for (final WiresShape shape : toBeRemoved) {
        shapesMap.remove(shape.getContainer().uuid());
    }
    for (final WiresShape shape : shapesMap.values()) {
        nodeBox = uuidMap.get(shape.getContainer().uuid());
        m_selected.add(shape);
        box.add(nodeBox);
    }
    for (final WiresConnector connector : m_wiresManager.getConnectorList()) {
        final boolean externallyConnected = isExternallyConnected(connector);
        final Point2DArray points = new Point2DArray();
        final Point2D loc = getSelectionShape().getLocation();
        final BoundingBox boundingBox = getSelectionShape().getBoundingBox();
        points.push(loc.getX(), loc.getY());
        points.push(loc.getX() + boundingBox.getWidth(), loc.getY());
        points.push(loc.getX() + boundingBox.getWidth(), loc.getY() + boundingBox.getHeight());
        points.push(loc.getX(), loc.getY() + boundingBox.getHeight());
        nodeBox = connector.getGroup().getComputedBoundingPoints().getBoundingBox();
        if (selectionBox.contains(nodeBox)) {
            addConnector(connector, externallyConnected, box, nodeBox);
        } else {
            Point2DArray intersections = Geometry.getIntersectPolyLinePath(points, connector.getLine().getPathPartList(), true);
            if ((intersections != null) && (intersections.size() > 0)) {
                addConnector(connector, externallyConnected, box, nodeBox);
            } else {
                // the above checked the line, also check the head and tail.
                // head is rotated around an offset with also set. The reverse of this must be applied to the
                // selection rectangle, to ensure thinsg are all in the same space,  for intersection to work
                MultiPath path = connector.getHead();
                Transform xfrm = new Transform();
                xfrm.translate(path.getOffset().getX(), path.getOffset().getY());
                xfrm.rotate(0 - path.getRotation());
                xfrm.translate(0 - path.getX(), 0 - path.getY());
                xfrm.translate(0 - path.getOffset().getX(), 0 - path.getOffset().getY());
                Point2DArray transformedPoints = points.copy();
                for (final Point2D p : transformedPoints) {
                    xfrm.transform(p, p);
                }
                intersections = Geometry.getIntersectPolyLinePath(transformedPoints, connector.getHead().getActualPathPartListArray().get(0), true);
                if ((intersections != null) && (intersections.size() > 0)) {
                    addConnector(connector, externallyConnected, box, nodeBox);
                } else {
                    // tail is rotated around an offset with also set. The reverse of this must be applied to the
                    // selection rectangle, to ensure thinsg are all in the same space,  for intersection to work
                    path = connector.getTail();
                    xfrm = new Transform();
                    xfrm.translate(path.getOffset().getX(), path.getOffset().getY());
                    xfrm.rotate(0 - path.getRotation());
                    xfrm.translate(0 - path.getX(), 0 - path.getY());
                    xfrm.translate(0 - path.getOffset().getX(), 0 - path.getOffset().getY());
                    transformedPoints = points.copy();
                    for (final Point2D p : transformedPoints) {
                        xfrm.transform(p, p);
                    }
                    intersections = Geometry.getIntersectPolyLinePath(transformedPoints, connector.getTail().getActualPathPartListArray().get(0), true);
                    if ((intersections != null) && (intersections.size() > 0)) {
                        addConnector(connector, externallyConnected, box, nodeBox);
                    }
                }
            }
        }
    }
}
Also used : MultiPath(com.ait.lienzo.client.core.shape.MultiPath) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) NFastArrayList(com.ait.tooling.nativetools.client.collection.NFastArrayList) Point2DArray(com.ait.lienzo.client.core.types.Point2DArray) Point2D(com.ait.lienzo.client.core.types.Point2D) BoundingBox(com.ait.lienzo.client.core.types.BoundingBox) Transform(com.ait.lienzo.client.core.types.Transform)

Example 28 with MultiPath

use of com.ait.lienzo.client.core.shape.MultiPath in project kie-wb-common by kiegroup.

the class WiresConnectorViewExtTest method setup.

@Before
@SuppressWarnings("unchecked")
public void setup() throws Exception {
    HEAD_DECORATOR = new MultiPathDecorator(new MultiPath().rect(0, 0, 10, 10));
    TAIL_DECORATOR = new MultiPathDecorator(new MultiPath().rect(0, 0, 10, 10));
    POINTS = new Point2DArray(new Point2D(0, 10), new Point2D(10, 10), new Point2D(20, 20), new Point2D(30, 30), new Point2D(40, 40));
    line = new PolyLine(POINTS);
    layer = spy(new Layer());
    doAnswer(invocation -> {
        ((Consumer) invocation.getArguments()[0]).accept(labelText);
        return label;
    }).when(label).configure(any(Consumer.class));
    tested = spy(new WiresConnectorViewExt(ShapeViewSupportedEvents.DESKTOP_CONNECTOR_EVENT_TYPES, line, HEAD_DECORATOR, TAIL_DECORATOR) {

        @Override
        protected Optional<WiresConnectorLabel> createLabel(String title) {
            return Optional.of(WiresConnectorViewExtTest.this.label);
        }
    });
    tested.setControl(connectorControl);
    layer.add(tested.getGroup());
}
Also used : Point2DArray(com.ait.lienzo.client.core.types.Point2DArray) MultiPath(com.ait.lienzo.client.core.shape.MultiPath) WiresConnectorLabel(com.ait.lienzo.client.core.shape.wires.util.WiresConnectorLabel) Consumer(com.ait.tooling.common.api.java.util.function.Consumer) Point2D(com.ait.lienzo.client.core.types.Point2D) MultiPathDecorator(com.ait.lienzo.client.core.shape.MultiPathDecorator) PolyLine(com.ait.lienzo.client.core.shape.PolyLine) Layer(com.ait.lienzo.client.core.shape.Layer) Before(org.junit.Before)

Example 29 with MultiPath

use of com.ait.lienzo.client.core.shape.MultiPath in project kie-wb-common by kiegroup.

the class AbstractConnectorView method createLine.

static Object[] createLine(LineConnectorFactory lineFactory, ConnectorShapeDef.Direction direction, final double... points) {
    // The head decorator must be not visible, as connectors are unidirectional.
    final MultiPath head = BOTH.equals(direction) ? getArrowMultiPath() : new MultiPath();
    final MultiPath tail = BOTH.equals(direction) || ONE.equals(direction) ? getArrowMultiPath() : new MultiPath();
    final AbstractDirectionalMultiPointShape<?> line = lineFactory.createLine(Point2DArray.fromArrayOfDouble(points));
    line.setDraggable(true);
    line.setSelectionStrokeOffset(SELECTION_OFFSET);
    line.setHeadOffset(head.getBoundingBox().getHeight());
    line.setTailOffset(tail.getBoundingBox().getHeight());
    final MultiPathDecorator headDecorator = new MultiPathDecorator(head);
    final MultiPathDecorator tailDecorator = new MultiPathDecorator(tail);
    return new Object[] { line, headDecorator, tailDecorator };
}
Also used : MultiPath(com.ait.lienzo.client.core.shape.MultiPath) MultiPathDecorator(com.ait.lienzo.client.core.shape.MultiPathDecorator)

Example 30 with MultiPath

use of com.ait.lienzo.client.core.shape.MultiPath in project kie-wb-common by kiegroup.

the class AuthorityRequirementView method createLine.

private static Object[] createLine(final double x1, final double y1, final double x2, final double y2) {
    final MultiPath head = new MultiPath();
    final MultiPath tail = new MultiPath().M(DECORATOR_RADIUS, -DECORATOR_RADIUS).circle(DECORATOR_RADIUS).setFillColor(ColorName.BLACK).setFillAlpha(1);
    final DirectionalLine line = new DirectionalLine(x1, y1, x2, y2);
    line.setDashArray(new DashArray(4, 4));
    line.setDraggable(true);
    line.setSelectionStrokeOffset(SELECTION_OFFSET);
    line.setHeadOffset(head.getBoundingBox().getHeight());
    line.setTailOffset(tail.getBoundingBox().getHeight());
    final MultiPathDecorator headDecorator = new MultiPathDecorator(head);
    final MultiPathDecorator tailDecorator = new MultiPathDecorator(tail);
    return new Object[] { line, headDecorator, tailDecorator };
}
Also used : MultiPath(com.ait.lienzo.client.core.shape.MultiPath) MultiPathDecorator(com.ait.lienzo.client.core.shape.MultiPathDecorator) DashArray(com.ait.lienzo.client.core.types.DashArray)

Aggregations

MultiPath (com.ait.lienzo.client.core.shape.MultiPath)39 Test (org.junit.Test)16 WiresShapeView (org.kie.workbench.common.stunner.client.lienzo.shape.view.wires.WiresShapeView)10 MultiPathDecorator (com.ait.lienzo.client.core.shape.MultiPathDecorator)9 WiresShape (com.ait.lienzo.client.core.shape.wires.WiresShape)9 BoundingBox (com.ait.lienzo.client.core.types.BoundingBox)7 Point2D (com.ait.lienzo.client.core.types.Point2D)7 Point2DArray (com.ait.lienzo.client.core.types.Point2DArray)4 Before (org.junit.Before)4 Layer (com.ait.lienzo.client.core.shape.Layer)3 PickerPart (com.ait.lienzo.client.core.shape.wires.PickerPart)3 DashArray (com.ait.lienzo.client.core.types.DashArray)3 PictureShapeView (org.kie.workbench.common.stunner.shapes.client.view.PictureShapeView)3 Group (com.ait.lienzo.client.core.shape.Group)2 WiresConnection (com.ait.lienzo.client.core.shape.wires.WiresConnection)2 WiresConnector (com.ait.lienzo.client.core.shape.wires.WiresConnector)2 WiresMagnet (com.ait.lienzo.client.core.shape.wires.WiresMagnet)2 NFastArrayList (com.ait.tooling.nativetools.client.collection.NFastArrayList)2 SafeUri (com.google.gwt.safehtml.shared.SafeUri)2 Edge (org.kie.workbench.common.stunner.core.graph.Edge)2