GUI xref

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

AltStyle によって変換されたページ (->オリジナル) /