package com.rc.retroweaver.gui;
import com.rc.retroweaver.*;
import com.rc.retroweaver.Weaver;
import com.rc.retroweaver.event.WeaveListener;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.*;
/**
* A simple graphical user interface for Retroweaver.
*
* @author rreyelts
* Donated by Sean Shubin
*
*/
public class RetroWeaverGui extends JPanel implements WeaveListener, RefVerifier.Listener {
public static void main(String[] args) {
String defaultPath = "";
if ( args.length > 0 ) {
defaultPath = args[ 0 ];
}
showInJFrame( "RetroWeaver", new RetroWeaverGui( defaultPath ) );
}
private static void showInJFrame( String title, Component contents ) {
JFrame frame = new JFrame( title );
frame.getContentPane().add( contents );
frame.setSize( 400, 300 );
centerOnScreen( frame );
frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
frame.setVisible( true );
}
private static void centerOnScreen( JFrame frame ) {
Dimension frameSize = frame.getSize();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int x = ( screenSize.width - frameSize.width ) / 2;
int y = ( screenSize.height - frameSize.height ) / 2;
frame.setLocation( x, y );
}
public RetroWeaverGui( String defaultPath ) {
super( new BorderLayout( ));
refClassPath = new JTextField();
add( createParameterSection(), BorderLayout.NORTH );
add( createMessageArea(), BorderLayout.CENTER );
add( createSouthSection(), BorderLayout.SOUTH );
pathField.setText( defaultPath );
}
public void weavingPath( String sourcePath ) {
String pathAsString = path.getAbsolutePath();
if ( sourcePath.startsWith( pathAsString ) ) {
sourcePath = sourcePath.substring( pathAsString.length() );
}
messages.append( "[RetroWeaver] Weaving " + sourcePath + "\n" );
messageScrollPane.getVerticalScrollBar().setValue( messageScrollPane.getVerticalScrollBar().getMaximum() );
}
public void verifyStarted( String msg ) {
messages.append( "[RefVerifier] " + msg + "\n" );
messageScrollPane.getVerticalScrollBar().setValue( messageScrollPane.getVerticalScrollBar().getMaximum() );
}
public void acceptWarning( String msg ) {
messages.append( "[RefVerifier] " + msg + "\n" );
messageScrollPane.getVerticalScrollBar().setValue( messageScrollPane.getVerticalScrollBar().getMaximum() );
}
private Component createParameterSection() {
JPanel ret = new JPanel( new GridBagLayout() );
addAt( ret, 0, 0, new JLabel( "Source:" ) );
addAt( ret, 1, 0, GridBagConstraints.HORIZONTAL, 2, 0.0, createPathField() );
addAt( ret, 3, 0, createBrowse() );
addAt( ret, 0, 1, new JLabel( "Version:" ) );
addAt( ret, 1, 1, createVersionChooser() );
addAt( ret, 2, 1, GridBagConstraints.HORIZONTAL, 1, 1.0, new JPanel() );
addAt( ret, 0, 2, new JLabel( "Ref Verify Classpath:" ) );
addAt( ret, 1, 2, GridBagConstraints.HORIZONTAL, 2, 0.0, refClassPath);
addAt( ret, 3, 2, GridBagConstraints.HORIZONTAL, 1, 1.0, new JPanel() );
return ret;
}
private Component createSouthSection() {
JPanel ret = new JPanel( new BorderLayout() );
ret.add( createActionButtons(), BorderLayout.CENTER );
ret.add( createStatus(), BorderLayout.SOUTH );
ret.setBorder( BorderFactory.createEmptyBorder( INSET_SIZE, INSET_SIZE, INSET_SIZE, INSET_SIZE ) );
return ret;
}
private Component createActionButtons() {
JPanel ret = new JPanel( new FlowLayout( FlowLayout.RIGHT ) );
ret.add( createTransform() );
ret.add( createExit() );
return ret;
}
private Component createPathField() {
pathField = new JTextField();
pathField.getDocument().addDocumentListener( new DocumentListener() {
public void insertUpdate( DocumentEvent e ) {
doPathChanged();
}
public void removeUpdate( DocumentEvent e ) {
doPathChanged();
}
public void changedUpdate( DocumentEvent e ) {
//do nothing
}
});
return pathField;
}
private Component createBrowse() {
browse = new JButton( "Browse..." );
browse.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
doBrowse();
}
});
return browse;
}
private Component createVersionChooser() {
versionCombo = new JComboBox( new String[] {"1.4", "1.3", "1.2" } );
versionCombo.setSelectedIndex( 0 );
versionCombo.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
status.setText( READY );
}
});
return versionCombo;
}
private Component createTransform() {
transform = new JButton( "Transform" );
transform.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
doTransform();
}
});
return transform;
}
private Component createExit() {
exit = new JButton( "Exit" );
exit.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
doExit();
}
});
return exit;
}
private Component createStatus() {
status = new JLabel( READY );
return status;
}
private Component createMessageArea() {
JPanel ret = new JPanel( new BorderLayout() );
ret.setBorder(BorderFactory.createTitledBorder( "Messages" ) );
messages = new JTextArea();
messageScrollPane = new JScrollPane( messages );
ret.add( messageScrollPane, BorderLayout.CENTER );
return ret;
}
private void addAt( Container container, int x, int y, Component component ) {
addAt(container, x, y, 0, 1, 0.0, component);
}
private void addAt( Container container, int x, int y, int fill, int gridwidth, double weightx, Component component ) {
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = x;
constraints.gridy = y;
constraints.fill = fill;
constraints.insets = INSETS;
constraints.gridwidth = gridwidth;
constraints.weightx = weightx;
container.add( component, constraints );
}
private void doTransform() {
if ( runWeaverThread != null && runWeaverThread.isAlive() ) {
JOptionPane.showMessageDialog( this, "RetroWeaver is already running, wait until it has finished " );
return;
}
path = new File( pathField.getText() );
if ( !path.exists() ) {
status.setText( "Error: Path \"" + path + "\" does not exist" );
return;
}
version = VERSION_NUMBERS[ versionCombo.getSelectedIndex() ];
runWeaverThread = createWeaverThread();
runWeaverThread.start();
}
private void doBrowse() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
if ( fileChooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION ) {
return;
}
pathField.setText( fileChooser.getSelectedFile().getAbsolutePath() );
status.setText( READY );
}
private void doExit() {
JFrame frame = (JFrame) getTopLevelAncestor();
frame.dispose();
}
private void doPathChanged() {
status.setText( READY );
}
private JButton transform;
private JButton browse;
private JTextField pathField;
private JTextField refClassPath;
private JComboBox versionCombo;
private JLabel status;
private JButton exit;
private JTextArea messages;
private int version;
private File path;
private JScrollPane messageScrollPane;
private static final String READY = "Ready";
private static final int INSET_SIZE = 3;
private static final Insets INSETS = new Insets( INSET_SIZE, INSET_SIZE, INSET_SIZE, INSET_SIZE );
private static final int[] VERSION_NUMBERS = new int[] { Weaver.VERSION_1_4, Weaver.VERSION_1_3, Weaver.VERSION_1_2 };
private Thread runWeaverThread;
private Thread createWeaverThread() {
return new Thread( new Runnable() {
public void run() {
Cursor oldCursor = getTopLevelAncestor().getCursor();
getTopLevelAncestor().setCursor(Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );
try {
status.setText( "Running" );
RetroWeaver weaver = new RetroWeaver( version );
messages.setText( "" );
weaver.setListener( RetroWeaverGui.this );
Weaver.invokeWeaver( weaver, path );
String refCp = refClassPath.getText();
if ( refCp.length() != 0 ) {
java.util.List<String> classpath = new ArrayList<String>();
StringTokenizer st = new StringTokenizer( refCp, File.pathSeparator );
while ( st.hasMoreTokens() ) {
classpath.add( st.nextToken() );
}
RefVerifier verifier = new RefVerifier( classpath, RetroWeaverGui.this );
Weaver.invokeVerifier( verifier, path );
}
status.setText( "Done" );
}
catch ( Exception ex ) {
status.setText( "Error: " + ex.getMessage() );
}
finally {
getTopLevelAncestor().setCursor( oldCursor );
}
}
});
}
}