/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.cpd;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import org.apache.commons.io.IOUtils;
import net.sourceforge.pmd.PMD;
public class GUI implements CPDListener {
// private interface Renderer {
// String render(Iterator<Match> items);
// }
private static final Object[][] RENDERER_SETS = new Object[][] { { "Text", new Renderer() {
@Override
public String render(Iterator<Match> items) {
return new SimpleRenderer().render(items);
}
}, }, { "XML", new Renderer() {
@Override
public String render(Iterator<Match> items) {
return new XMLRenderer().render(items);
}
}, }, { "CSV (comma)", new Renderer() {
@Override
public String render(Iterator<Match> items) {
return new CSVRenderer(',').render(items);
}
}, }, { "CSV (tab)", new Renderer() {
@Override
public String render(Iterator<Match> items) {
return new CSVRenderer('\t').render(items);
}
}, }, };
private abstract static class LanguageConfig {
public abstract Language languageFor(Properties p);
public boolean canIgnoreIdentifiers() {
return false;
}
public boolean canIgnoreLiterals() {
return false;
}
public boolean canIgnoreAnnotations() {
return false;
}
public boolean canIgnoreUsings() {
return false;
}
public abstract String[] extensions();
}
private static final Object[][] LANGUAGE_SETS;
static {
LANGUAGE_SETS = new Object[LanguageFactory.supportedLanguages.length + 1][2];
int index;
for (index = 0; index < LanguageFactory.supportedLanguages.length; index++) {
final String terseName = LanguageFactory.supportedLanguages[index];
final Language lang = LanguageFactory.createLanguage(terseName);
LANGUAGE_SETS[index][0] = lang.getName();
LANGUAGE_SETS[index][1] = new LanguageConfig() {
@Override
public Language languageFor(Properties p) {
lang.setProperties(p);
return lang;
}
@Override
public String[] extensions() {
List<String> exts = lang.getExtensions();
return exts.toArray(new String[exts.size()]);
}
@Override
public boolean canIgnoreAnnotations() {
return "java".equals(terseName);
}
@Override
public boolean canIgnoreIdentifiers() {
return "java".equals(terseName);
}
@Override
public boolean canIgnoreLiterals() {
return "java".equals(terseName);
}
@Override
public boolean canIgnoreUsings() {
return "cs".equals(terseName);
}
};
}
LANGUAGE_SETS[index][0] = "by extension...";
LANGUAGE_SETS[index][1] = new LanguageConfig() {
@Override
public Language languageFor(Properties p) {
return LanguageFactory.createLanguage(LanguageFactory.BY_EXTENSION, p);
}
@Override
public String[] extensions() {
return new String[] { "" };
}
};
}
private static final int DEFAULT_CPD_MINIMUM_LENGTH = 75;
private static final Map<String, LanguageConfig> LANGUAGE_CONFIGS_BY_LABEL = new HashMap<>(LANGUAGE_SETS.length);
private static final KeyStroke COPY_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK,
false);
private static final KeyStroke DELETE_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
private class ColumnSpec {
private String label;
private int alignment;
private int width;
private Comparator<Match> sorter;
ColumnSpec(String aLabel, int anAlignment, int aWidth, Comparator<Match> aSorter) {
label = aLabel;
alignment = anAlignment;
width = aWidth;
sorter = aSorter;
}
public String label() {
return label;
}
public int alignment() {
return alignment;
}
public int width() {
return width;
}
public Comparator<Match> sorter() {
return sorter;
}
}
private final ColumnSpec[] matchColumns = new ColumnSpec[] {
new ColumnSpec("Source", SwingConstants.LEFT, -1, Match.LABEL_COMPARATOR),
new ColumnSpec("Matches", SwingConstants.RIGHT, 60, Match.MATCHES_COMPARATOR),
new ColumnSpec("Lines", SwingConstants.RIGHT, 45, Match.LINES_COMPARATOR), };
static {
for (int i = 0; i < LANGUAGE_SETS.length; i++) {
LANGUAGE_CONFIGS_BY_LABEL.put((String) LANGUAGE_SETS[i][0], (LanguageConfig) LANGUAGE_SETS[i][1]);
}
}
private static LanguageConfig languageConfigFor(String label) {
return LANGUAGE_CONFIGS_BY_LABEL.get(label);
}
private static class CancelListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
private class GoListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
new Thread(new Runnable() {
@Override
public void run() {
tokenizingFilesBar.setValue(0);
tokenizingFilesBar.setString("");
resultsTextArea.setText("");
phaseLabel.setText("");
timeField.setText("");
go();
}
}).start();
}
}
private class SaveListener implements ActionListener {
final Renderer renderer;
SaveListener(Renderer theRenderer) {
renderer = theRenderer;
}
@Override
public void actionPerformed(ActionEvent evt) {
JFileChooser fcSave = new JFileChooser();
int ret = fcSave.showSaveDialog(GUI.this.frame);
File f = fcSave.getSelectedFile();
if (f == null || ret != JFileChooser.APPROVE_OPTION) {
return;
}
if (!f.canWrite()) {
PrintWriter pw = null;
try {
pw = new PrintWriter(new FileOutputStream(f));
pw.write(renderer.render(matches.iterator()));
pw.flush();
JOptionPane.showMessageDialog(frame, "Saved " + matches.size() + " matches");
} catch (IOException e) {
error("Couldn't save file" + f.getAbsolutePath(), e);
} finally {
IOUtils.closeQuietly(pw);
}
} else {
error("Could not write to file " + f.getAbsolutePath(), null);
}
}
private void error(String message, Exception e) {
if (e != null) {
e.printStackTrace();
}
JOptionPane.showMessageDialog(GUI.this.frame, message);
}
}
private class BrowseListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser(rootDirectoryField.getText());
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
fc.showDialog(frame, "Select");
if (fc.getSelectedFile() != null) {
rootDirectoryField.setText(fc.getSelectedFile().getAbsolutePath());
}
}
}
private class AlignmentRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = -2190382865483285032L;
private int[] alignments;
AlignmentRenderer(int[] theAlignments) {
alignments = theAlignments;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setHorizontalAlignment(alignments[column]);
return this;
}
}
private JTextField rootDirectoryField = new JTextField(System.getProperty("user.home"));
private JTextField minimumLengthField = new JTextField(Integer.toString(DEFAULT_CPD_MINIMUM_LENGTH));
private JTextField encodingField = new JTextField(System.getProperty("file.encoding"));
private JTextField timeField = new JTextField(6);
private JLabel phaseLabel = new JLabel();
private JProgressBar tokenizingFilesBar = new JProgressBar();
private JTextArea resultsTextArea = new JTextArea();
private JCheckBox recurseCheckbox = new JCheckBox("", true);
private JCheckBox ignoreIdentifiersCheckbox = new JCheckBox("", false);
private JCheckBox ignoreLiteralsCheckbox = new JCheckBox("", false);
private JCheckBox ignoreAnnotationsCheckbox = new JCheckBox("", false);
private JCheckBox ignoreUsingsCheckbox = new JCheckBox("", false);
private JComboBox<String> languageBox = new JComboBox<>();
private JTextField extensionField = new JTextField();
private JLabel extensionLabel = new JLabel("Extension:", SwingConstants.RIGHT);
private JTable resultsTable = new JTable();
private JButton goButton;
private JButton cancelButton;
private JPanel progressPanel;
private JFrame frame;
private boolean trimLeadingWhitespace;
private List<Match> matches = new ArrayList<>();
private void addSaveOptionsTo(JMenu menu) {
JMenuItem saveItem;
for (int i = 0; i < RENDERER_SETS.length; i++) {
saveItem = new JMenuItem("Save as " + RENDERER_SETS[i][0]);
saveItem.addActionListener(new SaveListener((Renderer) RENDERER_SETS[i][1]));
menu.add(saveItem);
}
}
public GUI() {
frame = new JFrame("PMD Duplicate Code Detector (v " + PMD.VERSION + ')');
timeField.setEditable(false);
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic('f');
addSaveOptionsTo(fileMenu);
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.setMnemonic('x');
exitItem.addActionListener(new CancelListener());
fileMenu.add(exitItem);
JMenu viewMenu = new JMenu("View");
fileMenu.setMnemonic('v');
JMenuItem trimItem = new JCheckBoxMenuItem("Trim leading whitespace");
trimItem.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
AbstractButton button = (AbstractButton) e.getItem();
GUI.this.trimLeadingWhitespace = button.isSelected();
}
});
viewMenu.add(trimItem);
JMenuBar menuBar = new JMenuBar();
menuBar.add(fileMenu);
menuBar.add(viewMenu);
frame.setJMenuBar(menuBar);
// first make all the buttons
JButton browseButton = new JButton("Browse");
browseButton.setMnemonic('b');
browseButton.addActionListener(new BrowseListener());
goButton = new JButton("Go");
goButton.setMnemonic('g');
goButton.addActionListener(new GoListener());
cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new CancelListener());
JPanel settingsPanel = makeSettingsPanel(browseButton, goButton, cancelButton);
progressPanel = makeProgressPanel();
JPanel resultsPanel = makeResultsPanel();
adjustLanguageControlsFor((LanguageConfig) LANGUAGE_SETS[0][1]);
frame.getContentPane().setLayout(new BorderLayout());
JPanel topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
topPanel.add(settingsPanel, BorderLayout.NORTH);
topPanel.add(progressPanel, BorderLayout.CENTER);
setProgressControls(false); // not running now
frame.getContentPane().add(topPanel, BorderLayout.NORTH);
frame.getContentPane().add(resultsPanel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private void adjustLanguageControlsFor(LanguageConfig current) {
ignoreIdentifiersCheckbox.setEnabled(current.canIgnoreIdentifiers());
ignoreLiteralsCheckbox.setEnabled(current.canIgnoreLiterals());
ignoreAnnotationsCheckbox.setEnabled(current.canIgnoreAnnotations());
ignoreUsingsCheckbox.setEnabled(current.canIgnoreUsings());
extensionField.setText(current.extensions()[0]);
boolean enableExtension = current.extensions()[0].length() == 0;
extensionField.setEnabled(enableExtension);
extensionLabel.setEnabled(enableExtension);
}
private JPanel makeSettingsPanel(JButton browseButton, JButton goButton, JButton cxButton) {
JPanel settingsPanel = new JPanel();
GridBagHelper helper = new GridBagHelper(settingsPanel, new double[] { 0.2, 0.7, 0.1, 0.1 });
helper.addLabel("Root source directory:");
helper.add(rootDirectoryField);
helper.add(browseButton, 2);
helper.nextRow();
helper.addLabel("Report duplicate chunks larger than:");
minimumLengthField.setColumns(4);
helper.add(minimumLengthField);
helper.addLabel("Language:");
for (int i = 0; i < LANGUAGE_SETS.length; i++) {
languageBox.addItem(String.valueOf(LANGUAGE_SETS[i][0]));
}
languageBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
adjustLanguageControlsFor(languageConfigFor((String) languageBox.getSelectedItem()));
}
});
helper.add(languageBox);
helper.nextRow();
helper.addLabel("Also scan subdirectories?");
helper.add(recurseCheckbox);
helper.add(extensionLabel);
helper.add(extensionField);
helper.nextRow();
helper.addLabel("Ignore literals?");
helper.add(ignoreLiteralsCheckbox);
helper.addLabel("");
helper.addLabel("");
helper.nextRow();
helper.nextRow();
helper.addLabel("Ignore identifiers?");
helper.add(ignoreIdentifiersCheckbox);
helper.addLabel("");
helper.addLabel("");
helper.nextRow();
helper.nextRow();
helper.addLabel("Ignore annotations?");
helper.add(ignoreAnnotationsCheckbox);
helper.addLabel("");
helper.addLabel("");
helper.nextRow();
helper.nextRow();
helper.addLabel("Ignore usings?");
helper.add(ignoreUsingsCheckbox);
helper.add(goButton);
helper.add(cxButton);
helper.nextRow();
helper.addLabel("File encoding (defaults based upon locale):");
encodingField.setColumns(1);
helper.add(encodingField);
helper.addLabel("");
helper.addLabel("");
helper.nextRow();
// settingsPanel.setBorder(BorderFactory.createTitledBorder("Settings"));
return settingsPanel;
}
private JPanel makeProgressPanel() {
JPanel progressPanel = new JPanel();
final double[] weights = { 0.0, 0.8, 0.4, 0.2 };
GridBagHelper helper = new GridBagHelper(progressPanel, weights);
helper.addLabel("Tokenizing files:");
helper.add(tokenizingFilesBar, 3);
helper.nextRow();
helper.addLabel("Phase:");
helper.add(phaseLabel);
helper.addLabel("Time elapsed:");
helper.add(timeField);
helper.nextRow();
progressPanel.setBorder(BorderFactory.createTitledBorder("Progress"));
return progressPanel;
}
private JPanel makeResultsPanel() {
JPanel resultsPanel = new JPanel();
resultsPanel.setLayout(new BorderLayout());
JScrollPane areaScrollPane = new JScrollPane(resultsTextArea);
resultsTextArea.setEditable(false);
areaScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
areaScrollPane.setPreferredSize(new Dimension(600, 300));
resultsPanel.add(makeMatchList(), BorderLayout.WEST);
resultsPanel.add(areaScrollPane, BorderLayout.CENTER);
return resultsPanel;
}
private void populateResultArea() {
int[] selectionIndices = resultsTable.getSelectedRows();
TableModel model = resultsTable.getModel();
List<Match> selections = new ArrayList<>(selectionIndices.length);
for (int i = 0; i < selectionIndices.length; i++) {
selections.add((Match) model.getValueAt(selectionIndices[i], 99));
}
String report = new SimpleRenderer(trimLeadingWhitespace).render(selections.iterator());
resultsTextArea.setText(report);
resultsTextArea.setCaretPosition(0); // move to the top
}
private void copyMatchListSelectionsToClipboard() {
int[] selectionIndices = resultsTable.getSelectedRows();
int colCount = resultsTable.getColumnCount();
StringBuilder sb = new StringBuilder();
for (int r = 0; r < selectionIndices.length; r++) {
if (r > 0) {
sb.append('\n');
}
sb.append(resultsTable.getValueAt(selectionIndices[r], 0));
for (int c = 1; c < colCount; c++) {
sb.append('\t');
sb.append(resultsTable.getValueAt(selectionIndices[r], c));
}
}
StringSelection ss = new StringSelection(sb.toString());
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
}
private void deleteMatchlistSelections() {
int[] selectionIndices = resultsTable.getSelectedRows();
for (int i = selectionIndices.length - 1; i >= 0; i--) {
matches.remove(selectionIndices[i]);
}
resultsTable.getSelectionModel().clearSelection();
resultsTable.addNotify();
}
private JComponent makeMatchList() {
resultsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
populateResultArea();
}
});
resultsTable.registerKeyboardAction(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
copyMatchListSelectionsToClipboard();
}
}, "Copy", COPY_KEY_STROKE, JComponent.WHEN_FOCUSED);
resultsTable.registerKeyboardAction(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteMatchlistSelections();
}
}, "Del", DELETE_KEY_STROKE, JComponent.WHEN_FOCUSED);
int[] alignments = new int[matchColumns.length];
for (int i = 0; i < alignments.length; i++) {
alignments[i] = matchColumns[i].alignment();
}
resultsTable.setDefaultRenderer(Object.class, new AlignmentRenderer(alignments));
final JTableHeader header = resultsTable.getTableHeader();
header.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
sortOnColumn(header.columnAtPoint(new Point(e.getX(), e.getY())));
}
});
return new JScrollPane(resultsTable);
}
private boolean isLegalPath(String path, LanguageConfig config) {
String[] extensions = config.extensions();
for (int i = 0; i < extensions.length; i++) {
if (path.endsWith(extensions[i]) && extensions[i].length() > 0) {
return true;
}
}
return false;
}
private String setLabelFor(Match match) {
Set<String> sourceIDs = new HashSet<>(match.getMarkCount());
for (Iterator<Mark> occurrences = match.iterator(); occurrences.hasNext();) {
sourceIDs.add(occurrences.next().getFilename());
}
String label;
if (sourceIDs.size() == 1) {
String sourceId = sourceIDs.iterator().next();
int separatorPos = sourceId.lastIndexOf(File.separatorChar);
label = "..." + sourceId.substring(separatorPos);
} else {
label = "(" + sourceIDs.size() + " separate files)";
}
match.setLabel(label);
return label;
}
private void setProgressControls(boolean isRunning) {
progressPanel.setVisible(isRunning);
goButton.setEnabled(!isRunning);
cancelButton.setEnabled(isRunning);
}
private void go() {
try {
File dirPath = new File(rootDirectoryField.getText());
if (!dirPath.exists()) {
JOptionPane.showMessageDialog(frame, "Can't read from that root source directory", "Error",
JOptionPane.ERROR_MESSAGE);
return;
}
setProgressControls(true);
Properties p = new Properties();
CPDConfiguration config = new CPDConfiguration();
config.setMinimumTileSize(Integer.parseInt(minimumLengthField.getText()));
config.setEncoding(encodingField.getText());
config.setIgnoreIdentifiers(ignoreIdentifiersCheckbox.isSelected());
config.setIgnoreLiterals(ignoreLiteralsCheckbox.isSelected());
config.setIgnoreAnnotations(ignoreAnnotationsCheckbox.isSelected());
config.setIgnoreUsings(ignoreUsingsCheckbox.isSelected());
p.setProperty(LanguageFactory.EXTENSION, extensionField.getText());
LanguageConfig conf = languageConfigFor((String) languageBox.getSelectedItem());
Language language = conf.languageFor(p);
config.setLanguage(language);
CPDConfiguration.setSystemProperties(config);
CPD cpd = new CPD(config);
cpd.setCpdListener(this);
tokenizingFilesBar.setMinimum(0);
phaseLabel.setText("");
if (isLegalPath(dirPath.getPath(), conf)) { // should use the
// language file filter
// instead?
cpd.add(dirPath);
} else {
if (recurseCheckbox.isSelected()) {
cpd.addRecursively(dirPath);
} else {
cpd.addAllInDirectory(dirPath);
}
}
Timer t = createTimer();
t.start();
cpd.go();
t.stop();
matches = new ArrayList<>();
for (Iterator<Match> i = cpd.getMatches(); i.hasNext();) {
Match match = i.next();
setLabelFor(match);
matches.add(match);
}
setListDataFrom(matches);
String report = new SimpleRenderer().render(cpd.getMatches());
if (report.length() == 0) {
JOptionPane.showMessageDialog(frame,
"Done. Couldn't find any duplicates longer than " + minimumLengthField.getText() + " tokens");
} else {
resultsTextArea.setText(report);
}
} catch (IOException t) {
t.printStackTrace();
JOptionPane.showMessageDialog(frame, "Halted due to " + t.getClass().getName() + "; " + t.getMessage());
} catch (RuntimeException t) {
t.printStackTrace();
JOptionPane.showMessageDialog(frame, "Halted due to " + t.getClass().getName() + "; " + t.getMessage());
}
setProgressControls(false);
}
private Timer createTimer() {
final long start = System.currentTimeMillis();
Timer t = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
long now = System.currentTimeMillis();
long elapsedMillis = now - start;
long elapsedSeconds = elapsedMillis / 1000;
long minutes = (long) Math.floor(elapsedSeconds / 60);
long seconds = elapsedSeconds - (minutes * 60);
timeField.setText(formatTime(minutes, seconds));
}
});
return t;
}
private static String formatTime(long minutes, long seconds) {
StringBuilder sb = new StringBuilder(5);
if (minutes < 10) {
sb.append('0');
}
sb.append(minutes).append(':');
if (seconds < 10) {
sb.append('0');
}
sb.append(seconds);
return sb.toString();
}
private interface SortingTableModel<E> extends TableModel {
int sortColumn();
void sortColumn(int column);
boolean sortDescending();
void sortDescending(boolean flag);
void sort(Comparator<E> comparator);
}
private TableModel tableModelFrom(final List<Match> items) {
TableModel model = new SortingTableModel<Match>() {
private int sortColumn;
private boolean sortDescending;
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Match match = items.get(rowIndex);
switch (columnIndex) {
case 0:
return match.getLabel();
case 2:
return Integer.toString(match.getLineCount());
case 1:
return match.getMarkCount() > 2 ? Integer.toString(match.getMarkCount()) : "";
case 99:
return match;
default:
return "";
}
}
@Override
public int getColumnCount() {
return matchColumns.length;
}
@Override
public int getRowCount() {
return items.size();
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Object.class;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
}
@Override
public String getColumnName(int i) {
return matchColumns[i].label();
}
@Override
public void addTableModelListener(TableModelListener l) {
}
@Override
public void removeTableModelListener(TableModelListener l) {
}
@Override
public int sortColumn() {
return sortColumn;
}
@Override
public void sortColumn(int column) {
sortColumn = column;
}
@Override
public boolean sortDescending() {
return sortDescending;
}
@Override
public void sortDescending(boolean flag) {
sortDescending = flag;
}
@Override
public void sort(Comparator<Match> comparator) {
Collections.sort(items, comparator);
if (sortDescending) {
Collections.reverse(items);
}
}
};
return model;
}
private void sortOnColumn(int columnIndex) {
Comparator<Match> comparator = matchColumns[columnIndex].sorter();
SortingTableModel<Match> model = (SortingTableModel<Match>) resultsTable.getModel();
if (model.sortColumn() == columnIndex) {
model.sortDescending(!model.sortDescending());
}
model.sortColumn(columnIndex);
model.sort(comparator);
resultsTable.getSelectionModel().clearSelection();
resultsTable.repaint();
}
private void setListDataFrom(List<Match> matches) {
resultsTable.setModel(tableModelFrom(matches));
TableColumnModel colModel = resultsTable.getColumnModel();
TableColumn column;
int width;
for (int i = 0; i < matchColumns.length; i++) {
if (matchColumns[i].width() > 0) {
column = colModel.getColumn(i);
width = matchColumns[i].width();
column.setPreferredWidth(width);
column.setMinWidth(width);
column.setMaxWidth(width);
}
}
}
// CPDListener
@Override
public void phaseUpdate(int phase) {
phaseLabel.setText(getPhaseText(phase));
}
public String getPhaseText(int phase) {
switch (phase) {
case CPDListener.INIT:
return "Initializing";
case CPDListener.HASH:
return "Hashing";
case CPDListener.MATCH:
return "Matching";
case CPDListener.GROUPING:
return "Grouping";
case CPDListener.DONE:
return "Done";
default:
return "Unknown";
}
}
@Override
public void addedFile(int fileCount, File file) {
tokenizingFilesBar.setMaximum(fileCount);
tokenizingFilesBar.setValue(tokenizingFilesBar.getValue() + 1);
}
// CPDListener
public static void main(String[] args) {
// this should prevent the disk not found popup
// System.setSecurityManager(null);
new GUI();
}
}