
import java.awt.* ;
import java.awt.event.* ;
import javax.swing.* ;

public class ReversePolish extends JFrame {

	private static int STACK_SIZE = 10 ;

	private JTextField field[] = new JTextField[ STACK_SIZE ] ;
	private JButton myAdd, mySub, myMul, myDiv, myPsh, myPop, myClr ;
	private JButton my1, my2, my3, my4, my5, my6, my7, my8, my9, my0, myD, myS ;
	private double x=0 ;

	public static void main( String args[] ) {
		ReversePolish app = new ReversePolish() ;
		app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE) ;
	}

	public ReversePolish() {
		super("Reverse Polish Calculator") ;

		//Create container and panels
		Container c = getContentPane() ;
		c.setLayout( new BorderLayout() ) ;

		JPanel topPanel = new JPanel() ;
		topPanel.setLayout( new GridLayout(STACK_SIZE,1) ) ;

		JPanel sidePanel = new JPanel() ;
		sidePanel.setLayout( new GridLayout(7,1) ) ;

		JPanel bottomPanel = new JPanel() ;
		bottomPanel.setLayout( new GridLayout(4,3) ) ;

		//Create+add top JObjects
		for ( int i = 0 ; i < field.length ; i++ ) {
			field[i] = new JTextField("0.0") ;
			field[i].setHorizontalAlignment( JTextField.RIGHT ) ;
			topPanel.add( field[i] ) ;
		}
		field[0].setText("") ;

		//Create+add side JObjects
		myAdd = new JButton("ADD") ;
		mySub = new JButton("SUB") ;
		myMul = new JButton("MUL") ;
		myDiv = new JButton("DIV") ;
		myPsh = new JButton("PUSH") ;
		myPop = new JButton("POP") ;
		myClr = new JButton("CLEAR") ;

		sidePanel.add( myAdd ) ;
		sidePanel.add( mySub ) ;
		sidePanel.add( myMul ) ;
		sidePanel.add( myDiv ) ;
		sidePanel.add( myPsh ) ;
		sidePanel.add( myPop ) ;
		sidePanel.add( myClr ) ;


		//Create+add bottom JObjects
		my1 = new JButton("1") ;
		my2 = new JButton("2") ;
		my3 = new JButton("3") ;
		my4 = new JButton("4") ;
		my5 = new JButton("5") ;
		my6 = new JButton("6") ;
		my7 = new JButton("7") ;
		my8 = new JButton("8") ;
		my9 = new JButton("9") ;
		my0 = new JButton("0") ;
		myD = new JButton(".") ;
		myS = new JButton("+/-") ;

		bottomPanel.add(my1) ;
		bottomPanel.add(my2) ;
		bottomPanel.add(my3) ;
		bottomPanel.add(my4) ;
		bottomPanel.add(my5) ;
		bottomPanel.add(my6) ;
		bottomPanel.add(my7) ;
		bottomPanel.add(my8) ;
		bottomPanel.add(my9) ;
		bottomPanel.add(my0) ;
		bottomPanel.add(myD) ;
		bottomPanel.add(myS) ;

		c.add( topPanel, BorderLayout.CENTER ) ;
		c.add( sidePanel, BorderLayout.EAST ) ;
		c.add( bottomPanel, BorderLayout.SOUTH ) ;

		//Add actions to JObjects
		HandleDigits h1 = new HandleDigits() ;
		my1.addActionListener(h1) ;
		my2.addActionListener(h1) ;
		my3.addActionListener(h1) ;
		my4.addActionListener(h1) ;
		my5.addActionListener(h1) ;
		my6.addActionListener(h1) ;
		my7.addActionListener(h1) ;
		my8.addActionListener(h1) ;
		my9.addActionListener(h1) ;
		my0.addActionListener(h1) ;
		myD.addActionListener(h1) ;
		myS.addActionListener(h1) ;


		HandleOperations h2 = new HandleOperations() ;
		myAdd.addActionListener(h2) ;
		mySub.addActionListener(h2) ;
		myMul.addActionListener(h2) ;
		myDiv.addActionListener(h2) ;
		myPsh.addActionListener(h2) ;
		myPop.addActionListener(h2) ;
		myClr.addActionListener(h2) ;

		setSize(300,400) ;
		setVisible(true) ;
	}



	private class HandleDigits implements ActionListener {
		public void actionPerformed( ActionEvent e ) {

			if ( e.getSource() == myS ) {

				String z = field[0].getText() ;
				int p = z.indexOf("-") ;
				if ( p < 0 ) {
					z = "-" + z ;
				} else {
					z = z.substring(p+1) ;
				}
				field[0].setText(z) ;

			} else {

				String x = "" ;
				String z = field[0].getText() ;

				     if ( e.getSource() == my1 ) { x = "1" ; } 
				else if ( e.getSource() == my2 ) { x = "2" ; }
				else if ( e.getSource() == my3 ) { x = "3" ; }
				else if ( e.getSource() == my4 ) { x = "4" ; }
				else if ( e.getSource() == my5 ) { x = "5" ; }
				else if ( e.getSource() == my6 ) { x = "6" ; }
				else if ( e.getSource() == my7 ) { x = "7" ; }
				else if ( e.getSource() == my8 ) { x = "8" ; }
				else if ( e.getSource() == my9 ) { x = "9" ; }
				else if ( e.getSource() == my0 ) { x = "0" ; }
				else if ( e.getSource() == myD ) { 
					int p = z.indexOf(".") ;
					if ( p < 0 ) {
						x = "." ;
					} else {
						x = "" ;
					}
				}

				field[0].setText( z + x ) ;
			}

		} //actionPerformed

	} //HandleDigits



	private class HandleOperations implements ActionListener {
		public void actionPerformed( ActionEvent e ) {

			if ( e.getSource() == myClr ) {

				field[0].setText("") ;

			} else if ( e.getSource() == myPsh ) {

				//Test for a well formatted double in field[0] before doing the push
				//Reformat the string as a double by parsing it and converting it back to a String
				try {
					Double.parseDouble( field[0].getText() ) ;                         //Test first
					for ( int i = field.length-2 ; i >= 0 ; i-- ) {
						String z = "" + Double.parseDouble( field[i].getText() ) ; //Reformatting
						field[i+1].setText(z) ;
					}
					field[0].setText("") ;
				}
				catch ( NumberFormatException ex ) {
					JOptionPane.showMessageDialog( null, "Poorly formatted double" ) ;
				}

			} else if ( e.getSource() == myPop ) {

				for ( int i = 0 ; i < field.length-1 ; i++ )
					field[i].setText( field[i+1].getText() ) ;
				field[ field.length-1 ].setText("0.0") ;

			} else {

				//Test for well formatted doubles in field[0] and [1] before doing math + popping
				try {
					double y = Double.parseDouble( field[0].getText() ) ;
					double x = Double.parseDouble( field[1].getText() ) ;
					String z = "" ;
					if ( e.getSource() == myAdd ) z += x+y ;
					if ( e.getSource() == mySub ) z += y-x ;
					if ( e.getSource() == myMul ) z += x*y ;
					if ( e.getSource() == myDiv ) z += y/x ;

					for ( int i = 0 ; i < field.length-1 ; i++ )
						field[i].setText( field[i+1].getText() ) ;
					field[ field.length-1 ].setText("0.0") ;
					field[0].setText(z) ;
				}
				catch ( NumberFormatException ex ) {
					JOptionPane.showMessageDialog( null, "Poorly formatted double" ) ;
				}

			} 


		}  //actionPerformed

	} //HandleOperations

}


