KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > util > designer > DFAPanel


1 package net.sourceforge.pmd.util.designer;
2
3 import net.sourceforge.pmd.ast.ASTMethodDeclaration;
4 import net.sourceforge.pmd.ast.SimpleNode;
5 import net.sourceforge.pmd.dfa.IDataFlowNode;
6 import net.sourceforge.pmd.dfa.variableaccess.VariableAccess;
7 import net.sourceforge.pmd.util.LineGetter;
8 import net.sourceforge.pmd.util.StringUtil;
9
10 import javax.swing.*;
11 import javax.swing.event.ListSelectionEvent JavaDoc;
12 import javax.swing.event.ListSelectionListener JavaDoc;
13 import java.awt.BorderLayout JavaDoc;
14 import java.awt.Color JavaDoc;
15 import java.awt.Dimension JavaDoc;
16 import java.awt.FontMetrics JavaDoc;
17 import java.awt.Graphics JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20
21 public class DFAPanel extends JComponent implements ListSelectionListener JavaDoc {
22
23     public static class DFACanvas extends JPanel {
24
25         private static final int NODE_RADIUS = 12;
26         private static final int NODE_DIAMETER = 2 * NODE_RADIUS;
27
28         private SimpleNode node;
29
30         private int x = 150;
31         private int y = 50;
32         private LineGetter lines;
33
34         private void addAccessLabel(StringBuffer JavaDoc sb, VariableAccess va) {
35
36             if (va.isDefinition()) {
37                 sb.append("d(");
38             } else if (va.isReference()) {
39                 sb.append("r(");
40             } else if (va.isUndefinition()) {
41                 sb.append("u(");
42                 //continue; // eo - the u() entries add a lot of clutter to the report
43
} else {
44                 sb.append("?(");
45             }
46
47             sb.append(va.getVariableName()).append(')');
48         }
49
50         private String JavaDoc childIndicesOf(IDataFlowNode node, String JavaDoc separator) {
51
52             List JavaDoc kids = node.getChildren();
53             if (kids.isEmpty()) return "";
54
55             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
56             sb.append(((IDataFlowNode)kids.get(0)).getIndex());
57
58             for (int j = 1; j < node.getChildren().size(); j++) {
59                 sb.append(separator);
60                 sb.append(((IDataFlowNode)kids.get(j)).getIndex());
61              }
62             return sb.toString();
63         }
64
65         private String JavaDoc[] deriveAccessLabels(List JavaDoc flow) {
66
67             if (flow == null || flow.isEmpty()) return StringUtil.EMPTY_STRINGS;
68
69             String JavaDoc[] labels = new String JavaDoc[flow.size()];
70
71             for (int i=0; i<labels.length; i++) {
72                 List JavaDoc access = ((IDataFlowNode) flow.get(i)).getVariableAccess();
73
74                 if (access == null || access.isEmpty()) {
75                     continue; // leave a null at this slot
76
}
77
78                 StringBuffer JavaDoc exp = new StringBuffer JavaDoc();
79                 addAccessLabel(exp, (VariableAccess) access.get(0));
80
81                 for (int k = 1; k < access.size(); k++) {
82                     exp.append(", ");
83                     addAccessLabel(exp, (VariableAccess) access.get(k));
84                     }
85
86                 labels[i] = exp.toString();
87             }
88             return labels;
89         }
90
91         private int maxWidthOf(String JavaDoc[] strings, FontMetrics JavaDoc fm) {
92
93             int max = 0;
94             String JavaDoc str;
95
96             for (int i=0; i<strings.length; i++) {
97                 str = strings[i];
98                 if (str == null) continue;
99                 max = Math.max(max, SwingUtilities.computeStringWidth(fm, str));
100             }
101             return max;
102         }
103
104
105         public void paintComponent(Graphics JavaDoc g) {
106             super.paintComponent(g);
107
108             if (node == null) return;
109
110             List JavaDoc flow = node.getDataFlowNode().getFlow();
111             FontMetrics JavaDoc fm = g.getFontMetrics();
112             int halfFontHeight = fm.getAscent() / 2;
113
114             String JavaDoc[] accessLabels = deriveAccessLabels(flow);
115             int maxAccessLabelWidth = maxWidthOf(accessLabels, fm);
116
117             for (int i = 0; i < flow.size(); i++) {
118                 IDataFlowNode inode = (IDataFlowNode) flow.get(i);
119
120                 y = computeDrawPos(inode.getIndex());
121
122                 g.drawArc(x, y, NODE_DIAMETER, NODE_DIAMETER, 0, 360);
123                 g.drawString(lines.getLine(inode.getLine()), x + 100 + maxAccessLabelWidth, y + 15);
124
125                 // draw index number centered inside of node
126
String JavaDoc idx = String.valueOf(inode.getIndex());
127                 int halfWidth = SwingUtilities.computeStringWidth(fm, idx) / 2;
128                 g.drawString(idx, x + NODE_RADIUS - halfWidth, y + NODE_RADIUS + halfFontHeight);
129
130                 String JavaDoc accessLabel = accessLabels[i];
131                 if (accessLabel != null) {
132                     g.drawString(accessLabel, x + 70, y + 15);
133                 }
134
135                 for (int j = 0; j < inode.getChildren().size(); j++) {
136                     IDataFlowNode n = (IDataFlowNode) inode.getChildren().get(j);
137                     drawMyLine(inode.getIndex(), n.getIndex(), g);
138                 }
139                 String JavaDoc childIndices = childIndicesOf(inode, ", ");
140                 g.drawString(childIndices, x - 3 * NODE_DIAMETER, y + NODE_RADIUS - 2);
141             }
142         }
143
144         public void setCode(LineGetter h) {
145             this.lines = h;
146         }
147
148         public void setMethod(SimpleNode node) {
149             this.node = node;
150         }
151
152         private int computeDrawPos(int index) {
153             int z = NODE_RADIUS * 4;
154             return z + index * z;
155         }
156
157         private void drawArrow(Graphics JavaDoc g, int x, int y, int direction) {
158
159             final int height = NODE_RADIUS * 2/3;
160             final int width = NODE_RADIUS * 2/3;
161
162             switch (direction) {
163                case SwingConstants.NORTH :
164                    g.drawLine(x, y, x - width/2, y + height);
165                    g.drawLine(x, y, x + width/2, y + height);
166                    break;
167                case SwingConstants.SOUTH :
168                    g.drawLine(x, y, x - width/2, y - height);
169                    g.drawLine(x, y, x + width/2, y - height);
170                    break;
171                case SwingConstants.EAST :
172                    g.drawLine(x, y, x - height, y - width/2);
173                    g.drawLine(x, y, x - height, y + width/2);
174                    break;
175                case SwingConstants.WEST :
176                    g.drawLine(x, y, x + height, y - width/2);
177                    g.drawLine(x, y, x + height, y + width/2);
178             }
179         }
180
181         private void drawMyLine(int index1, int index2, Graphics JavaDoc g) {
182             int y1 = this.computeDrawPos(index1);
183             int y2 = this.computeDrawPos(index2);
184
185             int arrow = 6;
186
187             if (index1 < index2) {
188                 if (index2 - index1 == 1) {
189                     x += NODE_RADIUS;
190                     g.drawLine(x, y1 + NODE_DIAMETER, x, y2);
191                   // g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
192
drawArrow(g, x, y2, SwingConstants.SOUTH);
193                     x -= NODE_RADIUS;
194                 } else if (index2 - index1 > 1) {
195                     y1 = y1 + NODE_RADIUS;
196                     y2 = y2 + NODE_RADIUS;
197                     int n = ((index2 - index1 - 2) * 10) + 10;
198                     g.drawLine(x, y1, x - n, y1);
199                     g.drawLine(x - n, y1, x - n, y2);
200                     g.drawLine(x - n, y2, x, y2);
201                  // g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
202
drawArrow(g, x,y2, SwingConstants.EAST);
203                 }
204
205             } else {
206                 if (index1 - index2 > 1) {
207                     y1 = y1 + NODE_RADIUS;
208                     y2 = y2 + NODE_RADIUS;
209                     x = x + NODE_DIAMETER;
210                     int n = ((index1 - index2 - 2) * 10) + 10;
211                     g.drawLine(x, y1, x + n, y1);
212                     g.drawLine(x + n, y1, x + n, y2);
213                     g.drawLine(x + n, y2, x, y2);
214               // g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
215
drawArrow(g, x, y2, SwingConstants.WEST);
216                     x = x - NODE_DIAMETER;
217                 } else if (index1 - index2 == 1) {
218                     y2 = y2 + NODE_DIAMETER;
219                     g.drawLine(x + NODE_RADIUS, y2, x + NODE_RADIUS, y1);
220                  // g.fillRect(x + NODE_RADIUS - arrow, y2 - arrow, arrow * 2, arrow * 2);
221
drawArrow(g, x + NODE_RADIUS, y2, SwingConstants.NORTH);
222                 }
223             }
224         }
225     }
226
227     private static class ElementWrapper {
228         private ASTMethodDeclaration node;
229
230         public ElementWrapper(ASTMethodDeclaration node) {
231             this.node = node;
232         }
233
234         public ASTMethodDeclaration getNode() {
235             return node;
236         }
237
238         public String JavaDoc toString() {
239             return node.getMethodName();
240         }
241     }
242
243     private DFACanvas dfaCanvas;
244     private JList nodeList;
245     private DefaultListModel nodes = new DefaultListModel();
246
247     public DFAPanel() {
248         super();
249
250         setLayout(new BorderLayout JavaDoc());
251         JPanel leftPanel = new JPanel();
252
253         nodeList = new JList(nodes);
254         nodeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
255         nodeList.setFixedCellWidth(150);
256         nodeList.setBorder(BorderFactory.createLineBorder(Color.black));
257         nodeList.addListSelectionListener(this);
258
259         leftPanel.add(nodeList);
260         add(leftPanel, BorderLayout.WEST);
261
262         dfaCanvas = new DFACanvas();
263         dfaCanvas.setBackground(Color.WHITE);
264         dfaCanvas.setPreferredSize(new Dimension JavaDoc(900, 1400));
265
266         JScrollPane scrollPane = new JScrollPane(dfaCanvas);
267
268         add(scrollPane, BorderLayout.CENTER);
269     }
270
271     public void valueChanged(ListSelectionEvent JavaDoc event) {
272         ElementWrapper wrapper = null;
273         if (nodes.size() == 1) {
274             wrapper = (ElementWrapper) nodes.get(0);
275         } else if (nodes.isEmpty()) {
276             return;
277         } else if (nodeList.getSelectedValue() == null) {
278             wrapper = (ElementWrapper) nodes.get(0);
279         } else {
280             wrapper = (ElementWrapper) nodeList.getSelectedValue();
281         }
282         dfaCanvas.setMethod(wrapper.getNode());
283         dfaCanvas.repaint();
284     }
285
286     public void resetTo(List JavaDoc newNodes, LineGetter lines) {
287         dfaCanvas.setCode(lines);
288         nodes.clear();
289         for (Iterator JavaDoc i = newNodes.iterator(); i.hasNext();) {
290             nodes.addElement(new ElementWrapper((ASTMethodDeclaration) i.next()));
291         }
292         nodeList.setSelectedIndex(0);
293         dfaCanvas.setMethod((SimpleNode) newNodes.get(0));
294         repaint();
295     }
296 }
297
Popular Tags