From ef7903ab3df7007923406859acff6336c219bb7d Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 21 Jun 2016 21:27:52 +0300 Subject: [PATCH] [vcs-log] move references to the right and paint them with tag icons --- .../ui/render/GraphCommitCellRenderer.java | 94 +++--------- .../vcs/log/ui/render/TagLabelPainter.java | 138 ++++++++++++++++++ .../vcs/log/ui/render/TextLabelPainter.java | 2 - 3 files changed, 159 insertions(+), 75 deletions(-) create mode 100644 platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/TagLabelPainter.java diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRenderer.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRenderer.java index 777247e5a887..2b1ee36269d2 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRenderer.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRenderer.java @@ -4,7 +4,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkRenderer; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ColoredTableCellRenderer; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.VcsRef; import com.intellij.vcs.log.data.VcsLogData; @@ -20,23 +22,20 @@ import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; public class GraphCommitCellRenderer extends ColoredTableCellRenderer { - private static final Logger LOG = Logger.getInstance(GraphCommitCellRenderer.class); private static final int MAX_GRAPH_WIDTH = 10; + private static final int VERTICAL_PADDING = JBUI.scale(7); + @NotNull private final VcsLogData myLogData; @NotNull private final GraphCellPainter myPainter; @NotNull private final VcsLogGraphTable myGraphTable; - @NotNull private final TextLabelPainter myTextLabelPainter; @NotNull private final IssueLinkRenderer myIssueLinkRenderer; + @NotNull private final TagLabelPainter myTextLabelPainter = new TagLabelPainter(); @Nullable private PaintInfo myGraphImage; - @Nullable private Collection myRefs; @NotNull private Font myFont; private int myHeight; @@ -46,8 +45,7 @@ public class GraphCommitCellRenderer extends ColoredTableCellRenderer { myLogData = logData; myPainter = painter; myGraphTable = table; - myTextLabelPainter = TextLabelPainter.createPainter(false); - myIssueLinkRenderer = new IssueLinkRenderer(logData.getProject(), this); + myIssueLinkRenderer = new IssueLinkRenderer(myLogData.getProject(), this); myFont = TextLabelPainter.getFont(); myHeight = calculateHeight(); } @@ -69,23 +67,14 @@ public class GraphCommitCellRenderer extends ColoredTableCellRenderer { } private int calculateHeight() { - return myTextLabelPainter.calculateSize("", getFontMetrics(myFont)).height + 4; + return Math.max(myTextLabelPainter.getSize().height, getFontMetrics(myFont).getHeight() + VERTICAL_PADDING); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); - if (myRefs != null) { - int paddingX = (myGraphImage != null ? myGraphImage.getWidth() : 0) + PaintParameters.LABEL_PADDING; - Map labelsForReferences = collectLabelsForRefs(myRefs); - for (Map.Entry entry : labelsForReferences.entrySet()) { - Dimension size = myTextLabelPainter.calculateSize(entry.getKey(), g.getFontMetrics(TextLabelPainter.getFont())); - int paddingY = (myGraphTable.getRowHeight() - size.height) / 2; - myTextLabelPainter.paint((Graphics2D)g, entry.getKey(), paddingX, paddingY, entry.getValue()); - paddingX += size.width + PaintParameters.LABEL_PADDING; - } - } + myTextLabelPainter.paint((Graphics2D)g, getWidth() - myTextLabelPainter.getSize().width, 0, getHeight()); if (myGraphImage != null) { UIUtil.drawImage(g, myGraphImage.getImage(), 0, 0, null); @@ -103,7 +92,6 @@ public class GraphCommitCellRenderer extends ColoredTableCellRenderer { GraphCommitCell cell = getAssertCommitCell(value); myGraphImage = getGraphImage(row); - myRefs = cell.getRefsToThisCommit(); int graphPadding; if (myGraphImage != null) { @@ -115,12 +103,22 @@ public class GraphCommitCellRenderer extends ColoredTableCellRenderer { else { graphPadding = 0; } - int textPadding = graphPadding + calculateReferencePadding(myRefs); setBorder(null); append(""); - appendTextPadding(textPadding); + appendTextPadding(graphPadding); myIssueLinkRenderer.appendTextWithLinks(cell.getText(), myGraphTable.applyHighlighters(this, row, column, "", hasFocus, isSelected)); + + Collection refs = cell.getRefsToThisCommit(); + if (refs.isEmpty()) { + myTextLabelPainter.customizePainter(this, refs); + } + else { + VirtualFile root = ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(refs)).getRoot(); + myTextLabelPainter + .customizePainter(this, + ContainerUtil.sorted(refs, myLogData.getLogProvider(root).getReferenceManager().getLabelsOrderComparator())); + } } @Nullable @@ -139,7 +137,7 @@ public class GraphCommitCellRenderer extends ColoredTableCellRenderer { Graphics2D g2 = image.createGraphics(); myPainter.draw(g2, printElements); - final int width = maxIndex * PaintParameters.getNodeWidth(myGraphTable.getRowHeight()); + int width = maxIndex * PaintParameters.getNodeWidth(myGraphTable.getRowHeight()); return new PaintInfo(image, width); } @@ -148,56 +146,6 @@ public class GraphCommitCellRenderer extends ColoredTableCellRenderer { return (GraphCommitCell)value; } - @NotNull - private Map collectLabelsForRefs(@NotNull Collection refs) { - if (refs.isEmpty()) { - return Collections.emptyMap(); - } - VirtualFile root = refs.iterator().next().getRoot(); // all refs are from the same commit => they have the same root - refs = ContainerUtil.sorted(refs, myLogData.getLogProvider(root).getReferenceManager().getLabelsOrderComparator()); - List branches = ContainerUtil.newArrayList(); - List tags = ContainerUtil.newArrayList(); - refs.forEach(ref -> { - if (ref.getType().isBranch()) { - branches.add(ref); - } - else { - tags.add(ref); - } - }); - return getLabelsForRefs(branches, tags); - } - - private int calculateReferencePadding(@NotNull Collection references) { - if (references.isEmpty()) return 0; - - int paddingX = 2 * PaintParameters.LABEL_PADDING; - for (String label : collectLabelsForRefs(references).keySet()) { - Dimension size = myTextLabelPainter.calculateSize(label, this.getFontMetrics(TextLabelPainter.getFont())); - paddingX += size.width + PaintParameters.LABEL_PADDING; - } - return paddingX; - } - - @NotNull - private static Map getLabelsForRefs(@NotNull List branches, @NotNull Collection tags) { - Map labels = ContainerUtil.newLinkedHashMap(); - for (VcsRef branch : branches) { - labels.put(branch.getName(), branch.getType().getBackgroundColor()); - } - if (!tags.isEmpty()) { - VcsRef firstTag = tags.iterator().next(); - Color color = firstTag.getType().getBackgroundColor(); - if (tags.size() > 1) { - labels.put(firstTag.getName() + " +", color); - } - else { - labels.put(firstTag.getName(), color); - } - } - return labels; - } - private static class PaintInfo { private int myWidth; @NotNull private Image myImage; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/TagLabelPainter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/TagLabelPainter.java new file mode 100644 index 000000000000..e2e8030f94cc --- /dev/null +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/TagLabelPainter.java @@ -0,0 +1,138 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.intellij.vcs.log.ui.render; +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.openapi.util.Pair; +import com.intellij.ui.JBColor; +import com.intellij.ui.SimpleColoredComponent; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.GraphicsUtil; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UIUtil; +import com.intellij.vcs.log.VcsRef; +import com.intellij.vcs.log.VcsRefType; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class TagLabelPainter { + public static final int TOP_TEXT_PADDING = JBUI.scale(2); + public static final int BOTTOM_TEXT_PADDING = JBUI.scale(1); + public static final int GRADIENT_WIDTH = JBUI.scale(25); + public static final int RIGHT_PADDING = JBUI.scale(5); + public static final int MIDDLE_PADDING = JBUI.scale(5); + + @NotNull + private List> myLabels = ContainerUtil.newArrayList(); + private int myHeight = JBUI.scale(22); + private int myWidth = 0; + @NotNull + private Color myBackground = UIUtil.getTableBackground(); + @NotNull + private Color myForeground = UIUtil.getTableForeground(); + + public void customizePainter(@NotNull JComponent component, @NotNull Collection references) { + myBackground = component.getBackground(); + myForeground = component.getForeground(); + + FontMetrics metrics = component.getFontMetrics(getReferenceFont()); + myHeight = metrics.getHeight() + TOP_TEXT_PADDING + BOTTOM_TEXT_PADDING; + myWidth = GRADIENT_WIDTH + RIGHT_PADDING; + + myLabels = ContainerUtil.newArrayList(); + for (Map.Entry> typeAndRefs : ContainerUtil.groupBy(references, VcsRef::getType).entrySet()) { + VcsRef firstRef = ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(typeAndRefs.getValue())); + VcsRefType type = typeAndRefs.getKey(); + boolean multiple = typeAndRefs.getValue().size() > 1; + TagIcon tagIcon = new TagIcon(myHeight, myBackground, multiple + ? new Color[]{type.getBackgroundColor(), type.getBackgroundColor()} + : new Color[]{type.getBackgroundColor()}); + + String text = firstRef.getName() + (multiple ? " +" : ""); + myLabels.add(Pair.create(text, tagIcon)); + + myWidth += tagIcon.getIconWidth() + metrics.stringWidth(text) + MIDDLE_PADDING; + } + } + + public void paint(@NotNull Graphics2D g2, int x, int y, int height) { + if (myLabels.isEmpty()) return; + + GraphicsConfig config = GraphicsUtil.setupAAPainting(g2); + g2.setFont(getReferenceFont()); + g2.setStroke(new BasicStroke(1.5f)); + + FontMetrics fontMetrics = g2.getFontMetrics(); + + g2.setPaint( + new GradientPaint(x, y, new Color(myBackground.getRed(), myBackground.getGreen(), myBackground.getBlue(), 0), x + GRADIENT_WIDTH, y, + myBackground)); + g2.fill(new Rectangle(x, y, GRADIENT_WIDTH, height)); + x += GRADIENT_WIDTH; + + g2.setColor(myBackground); + g2.fillRect(x, y, myWidth - GRADIENT_WIDTH, height); + + for (Pair label : myLabels) { + TagIcon icon = label.second; + String text = label.first; + + icon.paintIcon(null, g2, x, y + (height - icon.getIconHeight()) / 2); + x += icon.getIconWidth(); + + g2.setColor(myForeground); + g2.drawString(text, x, y + SimpleColoredComponent.getTextBaseLine(fontMetrics, height)); + x += fontMetrics.stringWidth(text) + MIDDLE_PADDING; + } + + config.restore(); + } + + public Dimension getSize() { + if (myLabels.isEmpty()) return new Dimension(); + return new Dimension(myWidth, myHeight); + } + + protected Font getReferenceFont() { + return getFont(); + } + + public static Font getFont() { + return UIUtil.getLabelFont(); + } +} + diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/TextLabelPainter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/TextLabelPainter.java index 60410a4b917b..52b16d6c4d6c 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/TextLabelPainter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/TextLabelPainter.java @@ -24,8 +24,6 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import java.awt.*; -import java.awt.geom.Area; -import java.awt.geom.Ellipse2D; import java.awt.geom.RoundRectangle2D; public class TextLabelPainter {