From ed93e5916034665474a74f336b594df41e64efa0 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 4 Nov 2013 21:36:55 +0400 Subject: [PATCH] [log] Shift mouse-over-node/branch area in multi-root projects Use the root column width, since the column might be made resizeable in future. The column model is not ready at the beginning => listen to column model changes and pass the root column to the GraphCellPainter. --- .../log/graph/render/GraphCellPainter.java | 3 ++ .../vcs/log/graph/render/PositionUtil.java | 16 ++++---- .../graph/render/SimpleGraphCellPainter.java | 24 ++++++++++-- .../vcs/log/data/VcsLogDataHolder.java | 4 ++ .../vcs/log/ui/frame/VcsLogGraphTable.java | 37 +++++++++++++++---- 5 files changed, 65 insertions(+), 19 deletions(-) diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/GraphCellPainter.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/GraphCellPainter.java index efc713aef3d3..b2fe9d65e966 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/GraphCellPainter.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/GraphCellPainter.java @@ -6,6 +6,7 @@ import com.intellij.vcs.log.printmodel.SpecialPrintElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.table.TableColumn; import java.awt.*; /** @@ -20,5 +21,7 @@ public interface GraphCellPainter { @Nullable SpecialPrintElement mouseOverArrow(@NotNull GraphPrintCell row, int x, int y); + + void setRootColumn(TableColumn column); } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/PositionUtil.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/PositionUtil.java index 1feae3056769..025577f7ae72 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/PositionUtil.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/PositionUtil.java @@ -15,27 +15,27 @@ public class PositionUtil { return (float)Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } - public static boolean overUpEdge(ShortEdge edge, int x, int y) { + public static boolean overUpEdge(ShortEdge edge, int x, int y, int offset) { float thick = THICK_LINE; - int x1 = WIDTH_NODE * edge.getDownPosition() + WIDTH_NODE / 2; + int x1 = WIDTH_NODE * edge.getDownPosition() + WIDTH_NODE / 2 + offset; int y1 = HEIGHT_CELL / 2; - int x2 = WIDTH_NODE * edge.getUpPosition() + WIDTH_NODE / 2; + int x2 = WIDTH_NODE * edge.getUpPosition() + WIDTH_NODE / 2 + offset; int y2 = -HEIGHT_CELL / 2; //return true; return (distance(x1, y1, x, y) + distance(x2, y2, x, y) < distance(x1, y1, x2, y2) + thick); } - public static boolean overDownEdge(ShortEdge edge, int x, int y) { + public static boolean overDownEdge(ShortEdge edge, int x, int y, int offset) { float thick = THICK_LINE; - int x1 = WIDTH_NODE * edge.getUpPosition() + WIDTH_NODE / 2; + int x1 = WIDTH_NODE * edge.getUpPosition() + WIDTH_NODE / 2 + offset; int y1 = HEIGHT_CELL / 2; - int x2 = WIDTH_NODE * edge.getDownPosition() + WIDTH_NODE / 2; + int x2 = WIDTH_NODE * edge.getDownPosition() + WIDTH_NODE / 2 + offset; int y2 = HEIGHT_CELL + HEIGHT_CELL / 2; return distance(x1, y1, x, y) + distance(x2, y2, x, y) < distance(x1, y1, x2, y2) + thick; } - public static boolean overNode(int position, int x, int y) { - int x0 = WIDTH_NODE * position + WIDTH_NODE / 2; + public static boolean overNode(int position, int x, int y, int xOffset) { + int x0 = WIDTH_NODE * position + WIDTH_NODE / 2 + xOffset; int y0 = HEIGHT_CELL / 2; int r = CIRCLE_RADIUS; return distance(x0, y0, x, y) <= r; diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/SimpleGraphCellPainter.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/SimpleGraphCellPainter.java index 5924b7937e33..4c9c1cff271c 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/SimpleGraphCellPainter.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/SimpleGraphCellPainter.java @@ -10,6 +10,7 @@ import com.intellij.vcs.log.printmodel.SpecialPrintElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.table.TableColumn; import java.awt.*; import java.awt.geom.Ellipse2D; @@ -19,6 +20,8 @@ import java.awt.geom.Ellipse2D; public class SimpleGraphCellPainter implements GraphCellPainter { private static final Color MARK_COLOR = JBColor.BLACK; + private final boolean myMultiRoot; + private TableColumn myRootColumn; private Graphics2D g2; @@ -27,6 +30,10 @@ public class SimpleGraphCellPainter implements GraphCellPainter { private final Stroke selectUsual = new BasicStroke(PrintParameters.SELECT_THICK_LINE, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL); private final Stroke selectHide = new BasicStroke(PrintParameters.SELECT_THICK_LINE, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL, 0, new float[]{7}, 0); + public SimpleGraphCellPainter(boolean multiRoot) { + myMultiRoot = multiRoot; + } + private void paintUpLine(int from, int to, Color color) { int x1 = PrintParameters.WIDTH_NODE * from + PrintParameters.WIDTH_NODE / 2; int y1 = PrintParameters.HEIGHT_CELL / 2; @@ -210,18 +217,18 @@ public class SimpleGraphCellPainter implements GraphCellPainter { public GraphElement mouseOver(@NotNull GraphPrintCell row, int x, int y) { for (SpecialPrintElement printElement : row.getSpecialPrintElements()) { if (printElement.getType() == SpecialPrintElement.Type.COMMIT_NODE) { - if (PositionUtil.overNode(printElement.getPosition(), x, y)) { + if (PositionUtil.overNode(printElement.getPosition(), x, y, getXOffset())) { return printElement.getGraphElement(); } } } for (ShortEdge edge : row.getUpEdges()) { - if (PositionUtil.overUpEdge(edge, x, y)) { + if (PositionUtil.overUpEdge(edge, x, y, getXOffset())) { return edge.getEdge(); } } for (ShortEdge edge : row.getDownEdges()) { - if (PositionUtil.overDownEdge(edge, x, y)) { + if (PositionUtil.overDownEdge(edge, x, y, getXOffset())) { return edge.getEdge(); } } @@ -229,16 +236,25 @@ public class SimpleGraphCellPainter implements GraphCellPainter { return null; } + private int getXOffset() { + return myMultiRoot && myRootColumn != null ? myRootColumn.getWidth() : 0; + } + @Nullable @Override public SpecialPrintElement mouseOverArrow(@NotNull GraphPrintCell row, int x, int y) { for (SpecialPrintElement printElement : row.getSpecialPrintElements()) { if (printElement.getType() != SpecialPrintElement.Type.COMMIT_NODE) { - if (PositionUtil.overNode(printElement.getPosition(), x, y)) { + if (PositionUtil.overNode(printElement.getPosition(), x, y, getXOffset())) { return printElement; } } } return null; } + + @Override + public void setRootColumn(TableColumn column) { + myRootColumn = column; + } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java index ec00c7a5f7d4..b6c603a125ee 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java @@ -465,6 +465,10 @@ public class VcsLogDataHolder implements Disposable { return myCurrentUser; } + public boolean isMultiRoot() { + return myLogProviders.size() > 1; + } + private static class RecentCommitsInfo { List firstBlockCommits; Collection newRefs; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index c1bc44f5b139..2c959bfd4bc8 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -28,12 +28,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableModel; +import javax.swing.event.*; +import javax.swing.table.*; import java.awt.*; import java.awt.datatransfer.StringSelection; import java.awt.event.MouseAdapter; @@ -51,7 +47,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C private static final int ROOT_INDICATOR_WIDTH = 5; @NotNull private final VcsLogUI myUI; - @NotNull private final GraphCellPainter myGraphPainter = new SimpleGraphCellPainter(); + @NotNull private final GraphCellPainter myGraphPainter; private volatile boolean myRepaintFreezed; @@ -59,6 +55,8 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C super(); myUI = UI; + myGraphPainter = new SimpleGraphCellPainter(logDataHolder.isMultiRoot()); + setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI)); setDefaultRenderer(GraphCommitCell.class, new GraphCommitCellRender(myGraphPainter, logDataHolder, myUI.getColorManager())); setDefaultRenderer(CommitCell.class, new CommitCellRender(myUI.getColorManager())); @@ -83,6 +81,31 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C addMouseListener(mouseAdapter); PopupHandler.installPopupHandler(this, VcsLogUI.POPUP_ACTION_GROUP, VcsLogUI.VCS_LOG_TABLE_PLACE); + + getColumnModel().addColumnModelListener(new TableColumnModelListener() { + @Override + public void columnAdded(TableColumnModelEvent e) { + if (e.getToIndex() == AbstractVcsLogTableModel.ROOT_COLUMN) { + myGraphPainter.setRootColumn(getColumnModel().getColumn(AbstractVcsLogTableModel.ROOT_COLUMN)); + } + } + + @Override + public void columnRemoved(TableColumnModelEvent e) { + } + + @Override + public void columnMoved(TableColumnModelEvent e) { + } + + @Override + public void columnMarginChanged(ChangeEvent e) { + } + + @Override + public void columnSelectionChanged(ListSelectionEvent e) { + } + }); } @Override