Source code: com/puppycrawl/tools/checkstyle/gui/ParseTreeInfoPanel.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2002 Oliver Burn
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ////////////////////////////////////////////////////////////////////////////////
19
20 package com.puppycrawl.tools.checkstyle.gui;
21
22 import java.awt.BorderLayout;
23 import java.awt.Component;
24 import java.awt.GridLayout;
25 import java.awt.event.ActionEvent;
26 import java.awt.event.KeyEvent;
27 import java.io.File;
28 import java.io.IOException;
29 import java.util.TooManyListenersException;
30
31 import javax.swing.AbstractAction;
32 import javax.swing.Action;
33 import javax.swing.JButton;
34 import javax.swing.JFileChooser;
35 import javax.swing.JOptionPane;
36 import javax.swing.JPanel;
37 import javax.swing.JScrollPane;
38 import javax.swing.KeyStroke;
39 import javax.swing.SwingUtilities;
40 import javax.swing.filechooser.FileFilter;
41
42 import antlr.ANTLRException;
43 import com.puppycrawl.tools.checkstyle.TreeWalker;
44 import com.puppycrawl.tools.checkstyle.api.DetailAST;
45 import com.puppycrawl.tools.checkstyle.api.FileContents;
46 import com.puppycrawl.tools.checkstyle.api.Utils;
47
48 /**
49 * Displays information about a parse tree.
50 * The user can change the file that is parsed and displayed
51 * through a JFileChooser.
52 *
53 * @author Lars Kühne
54 */
55 public class ParseTreeInfoPanel extends JPanel
56 {
57 private JTreeTable mTreeTable;
58 private ParseTreeModel mParseTreeModel;
59 private File mLastDirectory = null;
60 private File mCurrentFile = null;
61 private final Action reloadAction;
62
63 private static class JavaFileFilter extends FileFilter
64 {
65 public boolean accept(File f)
66 {
67 if (f == null) {
68 return false;
69 }
70 return f.isDirectory() || f.getName().endsWith(".java");
71 }
72
73 public String getDescription()
74 {
75 return "Java Source Code";
76 }
77 }
78
79 private class FileSelectionAction extends AbstractAction
80 {
81 public FileSelectionAction()
82 {
83 super("Select Java File");
84 putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_S));
85 }
86
87 public void actionPerformed(ActionEvent e)
88 {
89 JFileChooser fc = new JFileChooser( mLastDirectory );
90 FileFilter filter = new JavaFileFilter();
91 fc.setFileFilter(filter);
92 final Component parent =
93 SwingUtilities.getRoot(ParseTreeInfoPanel.this);
94 fc.showDialog(parent, "Open");
95 File file = fc.getSelectedFile();
96 openFile(file, parent);
97 }
98 }
99
100 private class ReloadAction extends AbstractAction
101 {
102 public ReloadAction()
103 {
104 super("Reload Java File");
105 putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_R));
106 }
107
108 public void actionPerformed(ActionEvent e)
109 {
110 final Component parent =
111 SwingUtilities.getRoot(ParseTreeInfoPanel.this);
112 openFile(mCurrentFile, parent);
113 }
114 }
115
116
117 private class FileDropListener implements FileDrop.Listener
118 {
119 private final JScrollPane mSp;
120
121 public void filesDropped(File[] files)
122 {
123 if (files != null && files.length > 0)
124 {
125 File file = files[0];
126 openFile(file, mSp);
127 }
128 }
129
130 public FileDropListener(JScrollPane aSp)
131 {
132 mSp = aSp;
133 }
134 }
135
136 private void openFile(File aFile, final Component aParent)
137 {
138 if (aFile != null) {
139 try {
140 DetailAST parseTree = parseFile(aFile.getAbsolutePath());
141 mParseTreeModel.setParseTree(parseTree);
142 mCurrentFile = aFile;
143 mLastDirectory = aFile.getParentFile();
144 reloadAction.setEnabled(true);
145 }
146 catch (IOException ex) {
147 showErrorDialog(
148 aParent,
149 "Could not open " + aFile + ": " + ex.getMessage());
150 }
151 catch (ANTLRException ex) {
152 showErrorDialog(
153 aParent,
154 "Could not parse " + aFile + ": " + ex.getMessage());
155 }
156 }
157 }
158
159 /**
160 * Parses a file and returns the parse tree.
161 * @param aFileName the file to parse
162 * @return the root node of the parse tree
163 * @throws IOException if the file cannot be opened
164 * @throws ANTLRException if the file is not a Java source
165 */
166 public static DetailAST parseFile(String aFileName)
167 throws IOException, ANTLRException
168 {
169 final String[] lines = Utils.getLines(aFileName);
170 final FileContents contents = new FileContents(aFileName, lines);
171 return TreeWalker.parse(contents);
172 }
173
174 /**
175 * Create a new ParseTreeInfoPanel instance.
176 */
177 public ParseTreeInfoPanel()
178 {
179 setLayout(new BorderLayout());
180
181 DetailAST treeRoot = null;
182 mParseTreeModel = new ParseTreeModel(treeRoot);
183 mTreeTable = new JTreeTable(mParseTreeModel);
184 final JScrollPane sp = new JScrollPane(mTreeTable);
185 this.add(sp, BorderLayout.CENTER);
186
187 final JPanel p = new JPanel(new GridLayout(1,2));
188 this.add(p, BorderLayout.SOUTH);
189
190 final JButton fileSelectionButton =
191 new JButton(new FileSelectionAction());
192
193 reloadAction = new ReloadAction();
194 reloadAction.setEnabled(false);
195 final JButton reloadButton = new JButton(reloadAction);
196
197 p.add(fileSelectionButton);
198 p.add(reloadButton);
199
200 try {
201 // TODO: creating an object for the side effect of the constructor
202 // and then ignoring the object looks strange.
203 new FileDrop(sp, new FileDropListener(sp));
204 }
205 catch (TooManyListenersException ex)
206 {
207 showErrorDialog(null, "Cannot initialize Drag and Drop support");
208 }
209
210 }
211
212 private void showErrorDialog(final Component parent, final String msg)
213 {
214 Runnable showError = new Runnable()
215 {
216 public void run()
217 {
218 JOptionPane.showMessageDialog(parent, msg);
219 }
220 };
221 SwingUtilities.invokeLater(showError);
222 }
223
224 }