Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes

ChatClientFrame Class Reference

Chat client GUI front-end. More...

Inheritance diagram for ChatClientFrame:
Inheritance graph
[legend]
Collaboration diagram for ChatClientFrame:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 ChatClientFrame (String args[])
 Creates a new instance of the ChatClientFrame.
void logMessage (String str)
 Logs message formated with limited HTML (limited because of JEditoPane)
void logStatus (String str)
 Updates status message by updating window title.
void actionPerformed (ActionEvent ae)
 Handle events from the Swing Timer.
void keyPressed (KeyEvent ke)
 Implements KeyListener's key pressed event.
void parseInputMessage ()
 Parses input message from inputMsg and sends it to chat server.
void keyReleased (KeyEvent ke)
 Implements KeyListener's key released event.
void keyTyped (KeyEvent ke)
 Implements KeyListener's key typed event.

Static Public Member Functions

static void main (String args[])
 Main entry point.

Private Member Functions

void sendButton_Clicked (MouseEvent evt)
 Parses input message and send it to chat server.

Private Attributes

String host = "127.0.0.1"
 Host name or IP address of the remote chat server.
int port = 2000
 TCP port where to connect to on remote chat server.
ChatClient connection
 Instance of threaded connection to chat server.
int reconnectTimeout = -1
 Interconnect delay timer.
int reconnectRetryCount = 0
 Retry counter of failed connecting attempts.
JButton sendButton
JTextField inputMsg
JLabel idLabel
JTextField userId
JEditorPane logArea

Static Private Attributes

static final long serialVersionUID = 7406765627069159382L
 Implements java.io.Serializable interface.
static final String defaultInputMsg = "<type message here>"
 Initial message content of the input text message field.

Detailed Description

Chat client GUI front-end.

Author:
Mikica B Kocic

Definition at line 28 of file ChatClientFrame.java.


Constructor & Destructor Documentation

ChatClientFrame.ChatClientFrame ( String  args[] )

Creates a new instance of the ChatClientFrame.

Parameters:
argsthe command line arguments passed to main

Definition at line 79 of file ChatClientFrame.java.

References connection, defaultInputMsg, host, idLabel, inputMsg, logArea, logMessage(), port, sendButton, sendButton_Clicked(), ChatClient.start(), and userId.

Referenced by main().

    {
        super( "IP1-4.1.1: Yet Another Simple Chat Client" );
        
        setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );

        //////////////////////////////////////////////////////////////////////////////////
        
        /* Top level components
         */
        Font textFont = new Font( Font.SANS_SERIF, Font.PLAIN, 14 );
        
        inputMsg = new JTextField( defaultInputMsg, 30 );
        inputMsg.addKeyListener( this );
        inputMsg.setFont( textFont );
        inputMsg.selectAll ();

        sendButton = new JButton ();
        sendButton.setText( "Send" );

        sendButton.addMouseListener(
                new MouseAdapter () {
                    public void mouseClicked( MouseEvent evt ) {
                        sendButton_Clicked( evt );
                    }
                }
            );

        idLabel = new JLabel( "My ID:" );
        idLabel.setFont( textFont );
        
        userId = new JTextField( System.getProperty( "user.name" ) );
        userId.addKeyListener( this );
        userId.setFont( textFont );

        logArea = new JEditorPane ();
        logArea.setFont( textFont );
        logArea.setBackground( new Color( 255, 255, 224 ) );
        logArea.setForeground( Color.BLACK );
        logArea.setEditable( false );
        
        logArea.setContentType( "text/html" );
        logArea.setText( "<html><head></head><body>\n</body></html>" ); 

        JScrollPane logPane = new JScrollPane ();
        logPane.setViewportView( logArea );

        //////////////////////////////////////////////////////////////////////////////////
        
        /* Layout (self explained?): 
         *     Upper: sendButton, inputMsg, idLabel and userId 
         *     Lower: scrolled logArea 
         */
        GroupLayout layout = new GroupLayout( getContentPane () );
        getContentPane().setLayout( layout );
        layout.setAutoCreateContainerGaps( true );
        layout.setAutoCreateGaps( true );

        layout.setHorizontalGroup
        (
            layout
                .createParallelGroup( GroupLayout.Alignment.LEADING )
                .addGroup
                ( 
                    layout
                        .createSequentialGroup ()
                        .addGroup
                        ( 
                            layout
                                .createParallelGroup( GroupLayout.Alignment.LEADING )
                                .addGroup
                                (
                                    GroupLayout.Alignment.TRAILING, 
                                    layout
                                        .createSequentialGroup ()
                                        .addComponent( sendButton )
                                        .addComponent( inputMsg )
                                        .addComponent( idLabel )
                                        .addComponent( userId )
                                )
                                .addComponent( logPane )
                        )
                )
        );
        
        layout.setVerticalGroup
        (
            layout
                .createParallelGroup( GroupLayout.Alignment.LEADING )
                .addGroup
                (
                    layout
                        .createSequentialGroup ()
                        .addGroup
                        (
                            layout
                                .createParallelGroup( GroupLayout.Alignment.BASELINE )
                                .addComponent( sendButton )
                                .addComponent( inputMsg )
                                .addComponent( idLabel )
                                .addComponent( userId )
                        )
                        .addComponent( logPane )
                )
        );
        
        pack();
        
        //////////////////////////////////////////////////////////////////////////////////
        
        /* Adjust window dimensions not to exceed screen dimensions ...
         */
        Dimension win = new Dimension( 1024, 600 );
        Dimension scsz = Toolkit.getDefaultToolkit().getScreenSize();
        win.width  = Math.min( win.width, scsz.width );
        win.height = Math.min( win.height, scsz.height - 40 );
        setSize( win );
        
        /* ... then center window on the screen.
         */
        setLocation( ( scsz.width - win.width )/2, ( scsz.height - 40 - win.height )/2 );
        
        /* Parse arguments: [ <host> [ <port> ] ]
         */
        if ( args.length >= 1 )
        {
            host = args[ 0 ];
            if( args.length >= 2 ) try {
                port = Integer.parseInt( args[ 1 ] );
            } catch ( NumberFormatException e ) {
                // TODO might report that we are using default port?
            }
        }
        
        /* Default 'usage' info...
         */
        logMessage( "<table border='0' cellspacing='2' align='right' color='#0000FF'>"
                + "<td><b>Usage:</b>&nbsp;</td>\n"
                + "<td><table border='0' cellspacing='0' bgcolor='#E0F0E0'>"
                + "<tr><td><code>:open [ &lt;hostname&gt; [ &lt;port&gt; ] ]</code></td>"
                + "<td><code><em>-- open new connection</em></code></td></tr>\n"
                + "<tr><td><code>:close</code></td>"
                + "<td><code><em>-- close current connection</em></code></td></tr>\n"
                + "<tr><td><code>:exit</code></td>"
                + "<td><code><em>-- quit application</em></code></td></tr>\n"
                + "<tr><td><code>:who</code></td>"
                + "<td><code><em>-- send 'wwhhoo' to chat server</em></code></td></tr>\n"
                + "</table>"
                + "</td></tr></table>"
                );

        /* Open communication link to server...
         */
        connection = new ChatClient( host, port, this );
        connection.start ();

        /* Instantiate connection monitor timer (for reconnect supervision)
         */
        Timer timer = new Timer( 1000, this );
        timer.start ();

        /* Ready for user to type in something...
         */
        inputMsg.selectAll ();
        inputMsg.requestFocus ();
    }

Member Function Documentation

void ChatClientFrame.actionPerformed ( ActionEvent  ae )

Handle events from the Swing Timer.

If connection is detected to be down, it will try to reconnect to chat server after some period of time. If reconnection retry count exceeded maximum, timer will stop retrying.

Definition at line 304 of file ChatClientFrame.java.

References connection, host, logMessage(), logStatus(), port, reconnectRetryCount, reconnectTimeout, and ChatClient.start().

    {
        final int maxRetryCount = 3;
        final int reconnectDelay = 2;
        
        if ( connection.isAlive () ) {
            reconnectTimeout = -1; // disables timer
            return;
        }

        if ( reconnectRetryCount >= maxRetryCount ) {

            if ( reconnectRetryCount == maxRetryCount ) {
                
                ++reconnectRetryCount;
                
                logMessage( "<br/><code>Press ENTER to quit or type<br/><br/>"
                    + "&nbsp;&nbsp; :open [ &lt;hostname&gt; [ &lt;port&gt; ] ]<br/><br/>"
                    + "to open new connection...</code><br/><br/>" 
                    );
                logStatus( "Dead" );
            }
            
            return; // leave to user to quit by pressing ENTER
        } 
            
        if ( reconnectTimeout < 0 )  {
            logStatus( "Disconnected" );
            logMessage( "<br/><code>Reconnecting in " 
                    + reconnectDelay + " seconds...</code>"
                    );
            reconnectTimeout = reconnectDelay; // start timer
            return;
        }
        
        if ( --reconnectTimeout > 0 ) {
            return;
        }
        
        logMessage( "<code>retry #"
               + ( ++reconnectRetryCount ) 
               + " of max " 
               + maxRetryCount
               + ":</code><br/>"
               );

        reconnectTimeout = -1; // disables timer and restarts new connection

        connection = new ChatClient( host, port , this );
        connection.start ();
    }
void ChatClientFrame.keyPressed ( KeyEvent  ke )

Implements KeyListener's key pressed event.

Definition at line 359 of file ChatClientFrame.java.

References parseInputMessage().

                                          {
        
        int keyCode = ke.getKeyCode ();
        
        if( keyCode == KeyEvent.VK_ENTER )
        {
            parseInputMessage ();
        }
    }
void ChatClientFrame.keyReleased ( KeyEvent  ke )

Implements KeyListener's key released event.

Definition at line 441 of file ChatClientFrame.java.

    {
        /* unused */
    }
void ChatClientFrame.keyTyped ( KeyEvent  ke )

Implements KeyListener's key typed event.

Definition at line 449 of file ChatClientFrame.java.

    {
        /* unused */
    }
void ChatClientFrame.logMessage ( String  str ) [virtual]

Logs message formated with limited HTML (limited because of JEditoPane)

Parameters:
strmessage that will be logged

Implements ChatClient.Context.

Definition at line 260 of file ChatClientFrame.java.

References logArea.

Referenced by actionPerformed(), and ChatClientFrame().

    {
        final String strCopy = new String( str );
        
        java.awt.EventQueue.invokeLater( 
                new Runnable() {
                    public void run() {
                        synchronized( logArea )
                        {
                            /* Append the string to the end of <body> element...
                             */
                            String html = logArea.getText ();
                            html = html.replace( "</body>", strCopy + "\n</body>" );
                            logArea.setText( html );
                        }
                    }
                }
            );
    }
void ChatClientFrame.logStatus ( String  str ) [virtual]

Updates status message by updating window title.

Parameters:
strnew status message

Implements ChatClient.Context.

Definition at line 286 of file ChatClientFrame.java.

Referenced by actionPerformed().

    {
        final String strCopy = new String( str );
        
        java.awt.EventQueue.invokeLater( 
                new Runnable() {
                    public void run() {
                        setTitle( "IP1-4.1.1 Chat Client: " + strCopy );
                    }
                }
            );
    }
static void ChatClientFrame.main ( String  args[] ) [static]

Main entry point.

Parameters:
argsthe command line arguments

Definition at line 459 of file ChatClientFrame.java.

References ChatClientFrame().

    {
        final String[] copyOfArgs = args;
        
        java.awt.EventQueue.invokeLater( 
                new Runnable() {
                    public void run() {
                        new ChatClientFrame( copyOfArgs ).setVisible( true );
                    }
                }
            );
    }
void ChatClientFrame.parseInputMessage (  )

Parses input message from inputMsg and sends it to chat server.

Also performs various commands :open, :close, :exit ...

Definition at line 373 of file ChatClientFrame.java.

References ChatClient.close(), connection, defaultInputMsg, host, inputMsg, port, reconnectRetryCount, ChatClient.send(), ChatClient.start(), and userId.

Referenced by keyPressed(), and sendButton_Clicked().

    {
        /* Split string into words, removing all leading, trailing 
         * and superfluous (btw words) white-spaces
         */
        String[] args = inputMsg.getText().trim().split( "\\s{1,}" );
        
        String cmd = args.length > 0 ? args[0] : "";

        if ( cmd.equalsIgnoreCase( ":who" ) ) {
            inputMsg.setText( "" );
            connection.send( "wwhhoo" );
            return;
        }
        else if ( cmd.equalsIgnoreCase( ":close" ) ) {
            inputMsg.setText( "" );
            reconnectRetryCount = Integer.MAX_VALUE; // suppresses reconnection
            connection.close ();
            return;
        }
        else if ( cmd.equalsIgnoreCase( ":open" ) ) {
            inputMsg.setText( "" );
            reconnectRetryCount = Integer.MAX_VALUE; // suppresses reconnection
            connection.close ();
            
            if ( args.length >= 2 )
            {
                host = args[ 1 ];
                port = 2000; // default port
                if( args.length >= 3 ) try {
                    port = Integer.parseInt( args[ 2 ] );
                } catch ( NumberFormatException e ) {
                    // TODO handle this
                }
            }
            
            connection = new ChatClient( host, port , this );
            connection.start ();
            reconnectRetryCount = 0;
            return;
        }
        else if ( cmd.equalsIgnoreCase( ":exit" ) ) {
            inputMsg.setText( "" );
            connection.close ();
            System.exit( 0 );
        }

        /* Default task: send message to chat server
         */
        if ( defaultInputMsg.equalsIgnoreCase( inputMsg.getText () ) ) {
            /* ignore default input message */
        } else if ( userId.getText ().trim ().length () == 0 ) { // an empty userId
            connection.send( inputMsg.getText () );
            inputMsg.setText( "" );
        } else {
            connection.send( inputMsg.getText (), userId.getText () );
            inputMsg.setText( "" );
        }

        if ( ! connection.isAlive () )
        {
            System.exit( 0 );
        }
    }
void ChatClientFrame.sendButton_Clicked ( MouseEvent  evt ) [private]

Parses input message and send it to chat server.

Definition at line 249 of file ChatClientFrame.java.

References parseInputMessage().

Referenced by ChatClientFrame().


Member Data Documentation

Instance of threaded connection to chat server.

Definition at line 54 of file ChatClientFrame.java.

Referenced by actionPerformed(), ChatClientFrame(), and parseInputMessage().

final String ChatClientFrame.defaultInputMsg = "<type message here>" [static, private]

Initial message content of the input text message field.

Definition at line 39 of file ChatClientFrame.java.

Referenced by ChatClientFrame(), and parseInputMessage().

String ChatClientFrame.host = "127.0.0.1" [private]

Host name or IP address of the remote chat server.

Default: localhost

Definition at line 44 of file ChatClientFrame.java.

Referenced by actionPerformed(), ChatClientFrame(), and parseInputMessage().

JLabel ChatClientFrame.idLabel [private]

Definition at line 70 of file ChatClientFrame.java.

Referenced by ChatClientFrame().

JTextField ChatClientFrame.inputMsg [private]

Definition at line 69 of file ChatClientFrame.java.

Referenced by ChatClientFrame(), and parseInputMessage().

JEditorPane ChatClientFrame.logArea [private]

Definition at line 72 of file ChatClientFrame.java.

Referenced by ChatClientFrame(), and logMessage().

int ChatClientFrame.port = 2000 [private]

TCP port where to connect to on remote chat server.

Default: 2000

Definition at line 49 of file ChatClientFrame.java.

Referenced by actionPerformed(), ChatClientFrame(), and parseInputMessage().

Retry counter of failed connecting attempts.

Definition at line 64 of file ChatClientFrame.java.

Referenced by actionPerformed(), and parseInputMessage().

Interconnect delay timer.

Value -1 means 'disabled'.

Definition at line 59 of file ChatClientFrame.java.

Referenced by actionPerformed().

JButton ChatClientFrame.sendButton [private]

Definition at line 68 of file ChatClientFrame.java.

Referenced by ChatClientFrame().

final long ChatClientFrame.serialVersionUID = 7406765627069159382L [static, private]

Implements java.io.Serializable interface.

Definition at line 34 of file ChatClientFrame.java.

JTextField ChatClientFrame.userId [private]

Definition at line 71 of file ChatClientFrame.java.

Referenced by ChatClientFrame(), and parseInputMessage().


The documentation for this class was generated from the following file: