use of android.support.constraint.solver.widgets.ConstraintAnchor in project android by JetBrains.
the class SnapPlacement method gatherMargins.
/**
* Given a margin and its orientation, gather all similar margins among the widgets.
* the margins list will be filled with the margins we found.
*
* @param widgets the list of known widgets
* @param margins the list of margins we found
* @param margin the value of the margin we are looking for
* @param isVertical the orientation of the margin we are looking for
*/
public static void gatherMargins(Collection<ConstraintWidget> widgets, ArrayList<SnapCandidate> margins, int margin, boolean isVertical) {
margin = Math.abs(margin);
if (margin == 0) {
return;
}
// TODO: we should cache the margins found
ArrayList<SnapCandidate> foundMargins = new ArrayList<>();
for (ConstraintWidget w1 : widgets) {
for (ConstraintAnchor a1 : w1.getAnchors()) {
if (!a1.isSideAnchor()) {
continue;
}
if (a1.isVerticalAnchor() != isVertical) {
continue;
}
for (ConstraintWidget w2 : widgets) {
for (ConstraintAnchor a2 : w2.getAnchors()) {
if (!a2.isSideAnchor()) {
continue;
}
if (!a2.isSimilarDimensionConnection(a1)) {
continue;
}
ConstraintHandle h1 = WidgetInteractionTargets.constraintHandle(a1);
ConstraintHandle h2 = WidgetInteractionTargets.constraintHandle(a2);
if (h1 == null || h2 == null) {
continue;
}
int currentMargin = h1.getStraightDistanceFrom(h2);
if (Math.abs(currentMargin) == margin) {
SnapCandidate candidate = new SnapCandidate();
candidate.source = a1;
candidate.target = a2;
candidate.margin = currentMargin;
foundMargins.add(candidate);
}
}
}
}
}
for (SnapCandidate c1 : foundMargins) {
boolean insert = true;
for (SnapCandidate c2 : margins) {
// if we have the opposite margin, don't use it
if ((Math.abs(c1.margin) == Math.abs(c2.margin)) && ((c2.source == c1.target && c2.target == c1.source) || (c2.source == c1.source && c2.target == c1.target))) {
insert = false;
break;
}
// if we have margins for the same position, don't use them
if (c1.source.isSimilarDimensionConnection(c2.source) && c1.margin == c2.margin) {
ConstraintHandle sourceHandle1 = WidgetInteractionTargets.constraintHandle(c1.source);
ConstraintHandle targetHandle1 = WidgetInteractionTargets.constraintHandle(c1.target);
ConstraintHandle sourceHandle2 = WidgetInteractionTargets.constraintHandle(c2.source);
ConstraintHandle targetHandle2 = WidgetInteractionTargets.constraintHandle(c2.target);
if (c1.source.isVerticalAnchor()) {
if (Math.min(sourceHandle1.getDrawY(), targetHandle1.getDrawY()) == Math.min(sourceHandle2.getDrawY(), targetHandle2.getDrawY())) {
insert = false;
break;
}
} else if (Math.min(sourceHandle1.getDrawX(), targetHandle1.getDrawX()) == Math.min(sourceHandle2.getDrawX(), targetHandle2.getDrawX())) {
insert = false;
break;
}
}
}
if (insert) {
margins.add(c1);
}
}
}
use of android.support.constraint.solver.widgets.ConstraintAnchor in project android by JetBrains.
the class SnapPlacement method snapAnchor.
/**
* Try to find snapping candidates for the given anchor
*
* @param widgets the list of known widgets
* @param widget the widget we operate on
* @param anchor the anchor we are trying to snap
* @param candidate the current candidate
*/
public static void snapAnchor(Collection<ConstraintWidget> widgets, ConstraintWidget widget, ConstraintAnchor anchor, SnapCandidate candidate) {
if (widget.getParent() != null) {
if (!anchor.isVerticalAnchor()) {
checkHorizontalParentMarginSnap(anchor, ConstraintAnchor.Type.RIGHT, -DEFAULT_MARGIN, candidate);
checkHorizontalParentMarginSnap(anchor, ConstraintAnchor.Type.LEFT, DEFAULT_MARGIN, candidate);
} else {
checkVerticalParentMarginSnap(anchor, ConstraintAnchor.Type.BOTTOM, -DEFAULT_MARGIN, candidate);
checkVerticalParentMarginSnap(anchor, ConstraintAnchor.Type.TOP, DEFAULT_MARGIN, candidate);
}
}
for (ConstraintWidget w : widgets) {
if (w == widget) {
continue;
}
ArrayList<ConstraintAnchor> anchorsTarget = w.getAnchors();
for (ConstraintAnchor at : anchorsTarget) {
snapCheck(anchor, at, candidate, CONNECTION_SLOPE);
}
}
}
use of android.support.constraint.solver.widgets.ConstraintAnchor in project android by JetBrains.
the class SnapPlacement method snapExistingVerticalMargin.
/**
* Try move the widget on the vertical axis, snapping an existing margin
* to WidgetsView.GRID_SPACING
*
* @param widget the widget we operate on
* @param candidatePoint the candidate new position
* @return true if we changed the margin on the vertical axis
*/
private static boolean snapExistingVerticalMargin(ConstraintWidget widget, Point candidatePoint) {
int y = candidatePoint.y;
boolean snapped = false;
ConstraintAnchor top = widget.getAnchor(ConstraintAnchor.Type.TOP);
ConstraintAnchor bottom = widget.getAnchor(ConstraintAnchor.Type.BOTTOM);
if (top.isConnected() && bottom.isConnected()) {
// we do nothing in this case
} else if (top.isConnected()) {
int y1 = y;
int y2 = WidgetInteractionTargets.constraintHandle(top.getTarget()).getDrawY();
int margin = ((y1 - y2) / SceneDraw.GRID_SPACING) * SceneDraw.GRID_SPACING;
if (margin < 0) {
margin = 0;
}
top.setMargin(margin);
snapped = true;
} else if (bottom.isConnected()) {
int y1 = y + widget.getHeight();
int y2 = WidgetInteractionTargets.constraintHandle(bottom.getTarget()).getDrawY();
int margin = ((y2 - y1) / SceneDraw.GRID_SPACING) * SceneDraw.GRID_SPACING;
if (margin < 0) {
margin = 0;
}
bottom.setMargin(margin);
snapped = true;
}
return snapped;
}
use of android.support.constraint.solver.widgets.ConstraintAnchor in project android by JetBrains.
the class SnapPlacement method checkHorizontalParentMarginSnap.
/**
* Check to snap on the horizontal internal margins of a parent (used when resizing)
*
* @param anchor the anchor we are trying to snap
* @param type the type of anchor on the parent that we want to check against
* @param margin the margin we'll use for the internal margin
* @param candidate the current candidate that we can fill in
*/
private static void checkHorizontalParentMarginSnap(ConstraintAnchor anchor, ConstraintAnchor.Type type, int margin, SnapCandidate candidate) {
ConstraintWidget widget = anchor.getOwner();
if (widget.getParent() == null) {
return;
}
ConstraintAnchor targetParent = widget.getParent().getAnchor(type);
ConstraintHandle targetParentHandle = WidgetInteractionTargets.constraintHandle(targetParent);
ConstraintHandle anchorHandle = WidgetInteractionTargets.constraintHandle(anchor);
ConstraintAnchor target = new ConstraintAnchor(widget.getParent(), type);
int tx = targetParentHandle.getDrawX() + margin;
int ty = targetParentHandle.getDrawY();
int distance = Math.abs(anchorHandle.getDrawX() - tx);
if (distance <= CONNECTION_SLOPE) {
candidate.distance = distance;
candidate.target = target;
candidate.source = anchor;
candidate.x = tx;
candidate.y = ty;
}
}
use of android.support.constraint.solver.widgets.ConstraintAnchor in project android by JetBrains.
the class WidgetResize method resizeWidget.
/**
* Resize the widget given the current mouse position
*
* @param widgets the list of known widgets
* @param widget the widget we are resizing
* @param posX in android coordinate
* @param posY in android coordinate
*/
public void resizeWidget(Collection<ConstraintWidget> widgets, ConstraintWidget widget, ResizeHandle handle, Rectangle originalBounds, int posX, int posY) {
if (widget == null) {
return;
}
Animator.setAnimationEnabled(false);
mSnapCandidates.clear();
int x = widget.getDrawX();
int y = widget.getDrawY();
int w = widget.getDrawWidth();
int h = widget.getDrawHeight();
ResizeHandle.Type resize = handle.getType();
ConstraintAnchor left = widget.getAnchor(ConstraintAnchor.Type.LEFT);
ConstraintAnchor top = widget.getAnchor(ConstraintAnchor.Type.TOP);
ConstraintAnchor right = widget.getAnchor(ConstraintAnchor.Type.RIGHT);
ConstraintAnchor bottom = widget.getAnchor(ConstraintAnchor.Type.BOTTOM);
ConstraintAnchor baseline = widget.getAnchor(ConstraintAnchor.Type.BASELINE);
boolean leftIsConnected = left != null && left.isConnected();
boolean rightIsConnected = right != null && right.isConnected();
boolean topIsConnected = top != null && top.isConnected();
boolean bottomIsConnected = bottom != null && bottom.isConnected();
boolean baselineIsConnected = baseline != null && baseline.isConnected();
// Limits range of motion depending on which anchor is connected
if (leftIsConnected && !rightIsConnected) {
switch(resize) {
case LEFT_TOP:
{
resize = ResizeHandle.Type.TOP_SIDE;
}
break;
case LEFT_BOTTOM:
{
resize = ResizeHandle.Type.BOTTOM_SIDE;
}
break;
}
}
if (rightIsConnected && !leftIsConnected) {
switch(resize) {
case RIGHT_TOP:
{
resize = ResizeHandle.Type.TOP_SIDE;
}
break;
case RIGHT_BOTTOM:
{
resize = ResizeHandle.Type.BOTTOM_SIDE;
}
break;
}
}
if ((topIsConnected || baselineIsConnected) && !bottomIsConnected) {
switch(resize) {
case LEFT_TOP:
{
resize = ResizeHandle.Type.LEFT_SIDE;
}
break;
case RIGHT_TOP:
{
resize = ResizeHandle.Type.RIGHT_SIDE;
}
break;
}
}
if (bottomIsConnected && !topIsConnected) {
switch(resize) {
case LEFT_BOTTOM:
{
resize = ResizeHandle.Type.LEFT_SIDE;
}
break;
case RIGHT_BOTTOM:
{
resize = ResizeHandle.Type.RIGHT_SIDE;
}
break;
}
}
ConstraintWidget base = widget.getParent();
switch(resize) {
case LEFT_TOP:
{
int newX = Math.min(originalBounds.x + originalBounds.width - widget.getMinWidth(), posX);
newX = clampX(newX, base);
newX = snapLeft(widgets, widget, newX, mSnapCandidates);
int newY = Math.min(originalBounds.y + originalBounds.height - widget.getMinHeight(), posY);
newY = clampY(newY, base);
newY = snapTop(widgets, widget, newY, mSnapCandidates);
int newWidth = originalBounds.x + originalBounds.width - newX;
int newHeight = originalBounds.y + originalBounds.height - newY;
setNewFrame(widget, newX, newY, newWidth, newHeight);
}
break;
case LEFT_BOTTOM:
{
int newX = Math.min(originalBounds.x + originalBounds.width - widget.getMinWidth(), posX);
newX = clampX(newX, base);
newX = snapLeft(widgets, widget, newX, mSnapCandidates);
int newWidth = originalBounds.x + originalBounds.width - newX;
int newHeight = posY - originalBounds.y;
newHeight = snapHeight(widgets, widget, newHeight, mSnapCandidates);
setNewFrame(widget, newX, y, newWidth, newHeight);
}
break;
case RIGHT_TOP:
{
int newY = Math.min(originalBounds.y + originalBounds.height - widget.getMinHeight(), posY);
newY = clampY(newY, base);
newY = snapTop(widgets, widget, newY, mSnapCandidates);
int newWidth = posX - originalBounds.x;
newWidth = snapWidth(widgets, widget, newWidth, mSnapCandidates);
int newHeight = originalBounds.y + originalBounds.height - newY;
setNewFrame(widget, x, newY, newWidth, newHeight);
}
break;
case RIGHT_BOTTOM:
{
int newWidth = posX - originalBounds.x;
int newHeight = posY - originalBounds.y;
newWidth = snapWidth(widgets, widget, newWidth, mSnapCandidates);
newHeight = snapHeight(widgets, widget, newHeight, mSnapCandidates);
setNewFrame(widget, x, y, newWidth, newHeight);
}
break;
case LEFT_SIDE:
{
int newX = Math.min(originalBounds.x + originalBounds.width - widget.getMinWidth(), posX);
if (widget instanceof Guideline) {
newX = posX;
}
newX = clampX(newX, base);
newX = snapLeft(widgets, widget, newX, mSnapCandidates);
int newWidth = originalBounds.x + originalBounds.width - newX;
setNewFrame(widget, newX, y, newWidth, h);
}
break;
case RIGHT_SIDE:
{
int newWidth = posX - originalBounds.x;
newWidth = snapWidth(widgets, widget, newWidth, mSnapCandidates);
setNewFrame(widget, x, y, newWidth, h);
}
break;
case TOP_SIDE:
{
int newY = Math.min(originalBounds.y + originalBounds.height - widget.getMinHeight(), posY);
if (widget instanceof Guideline) {
newY = posY;
}
newY = clampY(newY, base);
newY = snapTop(widgets, widget, newY, mSnapCandidates);
int newHeight = originalBounds.y + originalBounds.height - newY;
setNewFrame(widget, x, newY, w, newHeight);
}
break;
case BOTTOM_SIDE:
{
int newHeight = posY - originalBounds.y;
newHeight = snapHeight(widgets, widget, newHeight, mSnapCandidates);
setNewFrame(widget, x, y, w, newHeight);
}
break;
}
}
Aggregations