use of android.support.constraint.solver.widgets.Guideline in project android by JetBrains.
the class WidgetInteractionTargets method findClosestConnection.
/**
* Fill in the ConnectionCandidate structure with the closest anchor found at (x, y).
* This function will not consider CENTER_X/CENTER_Y anchors.
*
* @param viewTransform
* @param x x coordinate we are looking at
* @param y y coordinate we are looking at
* @param candidate a structure containing the current best anchor candidate.
* @param mousePress true if we are in mouse press
*/
public void findClosestConnection(ViewTransform viewTransform, float x, float y, ConnectionCandidate candidate, boolean mousePress) {
// FIXME: should use subclasses this
if (mWidget instanceof Guideline) {
float distance;
Guideline guideline = (Guideline) mWidget;
ConstraintAnchor anchor = guideline.getAnchor();
ConstraintHandle handle = constraintHandle(anchor);
if (handle == null) {
return;
}
if (guideline.getOrientation() == Guideline.VERTICAL) {
distance = (handle.getDrawX() - x) * (handle.getDrawX() - x);
} else {
distance = (handle.getDrawY() - y) * (handle.getDrawY() - y);
}
distance = viewTransform.getSwingDimensionF(distance);
if (distance < candidate.distance) {
candidate.anchorTarget = anchor;
candidate.distance = distance;
}
} else if (mWidget instanceof ConstraintWidgetContainer) {
for (ConstraintHandle handle : mConstraintHandles) {
ConstraintAnchor anchor = handle.getAnchor();
if (anchor.getType() == ConstraintAnchor.Type.CENTER_X || anchor.getType() == ConstraintAnchor.Type.CENTER_Y) {
continue;
}
float distance = 0;
boolean computed = false;
if (!mousePress && anchor.isSideAnchor()) {
if (!anchor.isVerticalAnchor()) {
if (y >= mWidget.getDrawY() && y <= mWidget.getDrawBottom()) {
distance = (handle.getDrawX() - x) * (handle.getDrawX() - x);
computed = true;
}
} else {
if (x >= mWidget.getDrawX() && x <= mWidget.getDrawRight()) {
distance = (handle.getDrawY() - y) * (handle.getDrawY() - y);
computed = true;
}
}
}
if (!computed) {
distance = (handle.getDrawX() - x) * (handle.getDrawX() - x) + (handle.getDrawY() - y) * (handle.getDrawY() - y);
}
distance = viewTransform.getSwingDimensionF(distance);
if (distance < candidate.distance) {
candidate.anchorTarget = anchor;
candidate.distance = distance;
}
}
} else {
for (ConstraintHandle handle : mConstraintHandles) {
ConstraintAnchor anchor = handle.getAnchor();
float distance = (handle.getDrawX() - x) * (handle.getDrawX() - x) + (handle.getDrawY() - y) * (handle.getDrawY() - y);
if (anchor.getType() == ConstraintAnchor.Type.CENTER_X || anchor.getType() == ConstraintAnchor.Type.CENTER_Y) {
continue;
}
if (anchor.getType() == ConstraintAnchor.Type.BASELINE) {
if (!anchor.getOwner().hasBaseline()) {
continue;
}
ConstraintWidget widget = anchor.getOwner();
int minX = widget.getDrawX();
int maxX = widget.getDrawRight();
float d = Math.abs(handle.getDrawY() - y);
if (x >= minX && x <= maxX && d < 3) {
distance = d * d;
}
}
distance = viewTransform.getSwingDimensionF(distance);
if (distance <= candidate.distance) {
if (candidate.anchorTarget == null || candidate.anchorTarget.getPriorityLevel() < anchor.getPriorityLevel()) {
candidate.anchorTarget = anchor;
candidate.distance = distance;
}
}
}
}
}
use of android.support.constraint.solver.widgets.Guideline in project android by JetBrains.
the class TableDecorator method mousePressed.
/**
* Handle mouse press event to add click targets. TODO: clean this up.
*
* @param x mouse x coordinate
* @param y mouse y coordinate
* @param transform view transform
* @param selection the current selection of widgets
*/
@Override
public ConstraintWidget mousePressed(float x, float y, ViewTransform transform, Selection selection) {
ConstraintTableLayout table = (ConstraintTableLayout) mWidget;
mTableClickTargets.clear();
ArrayList<Guideline> vertical = table.getVerticalGuidelines();
int l = transform.getSwingX(table.getDrawX());
int t = transform.getSwingY(table.getDrawY());
int column = 0;
TableClickTarget firstTarget = new TableClickTarget(table, column++, l, t - 20 - 4, 20, 20);
mTableClickTargets.add(firstTarget);
for (ConstraintWidget v : vertical) {
int bx = transform.getSwingX(v.getX()) + l;
TableClickTarget target = new TableClickTarget(table, column++, bx, t - 20 - 4, 20, 20);
mTableClickTargets.add(target);
}
ConstraintWidget widgetHit = null;
if (mTableClickTargets.size() > 0) {
for (TableClickTarget tableClickTarget : mTableClickTargets) {
if (tableClickTarget.contains(x, y)) {
widgetHit = tableClickTarget.getTable();
break;
}
}
if (selection.isEmpty()) {
mTableClickTargets.clear();
}
}
return widgetHit;
}
use of android.support.constraint.solver.widgets.Guideline 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.Guideline 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.Guideline 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