1   // joi/10/juno/GUILoginConsole.java                         
2   //                                                            
3   //                                                            
4   // Copyright 2003 Bill Campbell and Ethan Bolker                         
5                                                               
6   import javax.swing.*;
7   import javax.swing.event.*;
8   import java.awt.*;
9   import java.awt.event.*;
10  
11  /**
12   *  The graphical user interface to Juno.
13   */
14  
15  public class GUILoginConsole extends JFrame
16      implements OutputInterface
17  {
18      private static final int FIELDWIDTH = 30;
19      private static final int FIELDHEIGHT = 5;
20  
21      private final Juno junoSystem;
22      private WindowCloser closeMe; // to shut down Juno
23  
24      private String title;  // title for the windows
25  
26      // The interpreter interprets one-line commands.
27      private InterpreterInterface interpreter; 
28      private boolean echoInput;
29  
30      // All output goes to messages.
31      private JTextArea messages;
32  
33      /**
34       *  Construct a GUI console for Juno.
35       *
36       *  @param title the title for this window.
37       *  @param junoSystem the Juno system for which this is a GUI
38       *  @param interpreter the object to which to send user input.
39       *  @param echoInput true when input echoes to this console.
40       */
41  
42      public GUILoginConsole( String title, Juno junoSystem,
43                              InterpreterInterface interpreter,
44                              boolean echoInput) 
45      { 
46          super( title );
47          this.title       = title;
48          this.junoSystem  = junoSystem;
49          this.interpreter = interpreter;
50          this.echoInput   = echoInput;
51          this.closeMe = new WindowCloser( junoSystem );
52  
53          // Set up the look and feel;
54          // Everthing is placed on a panel (using BorderLayout)
55  
56          JPanel panel = new JPanel();
57          panel.setLayout( new BorderLayout() );
58  
59          // First a tabbed pane, with two tabs:
60          //   one for login, one for registration
61  
62          JTabbedPane tabs = new JTabbedPane();
63          tabs.addTab( "Login" , null, 
64                       new LoginPane( interpreter, echoInput, closeMe ) );
65          tabs.addTab( "Register", null,
66                       new RegisterPane( interpreter, echoInput ) );
67          tabs.setSelectedIndex( 0 );  // Login selected by default
68          panel.add( tabs, BorderLayout.NORTH );
69  
70          // and the output messages area.
71          panel.add( new JLabel( "Messages:" ), BorderLayout.CENTER );
72          messages = new JTextArea( FIELDHEIGHT, FIELDWIDTH );
73          panel.add( messages, BorderLayout.SOUTH );
74  
75          // Add the panel to this JFrame
76          this.getContentPane().add( panel );
77  
78          // Closing this window
79          this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
80          this.addWindowListener( closeMe );
81  
82          // Size and display this JFrame
83          pack();
84          show();
85      }
86  
87      // Implementing the OutputInterface. Everything goes to the
88      // single message area.
89  
90      /**
91       * Write a String followed by a newline
92       * to message area.
93       *
94       * @param str - the string to write
95       */
96  
97      public void println(String str ) 
98      {
99          messages.append( str + "\n" );
100     }
101     
102     /**
103      * Write a String followed by a newline
104      * to message area.
105      *
106      * @param str - the String to write
107      */
108 
109     public void errPrintln(String str ) 
110     {
111         println( str );
112     }
113 
114     /**
115      * Query what kind of console this is.
116      *
117      * @return true if and only if echoing input.
118      */
119 
120     public boolean isEchoInput() 
121     {
122         return echoInput;
123     }
124 
125     /**
126      * Query what kind of console this is.
127      *
128      * @return true if and only if GUI
129      */
130 
131     public boolean isGUI() 
132     {
133         return true;
134     }
135 
136     /**
137      * Query what kind of console this is.
138      *
139      * @return true if and only if remote
140      */
141 
142     public boolean isRemote() 
143     {
144         return false;
145     }
146         
147     // The Login pane is specified in a private inner class,
148     // visible only here.
149 
150     private class  LoginPane extends JPanel
151     {
152         // The login pane has two text fields and two buttons.
153         private JTextField nameField; 
154         private JTextField passwordField;
155         
156         private JButton ok;
157         private JButton exit;
158 
159         private WindowCloser closeMe; // to shut down Juno
160         // Construct the login pane and set up its listeners.
161 
162         public LoginPane( InterpreterInterface interpreter,
163                           boolean echoInput, WindowCloser closeMe ) 
164         { 
165             super();
166             this.closeMe = closeMe;
167 
168             // Set up the look and feel.
169             // Everything will go into a vertical Box, a container
170             // whose contents are laid out using BoxLayout
171 
172             Box box = Box.createVerticalBox();
173 
174             // First a panel, containing the two text fields
175 
176             JPanel p  = new JPanel();
177             p.setLayout( new GridLayout( 4 , 1 ) );
178 
179             p.add( new JLabel( "Login:" ) );
180             nameField = new JTextField( FIELDWIDTH );
181             p.add( nameField );
182 
183             p.add( new JLabel( "Password:" ) );
184             passwordField = new JPasswordField( FIELDWIDTH );
185             p.add( passwordField );
186             box.add( p );
187             box.add( Box.createVerticalStrut( 15 ) );
188 
189             // Then a horizontal Box containing the two buttons
190 
191             Box row = Box.createHorizontalBox();
192             row.add( Box.createGlue() );
193             
194             ok = new JButton( "OK" );
195             row.add( ok );
196             row.add( Box.createGlue() );
197 
198             exit = new JButton( "Exit" );
199             row.add( exit );
200             row.add( Box.createGlue() );
201             box.add( row );
202             box.add( Box.createVerticalStrut( 15 ) );
203 
204             this.setLayout( new BorderLayout() );
205             this.add( box, BorderLayout.CENTER );
206 
207             // Set up the listeners (the semantics)
208 
209             ok.addActionListener( new LoginProcessor() );
210             exit.addActionListener( closeMe ); // shuts down Juno
211         }
212 
213         // An inner inner class for the semantics 
214         // when the user clicks OK.
215 
216         private class LoginProcessor implements ActionListener 
217         {
218             public void actionPerformed(ActionEvent e) 
219             {
220                 String str = nameField.getText() +  " " +
221                     passwordField.getText();
222                 nameField.setText("");
223                 passwordField.setText("");
224                 messages.setText(str+'\n');  // for debugging
225                 interpreter.interpret( str );
226             }
227         }
228     }
229 
230     // The Register pane is specified in a private inner class,
231     // visible only here.
232 
233     private class  RegisterPane extends JPanel
234     {
235         // The register pane has four textfields and two buttons.
236         private JTextField chosenName;
237         private JTextField fullName;
238         private JTextField password1;
239         private JTextField password2;
240         
241         private JButton register;
242         private JButton clear;
243 
244         public RegisterPane( InterpreterInterface interpreter,
245                              boolean echoInput) 
246         { 
247             super();
248 
249             // Define the look and feel
250             // Everything goes into a vertical Box
251             Box box = Box.createVerticalBox();
252 
253             // First a panel containing the text fields
254 
255             JPanel p  = new JPanel();
256             p.setLayout( new GridLayout( 0 , 1 ) );
257             
258             p.add( new JLabel( "Choose login name:" ) );
259             chosenName = new JTextField( FIELDWIDTH );
260             p.add( chosenName );
261             
262             p.add( new JLabel( "Give full name:" ) );
263             fullName = new JTextField( FIELDWIDTH );
264             p.add( fullName );
265             
266             p.add( new JLabel( "Choose password:" ) );
267             password1  = new JPasswordField( FIELDWIDTH );
268             p.add( password1 );
269             
270             p.add( new JLabel( "Retype password:" ) );
271             password2  = new JPasswordField( FIELDWIDTH );
272             p.add( password2 );
273 
274             box.add( p );
275             box.add( Box.createVerticalStrut( 15 ) );
276 
277             // Then a horizontal Box containing the buttons
278             
279             Box row = Box.createHorizontalBox();
280             row.add( Box.createGlue() );
281             register = new JButton( "Register" );
282             row.add( register );
283             row.add( Box.createGlue() );
284             clear = new JButton( "Clear" );
285             row.add( clear );
286             row.add( Box.createGlue() );
287             box.add( row );
288             box.add( Box.createVerticalStrut( 15 ) );
289             
290             this.setLayout( new BorderLayout() );
291             this.add( box, BorderLayout.CENTER );
292 
293             // Set up the listeners (the semantics)
294 
295             register.addActionListener( new Registration() );
296             clear.addActionListener( new Cleanser() );
297         }
298 
299         // An inner inner class for the semantics when the user 
300         // clicks Register.
301 
302         private class Registration implements ActionListener 
303         {
304             public void actionPerformed(ActionEvent e) 
305             {
306                 if ( password1.getText().trim().equals(
307                      password2.getText().trim() ) ) {
308                     String str = "register " +
309                         chosenName.getText() +  " " +
310                         password1.getText() + " " +
311                         fullName.getText() ;
312                     chosenName.setText("");
313                     fullName.setText("");
314                     messages.setText(str+'\n');  // for debugging
315                     interpreter.interpret(str);
316                 }
317                 else {
318                     messages.setText( 
319                         "Sorry, passwords don't match.\n" );
320                 }
321                 password1.setText("");
322                 password2.setText("");
323             }
324         }
325 
326         // An inner inner class for the semantics when the user 
327         // clicks Clear.
328 
329         private class Cleanser implements ActionListener {
330             public void actionPerformed(ActionEvent e) {
331                 chosenName.setText("");
332                 fullName.setText("");
333                 password1.setText("");
334                 password2.setText("");
335             }
336         }
337     }
338 
339     //  A WindowCloser instance handles close events generated 
340     //  by the underlying window system with its windowClosing
341     //  method, and close events from buttons or other user
342     //  components with its actionPerformed method.
343     //
344     //  The action is to shut down Juno.
345 
346     private static class WindowCloser extends WindowAdapter
347         implements ActionListener  
348     {
349         Juno system;
350 
351         public WindowCloser( Juno system ) 
352         {
353             this.system = system;
354         }
355 
356         public void windowClosing (WindowEvent e) 
357         {
358             this.actionPerformed( null ); 
359         }
360 
361         public void actionPerformed(ActionEvent e) 
362         {
363             if (system != null) {
364                 system.shutDown();
365             }
366             System.exit(0);
367         }
368     }
369 
370     /**
371      * main() in GUILoginConsole class for 
372      * unit testing during development.
373      */  
374 
375     public static void main( String[] args ) 
376     {
377         new GUILoginConsole( "GUItest", null, null, true ).show();
378     }
379 }
380 
381