Search in sources :

Example 31 with ConstraintWidget

use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.

the class ConstraintHandle method drawConnection.

/**
     * Implements the drawing of the connection from this anchor to its target
     *
     * @param transform  the view transform
     * @param g          the graphics context
     * @param colorSet   the current colorset
     * @param isSelected if the connection is selected
     */
public void drawConnection(ViewTransform transform, Graphics2D g, ColorSet colorSet, boolean isSelected, boolean showMargin, int originalCreator, float progress) {
    if (!mAnchor.isConnected()) {
        return;
    }
    if (mAnchor != null && mAnchor.getConnectionCreator() == ConstraintAnchor.AUTO_CONSTRAINT_CREATOR) {
        startLock();
    }
    ConnectionDrawing drawing = new ConnectionDrawing();
    ConstraintWidget targetWidget = mAnchor.getTarget().getOwner();
    WidgetCompanion targetCompanion = (WidgetCompanion) targetWidget.getCompanionWidget();
    if (targetCompanion == null) {
        return;
    }
    WidgetInteractionTargets interactionTargets = targetCompanion.getWidgetInteractionTargets();
    ConstraintHandle targetHandle = interactionTargets.getConstraintHandle(mAnchor.getTarget());
    if (targetHandle == null) {
        // TODO fix -- sometimes triggered with guideline and inference
        return;
    }
    g.setStroke(sSimpleStroke);
    int sx = transform.getSwingFX(mX);
    int sy = transform.getSwingFY(mY);
    int tx = transform.getSwingFX(targetHandle.getDrawX());
    int ty = transform.getSwingFY(targetHandle.getDrawY());
    if (targetHandle.getOwner().isRootContainer()) {
        if (mAnchor.isVerticalAnchor()) {
            tx = sx;
        } else {
            ty = sy;
        }
    }
    int minimum = (int) (1.5 * ConnectionDraw.CONNECTION_ANCHOR_SIZE);
    if (Math.abs(sx - tx) < minimum && Math.abs(sy - ty) < minimum) {
        switch(mAnchor.getType()) {
            case LEFT:
                {
                    drawShadowedArrow(g, colorSet, ConnectionDraw.getLeftArrow(), sx, sy);
                }
                break;
            case TOP:
                {
                    drawShadowedArrow(g, colorSet, ConnectionDraw.getTopArrow(), sx, sy);
                }
                break;
            case RIGHT:
                {
                    drawShadowedArrow(g, colorSet, ConnectionDraw.getRightArrow(), sx, sy);
                }
                break;
            case BOTTOM:
                {
                    drawShadowedArrow(g, colorSet, ConnectionDraw.getBottomArrow(), sx, sy);
                }
                break;
        }
        return;
    }
    if (mAnchor.getOpposite() != null && mAnchor.getOpposite().isConnected()) {
        // Draw centered connections
        if (mAnchor.getOpposite().getTarget() == mAnchor.getTarget()) {
            // Center connection on same anchor
            addPathCenteredConnectionOnSameAnchor(transform, g, isSelected, drawing, targetHandle, targetWidget);
        } else if ((mAnchor.getOpposite().getTarget().getOwner() == mAnchor.getTarget().getOwner()) && targetWidget != getOwner().getParent()) {
            if (mAnchor.getConnectionCreator() == ConstraintAnchor.AUTO_CONSTRAINT_CREATOR) {
                g.setStroke(colorSet.getSoftConstraintStroke());
            }
            // Center connection on same widget (save our parent)
            addPathCenteredConnectionOnSameWidget(transform, g, isSelected, drawing, colorSet, targetHandle, targetWidget);
        } else {
            if (mAnchor.getConnectionCreator() == ConstraintAnchor.AUTO_CONSTRAINT_CREATOR) {
                g.setStroke(colorSet.getSoftConstraintStroke());
            }
            // Center connection on different widgets (or our parent)
            addPathCenteredConnection(transform, g, isSelected, drawing, colorSet, targetHandle, targetWidget);
        }
    } else {
        addPathConnection(transform, g, isSelected, showMargin, drawing, colorSet, targetHandle.getDrawX(), targetHandle.getDrawY(), mAnchor.isConnected(), targetHandle.getAnchor().isConnected());
    }
    // If a lock timer is active, draw the path a second time
    if (progress <= 1 && progress >= 0.1) {
        int distance = lengthOfPath(drawing.mPath);
        int dashFull = (int) (distance * progress);
        int dashEmpty = (int) (distance * (1 - progress));
        if (dashFull > 0 || dashEmpty > 0) {
            Stroke s = g.getStroke();
            if (originalCreator == ConstraintAnchor.AUTO_CONSTRAINT_CREATOR || originalCreator == ConstraintAnchor.SCOUT_CREATOR) {
                if (originalCreator != ConstraintAnchor.SCOUT_CREATOR) {
                    g.setColor(colorSet.getSoftConstraintColor());
                    g.setStroke(colorSet.getSoftConstraintStroke());
                    drawing.draw(g);
                }
                Stroke progressStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { dashFull, dashEmpty }, 0);
                g.setStroke(progressStroke);
                if (progress != 1) {
                    drawing.mDrawArrow = false;
                }
                if (originalCreator != ConstraintAnchor.SCOUT_CREATOR) {
                    g.setColor(colorSet.getSelectedConstraints());
                }
                drawing.draw(g);
            } else {
                g.setColor(colorSet.getSoftConstraintColor());
                g.setStroke(colorSet.getSoftConstraintStroke());
                drawing.draw(g);
                Stroke progressStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { dashEmpty, dashFull }, 0);
                g.setColor(colorSet.getSelectedConstraints());
                g.setStroke(progressStroke);
                if (progress == 1) {
                    drawing.mDrawArrow = false;
                }
                drawing.draw(g);
            }
            int distanceCircle = (int) (2 * Math.PI * 10);
            Color prev = g.getColor();
            int solidCircle = (int) (distanceCircle * progress);
            int emptyCircle = (int) (distanceCircle * (1 - progress));
            Stroke circleProgressStrokeOuter = new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { solidCircle, emptyCircle }, 0);
            g.setColor(colorSet.getBackground());
            g.setStroke(circleProgressStrokeOuter);
            int d = 2 * sCountDownRadius;
            g.drawRoundRect(sx - sCountDownRadius, sy - sCountDownRadius, d, d, d, d);
            Stroke circleProgressStroke = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { solidCircle, emptyCircle }, 0);
            g.setColor(prev);
            g.setStroke(circleProgressStroke);
            g.drawRoundRect(sx - sCountDownRadius, sy - sCountDownRadius, d, d, d, d);
            g.setStroke(s);
        }
    } else {
        paintShadow(g, colorSet, drawing);
        drawing.draw(g);
    }
}
Also used : ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) WidgetCompanion(com.android.tools.sherpa.structure.WidgetCompanion)

Example 32 with ConstraintWidget

use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.

the class SnapPlacement method checkVerticalParentMarginSnap.

/**
     * Check to snap on the vertical internal margins of a parent (used when resizing)
     *
     * @param anchor    the anchor we are trying to snap
     * @param type      the type of anchor on the parent that we want to check against
     * @param margin    the margin we'll use for the internal margin
     * @param candidate the current candidate that we can fill in
     */
private static void checkVerticalParentMarginSnap(ConstraintAnchor anchor, ConstraintAnchor.Type type, int margin, SnapCandidate candidate) {
    ConstraintWidget widget = anchor.getOwner();
    if (widget.getParent() == null) {
        return;
    }
    ConstraintAnchor targetParent = widget.getParent().getAnchor(type);
    ConstraintHandle targetParentHandle = WidgetInteractionTargets.constraintHandle(targetParent);
    ConstraintHandle anchorHandle = WidgetInteractionTargets.constraintHandle(anchor);
    ConstraintAnchor target = new ConstraintAnchor(widget.getParent(), type);
    int tx = targetParentHandle.getDrawX();
    int ty = targetParentHandle.getDrawY() + margin;
    int distance = Math.abs(anchorHandle.getDrawY() - ty);
    if (distance <= CONNECTION_SLOPE) {
        candidate.distance = distance;
        candidate.target = target;
        candidate.source = anchor;
        candidate.x = tx;
        candidate.y = ty;
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) Point(java.awt.Point)

Example 33 with ConstraintWidget

use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.

the class SnapPlacement method gatherMargins.

/**
     * Given a margin and its orientation, gather all similar margins among the widgets.
     * the margins list will be filled with the margins we found.
     *
     * @param widgets    the list of known widgets
     * @param margins    the list of margins we found
     * @param margin     the value of the margin we are looking for
     * @param isVertical the orientation of the margin we are looking for
     */
public static void gatherMargins(Collection<ConstraintWidget> widgets, ArrayList<SnapCandidate> margins, int margin, boolean isVertical) {
    margin = Math.abs(margin);
    if (margin == 0) {
        return;
    }
    // TODO: we should cache the margins found
    ArrayList<SnapCandidate> foundMargins = new ArrayList<>();
    for (ConstraintWidget w1 : widgets) {
        for (ConstraintAnchor a1 : w1.getAnchors()) {
            if (!a1.isSideAnchor()) {
                continue;
            }
            if (a1.isVerticalAnchor() != isVertical) {
                continue;
            }
            for (ConstraintWidget w2 : widgets) {
                for (ConstraintAnchor a2 : w2.getAnchors()) {
                    if (!a2.isSideAnchor()) {
                        continue;
                    }
                    if (!a2.isSimilarDimensionConnection(a1)) {
                        continue;
                    }
                    ConstraintHandle h1 = WidgetInteractionTargets.constraintHandle(a1);
                    ConstraintHandle h2 = WidgetInteractionTargets.constraintHandle(a2);
                    if (h1 == null || h2 == null) {
                        continue;
                    }
                    int currentMargin = h1.getStraightDistanceFrom(h2);
                    if (Math.abs(currentMargin) == margin) {
                        SnapCandidate candidate = new SnapCandidate();
                        candidate.source = a1;
                        candidate.target = a2;
                        candidate.margin = currentMargin;
                        foundMargins.add(candidate);
                    }
                }
            }
        }
    }
    for (SnapCandidate c1 : foundMargins) {
        boolean insert = true;
        for (SnapCandidate c2 : margins) {
            // if we have the opposite margin, don't use it
            if ((Math.abs(c1.margin) == Math.abs(c2.margin)) && ((c2.source == c1.target && c2.target == c1.source) || (c2.source == c1.source && c2.target == c1.target))) {
                insert = false;
                break;
            }
            // if we have margins for the same position, don't use them
            if (c1.source.isSimilarDimensionConnection(c2.source) && c1.margin == c2.margin) {
                ConstraintHandle sourceHandle1 = WidgetInteractionTargets.constraintHandle(c1.source);
                ConstraintHandle targetHandle1 = WidgetInteractionTargets.constraintHandle(c1.target);
                ConstraintHandle sourceHandle2 = WidgetInteractionTargets.constraintHandle(c2.source);
                ConstraintHandle targetHandle2 = WidgetInteractionTargets.constraintHandle(c2.target);
                if (c1.source.isVerticalAnchor()) {
                    if (Math.min(sourceHandle1.getDrawY(), targetHandle1.getDrawY()) == Math.min(sourceHandle2.getDrawY(), targetHandle2.getDrawY())) {
                        insert = false;
                        break;
                    }
                } else if (Math.min(sourceHandle1.getDrawX(), targetHandle1.getDrawX()) == Math.min(sourceHandle2.getDrawX(), targetHandle2.getDrawX())) {
                    insert = false;
                    break;
                }
            }
        }
        if (insert) {
            margins.add(c1);
        }
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) ArrayList(java.util.ArrayList) Point(java.awt.Point)

Example 34 with ConstraintWidget

use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.

the class SnapPlacement method snapAnchor.

/**
     * Try to find snapping candidates for the given anchor
     *
     * @param widgets   the list of known widgets
     * @param widget    the widget we operate on
     * @param anchor    the anchor we are trying to snap
     * @param candidate the current candidate
     */
public static void snapAnchor(Collection<ConstraintWidget> widgets, ConstraintWidget widget, ConstraintAnchor anchor, SnapCandidate candidate) {
    if (widget.getParent() != null) {
        if (!anchor.isVerticalAnchor()) {
            checkHorizontalParentMarginSnap(anchor, ConstraintAnchor.Type.RIGHT, -DEFAULT_MARGIN, candidate);
            checkHorizontalParentMarginSnap(anchor, ConstraintAnchor.Type.LEFT, DEFAULT_MARGIN, candidate);
        } else {
            checkVerticalParentMarginSnap(anchor, ConstraintAnchor.Type.BOTTOM, -DEFAULT_MARGIN, candidate);
            checkVerticalParentMarginSnap(anchor, ConstraintAnchor.Type.TOP, DEFAULT_MARGIN, candidate);
        }
    }
    for (ConstraintWidget w : widgets) {
        if (w == widget) {
            continue;
        }
        ArrayList<ConstraintAnchor> anchorsTarget = w.getAnchors();
        for (ConstraintAnchor at : anchorsTarget) {
            snapCheck(anchor, at, candidate, CONNECTION_SLOPE);
        }
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget)

Example 35 with ConstraintWidget

use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.

the class SnapPlacement method checkHorizontalParentMarginSnap.

/**
     * Check to snap on the horizontal internal margins of a parent (used when resizing)
     *
     * @param anchor    the anchor we are trying to snap
     * @param type      the type of anchor on the parent that we want to check against
     * @param margin    the margin we'll use for the internal margin
     * @param candidate the current candidate that we can fill in
     */
private static void checkHorizontalParentMarginSnap(ConstraintAnchor anchor, ConstraintAnchor.Type type, int margin, SnapCandidate candidate) {
    ConstraintWidget widget = anchor.getOwner();
    if (widget.getParent() == null) {
        return;
    }
    ConstraintAnchor targetParent = widget.getParent().getAnchor(type);
    ConstraintHandle targetParentHandle = WidgetInteractionTargets.constraintHandle(targetParent);
    ConstraintHandle anchorHandle = WidgetInteractionTargets.constraintHandle(anchor);
    ConstraintAnchor target = new ConstraintAnchor(widget.getParent(), type);
    int tx = targetParentHandle.getDrawX() + margin;
    int ty = targetParentHandle.getDrawY();
    int distance = Math.abs(anchorHandle.getDrawX() - tx);
    if (distance <= CONNECTION_SLOPE) {
        candidate.distance = distance;
        candidate.target = target;
        candidate.source = anchor;
        candidate.x = tx;
        candidate.y = ty;
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) Point(java.awt.Point)

Aggregations

ConstraintWidget (android.support.constraint.solver.widgets.ConstraintWidget)37 ConstraintAnchor (android.support.constraint.solver.widgets.ConstraintAnchor)11 Guideline (android.support.constraint.solver.widgets.Guideline)8 Rectangle (java.awt.Rectangle)7 ArrayList (java.util.ArrayList)7 WidgetCompanion (com.android.tools.sherpa.structure.WidgetCompanion)5 Point (java.awt.Point)5 ConstraintWidgetContainer (android.support.constraint.solver.widgets.ConstraintWidgetContainer)3 WidgetContainer (android.support.constraint.solver.widgets.WidgetContainer)3 ConstraintTableLayout (android.support.constraint.solver.widgets.ConstraintTableLayout)2 WidgetDecorator (com.android.tools.sherpa.drawing.decorator.WidgetDecorator)1 WidgetInteractionTargets (com.android.tools.sherpa.interaction.WidgetInteractionTargets)1 Ellipse2D (java.awt.geom.Ellipse2D)1 Arrays (java.util.Arrays)1 Comparator (java.util.Comparator)1 Iterator (java.util.Iterator)1