use of android.support.constraint.solver.widgets.ConstraintAnchor 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;
}
}
}
}
use of android.support.constraint.solver.widgets.ConstraintAnchor 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);
}
}
}
}
}
use of android.support.constraint.solver.widgets.ConstraintAnchor in project android by JetBrains.
the class SnapPlacement method createSnapCandidate.
/**
* Internal utility function to create a snap candidate on the fly for a margin.
*
* @param widget the widget we operate on
* @param type the type of ConstraintAnchor we want to use for the target
* @param x the horizontal position for the ConstraintAnchor target
* @param y the vertical position for the ConstraintAnchor target
* @return a new instance of SnapCandidate representing the margin
*/
private static SnapCandidate createSnapCandidate(ConstraintWidget widget, ConstraintAnchor.Type type, int x, int y) {
SnapCandidate candidate = new SnapCandidate();
candidate.source = widget.getAnchor(type);
ConstraintWidget owner = widget.getParent();
ConstraintAnchor anchor = new ConstraintAnchor(owner, type);
candidate.x = x;
candidate.y = y;
candidate.target = anchor;
return candidate;
}
use of android.support.constraint.solver.widgets.ConstraintAnchor in project android by JetBrains.
the class SnapPlacement method snapExistingHorizontalMargin.
/**
* Try move the widget on the horizontal 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 horizontal axis
*/
private static boolean snapExistingHorizontalMargin(ConstraintWidget widget, Point candidatePoint) {
int x = candidatePoint.x;
ConstraintAnchor left = widget.getAnchor(ConstraintAnchor.Type.LEFT);
ConstraintAnchor right = widget.getAnchor(ConstraintAnchor.Type.RIGHT);
boolean snapped = false;
if (left.isConnected() && right.isConnected()) {
// we do nothing in this case.
} else if (left.isConnected()) {
int x1 = x;
int x2 = WidgetInteractionTargets.constraintHandle(left.getTarget()).getDrawX();
int margin = ((x1 - x2) / SceneDraw.GRID_SPACING) * SceneDraw.GRID_SPACING;
if (margin < 0) {
margin = 0;
}
left.setMargin(margin);
snapped = true;
} else if (right != null && right.isConnected()) {
int x1 = x + widget.getDrawWidth();
int x2 = WidgetInteractionTargets.constraintHandle(right.getTarget()).getDrawX();
int margin = ((x2 - x1) / SceneDraw.GRID_SPACING) * SceneDraw.GRID_SPACING;
if (margin < 0) {
margin = 0;
}
right.setMargin(margin);
snapped = true;
}
return snapped;
}
use of android.support.constraint.solver.widgets.ConstraintAnchor 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;
}
Aggregations