Source of ClientGUI.java


  1: // Fig. 24.28: ClientGUI.java
  2: // ClientGUI provides a user interface for sending and receiving
  3: // messages to and from the DeitelMessengerServer.
  4: package com.deitel.messenger;
  5: 
  6: import java.awt.BorderLayout;
  7: import java.awt.event.ActionEvent;
  8: import java.awt.event.ActionListener;
  9: import java.awt.event.WindowAdapter;
 10: import java.awt.event.WindowEvent;
 11: import javax.swing.Box;
 12: import javax.swing.BoxLayout;
 13: import javax.swing.Icon;
 14: import javax.swing.ImageIcon;
 15: import javax.swing.JButton;
 16: import javax.swing.JFrame;
 17: import javax.swing.JLabel;
 18: import javax.swing.JMenu;
 19: import javax.swing.JMenuBar;
 20: import javax.swing.JMenuItem;
 21: import javax.swing.JOptionPane;
 22: import javax.swing.JPanel;
 23: import javax.swing.JScrollPane;
 24: import javax.swing.JTextArea;
 25: import javax.swing.SwingUtilities;
 26: import javax.swing.border.BevelBorder;
 27: 
 28: public class ClientGUI extends JFrame 
 29: {   
 30:    private JMenu serverMenu; // for connecting/disconnecting server
 31:    private JTextArea messageArea; // displays messages
 32:    private JTextArea inputArea; // inputs messages
 33:    private JButton connectButton; // button for connecting
 34:    private JMenuItem connectMenuItem; // menu item for connecting
 35:    private JButton disconnectButton; // button for disconnecting
 36:    private JMenuItem disconnectMenuItem; // menu item for disconnecting
 37:    private JButton sendButton; // sends messages
 38:    private JLabel statusBar; // label for connection status
 39:    private String userName; // userName to add to outgoing messages
 40:    private MessageManager messageManager; // communicates with server
 41:    private MessageListener messageListener; // receives incoming messages
 42:  
 43:    // ClientGUI constructor
 44:    public ClientGUI( MessageManager manager ) 
 45:    {       
 46:       super( "Deitel Messenger" );
 47:       
 48:       messageManager = manager; // set the MessageManager
 49:       
 50:       // create MyMessageListener for receiving messages
 51:       messageListener = new MyMessageListener(); 
 52:       
 53:       serverMenu = new JMenu ( "Server" ); // create Server JMenu
 54:       serverMenu.setMnemonic( 'S' ); // set mnemonic for server menu
 55:       JMenuBar menuBar = new JMenuBar(); // create JMenuBar
 56:       menuBar.add( serverMenu ); // add server menu to menu bar
 57:       setJMenuBar( menuBar ); // add JMenuBar to application
 58:       
 59:       // create ImageIcon for connect buttons
 60:       Icon connectIcon = new ImageIcon( 
 61:          getClass().getResource( "images/Connect.gif" ) );
 62:       
 63:       // create connectButton and connectMenuItem
 64:       connectButton = new JButton( "Connect", connectIcon );
 65:       connectMenuItem = new JMenuItem( "Connect", connectIcon );  
 66:       connectMenuItem.setMnemonic( 'C' );
 67:       
 68:       // create ConnectListener for connect buttons
 69:       ActionListener connectListener = new ConnectListener();
 70:       connectButton.addActionListener( connectListener );
 71:       connectMenuItem.addActionListener( connectListener ); 
 72:       
 73:       // create ImageIcon for disconnect buttons
 74:       Icon disconnectIcon = new ImageIcon( 
 75:          getClass().getResource( "images/Disconnect.gif" ) );
 76:       
 77:       // create disconnectButton and disconnectMenuItem
 78:       disconnectButton = new JButton( "Disconnect", disconnectIcon );
 79:       disconnectMenuItem = new JMenuItem( "Disconnect", disconnectIcon );      
 80:       disconnectMenuItem.setMnemonic( 'D' );
 81:       
 82:       // disable disconnect button and menu item
 83:       disconnectButton.setEnabled( false );
 84:       disconnectMenuItem.setEnabled( false );
 85:       
 86:       // create DisconnectListener for disconnect buttons
 87:       ActionListener disconnectListener = new DisconnectListener();
 88:       disconnectButton.addActionListener( disconnectListener );
 89:       disconnectMenuItem.addActionListener( disconnectListener );
 90:       
 91:       // add connect and disconnect JMenuItems to fileMenu
 92:       serverMenu.add( connectMenuItem );
 93:       serverMenu.add( disconnectMenuItem );           
 94:   
 95:       // add connect and disconnect JButtons to buttonPanel
 96:       JPanel buttonPanel = new JPanel();
 97:       buttonPanel.add( connectButton );
 98:       buttonPanel.add( disconnectButton );
 99:      
100:       messageArea = new JTextArea(); // displays messages
101:       messageArea.setEditable( false ); // disable editing
102:       messageArea.setWrapStyleWord( true ); // set wrap style to word
103:       messageArea.setLineWrap( true ); // enable line wrapping
104:       
105:       // put messageArea in JScrollPane to enable scrolling
106:       JPanel messagePanel = new JPanel();
107:       messagePanel.setLayout( new BorderLayout( 10, 10 ) );
108:       messagePanel.add( new JScrollPane( messageArea ), 
109:          BorderLayout.CENTER );
110:       
111:       inputArea = new JTextArea( 4, 20 ); // for entering new messages
112:       inputArea.setWrapStyleWord( true ); // set wrap style to word
113:       inputArea.setLineWrap( true ); // enable line wrapping
114:       inputArea.setEditable( false ); // disable editing
115:       
116:       // create Icon for sendButton
117:       Icon sendIcon = new ImageIcon( 
118:          getClass().getResource( "images/Send.gif" ) );
119:       
120:       sendButton = new JButton( "Send", sendIcon ); // create send button
121:       sendButton.setEnabled( false ); // disable send button
122:       sendButton.addActionListener(
123:          new ActionListener() 
124:          {
125:             // send new message when user activates sendButton
126:             public void actionPerformed( ActionEvent event )
127:             {
128:                messageManager.sendMessage( userName, 
129:                   inputArea.getText() ); // send message
130:                inputArea.setText( "" ); // clear inputArea
131:             } // end method actionPerformed
132:          } // end anonymous inner class
133:       ); // end call to addActionListener
134:       
135:       Box box = new Box( BoxLayout.X_AXIS ); // create new box for layout
136:       box.add( new JScrollPane( inputArea ) ); // add input area to box
137:       box.add( sendButton ); // add send button to box
138:       messagePanel.add( box, BorderLayout.SOUTH ); // add box to panel
139:       
140:       // create JLabel for statusBar with a recessed border
141:       statusBar = new JLabel( "Not Connected" );
142:       statusBar.setBorder( new BevelBorder( BevelBorder.LOWERED ) );
143: 
144:       add( buttonPanel, BorderLayout.NORTH ); // add button panel
145:       add( messagePanel, BorderLayout.CENTER ); // add message panel
146:       add( statusBar, BorderLayout.SOUTH ); // add status bar
147:       
148:       // add WindowListener to disconnect when user quits
149:       addWindowListener ( 
150:          new WindowAdapter () 
151:          {
152:             // disconnect from server and exit application
153:             public void windowClosing ( WindowEvent event ) 
154:             {
155:                messageManager.disconnect( messageListener );
156:                System.exit( 0 );
157:             } // end method windowClosing
158:          } // end anonymous inner class
159:       ); // end call to addWindowListener
160:    } // end ClientGUI constructor
161:    
162:    // ConnectListener listens for user requests to connect to server
163:    private class ConnectListener implements ActionListener 
164:    {
165:       // connect to server and enable/disable GUI components
166:       public void actionPerformed( ActionEvent event )
167:       {
168:          // connect to server and route messages to messageListener
169:          messageManager.connect( messageListener ); 
170: 
171:          // prompt for userName
172:          userName = JOptionPane.showInputDialog( 
173:             ClientGUI.this, "Enter user name:" );
174:          
175:          messageArea.setText( "" ); // clear messageArea
176:          connectButton.setEnabled( false ); // disable connect
177:          connectMenuItem.setEnabled( false ); // disable connect
178:          disconnectButton.setEnabled( true ); // enable disconnect
179:          disconnectMenuItem.setEnabled( true ); // enable disconnect
180:          sendButton.setEnabled( true ); // enable send button
181:          inputArea.setEditable( true ); // enable editing for input area
182:          inputArea.requestFocus(); // set focus to input area
183:          statusBar.setText( "Connected: " + userName ); // set text
184:       } // end method actionPerformed      
185:    } // end ConnectListener inner class
186:    
187:    // DisconnectListener listens for user requests to disconnect
188:    // from DeitelMessengerServer
189:    private class DisconnectListener implements ActionListener 
190:    {
191:       // disconnect from server and enable/disable GUI components
192:       public void actionPerformed( ActionEvent event )
193:       {
194:          // disconnect from server and stop routing messages
195:          messageManager.disconnect( messageListener );
196:          sendButton.setEnabled( false ); // disable send button
197:          disconnectButton.setEnabled( false ); // disable disconnect
198:          disconnectMenuItem.setEnabled( false ); // disable disconnect
199:          inputArea.setEditable( false ); // disable editing
200:          connectButton.setEnabled( true ); // enable connect
201:          connectMenuItem.setEnabled( true ); // enable connect
202:          statusBar.setText( "Not Connected" ); // set status bar text
203:       } // end method actionPerformed      
204:    } // end DisconnectListener inner class
205:    
206:    // MyMessageListener listens for new messages from MessageManager and 
207:    // displays messages in messageArea using MessageDisplayer.
208:    private class MyMessageListener implements MessageListener 
209:    {
210:       // when received, display new messages in messageArea
211:       public void messageReceived( String from, String message ) 
212:       {
213:          // append message using MessageDisplayer
214:          SwingUtilities.invokeLater( 
215:             new MessageDisplayer( from, message ) );
216:       } // end method messageReceived
217:    } // end MyMessageListener inner class
218:    
219:    // Displays new message by appending message to JTextArea.  Should
220:    // be executed only in Event thread; modifies live Swing component
221:    private class MessageDisplayer implements Runnable
222:    {
223:       private String fromUser; // user from which message came
224:       private String messageBody; // body of message
225:       
226:       // MessageDisplayer constructor
227:       public MessageDisplayer( String from, String body )
228:       {
229:          fromUser = from; // store originating user
230:          messageBody = body; // store message body
231:       } // end MessageDisplayer constructor
232:       
233:       // display new message in messageArea
234:       public void run() 
235:       {
236:          // append new message
237:          messageArea.append( "\n" + fromUser + "> " + messageBody );   
238:       } // end method run      
239:    } // end MessageDisplayer inner class
240: } // end class ClientGUI
241: 
242: 
243: /**************************************************************************
244:  * (C) Copyright 1992-2005 by Deitel & Associates, Inc. and               *
245:  * Pearson Education, Inc. All Rights Reserved.                           *
246:  *                                                                        *
247:  * DISCLAIMER: The authors and publisher of this book have used their     *
248:  * best efforts in preparing the book. These efforts include the          *
249:  * development, research, and testing of the theories and programs        *
250:  * to determine their effectiveness. The authors and publisher make       *
251:  * no warranty of any kind, expressed or implied, with regard to these    *
252:  * programs or to the documentation contained in these books. The authors *
253:  * and publisher shall not be liable in any event for incidental or       *
254:  * consequential damages in connection with, or arising out of, the       *
255:  * furnishing, performance, or use of these programs.                     *
256:  *************************************************************************/