Search in sources :

Example 21 with ConstraintAnchor

use of android.support.constraint.solver.widgets.ConstraintAnchor 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 22 with ConstraintAnchor

use of android.support.constraint.solver.widgets.ConstraintAnchor 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 23 with ConstraintAnchor

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

the class SnapPlacement method snapExistingVerticalMargin.

/**
     * Try move the widget on the vertical axis, snapping an existing margin
     * to WidgetsView.GRID_SPACING
     *
     * @param widget         the widget we operate on
     * @param candidatePoint the candidate new position
     * @return true if we changed the margin on the vertical axis
     */
private static boolean snapExistingVerticalMargin(ConstraintWidget widget, Point candidatePoint) {
    int y = candidatePoint.y;
    boolean snapped = false;
    ConstraintAnchor top = widget.getAnchor(ConstraintAnchor.Type.TOP);
    ConstraintAnchor bottom = widget.getAnchor(ConstraintAnchor.Type.BOTTOM);
    if (top.isConnected() && bottom.isConnected()) {
    // we do nothing in this case
    } else if (top.isConnected()) {
        int y1 = y;
        int y2 = WidgetInteractionTargets.constraintHandle(top.getTarget()).getDrawY();
        int margin = ((y1 - y2) / SceneDraw.GRID_SPACING) * SceneDraw.GRID_SPACING;
        if (margin < 0) {
            margin = 0;
        }
        top.setMargin(margin);
        snapped = true;
    } else if (bottom.isConnected()) {
        int y1 = y + widget.getHeight();
        int y2 = WidgetInteractionTargets.constraintHandle(bottom.getTarget()).getDrawY();
        int margin = ((y2 - y1) / SceneDraw.GRID_SPACING) * SceneDraw.GRID_SPACING;
        if (margin < 0) {
            margin = 0;
        }
        bottom.setMargin(margin);
        snapped = true;
    }
    return snapped;
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) Point(java.awt.Point)

Example 24 with ConstraintAnchor

use of android.support.constraint.solver.widgets.ConstraintAnchor 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)

Example 25 with ConstraintAnchor

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

the class WidgetResize method resizeWidget.

/**
     * Resize the widget given the current mouse position
     *
     * @param widgets the list of known widgets
     * @param widget the widget we are resizing
     * @param posX   in android coordinate
     * @param posY   in android coordinate
     */
public void resizeWidget(Collection<ConstraintWidget> widgets, ConstraintWidget widget, ResizeHandle handle, Rectangle originalBounds, int posX, int posY) {
    if (widget == null) {
        return;
    }
    Animator.setAnimationEnabled(false);
    mSnapCandidates.clear();
    int x = widget.getDrawX();
    int y = widget.getDrawY();
    int w = widget.getDrawWidth();
    int h = widget.getDrawHeight();
    ResizeHandle.Type resize = handle.getType();
    ConstraintAnchor left = widget.getAnchor(ConstraintAnchor.Type.LEFT);
    ConstraintAnchor top = widget.getAnchor(ConstraintAnchor.Type.TOP);
    ConstraintAnchor right = widget.getAnchor(ConstraintAnchor.Type.RIGHT);
    ConstraintAnchor bottom = widget.getAnchor(ConstraintAnchor.Type.BOTTOM);
    ConstraintAnchor baseline = widget.getAnchor(ConstraintAnchor.Type.BASELINE);
    boolean leftIsConnected = left != null && left.isConnected();
    boolean rightIsConnected = right != null && right.isConnected();
    boolean topIsConnected = top != null && top.isConnected();
    boolean bottomIsConnected = bottom != null && bottom.isConnected();
    boolean baselineIsConnected = baseline != null && baseline.isConnected();
    // Limits range of motion depending on which anchor is connected
    if (leftIsConnected && !rightIsConnected) {
        switch(resize) {
            case LEFT_TOP:
                {
                    resize = ResizeHandle.Type.TOP_SIDE;
                }
                break;
            case LEFT_BOTTOM:
                {
                    resize = ResizeHandle.Type.BOTTOM_SIDE;
                }
                break;
        }
    }
    if (rightIsConnected && !leftIsConnected) {
        switch(resize) {
            case RIGHT_TOP:
                {
                    resize = ResizeHandle.Type.TOP_SIDE;
                }
                break;
            case RIGHT_BOTTOM:
                {
                    resize = ResizeHandle.Type.BOTTOM_SIDE;
                }
                break;
        }
    }
    if ((topIsConnected || baselineIsConnected) && !bottomIsConnected) {
        switch(resize) {
            case LEFT_TOP:
                {
                    resize = ResizeHandle.Type.LEFT_SIDE;
                }
                break;
            case RIGHT_TOP:
                {
                    resize = ResizeHandle.Type.RIGHT_SIDE;
                }
                break;
        }
    }
    if (bottomIsConnected && !topIsConnected) {
        switch(resize) {
            case LEFT_BOTTOM:
                {
                    resize = ResizeHandle.Type.LEFT_SIDE;
                }
                break;
            case RIGHT_BOTTOM:
                {
                    resize = ResizeHandle.Type.RIGHT_SIDE;
                }
                break;
        }
    }
    ConstraintWidget base = widget.getParent();
    switch(resize) {
        case LEFT_TOP:
            {
                int newX = Math.min(originalBounds.x + originalBounds.width - widget.getMinWidth(), posX);
                newX = clampX(newX, base);
                newX = snapLeft(widgets, widget, newX, mSnapCandidates);
                int newY = Math.min(originalBounds.y + originalBounds.height - widget.getMinHeight(), posY);
                newY = clampY(newY, base);
                newY = snapTop(widgets, widget, newY, mSnapCandidates);
                int newWidth = originalBounds.x + originalBounds.width - newX;
                int newHeight = originalBounds.y + originalBounds.height - newY;
                setNewFrame(widget, newX, newY, newWidth, newHeight);
            }
            break;
        case LEFT_BOTTOM:
            {
                int newX = Math.min(originalBounds.x + originalBounds.width - widget.getMinWidth(), posX);
                newX = clampX(newX, base);
                newX = snapLeft(widgets, widget, newX, mSnapCandidates);
                int newWidth = originalBounds.x + originalBounds.width - newX;
                int newHeight = posY - originalBounds.y;
                newHeight = snapHeight(widgets, widget, newHeight, mSnapCandidates);
                setNewFrame(widget, newX, y, newWidth, newHeight);
            }
            break;
        case RIGHT_TOP:
            {
                int newY = Math.min(originalBounds.y + originalBounds.height - widget.getMinHeight(), posY);
                newY = clampY(newY, base);
                newY = snapTop(widgets, widget, newY, mSnapCandidates);
                int newWidth = posX - originalBounds.x;
                newWidth = snapWidth(widgets, widget, newWidth, mSnapCandidates);
                int newHeight = originalBounds.y + originalBounds.height - newY;
                setNewFrame(widget, x, newY, newWidth, newHeight);
            }
            break;
        case RIGHT_BOTTOM:
            {
                int newWidth = posX - originalBounds.x;
                int newHeight = posY - originalBounds.y;
                newWidth = snapWidth(widgets, widget, newWidth, mSnapCandidates);
                newHeight = snapHeight(widgets, widget, newHeight, mSnapCandidates);
                setNewFrame(widget, x, y, newWidth, newHeight);
            }
            break;
        case LEFT_SIDE:
            {
                int newX = Math.min(originalBounds.x + originalBounds.width - widget.getMinWidth(), posX);
                if (widget instanceof Guideline) {
                    newX = posX;
                }
                newX = clampX(newX, base);
                newX = snapLeft(widgets, widget, newX, mSnapCandidates);
                int newWidth = originalBounds.x + originalBounds.width - newX;
                setNewFrame(widget, newX, y, newWidth, h);
            }
            break;
        case RIGHT_SIDE:
            {
                int newWidth = posX - originalBounds.x;
                newWidth = snapWidth(widgets, widget, newWidth, mSnapCandidates);
                setNewFrame(widget, x, y, newWidth, h);
            }
            break;
        case TOP_SIDE:
            {
                int newY = Math.min(originalBounds.y + originalBounds.height - widget.getMinHeight(), posY);
                if (widget instanceof Guideline) {
                    newY = posY;
                }
                newY = clampY(newY, base);
                newY = snapTop(widgets, widget, newY, mSnapCandidates);
                int newHeight = originalBounds.y + originalBounds.height - newY;
                setNewFrame(widget, x, newY, w, newHeight);
            }
            break;
        case BOTTOM_SIDE:
            {
                int newHeight = posY - originalBounds.y;
                newHeight = snapHeight(widgets, widget, newHeight, mSnapCandidates);
                setNewFrame(widget, x, y, w, newHeight);
            }
            break;
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) Guideline(android.support.constraint.solver.widgets.Guideline)

Aggregations

ConstraintAnchor (android.support.constraint.solver.widgets.ConstraintAnchor)26 ConstraintWidget (android.support.constraint.solver.widgets.ConstraintWidget)10 Guideline (android.support.constraint.solver.widgets.Guideline)8 Point (java.awt.Point)7 ConstraintHandle (com.android.tools.sherpa.interaction.ConstraintHandle)4 ConstraintWidgetContainer (android.support.constraint.solver.widgets.ConstraintWidgetContainer)3 WidgetCompanion (com.android.tools.sherpa.structure.WidgetCompanion)3 Graphics2D (java.awt.Graphics2D)2 ArrayList (java.util.ArrayList)2 ConstraintTableLayout (android.support.constraint.solver.widgets.ConstraintTableLayout)1 WidgetDecorator (com.android.tools.sherpa.drawing.decorator.WidgetDecorator)1 WidgetInteractionTargets (com.android.tools.sherpa.interaction.WidgetInteractionTargets)1