|
1 |
| |
|
2 |
| |
|
3 |
| |
|
4 |
| package net.sourceforge.pmd.util.designer; |
|
5 |
| |
|
6 |
| import net.sourceforge.pmd.PMD; |
|
7 |
| import net.sourceforge.pmd.RuleContext; |
|
8 |
| import net.sourceforge.pmd.RuleSet; |
|
9 |
| import net.sourceforge.pmd.SourceType; |
|
10 |
| import net.sourceforge.pmd.TargetJDK1_3; |
|
11 |
| import net.sourceforge.pmd.TargetJDK1_4; |
|
12 |
| import net.sourceforge.pmd.TargetJDK1_5; |
|
13 |
| import net.sourceforge.pmd.TargetJDK1_6; |
|
14 |
| import net.sourceforge.pmd.ast.Node; |
|
15 |
| import net.sourceforge.pmd.ast.ParseException; |
|
16 |
| import net.sourceforge.pmd.ast.SimpleNode; |
|
17 |
| import net.sourceforge.pmd.jaxen.DocumentNavigator; |
|
18 |
| import net.sourceforge.pmd.jaxen.MatchesFunction; |
|
19 |
| import net.sourceforge.pmd.jsp.ast.JspCharStream; |
|
20 |
| import net.sourceforge.pmd.jsp.ast.JspParser; |
|
21 |
| import net.sourceforge.pmd.util.NumericConstants; |
|
22 |
| import net.sourceforge.pmd.util.StringUtil; |
|
23 |
| import org.jaxen.BaseXPath; |
|
24 |
| import org.jaxen.JaxenException; |
|
25 |
| import org.jaxen.XPath; |
|
26 |
| |
|
27 |
| import javax.swing.*; |
|
28 |
| import javax.swing.event.*; |
|
29 |
| import javax.swing.text.JTextComponent; |
|
30 |
| import javax.swing.tree.DefaultTreeCellRenderer; |
|
31 |
| import javax.swing.tree.DefaultTreeModel; |
|
32 |
| import javax.swing.tree.TreeNode; |
|
33 |
| import javax.swing.tree.TreePath; |
|
34 |
| import javax.swing.undo.*; |
|
35 |
| import java.awt.BorderLayout; |
|
36 |
| import java.awt.Color; |
|
37 |
| import java.awt.Component; |
|
38 |
| import java.awt.Dimension; |
|
39 |
| import java.awt.Font; |
|
40 |
| import java.awt.FontMetrics; |
|
41 |
| import java.awt.Graphics; |
|
42 |
| import java.awt.Toolkit; |
|
43 |
| import java.awt.datatransfer.Clipboard; |
|
44 |
| import java.awt.datatransfer.ClipboardOwner; |
|
45 |
| import java.awt.datatransfer.StringSelection; |
|
46 |
| import java.awt.datatransfer.Transferable; |
|
47 |
| import java.awt.event.ActionEvent; |
|
48 |
| import java.awt.event.ActionListener; |
|
49 |
| import java.awt.event.ComponentEvent; |
|
50 |
| import java.awt.event.KeyEvent; |
|
51 |
| import java.io.IOException; |
|
52 |
| import java.io.StringReader; |
|
53 |
| import java.io.StringWriter; |
|
54 |
| import java.lang.reflect.InvocationTargetException; |
|
55 |
| import java.lang.reflect.Method; |
|
56 |
| import java.util.Enumeration; |
|
57 |
| import java.util.Iterator; |
|
58 |
| import java.util.List; |
|
59 |
| import java.util.Vector; |
|
60 |
| |
|
61 |
| public class Designer implements ClipboardOwner { |
|
62 |
| |
|
63 |
| private static final char LABEL_IMAGE_SEPARATOR = ':'; |
|
64 |
| private static final Color IMAGE_TEXT_COLOR = Color.BLUE; |
|
65 |
| |
|
66 |
| private interface Parser { public SimpleNode parse(StringReader sr); }; |
|
67 |
| |
|
68 |
| private static final Parser jdkParser1_3 = new Parser() { |
|
69 |
0
| public SimpleNode parse(StringReader sr) { return new TargetJDK1_3().createParser(sr).CompilationUnit(); };
|
|
70 |
| }; |
|
71 |
| |
|
72 |
| private static final Parser jdkParser1_4 = new Parser() { |
|
73 |
0
| public SimpleNode parse(StringReader sr) { return new TargetJDK1_4().createParser(sr).CompilationUnit(); };
|
|
74 |
| }; |
|
75 |
| |
|
76 |
| private static final Parser jdkParser1_5 = new Parser() { |
|
77 |
0
| public SimpleNode parse(StringReader sr) { return new TargetJDK1_5().createParser(sr).CompilationUnit(); };
|
|
78 |
| }; |
|
79 |
| |
|
80 |
| private static final Parser jdkParser1_6 = new Parser() { |
|
81 |
0
| public SimpleNode parse(StringReader sr) { return new TargetJDK1_6().createParser(sr).CompilationUnit(); };
|
|
82 |
| }; |
|
83 |
| |
|
84 |
| private static final Parser jspParser = new Parser() { |
|
85 |
0
| public SimpleNode parse(StringReader sr) { return new JspParser(new JspCharStream(sr)).CompilationUnit(); };
|
|
86 |
| }; |
|
87 |
| |
|
88 |
| private static final Object[][] sourceTypeSets = new Object[][] { |
|
89 |
| { "JDK 1.3", SourceType.JAVA_13, jdkParser1_3 }, |
|
90 |
| { "JDK 1.4", SourceType.JAVA_14, jdkParser1_4 }, |
|
91 |
| { "JDK 1.5", SourceType.JAVA_15, jdkParser1_5 }, |
|
92 |
| { "JDK 1.6", SourceType.JAVA_16, jdkParser1_6 }, |
|
93 |
| { "JSP", SourceType.JSP, jspParser } |
|
94 |
| }; |
|
95 |
| |
|
96 |
| private static final int defaultSourceTypeSelectionIndex = 1; |
|
97 |
| |
|
98 |
| |
|
99 |
0
| private SimpleNode getCompilationUnit() {
|
|
100 |
| |
|
101 |
0
| Parser parser = (Parser)sourceTypeSets[selectedSourceTypeIndex()][2];
|
|
102 |
0
| return parser.parse(new StringReader(codeEditorPane.getText()));
|
|
103 |
| } |
|
104 |
| |
|
105 |
0
| private SourceType getSourceType() {
|
|
106 |
| |
|
107 |
0
| return (SourceType)sourceTypeSets[selectedSourceTypeIndex()][1];
|
|
108 |
| } |
|
109 |
| |
|
110 |
0
| private int selectedSourceTypeIndex() {
|
|
111 |
0
| for (int i=0; i<sourceTypeMenuItems.length; i++) {
|
|
112 |
0
| if (sourceTypeMenuItems[i].isSelected()) return i;
|
|
113 |
| } |
|
114 |
0
| throw new RuntimeException("Initial default source type not specified");
|
|
115 |
| } |
|
116 |
| |
|
117 |
| private class ExceptionNode implements TreeNode { |
|
118 |
| |
|
119 |
| private Object item; |
|
120 |
| private ExceptionNode[] kids; |
|
121 |
| |
|
122 |
0
| public ExceptionNode(Object theItem) {
|
|
123 |
0
| item = theItem;
|
|
124 |
| |
|
125 |
0
| if (item instanceof ParseException) createKids();
|
|
126 |
| } |
|
127 |
| |
|
128 |
| |
|
129 |
0
| private void createKids() {
|
|
130 |
| |
|
131 |
0
| String message = ((ParseException)item).getMessage();
|
|
132 |
0
| String[] lines = StringUtil.substringsOf(message, PMD.EOL);
|
|
133 |
| |
|
134 |
0
| kids = new ExceptionNode[lines.length];
|
|
135 |
0
| for (int i=0; i<lines.length; i++) {
|
|
136 |
0
| kids[i] = new ExceptionNode(lines[i]);
|
|
137 |
| } |
|
138 |
| } |
|
139 |
| |
|
140 |
0
| public int getChildCount() { return kids == null ? 0 : kids.length; }
|
|
141 |
0
| public boolean getAllowsChildren() {return false; }
|
|
142 |
0
| public boolean isLeaf() { return kids == null; }
|
|
143 |
0
| public TreeNode getParent() { return null; }
|
|
144 |
0
| public TreeNode getChildAt(int childIndex) { return kids[childIndex]; }
|
|
145 |
0
| public String label() { return item.toString(); }
|
|
146 |
| |
|
147 |
0
| public Enumeration children() {
|
|
148 |
0
| Enumeration e = new Enumeration() {
|
|
149 |
| int i = 0; |
|
150 |
0
| public boolean hasMoreElements() {
|
|
151 |
0
| return kids != null && i < kids.length;
|
|
152 |
| } |
|
153 |
| |
|
154 |
0
| public Object nextElement() { return kids[i++]; }
|
|
155 |
| }; |
|
156 |
0
| return e;
|
|
157 |
| } |
|
158 |
| |
|
159 |
0
| public int getIndex(TreeNode node) {
|
|
160 |
0
| for (int i=0; i<kids.length; i++) {
|
|
161 |
0
| if (kids[i] == node) return i;
|
|
162 |
| } |
|
163 |
0
| return -1;
|
|
164 |
| } |
|
165 |
| } |
|
166 |
| |
|
167 |
| |
|
168 |
| |
|
169 |
| private class ASTTreeNode implements TreeNode { |
|
170 |
| |
|
171 |
| private Node node; |
|
172 |
| private ASTTreeNode parent; |
|
173 |
| private ASTTreeNode[] kids; |
|
174 |
| |
|
175 |
0
| public ASTTreeNode(Node theNode) {
|
|
176 |
0
| node = theNode;
|
|
177 |
| |
|
178 |
0
| Node prnt = node.jjtGetParent();
|
|
179 |
0
| if (prnt != null) parent = new ASTTreeNode(prnt);
|
|
180 |
| } |
|
181 |
| |
|
182 |
0
| public int getChildCount() { return node.jjtGetNumChildren(); }
|
|
183 |
0
| public boolean getAllowsChildren() { return false; }
|
|
184 |
0
| public boolean isLeaf() { return node.jjtGetNumChildren() == 0; }
|
|
185 |
0
| public TreeNode getParent() { return parent; }
|
|
186 |
| |
|
187 |
0
| public Enumeration children() {
|
|
188 |
| |
|
189 |
0
| if (getChildCount() > 0) getChildAt(0);
|
|
190 |
| |
|
191 |
0
| Enumeration e = new Enumeration() {
|
|
192 |
| int i = 0; |
|
193 |
0
| public boolean hasMoreElements() {
|
|
194 |
0
| return kids != null && i < kids.length;
|
|
195 |
| } |
|
196 |
0
| public Object nextElement() { return kids[i++]; }
|
|
197 |
| }; |
|
198 |
0
| return e;
|
|
199 |
| } |
|
200 |
| |
|
201 |
0
| public TreeNode getChildAt(int childIndex) {
|
|
202 |
| |
|
203 |
0
| if (kids == null) {
|
|
204 |
0
| kids = new ASTTreeNode[node.jjtGetNumChildren()];
|
|
205 |
0
| for (int i=0; i<kids.length; i++) {
|
|
206 |
0
| kids[i] = new ASTTreeNode(node.jjtGetChild(i));
|
|
207 |
| } |
|
208 |
| } |
|
209 |
0
| return kids[childIndex];
|
|
210 |
| } |
|
211 |
| |
|
212 |
0
| public int getIndex(TreeNode node) {
|
|
213 |
| |
|
214 |
0
| for (int i=0; i<kids.length; i++) {
|
|
215 |
0
| if (kids[i] == node) return i;
|
|
216 |
| } |
|
217 |
0
| return -1;
|
|
218 |
| } |
|
219 |
| |
|
220 |
0
| public String label() {
|
|
221 |
0
| if (node instanceof SimpleNode) {
|
|
222 |
0
| SimpleNode sn = (SimpleNode)node;
|
|
223 |
0
| if (sn.getLabel() != null) {
|
|
224 |
0
| return node.toString() + LABEL_IMAGE_SEPARATOR + sn.getLabel();
|
|
225 |
| } |
|
226 |
0
| if (sn.getImage() == null) {
|
|
227 |
0
| return node.toString();
|
|
228 |
| } |
|
229 |
0
| return node.toString() + LABEL_IMAGE_SEPARATOR + sn.getImage();
|
|
230 |
| } |
|
231 |
0
| return node.toString();
|
|
232 |
| } |
|
233 |
| } |
|
234 |
| |
|
235 |
| |
|
236 |
| |
|
237 |
| |
|
238 |
| |
|
239 |
| private class ASTCellRenderer extends DefaultTreeCellRenderer { |
|
240 |
| |
|
241 |
| private ASTTreeNode node; |
|
242 |
| |
|
243 |
0
| public Icon getIcon() { return null; };
|
|
244 |
| |
|
245 |
0
| public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel,boolean expanded,boolean leaf, int row, boolean hasFocus) {
|
|
246 |
| |
|
247 |
0
| if (value instanceof ASTTreeNode) {
|
|
248 |
0
| node = (ASTTreeNode)value;
|
|
249 |
| } |
|
250 |
0
| return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
|
251 |
| } |
|
252 |
| |
|
253 |
| |
|
254 |
0
| public void paint(Graphics g) {
|
|
255 |
| |
|
256 |
0
| super.paint(g);
|
|
257 |
| |
|
258 |
0
| if (node == null) return;
|
|
259 |
| |
|
260 |
0
| String text = node.label();
|
|
261 |
0
| int separatorPos = text.indexOf(LABEL_IMAGE_SEPARATOR);
|
|
262 |
0
| if (separatorPos < 0) return;
|
|
263 |
| |
|
264 |
0
| String label = text.substring(0, separatorPos+1);
|
|
265 |
0
| String image = text.substring(separatorPos+1);
|
|
266 |
| |
|
267 |
0
| FontMetrics fm = g.getFontMetrics();
|
|
268 |
0
| int width = SwingUtilities.computeStringWidth(fm, label);
|
|
269 |
| |
|
270 |
0
| g.setColor(IMAGE_TEXT_COLOR);
|
|
271 |
0
| g.drawString(image, width, fm.getMaxAscent());
|
|
272 |
| } |
|
273 |
| } |
|
274 |
| |
|
275 |
| |
|
276 |
| |
|
277 |
| |
|
278 |
| private class ASTTreeWidget extends JTree { |
|
279 |
| |
|
280 |
0
| public ASTTreeWidget(Vector items) {
|
|
281 |
0
| super(items);
|
|
282 |
| } |
|
283 |
| |
|
284 |
0
| public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
|
285 |
0
| if (value == null) return "";
|
|
286 |
0
| if (value instanceof ASTTreeNode) {
|
|
287 |
0
| return ((ASTTreeNode)value).label();
|
|
288 |
| } |
|
289 |
0
| if (value instanceof ExceptionNode) {
|
|
290 |
0
| return ((ExceptionNode)value).label();
|
|
291 |
| } |
|
292 |
0
| return value.toString();
|
|
293 |
| } |
|
294 |
| |
|
295 |
0
| public void expandAll(boolean expand) {
|
|
296 |
0
| TreeNode root = (TreeNode)getModel().getRoot();
|
|
297 |
0
| expandAll(new TreePath(root), expand);
|
|
298 |
| } |
|
299 |
| |
|
300 |
0
| private void expandAll(TreePath parent, boolean expand) {
|
|
301 |
| |
|
302 |
0
| TreeNode node = (TreeNode)parent.getLastPathComponent();
|
|
303 |
0
| if (node.getChildCount() >= 0) {
|
|
304 |
0
| for (Enumeration e=node.children(); e.hasMoreElements(); ) {
|
|
305 |
0
| TreeNode n = (TreeNode)e.nextElement();
|
|
306 |
0
| TreePath path = parent.pathByAddingChild(n);
|
|
307 |
0
| expandAll(path, expand);
|
|
308 |
| } |
|
309 |
| } |
|
310 |
| |
|
311 |
0
| if (expand) {
|
|
312 |
0
| expandPath(parent);
|
|
313 |
| } else { |
|
314 |
0
| collapsePath(parent);
|
|
315 |
| } |
|
316 |
| } |
|
317 |
| } |
|
318 |
| |
|
319 |
0
| private void loadTreeData(TreeNode rootNode) {
|
|
320 |
0
| astWidget.setModel(new DefaultTreeModel(rootNode));
|
|
321 |
0
| astWidget.expandAll(true);
|
|
322 |
| } |
|
323 |
| |
|
324 |
| private class ShowListener implements ActionListener { |
|
325 |
0
| public void actionPerformed(ActionEvent ae) {
|
|
326 |
0
| MyPrintStream ps = new MyPrintStream();
|
|
327 |
0
| System.setOut(ps);
|
|
328 |
0
| TreeNode tn;
|
|
329 |
0
| try {
|
|
330 |
0
| SimpleNode lastCompilationUnit = getCompilationUnit();
|
|
331 |
0
| tn = new ASTTreeNode(lastCompilationUnit);
|
|
332 |
| } catch (ParseException pe) { |
|
333 |
0
| tn = new ExceptionNode(pe);
|
|
334 |
| } |
|
335 |
| |
|
336 |
0
| loadTreeData(tn);
|
|
337 |
| } |
|
338 |
| } |
|
339 |
| |
|
340 |
| private class DFAListener implements ActionListener { |
|
341 |
0
| public void actionPerformed(ActionEvent ae) {
|
|
342 |
| |
|
343 |
0
| DFAGraphRule dfaGraphRule = new DFAGraphRule();
|
|
344 |
0
| RuleSet rs = new RuleSet();
|
|
345 |
0
| SourceType sourceType = getSourceType();
|
|
346 |
0
| if (!sourceType.equals(SourceType.JSP)){
|
|
347 |
0
| rs.addRule(dfaGraphRule);
|
|
348 |
| } |
|
349 |
0
| RuleContext ctx = new RuleContext();
|
|
350 |
0
| ctx.setSourceCodeFilename("[no filename]");
|
|
351 |
0
| StringReader reader = new StringReader(codeEditorPane.getText());
|
|
352 |
0
| PMD pmd = new PMD();
|
|
353 |
0
| pmd.setJavaVersion(sourceType);
|
|
354 |
| |
|
355 |
0
| try {
|
|
356 |
0
| pmd.processFile(reader, rs, ctx);
|
|
357 |
| |
|
358 |
| |
|
359 |
| } catch (Exception e) { |
|
360 |
0
| e.printStackTrace();
|
|
361 |
| } |
|
362 |
| |
|
363 |
0
| List methods = dfaGraphRule.getMethods();
|
|
364 |
0
| if (methods != null && !methods.isEmpty()) {
|
|
365 |
0
| dfaPanel.resetTo(methods, codeEditorPane);
|
|
366 |
0
| dfaPanel.repaint();
|
|
367 |
| } |
|
368 |
| } |
|
369 |
| } |
|
370 |
| |
|
371 |
| private class XPathListener implements ActionListener { |
|
372 |
0
| public void actionPerformed(ActionEvent ae) {
|
|
373 |
0
| xpathResults.clear();
|
|
374 |
0
| if (xpathQueryArea.getText().length() == 0) {
|
|
375 |
0
| xpathResults.addElement("XPath query field is empty");
|
|
376 |
0
| xpathResultList.repaint();
|
|
377 |
0
| codeEditorPane.requestFocus();
|
|
378 |
0
| return;
|
|
379 |
| } |
|
380 |
0
| SimpleNode c = getCompilationUnit();
|
|
381 |
0
| try {
|
|
382 |
0
| XPath xpath = new BaseXPath(xpathQueryArea.getText(), new DocumentNavigator());
|
|
383 |
0
| for (Iterator iter = xpath.selectNodes(c).iterator(); iter.hasNext();) {
|
|
384 |
0
| StringBuffer sb = new StringBuffer();
|
|
385 |
0
| Object obj = iter.next();
|
|
386 |
0
| if (obj instanceof String) {
|
|
387 |
0
| System.out.println("Result was a string: " + ((String) obj));
|
|
388 |
0
| } else if (!(obj instanceof Boolean)) {
|
|
389 |
| |
|
390 |
0
| SimpleNode node = (SimpleNode) obj;
|
|
391 |
0
| String name = node.getClass().getName().substring(node.getClass().getName().lastIndexOf('.') + 1);
|
|
392 |
0
| String line = " at line " + node.getBeginLine();
|
|
393 |
0
| sb.append(name).append(line).append(PMD.EOL);
|
|
394 |
0
| xpathResults.addElement(sb.toString().trim());
|
|
395 |
| } |
|
396 |
| } |
|
397 |
0
| if (xpathResults.isEmpty()) {
|
|
398 |
0
| xpathResults.addElement("No matching nodes " + System.currentTimeMillis());
|
|
399 |
| } |
|
400 |
| } catch (ParseException pe) { |
|
401 |
0
| xpathResults.addElement(pe.fillInStackTrace().getMessage());
|
|
402 |
| } catch (JaxenException je) { |
|
403 |
0
| xpathResults.addElement(je.fillInStackTrace().getMessage());
|
|
404 |
| } |
|
405 |
0
| xpathResultList.repaint();
|
|
406 |
0
| xpathQueryArea.requestFocus();
|
|
407 |
| } |
|
408 |
| } |
|
409 |
| |
|
410 |
| private final CodeEditorTextPane codeEditorPane = new CodeEditorTextPane(); |
|
411 |
| private final ASTTreeWidget astWidget = new ASTTreeWidget(new Vector()); |
|
412 |
| private DefaultListModel xpathResults = new DefaultListModel(); |
|
413 |
| private final JList xpathResultList = new JList(xpathResults); |
|
414 |
| private final JTextArea xpathQueryArea = new JTextArea(15, 30); |
|
415 |
| private final JFrame frame = new JFrame("PMD Rule Designer"); |
|
416 |
| private final DFAPanel dfaPanel = new DFAPanel(); |
|
417 |
| private final JRadioButtonMenuItem[] sourceTypeMenuItems = new JRadioButtonMenuItem[sourceTypeSets.length]; |
|
418 |
| |
|
419 |
0
| public Designer() {
|
|
420 |
0
| MatchesFunction.registerSelfInSimpleContext();
|
|
421 |
| |
|
422 |
0
| xpathQueryArea.setFont(new Font("Verdana", Font.PLAIN, 16));
|
|
423 |
0
| makeTextComponentUndoable(codeEditorPane);
|
|
424 |
0
| JSplitPane controlSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(codeEditorPane), createXPathQueryPanel());
|
|
425 |
0
| JSplitPane resultsSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, createASTPanel(), createXPathResultPanel());
|
|
426 |
| |
|
427 |
0
| JTabbedPane tabbed = new JTabbedPane();
|
|
428 |
0
| tabbed.addTab("Abstract Syntax Tree / XPath", resultsSplitPane);
|
|
429 |
0
| tabbed.addTab("Data Flow Analysis", dfaPanel);
|
|
430 |
0
| try {
|
|
431 |
| |
|
432 |
0
| Method setMnemonicAt = JTabbedPane.class.getMethod("setMnemonicAt", new Class[]{Integer.TYPE, Integer.TYPE});
|
|
433 |
0
| if (setMnemonicAt != null) {
|
|
434 |
| |
|
435 |
| |
|
436 |
| |
|
437 |
0
| setMnemonicAt.invoke(tabbed, new Object[]{NumericConstants.ZERO, new Integer(KeyEvent.VK_A)});
|
|
438 |
0
| setMnemonicAt.invoke(tabbed, new Object[]{NumericConstants.ONE, new Integer(KeyEvent.VK_D)});
|
|
439 |
| } |
|
440 |
| } catch (NoSuchMethodException nsme) { |
|
441 |
| } catch (IllegalAccessException e) { |
|
442 |
0
| e.printStackTrace();
|
|
443 |
0
| throw new InternalError("Runtime reports to be >= JDK 1.4 yet String.split(java.lang.String) is broken.");
|
|
444 |
| } catch (IllegalArgumentException e) { |
|
445 |
0
| e.printStackTrace();
|
|
446 |
0
| throw new InternalError("Runtime reports to be >= JDK 1.4 yet String.split(java.lang.String) is broken.");
|
|
447 |
| } catch (InvocationTargetException e) { |
|
448 |
0
| e.printStackTrace();
|
|
449 |
0
| throw new InternalError("Runtime reports to be >= JDK 1.4 yet String.split(java.lang.String) is broken.");
|
|
450 |
| } |
|
451 |
| |
|
452 |
0
| JSplitPane containerSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, controlSplitPane, tabbed);
|
|
453 |
0
| containerSplitPane.setContinuousLayout(true);
|
|
454 |
| |
|
455 |
0
| JMenuBar menuBar = createMenuBar();
|
|
456 |
0
| frame.setJMenuBar(menuBar);
|
|
457 |
0
| frame.getContentPane().add(containerSplitPane);
|
|
458 |
0
| frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
459 |
| |
|
460 |
0
| Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
|
461 |
0
| int screenHeight = screenSize.height;
|
|
462 |
0
| int screenWidth = screenSize.width;
|
|
463 |
| |
|
464 |
0
| frame.pack();
|
|
465 |
0
| frame.setSize((screenWidth*3/4),(screenHeight*3/4));
|
|
466 |
0
| frame.setLocation((screenWidth -frame.getWidth()) / 2, (screenHeight - frame.getHeight()) / 2);
|
|
467 |
0
| frame.setVisible(true);
|
|
468 |
0
| resultsSplitPane.setDividerLocation(resultsSplitPane.getMaximumDividerLocation() - (resultsSplitPane.getMaximumDividerLocation() / 2));
|
|
469 |
0
| containerSplitPane.setDividerLocation(containerSplitPane.getMaximumDividerLocation() / 2);
|
|
470 |
| } |
|
471 |
| |
|
472 |
0
| private JMenuBar createMenuBar() {
|
|
473 |
0
| JMenuBar menuBar = new JMenuBar();
|
|
474 |
0
| JMenu menu = new JMenu("JDK");
|
|
475 |
0
| ButtonGroup group = new ButtonGroup();
|
|
476 |
| |
|
477 |
0
| for (int i=0; i<sourceTypeSets.length; i++) {
|
|
478 |
0
| JRadioButtonMenuItem button = new JRadioButtonMenuItem(sourceTypeSets[i][0].toString());
|
|
479 |
0
| sourceTypeMenuItems[i] = button;
|
|
480 |
0
| group.add(button);
|
|
481 |
0
| menu.add(button);
|
|
482 |
| } |
|
483 |
0
| sourceTypeMenuItems[defaultSourceTypeSelectionIndex].setSelected(true);
|
|
484 |
0
| menuBar.add(menu);
|
|
485 |
| |
|
486 |
0
| JMenu actionsMenu = new JMenu("Actions");
|
|
487 |
0
| JMenuItem copyXMLItem = new JMenuItem("Copy xml to clipboard");
|
|
488 |
0
| copyXMLItem.addActionListener(new ActionListener() {
|
|
489 |
0
| public void actionPerformed(ActionEvent e) {
|
|
490 |
0
| copyXmlToClipboard();
|
|
491 |
| } |
|
492 |
| }); |
|
493 |
0
| actionsMenu.add(copyXMLItem);
|
|
494 |
0
| JMenuItem createRuleXMLItem = new JMenuItem("Create rule XML");
|
|
495 |
0
| createRuleXMLItem.addActionListener(new ActionListener() {
|
|
496 |
0
| public void actionPerformed(ActionEvent e) {
|
|
497 |
0
| createRuleXML();
|
|
498 |
| } |
|
499 |
| }); |
|
500 |
0
| actionsMenu.add(createRuleXMLItem);
|
|
501 |
0
| menuBar.add(actionsMenu);
|
|
502 |
| |
|
503 |
0
| return menuBar;
|
|
504 |
| } |
|
505 |
| |
|
506 |
0
| private void createRuleXML() {
|
|
507 |
0
| CreateXMLRulePanel rulePanel = new CreateXMLRulePanel(xpathQueryArea, codeEditorPane);
|
|
508 |
0
| JFrame xmlframe = new JFrame("Create XML Rule");
|
|
509 |
0
| xmlframe.setContentPane(rulePanel);
|
|
510 |
0
| xmlframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
|
511 |
0
| xmlframe.setSize(new Dimension(600, 700));
|
|
512 |
0
| xmlframe.addComponentListener(new java.awt.event.ComponentAdapter() {
|
|
513 |
0
| public void componentResized(ComponentEvent e) {
|
|
514 |
0
| JFrame tmp = (JFrame)e.getSource();
|
|
515 |
0
| if (tmp.getWidth()<600 || tmp.getHeight()<700) {
|
|
516 |
0
| tmp.setSize(600, 700);
|
|
517 |
| } |
|
518 |
| } |
|
519 |
| }); |
|
520 |
0
| int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
|
|
521 |
0
| int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
|
|
522 |
0
| xmlframe.pack();
|
|
523 |
0
| xmlframe.setLocation((screenWidth - xmlframe.getWidth()) / 2, (screenHeight - xmlframe.getHeight()) / 2);
|
|
524 |
0
| xmlframe.setVisible(true);
|
|
525 |
| } |
|
526 |
| |
|
527 |
0
| private JComponent createASTPanel() {
|
|
528 |
0
| astWidget.setCellRenderer(new ASTCellRenderer());
|
|
529 |
0
| return new JScrollPane(astWidget);
|
|
530 |
| } |
|
531 |
| |
|
532 |
0
| private JComponent createXPathResultPanel() {
|
|
533 |
0
| xpathResults.addElement("No results yet");
|
|
534 |
0
| xpathResultList.setBorder(BorderFactory.createLineBorder(Color.black));
|
|
535 |
0
| xpathResultList.setFixedCellWidth(300);
|
|
536 |
0
| JScrollPane scrollPane = new JScrollPane();
|
|
537 |
0
| scrollPane.getViewport().setView(xpathResultList);
|
|
538 |
0
| return scrollPane;
|
|
539 |
| } |
|
540 |
| |
|
541 |
0
| private JPanel createXPathQueryPanel() {
|
|
542 |
0
| JPanel p = new JPanel();
|
|
543 |
0
| p.setLayout(new BorderLayout());
|
|
544 |
0
| xpathQueryArea.setBorder(BorderFactory.createLineBorder(Color.black));
|
|
545 |
0
| makeTextComponentUndoable(xpathQueryArea);
|
|
546 |
0
| JScrollPane scrollPane = new JScrollPane(xpathQueryArea);
|
|
547 |
0
| scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
|
548 |
0
| scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
|
|
549 |
0
| final JButton b = createGoButton();
|
|
550 |
| |
|
551 |
0
| p.add(new JLabel("XPath Query (if any)"), BorderLayout.NORTH);
|
|
552 |
0
| p.add(scrollPane, BorderLayout.CENTER);
|
|
553 |
0
| p.add(b, BorderLayout.SOUTH);
|
|
554 |
| |
|
555 |
0
| return p;
|
|
556 |
| } |
|
557 |
| |
|
558 |
0
| private JButton createGoButton() {
|
|
559 |
0
| JButton b = new JButton("Go");
|
|
560 |
0
| b.setMnemonic('g');
|
|
561 |
0
| b.addActionListener(new ShowListener());
|
|
562 |
0
| b.addActionListener(codeEditorPane);
|
|
563 |
0
| b.addActionListener(new XPathListener());
|
|
564 |
0
| b.addActionListener(new DFAListener());
|
|
565 |
0
| return b;
|
|
566 |
| } |
|
567 |
| |
|
568 |
0
| private static void makeTextComponentUndoable(JTextComponent textConponent) {
|
|
569 |
0
| final UndoManager undoManager = new UndoManager();
|
|
570 |
0
| textConponent.getDocument().addUndoableEditListener(new UndoableEditListener() {
|
|
571 |
0
| public void undoableEditHappened(
|
|
572 |
| UndoableEditEvent evt) { |
|
573 |
0
| undoManager.addEdit(evt.getEdit());
|
|
574 |
| } |
|
575 |
| }); |
|
576 |
0
| ActionMap actionMap = textConponent.getActionMap();
|
|
577 |
0
| InputMap inputMap = textConponent.getInputMap();
|
|
578 |
0
| actionMap.put("Undo", new AbstractAction("Undo") {
|
|
579 |
0
| public void actionPerformed(ActionEvent evt) {
|
|
580 |
0
| try {
|
|
581 |
0
| if (undoManager.canUndo()) {
|
|
582 |
0
| undoManager.undo();
|
|
583 |
| } |
|
584 |
| } catch (CannotUndoException e) { |
|
585 |
| } |
|
586 |
| } |
|
587 |
| }); |
|
588 |
0
| inputMap.put(KeyStroke.getKeyStroke("control Z"), "Undo");
|
|
589 |
| |
|
590 |
0
| actionMap.put("Redo", new AbstractAction("Redo") {
|
|
591 |
0
| public void actionPerformed(ActionEvent evt) {
|
|
592 |
0
| try {
|
|
593 |
0
| if (undoManager.canRedo()) {
|
|
594 |
0
| undoManager.redo();
|
|
595 |
| } |
|
596 |
| } catch (CannotRedoException e) { |
|
597 |
| } |
|
598 |
| } |
|
599 |
| }); |
|
600 |
0
| inputMap.put(KeyStroke.getKeyStroke("control Y"), "Redo");
|
|
601 |
| } |
|
602 |
| |
|
603 |
0
| public static void main(String[] args) {
|
|
604 |
0
| new Designer();
|
|
605 |
| } |
|
606 |
| |
|
607 |
0
| private final void copyXmlToClipboard() {
|
|
608 |
0
| if (codeEditorPane.getText() != null && codeEditorPane.getText().trim().length() > 0) {
|
|
609 |
0
| String xml = "";
|
|
610 |
0
| SimpleNode cu = getCompilationUnit();
|
|
611 |
0
| if (cu != null) {
|
|
612 |
0
| try {
|
|
613 |
0
| xml = getXmlString(cu);
|
|
614 |
| } catch (IOException e) { |
|
615 |
0
| e.printStackTrace();
|
|
616 |
0
| xml = "Error trying to construct XML representation";
|
|
617 |
| } |
|
618 |
| } |
|
619 |
0
| Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(xml), this);
|
|
620 |
| } |
|
621 |
| } |
|
622 |
| |
|
623 |
| |
|
624 |
| |
|
625 |
| |
|
626 |
| |
|
627 |
| |
|
628 |
| |
|
629 |
| |
|
630 |
0
| private String getXmlString(SimpleNode node) throws IOException {
|
|
631 |
| |
|
632 |
| |
|
633 |
| |
|
634 |
| |
|
635 |
| |
|
636 |
| |
|
637 |
| |
|
638 |
0
| return "FIXME";
|
|
639 |
| } |
|
640 |
| |
|
641 |
0
| public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
|
642 |
| } |
|
643 |
| } |
|
644 |
| |