Search in sources :

Example 11 with WidgetCompanion

use of com.android.tools.sherpa.structure.WidgetCompanion in project android by JetBrains.

the class WidgetInteractionTargets method constraintHandle.

/**
     * Utility function giving the ConstraintHandle associated to the given ConstraintAnchor
     * @param anchor the ConstraintAnchor
     * @return the associated ConstraintHandle, or null if not found
     */
public static ConstraintHandle constraintHandle(ConstraintAnchor anchor) {
    if (anchor == null) {
        return null;
    }
    ConstraintWidget widget = anchor.getOwner();
    if (widget == null) {
        return null;
    }
    if (widget.getCompanionWidget() == null) {
        return null;
    }
    WidgetCompanion widgetCompanion = (WidgetCompanion) widget.getCompanionWidget();
    WidgetInteractionTargets widgetInteraction = widgetCompanion.getWidgetInteractionTargets();
    return widgetInteraction.getConstraintHandle(anchor);
}
Also used : ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) WidgetCompanion(com.android.tools.sherpa.structure.WidgetCompanion)

Example 12 with WidgetCompanion

use of com.android.tools.sherpa.structure.WidgetCompanion 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 13 with WidgetCompanion

use of com.android.tools.sherpa.structure.WidgetCompanion in project android by JetBrains.

the class WidgetMotion method snapBias.

/**
     * Snap the widget's horizontal or vertical bias if we have horizontal/vertical
     * centered connections
     *
     * @param widget         the current widget
     * @param candidatePoint the candidate point containing the current location
     */
private void snapBias(ConstraintWidget widget, Point candidatePoint) {
    WidgetCompanion widgetCompanion = (WidgetCompanion) widget.getCompanionWidget();
    int currentStyle = WidgetDecorator.BLUEPRINT_STYLE;
    if (mSceneDraw != null) {
        currentStyle = mSceneDraw.getCurrentStyle();
    }
    WidgetDecorator decorator = widgetCompanion.getWidgetDecorator(currentStyle);
    ConstraintAnchor leftAnchor = widget.getAnchor(ConstraintAnchor.Type.LEFT);
    ConstraintAnchor rightAnchor = widget.getAnchor(ConstraintAnchor.Type.RIGHT);
    if (leftAnchor != null && rightAnchor != null && leftAnchor.isConnected() && rightAnchor.isConnected() && leftAnchor.getTarget() != rightAnchor.getTarget()) {
        int begin = WidgetInteractionTargets.constraintHandle(leftAnchor.getTarget()).getDrawX();
        int end = WidgetInteractionTargets.constraintHandle(rightAnchor.getTarget()).getDrawX();
        int width = widget.getDrawWidth();
        int delta = candidatePoint.x - begin;
        float percent = delta / (float) (end - begin - width);
        percent = Math.max(0, Math.min(1, percent));
        percent = snapPercent(percent);
        widget.setHorizontalBiasPercent(percent);
        decorator.updateBias();
    }
    ConstraintAnchor topAnchor = widget.getAnchor(ConstraintAnchor.Type.TOP);
    ConstraintAnchor bottomAnchor = widget.getAnchor(ConstraintAnchor.Type.BOTTOM);
    if (topAnchor != null && bottomAnchor != null && topAnchor.isConnected() && bottomAnchor.isConnected() && topAnchor.getTarget() != bottomAnchor.getTarget()) {
        int begin = WidgetInteractionTargets.constraintHandle(topAnchor.getTarget()).getDrawY();
        int end = WidgetInteractionTargets.constraintHandle(bottomAnchor.getTarget()).getDrawY();
        int height = widget.getDrawHeight();
        int delta = candidatePoint.y - begin;
        float percent = delta / (float) (end - begin - height);
        percent = Math.max(0, Math.min(1, percent));
        percent = snapPercent(percent);
        widget.setVerticalBiasPercent(percent);
        decorator.updateBias();
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) WidgetCompanion(com.android.tools.sherpa.structure.WidgetCompanion) WidgetDecorator(com.android.tools.sherpa.drawing.decorator.WidgetDecorator)

Example 14 with WidgetCompanion

use of com.android.tools.sherpa.structure.WidgetCompanion 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 15 with WidgetCompanion

use of com.android.tools.sherpa.structure.WidgetCompanion in project android by JetBrains.

the class SnapPlacement method snapWidget.

/**
     * Constraint a candidate position for a given widget.
     * If the widget has existing connections, we'll allow moving on the corresponding axis
     * by modifying the margin of the connection; we'll also snap to WidgetsView.GRID_SPACING
     * the margin's value.
     * If the widget did not have connections on that axis, we'll try to snap the new position to
     * closeby widget. Otherwise, we'll snap the position on the base grid,
     * using WidgetsView.GRID_SPACING. The function will also fill in the snapCandidates
     * array with any SnapCandidate used.
     *
     * @param widgets        the list of known widgets
     * @param widget         the widget we operate on
     * @param candidatePoint the candidate new position
     * @param useGridSnap    flag to use or not snapping on the base grid
     * @param snapCandidates an array that will contain the snap candidates if any.
     * @param transform      the view transform
     */
public static void snapWidget(Collection<ConstraintWidget> widgets, ConstraintWidget widget, Point candidatePoint, boolean useGridSnap, ArrayList<SnapCandidate> snapCandidates, ViewTransform transform) {
    if (widget instanceof Guideline) {
        return;
    }
    ConstraintAnchor left = widget.getAnchor(ConstraintAnchor.Type.LEFT);
    ConstraintAnchor right = widget.getAnchor(ConstraintAnchor.Type.RIGHT);
    if (left.isConnected() && right.isConnected()) {
    // do nothing, as movement is constrained
    } else {
        widget.setDrawX(candidatePoint.x);
        WidgetCompanion widgetCompanion = (WidgetCompanion) widget.getCompanionWidget();
        WidgetInteractionTargets widgetInteraction = widgetCompanion.getWidgetInteractionTargets();
        widgetInteraction.updatePosition(transform);
        if (!checkHorizontalMarginsSnap(snapCandidates, widget, candidatePoint, DEFAULT_MARGIN)) {
            if (!snapExistingHorizontalMargin(widget, candidatePoint)) {
                SnapCandidate candidate = new SnapCandidate();
                findSnap(widgets, widget, candidate, true);
                if (candidate.target == null || candidate.target.getType() == ConstraintAnchor.Type.CENTER_X || candidate.target.getType() == ConstraintAnchor.Type.CENTER) {
                    // no anchor found, let's try to find margins
                    for (int i = SNAP_MARGIN_INCREMENT; i <= SNAP_MARGIN_MAX; i += SNAP_MARGIN_INCREMENT) {
                        findSnapMargin(widgets, widget, candidate, false, ConstraintAnchor.Type.LEFT, ConstraintAnchor.Type.RIGHT, i, CONNECTION_SLOPE);
                        findSnapMargin(widgets, widget, candidate, false, ConstraintAnchor.Type.RIGHT, ConstraintAnchor.Type.LEFT, -i, CONNECTION_SLOPE);
                    }
                }
                if (!snapToHorizontalAnchor(candidatePoint, widget, candidate)) {
                    if (useGridSnap) {
                        snapHorizontalGrid(candidatePoint);
                    }
                } else {
                    snapCandidates.add(candidate);
                }
            }
        }
    }
    ConstraintAnchor top = widget.getAnchor(ConstraintAnchor.Type.TOP);
    ConstraintAnchor bottom = widget.getAnchor(ConstraintAnchor.Type.BOTTOM);
    ConstraintAnchor baseline = widget.getAnchor(ConstraintAnchor.Type.BASELINE);
    if (baseline.isConnected() || (top.isConnected() && bottom.isConnected())) {
    // do nothing, as movement is constrained
    } else {
        widget.setDrawY(candidatePoint.y);
        WidgetCompanion widgetCompanion = (WidgetCompanion) widget.getCompanionWidget();
        WidgetInteractionTargets widgetInteraction = widgetCompanion.getWidgetInteractionTargets();
        widgetInteraction.updatePosition(transform);
        if (!checkVerticalMarginsSnap(snapCandidates, widget, candidatePoint, DEFAULT_MARGIN)) {
            if (!snapExistingVerticalMargin(widget, candidatePoint)) {
                SnapCandidate candidate = new SnapCandidate();
                findSnap(widgets, widget, candidate, false);
                if (candidate.target == null || candidate.target.getType() == ConstraintAnchor.Type.CENTER_Y || candidate.target.getType() == ConstraintAnchor.Type.CENTER) {
                    // no anchor found, let's try to find margins
                    for (int i = SNAP_MARGIN_INCREMENT; i <= SNAP_MARGIN_MAX; i += SNAP_MARGIN_INCREMENT) {
                        findSnapMargin(widgets, widget, candidate, true, ConstraintAnchor.Type.TOP, ConstraintAnchor.Type.BOTTOM, i, CONNECTION_SLOPE);
                        findSnapMargin(widgets, widget, candidate, true, ConstraintAnchor.Type.BOTTOM, ConstraintAnchor.Type.TOP, -i, CONNECTION_SLOPE);
                    }
                }
                if (!snapToVerticalAnchor(candidatePoint, widget, candidate)) {
                    if (useGridSnap) {
                        snapVerticalGrid(candidatePoint);
                    }
                } else {
                    snapCandidates.add(candidate);
                }
            }
        }
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) WidgetCompanion(com.android.tools.sherpa.structure.WidgetCompanion) Guideline(android.support.constraint.solver.widgets.Guideline) Point(java.awt.Point)

Aggregations

WidgetCompanion (com.android.tools.sherpa.structure.WidgetCompanion)27 WidgetDecorator (com.android.tools.sherpa.drawing.decorator.WidgetDecorator)8 ConstraintWidget (android.support.constraint.solver.widgets.ConstraintWidget)5 WidgetInteractionTargets (com.android.tools.sherpa.interaction.WidgetInteractionTargets)5 ConstraintAnchor (android.support.constraint.solver.widgets.ConstraintAnchor)3 ConstraintHandle (com.android.tools.sherpa.interaction.ConstraintHandle)3 ArrayList (java.util.ArrayList)3 Selection (com.android.tools.sherpa.structure.Selection)2 Nullable (org.jetbrains.annotations.Nullable)2 Guideline (android.support.constraint.solver.widgets.Guideline)1 ResourceResolver (com.android.ide.common.resources.ResourceResolver)1 Configuration (com.android.tools.idea.configurations.Configuration)1 SceneComponent (com.android.tools.idea.uibuilder.scene.SceneComponent)1 AnimatedLine (com.android.tools.sherpa.animation.AnimatedLine)1 TextWidget (com.android.tools.sherpa.drawing.decorator.TextWidget)1 ResizeHandle (com.android.tools.sherpa.interaction.ResizeHandle)1 SnapCandidate (com.android.tools.sherpa.interaction.SnapCandidate)1 WidgetsScene (com.android.tools.sherpa.structure.WidgetsScene)1 Point (java.awt.Point)1 Ellipse2D (java.awt.geom.Ellipse2D)1