use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class ConstraintPainter method paintConstraint.
/**
* Paints a given match as a constraint.
*
* @param graphics the graphics context
* @param state the handler state
* @param match the match
*/
static void paintConstraint(NlGraphics graphics, GuidelineHandler state, Match match) {
NlComponent node = match.edge.component;
if (node == null) {
return;
}
Insets padding = node.getPadding();
Rectangle targetBounds = node == state.layout ? new Rectangle(node.x + padding.left, node.y + padding.top, Math.max(0, node.w - padding.left - padding.right), Math.max(0, node.h - padding.top - padding.bottom)) : new Rectangle(node.x, node.y, node.w, node.h);
ConstraintType type = match.type;
assert type != null;
Rectangle sourceBounds = state.myBounds;
paintConstraint(graphics, type, node, sourceBounds, node, targetBounds, null, /* allConstraints */
true, /* highlightTargetEdge */
state.myTextDirection);
}
use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class ConstraintPainter method paintVerticalConstraint.
/**
* Paints a vertical constraint, handling the various scenarios where there are
* margins, or where the two nodes overlap horizontally and where they don't, etc.
* <p/>
* Here's an example of what will be shown for a "below" constraint where the
* nodes do not overlap horizontally and the target node has a bottom margin:
* <pre>
* +--------+
* | Target |
* +--------+
* |
* v
* - - - - - - - - - - - - - -
* ^
* |
* +--------+
* | Source |
* +--------+
* </pre>
*/
private static void paintVerticalConstraint(NlGraphics graphics, ConstraintType type, NlComponent sourceNode, Rectangle sourceBounds, NlComponent targetNode, Rectangle targetBounds, boolean highlightTargetEdge) {
SegmentType sourceSegmentTypeY = type.sourceSegmentTypeY;
SegmentType targetSegmentTypeY = type.targetSegmentTypeY;
Insets targetMargins = targetNode.getMargins();
assert sourceSegmentTypeY != SegmentType.UNKNOWN;
assert targetBounds != null;
int sourceY = sourceSegmentTypeY.getY(sourceNode, sourceBounds);
int targetY = targetSegmentTypeY == SegmentType.UNKNOWN ? sourceY : targetSegmentTypeY.getY(targetNode, targetBounds);
if (highlightTargetEdge && type.isRelativeToParentEdge()) {
graphics.useStyle(DROP_ZONE_ACTIVE);
graphics.fillRect(targetBounds.x, targetY - PARENT_RECT_SIZE / 2, targetBounds.width, PARENT_RECT_SIZE);
}
// First see if the two views overlap horizontally. If so, we can just draw a direct
// arrow from the source up to (or down to) the target.
//
// +--------+
// | Target |
// +--------+
// ^
// |
// |
// +--------+
// | Source |
// +--------+
//
int maxLeft = Math.max(sourceBounds.x, targetBounds.x);
int minRight = Math.min(x2(sourceBounds), x2(targetBounds));
int center = (maxLeft + minRight) / 2;
if (center > sourceBounds.x && center < x2(sourceBounds)) {
// for small margins
if (targetSegmentTypeY == SegmentType.BOTTOM && targetMargins.bottom > 5) {
int sharedY = targetY + targetMargins.bottom;
if (sourceY > sharedY + 2) {
// Skip when source falls on the margin line
graphics.useStyle(GUIDELINE_DASHED);
graphics.drawLine(targetBounds.x, sharedY, x2(targetBounds), sharedY);
graphics.useStyle(GUIDELINE);
graphics.drawArrow(center, sourceY, center, sharedY + 2);
graphics.drawArrow(center, targetY, center, sharedY - 3);
} else {
graphics.useStyle(GUIDELINE);
// Draw reverse arrow to make it clear the node is as close
// at it can be
graphics.drawArrow(center, targetY, center, sourceY);
}
return;
} else if (targetSegmentTypeY == SegmentType.TOP && targetMargins.top > 5) {
int sharedY = targetY - targetMargins.top;
if (sourceY < sharedY - 2) {
graphics.useStyle(GUIDELINE_DASHED);
graphics.drawLine(targetBounds.x, sharedY, x2(targetBounds), sharedY);
graphics.useStyle(GUIDELINE);
graphics.drawArrow(center, sourceY, center, sharedY - 3);
graphics.drawArrow(center, targetY, center, sharedY + 3);
} else {
graphics.useStyle(GUIDELINE);
graphics.drawArrow(center, targetY, center, sourceY);
}
return;
}
// direction
if (sourceY == targetY) {
if (sourceSegmentTypeY == SegmentType.BOTTOM || sourceSegmentTypeY == SegmentType.BASELINE) {
sourceY -= 2 * ARROW_SIZE;
} else if (sourceSegmentTypeY == SegmentType.TOP) {
sourceY += 2 * ARROW_SIZE;
} else {
assert sourceSegmentTypeY == SegmentType.CENTER_HORIZONTAL : sourceSegmentTypeY;
sourceY += sourceBounds.height / 2 - 2 * ARROW_SIZE;
}
} else if (sourceSegmentTypeY == SegmentType.BASELINE) {
sourceY = targetY - 2 * ARROW_SIZE;
}
// Center the vertical line in the overlap region
graphics.useStyle(GUIDELINE);
graphics.drawArrow(center, sourceY, center, targetY);
return;
}
// If there is no horizontal overlap in the vertical constraints, then we
// will show the attachment relative to a dashed line that extends beyond
// the target bounds, like this:
//
// +--------+
// | Target |
// +--------+ - - - - - - - - -
// ^
// |
// +--------+
// | Source |
// +--------+
//
// However, if the target node has a vertical margin, we may need to offset
// the line:
//
// +--------+
// | Target |
// +--------+
// |
// v
// - - - - - - - - - - - - - -
// ^
// |
// +--------+
// | Source |
// +--------+
//
// If not, we'll need to indicate a shared edge. This is the edge that separate
// them (but this will require me to evaluate margins!)
// Compute overlap region and pick the middle
int sharedY = targetSegmentTypeY == SegmentType.UNKNOWN ? sourceY : targetSegmentTypeY.getY(targetNode, targetBounds);
if (type.relativeToMargin) {
if (targetSegmentTypeY == SegmentType.TOP) {
sharedY -= targetMargins.top;
} else if (targetSegmentTypeY == SegmentType.BOTTOM) {
sharedY += targetMargins.bottom;
}
}
int startX;
int endX;
if (center <= sourceBounds.x) {
startX = targetBounds.x + targetBounds.width / 4;
endX = x2(sourceBounds);
} else {
assert (center >= x2(sourceBounds));
startX = sourceBounds.x;
endX = targetBounds.x + 3 * targetBounds.width / 4;
}
// Must draw segmented line instead
// Place the arrow 1/4 instead of 1/2 in the source to avoid overlapping with the
// selection handles
graphics.useStyle(GUIDELINE_DASHED);
graphics.drawLine(startX, sharedY, endX, sharedY);
// should point directly at the edge
if (Math.abs(sharedY - sourceY) < 2 * ARROW_SIZE) {
if (sourceSegmentTypeY == SegmentType.BASELINE) {
sourceY = sharedY - 2 * ARROW_SIZE;
} else if (sourceSegmentTypeY == SegmentType.TOP) {
sharedY = sourceY;
sourceY = sharedY + 2 * ARROW_SIZE;
} else {
sharedY = sourceY;
sourceY = sharedY - 2 * ARROW_SIZE;
}
}
graphics.useStyle(GUIDELINE);
// Draw the line from the source anchor to the shared edge
int x = sourceBounds.x + ((sourceSegmentTypeY == SegmentType.BASELINE) ? sourceBounds.width / 2 : sourceBounds.width / 4);
graphics.drawArrow(x, sourceY, x, sharedY);
// Draw the line from the target to the horizontal shared edge
int tx = centerX(targetBounds);
if (targetSegmentTypeY == SegmentType.TOP) {
int ty = targetBounds.y;
int margin = targetMargins.top;
if (margin == 0 || !type.relativeToMargin) {
graphics.drawArrow(tx, ty + 2 * ARROW_SIZE, tx, ty);
} else {
graphics.drawArrow(tx, ty, tx, ty - margin);
}
} else if (targetSegmentTypeY == SegmentType.BOTTOM) {
int ty = y2(targetBounds);
int margin = targetMargins.bottom;
if (margin == 0 || !type.relativeToMargin) {
graphics.drawArrow(tx, ty - 2 * ARROW_SIZE, tx, ty);
} else {
graphics.drawArrow(tx, ty, tx, ty + margin);
}
} else {
assert targetSegmentTypeY == SegmentType.BASELINE : targetSegmentTypeY;
int ty = targetSegmentTypeY.getY(targetNode, targetBounds);
graphics.drawArrow(tx, ty - 2 * ARROW_SIZE, tx, ty);
}
}
use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class GuidelineHandler method addBounds.
/**
* Records the matchable outside edges for the given node to the potential match list
*/
protected void addBounds(NlComponent node, String id, boolean addHorizontal, boolean addVertical, boolean includePadding) {
// TODO - inline constants
Rectangle b = new Rectangle(node.x, node.y, node.w, node.h);
Insets m = node.getMargins();
Insets p = includePadding ? node.getPadding() : Insets.NONE;
if (addHorizontal) {
if (m.top != 0) {
myHorizontalEdges.add(new Segment(b.y + p.top, b.x + p.left, x2(b) - p.right, node, id, SegmentType.TOP, WITHOUT_MARGIN));
myHorizontalEdges.add(new Segment(b.y - m.top + p.top, b.x + p.left, x2(b) - p.right, node, id, SegmentType.TOP, WITH_MARGIN));
} else {
myHorizontalEdges.add(new Segment(b.y + p.top, b.x + p.left, x2(b) - p.right, node, id, SegmentType.TOP, NO_MARGIN));
}
if (m.bottom != 0) {
myHorizontalEdges.add(new Segment(y2(b) - p.bottom, b.x + p.left, x2(b) - p.right, node, id, SegmentType.BOTTOM, WITHOUT_MARGIN));
myHorizontalEdges.add(new Segment(y2(b) + m.bottom - p.bottom, b.x + p.left, x2(b) - p.right, node, id, SegmentType.BOTTOM, WITH_MARGIN));
} else {
myHorizontalEdges.add(new Segment(y2(b) - p.bottom, b.x + p.left, x2(b) - p.right, node, id, SegmentType.BOTTOM, NO_MARGIN));
}
}
if (addVertical) {
if (m.left != 0) {
myVerticalEdges.add(new Segment(b.x + p.left, b.y + p.top, y2(b) - p.bottom, node, id, SegmentType.LEFT, WITHOUT_MARGIN));
myVerticalEdges.add(new Segment(b.x - m.left + p.left, b.y + p.top, y2(b) - p.bottom, node, id, SegmentType.LEFT, WITH_MARGIN));
} else {
myVerticalEdges.add(new Segment(b.x + p.left, b.y + p.top, y2(b) - p.bottom, node, id, SegmentType.LEFT, NO_MARGIN));
}
if (m.right != 0) {
myVerticalEdges.add(new Segment(x2(b) - p.right, b.y + p.top, y2(b) - p.bottom, node, id, SegmentType.RIGHT, WITHOUT_MARGIN));
myVerticalEdges.add(new Segment(x2(b) + m.right - p.right, b.y + p.top, y2(b) - p.bottom, node, id, SegmentType.RIGHT, WITH_MARGIN));
} else {
myVerticalEdges.add(new Segment(x2(b) - p.right, b.y + p.top, y2(b) - p.bottom, node, id, SegmentType.RIGHT, NO_MARGIN));
}
}
}
use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class GridInfo method initHorizontalLineLocations.
private void initHorizontalLineLocations() throws NoSuchFieldException, IllegalAccessException {
Insets padding = layout.getPadding();
int[] verticalAxisLocations = getAxisLocations("mVerticalAxis", "verticalAxis");
horizontalLineLocations = initLineLocations(layout.h - padding.height(), size.height, verticalAxisLocations);
translate(horizontalLineLocations, layout.y + padding.top);
}
use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class GridInfo method getSize.
@AndroidCoordinate
private Dimension getSize() {
Dimension size = new Dimension();
if (layout.children != null) {
Insets padding = layout.getPadding();
for (NlComponent child : layout.children) {
size.width = Math.max(child.x - layout.x - padding.left + child.w, size.width);
size.height = Math.max(child.y - layout.y - padding.top + child.h, size.height);
}
}
return size;
}
Aggregations