1 4 package net.sourceforge.pmd.cpd; 5 6 import javax.swing.*; 7 import javax.swing.event.ListSelectionEvent ; 8 import javax.swing.event.ListSelectionListener ; 9 import javax.swing.event.TableModelListener ; 10 import javax.swing.table.DefaultTableCellRenderer ; 11 import javax.swing.table.JTableHeader ; 12 import javax.swing.table.TableColumn ; 13 import javax.swing.table.TableColumnModel ; 14 import javax.swing.table.TableModel ; 15 import java.awt.BorderLayout ; 16 import java.awt.Component ; 17 import java.awt.Dimension ; 18 import java.awt.Point ; 19 import java.awt.Toolkit ; 20 import java.awt.datatransfer.StringSelection ; 21 import java.awt.event.ActionEvent ; 22 import java.awt.event.ActionListener ; 23 import java.awt.event.ItemEvent ; 24 import java.awt.event.ItemListener ; 25 import java.awt.event.KeyEvent ; 26 import java.awt.event.MouseAdapter ; 27 import java.awt.event.MouseEvent ; 28 import java.io.File ; 29 import java.io.FileOutputStream ; 30 import java.io.IOException ; 31 import java.io.PrintWriter ; 32 import java.util.ArrayList ; 33 import java.util.Collections ; 34 import java.util.Comparator ; 35 import java.util.HashMap ; 36 import java.util.HashSet ; 37 import java.util.Iterator ; 38 import java.util.List ; 39 import java.util.Map ; 40 import java.util.Properties ; 41 import java.util.Set ; 42 43 public class GUI implements CPDListener { 44 45 private interface Renderer { 46 String render(Iterator items); 47 } 48 49 private static final Object [][] rendererSets = new Object [][] { 50 { "Text", new Renderer() { public String render(Iterator items) { return new SimpleRenderer().render(items); } } }, 51 { "XML", new Renderer() { public String render(Iterator items) { return new XMLRenderer().render(items); } } }, 52 { "CSV (comma)",new Renderer() { public String render(Iterator items) { return new CSVRenderer(',').render(items); } } }, 53 { "CSV (tab)", new Renderer() { public String render(Iterator items) { return new CSVRenderer('\t').render(items); } } } 54 }; 55 56 private interface LanguageConfig { 57 Language languageFor(LanguageFactory lf, Properties p); 58 boolean ignoreLiteralsByDefault(); 59 String [] extensions(); 60 }; 61 62 private static final Object [][] languageSets = new Object [][] { 63 {"Java", new LanguageConfig() { 64 public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.JAVA_KEY); } 65 public boolean ignoreLiteralsByDefault() { return true; } 66 public String [] extensions() { return new String [] {".java", ".class" }; }; } }, 67 {"JSP", new LanguageConfig() { 68 public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.JSP_KEY); } 69 public boolean ignoreLiteralsByDefault() { return false; } 70 public String [] extensions() { return new String [] {".jsp" }; }; } }, 71 {"C++", new LanguageConfig() { 72 public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.CPP_KEY); } 73 public boolean ignoreLiteralsByDefault() { return false; } 74 public String [] extensions() { return new String [] {".cpp", ".c" }; }; } }, 75 {"Ruby", new LanguageConfig() { 76 public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.RUBY_KEY); } 77 public boolean ignoreLiteralsByDefault() { return false; } 78 public String [] extensions() { return new String [] {".rb" }; }; } }, 79 {"by extension...", new LanguageConfig() { 80 public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.BY_EXTENSION, p); } 81 public boolean ignoreLiteralsByDefault() { return false; } 82 public String [] extensions() { return new String [] {"" }; }; } }, 83 {"PHP", new LanguageConfig() { 84 public Language languageFor(LanguageFactory lf, Properties p) { return lf.createLanguage(LanguageFactory.PHP_KEY); } 85 public boolean ignoreLiteralsByDefault() { return false; } 86 public String [] extensions() { return new String [] {".php" }; }; } }, 87 }; 88 89 private static final int defaultCPDMinimumLength = 75; 90 private static final Map langConfigsByLabel = new HashMap (languageSets.length); 91 private static final KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C,ActionEvent.CTRL_MASK,false); 92 private static final KeyStroke delete = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0); 93 94 private class ColumnSpec { 95 private String label; 96 private int alignment; 97 private int width; 98 private Comparator sorter; 99 100 public ColumnSpec(String aLabel, int anAlignment, int aWidth, Comparator aSorter) { 101 label = aLabel; 102 alignment = anAlignment; 103 width = aWidth; 104 sorter = aSorter; 105 } 106 public String label() { return label; }; 107 public int alignment() { return alignment; }; 108 public int width() { return width; }; 109 public Comparator sorter() { return sorter; }; 110 } 111 112 private final ColumnSpec[] matchColumns = new ColumnSpec[] { 113 new ColumnSpec("Source", SwingConstants.LEFT, -1, Match.LabelComparator), 114 new ColumnSpec("Matches", SwingConstants.RIGHT, 60, Match.MatchesComparator), 115 new ColumnSpec("Lines", SwingConstants.RIGHT, 45, Match.LinesComparator), 116 }; 117 118 static { 119 for (int i=0; i<languageSets.length; i++) { 120 langConfigsByLabel.put(languageSets[i][0], languageSets[i][1]); 121 } 122 } 123 124 private static LanguageConfig languageConfigFor(String label) { 125 return (LanguageConfig)langConfigsByLabel.get(label); 126 } 127 128 private static class CancelListener implements ActionListener { 129 public void actionPerformed(ActionEvent e) { 130 System.exit(0); 131 } 132 } 133 134 private class GoListener implements ActionListener { 135 public void actionPerformed(ActionEvent e) { 136 new Thread (new Runnable () { 137 public void run() { 138 tokenizingFilesBar.setValue(0); 139 tokenizingFilesBar.setString(""); 140 resultsTextArea.setText(""); 141 phaseLabel.setText(""); 142 timeField.setText(""); 143 go(); 144 } 145 }).start(); 146 } 147 } 148 149 private class SaveListener implements ActionListener { 150 151 final Renderer renderer; 152 153 public SaveListener(Renderer theRenderer) { 154 renderer = theRenderer; 155 } 156 157 public void actionPerformed(ActionEvent evt) { 158 JFileChooser fcSave = new JFileChooser(); 159 int ret = fcSave.showSaveDialog(GUI.this.frame); 160 File f = fcSave.getSelectedFile(); 161 if (f == null || ret != JFileChooser.APPROVE_OPTION) return; 162 163 if (!f.canWrite()) { 164 PrintWriter pw = null; 165 try { 166 pw = new PrintWriter (new FileOutputStream (f)); 167 pw.write(renderer.render(matches.iterator())); 168 pw.flush(); 169 JOptionPane.showMessageDialog(frame, "Saved " + matches.size() + " matches"); 170 } catch (IOException e) { 171 error("Couldn't save file" + f.getAbsolutePath(), e); 172 } finally { 173 if (pw != null) pw.close(); 174 } 175 } else { 176 error("Could not write to file " + f.getAbsolutePath(), null); 177 } 178 } 179 180 private void error(String message, Exception e) { 181 if (e != null) { 182 e.printStackTrace(); 183 } 184 JOptionPane.showMessageDialog(GUI.this.frame, message); 185 } 186 187 } 188 189 private class BrowseListener implements ActionListener { 190 public void actionPerformed(ActionEvent e) { 191 JFileChooser fc = new JFileChooser(rootDirectoryField.getText()); 192 fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 193 fc.showDialog(frame, "Select"); 194 if (fc.getSelectedFile() != null) { 195 rootDirectoryField.setText(fc.getSelectedFile().getAbsolutePath()); 196 } 197 } 198 } 199 200 private class AlignmentRenderer extends DefaultTableCellRenderer { 201 202 private int[] alignments; 203 204 public AlignmentRenderer(int[] theAlignments) { 205 alignments = theAlignments; 206 }; 207 208 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 209 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 210 211 setHorizontalAlignment(alignments[column]); 212 213 return this; 214 } 215 } 216 217 private JTextField rootDirectoryField = new JTextField(System.getProperty("user.home")); 218 private JTextField minimumLengthField = new JTextField(Integer.toString(defaultCPDMinimumLength)); 219 private JTextField timeField = new JTextField(6); 220 private JLabel phaseLabel = new JLabel(); 221 private JProgressBar tokenizingFilesBar = new JProgressBar(); 222 private JTextArea resultsTextArea = new JTextArea(); 223 private JCheckBox recurseCheckbox = new JCheckBox("", true); 224 private JCheckBox ignoreLiteralsCheckbox = new JCheckBox("", false); 225 private JComboBox languageBox = new JComboBox(); 226 private JTextField extensionField = new JTextField(); 227 private JLabel extensionLabel = new JLabel("Extension:", SwingConstants.RIGHT); 228 private JTable resultsTable = new JTable(); 229 private JButton goButton; 230 private JButton cancelButton; 231 private JPanel progressPanel; 232 private JFrame frame; 233 private boolean trimLeadingWhitespace; 234 235 private List matches = new ArrayList (); 236 237 private void addSaveOptionsTo(JMenu menu) { 238 239 JMenuItem saveItem; 240 241 for (int i=0; i<rendererSets.length; i++) { 242 saveItem = new JMenuItem("Save as " + rendererSets[i][0]); 243 saveItem.addActionListener(new SaveListener((Renderer)rendererSets[i][1])); 244 menu.add(saveItem); 245 } 246 } 247 248 public GUI() { 249 frame = new JFrame("PMD Duplicate Code Detector"); 250 251 timeField.setEditable(false); 252 253 JMenu fileMenu = new JMenu("File"); 254 fileMenu.setMnemonic('f'); 255 256 addSaveOptionsTo(fileMenu); 257 258 JMenuItem exitItem = new JMenuItem("Exit"); 259 exitItem.setMnemonic('x'); 260 exitItem.addActionListener(new CancelListener()); 261 fileMenu.add(exitItem); 262 JMenu viewMenu = new JMenu("View"); 263 fileMenu.setMnemonic('v'); 264 JMenuItem trimItem = new JCheckBoxMenuItem("Trim leading whitespace"); 265 trimItem.addItemListener(new ItemListener () { 266 public void itemStateChanged(ItemEvent e) { 267 AbstractButton button = (AbstractButton)e.getItem(); 268 GUI.this.trimLeadingWhitespace = button.isSelected(); 269 } 270 }); 271 viewMenu.add(trimItem); 272 JMenuBar menuBar = new JMenuBar(); 273 menuBar.add(fileMenu); 274 menuBar.add(viewMenu); 275 frame.setJMenuBar(menuBar); 276 277 JButton browseButton = new JButton("Browse"); 279 browseButton.setMnemonic('b'); 280 browseButton.addActionListener(new BrowseListener()); 281 goButton = new JButton("Go"); 282 goButton.setMnemonic('g'); 283 goButton.addActionListener(new GoListener()); 284 cancelButton = new JButton("Cancel"); 285 cancelButton.addActionListener(new CancelListener()); 286 287 JPanel settingsPanel = makeSettingsPanel(browseButton, goButton, cancelButton); 288 progressPanel = makeProgressPanel(); 289 JPanel resultsPanel = makeResultsPanel(); 290 291 adjustLanguageControlsFor((LanguageConfig)languageSets[0][1]); 292 293 frame.getContentPane().setLayout(new BorderLayout ()); 294 JPanel topPanel = new JPanel(); 295 topPanel.setLayout(new BorderLayout ()); 296 topPanel.add(settingsPanel, BorderLayout.NORTH); 297 topPanel.add(progressPanel, BorderLayout.CENTER); 298 setProgressControls(false); frame.getContentPane().add(topPanel, BorderLayout.NORTH); 300 frame.getContentPane().add(resultsPanel, BorderLayout.CENTER); 301 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 302 frame.pack(); 303 frame.setVisible(true); 304 } 305 306 private void adjustLanguageControlsFor(LanguageConfig current) { 307 ignoreLiteralsCheckbox.setEnabled(current.ignoreLiteralsByDefault()); 308 extensionField.setText(current.extensions()[0]); 309 boolean enableExtension = current.extensions()[0].length() == 0; 310 extensionField.setEnabled(enableExtension); 311 extensionLabel.setEnabled(enableExtension); 312 } 313 314 private JPanel makeSettingsPanel(JButton browseButton, JButton goButton, JButton cxButton) { 315 JPanel settingsPanel = new JPanel(); 316 GridBagHelper helper = new GridBagHelper(settingsPanel, new double[]{0.2, 0.7, 0.1, 0.1}); 317 helper.addLabel("Root source directory:"); 318 helper.add(rootDirectoryField); 319 helper.add(browseButton, 2); 320 helper.nextRow(); 321 helper.addLabel("Report duplicate chunks larger than:"); 322 minimumLengthField.setColumns(4); 323 helper.add(minimumLengthField); 324 helper.addLabel("Language:"); 325 for (int i=0; i<languageSets.length; i++) { 326 languageBox.addItem(languageSets[i][0]); 327 } 328 languageBox.addActionListener(new ActionListener () { 329 public void actionPerformed(ActionEvent e) { 330 adjustLanguageControlsFor( 331 languageConfigFor((String )languageBox.getSelectedItem()) 332 ); 333 } 334 }); 335 helper.add(languageBox); 336 helper.nextRow(); 337 helper.addLabel("Also scan subdirectories?"); 338 helper.add(recurseCheckbox); 339 340 helper.add(extensionLabel); 341 helper.add(extensionField); 342 343 helper.nextRow(); 344 helper.addLabel("Ignore literals and identifiers?"); 345 helper.add(ignoreLiteralsCheckbox); 346 helper.add(goButton); 347 helper.add(cxButton); 348 helper.nextRow(); 349 return settingsPanel; 351 } 352 353 private JPanel makeProgressPanel() { 354 JPanel progressPanel = new JPanel(); 355 final double[] weights = {0.0, 0.8, 0.4, 0.2}; 356 GridBagHelper helper = new GridBagHelper(progressPanel, weights); 357 helper.addLabel("Tokenizing files:"); 358 helper.add(tokenizingFilesBar, 3); 359 helper.nextRow(); 360 helper.addLabel("Phase:"); 361 helper.add(phaseLabel); 362 helper.addLabel("Time elapsed:"); 363 helper.add(timeField); 364 helper.nextRow(); 365 progressPanel.setBorder(BorderFactory.createTitledBorder("Progress")); 366 return progressPanel; 367 } 368 369 private JPanel makeResultsPanel() { 370 JPanel resultsPanel = new JPanel(); 371 resultsPanel.setLayout(new BorderLayout ()); 372 JScrollPane areaScrollPane = new JScrollPane(resultsTextArea); 373 resultsTextArea.setEditable(false); 374 areaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 375 areaScrollPane.setPreferredSize(new Dimension (600, 300)); 376 377 resultsPanel.add(makeMatchList(), BorderLayout.WEST); 378 resultsPanel.add(areaScrollPane, BorderLayout.CENTER); 379 return resultsPanel; 380 } 381 382 private void populateResultArea() { 383 int[] selectionIndices = resultsTable.getSelectedRows(); 384 TableModel model = resultsTable.getModel(); 385 List selections = new ArrayList (selectionIndices.length); 386 for (int i=0; i<selectionIndices.length; i++) { 387 selections.add(model.getValueAt(selectionIndices[i], 99)); 388 } 389 String report = new SimpleRenderer(trimLeadingWhitespace).render(selections.iterator()); 390 resultsTextArea.setText(report); 391 resultsTextArea.setCaretPosition(0); } 393 394 private void copyMatchListSelectionsToClipboard() { 395 396 int[] selectionIndices = resultsTable.getSelectedRows(); 397 int colCount = resultsTable.getColumnCount(); 398 399 StringBuffer sb = new StringBuffer (); 400 401 for (int r=0; r<selectionIndices.length; r++) { 402 if (r > 0) sb.append('\n'); 403 sb.append(resultsTable.getValueAt(selectionIndices[r], 0)); 404 for (int c=1; c<colCount; c++) { 405 sb.append('\t'); 406 sb.append(resultsTable.getValueAt(selectionIndices[r], c)); 407 } 408 } 409 410 StringSelection ss = new StringSelection (sb.toString()); 411 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null); 412 } 413 414 private void deleteMatchlistSelections() { 415 416 int[] selectionIndices = resultsTable.getSelectedRows(); 417 418 for (int i=selectionIndices.length-1; i >=0; i--) { 419 matches.remove(selectionIndices[i]); 420 } 421 422 resultsTable.getSelectionModel().clearSelection(); 423 resultsTable.addNotify(); 424 } 425 426 private JComponent makeMatchList() { 427 428 resultsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener () { 429 public void valueChanged(ListSelectionEvent e) { 430 populateResultArea(); 431 }}); 432 433 resultsTable.registerKeyboardAction(new ActionListener () { 434 public void actionPerformed(ActionEvent e) { copyMatchListSelectionsToClipboard(); } 435 },"Copy", copy, JComponent.WHEN_FOCUSED); 436 437 resultsTable.registerKeyboardAction(new ActionListener () { 438 public void actionPerformed(ActionEvent e) { deleteMatchlistSelections(); } 439 },"Del", delete, JComponent.WHEN_FOCUSED); 440 441 int[] alignments = new int[matchColumns.length]; 442 for (int i=0; i<alignments.length; i++) alignments[i] = matchColumns[i].alignment(); 443 444 resultsTable.setDefaultRenderer(Object .class, new AlignmentRenderer(alignments)); 445 446 final JTableHeader header = resultsTable.getTableHeader(); 447 header.addMouseListener( new MouseAdapter () { 448 public void mouseClicked(MouseEvent e) { 449 sortOnColumn(header.columnAtPoint(new Point (e.getX(), e.getY()))); 450 } 451 }); 452 453 return new JScrollPane(resultsTable); 454 } 455 456 private boolean isLegalPath(String path, LanguageConfig config) { 457 String [] extensions = config.extensions(); 458 for (int i=0; i<extensions.length; i++) { 459 if (path.endsWith(extensions[i]) && extensions[i].length() > 0) return true; 460 } 461 return false; 462 } 463 464 private String setLabelFor(Match match) { 465 466 Set sourceIDs = new HashSet (match.getMarkCount()); 467 for (Iterator occurrences = match.iterator(); occurrences.hasNext();) { 468 sourceIDs.add( ((TokenEntry) occurrences.next()).getTokenSrcID()); 469 } 470 String label; 471 472 if (sourceIDs.size() == 1) { 473 String sourceId = (String )sourceIDs.iterator().next(); 474 int separatorPos = sourceId.lastIndexOf(File.separatorChar); 475 label = "..." + sourceId.substring(separatorPos); 476 } else { 477 label = "(" + sourceIDs.size() + " separate files)"; 478 } 479 480 match.setLabel(label); 481 return label; 482 } 483 484 private void setProgressControls(boolean isRunning) { 485 progressPanel.setVisible(isRunning); 486 goButton.setEnabled(!isRunning); 487 cancelButton.setEnabled(isRunning); 488 } 489 490 private void go() { 491 String dirPath = rootDirectoryField.getText(); 492 try { 493 if (!(new File (dirPath)).exists()) { 494 JOptionPane.showMessageDialog(frame, 495 "Can't read from that root source directory", 496 "Error", JOptionPane.ERROR_MESSAGE); 497 return; 498 } 499 500 setProgressControls(true); 501 502 Properties p = new Properties (); 503 p.setProperty(JavaTokenizer.IGNORE_LITERALS, String.valueOf(ignoreLiteralsCheckbox.isSelected())); 504 p.setProperty(LanguageFactory.EXTENSION, extensionField.getText()); 505 LanguageConfig conf = languageConfigFor((String )languageBox.getSelectedItem()); 506 Language language = conf.languageFor(new LanguageFactory(), p); 507 CPD cpd = new CPD(Integer.parseInt(minimumLengthField.getText()), language); 508 cpd.setCpdListener(this); 509 tokenizingFilesBar.setMinimum(0); 510 phaseLabel.setText(""); 511 if (isLegalPath(dirPath, conf)) { cpd.add(new File (dirPath)); 513 } else { 514 if (recurseCheckbox.isSelected()) { 515 cpd.addRecursively(dirPath); 516 } else { 517 cpd.addAllInDirectory(dirPath); 518 } 519 } 520 final long start = System.currentTimeMillis(); 521 Timer t = new Timer(1000, new ActionListener () { 522 public void actionPerformed(ActionEvent e) { 523 long now = System.currentTimeMillis(); 524 long elapsedMillis = now - start; 525 long elapsedSeconds = elapsedMillis / 1000; 526 long minutes = (long) Math.floor(elapsedSeconds / 60); 527 long seconds = elapsedSeconds - (minutes * 60); 528 timeField.setText("" 529 + munge(String.valueOf(minutes)) 530 + ':' 531 + munge(String.valueOf(seconds))); 532 } 533 534 private String munge(String in) { 535 if (in.length() < 2) { 536 in = "0" + in; 537 } 538 return in; 539 } 540 }); 541 t.start(); 542 cpd.go(); 543 t.stop(); 544 545 matches = new ArrayList (); 546 Match match; 547 for (Iterator i = cpd.getMatches(); i.hasNext();) { 548 match = (Match)i.next(); 549 setLabelFor(match); 550 matches.add(match); 551 } 552 553 String report = new SimpleRenderer().render(cpd.getMatches()); 554 if (report.length() == 0) { 555 JOptionPane.showMessageDialog(frame, 556 "Done; couldn't find any duplicates longer than " + minimumLengthField.getText() + " tokens"); 557 } else { 558 resultsTextArea.setText(report); 559 setListDataFrom(cpd.getMatches()); 560 561 } 562 } catch (Throwable t) { 563 t.printStackTrace(); 564 JOptionPane.showMessageDialog(frame, "Halted due to " + t.getClass().getName() + "; " + t.getMessage()); 565 } 566 setProgressControls(false); 567 } 568 569 private interface SortingTableModel extends TableModel { 570 public int sortColumn(); 571 public void sortColumn(int column); 572 public boolean sortDescending(); 573 public void sortDescending(boolean flag); 574 public void sort(Comparator comparator); 575 } 576 577 private TableModel tableModelFrom(final List items) { 578 579 TableModel model = new SortingTableModel() { 580 581 private int sortColumn; 582 private boolean sortDescending; 583 584 public Object getValueAt(int rowIndex, int columnIndex) { 585 Match match = (Match) items.get(rowIndex); 586 switch (columnIndex) { 587 case 0: return match.getLabel(); 588 case 2: return Integer.toString(match.getLineCount()); 589 case 1: return match.getMarkCount() > 2 ? Integer.toString(match.getMarkCount()) : ""; 590 case 99: return match; 591 } 592 return ""; 593 } 594 public int getColumnCount() { return matchColumns.length; } 595 public int getRowCount() { return items.size(); } 596 public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } 597 public Class getColumnClass(int columnIndex) { return Object .class; } 598 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { } 599 public String getColumnName(int i) { return matchColumns[i].label(); } 600 public void addTableModelListener(TableModelListener l) { } 601 public void removeTableModelListener(TableModelListener l) { } 602 public int sortColumn() { return sortColumn; }; 603 public void sortColumn(int column) { sortColumn = column; }; 604 public boolean sortDescending() { return sortDescending; }; 605 public void sortDescending(boolean flag) { sortDescending = flag; }; 606 public void sort(Comparator comparator) { 607 Collections.sort(items, comparator); 608 if (sortDescending) Collections.reverse(items); 609 } 610 }; 611 612 return model; 613 } 614 615 private void sortOnColumn(int columnIndex) { 616 Comparator comparator = matchColumns[columnIndex].sorter(); 617 SortingTableModel model = (SortingTableModel)resultsTable.getModel(); 618 if (model.sortColumn() == columnIndex) { 619 model.sortDescending(!model.sortDescending()); 620 } 621 model.sortColumn(columnIndex); 622 model.sort(comparator); 623 624 resultsTable.getSelectionModel().clearSelection(); 625 resultsTable.repaint(); 626 } 627 628 private void setListDataFrom(Iterator iter) { 629 630 resultsTable.setModel(tableModelFrom(matches)); 631 632 TableColumnModel colModel = resultsTable.getColumnModel(); 633 TableColumn column; 634 int width; 635 636 for (int i=0; i<matchColumns.length; i++) { 637 if (matchColumns[i].width() > 0) { 638 column = colModel.getColumn(i); 639 width = matchColumns[i].width(); 640 column.setPreferredWidth(width); 641 column.setMinWidth(width); 642 column.setMaxWidth(width); 643 } 644 } 645 } 646 647 public void phaseUpdate(int phase) { 649 phaseLabel.setText(getPhaseText(phase)); 650 } 651 652 public String getPhaseText(int phase) { 653 switch (phase) { 654 case CPDListener.INIT: 655 return "Initializing"; 656 case CPDListener.HASH: 657 return "Hashing"; 658 case CPDListener.MATCH: 659 return "Matching"; 660 case CPDListener.GROUPING: 661 return "Grouping"; 662 case CPDListener.DONE: 663 return "Done"; 664 default : 665 return "Unknown"; 666 } 667 } 668 669 public void addedFile(int fileCount, File file) { 670 tokenizingFilesBar.setMaximum(fileCount); 671 tokenizingFilesBar.setValue(tokenizingFilesBar.getValue() + 1); 672 } 673 675 676 public static void main(String [] args) { 677 new GUI(); 680 } 681 682 } 683 | Popular Tags |