|
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 |
| |