001 /* 002 * Calculator GUI 003 * 004 * Developed for "Rethinking CS101", a project of Lynn Andrea Stein's AP Group. 005 * For more information, see <a href="http://www.ai.mit.edu/projects/cs101/">the 006 * CS101 homepage</a> or email <las@ai.mit.edu>. 007 * 008 * Copyright (C) 1996 Massachusetts Institute of Technology. 009 * Please do not redistribute without obtaining permission. 010 */ 011 package calculator; 012 013 import java.awt.*; 014 import java.awt.event.*; 015 import cs101.util.semaphore.IntBuffer; 016 017 /** 018 * This is an implementation of the GUI for a basic four-function 019 * calculator. It relies on a ButtonHandler (Runnable) to repeatedly 020 * call getButton() and consume the buttonIDs that the Calculator 021 * object produces. 022 * 023 * <P>This follows the interactive-control-loop design described in the 024 * early parts of 6.096 and as a part of the 025 * <a href="http://www.ai.mit.edu/projects/cs101/"> 026 * Rethinking CS101 027 * </a> project of Lynn Andrea Stein's AP Group at the MIT 028 * Artificial Intelligence Laboratory. 029 * 030 * <P>Copyright (c) 1998 Massachusetts Institute of Technology 031 * 032 * @author: Todd C. Parnell, tparnell@ai.mit.edu 033 * @author: Emil Sit, sit@mit.edu 034 * @author: Lynn Andrea Stein, las@ai.mit.edu 035 * @version: $Id: CalculatorGUI.java,v 1.1.1.1 2002/06/05 21:56:34 root Exp $ 036 * 037 * @see calculator.ButtonHandler 038 * @see cs101.util.semaphore.IntBuffer 039 * 040 */ 041 042 public class CalculatorGUI extends Frame implements Calculator { 043 044 /** 045 * The "screen" of the calculator. Private -- do not use. 046 */ 047 private TextField display; 048 049 /** 050 * Synchronized storage for put/getButton. Private -- do not use. 051 * Note: currently package visible becuase buttonBuf is used by an 052 * inner class. This is a workaround for a bug in the JDK. (6 July 98) 053 */ 054 /* private */ IntBuffer buttonBuf = new IntBuffer(); 055 056 /** 057 * The Button components themselves. Private -- do not use. 058 */ 059 private Button[] Buttons = new Button[Calculator.LAST]; 060 061 // Set up the labels w/ static initializer (only need to do this once). 062 static { 063 for ( int i = 0; i < 10; i++ ) { 064 ButtonLabels[i] = String.valueOf( i ); 065 } 066 ButtonLabels[Calculator.OP_DIV] = "/"; 067 ButtonLabels[Calculator.OP_MUL] = "*"; 068 ButtonLabels[Calculator.OP_ADD] = "+"; 069 ButtonLabels[Calculator.OP_SUB] = "-"; 070 ButtonLabels[Calculator.DOT] = "."; 071 ButtonLabels[Calculator.EQUALS] = "="; 072 ButtonLabels[Calculator.CLEAR] = "clear"; 073 } 074 075 /** 076 * Initialize components and such at runtime. Automagically called 077 * by the java runtime. You should not use it. 078 */ 079 public CalculatorGUI() { 080 super("CS101 Calculator"); 081 082 this.setLayout( new GridLayout( 0, 1 ) ); 083 084 this.display = new TextField(""); 085 this.display.setEditable( false ); 086 this.display.setBackground( Color.white ); 087 this.display.setForeground( Color.blue ); 088 this.display.setFont( new Font("Monospaced", Font.BOLD, 24) ); 089 this.display.setCursor( new Cursor(Cursor.HAND_CURSOR) ); 090 091 this.add( this.display ); 092 093 for ( int i = 0; i < Calculator.LAST; i++ ) { 094 this.Buttons[i] = new Button( Calculator.ButtonLabels[i] ); 095 // Add the ActionListener for this button 096 this.Buttons[i].addActionListener(new ActionListener() { 097 public void actionPerformed(ActionEvent e) { 098 // Find out what button was pressed. We cannot (unfortunately) 099 // simply use "i" here, so we do it the hard way. 100 String label = ((Button)e.getSource()).getLabel(); 101 for ( int k = 0; k < Calculator.LAST; k++ ) { 102 if (Calculator.ButtonLabels[k].equals(label)) { 103 CalculatorGUI.this.buttonBuf.putButton( k ); 104 break; // only one match is possible 105 } 106 } 107 } 108 }); 109 } 110 // Layout the keypad one row at a time. 111 Panel numberPad = new Panel(); 112 numberPad.setBackground( Color.lightGray ); 113 numberPad.setForeground( Color.black ); 114 numberPad.setFont( new Font("Monospaced", Font.BOLD, 20) ); 115 numberPad.setCursor( new Cursor(Cursor.HAND_CURSOR) ); 116 117 numberPad.setLayout( new GridLayout( 0, 4, 1, 1 ) ); 118 numberPad.add( this.Buttons[7] ); // Row 1 119 numberPad.add( this.Buttons[8] ); 120 numberPad.add( this.Buttons[9] ); 121 numberPad.add( this.Buttons[Calculator.OP_DIV] ); 122 numberPad.add( this.Buttons[4] ); // Row 2 123 numberPad.add( this.Buttons[5] ); 124 numberPad.add( this.Buttons[6] ); 125 numberPad.add( this.Buttons[Calculator.OP_MUL] ); 126 numberPad.add( this.Buttons[1] ); // Row 3 127 numberPad.add( this.Buttons[2] ); 128 numberPad.add( this.Buttons[3] ); 129 numberPad.add( this.Buttons[Calculator.OP_ADD] ); 130 numberPad.add( this.Buttons[0] ); // Row 4 131 numberPad.add( this.Buttons[Calculator.DOT] ); 132 numberPad.add( this.Buttons[Calculator.EQUALS] ); 133 numberPad.add( this.Buttons[Calculator.OP_SUB] ); 134 numberPad.add( new Button("") ); // Row 5 135 numberPad.add( new Button("") ); 136 numberPad.add( new Button("") ); 137 numberPad.add( this.Buttons[Calculator.CLEAR] ); // --BIG button 138 this.add( numberPad ); 139 140 this.pack(); // Set the window size, 141 this.show(); // pop it up, 142 this.validate(); // 143 this.setResizable(false); // 144 145 146 this.addWindowListener( new WindowAdapter() { 147 public void windowClosing( WindowEvent e) { 148 System.out.println("Exiting..."); 149 CalculatorGUI.this.dispose(); 150 System.exit(0); 151 } 152 }); 153 154 } 155 156 /** 157 * Get the next Button pressed. The return value will be an int 158 * between 0 and 9 (if the button was a number) or one of the 159 * Calculator constants. 160 * 161 * @return the next button to be handled. 162 */ 163 public int getButton() { 164 return this.buttonBuf.getButton(); 165 } 166 167 /** 168 * Get the label for the given Button ID. The argument 169 * should be an int between 0 and 9 (if the button was 170 * a number) or one of the Calculator constants, 171 * otherwise the empty string ("") will be returned. 172 * 173 * @return the button label as a String. 174 */ 175 public String getButtonLabel(int buttonID) { 176 if ((buttonID < 0) || (buttonID > Calculator.LAST)) { 177 return ""; 178 } else { 179 return ButtonLabels[buttonID]; 180 } 181 } 182 183 /** 184 * Get the text currently displayed on the Calculator. 185 * 186 * @return the text as a String. 187 */ 188 public String getText() { 189 return this.display.getText(); 190 } 191 192 193 /** 194 * Set the text currently displayed on the Calculator. 195 * 196 * @param newText the text to be displayed. 197 */ 198 public void setText( String newText ) { 199 this.display.setText( newText ); 200 } 201 } 202 203 /* Comments: 204 * 205 * History: 206 * $Log: CalculatorGUI.java,v $ 207 * Revision 1.1.1.1 2002/06/05 21:56:34 root 208 * CS101 comes to Olin finally. 209 * 210 * Revision 1.3 2000/05/01 06:25:19 mharder 211 * Changed javadoc to agree with new cs101 packages. 212 * 213 * Revision 1.2 2000/04/25 17:45:34 nathanw 214 * Adapt to new cs101.* layout 215 * 216 * Revision 1.1 1999/10/08 15:09:24 las 217 * This pset replaces the old Calculator pset. However, not everything 218 * has been transferred. At the moment, it's just java, doc, and index. 219 * The rest are still in the repository under Calculator-Old. 220 * 221 * Revision 1.6 1998/07/24 16:37:14 tparnell 222 * Placate new javadoc behavior 223 * 224 * Revision 1.5 1998/07/21 14:58:44 tparnell 225 * javadoc fix 226 * 227 * Revision 1.4 1998/07/07 14:22:00 tparnell 228 * changed refrences to Frame.HAND_CURSOR to Cursor.HAND_CURSOR 229 * 230 * Revision 1.3 1998/07/06 20:08:32 tparnell 231 * removed some JDK1.0 code still present in file. minor redesign of event 232 * handling. CalculatorGUI used to implement ActionListener and handled 233 * events from the various buttons. Now that work is done by an anonymous 234 * inner class. 235 * 236 * Revision 1.2 1998/06/05 05:19:29 craigh 237 * added getButtonLabel() to Calculator interface. Implemented the 238 * method in CalculatorGUI, and made use of it in ButtonHandler. 239 * 240 * Revision 1.1 1998/02/26 17:25:45 tparnell 241 * Reconstruction from hard drive failure. Everything appears intact. 242 * 243 * Revision 1.3 1997/10/05 21:11:20 shong 244 * Updated for fall97, to Java 1.1 245 * changed GUI, using 1.1 Event Model 246 * 247 * Revision 1.2 1997/07/16 14:15:21 tparnell 248 * *** empty log message *** 249 * 250 * Revision 1.2 1996/10/04 19:02:26 las 251 * Fixed the location of the clear button so that it's not quite so 252 * grotesque. (I suppose that the right answer is a GridBagLayout....) 253 * 254 * Revision 1.1 1996/10/04 16:20:21 las 255 * Transformed Calculator into an application and made it a package. See 256 * STAFF_SETUP for which files are public. To run, use Calculator.Main. 257 * 258 * Specifics: 259 * Added Main.java, which starts the calculator program (both 260 * CalculatorGUI and ButtonHandler); 261 * Made Calculator an interface; 262 * Moved GUI implementation (previously in Calculator) to 263 * CalculatorGUI. 264 * Added clear button, which looks pretty gross right now. (It can 265 * be deleted in a single line, though.) 266 * 267 * Revision 1.1.1.1 1996/07/18 17:26:12 sit 268 * Import from summer 6.80s web tree 269 * 270 * 271 */ 272