package ca.janeg.calc;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Calculator extends JFrame {
private final Class ENGINE;
private final CalculatorEngine engine = new CalculatorEngine();
private final JTextField display = new JTextField();
public Calculator(){
setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
setTitle( "Calculator" );
display.setEditable( false );
display.setBackground( Color.WHITE );
ENGINE = engine.getClass();
buildGUI();
pack();
setResizable( false );
setLAF();
center( this );
setVisible( true );
}
private void buildGUI(){
Container cp = getContentPane();
cp.setLayout( new BoxLayout( cp, BoxLayout.Y_AXIS ) );
cp.add( display );
cp.add( buildControlPanel() );
cp.add( buildButtonPanels() );
}
private JPanel buildControlPanel(){
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add( Box.createHorizontalGlue() );
panel.add( new ControlButton( "Backspace", "backspace" ) );
panel.add( Box.createRigidArea( new Dimension( 2, 0 ) ) );
JPanel panel2 = new JPanel( new GridLayout( 1, 1, 2, 2 ) );
panel2.add( new ControlButton( "CE", "clearEntry" ) );
panel2.add( new ControlButton( "C", "clear" ) );
panel.add( panel2 );
return panel;
}
private JPanel buildButtonPanels() {
JPanel buttons = new JPanel();
buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
buttons.setFont(new Font("Courier", 10, Font.BOLD));
buttons.add( buildUnaryPanel() );
buttons.add( buildDigitPanel() );
buttons.add( buildFunctionPanel() );
return buttons;
}
private JPanel buildDigitPanel(){
JPanel panel = new JPanel();
panel.setLayout( new GridLayout( 4, 3, 2, 2 ) );
panel.add( new DigitButton( "7" ) );
panel.add( new DigitButton( "8" ) );
panel.add( new DigitButton( "9" ) );
panel.add( new DigitButton( "4" ) );
panel.add( new DigitButton( "5" ) );
panel.add( new DigitButton( "6" ) );
panel.add( new DigitButton( "1" ) );
panel.add( new DigitButton( "2" ) );
panel.add( new DigitButton( "3" ) );
panel.add( new DigitButton( "0" ) );
panel.add( new DigitButton( "." ) );
panel.add( new UnaryButton( " +/- ", "sign" ) );
return panel;
}
private JPanel buildFunctionPanel(){
JPanel buttons = new JPanel( new GridLayout( 4, 3, 2, 2 ) );
buttons.add( new FunctionButton( "/", "divide" ) );
buttons.add( new FunctionButton( "&", "and" ) );
buttons.add( new FunctionButton( "<<", "leftShift" ) );
buttons.add( new FunctionButton( "*", "multiply" ) );
buttons.add( new FunctionButton( "|", "divide" ) );
buttons.add( new FunctionButton( ">>", "rightShift" ) );
buttons.add( new FunctionButton( "-", "subtract" ) );
buttons.add( new FunctionButton( "^" , "xor" ) );
buttons.add( new FunctionButton( "pow" ) );
buttons.add( new FunctionButton( "+", "add" ) );
buttons.add( new FunctionButton( "=", "equals" ) );
buttons.add( new FunctionButton( "mod" ) );
return buttons;
}
private JPanel buildUnaryPanel(){
JPanel buttons = new JPanel( new GridLayout( 4, 3, 2, 2 ) );
buttons.add( new UnaryButton( "sin" ) );
buttons.add( new UnaryButton( "cos" ) );
buttons.add( new UnaryButton( "tan" ) );
buttons.add( new UnaryButton( "asin" ) );
buttons.add( new UnaryButton( "acos" ) );
buttons.add( new UnaryButton( "atan" ) );
buttons.add( new UnaryButton( "log" ) );
buttons.add( new UnaryButton( "deg", "degrees" ) );
buttons.add( new UnaryButton( "rad", "radians" ) );
buttons.add( new UnaryButton( "sqrt" ) );
buttons.add( new UnaryButton( "%", "percent" ) );
buttons.add( new UnaryButton( "1/x", "reciprocal" ) );
return buttons;
}
private void center( Window window ) {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = window.getSize().width;
int h = window.getSize().height;
int x = (dim.width - w) / 2;
int y = (dim.height - h) / 2;
window.setLocation(x, y);
}
private void setLAF() {
String nativeLF = UIManager.getSystemLookAndFeelClassName();
try {
UIManager.setLookAndFeel(nativeLF);
} catch (InstantiationException e) {
System.out.println( e.getMessage() );
} catch (ClassNotFoundException e) {
System.out.println( e.getMessage() );
} catch (UnsupportedLookAndFeelException e) {
System.out.println( e.getMessage() );
} catch (IllegalAccessException e) {
System.out.println( e.getMessage() );
}
}
private class CalcButton extends JButton implements ActionListener{
CalcButton( String s, String action ){
super( s );
setActionCommand( action );
setMargin( new Insets( 2, 2, 2, 2 ) );
setForeground( Color.WHITE );
addActionListener( this );
}
public void actionPerformed(ActionEvent e) {
String methodName = e.getActionCommand();
Method method = null;
try {
if ( e.getSource() instanceof DigitButton ) {
method =
ENGINE.getMethod("digit", new Class[] { int.class });
if (methodName.equals(".")) {
method.invoke(engine, new Object[] { new Integer( '.' )});
} else {
method.invoke(engine, new Object[] {
new Integer( methodName )});
}
} else {
method = ENGINE.getMethod(methodName, null);
method.invoke(engine, null);
}
} catch (NoSuchMethodException ex) {
System.out.println("No such method: " + methodName);
} catch (IllegalAccessException ea) {
System.out.println("Illegal access" + methodName);
} catch (InvocationTargetException et) {
System.out.println("Target exception: " + methodName);
}
display.setText(engine.display());
}
}
private class DigitButton extends CalcButton {
DigitButton( String s ){
super( s, s );
setForeground( Color.BLUE );
}
}
private class FunctionButton extends CalcButton {
FunctionButton( String s ){
this( s, s );
}
FunctionButton( String s, String action ){
super( s, action );
setBackground( Color.GRAY );
}
}
private class ControlButton extends CalcButton{
ControlButton( String s ){
this( s, s );
}
ControlButton( String s, String action ){
super( s, action );
setBackground( Color.RED );
}
}
private class UnaryButton extends CalcButton {
UnaryButton( String s ){
this( s, s );
}
UnaryButton( String s, String action ){
super( s, action );
setBackground( Color.BLUE );
}
}
public static void main(String[] args) {
new Calculator();
}
}