use of android.support.constraint.solver.widgets.ConstraintWidget 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;
}
}
use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.
the class ScoutWidget method recursiveConnectedDistanceToRoot.
/**
* Walk the widget connections to get the distance to the container in a direction
*
* @param list list of widgets (container is list[0]
* @param direction direction to check in
* @return distance root or NaN if no connection available
*/
private float recursiveConnectedDistanceToRoot(ScoutWidget[] list, Direction direction) {
if (isDistanceToRootCache(direction)) {
return mDistToRootCache[direction.getDirection()];
}
ConstraintAnchor.Type anchorType = lookupType(direction);
ConstraintAnchor anchor = mConstraintWidget.getAnchor(anchorType);
if (anchor == null || !anchor.isConnected()) {
return Float.NaN;
}
float margin = anchor.getMargin();
ConstraintAnchor toAnchor = anchor.getTarget();
ConstraintWidget toWidget = toAnchor.getOwner();
if (list[0].mConstraintWidget == toWidget) {
// found the base return;
return margin;
}
// if atached to the same side
if (toAnchor.getType() == anchorType) {
for (ScoutWidget scoutWidget : list) {
if (scoutWidget.mConstraintWidget == toWidget) {
float dist = scoutWidget.recursiveConnectedDistanceToRoot(list, direction);
scoutWidget.cacheRootDistance(direction, dist);
return margin + dist;
}
}
}
// if atached to the other side (you will need to add the length of the widget
if (toAnchor.getType() == lookupType(direction.getOpposite())) {
for (ScoutWidget scoutWidget : list) {
if (scoutWidget.mConstraintWidget == toWidget) {
margin += scoutWidget.getLength(direction);
float dist = scoutWidget.recursiveConnectedDistanceToRoot(list, direction);
scoutWidget.cacheRootDistance(direction, dist);
return margin + dist;
}
}
}
return Float.NaN;
}
use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.
the class Selection method createBounds.
/**
* If the selection has more than one element, it will create a temporary
* Element object as the bounds of the entire selection. We then use
* this bounds object to snap the full selection on screen.
*/
public void createBounds() {
if (isEmpty() || hasSingleElement()) {
mBounds = null;
return;
}
int l = Integer.MAX_VALUE;
int t = Integer.MAX_VALUE;
int r = 0;
int b = 0;
for (Selection.Element selection : getElements()) {
ConstraintWidget w = selection.widget;
l = Math.min(w.getDrawX(), l);
t = Math.min(w.getDrawY(), t);
r = Math.max(w.getDrawRight(), r);
b = Math.max(w.getDrawBottom(), b);
}
ConstraintWidget bounds = new ConstraintWidget(l, t, r - l, b - t);
bounds.setCompanionWidget(WidgetCompanion.create(bounds));
mBounds = new Element(bounds);
updateOriginFromBounds();
}
use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.
the class ScoutArrange method gapWidget.
/**
* Calculate the nearest widget
*
* @param direction the direction to check
* @param list list of other widgets (root == list[0])
* @return the distance on that side
*/
public static ConstraintWidget gapWidget(Direction direction, Rectangle region, ConstraintWidget[] list) {
int rootWidth = list[0].getParent().getWidth();
int rootHeight = list[0].getParent().getHeight();
Rectangle rect = new Rectangle();
switch(direction) {
case NORTH:
{
rect.y = 0;
rect.x = region.x + 1;
rect.width = region.width - 2;
rect.height = region.y;
}
break;
case SOUTH:
{
rect.y = region.y + region.height + 1;
rect.x = region.x + 1;
rect.width = region.width - 2;
rect.height = rootHeight - rect.y;
}
break;
case WEST:
{
rect.y = region.y + 1;
rect.x = 0;
rect.width = region.x;
rect.height = region.height - 2;
}
break;
case EAST:
{
rect.y = region.y + 1;
rect.x = region.x + region.width + 1;
rect.width = rootWidth - rect.x;
rect.height = region.height - 2;
}
break;
}
int min = Integer.MAX_VALUE;
ConstraintWidget minWidget = null;
for (ConstraintWidget widget : list) {
Rectangle r = getRectangle(widget);
if (r.intersects(rect)) {
int dist = (int) distance(r, region);
if (min > dist) {
minWidget = widget;
min = dist;
}
}
}
if (min > Math.max(rootHeight, rootWidth)) {
return list[0].getParent();
}
return minWidget;
}
use of android.support.constraint.solver.widgets.ConstraintWidget 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);
}
Aggregations