use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class GuidelinePainter method paint.
public static void paint(@NotNull NlGraphics g, GuidelineHandler myState) {
g.useStyle(DRAGGED);
for (NlComponent dragged : myState.myDraggedNodes) {
if (dragged.w > 0 && dragged.h > 0) {
g.fillRect(dragged.x, dragged.y, dragged.w, dragged.h);
}
}
Set<NlComponent> horizontalDeps = myState.myHorizontalDeps;
Set<NlComponent> verticalDeps = myState.myVerticalDeps;
Set<NlComponent> deps = new HashSet<NlComponent>(horizontalDeps.size() + verticalDeps.size());
deps.addAll(horizontalDeps);
deps.addAll(verticalDeps);
if (deps.size() > 0) {
g.useStyle(DEPENDENCY);
for (NlComponent n : deps) {
// Don't highlight the selected nodes themselves
if (myState.myDraggedNodes.contains(n)) {
continue;
}
g.fillRect(n.x, n.y, n.w, n.h);
}
}
// If the layout has padding applied, draw the padding bounds to make it obvious what the boundaries are
if (!myState.layout.getPadding().isEmpty() || !myState.layout.getMargins().isEmpty()) {
g.useStyle(NlDrawingStyle.PADDING_BOUNDS);
NlComponent layout = myState.layout;
Insets padding = layout.getPadding();
g.drawRect(layout.x + padding.left, layout.y + padding.top, Math.max(0, layout.w - padding.left - padding.right), Math.max(0, layout.h - padding.top - padding.bottom));
}
if (myState.myBounds != null) {
Rectangle bounds = myState.myBounds;
if (myState instanceof RelativeDragHandler) {
g.useStyle(DROP_PREVIEW);
} else {
// Resizing
if (myState.haveSuggestions()) {
g.useStyle(RESIZE_PREVIEW);
} else {
g.useStyle(RESIZE_FAIL);
}
}
g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
// Draw baseline preview too
// TODO: Implement when we have drag information from palette drag previews
//if (myFeedback.dragBaseline != -1) {
// int y = myState.myBounds.y + myFeedback.dragBaseline;
// g.drawLine(myState.myBounds.x, y, myState.myBounds.x + myState.myBounds.width, y);
//}
}
showMatch(g, myState.getCurrentLeftMatch(), myState);
showMatch(g, myState.getCurrentRightMatch(), myState);
showMatch(g, myState.getCurrentTopMatch(), myState);
showMatch(g, myState.getCurrentBottomMatch(), myState);
if (myState.myHorizontalCycle != null) {
paintCycle(myState, g, myState.myHorizontalCycle);
}
if (myState.myVerticalCycle != null) {
paintCycle(myState, g, myState.myVerticalCycle);
}
}
use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class ConstraintPainter method paintHorizontalConstraint.
/**
* Paints a horizontal constraint, handling the various scenarios where there are margins,
* or where the two nodes overlap horizontally and where they don't, etc.
*/
private static void paintHorizontalConstraint(NlGraphics graphics, ConstraintType type, NlComponent sourceNode, Rectangle sourceBounds, NlComponent targetNode, Rectangle targetBounds, boolean highlightTargetEdge, TextDirection textDirection) {
SegmentType sourceSegmentTypeX = type.sourceSegmentTypeX;
SegmentType targetSegmentTypeX = type.targetSegmentTypeX;
Insets targetMargins = targetNode.getMargins();
assert sourceSegmentTypeX != SegmentType.UNKNOWN;
assert targetBounds != null;
// See paintVerticalConstraint for explanations of the various cases.
int sourceX = sourceSegmentTypeX.getX(textDirection, sourceNode, sourceBounds);
int targetX = targetSegmentTypeX == SegmentType.UNKNOWN ? sourceX : targetSegmentTypeX.getX(textDirection, targetNode, targetBounds);
if (highlightTargetEdge && type.isRelativeToParentEdge()) {
graphics.useStyle(DROP_ZONE_ACTIVE);
graphics.fillRect(targetX - PARENT_RECT_SIZE / 2, targetBounds.y, PARENT_RECT_SIZE, targetBounds.height);
}
int maxTop = Math.max(sourceBounds.y, targetBounds.y);
int minBottom = Math.min(y2(sourceBounds), y2(targetBounds));
// First see if the two views overlap vertically. If so, we can just draw a direct
// arrow from the source over to the target.
int center = (maxTop + minBottom) / 2;
if (center > sourceBounds.y && center < y2(sourceBounds)) {
// See if we should draw a margin line
if (textDirection.isRightSegment(targetSegmentTypeX) && targetMargins.right > 5) {
int sharedX = targetX + targetMargins.right;
if (sourceX > sharedX + 2) {
// Skip when source falls on the margin line
graphics.useStyle(GUIDELINE_DASHED);
graphics.drawLine(sharedX, targetBounds.y, sharedX, y2(targetBounds));
graphics.useStyle(GUIDELINE);
graphics.drawArrow(sourceX, center, sharedX + 2, center);
graphics.drawArrow(targetX, center, sharedX - 3, center);
} else {
graphics.useStyle(GUIDELINE);
// Draw reverse arrow to make it clear the node is as close
// at it can be
graphics.drawArrow(targetX, center, sourceX, center);
}
return;
} else if (textDirection.isLeftSegment(targetSegmentTypeX) && targetMargins.left > 5) {
int sharedX = targetX - targetMargins.left;
if (sourceX < sharedX - 2) {
graphics.useStyle(GUIDELINE_DASHED);
graphics.drawLine(sharedX, targetBounds.y, sharedX, y2(targetBounds));
graphics.useStyle(GUIDELINE);
graphics.drawArrow(sourceX, center, sharedX - 3, center);
graphics.drawArrow(targetX, center, sharedX + 3, center);
} else {
graphics.useStyle(GUIDELINE);
graphics.drawArrow(targetX, center, sourceX, center);
}
return;
}
if (sourceX == targetX) {
if (textDirection.isRightSegment(sourceSegmentTypeX)) {
sourceX -= 2 * ARROW_SIZE;
} else if (textDirection.isLeftSegment(sourceSegmentTypeX)) {
sourceX += 2 * ARROW_SIZE;
} else {
assert sourceSegmentTypeX == SegmentType.CENTER_VERTICAL : sourceSegmentTypeX;
sourceX += sourceBounds.width / 2 - 2 * ARROW_SIZE;
}
}
graphics.useStyle(GUIDELINE);
graphics.drawArrow(sourceX, center, targetX, center);
return;
}
// Segment line
// Compute overlap region and pick the middle
int sharedX = targetSegmentTypeX == SegmentType.UNKNOWN ? sourceX : targetSegmentTypeX.getX(textDirection, targetNode, targetBounds);
if (type.relativeToMargin) {
if (textDirection.isLeftSegment(targetSegmentTypeX)) {
sharedX -= targetMargins.left;
} else if (textDirection.isRightSegment(targetSegmentTypeX)) {
sharedX += targetMargins.right;
}
}
int startY, endY;
if (center <= sourceBounds.y) {
startY = targetBounds.y + targetBounds.height / 4;
endY = y2(sourceBounds);
} else {
assert (center >= y2(sourceBounds));
startY = sourceBounds.y;
endY = targetBounds.y + 3 * targetBounds.height / 2;
}
// Must draw segmented line instead
// Place at 1/4 instead of 1/2 to avoid overlapping with selection handles
int y = sourceBounds.y + sourceBounds.height / 4;
graphics.useStyle(GUIDELINE_DASHED);
graphics.drawLine(sharedX, startY, sharedX, endY);
// should point directly at the edge
if (Math.abs(sharedX - sourceX) < 2 * ARROW_SIZE) {
if (textDirection.isLeftSegment(sourceSegmentTypeX)) {
sharedX = sourceX;
sourceX = sharedX + 2 * ARROW_SIZE;
} else {
sharedX = sourceX;
sourceX = sharedX - 2 * ARROW_SIZE;
}
}
graphics.useStyle(GUIDELINE);
// Draw the line from the source anchor to the shared edge
graphics.drawArrow(sourceX, y, sharedX, y);
// Draw the line from the target to the horizontal shared edge
int ty = centerY(targetBounds);
if (textDirection.isLeftSegment(targetSegmentTypeX)) {
int tx = targetBounds.x;
int margin = targetMargins.left;
if (margin == 0 || !type.relativeToMargin) {
graphics.drawArrow(tx + 2 * ARROW_SIZE, ty, tx, ty);
} else {
graphics.drawArrow(tx, ty, tx - margin, ty);
}
} else {
assert textDirection.isRightSegment(targetSegmentTypeX);
int tx = x2(targetBounds);
int margin = targetMargins.right;
if (margin == 0 || !type.relativeToMargin) {
graphics.drawArrow(tx - 2 * ARROW_SIZE, ty, tx, ty);
} else {
graphics.drawArrow(tx, ty, tx + margin, ty);
}
}
}
use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class GridInfo method initVerticalLineLocations.
private void initVerticalLineLocations() throws NoSuchFieldException, IllegalAccessException {
Insets padding = layout.getPadding();
int[] horizontalAxisLocations = getAxisLocations("mHorizontalAxis", "horizontalAxis");
verticalLineLocations = initLineLocations(layout.w - padding.width(), size.width, horizontalAxisLocations);
translate(verticalLineLocations, layout.x + padding.left);
}
use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class GridDragHandler method paint.
@Override
public void paint(@NotNull NlGraphics graphics) {
Insets padding = layout.getPadding();
int layoutX1 = layout.x + padding.left;
int layoutY1 = layout.y + padding.top;
int layoutX2 = layout.x + padding.left + layout.w - padding.width() - 1;
int layoutY2 = layout.y + padding.top + layout.h - padding.height() - 1;
graphics.useStyle(NlDrawingStyle.DROP_ZONE);
for (int x : info.getVerticalLineLocations()) {
graphics.drawLine(x, layoutY1, x, layoutY2);
}
for (int y : info.getHorizontalLineLocations()) {
graphics.drawLine(layoutX1, y, layoutX2, y);
}
graphics.useStyle(NlDrawingStyle.DROP_RECIPIENT);
graphics.drawRect(layoutX1, layoutY1, layout.w - padding.width(), layout.h - padding.height());
graphics.useStyle(info.cellHasChild(row, column) ? NlDrawingStyle.INVALID : NlDrawingStyle.DROP_ZONE_ACTIVE);
Rectangle rectangle = getActiveDropZoneRectangle();
graphics.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
}
use of com.android.tools.idea.uibuilder.model.Insets in project android by JetBrains.
the class ConstraintModel method updateConstraintLayoutRoots.
/**
* Traverse the hierarchy to find all ConstraintLayout instances
* and update them. We set all the wrap_content sizes of the ConstraintLayout children
* from layout lib
* @param container
*
*/
private void updateConstraintLayoutRoots(WidgetContainer container) {
if (container == null) {
return;
}
Map<NlComponent, Dimension> wrapContentSizes = Maps.newHashMap();
if (container instanceof ConstraintWidgetContainer) {
NlComponent component = (NlComponent) ((WidgetCompanion) container.getCompanionWidget()).getWidgetModel();
Insets padding = component.getPadding(true);
container.setDimension(pxToDp(component.w - padding.width()), pxToDp(component.h - padding.height()));
int x = pxToDp(component.x);
int y = pxToDp(component.y);
x += pxToDp(padding.left);
y += pxToDp(padding.top);
WidgetContainer parentContainer = (WidgetContainer) container.getParent();
if (parentContainer != null) {
if (!(parentContainer instanceof ConstraintWidgetContainer)) {
x = pxToDp(component.x - component.getParent().x);
y = pxToDp(component.y - component.getParent().y);
} else {
x -= parentContainer.getDrawX();
y -= parentContainer.getDrawY();
}
}
if (container.getX() != x || container.getY() != y) {
container.setOrigin(x, y);
container.forceUpdateDrawPosition();
}
}
if (!(container instanceof ConstraintWidgetContainer)) {
NlComponent component = (NlComponent) ((WidgetCompanion) container.getCompanionWidget()).getWidgetModel();
container.setDimension(pxToDp(component.w), pxToDp(component.h));
}
if (container instanceof ConstraintWidgetContainer && container.getChildren().size() > 0) {
NlComponent root = (NlComponent) ((WidgetCompanion) container.getCompanionWidget()).getWidgetModel();
XmlTag parentTag = root.getTag();
if (parentTag.isValid()) {
Map<XmlTag, NlComponent> tagToComponent = Maps.newHashMapWithExpectedSize(root.getChildCount());
for (NlComponent child : root.getChildren()) {
tagToComponent.put(child.getTag(), child);
}
XmlFile xmlFile = myNlModel.getFile();
AndroidFacet facet = myNlModel.getFacet();
RenderService renderService = RenderService.get(facet);
RenderLogger logger = renderService.createLogger();
final RenderTask task = renderService.createTask(xmlFile, myNlModel.getConfiguration(), logger, null);
if (task != null) {
// Measure wrap_content bounds
Map<XmlTag, ViewInfo> map = task.measureChildren(parentTag, new RenderTask.AttributeFilter() {
@Override
public String getAttribute(@NotNull XmlTag n, @Nullable String namespace, @NotNull String localName) {
// Change attributes to wrap_content
if (ATTR_LAYOUT_WIDTH.equals(localName) && ANDROID_URI.equals(namespace)) {
return VALUE_WRAP_CONTENT;
}
if (ATTR_LAYOUT_HEIGHT.equals(localName) && ANDROID_URI.equals(namespace)) {
return VALUE_WRAP_CONTENT;
}
return null;
}
});
task.dispose();
if (map != null) {
for (Map.Entry<XmlTag, ViewInfo> entry : map.entrySet()) {
ViewInfo viewInfo = entry.getValue();
viewInfo = RenderService.getSafeBounds(viewInfo);
Dimension size = new Dimension(viewInfo.getRight() - viewInfo.getLeft(), viewInfo.getBottom() - viewInfo.getTop());
NlComponent child = tagToComponent.get(entry.getKey());
if (child != null) {
wrapContentSizes.put(child, size);
}
}
}
}
}
}
for (ConstraintWidget child : container.getChildren()) {
NlComponent component = (NlComponent) ((WidgetCompanion) child.getCompanionWidget()).getWidgetModel();
Dimension dimension = wrapContentSizes.get(component);
if (dimension != null) {
child.setWrapWidth(pxToDp((int) dimension.getWidth()));
child.setWrapHeight(pxToDp((int) dimension.getHeight()));
}
if (child instanceof WidgetContainer) {
updateConstraintLayoutRoots((WidgetContainer) child);
}
}
}
Aggregations