package com.pugh.sockso.gui;
import com.pugh.sockso.commands.CommandExecuter;
import com.pugh.sockso.resources.Resources;
import com.pugh.sockso.resources.Locale;
import java.awt.Font;
import java.awt.Container;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.InputStream;
import java.io.OutputStream;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ImageIcon;
import org.apache.log4j.Logger;
import com.google.inject.Inject;
/**
* A window for interacting with the Sockso console from the GUI
*
*/
public class ConsoleFrame extends JFrame {
private static final Logger log = Logger.getLogger( ConsoleFrame.class );
private static final int MAX_OUTPUT_LENGTH = 5000;
private final CommandExecuter cmd;
private final Resources r;
private final Locale locale;
private JTextField inputField;
protected JTextArea outputArea;
private JButton commandButton, hideButton;
@Inject
public ConsoleFrame( final CommandExecuter cmd, final Resources r, final Locale locale ) {
super( locale.getString("gui.window.console") );
this.cmd = cmd;
this.r = r;
this.locale = locale;
createComponents();
layoutComponents();
}
/**
* creates the components for the GUI and set up actions, etc...
*
*/
private void createComponents() {
inputField = new JTextField();
inputField.addActionListener( getConsoleCommandAction() );
outputArea = new JTextArea();
outputArea.setEditable( false );
outputArea.setFont(new Font( "Courier", Font.PLAIN, 12 ));
commandButton = new JButton( locale.getString("gui.label.consoleCommandGo"), new ImageIcon(r.getImage("icons/22x22/execute.png")) );
commandButton.addActionListener( getConsoleCommandAction() );
hideButton = new JButton( locale.getString("gui.label.hide"), new ImageIcon(r.getImage("icons/22x22/hide.png")) );
hideButton.addActionListener( getHideButtonAction() );
}
/**
* lays out the GUI's components
*
*/
private void layoutComponents() {
JPanel buttonPanel = new JPanel( new FlowLayout() );
buttonPanel.add( commandButton );
buttonPanel.add( hideButton );
JPanel commandPanel = new JPanel();
commandPanel.setLayout( new BorderLayout() );
commandPanel.add( inputField, BorderLayout.CENTER );
commandPanel.add( buttonPanel, BorderLayout.EAST );
Container c = getContentPane();
c.setLayout( new BorderLayout() );
c.add( new JScrollPane(outputArea), BorderLayout.CENTER );
c.add( commandPanel, BorderLayout.SOUTH );
}
/**
* returns the action to use when executing a command
*
* @return
*
*/
private ActionListener getConsoleCommandAction() {
return new ActionListener() {
public void actionPerformed( ActionEvent evt ) {
try {
// constrain the amount of text displayed in the outputArea,
// don't want it getting too massive.
final String newText = outputArea.getText() + cmd.execute( inputField.getText() ) + "\n\n";
final int len = newText.length();
final int start = len > MAX_OUTPUT_LENGTH ? len - MAX_OUTPUT_LENGTH : 0;
outputArea.setText( newText.substring(start,len) + "\n" );
inputField.setText( "" );
}
catch ( Exception e ) {
log.error( e );
}
}
};
}
/**
* returns the action handler for the hide button
*
* @return
*
*/
private ActionListener getHideButtonAction() {
return new ActionListener() {
public void actionPerformed( ActionEvent evt ) {
setVisible( false );
}
};
}
}
/**
* the input stream of data for the console to read from, HOWEVER, this is
* unused as we just access the consoles dispatchCommand() method directly
*
*/
class ConsoleInputStream extends InputStream {
@Override
public int read() {
return -1;
}
}
/**
* class to read data that comes back from the console. it will then write
* this data into the main text area for the user to see
*
*/
class ConsoleOutputStream extends OutputStream {
private final ConsoleFrame frame;
public ConsoleOutputStream( ConsoleFrame frame ) {
this.frame = frame;
}
public void write( int i ) {
StringBuffer sb = new StringBuffer( frame.outputArea.getText() );
sb.append( (char) i );
frame.outputArea.setText( sb.toString() );
}
}