Search in sources :

Example 6 with ConstraintWidget

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

the class WidgetInteractionTargets method findClosestConnection.

/**
     * Fill in the ConnectionCandidate structure with the closest anchor found at (x, y).
     * This function will not consider CENTER_X/CENTER_Y anchors.
     *
     * @param viewTransform
     * @param x         x coordinate we are looking at
     * @param y         y coordinate we are looking at
     * @param candidate a structure containing the current best anchor candidate.
     * @param mousePress true if we are in mouse press
     */
public void findClosestConnection(ViewTransform viewTransform, float x, float y, ConnectionCandidate candidate, boolean mousePress) {
    // FIXME: should use subclasses this
    if (mWidget instanceof Guideline) {
        float distance;
        Guideline guideline = (Guideline) mWidget;
        ConstraintAnchor anchor = guideline.getAnchor();
        ConstraintHandle handle = constraintHandle(anchor);
        if (handle == null) {
            return;
        }
        if (guideline.getOrientation() == Guideline.VERTICAL) {
            distance = (handle.getDrawX() - x) * (handle.getDrawX() - x);
        } else {
            distance = (handle.getDrawY() - y) * (handle.getDrawY() - y);
        }
        distance = viewTransform.getSwingDimensionF(distance);
        if (distance < candidate.distance) {
            candidate.anchorTarget = anchor;
            candidate.distance = distance;
        }
    } else if (mWidget instanceof ConstraintWidgetContainer) {
        for (ConstraintHandle handle : mConstraintHandles) {
            ConstraintAnchor anchor = handle.getAnchor();
            if (anchor.getType() == ConstraintAnchor.Type.CENTER_X || anchor.getType() == ConstraintAnchor.Type.CENTER_Y) {
                continue;
            }
            float distance = 0;
            boolean computed = false;
            if (!mousePress && anchor.isSideAnchor()) {
                if (!anchor.isVerticalAnchor()) {
                    if (y >= mWidget.getDrawY() && y <= mWidget.getDrawBottom()) {
                        distance = (handle.getDrawX() - x) * (handle.getDrawX() - x);
                        computed = true;
                    }
                } else {
                    if (x >= mWidget.getDrawX() && x <= mWidget.getDrawRight()) {
                        distance = (handle.getDrawY() - y) * (handle.getDrawY() - y);
                        computed = true;
                    }
                }
            }
            if (!computed) {
                distance = (handle.getDrawX() - x) * (handle.getDrawX() - x) + (handle.getDrawY() - y) * (handle.getDrawY() - y);
            }
            distance = viewTransform.getSwingDimensionF(distance);
            if (distance < candidate.distance) {
                candidate.anchorTarget = anchor;
                candidate.distance = distance;
            }
        }
    } else {
        for (ConstraintHandle handle : mConstraintHandles) {
            ConstraintAnchor anchor = handle.getAnchor();
            float distance = (handle.getDrawX() - x) * (handle.getDrawX() - x) + (handle.getDrawY() - y) * (handle.getDrawY() - y);
            if (anchor.getType() == ConstraintAnchor.Type.CENTER_X || anchor.getType() == ConstraintAnchor.Type.CENTER_Y) {
                continue;
            }
            if (anchor.getType() == ConstraintAnchor.Type.BASELINE) {
                if (!anchor.getOwner().hasBaseline()) {
                    continue;
                }
                ConstraintWidget widget = anchor.getOwner();
                int minX = widget.getDrawX();
                int maxX = widget.getDrawRight();
                float d = Math.abs(handle.getDrawY() - y);
                if (x >= minX && x <= maxX && d < 3) {
                    distance = d * d;
                }
            }
            distance = viewTransform.getSwingDimensionF(distance);
            if (distance <= candidate.distance) {
                if (candidate.anchorTarget == null || candidate.anchorTarget.getPriorityLevel() < anchor.getPriorityLevel()) {
                    candidate.anchorTarget = anchor;
                    candidate.distance = distance;
                }
            }
        }
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) ConstraintWidgetContainer(android.support.constraint.solver.widgets.ConstraintWidgetContainer) Guideline(android.support.constraint.solver.widgets.Guideline)

Example 7 with ConstraintWidget

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

the class WidgetMotion method dragWidget.

/**
     * Drag widget to a new position
     *
     * @param widget      widget we are moving
     * @param x           in android coordinate
     * @param y           in android coordinate
     * @param snap        true if we want to snap this widget against others
     * @param isShiftDown true if the shift button is pressed
     * @param transform   the view transform
     * @return the type of direction (locked in x/y or not)
     */
public int dragWidget(Point startPoint, Selection.Element widget, int x, int y, boolean snap, boolean isShiftDown, ViewTransform transform) {
    int directionLockedStatus = Selection.DIRECTION_UNLOCKED;
    if (widget == null) {
        return directionLockedStatus;
    }
    Animator.setAnimationEnabled(false);
    int dX = startPoint.x - widget.origin.x;
    int dY = startPoint.y - widget.origin.y;
    int dragX = Math.abs(widget.widget.getDrawX() - widget.origin.x);
    int dragY = Math.abs(widget.widget.getDrawY() - widget.origin.y);
    if (dragX > SLOPE || dragY > SLOPE) {
        // Let's not show the anchors and resize handles if we are dragging
        mShowDecorations = false;
    }
    if (isShiftDown) {
        // check which overall direction we are going after enough drag
        if (widget.directionLocked == Selection.DIRECTION_UNLOCKED) {
            if (dragX > SLOPE || dragY > SLOPE) {
                if (dragX > dragY) {
                    // lock in x
                    widget.directionLocked = Selection.DIRECTION_LOCKED_X;
                    directionLockedStatus = Selection.DIRECTION_LOCKED_X;
                } else {
                    widget.directionLocked = Selection.DIRECTION_LOCKED_Y;
                    directionLockedStatus = Selection.DIRECTION_LOCKED_Y;
                }
            } else {
                // prevent snapping while we are figuring out the locked axis
                snap = false;
            }
        }
    } else {
        widget.directionLocked = Selection.DIRECTION_UNLOCKED;
    }
    candidatePoint.setLocation(x - dX, y - dY);
    ConstraintWidget base = widget.widget.getParent();
    if (base != null) {
        // limit motion to inside base
        if (candidatePoint.x < base.getDrawX()) {
            candidatePoint.x = base.getDrawX();
        } else if (candidatePoint.x > base.getDrawRight()) {
            candidatePoint.x = base.getDrawRight();
        }
        if (candidatePoint.y < base.getDrawY()) {
            candidatePoint.y = base.getDrawY();
        } else if (candidatePoint.y > base.getDrawBottom()) {
            candidatePoint.y = base.getDrawBottom();
        }
    }
    mSnapCandidates.clear();
    ArrayList<ConstraintWidget> widgetsToCheck = new ArrayList<>();
    for (ConstraintWidget w : mWidgetsScene.getWidgets()) {
        if (w.hasAncestor(widget.widget)) {
            continue;
        }
        if (mSelection.contains(w)) {
            continue;
        }
        widgetsToCheck.add(w);
    }
    // lock direction before applying the snap
    if (widget.directionLocked == Selection.DIRECTION_LOCKED_X) {
        candidatePoint.y = widget.origin.y;
    } else if (widget.directionLocked == Selection.DIRECTION_LOCKED_Y) {
        candidatePoint.x = widget.origin.x;
    }
    if (snap) {
        SnapPlacement.snapWidget(widgetsToCheck, widget.widget, candidatePoint, false, mSnapCandidates, transform);
    }
    WidgetCompanion widgetCompanion = (WidgetCompanion) widget.widget.getCompanionWidget();
    WidgetInteractionTargets widgetInteraction = widgetCompanion.getWidgetInteractionTargets();
    // check if we have centered connections, if so allow moving and snapping
    // on specific percentage positions
    snapBias(widget.widget, candidatePoint);
    widget.widget.setDrawOrigin(candidatePoint.x, candidatePoint.y);
    widget.widget.forceUpdateDrawPosition();
    widgetInteraction.updatePosition(transform);
    mSimilarMargins.clear();
    for (SnapCandidate candidate : mSnapCandidates) {
        if (candidate.margin != 0) {
            mSimilarMargins.add(candidate);
        }
    }
    for (SnapCandidate candidate : mSnapCandidates) {
        SnapPlacement.gatherMargins(mWidgetsScene.getWidgets(), mSimilarMargins, candidate.margin, candidate.source.isVerticalAnchor());
    }
    return directionLockedStatus;
}
Also used : ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) WidgetCompanion(com.android.tools.sherpa.structure.WidgetCompanion) ArrayList(java.util.ArrayList)

Example 8 with ConstraintWidget

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

the class ConstraintHandle method updatePosition.

/**
     * Update the position of the anchor depending on the owner's position
     *
     */
void updatePosition() {
    if (mOwner == null) {
        mX = 0;
        mY = 0;
        return;
    }
    ConstraintWidget widget = mOwner.getConstraintWidget();
    int x = widget.getDrawX();
    int y = widget.getDrawY();
    int w = widget.getDrawWidth();
    int h = widget.getDrawHeight();
    if (mAnchor == null) {
        return;
    }
    switch(mAnchor.getType()) {
        case LEFT:
            {
                mX = x;
                mY = y + h / 2;
            }
            break;
        case TOP:
            {
                mX = x + w / 2;
                mY = y;
            }
            break;
        case RIGHT:
            {
                mX = x + w;
                mY = y + h / 2;
            }
            break;
        case BOTTOM:
            {
                mX = x + w / 2;
                mY = y + h;
            }
            break;
        case CENTER:
        case CENTER_X:
        case CENTER_Y:
            {
                mX = x + w / 2;
                mY = y + h / 2;
            }
            break;
        case BASELINE:
            {
                mX = x + w / 2;
                mY = y + widget.getBaselineDistance();
            }
            break;
    }
}
Also used : ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget)

Example 9 with ConstraintWidget

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

the class ConstraintHandle method draw.

/**
     * Draw function for the ConstraintHandle
     *
     * @param transform  the view transform
     * @param g          the graphics context
     * @param colorSet   the current colorset
     * @param isSelected if the constraint is selected or not
     */
public void draw(ViewTransform transform, Graphics2D g, ColorSet colorSet, boolean isSelected) {
    ConstraintWidget widget = getOwner();
    WidgetCompanion companion = (WidgetCompanion) widget.getCompanionWidget();
    WidgetDecorator decorator = companion.getWidgetDecorator(colorSet.getStyle());
    Color backgroundColor = decorator.getBackgroundColor();
    if (mType == ConstraintAnchor.Type.BASELINE) {
        int x = transform.getSwingX(getOwner().getDrawX());
        int y = transform.getSwingY(getOwner().getDrawY());
        int w = transform.getSwingDimension(getOwner().getDrawWidth());
        int baseline = transform.getSwingDimension(getOwner().getBaselineDistance());
        int padding = (w - getBaselineHandleWidth(transform)) / 2;
        int bh = 7;
        int by = y + baseline;
        if (isSelected) {
            Color pre = g.getColor();
            Stroke preStroke = g.getStroke();
            g.setColor(colorSet.getShadow());
            g.setStroke(colorSet.getShadowStroke());
            g.drawRoundRect(x + padding, by - bh / 2, w - 2 * padding, bh, bh, bh);
            g.setStroke(preStroke);
            g.setColor(pre);
        }
        Color previous = g.getColor();
        g.setColor(new Color(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), previous.getAlpha()));
        g.fillRoundRect(x + padding, by - bh / 2, w - 2 * padding, bh, bh, bh);
        g.setColor(previous);
        g.drawRoundRect(x + padding, by - bh / 2, w - 2 * padding, bh, bh, bh);
        g.drawLine(x, by, x + padding, by);
        g.drawLine(x + w - padding, by, x + w, by);
        if (mAnchor.isConnected()) {
            int margin = 2;
            g.fillRoundRect(x + padding + margin, by - bh / 2 + margin, w - 2 * padding - 2 * margin, bh - 2 * margin, bh, bh);
            g.drawRoundRect(x + padding + margin, by - bh / 2 + margin, w - 2 * padding - 2 * margin, bh - 2 * margin, bh, bh);
        }
    } else {
        int innerMargin = 3;
        int radius = ConnectionDraw.CONNECTION_ANCHOR_SIZE;
        int dimension = radius * 2;
        int cx = transform.getSwingFX(mX) - dimension / 2;
        int cy = transform.getSwingFY(mY) - dimension / 2;
        Ellipse2D.Float outerCircle = new Ellipse2D.Float(cx, cy, dimension, dimension);
        if (isSelected) {
            Color pre = g.getColor();
            Stroke preStroke = g.getStroke();
            g.setColor(sShadowColor);
            g.setStroke(sShadowStroke);
            g.draw(outerCircle);
            g.setStroke(preStroke);
            g.setColor(pre);
        }
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setColor(backgroundColor);
        g2.fill(outerCircle);
        g2.dispose();
        g.draw(outerCircle);
        if (mAnchor.isConnected()) {
            int d = dimension - innerMargin * 2;
            g.fillRoundRect(cx + innerMargin, cy + innerMargin, d, d, d, d);
            g.drawRoundRect(cx + innerMargin, cy + innerMargin, d, d, d, d);
        }
    }
}
Also used : ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) WidgetCompanion(com.android.tools.sherpa.structure.WidgetCompanion) WidgetDecorator(com.android.tools.sherpa.drawing.decorator.WidgetDecorator) Ellipse2D(java.awt.geom.Ellipse2D)

Example 10 with ConstraintWidget

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

the class TableDecorator method mousePressed.

/**
     * Handle mouse press event to add click targets. TODO: clean this up.
     *
     * @param x         mouse x coordinate
     * @param y         mouse y coordinate
     * @param transform view transform
     * @param selection the current selection of widgets
     */
@Override
public ConstraintWidget mousePressed(float x, float y, ViewTransform transform, Selection selection) {
    ConstraintTableLayout table = (ConstraintTableLayout) mWidget;
    mTableClickTargets.clear();
    ArrayList<Guideline> vertical = table.getVerticalGuidelines();
    int l = transform.getSwingX(table.getDrawX());
    int t = transform.getSwingY(table.getDrawY());
    int column = 0;
    TableClickTarget firstTarget = new TableClickTarget(table, column++, l, t - 20 - 4, 20, 20);
    mTableClickTargets.add(firstTarget);
    for (ConstraintWidget v : vertical) {
        int bx = transform.getSwingX(v.getX()) + l;
        TableClickTarget target = new TableClickTarget(table, column++, bx, t - 20 - 4, 20, 20);
        mTableClickTargets.add(target);
    }
    ConstraintWidget widgetHit = null;
    if (mTableClickTargets.size() > 0) {
        for (TableClickTarget tableClickTarget : mTableClickTargets) {
            if (tableClickTarget.contains(x, y)) {
                widgetHit = tableClickTarget.getTable();
                break;
            }
        }
        if (selection.isEmpty()) {
            mTableClickTargets.clear();
        }
    }
    return widgetHit;
}
Also used : ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) ConstraintTableLayout(android.support.constraint.solver.widgets.ConstraintTableLayout) Guideline(android.support.constraint.solver.widgets.Guideline)

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