Search in sources :

Example 1 with WidgetContainer

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

the class ScoutArrange method align.

/**
     * Perform various types of arrangements on a selection of widgets
     *
     * @param type             the type of change
     * @param widgetList       the list of selected widgets
     * @param applyConstraints if true apply related constraints (except expand and pack)
     */
public static void align(Scout.Arrange type, ArrayList<ConstraintWidget> widgetList, boolean applyConstraints) {
    if (widgetList == null || widgetList.size() == 0) {
        return;
    }
    int margin = Scout.getMargin();
    ConstraintWidget[] widgets = new ConstraintWidget[widgetList.size()];
    widgets = widgetList.toArray(widgets);
    switch(type) {
        case AlignHorizontallyCenter:
        case AlignHorizontallyLeft:
        case AlignHorizontallyRight:
            Arrays.sort(widgets, sSortY);
            if (rootDistance(widgets[0]) > rootDistance(widgets[widgets.length - 1])) {
                reverse(widgets);
            }
            break;
        case DistributeVertically:
            Arrays.sort(widgets, sSortY);
            break;
        case AlignVerticallyTop:
        case AlignVerticallyMiddle:
        case AlignBaseline:
        case AlignVerticallyBottom:
            Arrays.sort(widgets, sSortX);
            if (rootDistance(widgets[0]) > rootDistance(widgets[widgets.length - 1])) {
                reverse(widgets);
            }
            break;
        case DistributeHorizontally:
            Arrays.sort(widgets, sSortX);
            break;
    }
    switch(type) {
        case CenterHorizontally:
            {
                Rectangle rectangle = new Rectangle();
                WidgetContainer parent = (WidgetContainer) widgets[0].getParent();
                ConstraintWidget[] pears = new ConstraintWidget[parent.getChildren().size()];
                pears = parent.getChildren().toArray(pears);
                for (ConstraintWidget widget : widgets) {
                    rectangle.x = widget.getX();
                    rectangle.y = widget.getY();
                    rectangle.width = widget.getWidth();
                    rectangle.height = widget.getHeight();
                    int westDistance = gap(Direction.WEST, rectangle, pears);
                    int eastDistance = gap(Direction.EAST, rectangle, pears);
                    int x = widget.getX();
                    if (applyConstraints) {
                        ConstraintWidget westConnect = gapWidget(Direction.WEST, rectangle, pears);
                        ConstraintWidget eastConnect = gapWidget(Direction.EAST, rectangle, pears);
                        ConstraintAnchor.Type dir = ConstraintAnchor.Type.RIGHT;
                        if (westConnect == parent) {
                            dir = ConstraintAnchor.Type.LEFT;
                        }
                        widget.connect(ConstraintAnchor.Type.LEFT, westConnect, dir, 0);
                        dir = ConstraintAnchor.Type.LEFT;
                        if (eastConnect == parent) {
                            dir = ConstraintAnchor.Type.RIGHT;
                        }
                        widget.connect(ConstraintAnchor.Type.RIGHT, eastConnect, dir, 0);
                        widget.setHorizontalBiasPercent(.5f);
                    } else {
                        widget.setX(x + (eastDistance - westDistance) / 2);
                    }
                }
            }
            break;
        case CenterVertically:
            {
                Rectangle rectangle = new Rectangle();
                WidgetContainer parent = (WidgetContainer) widgets[0].getParent();
                ConstraintWidget[] pears = new ConstraintWidget[parent.getChildren().size()];
                pears = parent.getChildren().toArray(pears);
                for (ConstraintWidget widget : widgets) {
                    rectangle.x = widget.getX();
                    rectangle.y = widget.getY();
                    rectangle.width = widget.getWidth();
                    rectangle.height = widget.getHeight();
                    int northDistance = gap(Direction.NORTH, rectangle, pears);
                    int southDistance = gap(Direction.SOUTH, rectangle, pears);
                    int Y = widget.getY();
                    if (applyConstraints) {
                        ConstraintWidget northConnect = gapWidget(Direction.NORTH, rectangle, pears);
                        ConstraintWidget southConnect = gapWidget(Direction.SOUTH, rectangle, pears);
                        ConstraintAnchor.Type dir = ConstraintAnchor.Type.BOTTOM;
                        if (northConnect == parent) {
                            dir = ConstraintAnchor.Type.TOP;
                        }
                        widget.connect(ConstraintAnchor.Type.TOP, northConnect, dir, 0);
                        dir = ConstraintAnchor.Type.TOP;
                        if (southConnect == parent) {
                            dir = ConstraintAnchor.Type.BOTTOM;
                        }
                        widget.connect(ConstraintAnchor.Type.BOTTOM, southConnect, dir, 0);
                        widget.setVerticalBiasPercent(.5f);
                    } else {
                        widget.setY(Y + (southDistance - northDistance) / 2);
                    }
                }
            }
            break;
        case CenterHorizontallyInParent:
            {
                for (ConstraintWidget widget : widgets) {
                    int parentWidth = widget.getParent().getWidth();
                    int width = widget.getWidth();
                    widget.setX((parentWidth - width) / 2);
                    if (applyConstraints) {
                        widget.connect(ConstraintAnchor.Type.CENTER_X, widget.getParent(), ConstraintAnchor.Type.CENTER_X, 0);
                        widget.setHorizontalBiasPercent(.5f);
                    }
                }
            }
            break;
        case CenterVerticallyInParent:
            {
                for (ConstraintWidget widget : widgets) {
                    int parentHeight = widget.getParent().getHeight();
                    int height = widget.getHeight();
                    widget.setY((parentHeight - height) / 2);
                    if (applyConstraints) {
                        widget.connect(ConstraintAnchor.Type.CENTER_Y, widget.getParent(), ConstraintAnchor.Type.CENTER_Y, 0);
                        widget.setVerticalBiasPercent(.5f);
                    }
                }
            }
            break;
        case AlignHorizontallyCenter:
            {
                int count = 0;
                float avg = 0;
                for (ConstraintWidget widget : widgets) {
                    avg += widget.getX() + widget.getWidth() / 2.0f;
                    count++;
                }
                avg /= count;
                ConstraintWidget previousWidget = null;
                for (ConstraintWidget widget : widgets) {
                    float current = widget.getWidth() / 2.0f;
                    widget.setX((int) (avg - current));
                    if (applyConstraints) {
                        if (previousWidget != null) {
                            widget.connect(ConstraintAnchor.Type.CENTER_X, previousWidget, ConstraintAnchor.Type.CENTER_X, 0);
                        }
                    }
                    previousWidget = widget;
                }
            }
            break;
        case AlignHorizontallyLeft:
            {
                int min = Integer.MAX_VALUE;
                for (ConstraintWidget widget : widgets) {
                    min = Math.min(min, widget.getX());
                }
                ConstraintWidget previousWidget = null;
                for (ConstraintWidget widget : widgets) {
                    widget.setX(min);
                    if (applyConstraints) {
                        if (previousWidget != null) {
                            widget.resetAnchor(widget.getAnchor(ConstraintAnchor.Type.RIGHT));
                            widget.connect(ConstraintAnchor.Type.LEFT, previousWidget, ConstraintAnchor.Type.LEFT, 0);
                        }
                    }
                    previousWidget = widget;
                }
            }
            break;
        case AlignHorizontallyRight:
            {
                int max = Integer.MIN_VALUE;
                for (ConstraintWidget widget : widgets) {
                    max = Math.max(max, widget.getX() + widget.getWidth());
                }
                ConstraintWidget previousWidget = null;
                for (ConstraintWidget widget : widgets) {
                    float current = widget.getWidth();
                    widget.setX((int) (max - current));
                    if (applyConstraints) {
                        if (previousWidget != null) {
                            widget.resetAnchor(widget.getAnchor(ConstraintAnchor.Type.LEFT));
                            widget.connect(ConstraintAnchor.Type.RIGHT, previousWidget, ConstraintAnchor.Type.RIGHT, 0);
                        }
                    }
                    previousWidget = widget;
                }
            }
            break;
        case AlignVerticallyTop:
            {
                int min = Integer.MAX_VALUE;
                for (ConstraintWidget widget : widgets) {
                    min = Math.min(min, widget.getY());
                }
                ConstraintWidget previousWidget = null;
                for (ConstraintWidget widget : widgets) {
                    widget.setY(min);
                    if (applyConstraints) {
                        if (previousWidget != null) {
                            widget.resetAnchor(widget.getAnchor(ConstraintAnchor.Type.BOTTOM));
                            widget.connect(ConstraintAnchor.Type.TOP, previousWidget, ConstraintAnchor.Type.TOP, 0);
                        }
                    }
                    previousWidget = widget;
                }
            }
            break;
        case AlignVerticallyMiddle:
            {
                int count = 0;
                float avg = 0;
                for (ConstraintWidget widget : widgets) {
                    avg += widget.getY() + widget.getHeight() / 2.0f;
                    count++;
                }
                avg /= count;
                ConstraintWidget previousWidget = null;
                for (ConstraintWidget widget : widgets) {
                    float current = widget.getHeight() / 2.0f;
                    widget.setY((int) (avg - current));
                    if (applyConstraints) {
                        if (previousWidget != null) {
                            widget.connect(ConstraintAnchor.Type.CENTER_Y, previousWidget, ConstraintAnchor.Type.CENTER_Y, 0);
                        }
                    }
                    previousWidget = widget;
                }
            }
            break;
        case AlignBaseline:
            {
                int count = 0;
                float avg = 0;
                int number_of_constrained = 0;
                ConstraintWidget fixedWidget = null;
                for (ConstraintWidget widget : widgets) {
                    if (isVerticallyConstrained(widget)) {
                        number_of_constrained++;
                        fixedWidget = widget;
                    }
                    avg += widget.getY() + widget.getBaselineDistance();
                    count++;
                }
                avg /= count;
                // if one is already constrained move the rest to it
                if (number_of_constrained == 1) {
                    avg = fixedWidget.getY() + fixedWidget.getBaselineDistance();
                }
                ConstraintWidget previousWidget = null;
                if (!applyConstraints || number_of_constrained == 0) {
                    for (ConstraintWidget widget : widgets) {
                        float baseline = widget.getBaselineDistance();
                        widget.setY((int) (avg - baseline));
                        if (applyConstraints) {
                            if (previousWidget != null) {
                                widget.connect(ConstraintAnchor.Type.BASELINE, previousWidget, ConstraintAnchor.Type.BASELINE, 0);
                            }
                        }
                        previousWidget = widget;
                    }
                } else {
                    // if you are creating constraints and some are already constrained
                    // Build a list of constrained and unconstrained widgets
                    ArrayList<ConstraintWidget> unconstrained = new ArrayList<>();
                    ArrayList<ConstraintWidget> constrained = new ArrayList<>();
                    for (ConstraintWidget widget : widgets) {
                        if (isVerticallyConstrained(widget)) {
                            constrained.add(widget);
                        } else {
                            unconstrained.add(widget);
                        }
                    }
                    // one by one constrain widgets by finding the closest between the two list
                    while (!unconstrained.isEmpty()) {
                        ConstraintWidget to = null;
                        ConstraintWidget from = null;
                        int min = Integer.MAX_VALUE;
                        for (ConstraintWidget fromCandidate : unconstrained) {
                            for (ConstraintWidget toCandidate : constrained) {
                                int fromLeft = fromCandidate.getX();
                                int fromRight = fromLeft + fromCandidate.getWidth();
                                int toLeft = toCandidate.getX();
                                int toRight = toLeft + toCandidate.getWidth();
                                int dist = Math.abs(toLeft - fromLeft);
                                dist = Math.min(dist, Math.abs(toLeft - fromRight));
                                dist = Math.min(dist, Math.abs(toRight - fromRight));
                                dist = Math.min(dist, Math.abs(toRight - fromLeft));
                                if (dist < min) {
                                    min = dist;
                                    to = toCandidate;
                                    from = fromCandidate;
                                }
                            }
                        }
                        from.connect(ConstraintAnchor.Type.BASELINE, to, ConstraintAnchor.Type.BASELINE, 0);
                        constrained.add(from);
                        unconstrained.remove(from);
                    }
                }
            }
            break;
        case AlignVerticallyBottom:
            {
                int max = Integer.MIN_VALUE;
                for (ConstraintWidget widget : widgets) {
                    max = Math.max(max, widget.getY() + widget.getHeight());
                }
                ConstraintWidget previousWidget = null;
                for (ConstraintWidget widget : widgets) {
                    float current = widget.getHeight();
                    widget.setY((int) (max - current));
                    if (applyConstraints) {
                        if (previousWidget != null) {
                            widget.resetAnchor(widget.getAnchor(ConstraintAnchor.Type.TOP));
                            widget.connect(ConstraintAnchor.Type.BOTTOM, previousWidget, ConstraintAnchor.Type.BOTTOM, 0);
                        }
                    }
                    previousWidget = widget;
                }
            }
            break;
        case DistributeVertically:
            {
                int count = 0;
                int sum = 0;
                int min = widgetList.get(0).getY();
                int max = widgetList.get(0).getY() + widgetList.get(0).getHeight();
                for (ConstraintWidget widget : widgets) {
                    int start = widget.getY();
                    int size = widget.getHeight();
                    int end = start + size;
                    sum += size;
                    min = Math.min(min, start);
                    max = Math.max(max, end);
                    count++;
                }
                int gaps = count - 1;
                int totalGap = max - min - sum;
                int lastY = min;
                boolean reverse = rootDistanceY(widgets[0]) > rootDistanceY(widgets[widgets.length - 1]);
                for (int i = 0; i < count; i++) {
                    if (i > 0) {
                        int size = widgets[i - 1].getHeight();
                        min += size;
                        int pos = min + (totalGap * i) / gaps;
                        widgets[i].setY(pos);
                        if (applyConstraints) {
                            if (reverse) {
                                widgets[i - 1].connect(ConstraintAnchor.Type.BOTTOM, widgets[i], ConstraintAnchor.Type.TOP, pos - lastY - size);
                            } else {
                                widgets[i].connect(ConstraintAnchor.Type.TOP, widgets[i - 1], ConstraintAnchor.Type.BOTTOM, pos - lastY - size);
                            }
                            lastY = pos;
                        }
                    }
                }
            }
            break;
        case DistributeHorizontally:
            {
                int count = 0;
                int sum = 0;
                int min = widgetList.get(0).getX();
                int max = widgetList.get(0).getX() + widgetList.get(0).getHeight();
                for (ConstraintWidget widget : widgets) {
                    int start = widget.getX();
                    int size = widget.getWidth();
                    int end = start + size;
                    sum += size;
                    min = Math.min(min, start);
                    max = Math.max(max, end);
                    count++;
                }
                int gaps = count - 1;
                int totalGap = max - min - sum;
                int lastX = min;
                boolean reverse = rootDistanceX(widgets[0]) > rootDistanceX(widgets[widgets.length - 1]);
                for (int i = 0; i < count; i++) {
                    if (i > 0) {
                        int size = widgets[i - 1].getWidth();
                        min += size;
                        int pos = min + (totalGap * i) / gaps;
                        widgets[i].setX(pos);
                        if (applyConstraints) {
                            if (reverse) {
                                widgets[i - 1].connect(ConstraintAnchor.Type.RIGHT, widgets[i], ConstraintAnchor.Type.LEFT, pos - lastX - size);
                            } else {
                                widgets[i].connect(ConstraintAnchor.Type.LEFT, widgets[i - 1], ConstraintAnchor.Type.RIGHT, pos - lastX - size);
                            }
                            lastX = pos;
                        }
                    }
                }
            }
            break;
        case VerticalPack:
            {
                Rectangle original = getBoundingBox(widgetList);
                ConstraintWidget[] wArray = new ConstraintWidget[widgetList.size()];
                wArray = widgetList.toArray(wArray);
                Arrays.sort(wArray, (w1, w2) -> Integer.compare(w1.getY(), w2.getY()));
                ScoutWidget[] list = ScoutWidget.getWidgetArray((WidgetContainer) widgetList.get(0).getParent());
                for (ConstraintWidget cw : wArray) {
                    for (ScoutWidget scoutWidget : list) {
                        if (scoutWidget.mConstraintWidget == cw) {
                            int gapN = scoutWidget.gap(Direction.NORTH, list);
                            int newY = margin + scoutWidget.mConstraintWidget.getY() - gapN;
                            newY = Math.max(newY, original.y);
                            scoutWidget.setY(newY);
                        }
                    }
                }
            }
            break;
        case HorizontalPack:
            {
                Rectangle original = getBoundingBox(widgetList);
                ConstraintWidget[] wArray = new ConstraintWidget[widgetList.size()];
                wArray = widgetList.toArray(wArray);
                Arrays.sort(wArray, (w1, w2) -> Integer.compare(w1.getX(), w2.getX()));
                ScoutWidget[] list = ScoutWidget.getWidgetArray((WidgetContainer) widgetList.get(0).getParent());
                for (ConstraintWidget cw : wArray) {
                    for (ScoutWidget scoutWidget : list) {
                        if (scoutWidget.mConstraintWidget == cw) {
                            int gapW = scoutWidget.gap(Direction.WEST, list);
                            int newX = margin + scoutWidget.mConstraintWidget.getX() - gapW;
                            newX = Math.max(newX, original.x);
                            scoutWidget.setX(newX);
                        }
                    }
                }
            }
            break;
        case ExpandVertically:
            {
                expandVertically(widgetList, margin);
            }
            break;
        case ExpandHorizontally:
            {
                expandHorizontally(widgetList, margin);
            }
            break;
    }
}
Also used : WidgetContainer(android.support.constraint.solver.widgets.WidgetContainer) Rectangle(java.awt.Rectangle) Arrays(java.util.Arrays) Iterator(java.util.Iterator) ConstraintAnchor(android.support.constraint.solver.widgets.ConstraintAnchor) Comparator(java.util.Comparator) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) Guideline(android.support.constraint.solver.widgets.Guideline) ArrayList(java.util.ArrayList) ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) Rectangle(java.awt.Rectangle) ArrayList(java.util.ArrayList) WidgetContainer(android.support.constraint.solver.widgets.WidgetContainer)

Example 2 with WidgetContainer

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

the class ScoutArrange method expandVertically.

/**
     * Expands widgets vertically in an evenly spaced manner
     * @param widgetList
     * @param margin
     */
private static void expandVertically(ArrayList<ConstraintWidget> widgetList, int margin) {
    WidgetContainer base = (WidgetContainer) widgetList.get(0).getParent();
    ConstraintWidget[] pears = new ConstraintWidget[base.getChildren().size()];
    pears = base.getChildren().toArray(pears);
    Rectangle selectBounds = getBoundingBox(widgetList);
    Rectangle clip = new Rectangle();
    int gapNorth = gap(Direction.NORTH, selectBounds, pears);
    int gapSouth = gap(Direction.SOUTH, selectBounds, pears);
    clip.y = selectBounds.y - gapNorth;
    clip.height = selectBounds.height + gapSouth + gapNorth;
    ArrayList<ConstraintWidget> selectedList = new ArrayList<>(widgetList);
    while (!selectedList.isEmpty()) {
        ConstraintWidget widget = selectedList.remove(0);
        ArrayList<ConstraintWidget> col = new ArrayList<>();
        col.add(widget);
        for (Iterator<ConstraintWidget> iterator = selectedList.iterator(); iterator.hasNext(); ) {
            ConstraintWidget elem = iterator.next();
            if (isSameColumn(widget, elem)) {
                if (!col.contains(elem)) {
                    col.add(elem);
                }
                iterator.remove();
            }
        }
        ConstraintWidget[] colArray = new ConstraintWidget[col.size()];
        colArray = col.toArray(colArray);
        Arrays.sort(colArray, sSortY);
        int gaps = (colArray.length - 1) * margin;
        int totalHeight = (clip.height - gaps - 2 * margin);
        for (int i = 0; i < colArray.length; i++) {
            int y = margin * i + (i * (totalHeight)) / colArray.length;
            ConstraintWidget constraintWidget = colArray[i];
            constraintWidget.setY(y + clip.y + margin);
            int yend = margin * i + (totalHeight * (i + 1)) / colArray.length;
            constraintWidget.setVerticalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.FIXED);
            constraintWidget.setHeight(yend - y);
        }
    }
}
Also used : ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) Rectangle(java.awt.Rectangle) ArrayList(java.util.ArrayList) WidgetContainer(android.support.constraint.solver.widgets.WidgetContainer)

Example 3 with WidgetContainer

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

the class ScoutArrange method expandHorizontally.

/**
     * Expands widgets horizontally in an evenly spaced manner
     * @param widgetList
     * @param margin
     */
public static void expandHorizontally(ArrayList<ConstraintWidget> widgetList, int margin) {
    WidgetContainer base = (WidgetContainer) widgetList.get(0).getParent();
    ConstraintWidget[] pears = new ConstraintWidget[base.getChildren().size()];
    pears = base.getChildren().toArray(pears);
    Rectangle selectBounds = getBoundingBox(widgetList);
    Rectangle clip = new Rectangle();
    int gapWest = gap(Direction.WEST, selectBounds, pears);
    int gapEast = gap(Direction.EAST, selectBounds, pears);
    clip.x = selectBounds.x - gapWest;
    clip.width = selectBounds.width + gapEast + gapWest;
    ArrayList<ConstraintWidget> selectedList;
    selectedList = new ArrayList<ConstraintWidget>(widgetList);
    while (!selectedList.isEmpty()) {
        ConstraintWidget widget = selectedList.remove(0);
        ArrayList<ConstraintWidget> row = new ArrayList<>();
        row.add(widget);
        for (Iterator<ConstraintWidget> iterator = selectedList.iterator(); iterator.hasNext(); ) {
            ConstraintWidget elem = iterator.next();
            if (isSameRow(widget, elem)) {
                if (!row.contains(elem)) {
                    row.add(elem);
                }
                iterator.remove();
            }
        }
        ConstraintWidget[] rowArray = new ConstraintWidget[row.size()];
        rowArray = row.toArray(rowArray);
        Arrays.sort(rowArray, sSortX);
        int gaps = (rowArray.length - 1) * margin;
        int totalWidth = (clip.width - gaps - 2 * margin);
        for (int i = 0; i < rowArray.length; i++) {
            int x = margin * i + (i * (totalWidth)) / rowArray.length;
            ConstraintWidget constraintWidget = rowArray[i];
            constraintWidget.setX(x + clip.x + margin);
            int xend = margin * i + (totalWidth * (i + 1)) / rowArray.length;
            constraintWidget.setHorizontalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.FIXED);
            constraintWidget.setWidth(xend - x);
        }
    }
}
Also used : ConstraintWidget(android.support.constraint.solver.widgets.ConstraintWidget) Rectangle(java.awt.Rectangle) ArrayList(java.util.ArrayList) WidgetContainer(android.support.constraint.solver.widgets.WidgetContainer)

Aggregations

ConstraintWidget (android.support.constraint.solver.widgets.ConstraintWidget)3 WidgetContainer (android.support.constraint.solver.widgets.WidgetContainer)3 Rectangle (java.awt.Rectangle)3 ArrayList (java.util.ArrayList)3 ConstraintAnchor (android.support.constraint.solver.widgets.ConstraintAnchor)1 Guideline (android.support.constraint.solver.widgets.Guideline)1 Arrays (java.util.Arrays)1 Comparator (java.util.Comparator)1 Iterator (java.util.Iterator)1