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 }