import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics.*;
/**
 * Applet to find the nth row of Pascal's Triangle
 * Creation date: (01/27/2002 9:48:20 PM)
 * Modified date: (04/15/2002 2:49:00 PM)
 * @author: Andrew Freed, arf132@psu.edu
 */

/*
Development of this applet was sponsored by the Penn State Fund for 
Excellence in Learning and Teaching (FELT), project "Java-based 
Teaching of Mathematics in Information Sciences and Technology",
supervised by Frank Ritter and David Mudgett.
*/

public class PascalApplet extends Applet {
	private Button btnGo 		= new Button();
	private ScrollPane pneDisplay = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
	private Label lblAnswer 	= new Label();
	private Label lblInstruction	= new Label();
	private TextField txtNumRows 	= new TextField();

/**
 * Function that will return a string value containing the nth Pascal row
 */
    String getPascalRow(int rowNum)
    {
	//Trivial cases
      if( rowNum < 0 )
        return "Please input a valid row number";
      if( rowNum == 0 )
        return "1";
      if( rowNum == 1 )
        return "1 1";

	//Otherwise, we will build up the triangle row by row until we get the row we need
      int oldRow[] = {1,1};
      int curRow[] = {};
      for( int rowIdx = 2; rowIdx <= rowNum; rowIdx++ )
      {
	  //Create a new row with the proper number of entries, also with "1" at both ends.
        curRow = new int[rowIdx+1];
        curRow[0]=1;
        curRow[rowIdx]=1;

	  //The rest of the entries are figured out from the previous row
        for(int col=1; col < rowIdx; col++)
        {
          curRow[col] = oldRow[col-1] + oldRow[col];
        }

	  //Advance to the next row
        oldRow = curRow;
      }

	//Print the results to a string
	//Bracket the middle value(s) for easier interpretation
      String result = new String();
      for(int col = 0; col <= rowNum; col++ )
      {
	  if( col * 2 == rowNum )
	  	result  += (" [" + intToString(curRow[col]) + "] ");
	  
	  else if( 2*col == rowNum -1 || 2*col == rowNum + 1 )
		result  += (" [" + intToString(curRow[col]) + "] ");

	  else
        	result  += (" " + intToString(curRow[col]) + " ");
      }
      return result;
    }

//This method takes an integer value and converts it to a string with commas placed
//every three digits from the right.
private String intToString(int myInt)
{
	String result = "";
	String buf = new Integer(myInt).toString();
	boolean isNegative = false;
	int numCommas = 0;

	if( myInt < 0 )
	{
		//Truncate sign
		isNegative = true;
		buf = buf.substring(1);
	}	

	int len = buf.length();

	//Short case, no commas
	if( len <= 3 )
	{
		if( isNegative )
			result = "-" + buf;
		else
			result = buf;
		
		return result;
	}
	
	//Otherwise place the first comma from the *left*
	//At each step, remove from the buffer what has been added to the result
	int firstComma = len % 3;
	if( firstComma == 0 )
	{
		firstComma += 3;
		result = buf.substring(0, 3) + ",";
		buf = buf.substring(3);
	}
	else
	{
		result = buf.substring(0, firstComma) + ",";
		buf = buf.substring(firstComma);
	}
	numCommas++;

	// Truncation of integer division on purpose -- 4, 5, 6 digit numbers each have the
	// same number of commas
	while( numCommas < ((len-1) / 3) )
	{
		result += buf.substring(0, 3) + ",";
		buf = buf.substring(3);
		numCommas++;
	}
	result += buf;

	//Re-attach the sign if necessary
	if( isNegative)
		result = "-" + result;

	return result;
}

/**
 * Initializes the applet.
 */
public void init() {
	try {
		super.init();
		setName("PascalApplet");
		setLayout(null);
		setSize(500, 300);
			pneDisplay.setBounds(15, 150, 400, 50);
			btnGo.setBounds(216, 21, 56, 23);
			btnGo.setLabel("Go!");
			lblAnswer.setText("");
			lblInstruction.setText("Row number:");
			lblInstruction.setBounds(22, 18, 109, 23);
			txtNumRows.setBounds(143, 17, 48, 29);

		pneDisplay.add(lblAnswer);
		add(pneDisplay);
		add(lblInstruction);
		add(txtNumRows);
		add(btnGo);


			btnGo.addActionListener(new java.awt.event.ActionListener(){
				public void actionPerformed(java.awt.event.ActionEvent e)
				{
					makeCall();

					//Very odd... I can't get the scrollbars to show up
					//until I do this!
					pneDisplay.doLayout();
				}
			});
			txtNumRows.addActionListener(new java.awt.event.ActionListener(){
				public void actionPerformed(java.awt.event.ActionEvent e)
				{
					makeCall();

					//Very odd... I can't get the scrollbars to show up
					//until I do this!
					pneDisplay.doLayout();
				}
			});

		txtNumRows.requestFocus();

	} catch (java.lang.Throwable Exc) {
		handleException(Exc);
	}
}

	//Interface function that gathers text input and sends value to code.
	//Also sets output boxes with output value.
    private void makeCall()
    {
	  String strInput = txtNumRows.getText();
	  lblAnswer.setText("");
        
        if( strInput == null )
          lblAnswer.setText("Please type in the row number first");
        else
          lblAnswer.setText(getPascalRow(Integer.parseInt(strInput)));
    }


/**
 * Called whenever the part throws an exception.
 * @param exception java.lang.Throwable
 */
private void handleException(java.lang.Throwable exception) {

	/* Uncomment the following lines to print uncaught exceptions to stdout */
	// System.out.println("--------- UNCAUGHT EXCEPTION ---------");
	// exception.printStackTrace(System.out);
}

//main allows the applet to be run as a standalone application
/**
 * main entrypoint - starts the part when it is run as an application
 * @param args java.lang.String[]
 */
public static void main(java.lang.String[] args) {
	try {
		Frame frame = new java.awt.Frame();
		PascalApplet aPascalApplet;
		Class iiCls = Class.forName("PascalApplet");
		ClassLoader iiClsLoader = iiCls.getClassLoader();
		aPascalApplet = (PascalApplet)java.beans.Beans.instantiate(iiClsLoader,"PascalApplet");
		frame.add("Center", aPascalApplet);
		frame.setSize(aPascalApplet.getSize());
		frame.addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowClosing(java.awt.event.WindowEvent e) {
				System.exit(0);
			};
		});
		frame.show();
		java.awt.Insets insets = frame.getInsets();
		frame.setSize(frame.getWidth() + insets.left + insets.right, frame.getHeight() + insets.top + insets.bottom);
		frame.setVisible(true);
	} catch (Throwable exception) {
		System.err.println("Exception occurred in main() of java.applet.Applet");
		exception.printStackTrace(System.out);
	}
}

}
