use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.
the class ConstraintHandle method drawConnection.
/**
* Implements the drawing of the connection from this anchor to its target
*
* @param transform the view transform
* @param g the graphics context
* @param colorSet the current colorset
* @param isSelected if the connection is selected
*/
public void drawConnection(ViewTransform transform, Graphics2D g, ColorSet colorSet, boolean isSelected, boolean showMargin, int originalCreator, float progress) {
if (!mAnchor.isConnected()) {
return;
}
if (mAnchor != null && mAnchor.getConnectionCreator() == ConstraintAnchor.AUTO_CONSTRAINT_CREATOR) {
startLock();
}
ConnectionDrawing drawing = new ConnectionDrawing();
ConstraintWidget targetWidget = mAnchor.getTarget().getOwner();
WidgetCompanion targetCompanion = (WidgetCompanion) targetWidget.getCompanionWidget();
if (targetCompanion == null) {
return;
}
WidgetInteractionTargets interactionTargets = targetCompanion.getWidgetInteractionTargets();
ConstraintHandle targetHandle = interactionTargets.getConstraintHandle(mAnchor.getTarget());
if (targetHandle == null) {
// TODO fix -- sometimes triggered with guideline and inference
return;
}
g.setStroke(sSimpleStroke);
int sx = transform.getSwingFX(mX);
int sy = transform.getSwingFY(mY);
int tx = transform.getSwingFX(targetHandle.getDrawX());
int ty = transform.getSwingFY(targetHandle.getDrawY());
if (targetHandle.getOwner().isRootContainer()) {
if (mAnchor.isVerticalAnchor()) {
tx = sx;
} else {
ty = sy;
}
}
int minimum = (int) (1.5 * ConnectionDraw.CONNECTION_ANCHOR_SIZE);
if (Math.abs(sx - tx) < minimum && Math.abs(sy - ty) < minimum) {
switch(mAnchor.getType()) {
case LEFT:
{
drawShadowedArrow(g, colorSet, ConnectionDraw.getLeftArrow(), sx, sy);
}
break;
case TOP:
{
drawShadowedArrow(g, colorSet, ConnectionDraw.getTopArrow(), sx, sy);
}
break;
case RIGHT:
{
drawShadowedArrow(g, colorSet, ConnectionDraw.getRightArrow(), sx, sy);
}
break;
case BOTTOM:
{
drawShadowedArrow(g, colorSet, ConnectionDraw.getBottomArrow(), sx, sy);
}
break;
}
return;
}
if (mAnchor.getOpposite() != null && mAnchor.getOpposite().isConnected()) {
// Draw centered connections
if (mAnchor.getOpposite().getTarget() == mAnchor.getTarget()) {
// Center connection on same anchor
addPathCenteredConnectionOnSameAnchor(transform, g, isSelected, drawing, targetHandle, targetWidget);
} else if ((mAnchor.getOpposite().getTarget().getOwner() == mAnchor.getTarget().getOwner()) && targetWidget != getOwner().getParent()) {
if (mAnchor.getConnectionCreator() == ConstraintAnchor.AUTO_CONSTRAINT_CREATOR) {
g.setStroke(colorSet.getSoftConstraintStroke());
}
// Center connection on same widget (save our parent)
addPathCenteredConnectionOnSameWidget(transform, g, isSelected, drawing, colorSet, targetHandle, targetWidget);
} else {
if (mAnchor.getConnectionCreator() == ConstraintAnchor.AUTO_CONSTRAINT_CREATOR) {
g.setStroke(colorSet.getSoftConstraintStroke());
}
// Center connection on different widgets (or our parent)
addPathCenteredConnection(transform, g, isSelected, drawing, colorSet, targetHandle, targetWidget);
}
} else {
addPathConnection(transform, g, isSelected, showMargin, drawing, colorSet, targetHandle.getDrawX(), targetHandle.getDrawY(), mAnchor.isConnected(), targetHandle.getAnchor().isConnected());
}
// If a lock timer is active, draw the path a second time
if (progress <= 1 && progress >= 0.1) {
int distance = lengthOfPath(drawing.mPath);
int dashFull = (int) (distance * progress);
int dashEmpty = (int) (distance * (1 - progress));
if (dashFull > 0 || dashEmpty > 0) {
Stroke s = g.getStroke();
if (originalCreator == ConstraintAnchor.AUTO_CONSTRAINT_CREATOR || originalCreator == ConstraintAnchor.SCOUT_CREATOR) {
if (originalCreator != ConstraintAnchor.SCOUT_CREATOR) {
g.setColor(colorSet.getSoftConstraintColor());
g.setStroke(colorSet.getSoftConstraintStroke());
drawing.draw(g);
}
Stroke progressStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { dashFull, dashEmpty }, 0);
g.setStroke(progressStroke);
if (progress != 1) {
drawing.mDrawArrow = false;
}
if (originalCreator != ConstraintAnchor.SCOUT_CREATOR) {
g.setColor(colorSet.getSelectedConstraints());
}
drawing.draw(g);
} else {
g.setColor(colorSet.getSoftConstraintColor());
g.setStroke(colorSet.getSoftConstraintStroke());
drawing.draw(g);
Stroke progressStroke = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { dashEmpty, dashFull }, 0);
g.setColor(colorSet.getSelectedConstraints());
g.setStroke(progressStroke);
if (progress == 1) {
drawing.mDrawArrow = false;
}
drawing.draw(g);
}
int distanceCircle = (int) (2 * Math.PI * 10);
Color prev = g.getColor();
int solidCircle = (int) (distanceCircle * progress);
int emptyCircle = (int) (distanceCircle * (1 - progress));
Stroke circleProgressStrokeOuter = new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { solidCircle, emptyCircle }, 0);
g.setColor(colorSet.getBackground());
g.setStroke(circleProgressStrokeOuter);
int d = 2 * sCountDownRadius;
g.drawRoundRect(sx - sCountDownRadius, sy - sCountDownRadius, d, d, d, d);
Stroke circleProgressStroke = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { solidCircle, emptyCircle }, 0);
g.setColor(prev);
g.setStroke(circleProgressStroke);
g.drawRoundRect(sx - sCountDownRadius, sy - sCountDownRadius, d, d, d, d);
g.setStroke(s);
}
} else {
paintShadow(g, colorSet, drawing);
drawing.draw(g);
}
}
use of android.support.constraint.solver.widgets.ConstraintWidget in project android by JetBrains.
the class SnapPlacement method checkVerticalParentMarginSnap.
/**
* Check to snap on the vertical 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 checkVerticalParentMarginSnap(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();
int ty = targetParentHandle.getDrawY() + margin;
int distance = Math.abs(anchorHandle.getDrawY() - ty);
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.ConstraintWidget 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.ConstraintWidget 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.ConstraintWidget 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;
}
}
Aggregations