001: package org.acm.seguin.ide.common;
002:
003: import java.awt.BorderLayout;
004:
005: import java.awt.Frame;
006:
007: import java.awt.event.ActionEvent;
008: import java.awt.event.ActionListener;
009: import java.io.IOException;
010: import java.util.ArrayList;
011: import java.util.Iterator;
012: import java.util.List;
013: import javax.swing.JButton;
014: import javax.swing.JPanel;
015: import javax.swing.JScrollPane;
016: import javax.swing.JTree;
017: import javax.swing.event.TreeSelectionEvent;
018: import javax.swing.event.TreeSelectionListener;
019: import javax.swing.tree.DefaultMutableTreeNode;
020: import javax.swing.tree.DefaultTreeModel;
021: import javax.swing.tree.TreeSelectionModel;
022:
023: import org.acm.seguin.pmd.cpd.CPD;
024: import org.acm.seguin.pmd.cpd.Mark;
025: import org.acm.seguin.pmd.cpd.Match;
026:
027: /**
028: * A GUI Component to display Duplicate code.
029: *
030: * @author Jiger Patel
031: * @created 05 Apr 2003
032: */
033:
034: public class CPDDuplicateCodeViewer extends JPanel {
035: JTree tree;
036: DefaultTreeModel treeModel = new DefaultTreeModel(
037: new DefaultMutableTreeNode("CPD Results", true));
038: Frame view;
039: private final static String NAME = "CPDDuplicateCodeViewer";
040:
041: /**
042: * Constructor for the CPDDuplicateCodeViewer object
043: *
044: * @param aView Description of Parameter
045: */
046: public CPDDuplicateCodeViewer(Frame aView) {
047: this .view = aView;
048: setLayout(new BorderLayout());
049: JButton currentFile = new JButton("Current");
050: currentFile.addActionListener(new ActionListener() {
051: public void actionPerformed(ActionEvent evnt) {
052: try {
053: IDEPlugin.cpdBuffer(view, null);
054: } catch (java.io.IOException ex) {
055: IDEPlugin.log(IDEInterface.ERROR, NAME, ex
056: .getMessage());
057: }
058: }
059: });
060:
061: JButton allBuffers = new JButton("All Buffers");
062: allBuffers.addActionListener(new ActionListener() {
063: public void actionPerformed(ActionEvent evnt) {
064: try {
065: IDEPlugin.cpdAllOpenBuffers(view);
066: } catch (java.io.IOException ex) {
067: IDEPlugin.log(IDEInterface.ERROR, NAME, ex
068: .getMessage());
069: }
070: }
071: });
072:
073: JButton currentDir = new JButton("Dir");
074: currentDir.addActionListener(new ActionListener() {
075: public void actionPerformed(ActionEvent evnt) {
076: try {
077: IDEPlugin.cpdDir(view, false);
078: } catch (java.io.IOException ex) {
079: IDEPlugin.log(IDEInterface.ERROR, NAME, ex
080: .getMessage());
081: }
082: }
083: });
084:
085: JButton currentDirRecurse = new JButton("Subdirs");
086: currentDirRecurse.addActionListener(new ActionListener() {
087: public void actionPerformed(ActionEvent evnt) {
088: try {
089: IDEPlugin.cpdDir(view, true);
090: } catch (java.io.IOException ex) {
091: IDEPlugin.log(IDEInterface.ERROR, NAME, ex
092: .getMessage());
093: }
094: }
095: });
096: JButton clearbutton = new JButton(IDEPlugin
097: .loadIcon("Clear.png"));
098: clearbutton.setBorderPainted(false);
099: clearbutton.setToolTipText(IDEPlugin
100: .getProperty("javastyle.cpd.clear.label"));
101: clearbutton.addActionListener(new ActionListener() {
102: public void actionPerformed(ActionEvent evnt) {
103: clearDuplicates();
104: refreshTree();
105: }
106: });
107:
108: final JPanel top = new JPanel();
109: top.setLayout(new BorderLayout());
110:
111: final JPanel buttons = new JPanel();
112: buttons.setLayout(new java.awt.FlowLayout());
113: buttons.add(currentFile);
114: buttons.add(allBuffers);
115: buttons.add(currentDir);
116: buttons.add(currentDirRecurse);
117: buttons.add(clearbutton);
118: top.add(new javax.swing.JLabel("check for cut&paste in:"),
119: BorderLayout.NORTH);
120: top.add(buttons, BorderLayout.CENTER);
121: add(top, BorderLayout.NORTH);
122:
123: tree = new JTree(treeModel);
124: tree.getSelectionModel().setSelectionMode(
125: TreeSelectionModel.SINGLE_TREE_SELECTION);
126: tree.addTreeSelectionListener(new TreeSelectionListener() {
127: public void valueChanged(TreeSelectionEvent evnt) {
128: DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
129: .getLastSelectedPathComponent();
130:
131: if (node != null) {
132: //System.out.println("Node is " + node +" class "+ node.getClass());
133: if (node.isLeaf() && node instanceof Duplicate) {
134: Duplicate duplicate = (Duplicate) node;
135:
136: gotoDuplicate(duplicate);
137: //System.out.println("Got!! " + duplicate);
138: }
139: }
140: }
141: });
142:
143: add(new JScrollPane(tree));
144: }
145:
146: public void setView(Frame view) {
147: this .view = view;
148: }
149:
150: /**
151: * Gets the root attribute of the CPDDuplicateCodeViewer object
152: *
153: * @return The root value
154: */
155: public DefaultMutableTreeNode getRoot() {
156: return (DefaultMutableTreeNode) treeModel.getRoot();
157: }
158:
159: /** Description of the Method */
160: public void refreshTree() {
161: treeModel.reload();
162: }
163:
164: /**
165: * Description of the Method
166: *
167: * @param duplicate Description of Parameter
168: */
169: public void gotoDuplicate(final Duplicate duplicate) {
170: if (duplicate != null) {
171: //final Buffer buffer = jEdit.openFile(view.getView(), duplicate.getFilename());
172: try {
173: final Object buffer = IDEPlugin.openFile(view,
174: duplicate.getFilename());
175:
176: IDEPlugin.runInAWTThread(new Runnable() {
177: public void run() {
178: //view.getView().setBuffer(buffer);
179: IDEPlugin.setBuffer(view, buffer);
180:
181: //int start = buffer.getLineStartOffset(duplicate.getBeginLine());
182: //int end = buffer.getLineEndOffset(duplicate.getEndLine() - 2);
183: int start = IDEPlugin.getLineStartOffset(
184: buffer, duplicate.getBeginLine() - 1);
185: int end = IDEPlugin.getLineEndOffset(buffer,
186: duplicate.getEndLine() - 1);
187:
188: IDEPlugin.log(IDEInterface.DEBUG, this
189: .getClass(), "Start Line "
190: + duplicate.getBeginLine()
191: + " End Line " + duplicate.getEndLine()
192: + " Start=" + start + " End=" + end);
193: //view.getTextArea().moveCaretPosition(start);
194: IDEPlugin
195: .moveCaretPosition(view, buffer, start);
196: //Since an AIOOB Exception is thrown if the end is the end of file. we do a -1 from end to fix it.
197: //view.getTextArea().setSelection(new Selection.Range(start, end - 1));
198: IDEPlugin
199: .setSelection(view, buffer, start, end);
200: }
201: });
202: } catch (IOException ex) {
203: IDEPlugin
204: .log(IDEInterface.ERROR, NAME,
205: "can't open duplicate file! "
206: + ex.getMessage());
207: }
208: }
209: }
210:
211: /**
212: * Adds a feature to the Duplicates attribute of the CPDDuplicateCodeViewer object
213: *
214: * @param duplicates The feature to be added to the Duplicates attribute
215: */
216: public void addDuplicates(Duplicates duplicates) {
217: //System.out.println("Inside addDuplicates " + duplicates +" Root child count "+ treeModel.getChildCount(treeModel.getRoot()));
218: getRoot().add(duplicates);
219: }
220:
221: /** Description of the Method */
222: public void expandAll() {
223: int row = 0;
224:
225: while (row < tree.getRowCount()) {
226: tree.expandRow(row);
227: row++;
228: }
229: }
230:
231: /** Description of the Method */
232: public void collapseAll() {
233: int row = tree.getRowCount() - 1;
234:
235: while (row >= 0) {
236: tree.collapseRow(row);
237: row--;
238: }
239: }
240:
241: /** Description of the Method */
242: public void clearDuplicates() {
243: getRoot().removeAllChildren();
244: }
245:
246: /**
247: * Description of the Method
248: *
249: * @param cpd Description of Parameter
250: * @param view Description of Parameter
251: */
252: public void processDuplicates(CPD cpd, Frame view) {
253: clearDuplicates();
254: for (Iterator i = cpd.getMatches(); i.hasNext();) {
255: Match match = (Match) i.next();
256:
257: CPDDuplicateCodeViewer.Duplicates duplicates = new Duplicates(
258: match.getLineCount() + " duplicate lines", match
259: .getSourceCodeSlice());
260:
261: for (Iterator occurrences = match.iterator(); occurrences
262: .hasNext();) {
263: Mark mark = (Mark) occurrences.next();
264: int lastLine = mark.getBeginLine()
265: + match.getLineCount();
266: CPDDuplicateCodeViewer.Duplicate duplicate = new Duplicate(
267: mark.getTokenSrcID(), mark.getBeginLine(),
268: lastLine);
269: duplicates.addDuplicate(duplicate);
270: }
271: addDuplicates(duplicates);
272: }
273: refreshTree();
274: expandAll();
275: }
276:
277: /**
278: * Description of the Class
279: *
280: * @author Mike Atkinson
281: * @created September 13, 2003
282: */
283: public class Duplicates extends DefaultMutableTreeNode {
284: List vecduplicate = new ArrayList();
285: String message, sourcecode;
286:
287: /**
288: * Constructor for the Duplicates object
289: *
290: * @param message Description of Parameter
291: * @param sourcecode Description of Parameter
292: */
293: public Duplicates(String message, String sourcecode) {
294: this .message = message;
295: this .sourcecode = sourcecode;
296: }
297:
298: /**
299: * Gets the sourceCode attribute of the Duplicates object
300: *
301: * @return The sourceCode value
302: */
303: public String getSourceCode() {
304: return sourcecode;
305: }
306:
307: /**
308: * Adds a feature to the Duplicate attribute of the Duplicates object
309: *
310: * @param duplicate The feature to be added to the Duplicate attribute
311: */
312: public void addDuplicate(Duplicate duplicate) {
313: add(duplicate);
314: }
315:
316: /**
317: * Description of the Method
318: *
319: * @return Description of the Return Value
320: */
321: public String toString() {
322: return message;
323: }
324: }
325:
326: /**
327: * Description of the Class
328: *
329: * @author Mike Atkinson
330: * @created September 13, 2003
331: */
332: public class Duplicate extends DefaultMutableTreeNode {
333: private String filename;
334: private int beginLine, endLine;
335:
336: /**
337: * Constructor for the Duplicate object
338: *
339: * @param filename Description of Parameter
340: * @param beginLine Description of Parameter
341: * @param endLine Description of Parameter
342: */
343: public Duplicate(String filename, int beginLine, int endLine) {
344: this .filename = filename;
345: this .beginLine = beginLine;
346: this .endLine = endLine;
347: }
348:
349: /**
350: * Gets the filename attribute of the Duplicate object
351: *
352: * @return The filename value
353: */
354: public String getFilename() {
355: return filename;
356: }
357:
358: /**
359: * Gets the beginLine attribute of the Duplicate object
360: *
361: * @return The beginLine value
362: */
363: public int getBeginLine() {
364: return beginLine;
365: }
366:
367: /**
368: * Gets the endLine attribute of the Duplicate object
369: *
370: * @return The endLine value
371: */
372: public int getEndLine() {
373: return endLine;
374: }
375:
376: /**
377: * Description of the Method
378: *
379: * @return Description of the Return Value
380: */
381: public String toString() {
382: return filename + ":" + getBeginLine() + "-" + getEndLine();
383: }
384: }
385:
386: }
|