Search in sources :

Example 6 with Insets

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);
    }
}
Also used : Insets(com.android.tools.idea.uibuilder.model.Insets) NlComponent(com.android.tools.idea.uibuilder.model.NlComponent) HashSet(java.util.HashSet)

Example 7 with Insets

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);
        }
    }
}
Also used : SegmentType(com.android.tools.idea.uibuilder.model.SegmentType) Insets(com.android.tools.idea.uibuilder.model.Insets)

Example 8 with Insets

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);
}
Also used : Insets(com.android.tools.idea.uibuilder.model.Insets)

Example 9 with Insets

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);
}
Also used : Insets(com.android.tools.idea.uibuilder.model.Insets)

Example 10 with Insets

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);
        }
    }
}
Also used : Insets(com.android.tools.idea.uibuilder.model.Insets) RenderLogger(com.android.tools.idea.rendering.RenderLogger) XmlFile(com.intellij.psi.xml.XmlFile) RenderTask(com.android.tools.idea.rendering.RenderTask) AndroidFacet(org.jetbrains.android.facet.AndroidFacet) ViewInfo(com.android.ide.common.rendering.api.ViewInfo) RenderService(com.android.tools.idea.rendering.RenderService) Map(java.util.Map) WeakHashMap(com.intellij.util.containers.WeakHashMap) XmlTag(com.intellij.psi.xml.XmlTag)

Aggregations

Insets (com.android.tools.idea.uibuilder.model.Insets)10 NlComponent (com.android.tools.idea.uibuilder.model.NlComponent)3 SegmentType (com.android.tools.idea.uibuilder.model.SegmentType)2 ViewInfo (com.android.ide.common.rendering.api.ViewInfo)1 RenderLogger (com.android.tools.idea.rendering.RenderLogger)1 RenderService (com.android.tools.idea.rendering.RenderService)1 RenderTask (com.android.tools.idea.rendering.RenderTask)1 AndroidCoordinate (com.android.tools.idea.uibuilder.model.AndroidCoordinate)1 XmlFile (com.intellij.psi.xml.XmlFile)1 XmlTag (com.intellij.psi.xml.XmlTag)1 WeakHashMap (com.intellij.util.containers.WeakHashMap)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1 AndroidFacet (org.jetbrains.android.facet.AndroidFacet)1