[log] Create NoGraphTableModel for future filtering

Some filters will be unable to work on graph, therefore we introducing
special renderer and special table model for them.

* Move common stuff to the AbstractVcsLogTableModel.
* Introduce NoGraphTableModel. Just store the list of commits there.
  There will be not many of them, performance should be OK.
* Fix the Root renderer in the VcsLogGraphTable to get the root from
  value, not from the node.
This commit is contained in:
Kirill Likhodedov
2013-10-21 17:40:10 +04:00
parent 53da3b537d
commit 35879f85ec
4 changed files with 255 additions and 102 deletions
@@ -10,14 +10,14 @@ import com.intellij.vcs.log.data.VcsLogDataHolder;
import com.intellij.vcs.log.graph.elements.Edge;
import com.intellij.vcs.log.graph.elements.GraphElement;
import com.intellij.vcs.log.graph.elements.Node;
import com.intellij.vcs.log.graph.render.GraphCellPainter;
import com.intellij.vcs.log.graph.render.GraphCommitCell;
import com.intellij.vcs.log.graph.render.PositionUtil;
import com.intellij.vcs.log.graph.render.SimpleGraphCellPainter;
import com.intellij.vcs.log.graph.render.*;
import com.intellij.vcs.log.printmodel.GraphPrintCell;
import com.intellij.vcs.log.printmodel.SpecialPrintElement;
import com.intellij.vcs.log.ui.VcsLogUI;
import com.intellij.vcs.log.ui.render.AbstractPaddingCellRender;
import com.intellij.vcs.log.ui.render.CommitCellRender;
import com.intellij.vcs.log.ui.render.GraphCommitCellRender;
import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel;
import com.intellij.vcs.log.ui.tables.GraphTableModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -52,8 +52,9 @@ public class VcsLogGraphTable extends JBTable {
myUI = UI;
setTableHeader(null);
setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI, logDataHolder));
setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI));
setDefaultRenderer(GraphCommitCell.class, new GraphCommitCellRender(myGraphPainter, logDataHolder, myUI.getColorManager()));
setDefaultRenderer(CommitCell.class, new CommitCellRender(myUI.getColorManager()));
setDefaultRenderer(String.class, new StringCellRenderer());
setRowHeight(HEIGHT_CELL);
@@ -76,16 +77,16 @@ public class VcsLogGraphTable extends JBTable {
}
public void setPreferredColumnWidths() {
TableColumn rootColumn = getColumnModel().getColumn(GraphTableModel.ROOT_COLUMN);
TableColumn rootColumn = getColumnModel().getColumn(AbstractVcsLogTableModel.ROOT_COLUMN);
int rootWidth = myUI.getColorManager().isMultipleRoots() ? ROOT_INDICATOR_WIDTH : 0;
// NB: all further instructions and their order are important, otherwise the minimum size which is less than 15 won't be applied
rootColumn.setMinWidth(rootWidth);
rootColumn.setMaxWidth(rootWidth);
rootColumn.setPreferredWidth(rootWidth);
getColumnModel().getColumn(GraphTableModel.COMMIT_COLUMN).setPreferredWidth(700);
getColumnModel().getColumn(GraphTableModel.AUTHOR_COLUMN).setMinWidth(90);
getColumnModel().getColumn(GraphTableModel.DATE_COLUMN).setMinWidth(90);
getColumnModel().getColumn(AbstractVcsLogTableModel.COMMIT_COLUMN).setPreferredWidth(700);
getColumnModel().getColumn(AbstractVcsLogTableModel.AUTHOR_COLUMN).setMinWidth(90);
getColumnModel().getColumn(AbstractVcsLogTableModel.DATE_COLUMN).setMinWidth(90);
}
public void jumpToRow(int rowIndex) {
@@ -99,14 +100,18 @@ public class VcsLogGraphTable extends JBTable {
if (rowIndex >= model.getRowCount()) {
return null;
}
GraphCommitCell commitCell = (GraphCommitCell)model.getValueAt(rowIndex, GraphTableModel.COMMIT_COLUMN);
return commitCell.getPrintCell();
Object commitValue = model.getValueAt(rowIndex, AbstractVcsLogTableModel.COMMIT_COLUMN);
if (commitValue instanceof GraphCommitCell) {
GraphCommitCell commitCell = (GraphCommitCell)commitValue;
return commitCell.getPrintCell();
}
return null;
}
@Nullable
public List<Change> getSelectedChanges() {
TableModel model = getModel();
if (!(model instanceof GraphTableModel)) {
if (!(model instanceof AbstractVcsLogTableModel)) {
LOG.error("Unexpected table model passed to the VcsLogGraphTable: " + model);
return null;
}
@@ -193,13 +198,11 @@ public class VcsLogGraphTable extends JBTable {
private static final Logger LOG = Logger.getInstance(RootCellRenderer.class);
@NotNull private final VcsLogUI myUi;
@NotNull private final VcsLogDataHolder myDataHolder;
@NotNull private Color myColor = UIUtil.getTableBackground();
RootCellRenderer(@NotNull VcsLogUI ui, @NotNull VcsLogDataHolder dataHolder) {
RootCellRenderer(@NotNull VcsLogUI ui) {
myUi = ui;
myDataHolder = dataHolder;
}
@Override
@@ -212,12 +215,12 @@ public class VcsLogGraphTable extends JBTable {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Node commitNode = myDataHolder.getDataPack().getGraphModel().getGraph().getCommitNodeInRow(row);
if (commitNode == null) {
LOG.warn("Commit node not found for row " + row);
if (value instanceof VirtualFile) {
myColor = myUi.getColorManager().getRootColor((VirtualFile)value);
}
else {
myColor = myUi.getColorManager().getRootColor(commitNode.getBranch().getRepositoryRoot());
LOG.error("Incorrect value " + value + " specified in row #" + row + ", column #");
myColor = UIUtil.getTableBackground(isSelected);
}
return this;
}
@@ -227,10 +230,10 @@ public class VcsLogGraphTable extends JBTable {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component rendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Object commit = getValueAt(row, GraphTableModel.COMMIT_COLUMN);
Object commit = getValueAt(row, AbstractVcsLogTableModel.COMMIT_COLUMN);
if (commit instanceof GraphCommitCell) {
if (GraphCommitCellRender.isMarked(commit) && !isSelected) {
rendererComponent.setBackground(GraphCommitCellRender.MARKED_BACKGROUND);
if (AbstractPaddingCellRender.isMarked(commit) && !isSelected) {
rendererComponent.setBackground(AbstractPaddingCellRender.MARKED_BACKGROUND);
}
else {
setBackground(isSelected ? table.getSelectionBackground() : JBColor.WHITE);
@@ -0,0 +1,98 @@
package com.intellij.vcs.log.ui.tables;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.vcs.log.VcsShortCommitDetails;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.table.AbstractTableModel;
import java.util.List;
/**
* @param <T> commit column class
*/
public abstract class AbstractVcsLogTableModel<T> extends AbstractTableModel {
public static final VirtualFile UNKNOWN_ROOT = NullVirtualFile.INSTANCE;
public static final int ROOT_COLUMN = 0;
public static final int COMMIT_COLUMN = 1;
public static final int AUTHOR_COLUMN = 2;
public static final int DATE_COLUMN = 3;
private static final int COLUMN_COUNT = DATE_COLUMN + 1;
private static final String[] COLUMN_NAMES = {"Root", "Subject", "Author", "Date"};
@Override
public final int getColumnCount() {
return COLUMN_COUNT;
}
@Nullable
protected abstract VcsShortCommitDetails getShortDetails(int rowIndex);
@NotNull
@Override
public final Object getValueAt(int rowIndex, int columnIndex) {
VcsShortCommitDetails data = getShortDetails(rowIndex);
switch (columnIndex) {
case ROOT_COLUMN:
return getRoot(rowIndex);
case COMMIT_COLUMN:
return getCommitColumnCell(rowIndex, data);
case AUTHOR_COLUMN:
if (data == null) {
return "";
}
else {
return data.getAuthorName();
}
case DATE_COLUMN:
if (data == null) {
return "";
}
else {
return DateFormatUtil.formatDateTime(data.getAuthorTime());
}
default:
throw new IllegalArgumentException("columnIndex is " + columnIndex + " > " + (COLUMN_COUNT - 1));
}
}
@Nullable
public abstract List<Change> getSelectedChanges(int[] selectedRows);
@NotNull
protected abstract VirtualFile getRoot(int rowIndex);
@NotNull
protected abstract T getCommitColumnCell(int index, @Nullable VcsShortCommitDetails details);
@NotNull
protected abstract Class<T> getCommitColumnClass();
@Override
public Class<?> getColumnClass(int column) {
switch (column) {
case ROOT_COLUMN:
return VirtualFile.class;
case COMMIT_COLUMN:
return getCommitColumnClass();
case AUTHOR_COLUMN:
return String.class;
case DATE_COLUMN:
return String.class;
default:
throw new IllegalArgumentException("columnIndex is " + column + " > " + (COLUMN_COUNT - 1));
}
}
@Override
public String getColumnName(int column) {
return COLUMN_NAMES[column];
}
}
@@ -1,9 +1,9 @@
package com.intellij.vcs.log.ui.tables;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsRef;
import com.intellij.vcs.log.VcsShortCommitDetails;
@@ -17,21 +17,17 @@ import com.intellij.vcs.log.printmodel.GraphPrintCell;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.table.AbstractTableModel;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author erokhins
* @author Kirill Likhodedov
*/
public class GraphTableModel extends AbstractTableModel {
public class GraphTableModel extends AbstractVcsLogTableModel<GraphCommitCell> {
public static final int ROOT_COLUMN = 0;
public static final int COMMIT_COLUMN = 1;
public static final int AUTHOR_COLUMN = 2;
public static final int DATE_COLUMN = 3;
private static final int COLUMN_COUNT = DATE_COLUMN + 1;
private static final String[] COLUMN_NAMES = {"Root", "Subject", "Author", "Date"};
private static final Logger LOG = Logger.getInstance(GraphTableModel.class);
@NotNull private final DataPack myDataPack;
@NotNull private final VcsLogDataHolder myDataHolder;
@@ -46,79 +42,15 @@ public class GraphTableModel extends AbstractTableModel {
return myDataPack.getGraphModel().getGraph().getNodeRows().size();
}
@Nullable
@Override
public int getColumnCount() {
return COLUMN_COUNT;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
protected VcsShortCommitDetails getShortDetails(int rowIndex) {
Node commitNode = myDataPack.getGraphModel().getGraph().getCommitNodeInRow(rowIndex);
VcsShortCommitDetails data;
if (commitNode == null) {
data = null;
}
else {
data = myDataHolder.getMiniDetailsGetter().getCommitData(commitNode);
}
switch (columnIndex) {
case ROOT_COLUMN:
if (commitNode != null) {
return commitNode.getBranch().getRepositoryRoot();
}
else {
return null;
}
case COMMIT_COLUMN:
GraphPrintCell graphPrintCell = myDataPack.getPrintCellModel().getGraphPrintCell(rowIndex);
String message = "";
Collection<VcsRef> refs = Collections.emptyList();
if (data != null) {
message = data.getSubject();
refs = myDataPack.getRefsModel().refsToCommit(data.getHash());
}
return new GraphCommitCell(graphPrintCell, message, refs);
case AUTHOR_COLUMN:
if (data == null) {
return "";
}
else {
return data.getAuthorName();
}
case DATE_COLUMN:
if (data == null) {
return "";
}
else {
return DateFormatUtil.formatDateTime(data.getAuthorTime());
}
default:
throw new IllegalArgumentException("columnIndex is " + columnIndex + " > " + (COLUMN_COUNT - 1));
}
}
@Override
public Class<?> getColumnClass(int column) {
switch (column) {
case ROOT_COLUMN:
return VirtualFile.class;
case COMMIT_COLUMN:
return GraphCommitCell.class;
case AUTHOR_COLUMN:
return String.class;
case DATE_COLUMN:
return String.class;
default:
throw new IllegalArgumentException("columnIndex is " + column + " > " + (COLUMN_COUNT - 1));
}
}
@Override
public String getColumnName(int column) {
return COLUMN_NAMES[column];
return commitNode == null ? null : myDataHolder.getMiniDetailsGetter().getCommitData(commitNode);
}
@Nullable
@Override
public List<Change> getSelectedChanges(int[] selectedRows) {
List<Change> changes = new ArrayList<Change>();
for (Node node : nodes(selectedRows)) {
@@ -154,4 +86,35 @@ public class GraphTableModel extends AbstractTableModel {
return null;
}
@NotNull
@Override
protected VirtualFile getRoot(int rowIndex) {
Node commitNode = myDataPack.getGraphModel().getGraph().getCommitNodeInRow(rowIndex);
if (commitNode != null) {
return commitNode.getBranch().getRepositoryRoot();
}
else {
LOG.error("Couldn't identify commit node at " + rowIndex);
return UNKNOWN_ROOT;
}
}
@NotNull
@Override
protected GraphCommitCell getCommitColumnCell(int rowIndex, @Nullable VcsShortCommitDetails details) {
GraphPrintCell graphPrintCell = myDataPack.getPrintCellModel().getGraphPrintCell(rowIndex);
String message = "";
List<VcsRef> refs = Collections.emptyList();
if (details != null) {
message = details.getSubject();
refs = (List<VcsRef>)myDataPack.getRefsModel().refsToCommit(details.getHash());
}
return new GraphCommitCell(graphPrintCell, message, refs);
}
@NotNull
@Override
protected Class<GraphCommitCell> getCommitColumnClass() {
return GraphCommitCell.class;
}
}
@@ -0,0 +1,89 @@
package com.intellij.vcs.log.ui.tables;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsRef;
import com.intellij.vcs.log.VcsShortCommitDetails;
import com.intellij.vcs.log.data.RefsModel;
import com.intellij.vcs.log.graph.render.CommitCell;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class NoGraphTableModel extends AbstractVcsLogTableModel<CommitCell> {
private static final Logger LOG = Logger.getInstance(NoGraphTableModel.class);
@NotNull private final List<Pair<VcsFullCommitDetails, VirtualFile>> myCommitsWithRoots;
@NotNull private final RefsModel myRefsModel;
public NoGraphTableModel(@NotNull List<Pair<VcsFullCommitDetails,VirtualFile>> commitsWithRoots, @NotNull RefsModel refsModel) {
myCommitsWithRoots = commitsWithRoots;
myRefsModel = refsModel;
}
@Override
public int getRowCount() {
return myCommitsWithRoots.size();
}
@Nullable
@Override
protected VcsShortCommitDetails getShortDetails(int rowIndex) {
Pair<VcsFullCommitDetails, VirtualFile> commitAndRoot = myCommitsWithRoots.get(rowIndex);
if (commitAndRoot != null) {
return commitAndRoot.getFirst();
}
else {
LOG.error("Couldn't identify details for commit at " + rowIndex, new Attachment("loaded_commits", myCommitsWithRoots.toString()));
return null;
}
}
@Nullable
@Override
public List<Change> getSelectedChanges(int[] selectedRows) {
Arrays.sort(selectedRows);
List<Change> changes = new ArrayList<Change>();
for (int selectedRow : selectedRows) {
changes.addAll(myCommitsWithRoots.get(selectedRow).getFirst().getChanges());
}
return changes;
}
@NotNull
@Override
protected VirtualFile getRoot(int rowIndex) {
Pair<VcsFullCommitDetails, VirtualFile> commitAndRoot = myCommitsWithRoots.get(rowIndex);
if (commitAndRoot != null) {
return commitAndRoot.getSecond();
}
else {
LOG.error("Couldn't identify root for commit at " + rowIndex, new Attachment("loaded_commits", myCommitsWithRoots.toString()));
return UNKNOWN_ROOT;
}
}
@NotNull
@Override
protected CommitCell getCommitColumnCell(int index, @Nullable VcsShortCommitDetails details) {
String subject = "";
Collection<VcsRef> refs = Collections.emptyList();
if (details != null) {
subject = details.getSubject();
refs = myRefsModel.refsToCommit(details.getHash());
}
return new CommitCell(subject, refs);
}
@NotNull
@Override
protected Class<CommitCell> getCommitColumnClass() {
return CommitCell.class;
}
}