/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.eclipse.org/org/documents/epl-v10.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.ide.common.layout.relative;

import static com.android.ide.common.api.DrawingStyle.DEPENDENCY;
import static com.android.ide.common.api.DrawingStyle.GUIDELINE;
import static com.android.ide.common.api.DrawingStyle.GUIDELINE_DASHED;
import static com.android.ide.common.api.SegmentType.BASELINE;
import static com.android.ide.common.api.SegmentType.BOTTOM;
import static com.android.ide.common.api.SegmentType.CENTER_HORIZONTAL;
import static com.android.ide.common.api.SegmentType.CENTER_VERTICAL;
import static com.android.ide.common.api.SegmentType.LEFT;
import static com.android.ide.common.api.SegmentType.RIGHT;
import static com.android.ide.common.api.SegmentType.TOP;
import static com.android.ide.common.api.SegmentType.UNKNOWN;
import static com.android.ide.common.layout.relative.ConstraintType.ALIGN_BASELINE;
import static com.android.ide.common.layout.relative.ConstraintType.ALIGN_BOTTOM;
import static com.android.ide.common.layout.relative.ConstraintType.LAYOUT_ABOVE;
import static com.android.ide.common.layout.relative.ConstraintType.LAYOUT_BELOW;
import static com.android.ide.common.layout.relative.ConstraintType.LAYOUT_LEFT_OF;
import static com.android.ide.common.layout.relative.ConstraintType.LAYOUT_RIGHT_OF;

import com.android.ide.common.api.DrawingStyle;
import com.android.ide.common.api.IGraphics;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.Margins;
import com.android.ide.common.api.Rect;
import com.android.ide.common.api.SegmentType;
import com.android.ide.common.layout.relative.DependencyGraph.Constraint;
import com.android.ide.common.layout.relative.DependencyGraph.ViewData;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * The {@link ConstraintPainter} is responsible for painting relative layout constraints -
 * such as a source node having its top edge constrained to a target node with a given margin.
 * This painter is used both to show static constraints, as well as visualizing proposed
 * constraints during a move or resize operation.
 */
public class ConstraintPainter {
    /** The size of the arrow head */
    private static final int ARROW_SIZE = 5;
    /** Size (height for horizontal, and width for vertical) parent feedback rectangles */
    private static final int PARENT_RECT_SIZE = 12;

    /**
     * Paints a given match as a constraint.
     *
     * @param graphics the graphics context
     * @param sourceBounds the source bounds
     * @param match the match
     */
    static void paintConstraint(IGraphics graphics, Rect sourceBounds, Match match) {
        Rect targetBounds = match.edge.node.getBounds();
        ConstraintType type = match.type;
        assert type != null;
        paintConstraint(graphics, type, match.with.node, sourceBounds, match.edge.node,
                targetBounds, null /* allConstraints */, true /* highlightTargetEdge */);
    }

    /**
     * Paints a constraint.
     * <p>
     * TODO: when there are multiple links originating in the same direction from
     * center, maybe offset them slightly from each other?
     *
     * @param graphics the graphics context to draw into
     * @param constraint The constraint to be drawn
     */
    private static void paintConstraint(IGraphics graphics, Constraint constraint,
            Set<Constraint> allConstraints) {
        ViewData source = constraint.from;
        ViewData target = constraint.to;

        INode sourceNode = source.node;
        INode targetNode = target.node;
        if (sourceNode == targetNode) {
            // Self reference - don't visualize
            return;
        }

        Rect sourceBounds = sourceNode.getBounds();
        Rect targetBounds = targetNode.getBounds();
        paintConstraint(graphics, constraint.type, sourceNode, sourceBounds, targetNode,
                targetBounds, allConstraints, false /* highlightTargetEdge */);
    }

    /**
     * Paint selection feedback by painting constraints for the selected nodes
     *
     * @param graphics the graphics context
     * @param parentNode the parent relative layout
     * @param childNodes the nodes whose constraints should be painted
     * @param showDependents whether incoming constraints should be shown as well
     */
    public static void paintSelectionFeedback(IGraphics graphics, INode parentNode,
            List<? extends INode> childNodes, boolean showDependents) {

        DependencyGraph dependencyGraph = new DependencyGraph(parentNode);
        Set<INode> horizontalDeps = dependencyGraph.dependsOn(childNodes, false /* vertical */);
        Set<INode> verticalDeps = dependencyGraph.dependsOn(childNodes, true /* vertical */);
        Set<INode> deps = new HashSet<INode>(horizontalDeps.size() + verticalDeps.size());
        deps.addAll(horizontalDeps);
        deps.addAll(verticalDeps);
        if (deps.size() > 0) {
            graphics.useStyle(DEPENDENCY);
            for (INode node : deps) {
                // Don't highlight the selected nodes themselves
                if (childNodes.contains(node)) {
                    continue;
                }
                Rect bounds = node.getBounds();
                graphics.fillRect(bounds);
            }
        }

        graphics.useStyle(GUIDELINE);
        for (INode childNode : childNodes) {
            ViewData view = dependencyGraph.getView(childNode);
            if (view == null) {
                continue;
            }

            // Paint all incoming constraints
            if (showDependents) {
                paintConstraints(graphics, view.dependedOnBy);
            }

            // Paint all outgoing constraints
            paintConstraints(graphics, view.dependsOn);
        }
    }

    /**
     * Paints a set of constraints.
     */
    private static void paintConstraints(IGraphics graphics, List<Constraint> constraints) {
        Set<Constraint> mutableConstraintSet = new HashSet<Constraint>(constraints);

        // WORKAROUND! Hide alignBottom attachments if we also have a alignBaseline
        // constraint; this is because we also *add* alignBottom attachments when you add
        // alignBaseline constraints to work around a surprising behavior of baseline
        // constraints.
        for (Constraint constraint : constraints) {
            if (constraint.type == ALIGN_BASELINE) {
                // Remove any baseline
                for (Constraint c : constraints) {
                    if (c.type == ALIGN_BOTTOM && c.to.node == constraint.to.node) {
                        mutableConstraintSet.remove(c);
                    }
                }
            }
        }

        for (Constraint constraint : constraints) {
            // paintConstraint can digest more than one constraint, so we need to keep
            // checking to see if the given constraint is still relevant.
            if (mutableConstraintSet.contains(constraint)) {
                paintConstraint(graphics, constraint, mutableConstraintSet);
            }
        }
    }

    /**
     * Paints a constraint of the given type from the given source node, to the
     * given target node, with the specified bounds.
     */
    private static void paintConstraint(IGraphics graphics, ConstraintType type, INode sourceNode,
            Rect sourceBounds, INode targetNode, Rect targetBounds,
            Set<Constraint> allConstraints, boolean highlightTargetEdge) {

        SegmentType sourceSegmentTypeX = type.sourceSegmentTypeX;
        SegmentType sourceSegmentTypeY = type.sourceSegmentTypeY;
        SegmentType targetSegmentTypeX = type.targetSegmentTypeX;
        SegmentType targetSegmentTypeY = type.targetSegmentTypeY;

        // Horizontal center constraint?
        if (sourceSegmentTypeX == CENTER_VERTICAL && targetSegmentTypeX == CENTER_VERTICAL) {
            paintHorizontalCenterConstraint(graphics, sourceBounds, targetBounds);
            return;
        }

        // Vertical center constraint?
        if (sourceSegmentTypeY == CENTER_HORIZONTAL && targetSegmentTypeY == CENTER_HORIZONTAL) {
            paintVerticalCenterConstraint(graphics, sourceBounds, targetBounds);
            return;
        }

        // Corner constraint?
        if (allConstraints != null
                && (type == LAYOUT_ABOVE || type == LAYOUT_BELOW
                        || type == LAYOUT_LEFT_OF || type == LAYOUT_RIGHT_OF)) {
            if (paintCornerConstraint(graphics, type, sourceNode, sourceBounds, targetNode,
                    targetBounds, allConstraints)) {
                return;
            }
        }

        // Vertical constraint?
        if (sourceSegmentTypeX == UNKNOWN) {
            paintVerticalConstraint(graphics, type, sourceNode, sourceBounds, targetNode,
                    targetBounds, highlightTargetEdge);
            return;
        }

        // Horizontal constraint?
        if (sourceSegmentTypeY == UNKNOWN) {
            paintHorizontalConstraint(graphics, type, sourceNode, sourceBounds, targetNode,
                    targetBounds, highlightTargetEdge);
            return;
        }

        // This shouldn't happen - it means we have a constraint that defines all sides
        // and is not a centering constraint
        assert false;
    }

    /**
     * Paints a corner constraint, or returns false if this constraint is not a corner.
     * A corner is one where there are two constraints from this source node to the
     * same target node, one horizontal and one vertical, to the closest edges on
     * the target node.
     * <p>
     * Corners are a common occurrence. If we treat the horizontal and vertical
     * constraints separately (below & toRightOf), then we end up with a lot of
     * extra lines and arrows -- e.g. two shared edges and arrows pointing to these
     * shared edges:
     *
     * <pre>
     *  +--------+ |
     *  | Target -->
     *  +----|---+ |
     *       v
     *  - - - - - -|- - - - - -
     *                   ^
     *             | +---|----+
     *             <-- Source |
     *             | +--------+
     *
     * Instead, we can simply draw a diagonal arrow here to represent BOTH constraints and
     * reduce clutter:
     *
     *  +---------+
     *  | Target _|
     *  +-------|\+
     *            \
     *             \--------+
     *             | Source |
     *             +--------+
     * </pre>
     *
     * @param graphics the graphics context to draw
     * @param type the constraint to be drawn
     * @param sourceNode the source node
     * @param sourceBounds the bounds of the source node
     * @param targetNode the target node
     * @param targetBounds the bounds of the target node
     * @param allConstraints the set of all constraints; if a corner is found and painted the
     *    matching corner constraint is removed from the set
     * @return true if the constraint was handled and painted as a corner, false otherwise
     */
    private static boolean paintCornerConstraint(IGraphics graphics, ConstraintType type,
            INode sourceNode, Rect sourceBounds, INode targetNode, Rect targetBounds,
            Set<Constraint> allConstraints) {

        SegmentType sourceSegmentTypeX = type.sourceSegmentTypeX;
        SegmentType sourceSegmentTypeY = type.sourceSegmentTypeY;
        SegmentType targetSegmentTypeX = type.targetSegmentTypeX;
        SegmentType targetSegmentTypeY = type.targetSegmentTypeY;

        ConstraintType opposite1 = null, opposite2 = null;
        switch (type) {
            case LAYOUT_BELOW:
            case LAYOUT_ABOVE:
                opposite1 = LAYOUT_LEFT_OF;
                opposite2 = LAYOUT_RIGHT_OF;
                break;
            case LAYOUT_LEFT_OF:
            case LAYOUT_RIGHT_OF:
                opposite1 = LAYOUT_ABOVE;
                opposite2 = LAYOUT_BELOW;
                break;
            default:
                return false;
        }
        Constraint pair = null;
        for (Constraint constraint : allConstraints) {
            if ((constraint.type == opposite1 || constraint.type == opposite2) &&
                    constraint.to.node == targetNode && constraint.from.node == sourceNode) {
                pair = constraint;
                break;
            }
        }

        // TODO -- ensure that the nodes are adjacent! In other words, that
        // their bounds are within N pixels.

        if (pair != null) {
            // Visualize the corner constraint
            if (sourceSegmentTypeX == UNKNOWN) {
                sourceSegmentTypeX = pair.type.sourceSegmentTypeX;
            }
            if (sourceSegmentTypeY == UNKNOWN) {
                sourceSegmentTypeY = pair.type.sourceSegmentTypeY;
            }
            if (targetSegmentTypeX == UNKNOWN) {
                targetSegmentTypeX = pair.type.targetSegmentTypeX;
            }
            if (targetSegmentTypeY == UNKNOWN) {
                targetSegmentTypeY = pair.type.targetSegmentTypeY;
            }

            int x1, y1, x2, y2;
            if (sourceSegmentTypeX == LEFT) {
                x1 = sourceBounds.x + 1 * sourceBounds.w / 4;
            } else {
                x1 = sourceBounds.x + 3 * sourceBounds.w / 4;
            }
            if (sourceSegmentTypeY == TOP) {
                y1 = sourceBounds.y + 1 * sourceBounds.h / 4;
            } else {
                y1 = sourceBounds.y + 3 * sourceBounds.h / 4;
            }
            if (targetSegmentTypeX == LEFT) {
                x2 = targetBounds.x + 1 * targetBounds.w / 4;
            } else {
                x2 = targetBounds.x + 3 * targetBounds.w / 4;
            }
            if (targetSegmentTypeY == TOP) {
                y2 = targetBounds.y + 1 * targetBounds.h / 4;
            } else {
                y2 = targetBounds.y + 3 * targetBounds.h / 4;
            }

            graphics.useStyle(GUIDELINE);
            graphics.drawArrow(x1, y1, x2, y2, ARROW_SIZE);

            // Don't process this constraint on its own later.
            allConstraints.remove(pair);

            return true;
        }

        return false;
    }

    /**
     * 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(IGraphics graphics, ConstraintType type,
            INode sourceNode, Rect sourceBounds, INode targetNode, Rect targetBounds,
            boolean highlightTargetEdge) {
        SegmentType sourceSegmentTypeY = type.sourceSegmentTypeY;
        SegmentType targetSegmentTypeY = type.targetSegmentTypeY;
        Margins targetMargins = targetNode.getMargins();

        assert sourceSegmentTypeY != UNKNOWN;
        assert targetBounds != null;

        int sourceY = sourceSegmentTypeY.getY(sourceNode, sourceBounds);
        int targetY = targetSegmentTypeY ==
            UNKNOWN ? sourceY : targetSegmentTypeY.getY(targetNode, targetBounds);

        if (highlightTargetEdge && type.isRelativeToParentEdge()) {
            graphics.useStyle(DrawingStyle.DROP_ZONE_ACTIVE);
            graphics.fillRect(targetBounds.x, targetY - PARENT_RECT_SIZE / 2,
                    targetBounds.x2(), targetY + PARENT_RECT_SIZE / 2);
        }

        // 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(sourceBounds.x2(), targetBounds.x2());

        int center = (maxLeft + minRight) / 2;
        if (center > sourceBounds.x && center < sourceBounds.x2()) {
            // Yes, the lines overlap -- just draw a straight arrow
            //
            //
            // If however there is a margin on the target edge, it should be drawn like this:
            //
            //  +--------+
            //  | Target |
            //  +--------+
            //         |
            //         |
            //         v
            //   - - - - - - -
            //         ^
            //         |
            //         |
            //       +--------+
            //       | Source |
            //       +--------+
            //
            // Use a minimum threshold for this visualization since it doesn't look good
            // for small margins
            if (targetSegmentTypeY == 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, targetBounds.x2(), sharedY);
                    graphics.useStyle(GUIDELINE);
                    graphics.drawArrow(center, sourceY, center, sharedY + 2, ARROW_SIZE);
                    graphics.drawArrow(center, targetY, center, sharedY - 3, ARROW_SIZE);
                } 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, ARROW_SIZE);
                }
                return;
            } else if (targetSegmentTypeY == TOP && targetMargins.top > 5) {
                int sharedY = targetY - targetMargins.top;
                if (sourceY < sharedY - 2) {
                    graphics.useStyle(GUIDELINE_DASHED);
                    graphics.drawLine(targetBounds.x, sharedY, targetBounds.x2(), sharedY);
                    graphics.useStyle(GUIDELINE);
                    graphics.drawArrow(center, sourceY, center, sharedY - 3, ARROW_SIZE);
                    graphics.drawArrow(center, targetY, center, sharedY + 3, ARROW_SIZE);
                } else {
                    graphics.useStyle(GUIDELINE);
                    graphics.drawArrow(center, targetY, center, sourceY, ARROW_SIZE);
                }
                return;
            }

            // TODO: If the center falls smack in the center of the sourceBounds,
            // AND the source node is part of the selection, then adjust the
            // center location such that it is off to the side, let's say 1/4 or 3/4 of
            // the overlap region, to ensure that it does not overlap the center selection
            // handle

            // When the constraint is for two immediately adjacent edges, we
            // need to make some adjustments to make sure the arrow points in the right
            // direction
            if (sourceY == targetY) {
                if (sourceSegmentTypeY == BOTTOM || sourceSegmentTypeY == BASELINE) {
                    sourceY -= 2 * ARROW_SIZE;
                } else if (sourceSegmentTypeY == TOP) {
                    sourceY += 2 * ARROW_SIZE;
                } else {
                    assert sourceSegmentTypeY == CENTER_HORIZONTAL : sourceSegmentTypeY;
                    sourceY += sourceBounds.h / 2 - 2 * ARROW_SIZE;
                }
            } else if (sourceSegmentTypeY == BASELINE) {
                sourceY = targetY - 2 * ARROW_SIZE;
            }

            // Center the vertical line in the overlap region
            graphics.useStyle(GUIDELINE);
            graphics.drawArrow(center, sourceY, center, targetY, ARROW_SIZE);

            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 ==
            UNKNOWN ? sourceY : targetSegmentTypeY.getY(targetNode, targetBounds);
        if (type.relativeToMargin) {
            if (targetSegmentTypeY == TOP) {
                sharedY -= targetMargins.top;
            } else if (targetSegmentTypeY == BOTTOM) {
                sharedY += targetMargins.bottom;
            }
        }

        int startX;
        int endX;
        if (center <= sourceBounds.x) {
            startX = targetBounds.x + targetBounds.w / 4;
            endX = sourceBounds.x2();
        } else {
            assert (center >= sourceBounds.x2());
            startX = sourceBounds.x;
            endX = targetBounds.x + 3 * targetBounds.w / 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);

        // Adjust position of source arrow such that it does not sit across edge; it
        // should point directly at the edge
        if (Math.abs(sharedY - sourceY) < 2 * ARROW_SIZE) {
            if (sourceSegmentTypeY == BASELINE) {
                sourceY = sharedY - 2 * ARROW_SIZE;
            } else if (sourceSegmentTypeY == 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 == BASELINE) ?
                sourceBounds.w / 2 :  sourceBounds.w / 4);
        graphics.drawArrow(x, sourceY, x, sharedY, ARROW_SIZE);

        // Draw the line from the target to the horizontal shared edge
        int tx = targetBounds.centerX();
        if (targetSegmentTypeY == TOP) {
            int ty = targetBounds.y;
            int margin = targetMargins.top;
            if (margin == 0 || !type.relativeToMargin) {
                graphics.drawArrow(tx, ty + 2 * ARROW_SIZE, tx, ty, ARROW_SIZE);
            } else {
                graphics.drawArrow(tx, ty, tx, ty - margin, ARROW_SIZE);
            }
        } else if (targetSegmentTypeY == BOTTOM) {
            int ty = targetBounds.y2();
            int margin = targetMargins.bottom;
            if (margin == 0 || !type.relativeToMargin) {
                graphics.drawArrow(tx, ty - 2 * ARROW_SIZE, tx, ty, ARROW_SIZE);
            } else {
                graphics.drawArrow(tx, ty, tx, ty + margin, ARROW_SIZE);
            }
        } else {
            assert targetSegmentTypeY == BASELINE : targetSegmentTypeY;
            int ty = targetSegmentTypeY.getY(targetNode, targetBounds);
            graphics.drawArrow(tx, ty - 2 * ARROW_SIZE, tx, ty, ARROW_SIZE);
        }

        return;
    }

    /**
     * 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(IGraphics graphics, ConstraintType type,
            INode sourceNode, Rect sourceBounds, INode targetNode, Rect targetBounds,
            boolean highlightTargetEdge) {
        SegmentType sourceSegmentTypeX = type.sourceSegmentTypeX;
        SegmentType targetSegmentTypeX = type.targetSegmentTypeX;
        Margins targetMargins = targetNode.getMargins();

        assert sourceSegmentTypeX != UNKNOWN;
        assert targetBounds != null;

        // See paintVerticalConstraint for explanations of the various cases.

        int sourceX = sourceSegmentTypeX.getX(sourceNode, sourceBounds);
        int targetX = targetSegmentTypeX == UNKNOWN ?
                sourceX : targetSegmentTypeX.getX(targetNode, targetBounds);

        if (highlightTargetEdge && type.isRelativeToParentEdge()) {
            graphics.useStyle(DrawingStyle.DROP_ZONE_ACTIVE);
            graphics.fillRect(targetX - PARENT_RECT_SIZE / 2, targetBounds.y,
                    targetX + PARENT_RECT_SIZE / 2, targetBounds.y2());
        }

        int maxTop = Math.max(sourceBounds.y, targetBounds.y);
        int minBottom = Math.min(sourceBounds.y2(), targetBounds.y2());

        // 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 < sourceBounds.y2()) {
            // See if we should draw a margin line
            if (targetSegmentTypeX == RIGHT && 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, targetBounds.y2());
                    graphics.useStyle(GUIDELINE);
                    graphics.drawArrow(sourceX, center, sharedX + 2, center, ARROW_SIZE);
                    graphics.drawArrow(targetX, center, sharedX - 3, center, ARROW_SIZE);
                } 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, ARROW_SIZE);
                }
                return;
            } else if (targetSegmentTypeX == LEFT && targetMargins.left > 5) {
                int sharedX = targetX - targetMargins.left;
                if (sourceX < sharedX - 2) {
                    graphics.useStyle(GUIDELINE_DASHED);
                    graphics.drawLine(sharedX, targetBounds.y, sharedX, targetBounds.y2());
                    graphics.useStyle(GUIDELINE);
                    graphics.drawArrow(sourceX, center, sharedX - 3, center, ARROW_SIZE);
                    graphics.drawArrow(targetX, center, sharedX + 3, center, ARROW_SIZE);
                } else {
                    graphics.useStyle(GUIDELINE);
                    graphics.drawArrow(targetX, center, sourceX, center, ARROW_SIZE);
                }
                return;
            }

            if (sourceX == targetX) {
                if (sourceSegmentTypeX == RIGHT) {
                    sourceX -= 2 * ARROW_SIZE;
                } else if (sourceSegmentTypeX == LEFT ) {
                    sourceX += 2 * ARROW_SIZE;
                } else {
                    assert sourceSegmentTypeX == CENTER_VERTICAL : sourceSegmentTypeX;
                    sourceX += sourceBounds.w / 2 - 2 * ARROW_SIZE;
                }
            }

            graphics.useStyle(GUIDELINE);
            graphics.drawArrow(sourceX, center, targetX, center, ARROW_SIZE);
            return;
        }

        // Segment line

        // Compute overlap region and pick the middle
        int sharedX = targetSegmentTypeX == UNKNOWN ?
                sourceX : targetSegmentTypeX.getX(targetNode, targetBounds);
        if (type.relativeToMargin) {
            if (targetSegmentTypeX == LEFT) {
                sharedX -= targetMargins.left;
            } else if (targetSegmentTypeX == RIGHT) {
                sharedX += targetMargins.right;
            }
        }

        int startY, endY;
        if (center <= sourceBounds.y) {
            startY = targetBounds.y + targetBounds.h / 4;
            endY = sourceBounds.y2();
        } else {
            assert (center >= sourceBounds.y2());
            startY = sourceBounds.y;
            endY = targetBounds.y + 3 * targetBounds.h / 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.h / 4;
        graphics.useStyle(GUIDELINE_DASHED);
        graphics.drawLine(sharedX, startY, sharedX, endY);

        // Adjust position of source arrow such that it does not sit across edge; it
        // should point directly at the edge
        if (Math.abs(sharedX - sourceX) < 2 * ARROW_SIZE) {
            if (sourceSegmentTypeX == LEFT) {
                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, ARROW_SIZE);

        // Draw the line from the target to the horizontal shared edge
        int ty = targetBounds.centerY();
        if (targetSegmentTypeX == LEFT) {
            int tx = targetBounds.x;
            int margin = targetMargins.left;
            if (margin == 0 || !type.relativeToMargin) {
                graphics.drawArrow(tx + 2 * ARROW_SIZE, ty, tx, ty, ARROW_SIZE);
            } else {
                graphics.drawArrow(tx, ty, tx - margin, ty, ARROW_SIZE);
            }
        } else {
            assert targetSegmentTypeX == RIGHT;
            int tx = targetBounds.x2();
            int margin = targetMargins.right;
            if (margin == 0 || !type.relativeToMargin) {
                graphics.drawArrow(tx - 2 * ARROW_SIZE, ty, tx, ty, ARROW_SIZE);
            } else {
                graphics.drawArrow(tx, ty, tx + margin, ty, ARROW_SIZE);
            }
        }

        return;
    }

    /**
     * Paints a vertical center constraint. The constraint is shown as a dashed line
     * through the vertical view, and a solid line over the node bounds.
     */
    private static void paintVerticalCenterConstraint(IGraphics graphics, Rect sourceBounds,
            Rect targetBounds) {
        graphics.useStyle(GUIDELINE_DASHED);
        graphics.drawLine(targetBounds.x, targetBounds.centerY(),
                targetBounds.x2(), targetBounds.centerY());
        graphics.useStyle(GUIDELINE);
        graphics.drawLine(sourceBounds.x, sourceBounds.centerY(),
                sourceBounds.x2(), sourceBounds.centerY());
    }

    /**
     * Paints a horizontal center constraint. The constraint is shown as a dashed line
     * through the horizontal view, and a solid line over the node bounds.
     */
    private static void paintHorizontalCenterConstraint(IGraphics graphics, Rect sourceBounds,
            Rect targetBounds) {
        graphics.useStyle(GUIDELINE_DASHED);
        graphics.drawLine(targetBounds.centerX(), targetBounds.y,
                targetBounds.centerX(), targetBounds.y2());
        graphics.useStyle(GUIDELINE);
        graphics.drawLine(sourceBounds.centerX(), sourceBounds.y,
                sourceBounds.centerX(), sourceBounds.y2());
    }
}