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.HasLines; |
8 |
| |
9 |
| import javax.swing.*; |
10 |
| import javax.swing.event.ListSelectionEvent; |
11 |
| import javax.swing.event.ListSelectionListener; |
12 |
| import java.awt.BorderLayout; |
13 |
| import java.awt.Canvas; |
14 |
| import java.awt.Color; |
15 |
| import java.awt.Dimension; |
16 |
| import java.awt.Graphics; |
17 |
| import java.util.Iterator; |
18 |
| import java.util.List; |
19 |
| |
20 |
| public class DFAPanel extends JComponent implements ListSelectionListener { |
21 |
| |
22 |
| public static class DFACanvas extends Canvas { |
23 |
| |
24 |
| private static final int NODE_RADIUS = 10; |
25 |
| private static final int NODE_DIAMETER = 2 * NODE_RADIUS; |
26 |
| |
27 |
| private SimpleNode node; |
28 |
| |
29 |
| private int x = 150; |
30 |
| private int y = 50; |
31 |
| private HasLines lines; |
32 |
| |
33 |
0
| public void paint(Graphics g) {
|
34 |
0
| super.paint(g);
|
35 |
0
| if (node == null) {
|
36 |
0
| return;
|
37 |
| } |
38 |
0
| List flow = node.getDataFlowNode().getFlow();
|
39 |
0
| for (int i = 0; i < flow.size(); i++) {
|
40 |
0
| IDataFlowNode inode = (IDataFlowNode) flow.get(i);
|
41 |
| |
42 |
0
| y = computeDrawPos(inode.getIndex());
|
43 |
| |
44 |
0
| g.drawArc(x, y, NODE_DIAMETER, NODE_DIAMETER, 0, 360);
|
45 |
0
| g.drawString(lines.getLine(inode.getLine()), x + 200, y + 15);
|
46 |
| |
47 |
| |
48 |
0
| String idx = String.valueOf(inode.getIndex());
|
49 |
0
| int hack = 4 * (idx.length() / 2);
|
50 |
0
| g.drawString(idx, x + NODE_RADIUS - 2 - hack, y + NODE_RADIUS + 4);
|
51 |
| |
52 |
0
| List access = inode.getVariableAccess();
|
53 |
0
| if (access != null) {
|
54 |
0
| StringBuffer exp = new StringBuffer();
|
55 |
0
| for (int k = 0; k < access.size(); k++) {
|
56 |
0
| VariableAccess va = (VariableAccess) access.get(k);
|
57 |
0
| if (va.isDefinition()) {
|
58 |
0
| exp.append("d(");
|
59 |
0
| } else if (va.isReference()) {
|
60 |
0
| exp.append("r(");
|
61 |
0
| } else if (va.isUndefinition()) {
|
62 |
0
| exp.append("u(");
|
63 |
| |
64 |
| } else { |
65 |
0
| exp.append("?(");
|
66 |
| } |
67 |
0
| exp.append(va.getVariableName() + "), ");
|
68 |
| } |
69 |
0
| g.drawString(exp.toString(), x + 70, y + 15);
|
70 |
| } |
71 |
| |
72 |
0
| for (int j = 0; j < inode.getChildren().size(); j++) {
|
73 |
0
| IDataFlowNode n = (IDataFlowNode) inode.getChildren().get(j);
|
74 |
0
| this.drawMyLine(inode.getIndex(), n.getIndex(), g);
|
75 |
0
| String output = (j == 0 ? "" : ",") + String.valueOf(n.getIndex());
|
76 |
0
| g.drawString(output, x - 3 * NODE_DIAMETER + (j * 20), y + NODE_RADIUS - 2);
|
77 |
| } |
78 |
| } |
79 |
| } |
80 |
| |
81 |
0
| public void setCode(HasLines h) {
|
82 |
0
| this.lines = h;
|
83 |
| } |
84 |
| |
85 |
0
| public void setMethod(SimpleNode node) {
|
86 |
0
| this.node = node;
|
87 |
| } |
88 |
| |
89 |
0
| private int computeDrawPos(int index) {
|
90 |
0
| int z = NODE_RADIUS * 4;
|
91 |
0
| return z + index * z;
|
92 |
| } |
93 |
| |
94 |
0
| private void drawMyLine(int index1, int index2, Graphics g) {
|
95 |
0
| int y1 = this.computeDrawPos(index1);
|
96 |
0
| int y2 = this.computeDrawPos(index2);
|
97 |
| |
98 |
0
| int arrow = 3;
|
99 |
| |
100 |
0
| if (index1 < index2) {
|
101 |
0
| if (index2 - index1 == 1) {
|
102 |
0
| x += NODE_RADIUS;
|
103 |
0
| g.drawLine(x, y1 + NODE_DIAMETER, x, y2);
|
104 |
0
| g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
|
105 |
0
| x -= NODE_RADIUS;
|
106 |
0
| } else if (index2 - index1 > 1) {
|
107 |
0
| y1 = y1 + NODE_RADIUS;
|
108 |
0
| y2 = y2 + NODE_RADIUS;
|
109 |
0
| int n = ((index2 - index1 - 2) * 10) + 10;
|
110 |
0
| g.drawLine(x, y1, x - n, y1);
|
111 |
0
| g.drawLine(x - n, y1, x - n, y2);
|
112 |
0
| g.drawLine(x - n, y2, x, y2);
|
113 |
0
| g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
|
114 |
| } |
115 |
| |
116 |
| } else { |
117 |
0
| if (index1 - index2 > 1) {
|
118 |
0
| y1 = y1 + NODE_RADIUS;
|
119 |
0
| y2 = y2 + NODE_RADIUS;
|
120 |
0
| x = x + NODE_DIAMETER;
|
121 |
0
| int n = ((index1 - index2 - 2) * 10) + 10;
|
122 |
0
| g.drawLine(x, y1, x + n, y1);
|
123 |
0
| g.drawLine(x + n, y1, x + n, y2);
|
124 |
0
| g.drawLine(x + n, y2, x, y2);
|
125 |
0
| g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
|
126 |
0
| x = x - NODE_DIAMETER;
|
127 |
0
| } else if (index1 - index2 == 1) {
|
128 |
0
| y2 = y2 + NODE_DIAMETER;
|
129 |
0
| g.drawLine(x + NODE_RADIUS, y2, x + NODE_RADIUS, y1);
|
130 |
0
| g.fillRect(x + NODE_RADIUS - arrow, y2 - arrow, arrow * 2, arrow * 2);
|
131 |
| } |
132 |
| } |
133 |
| } |
134 |
| } |
135 |
| |
136 |
| private static class ElementWrapper { |
137 |
| private ASTMethodDeclaration node; |
138 |
| |
139 |
0
| public ElementWrapper(ASTMethodDeclaration node) {
|
140 |
0
| this.node = node;
|
141 |
| } |
142 |
| |
143 |
0
| public ASTMethodDeclaration getNode() {
|
144 |
0
| return node;
|
145 |
| } |
146 |
| |
147 |
0
| public String toString() {
|
148 |
0
| return node.getMethodName();
|
149 |
| } |
150 |
| } |
151 |
| |
152 |
| private DFACanvas dfaCanvas; |
153 |
| private JList nodeList; |
154 |
| private DefaultListModel nodes = new DefaultListModel(); |
155 |
| private JPanel wrapperPanel; |
156 |
| |
157 |
0
| public DFAPanel() {
|
158 |
0
| super();
|
159 |
| |
160 |
0
| setLayout(new BorderLayout());
|
161 |
0
| JPanel leftPanel = new JPanel();
|
162 |
0
| nodeList = new JList(nodes);
|
163 |
0
| nodeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
164 |
0
| nodeList.setFixedCellWidth(150);
|
165 |
0
| nodeList.setBorder(BorderFactory.createLineBorder(Color.black));
|
166 |
0
| nodeList.addListSelectionListener(this);
|
167 |
0
| leftPanel.add(nodeList);
|
168 |
0
| add(leftPanel, BorderLayout.WEST);
|
169 |
| |
170 |
0
| dfaCanvas = new DFACanvas();
|
171 |
0
| JScrollPane scrollPane = new JScrollPane();
|
172 |
0
| scrollPane.setPreferredSize(new Dimension(800, 450));
|
173 |
0
| dfaCanvas.setSize(2000, 4000);
|
174 |
0
| scrollPane.add(dfaCanvas);
|
175 |
0
| wrapperPanel = new JPanel();
|
176 |
0
| wrapperPanel.add(scrollPane);
|
177 |
0
| wrapperPanel.setBorder(BorderFactory.createLineBorder(Color.black));
|
178 |
0
| add(wrapperPanel, BorderLayout.EAST);
|
179 |
| } |
180 |
| |
181 |
0
| public void valueChanged(ListSelectionEvent event) {
|
182 |
0
| ElementWrapper wrapper = null;
|
183 |
0
| if (nodes.size() == 1) {
|
184 |
0
| wrapper = (ElementWrapper) nodes.get(0);
|
185 |
0
| } else if (nodes.isEmpty()) {
|
186 |
0
| return;
|
187 |
0
| } else if (nodeList.getSelectedValue() == null) {
|
188 |
0
| wrapper = (ElementWrapper) nodes.get(0);
|
189 |
| } else { |
190 |
0
| wrapper = (ElementWrapper) nodeList.getSelectedValue();
|
191 |
| } |
192 |
0
| dfaCanvas.setMethod(wrapper.getNode());
|
193 |
0
| dfaCanvas.repaint();
|
194 |
| } |
195 |
| |
196 |
0
| public void resetTo(List newNodes, HasLines lines) {
|
197 |
0
| dfaCanvas.setCode(lines);
|
198 |
0
| nodes.clear();
|
199 |
0
| for (Iterator i = newNodes.iterator(); i.hasNext();) {
|
200 |
0
| nodes.addElement(new ElementWrapper((ASTMethodDeclaration) i.next()));
|
201 |
| } |
202 |
0
| nodeList.setSelectedIndex(0);
|
203 |
0
| dfaCanvas.setMethod((SimpleNode) newNodes.get(0));
|
204 |
0
| repaint();
|
205 |
| } |
206 |
| } |
207 |
| |