blob: ee95c1fea6737956b5c8bf984e0a2ed2c1a7b201 [file] [log] [blame]
package com.intellij.vcs.log.ui.render;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkRenderer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.ColoredTableCellRenderer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.vcs.log.VcsRef;
import com.intellij.vcs.log.data.VcsLogDataHolder;
import com.intellij.vcs.log.graph.PaintInfo;
import com.intellij.vcs.log.graph.render.GraphCommitCell;
import com.intellij.vcs.log.ui.VcsLogColorManager;
import com.intellij.vcs.log.ui.frame.VcsLogGraphTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer {
private static final Logger LOG = Logger.getInstance(AbstractPaddingCellRender.class);
@NotNull private final VcsLogDataHolder myDataHolder;
@NotNull private final VcsLogGraphTable myGraphTable;
@NotNull private final RefPainter myRefPainter;
@NotNull private final IssueLinkRenderer myIssueLinkRenderer;
@Nullable private PaintInfo myGraphImage;
@Nullable private Collection<VcsRef> myRefs;
protected AbstractPaddingCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder,
@NotNull VcsLogGraphTable table) {
myDataHolder = dataHolder;
myGraphTable = table;
myRefPainter = new RefPainter(colorManager, false);
myIssueLinkRenderer = new IssueLinkRenderer(dataHolder.getProject(), this);
}
@Nullable
protected abstract PaintInfo getGraphImage(int row);
@Override
protected void customizeCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null) {
return;
}
GraphCommitCell cell = getAssertCommitCell(value);
myGraphImage = getGraphImage(row);
myRefs = cell.getRefsToThisCommit();
int graphPadding;
if (myGraphImage != null) {
graphPadding = myGraphImage.getWidth();
if (graphPadding < 2) { // TODO temporary diagnostics: why does graph sometimes disappear
LOG.error("Too small image width: " + graphPadding);
}
}
else {
graphPadding = 0;
}
int textPadding = graphPadding + calcRefsPadding(myRefs);
setBorder(null);
append("");
appendFixedTextFragmentWidth(textPadding);
myGraphTable.applyHighlighters(this, row, isSelected);
myIssueLinkRenderer.appendTextWithLinks(cell.getText());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (myRefs != null) {
int graphPadding = myGraphImage != null ? myGraphImage.getWidth() : 0;
drawRefs((Graphics2D)g, myRefs, graphPadding);
}
if (myGraphImage != null) {
UIUtil.drawImage(g, myGraphImage.getImage(), 0, 0, null);
}
else { // TODO temporary diagnostics: why does graph sometimes disappear
LOG.error("Image is null");
}
}
private static GraphCommitCell getAssertCommitCell(Object value) {
assert value instanceof GraphCommitCell : "Value of incorrect class was supplied: " + value;
return (GraphCommitCell)value;
}
protected void drawRefs(@NotNull Graphics2D g2, @NotNull Collection<VcsRef> refs, int padding) {
myRefPainter.drawLabels(g2, collectLabelsForRefs(refs), padding);
}
@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 = myDataHolder.getLogProvider(root).getReferenceManager().sort(refs);
List<VcsRef> branches = getBranches(refs);
Collection<VcsRef> tags = ContainerUtil.subtract(refs, branches);
return getLabelsForRefs(branches, tags);
}
protected int calcRefsPadding(@NotNull Collection<VcsRef> refs) {
return myRefPainter.padding(collectLabelsForRefs(refs).keySet(), this.getFontMetrics(RefPainter.DEFAULT_FONT));
}
@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 List<VcsRef> getBranches(Collection<VcsRef> refs) {
return ContainerUtil.filter(refs, new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
return ref.getType().isBranch();
}
});
}
}