Search in sources :

Example 1 with Guideline

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

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

Example 3 with Guideline

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

the class SnapPlacement method findSnapMargin.

/**
     * Utility function iterating through the widgets, comparing the specified anchors,
     * and finding snapping candidate on the indicated margin.
     * <p/>
     * TODO: iterate only on the closest widget (right now we iterate on all of them
     * and *then* check the distance)
     *
     * @param widgets      the list of known widgets
     * @param widget       the widget we operate on
     * @param candidate    the SnapCandidate instance we need to fill
     * @param isVertical   flag set indicating if we are looking at horizontal or vertical anchors
     * @param sourceAnchor the anchor type we are looking at on the widget
     * @param targetAnchor the anchor type we will compare to
     * @param margin       the margin value we are trying to snap on
     * @param slope        the allowed slope
     */
private static void findSnapMargin(Collection<ConstraintWidget> widgets, ConstraintWidget widget, SnapCandidate candidate, boolean isVertical, ConstraintAnchor.Type sourceAnchor, ConstraintAnchor.Type targetAnchor, int margin, int slope) {
    if (widget instanceof Guideline) {
        return;
    }
    ConstraintAnchor source = widget.getAnchor(sourceAnchor);
    for (ConstraintWidget w : widgets) {
        if (w == widget) {
            continue;
        }
        ConstraintAnchor target = w.getAnchor(targetAnchor);
        if (target == null) {
            // for e.g. guidelines
            continue;
        }
        ConstraintHandle sourceHandle = WidgetInteractionTargets.constraintHandle(source);
        ConstraintHandle targetHandle = WidgetInteractionTargets.constraintHandle(target);
        if (sourceHandle == null || targetHandle == null) {
            continue;
        }
        int anchorDistance = sourceHandle.getDrawX() - targetHandle.getDrawX() - margin;
        if (isVertical) {
            anchorDistance = sourceHandle.getDrawY() - targetHandle.getDrawY() - margin;
        }
        if (anchorDistance < 0) {
            continue;
        }
        int minDistance = sourceHandle.getDistanceFrom(target.getOwner());
        double distance = Math.sqrt(anchorDistance * anchorDistance + minDistance * minDistance);
        if (target.getOwner() instanceof Guideline) {
            distance = Math.sqrt(anchorDistance * anchorDistance);
        }
        if (anchorDistance < slope && distance <= candidate.distance && (ALLOWS_ALL_SNAP_MARGIN || distance < MAX_SNAP_MARGIN_DISTANCE)) {
            if (candidate.target == null || (candidate.margin > margin || (candidate.target.getType() == ConstraintAnchor.Type.CENTER_X || candidate.target.getType() == ConstraintAnchor.Type.CENTER || candidate.target.getType() == ConstraintAnchor.Type.CENTER_Y))) {
                candidate.distance = distance;
                candidate.target = target;
                candidate.source = source;
                candidate.margin = margin;
            }
        }
    }
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) Guideline(android.support.constraint.solver.widgets.Guideline) Point(java.awt.Point)

Example 4 with Guideline

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

Example 5 with Guideline

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

the class WidgetInteractionTargets method findResizeHandle.

/**
     * Iterate through the resize handles of this widget and return the handle intersecting
     * with the point (x, y), if any. Corner resize handles takes precedence over side handles.
     * We also don't return hits if the handles is inoperable (due to constraints on the widget)
     *
     * @param x the x coordinate of the point
     * @param y the y coordinate of the point
     * @return true if we find a resize handle below the given point
     */
public ResizeHandle findResizeHandle(float x, float y) {
    ResizeHandle candidate = null;
    if (mWidget instanceof Guideline) {
        Guideline guideline = (Guideline) mWidget;
        if (guideline.getOrientation() == Guideline.VERTICAL) {
            if (mLeftSide.hit(x, y)) {
                return mLeftSide;
            }
        } else {
            if (mTopSide.hit(x, y)) {
                return mTopSide;
            }
        }
    }
    ConstraintAnchor leftAnchor = mWidget.getAnchor(ConstraintAnchor.Type.LEFT);
    ConstraintAnchor topAnchor = mWidget.getAnchor(ConstraintAnchor.Type.TOP);
    ConstraintAnchor rightAnchor = mWidget.getAnchor(ConstraintAnchor.Type.RIGHT);
    ConstraintAnchor bottomAnchor = mWidget.getAnchor(ConstraintAnchor.Type.BOTTOM);
    ConstraintAnchor baselineAnchor = mWidget.getAnchor(ConstraintAnchor.Type.BASELINE);
    for (ResizeHandle handle : mResizeHandles) {
        if (handle.hit(x, y)) {
            boolean leftAnchorIsConnected = leftAnchor != null && leftAnchor.isConnected();
            boolean topAnchorIsConnected = topAnchor != null && topAnchor.isConnected();
            boolean rightAnchorIsConnected = rightAnchor != null && rightAnchor.isConnected();
            boolean bottomAnchorIsConnected = bottomAnchor != null && bottomAnchor.isConnected();
            boolean baselineAnchorIsConnected = baselineAnchor != null && baselineAnchor.isConnected();
            switch(handle.getType()) {
                case LEFT_TOP:
                    {
                        if (leftAnchorIsConnected || topAnchorIsConnected) {
                            continue;
                        }
                    }
                    break;
                case RIGHT_TOP:
                    {
                        if (rightAnchorIsConnected || topAnchorIsConnected) {
                            continue;
                        }
                    }
                    break;
                case LEFT_BOTTOM:
                    {
                        if (leftAnchorIsConnected || bottomAnchorIsConnected) {
                            continue;
                        }
                    }
                    break;
                case RIGHT_BOTTOM:
                    {
                        if (rightAnchorIsConnected || bottomAnchorIsConnected) {
                            continue;
                        }
                    }
                    break;
                case LEFT_SIDE:
                    {
                        if (leftAnchorIsConnected) {
                            continue;
                        }
                    }
                    break;
                case RIGHT_SIDE:
                    {
                        if (rightAnchorIsConnected) {
                            continue;
                        }
                    }
                    break;
                case TOP_SIDE:
                    {
                        if (topAnchorIsConnected || baselineAnchorIsConnected) {
                            continue;
                        }
                    }
                    break;
                case BOTTOM_SIDE:
                    {
                        if (bottomAnchorIsConnected) {
                            continue;
                        }
                    }
                    break;
            }
            if (candidate == null || candidate.isSideHandle()) {
                candidate = handle;
            }
        }
    }
    return candidate;
}
Also used : ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) Guideline(android.support.constraint.solver.widgets.Guideline)

Aggregations

Guideline (android.support.constraint.solver.widgets.Guideline)13 ConstraintAnchor (android.support.constraint.solver.widgets.ConstraintAnchor)8 ConstraintWidget (android.support.constraint.solver.widgets.ConstraintWidget)7 Point (java.awt.Point)3 ConstraintTableLayout (android.support.constraint.solver.widgets.ConstraintTableLayout)2 ConstraintWidgetContainer (android.support.constraint.solver.widgets.ConstraintWidgetContainer)2 ConstraintHandle (com.android.tools.sherpa.interaction.ConstraintHandle)2 Graphics2D (java.awt.Graphics2D)2 WidgetCompanion (com.android.tools.sherpa.structure.WidgetCompanion)1 Rectangle (java.awt.Rectangle)1