001 package net.sourceforge.retroweaver.gui;
002
003 import java.awt.BorderLayout;
004 import java.awt.Component;
005 import java.awt.Container;
006 import java.awt.Cursor;
007 import java.awt.Dimension;
008 import java.awt.FlowLayout;
009 import java.awt.GridBagConstraints;
010 import java.awt.GridBagLayout;
011 import java.awt.Insets;
012 import java.awt.Toolkit;
013 import java.awt.event.ActionEvent;
014 import java.awt.event.ActionListener;
015 import java.io.File;
016 import java.util.ArrayList;
017 import java.util.StringTokenizer;
018
019 import javax.swing.BorderFactory;
020 import javax.swing.JButton;
021 import javax.swing.JComboBox;
022 import javax.swing.JFileChooser;
023 import javax.swing.JFrame;
024 import javax.swing.JLabel;
025 import javax.swing.JOptionPane;
026 import javax.swing.JPanel;
027 import javax.swing.JScrollPane;
028 import javax.swing.JTextArea;
029 import javax.swing.JTextField;
030 import javax.swing.event.DocumentEvent;
031 import javax.swing.event.DocumentListener;
032
033 import org.objectweb.asm.commons.EmptyVisitor;
034
035 import net.sourceforge.retroweaver.RefVerifier;
036 import net.sourceforge.retroweaver.RetroWeaver;
037 import net.sourceforge.retroweaver.Weaver;
038 import net.sourceforge.retroweaver.event.VerifierListener;
039 import net.sourceforge.retroweaver.event.WeaveListener;
040
041 /**
042 * A simple graphical user interface for Retroweaver.
043 */
044 public class RetroWeaverGui extends JPanel implements WeaveListener,
045 VerifierListener {
046
047 public static void main(String[] args) {
048 String defaultPath = "";
049
050 if (args.length > 0) {
051 if (args[0].equals("-console")) {
052 String a[] = new String[args.length - 1];
053 System.arraycopy(args, 1, a, 0, args.length - 1);
054 Weaver.main(a);
055 return;
056 }
057 defaultPath = args[0];
058 }
059
060 String version = Weaver.getVersion();
061 showInJFrame("RetroWeaver " + version, new RetroWeaverGui(defaultPath));
062 }
063
064 private static void showInJFrame(String title, Component contents) {
065 JFrame frame = new JFrame(title);
066 frame.getContentPane().add(contents);
067 frame.setSize(400, 300);
068 centerOnScreen(frame);
069 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
070 frame.setVisible(true);
071 }
072
073 private static void centerOnScreen(JFrame frame) {
074 Dimension frameSize = frame.getSize();
075 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
076 int x = (screenSize.width - frameSize.width) / 2;
077 int y = (screenSize.height - frameSize.height) / 2;
078 frame.setLocation(x, y);
079 }
080
081 public RetroWeaverGui(String defaultPath) {
082 super(new BorderLayout());
083 refClassPath = new JTextField();
084 add(createParameterSection(), BorderLayout.NORTH);
085 add(createMessageArea(), BorderLayout.CENTER);
086 add(createSouthSection(), BorderLayout.SOUTH);
087 pathField.setText(defaultPath);
088 }
089
090 public void weavingStarted(String msg) {
091 displayWeavingMessage(msg);
092 }
093
094 public void weavingPath(String sourcePath) {
095 String pathAsString = path.getAbsolutePath();
096 String p;
097 if (sourcePath.startsWith(pathAsString)) {
098 p = sourcePath.substring(pathAsString.length());
099 } else {
100 p = sourcePath;
101 }
102 displayWeavingMessage(p);
103 }
104
105 public void weavingError(String msg) {
106 displayWeavingMessage(msg);
107 }
108
109 public void weavingCompleted(String msg) {
110 displayWeavingMessage(msg);
111 }
112
113 private void displayWeavingMessage(String msg) {
114 messages.append("[RetroWeaver] " + msg + "\n");
115 messageScrollPane.getVerticalScrollBar().setValue(
116 messageScrollPane.getVerticalScrollBar().getMaximum());
117 }
118
119 public void verifyPathStarted(String msg) {
120 displayVerifierMessage(msg);
121 }
122
123 public void verifyClassStarted(String msg) {
124 displayVerifierMessage(msg);
125 }
126
127 public void acceptWarning(String msg) {
128 displayVerifierMessage(msg);
129 }
130
131 public void displaySummary(int warningCount) {
132 displayVerifierMessage("Verification complete, " + warningCount
133 + " warning(s).");
134 }
135
136 private void displayVerifierMessage(String msg) {
137 messages.append("[RefVerifier] " + msg + "\n");
138 messageScrollPane.getVerticalScrollBar().setValue(
139 messageScrollPane.getVerticalScrollBar().getMaximum());
140 }
141
142 private Component createParameterSection() {
143 JPanel ret = new JPanel(new GridBagLayout());
144 addAt(ret, 0, 0, new JLabel("Source:"));
145 addAt(ret, 1, 0, GridBagConstraints.HORIZONTAL, 2, 0.0,
146 createPathField());
147 addAt(ret, 3, 0, createBrowse());
148 addAt(ret, 0, 1, new JLabel("Target:"));
149 addAt(ret, 1, 1, createTargetChooser());
150 addAt(ret, 2, 1, GridBagConstraints.HORIZONTAL, 1, 1.0, new JPanel());
151 addAt(ret, 0, 2, new JLabel("Ref Verify Classpath:"));
152 addAt(ret, 1, 2, GridBagConstraints.HORIZONTAL, 2, 0.0, refClassPath);
153 addAt(ret, 3, 2, GridBagConstraints.HORIZONTAL, 1, 1.0, new JPanel());
154 return ret;
155 }
156
157 private Component createSouthSection() {
158 JPanel ret = new JPanel(new BorderLayout());
159 ret.add(createActionButtons(), BorderLayout.CENTER);
160 ret.add(createStatus(), BorderLayout.SOUTH);
161 ret.setBorder(BorderFactory.createEmptyBorder(INSET_SIZE, INSET_SIZE,
162 INSET_SIZE, INSET_SIZE));
163 return ret;
164 }
165
166 private Component createActionButtons() {
167 JPanel ret = new JPanel(new FlowLayout(FlowLayout.RIGHT));
168 ret.add(createTransform());
169 ret.add(createExit());
170 return ret;
171 }
172
173 private Component createPathField() {
174 pathField = new JTextField();
175 pathField.getDocument().addDocumentListener(new DocumentListener() {
176 public void insertUpdate(DocumentEvent e) {
177 doPathChanged();
178 }
179
180 public void removeUpdate(DocumentEvent e) {
181 doPathChanged();
182 }
183
184 public void changedUpdate(DocumentEvent e) {
185 // do nothing
186 }
187 });
188 return pathField;
189 }
190
191 private Component createBrowse() {
192 JButton browse = new JButton("Browse...");
193 browse.addActionListener(new ActionListener() {
194 public void actionPerformed(ActionEvent e) {
195 doBrowse();
196 }
197 });
198 return browse;
199 }
200
201 private Component createTargetChooser() {
202 targetCombo = new JComboBox(new String[] { "1.4", "1.3", "1.2" });
203 targetCombo.setSelectedIndex(0);
204 targetCombo.addActionListener(new ActionListener() {
205 public void actionPerformed(ActionEvent e) {
206 status.setText(READY);
207 }
208 });
209 return targetCombo;
210 }
211
212 private Component createTransform() {
213 JButton transform = new JButton("Transform");
214 transform.addActionListener(new ActionListener() {
215 public void actionPerformed(ActionEvent e) {
216 doTransform();
217 }
218 });
219 return transform;
220 }
221
222 private Component createExit() {
223 JButton exit = new JButton("Exit");
224 exit.addActionListener(new ActionListener() {
225 public void actionPerformed(ActionEvent e) {
226 doExit();
227 }
228 });
229 return exit;
230 }
231
232 private Component createStatus() {
233 status = new JLabel(READY);
234 return status;
235 }
236
237 private Component createMessageArea() {
238 JPanel ret = new JPanel(new BorderLayout());
239 ret.setBorder(BorderFactory.createTitledBorder("Messages"));
240 messages = new JTextArea();
241 messageScrollPane = new JScrollPane(messages);
242 ret.add(messageScrollPane, BorderLayout.CENTER);
243 return ret;
244 }
245
246 private void addAt(Container container, int x, int y, Component component) {
247 addAt(container, x, y, 0, 1, 0.0, component);
248 }
249
250 private void addAt(Container container, int x, int y, int fill,
251 int gridwidth, double weightx, Component component) {
252 GridBagConstraints constraints = new GridBagConstraints();
253 constraints.gridx = x;
254 constraints.gridy = y;
255 constraints.fill = fill;
256 constraints.insets = INSETS;
257 constraints.gridwidth = gridwidth;
258 constraints.weightx = weightx;
259 container.add(component, constraints);
260 }
261
262 private void doTransform() {
263
264 if (runWeaverThread != null && runWeaverThread.isAlive()) {
265 JOptionPane
266 .showMessageDialog(this,
267 "RetroWeaver is already running, wait until it has finished ");
268 return;
269 }
270
271 path = new File(pathField.getText());
272
273 if (!path.exists()) {
274 status.setText("Error: Path \"" + path + "\" does not exist");
275 return;
276 }
277
278 version = VERSION_NUMBERS[targetCombo.getSelectedIndex()];
279 runWeaverThread = createWeaverThread();
280 runWeaverThread.start();
281 }
282
283 private void doBrowse() {
284 JFileChooser fileChooser = new JFileChooser();
285 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
286
287 if (fileChooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) {
288 return;
289 }
290
291 pathField.setText(fileChooser.getSelectedFile().getAbsolutePath());
292 status.setText(READY);
293 }
294
295 private void doExit() {
296 JFrame frame = (JFrame) getTopLevelAncestor();
297 frame.dispose();
298 }
299
300 private void doPathChanged() {
301 status.setText(READY);
302 }
303
304 private JTextField pathField;
305
306 private final JTextField refClassPath;
307
308 private JComboBox targetCombo;
309
310 private JLabel status;
311
312 private JTextArea messages;
313
314 private int version;
315
316 private File path;
317
318 private JScrollPane messageScrollPane;
319
320 private static final String READY = "Ready";
321
322 private static final int INSET_SIZE = 3;
323
324 private static final Insets INSETS = new Insets(INSET_SIZE, INSET_SIZE,
325 INSET_SIZE, INSET_SIZE);
326
327 private static final int[] VERSION_NUMBERS = new int[] {
328 Weaver.VERSION_1_4, Weaver.VERSION_1_3, Weaver.VERSION_1_2 };
329
330 private volatile Thread runWeaverThread;
331
332 private Thread createWeaverThread() {
333 return new Thread(new Runnable() {
334 public void run() {
335 Cursor oldCursor = getTopLevelAncestor().getCursor();
336 getTopLevelAncestor().setCursor(
337 Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
338
339 try {
340 status.setText("Running");
341 RetroWeaver weaver = new RetroWeaver(version);
342 messages.setText("");
343 weaver.setListener(RetroWeaverGui.this);
344
345 String refCp = refClassPath.getText();
346
347 if (refCp.length() != 0) {
348 java.util.List<String> classpath = new ArrayList<String>();
349 StringTokenizer st = new StringTokenizer(refCp,
350 File.pathSeparator);
351 while (st.hasMoreTokens()) {
352 classpath.add(st.nextToken());
353 }
354 RefVerifier verifier = new RefVerifier(version, new EmptyVisitor(), classpath,
355 RetroWeaverGui.this);
356 weaver.setVerifier(verifier);
357 }
358
359 weaver.weave(path);
360
361 status.setText("Done");
362 } catch (Exception ex) {
363 status.setText("Error: " + ex.getMessage());
364 } finally {
365 getTopLevelAncestor().setCursor(oldCursor);
366 }
367 }
368 });
369 }
370 }