Search in sources :

Example 1 with Insets

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

Example 2 with Insets

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

Example 3 with Insets

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

Example 4 with Insets

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

Example 5 with Insets

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

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