From f926dc2deee8dcc73512b86a47ed5c28b90de88b Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Thu, 20 Aug 2015 19:35:07 +0300 Subject: [PATCH] [vcs-log] fix lines and arrows painting (fixes IDEA-135359): - vertical lines have normal size and do not have visible junctions anymore; - diagonals are still twice the size (impossible to make them connect to each other well otherwize); - arrows rotate with lines. (cherry picked from commit 25aefc664e63121bdd7d82c298154dd22489c7f9) --- .../printer/idea/SimpleGraphCellPainter.java | 74 ++++++++++++++----- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/printer/idea/SimpleGraphCellPainter.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/printer/idea/SimpleGraphCellPainter.java index 0d9304b90b0a..90a35c3991ee 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/printer/idea/SimpleGraphCellPainter.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/printer/idea/SimpleGraphCellPainter.java @@ -15,6 +15,7 @@ */ package com.intellij.vcs.log.printer.idea; +import com.intellij.openapi.util.Pair; import com.intellij.ui.JBColor; import com.intellij.vcs.log.graph.EdgePrintElement; import com.intellij.vcs.log.graph.NodePrintElement; @@ -24,6 +25,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.awt.geom.Ellipse2D; +import java.awt.geom.Line2D; import java.util.Collection; /** @@ -33,6 +35,8 @@ public class SimpleGraphCellPainter implements GraphCellPainter { private static final Color MARK_COLOR = JBColor.BLACK; private static final int ROW_HEIGHT = 24; + private static final double ARROW_ANGLE_COS2 = 0.7; + private static final double ARROW_LENGTH = 0.3; private final Stroke usual = new BasicStroke(PrintParameters.THICK_LINE, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL); private final Stroke hide = @@ -54,35 +58,67 @@ public class SimpleGraphCellPainter implements GraphCellPainter { } private void paintUpLine(int from, int to, Color color, boolean hasArrow) { - int x1 = PrintParameters.WIDTH_NODE * from + PrintParameters.WIDTH_NODE / 2; - int y1 = getRowHeight() / 2; - int x2 = PrintParameters.WIDTH_NODE * to + PrintParameters.WIDTH_NODE / 2; - int y2 = -getRowHeight() / 2; - g2.setColor(color); - g2.drawLine(x2, y2, x1, y1); - if (hasArrow) { - int r = PrintParameters.CIRCLE_RADIUS; - int y = r + 2; - g2.drawLine(x1, y - r, x1 + r, y); - g2.drawLine(x1, y - r, x1 - r, y); + // paint vertical lines normal size + // paint non-vertical lines twice the size to make them dock with each other well + if (from == to) { + int x = PrintParameters.WIDTH_NODE * from + PrintParameters.WIDTH_NODE / 2; + int y1 = getRowHeight() / 2 - 1; + int y2 = 0; + paintLine(color, hasArrow, x, y1, x, y2, x, y2); + } + else { + int x1 = PrintParameters.WIDTH_NODE * from + PrintParameters.WIDTH_NODE / 2; + int y1 = getRowHeight() / 2; + int x2 = PrintParameters.WIDTH_NODE * to + PrintParameters.WIDTH_NODE / 2; + int y2 = -getRowHeight() / 2; + paintLine(color, hasArrow, x1, y1, x2, y2, (x1 + x2) / 2, (y1 + y2) / 2); } } private void paintDownLine(int from, int to, Color color, boolean hasArrow) { - int x1 = PrintParameters.WIDTH_NODE * from + PrintParameters.WIDTH_NODE / 2; - int y1 = getRowHeight() / 2; - int x2 = PrintParameters.WIDTH_NODE * to + PrintParameters.WIDTH_NODE / 2; - int y2 = getRowHeight() + getRowHeight() / 2; + if (from == to) { + int y2 = getRowHeight() - 1; + int y1 = getRowHeight() / 2; + int x = PrintParameters.WIDTH_NODE * from + PrintParameters.WIDTH_NODE / 2; + paintLine(color, hasArrow, x, y1, x, y2, x, y2); + } + else { + int x1 = PrintParameters.WIDTH_NODE * from + PrintParameters.WIDTH_NODE / 2; + int y1 = getRowHeight() / 2; + int x2 = PrintParameters.WIDTH_NODE * to + PrintParameters.WIDTH_NODE / 2; + int y2 = getRowHeight() + getRowHeight() / 2; + paintLine(color, hasArrow, x1, y1, x2, y2, (x1 + x2) / 2, (y1 + y2) / 2); + } + } + + private void paintLine(Color color, boolean hasArrow, int x1, int y1, int x2, int y2, int startArrowX, int startArrowY) { g2.setColor(color); g2.drawLine(x1, y1, x2, y2); if (hasArrow) { - int r = PrintParameters.CIRCLE_RADIUS; - int y = getRowHeight() - r - 2; - g2.drawLine(x1, y + r, x1 + r, y); - g2.drawLine(x1, y + r, x1 - r, y); + Pair rotate1 = + rotate(x1, y1, startArrowX, startArrowY, Math.sqrt(ARROW_ANGLE_COS2), Math.sqrt(1 - ARROW_ANGLE_COS2), ARROW_LENGTH * getRowHeight()); + Pair rotate2 = + rotate(x1, y1, startArrowX, startArrowY, Math.sqrt(ARROW_ANGLE_COS2), -Math.sqrt(1 - ARROW_ANGLE_COS2), ARROW_LENGTH * getRowHeight()); + g2.drawLine(startArrowX, startArrowY, rotate1.first, rotate1.second); + g2.drawLine(startArrowX, startArrowY, rotate2.first, rotate2.second); } } + @NotNull + private static Pair rotate(double x, double y, double centerX, double centerY, double cos, double sin, double arrowLength) { + double translateX = (x - centerX); + double translateY = (y - centerY); + + double d = Math.sqrt(translateX * translateX + translateY * translateY); + double scaleX = arrowLength * translateX / d; + double scaleY = arrowLength * translateY / d; + + double rotateX = scaleX * cos - scaleY * sin; + double rotateY = scaleX * sin + scaleY * cos; + + return Pair.create((int)Math.round(rotateX + centerX), (int)Math.round(rotateY + centerY)); + } + private void paintCircle(int position, Color color, boolean select) { int x0 = PrintParameters.WIDTH_NODE * position + PrintParameters.WIDTH_NODE / 2; int y0 = getRowHeight() / 2;