1  import java.awt.BorderLayout;
  2  import java.awt.GridLayout;
  3  import java.awt.event.ActionListener;
  4  import java.awt.event.ActionEvent;
  5  import javax.swing.ButtonGroup;
  6  import javax.swing.JButton;
  7  import javax.swing.JCheckBox;
  8  import javax.swing.JComboBox;
  9  import javax.swing.JFrame;
 10  import javax.swing.JPanel;
 11  import javax.swing.JRadioButton;
 12  import javax.swing.JLabel;
 13  import javax.swing.border.EtchedBorder;
 14  import javax.swing.border.TitledBorder;
 15  
 16  /**
 17     This frame contains a panel that displays buttons
 18     for a calculator and a panel with a text fields to
 19     specify the result of calculation.
 20  */
 21  public class CalculatorFrame extends JFrame
 22  {  
 23     private JLabel display;
 24     private JCheckBox radianCheckBox;
 25     private JRadioButton baseeButton;
 26     private JRadioButton base10Button;
 27     private JRadioButton base2Button;
 28     private JComboBox mathOpCombo;
 29     private JButton mathOpButton;
 30  
 31     private double lastValue;
 32     private String lastOperator;
 33     private boolean startNewValue;   
 34  
 35     private static final int FRAME_WIDTH = 400;
 36     private static final int FRAME_HEIGHT = 300;
 37  
 38     public CalculatorFrame()
 39     {
 40        createButtonPanel();
 41        createControlPanel();
 42  
 43        display = new JLabel("0");
 44        add(display, BorderLayout.NORTH);
 45  
 46        lastValue = 0;
 47        lastOperator = "=";
 48        startNewValue = true;
 49  
 50        setSize(FRAME_WIDTH, FRAME_HEIGHT);
 51     }
 52        
 53     /**
 54        Creates the control panel with the text field 
 55        and buttons on the frame.
 56     */
 57     private void createButtonPanel()
 58     {      
 59        JPanel buttonPanel = new JPanel();
 60        buttonPanel.setLayout(new GridLayout(4, 4));
 61  
 62        buttonPanel.add(makeDigitButton("7"));
 63        buttonPanel.add(makeDigitButton("8"));
 64        buttonPanel.add(makeDigitButton("9"));
 65        buttonPanel.add(makeOperatorButton("/"));
 66        buttonPanel.add(makeDigitButton("4"));
 67        buttonPanel.add(makeDigitButton("5"));
 68        buttonPanel.add(makeDigitButton("6"));
 69        buttonPanel.add(makeOperatorButton("*"));
 70        buttonPanel.add(makeDigitButton("1"));
 71        buttonPanel.add(makeDigitButton("2"));
 72        buttonPanel.add(makeDigitButton("3"));
 73        buttonPanel.add(makeOperatorButton("-"));
 74        buttonPanel.add(makeDigitButton("0"));
 75        buttonPanel.add(makeDigitButton("."));
 76        buttonPanel.add(makeOperatorButton("="));
 77        buttonPanel.add(makeOperatorButton("+"));
 78  
 79        add(buttonPanel, BorderLayout.CENTER);
 80     }
 81  
 82     class MathOpListener implements ActionListener
 83     {
 84        public void actionPerformed(ActionEvent event)
 85        {  
 86           double value = Double.parseDouble(display.getText());
 87           String mathOp = (String) mathOpCombo.getSelectedItem();
 88  
 89           double base = 10;
 90           if (baseeButton.isSelected()) { base = Math.E; }
 91           else if (base2Button.isSelected()) { base = 2; }
 92  
 93           boolean radian = radianCheckBox.isSelected();
 94           if (!radian && (mathOp.equals("sin") 
 95                 || mathOp.equals("cos") || mathOp.equals("tan")))
 96           {
 97              value = Math.toRadians(value);
 98           }
 99  
100           if (mathOp.equals("sin"))
101           {
102              value = Math.sin(value);
103           }
104           else if (mathOp.equals("cos"))
105           {
106              value = Math.cos(value);
107           }
108           else if (mathOp.equals("tan"))
109           {
110              value = Math.tan(value);
111           }
112           else if (mathOp.equals("log"))
113           {
114              value = Math.log(value) / Math.log(base);
115           }
116           else if (mathOp.equals("exp"))
117           {
118              value = Math.pow(base, value);
119           }
120           display.setText("" + value);
121  
122           startNewValue = true;         
123        }
124     }
125  
126     private JPanel createBaseButtons()
127     {
128        baseeButton = new JRadioButton("e");
129        base10Button = new JRadioButton("10");
130        base2Button = new JRadioButton("2");
131  
132        baseeButton.setSelected(true);
133  
134        ButtonGroup group = new ButtonGroup();
135        group.add(baseeButton);
136        group.add(base10Button);
137        group.add(base2Button);
138  
139        JPanel basePanel = new JPanel();
140        basePanel.add(baseeButton);
141        basePanel.add(base10Button);
142        basePanel.add(base2Button);
143        basePanel.setBorder(new TitledBorder(new EtchedBorder(), "Base"));
144        
145        return basePanel;
146     }
147  
148     private void createControlPanel()
149     {
150        radianCheckBox = new JCheckBox("Radian");
151        radianCheckBox.setSelected(true);
152  
153        mathOpCombo = new JComboBox();
154        mathOpCombo.addItem("sin");
155        mathOpCombo.addItem("cos");
156        mathOpCombo.addItem("tan");
157        mathOpCombo.addItem("log");
158        mathOpCombo.addItem("exp");
159  
160        mathOpButton = new JButton("Apply");
161        mathOpButton.addActionListener(new MathOpListener());
162  
163        JPanel controlPanel = new JPanel();
164        controlPanel.add(radianCheckBox);
165        controlPanel.add(createBaseButtons());
166        controlPanel.add(mathOpCombo);
167        controlPanel.add(mathOpButton);
168  
169        add(controlPanel, BorderLayout.SOUTH);
170     }
171  
172     /**
173        Combines two values with an operator.
174        @param value1 the first value
175        @param value2 the second value
176        @param op an operator (+, -, *, /, or =)
177     */
178     public double calculate(double value1, double value2, String op)
179     {  
180        if (op.equals("+")) 
181        {
182           return value1 + value2;
183        }
184        else if (op.equals("-")) 
185        {
186           return value1 - value2;
187        }
188        else if (op.equals("*")) 
189        {
190           return value1 * value2;
191        }
192        else if (op.equals("/")) 
193        {
194           return value1 / value2;
195        }
196        else // "="
197        {
198           return value2;
199        }
200     }
201     
202     class DigitButtonListener implements ActionListener
203     {
204        private String digit;
205        
206        /**
207           Constructs a listener whose actionPerformed method adds a digit
208           to the display.
209           @param aDigit the digit to add
210        */
211        public DigitButtonListener(String aDigit)
212        {
213           digit = aDigit;
214        }
215        
216        public void actionPerformed(ActionEvent event)
217        {  
218           if (startNewValue) 
219           {
220              display.setText("");
221              startNewValue = false;
222           }
223           display.setText(display.getText() + digit);
224        }        
225     }
226  
227     /**
228        Makes a button representing a digit of a calculator.
229        @param digit the digit of the calculator
230        @return the button of the calculator
231     */
232     public JButton makeDigitButton(String digit)
233     {
234        JButton button = new JButton(digit);      
235        ActionListener listener = new DigitButtonListener(digit);
236        button.addActionListener(listener);  
237        return button;    
238     } 
239  
240     class OperatorButtonListener implements ActionListener
241     {
242        private String operator;
243  
244        /**
245           Constructs a listener whose actionPerformed method
246           schedules an operator for execution.
247        */      
248        public OperatorButtonListener(String anOperator)
249        {
250           operator = anOperator;
251        }
252  
253        public void actionPerformed(ActionEvent event)
254        {  
255           if (!startNewValue)
256           {  
257              double value = Double.parseDouble(display.getText());
258              lastValue = calculate(lastValue, value, lastOperator);
259              display.setText("" + lastValue);
260              startNewValue = true;
261           }
262              
263           lastOperator = operator;
264        }       
265     }
266  
267     /**
268        Makes a button representing an operator of a calculator.
269        @param op the operator of the calculator
270        @return the button of the calculator
271     */
272     public JButton makeOperatorButton(String op)
273     {
274        JButton button = new JButton(op);      
275        ActionListener listener = new OperatorButtonListener(op);
276        button.addActionListener(listener);  
277        return button;    
278     }     
279  }