blob: 94d01022c83ea81d1e7f1bd0e39df9ae10de8e29 [file] [log] [blame]
/*
* Copyright 2000-2011 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 git4idea.ui;
import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.table.TableView;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import com.intellij.util.ui.UIUtil;
import git4idea.GitCommit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/**
* A table with the list of commits.
*
* @author Kirill Likhodedov
*/
public class GitCommitListPanel extends JPanel implements TypeSafeDataProvider {
private final List<GitCommit> myCommits;
private final TableView<GitCommit> myTable;
public GitCommitListPanel(@NotNull List<GitCommit> commits, @Nullable String emptyText) {
myCommits = commits;
myTable = new TableView<GitCommit>();
updateModel();
myTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
myTable.setStriped(true);
if (emptyText != null) {
myTable.getEmptyText().setText(emptyText);
}
setLayout(new BorderLayout());
add(ScrollPaneFactory.createScrollPane(myTable));
}
/**
* Adds a listener that would be called once user selects a commit in the table.
*/
public void addListSelectionListener(final @NotNull Consumer<GitCommit> listener) {
myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(final ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
int i = lsm.getMaxSelectionIndex();
int j = lsm.getMinSelectionIndex();
if (i >= 0 && i == j) {
listener.consume(myCommits.get(i));
}
}
});
}
public void addListMultipleSelectionListener(final @NotNull Consumer<List<Change>> listener) {
myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(final ListSelectionEvent e) {
List<GitCommit> commits = myTable.getSelectedObjects();
final List<Change> changes = new ArrayList<Change>();
// We need changes in asc order for zipChanges, and they are in desc order in Table
ListIterator<GitCommit> iterator = commits.listIterator(commits.size());
while (iterator.hasPrevious()) {
changes.addAll(iterator.previous().getChanges());
}
listener.consume(CommittedChangesTreeBrowser.zipChanges(changes));
}
});
}
/**
* Registers the diff action which will be called when the diff shortcut is pressed in the table.
*/
public void registerDiffAction(@NotNull AnAction diffAction) {
diffAction.registerCustomShortcutSet(CommonShortcuts.getDiff(), myTable);
}
// Make changes available for diff action
@Override
public void calcData(DataKey key, DataSink sink) {
if (VcsDataKeys.CHANGES.equals(key)) {
int[] rows = myTable.getSelectedRows();
if (rows.length != 1) return;
int row = rows[0];
GitCommit gitCommit = myCommits.get(row);
// suppressing: inherited API
//noinspection unchecked
sink.put(key, ArrayUtil.toObjectArray(gitCommit.getChanges(), Change.class));
}
}
@NotNull
public JComponent getPreferredFocusComponent() {
return myTable;
}
public void clearSelection() {
myTable.clearSelection();
}
public void setCommits(@NotNull List<GitCommit> commits) {
myCommits.clear();
myCommits.addAll(commits);
updateModel();
myTable.repaint();
}
private void updateModel() {
myTable.setModelAndUpdateColumns(new ListTableModel<GitCommit>(generateColumnsInfo(myCommits), myCommits, 0));
}
@NotNull
private ColumnInfo[] generateColumnsInfo(@NotNull List<GitCommit> commits) {
ItemAndWidth hash = new ItemAndWidth("", 0);
ItemAndWidth author = new ItemAndWidth("", 0);
ItemAndWidth time = new ItemAndWidth("", 0);
for (GitCommit commit : commits) {
hash = getMax(hash, getHash(commit));
author = getMax(author, getAuthor(commit));
time = getMax(time, getTime(commit));
}
return new ColumnInfo[] {
new GitCommitColumnInfo("Hash", hash.myItem) {
@Override
public String valueOf(GitCommit commit) {
return getHash(commit);
}
},
new ColumnInfo<GitCommit, String>("Subject") {
@Override
public String valueOf(GitCommit commit) {
return commit.getSubject();
}
},
new GitCommitColumnInfo("Author", author.myItem) {
@Override
public String valueOf(GitCommit commit) {
return getAuthor(commit);
}
},
new GitCommitColumnInfo("Author time", time.myItem) {
@Override
public String valueOf(GitCommit commit) {
return getTime(commit);
}
}
};
}
private ItemAndWidth getMax(ItemAndWidth current, String candidate) {
int width = myTable.getFontMetrics(myTable.getFont()).stringWidth(candidate);
if (width > current.myWidth) {
return new ItemAndWidth(candidate, width);
}
return current;
}
private static class ItemAndWidth {
private final String myItem;
private final int myWidth;
private ItemAndWidth(String item, int width) {
myItem = item;
myWidth = width;
}
}
private static String getHash(GitCommit commit) {
return DvcsUtil.getShortHash(commit.getId().toString());
}
private static String getAuthor(GitCommit commit) {
return commit.getAuthor().getName();
}
private static String getTime(GitCommit commit) {
return DateFormatUtil.formatPrettyDateTime(commit.getTimestamp());
}
private abstract static class GitCommitColumnInfo extends ColumnInfo<GitCommit, String> {
@NotNull private final String myMaxString;
public GitCommitColumnInfo(@NotNull String name, @NotNull String maxString) {
super(name);
myMaxString = maxString;
}
@Override
public String getMaxStringValue() {
return myMaxString;
}
@Override
public int getAdditionalWidth() {
return UIUtil.DEFAULT_HGAP;
}
}
}