[vcs-log] move references to the right and paint them with tag icons

This commit is contained in:
Julia Beliaeva
2016-09-07 20:03:48 +03:00
parent 65873d25b3
commit ef7903ab3d
3 changed files with 159 additions and 75 deletions
@@ -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<VcsRef> 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<String, Color> labelsForReferences = collectLabelsForRefs(myRefs);
for (Map.Entry<String, Color> 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<VcsRef> 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<String, Color> collectLabelsForRefs(@NotNull Collection<VcsRef> 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<VcsRef> branches = ContainerUtil.newArrayList();
List<VcsRef> 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<VcsRef> 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<String, Color> getLabelsForRefs(@NotNull List<VcsRef> branches, @NotNull Collection<VcsRef> tags) {
Map<String, Color> 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;
@@ -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<Pair<String, TagIcon>> 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<VcsRef> 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<VcsRefType, Collection<VcsRef>> 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<String, TagIcon> 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();
}
}
@@ -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 {