/*
 -------------------------------------------------------------
GridPuzzle 1.0b04 

This applet draws a 4 x 4 grid puzzle where the object is to rearrange
the numbers 1 through 16 so that all the columns and rows and the two
diagonals equal 34. It demonstrates a GUI in java.

Java's classes: Applet    (applet)
                Event     (awt)     user-generated action
                Graphics  (awt)     used for drawing
                Color     (awt)     defines colors
                Choice    (awt)     shape and color selection choices
                Vector    (util)    list of shapes

Custom classes: 

	GridPuzzle.class		handles init and mouse events and other grid functions.

	GridCell.class			defines data and methods for the cells in the grid.

	TotalGridCell.class		extends GridCell with a totalling method for grid.

	BoxButton.class			defines data and methods for the GUI tools for manipulating
							rows and columns.

	BoxButton3D.class		extends ButtonBox.class to include a beveled edge

Launched from:
GridPuzzle.html

 


------------------------------------------------------------- */

import java.applet.Applet;
import java.util.*;
import java.awt.*;

public class GridPuzzle extends Applet {
	//Our Image
	//Image theImage; remove cuz its too slow
   	
	//Offscreen stuff
    private boolean doubleBuffer=true; // or false of course
    private Image buf;                 // bitmap for double buffering
    private Graphics gBuf;             // gc to draw on bitmap
	
   Vector gridCellVector;
   Vector columnTotalVector;
   Vector rowTotalVector;
   Vector flipRowVector;
   Vector moveRowVector;
   Vector swapRowVector;
   Vector grayRowVector;
   
   Vector flipColumnVector;
   Vector moveColumnVector;
   Vector swapColumnVector;
   Vector grayColumnVector;
   
   int swapRowHit;
   int swapColumnHit;
   int moveRowHit;
   int moveColumnHit;
   int flipRowHit;
   int flipColumnHit;
   int swapCellHit;
   
   //Used in drag operations
   BoxButton currentBox;      
   GridCell currentCell;
      
   BoxButton3D solutionButton;
   BoxButton3D resetButton;
   
   int mouseDownX, mouseDownY;
   
   GridCell tempGridCell;
   GridCell tempCell;
   GridCell diagonalTLBR;
   GridCell diagonalTRBL;
   BoxButton tempBox;
   
   Choice  shapeChoice;
   Choice  colorChoice;
   Checkbox	moveCheckBox;  
   int i, j;
   int bigCellSize = 48;
   int MasterXOffset = 60;
   int MasterYOffset = 60;
   int column = 1;
   int row = 2;
   int diagonal = 3;
   
	ArtClass   theBG;
	boolean firstTime = true;
	
   /** Create the GUI. */
   public void init() {
   	  theBG = new ArtClass();
      gridCellVector = new Vector(); 
      columnTotalVector = new Vector(); 
      rowTotalVector = new Vector(); 
      flipRowVector = new Vector(); 
      moveRowVector = new Vector(); 
      swapRowVector = new Vector(); 
      grayRowVector = new Vector(); 

      flipColumnVector = new Vector(); 
      moveColumnVector = new Vector(); 
      swapColumnVector = new Vector(); 
      grayColumnVector = new Vector();
      
      
      for (j = 1; j <= 4; j++){ //for each row
      	for (i = 1; i <= 4; i++){ //for each column
      		tempGridCell = new GridCell();
			tempGridCell.SetCellFillColor(Color.white);
			tempGridCell.SetCellTextColor(Color.black);
			tempGridCell.SetCellBorder(true, true, true, true);
			tempGridCell.SetCellSize(bigCellSize, bigCellSize);
	     	tempGridCell.SetCellPosition(bigCellSize * (j - 1) + MasterYOffset, bigCellSize * (i - 1) + MasterXOffset);
	     	tempGridCell.SetCellValue(i + ((j - 1) * 4));
	     	
	     	gridCellVector.addElement(tempGridCell);
	     	
		}
      }

	// initialize the column and row total cells	
  	for (i = 1; i <= 4; i++){ //for each column
  		tempGridCell = new TotalGridCell();
		tempGridCell.SetCellFillColor(Color.red);
		tempGridCell.SetCellTextColor(Color.black);
		tempGridCell.SetCellBorder(false, true, true, true);
		tempGridCell.SetCellSize(bigCellSize, bigCellSize);
     	tempGridCell.SetCellPosition(MasterYOffset - bigCellSize, bigCellSize * (i - 1) + MasterXOffset);
     	//tempGridCell.SetCellTotal(gridCellVector, column, i);
     	columnTotalVector.addElement(tempGridCell);     	
	}
  	for (i = 1; i <= 4; i++){ //for each row
  		tempGridCell = new TotalGridCell();
		tempGridCell.SetCellFillColor(Color.red);
		tempGridCell.SetCellTextColor(Color.black);
		tempGridCell.SetCellBorder(true, true, true, false);
		tempGridCell.SetCellSize(bigCellSize, bigCellSize);
     	tempGridCell.SetCellPosition(bigCellSize * (i - 1) + MasterYOffset, bigCellSize * 4 + MasterXOffset);
     	//tempGridCell.SetCellTotal(gridCellVector, row, i);
     	rowTotalVector.addElement(tempGridCell);     	
	}
	
	// initialize the diagonal total cells
	    diagonalTLBR = new TotalGridCell();
		diagonalTLBR.SetCellFillColor(Color.red);
		diagonalTLBR.SetCellTextColor(Color.black);
		diagonalTLBR.SetCellBorder(false, false, true, true);
		diagonalTLBR.SetCellSize(bigCellSize, bigCellSize);
     	diagonalTLBR.SetCellPosition(MasterYOffset - bigCellSize, MasterXOffset - bigCellSize);
     	//diagonalTLBR.SetCellTotal(gridCellVector, diagonal, 1);

	    diagonalTRBL = new TotalGridCell();
		diagonalTRBL.SetCellFillColor(Color.red);
		diagonalTRBL.SetCellTextColor(Color.black);
		diagonalTRBL.SetCellBorder(false, true, true, false);
		diagonalTRBL.SetCellSize(bigCellSize, bigCellSize);
     	diagonalTRBL.SetCellPosition(MasterYOffset - bigCellSize, (4 * bigCellSize) + MasterXOffset);
     	//diagonalTRBL.SetCellTotal(gridCellVector, diagonal, 2);
     	
     SetTotals(); // calculate and set the total cell values

	// initialize the solution button
		solutionButton = new BoxButton3D();
		solutionButton.setState(false);
		solutionButton.setBevel(bigCellSize / 8);
		
		solutionButton.setColors(Color.orange.getRed(), Color.orange.getGreen(), Color.orange.getBlue(), 128, 128, 128);
		solutionButton.top = (4 * bigCellSize) + MasterYOffset;
		solutionButton.left = (4 * bigCellSize) + MasterXOffset;
		solutionButton.height = bigCellSize;
		solutionButton.width = bigCellSize;
		
	// initialize the reset button
		resetButton = new BoxButton3D();
		resetButton.setState(false);
		resetButton.setBevel(bigCellSize / 8);
		
		resetButton.setColors(Color.blue.getRed(), Color.blue.getGreen(), Color.blue.getBlue(), 128, 128, 128);
		resetButton.top = (4 * bigCellSize) + MasterYOffset;
		resetButton.left = MasterXOffset - bigCellSize;
		resetButton.height = bigCellSize;
		resetButton.width = bigCellSize;
		
	// initialize row flipper buttons		
		for (i = 1; i <= 4; i++){
			tempBox = new BoxButton();
			tempBox.top = (((((i * 8) - 4) - 1) * (4 * bigCellSize)) / 32) + MasterYOffset;
			tempBox.left = MasterXOffset - bigCellSize;
			tempBox.height = (4 * bigCellSize) / 16;
			tempBox.width = bigCellSize;
			tempBox.color = Color.magenta;
			
			flipRowVector.addElement(tempBox);
		}
		
	// initialize row mover buttons		
		for (i = 1; i <= 4; i++){
			tempBox = new BoxButton();
			tempBox.top = (((((i * 8) - 6) - 1) * (4 * bigCellSize)) / 32) + MasterYOffset;
			tempBox.left = MasterXOffset - bigCellSize;
			tempBox.height = (4 * bigCellSize) / 16;
			tempBox.width = bigCellSize;
			tempBox.color = Color.yellow;
			
			moveRowVector.addElement(tempBox);
		}

	// initialize row swapper buttons		
		for (i = 1; i <= 4; i++){
			tempBox = new BoxButton();
			tempBox.top = (((((i * 8) - 2) - 1) * (4 * bigCellSize)) / 32) + MasterYOffset;
			tempBox.left = MasterXOffset - bigCellSize;
			tempBox.height = (4 * bigCellSize) / 16;
			tempBox.width = bigCellSize;
			tempBox.color = Color.cyan;
			
			swapRowVector.addElement(tempBox);
		}
		
	// initialize row gray buttons	
		tempBox = new BoxButton();
		tempBox.top = MasterYOffset;
		tempBox.left = MasterXOffset - bigCellSize;
		tempBox.height = (4 * bigCellSize) / 32;
		tempBox.width = bigCellSize;
		tempBox.color = Color.gray;
		
		grayRowVector.addElement(tempBox);
		
		for (i = 1; i <= 3; i++){
			tempBox = new BoxButton();
			tempBox.top = ((((i * 8) - 1) * (4 * bigCellSize)) / 32) + MasterYOffset;
			tempBox.left = MasterXOffset - bigCellSize;
			tempBox.height = (4 * bigCellSize) / 16;
			tempBox.width = bigCellSize;
			tempBox.color = Color.gray;
			
			grayRowVector.addElement(tempBox);
		}
		
		tempBox = new BoxButton();
		tempBox.top = MasterYOffset + (4 * bigCellSize) - ((4 * bigCellSize) / 32);
		tempBox.left = MasterXOffset - bigCellSize;
		tempBox.height = (4 * bigCellSize) / 32;
		tempBox.width = bigCellSize;
		tempBox.color = Color.gray;
		
		grayRowVector.addElement(tempBox);

		
	// initialize column flipper buttons		
		for (i = 1; i <= 4; i++){
			tempBox = new BoxButton();
			tempBox.left = (((((i * 8) - 4) - 1) * (4 * bigCellSize)) / 32) + MasterXOffset;
			tempBox.top = MasterYOffset + (4 * bigCellSize);
			tempBox.width = (4 * bigCellSize) / 16;
			tempBox.height = bigCellSize;
			tempBox.color = Color.magenta;
			
			flipColumnVector.addElement(tempBox);
		}
		
	// initialize column mover buttons		
		for (i = 1; i <= 4; i++){
			tempBox = new BoxButton();
			tempBox.left = (((((i * 8) - 6) - 1) * (4 * bigCellSize)) / 32) + MasterXOffset;
			tempBox.top = MasterYOffset + (4 * bigCellSize);
			tempBox.width = (4 * bigCellSize) / 16;
			tempBox.height = bigCellSize;
			tempBox.color = Color.yellow;
			
			moveColumnVector.addElement(tempBox);
		}

	// initialize column swapper buttons		
		for (i = 1; i <= 4; i++){
			tempBox = new BoxButton();
			tempBox.left = (((((i * 8) - 2) - 1) * (4 * bigCellSize)) / 32) + MasterXOffset;
			tempBox.top = MasterYOffset + (4 * bigCellSize);
			tempBox.width = (4 * bigCellSize) / 16;
			tempBox.height = bigCellSize;
			tempBox.color = Color.cyan;
			
			swapColumnVector.addElement(tempBox);
		}
		
	// initialize column gray buttons	
		tempBox = new BoxButton();
		tempBox.left = MasterXOffset;
		tempBox.top = MasterYOffset + (4 * bigCellSize);
		tempBox.width = (4 * bigCellSize) / 32;
		tempBox.height = bigCellSize;
		tempBox.color = Color.gray;
		
		grayColumnVector.addElement(tempBox);
		
		for (i = 1; i <= 3; i++){
			tempBox = new BoxButton();
			tempBox.left = ((((i * 8) - 1) * (4 * bigCellSize)) / 32) + MasterXOffset;
			tempBox.top = MasterYOffset + (4 * bigCellSize);
			tempBox.width = (4 * bigCellSize) / 16;
			tempBox.height = bigCellSize;
			tempBox.color = Color.gray;
			
			grayColumnVector.addElement(tempBox);
		}
		
		tempBox = new BoxButton();
		tempBox.left = MasterXOffset + (4 * bigCellSize) - ((4 * bigCellSize) / 32);
		tempBox.top = MasterYOffset + (4 * bigCellSize);
		tempBox.width = (4 * bigCellSize) / 32;
		tempBox.height = bigCellSize;
		tempBox.color = Color.gray;
		
		grayColumnVector.addElement(tempBox);
		
      	//theImage = getImage(getDocumentBase(),"cockpit.gif"); removed cuz its too slow


		if (doubleBuffer)
        {
            Dimension d = size();
            buf = createImage(d.width, d.height);
            gBuf = buf.getGraphics();
        }
        

		//draw our GUI
    	repaint();     
   }
   
   /* Handle a mouse drag event. */
   public boolean mouseDrag(Event e, int x, int y) {
   boolean inValidBox;
   
   		inValidBox = false;
		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) swapRowVector.elementAt(i - 1);
			if ((tempBox.InsideBox(x, y)) && (swapRowHit != i) && (swapRowHit != 0)){
				inValidBox = true;
				if (tempBox != currentBox){
					if (currentBox != null) currentBox.color = Color.cyan;
				  	tempBox.color = Color.darkGray;
				  	currentBox = tempBox;
				  	repaint();
				}
			}
		}
		if ((inValidBox == false) && (swapRowHit != 0)){
			if (currentBox != null) {
				currentBox.color = Color.cyan;
				currentBox = null;
				repaint();
			}
		} 	

   		inValidBox = false;	  
		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) swapColumnVector.elementAt(i - 1);
			if ((tempBox.InsideBox(x, y)) && (swapColumnHit != i) && (swapColumnHit != 0)){
				inValidBox = true;
				if (tempBox != currentBox){
					if (currentBox != null) currentBox.color = Color.cyan;
				  	tempBox.color = Color.darkGray;
				  	currentBox = tempBox;
				  	repaint();
				}
			}
		}		
		if ((inValidBox == false) && (swapColumnHit != 0)){
			if (currentBox != null) {
				currentBox.color = Color.cyan;
				currentBox = null;
				repaint();
			}
		} 	
	  
   		inValidBox = false;
		for (i = 1; i <= 5; i++){
			tempBox = (BoxButton) grayRowVector.elementAt(i - 1);
			if ((tempBox.InsideBox(x, y)) && (moveRowHit != 0)){
				inValidBox = true;
				if (tempBox != currentBox){
					if (currentBox != null) currentBox.color = Color.gray;
				  	tempBox.color = Color.darkGray;
				  	currentBox = tempBox;
				  	repaint();
				}
			}
		}		
		if ((inValidBox == false) && (moveRowHit != 0)){
			if (currentBox != null) {
				currentBox.color = Color.gray;
				currentBox = null;
				repaint();
			}
		} 	
	  
   		inValidBox = false;
		for (i = 1; i <= 5; i++){
			tempBox = (BoxButton) grayColumnVector.elementAt(i - 1);
			if ((tempBox.InsideBox(x, y)) && (moveColumnHit != 0)){
				inValidBox = true;
				if (tempBox != currentBox){
					if (currentBox != null) currentBox.color = Color.gray;
				  	tempBox.color = Color.darkGray;
				  	currentBox = tempBox;
				  	repaint();
				}
			}
		}		
		if ((inValidBox == false) && (moveColumnHit != 0)){
			if (currentBox != null) {
				currentBox.color = Color.gray;
				currentBox = null;
				repaint();
			}
		} 	
	  
   		inValidBox = false;
		for (i = 1; i <= 16; i++){
			tempCell = (GridCell) gridCellVector.elementAt(i - 1);
			if ((tempCell.InsideBox(x, y)) && (swapCellHit != 0) && (swapCellHit != i)){
				inValidBox = true;
				if (tempCell != currentCell){
					if (currentCell != null) {
						currentCell.cellFillColor = Color.white;
						currentCell.cellTextColor = Color.black;
					}
				  	tempCell.cellFillColor = Color.darkGray;
				  	tempCell.cellTextColor = Color.white;
				  	currentCell = tempCell;
				  	repaint();
				}
			}
		}		
		if ((inValidBox == false) && (swapCellHit != 0)){
			if (currentCell != null) {
				currentCell.cellFillColor = Color.white;
				currentCell.cellTextColor = Color.black;
				currentCell = null;
				repaint();
			}
		} 	
	  
	  
	  
      return true;
   }
   
   /* Handle a mouse down event. */
   public boolean mouseDown(Event e, int x, int y) {
   
		int i;
		
		mouseDownX = x;
		mouseDownY = y;

		moveColumnHit = 0;
		moveRowHit = 0;
		
		swapColumnHit = 0;
		swapRowHit = 0;
		
		flipColumnHit = 0;
		flipRowHit = 0;
		
		currentBox = null;
		currentCell = null;
		
		if (solutionButton.InsideBox(x, y)){
		  	solutionButton.setState(true);
		  	repaint();
		}
		
		if (resetButton.InsideBox(x, y)){
		  	resetButton.setState(true);
		  	repaint();
		}
		
		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) swapRowVector.elementAt(i - 1);
			if (tempBox.InsideBox(x, y)){
			  	tempBox.color = Color.lightGray;
			  	swapRowHit = i;
			  	repaint();
		  	}
		}

		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) moveRowVector.elementAt(i - 1);
			if (tempBox.InsideBox(x, y)){
			  	tempBox.color = Color.lightGray;
			  	moveRowHit = i;
			  	repaint();
		  	}
		}

		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) flipRowVector.elementAt(i - 1);
			if (tempBox.InsideBox(x, y)){
			  	tempBox.color = Color.lightGray;
			  	flipRowHit = i;
			  	repaint();
		  	}
		}

		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) swapColumnVector.elementAt(i - 1);
			if (tempBox.InsideBox(x, y)){
			  	tempBox.color = Color.lightGray;
			  	swapColumnHit = i;
			  	repaint();
		  	}
		}

		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) moveColumnVector.elementAt(i - 1);
			if (tempBox.InsideBox(x, y)){
			  	tempBox.color = Color.lightGray;
			  	moveColumnHit = i;
			  	repaint();
		  	}
		}

		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) flipColumnVector.elementAt(i - 1);
			if (tempBox.InsideBox(x, y)){
			  	tempBox.color = Color.lightGray;
			  	flipColumnHit = i;
			  	repaint();
		  	}
		}

		//Handle mousedown in a GridCell
		for (i = 1; i <= 16; i++){
			tempCell = (GridCell) gridCellVector.elementAt(i - 1);
			if (tempCell.InsideBox(x, y)){
			  	tempCell.cellFillColor = Color.lightGray;
			  	swapCellHit = i;
			  	repaint();
		  	}
		}

      return true;
   }

   /* Handle a mouse up event. */
   public boolean mouseUp(Event e, int x, int y) {

	  // Check is user clicked solution button
	  if ((solutionButton.InsideBox(mouseDownX, mouseDownY)) && (solutionButton.InsideBox(x, y))){
	  	SetToSolution();
	  }
	  solutionButton.setState(false);


	  // Check is user clicked reset button	  
	  if ((resetButton.InsideBox(mouseDownX, mouseDownY)) && (resetButton.InsideBox(x, y))){
	  	ResetGrid();
	  }
   	  resetButton.setState(false);

	  // Handle Row/Column Operations
	  // ****************************
	  // Check is user clicked one of the flip buttons
		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) flipRowVector.elementAt(i - 1);
			if ((tempBox.InsideBox(x, y)) && (tempBox.InsideBox(mouseDownX, mouseDownY))){
			  	FlipRow(i);
			  	flipRowHit = 0;
		  	}
		  	tempBox.color = Color.magenta;
		}		
      
		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) flipColumnVector.elementAt(i - 1);
			if ((tempBox.InsideBox(x, y)) && (tempBox.InsideBox(mouseDownX, mouseDownY))){
			  	FlipColumn(i);
			  	flipColumnHit = 0;
		  	}
		  	tempBox.color = Color.magenta;
		}		
      
		// Check if user did a valid swap drag      
		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) swapColumnVector.elementAt(i - 1);
			if ((tempBox.InsideBox(x, y)) && (i != swapColumnHit) && (swapColumnHit != 0)){
			  	SwapColumns(i, swapColumnHit);
			  	swapColumnHit = 0;
		  	}
		  	tempBox.color = Color.cyan;
		}		

		for (i = 1; i <= 4; i++){
			tempBox = (BoxButton) swapRowVector.elementAt(i - 1);
			if ((tempBox.InsideBox(x, y)) && (i != swapRowHit) && (swapRowHit != 0)){
			  	SwapRows(i, swapRowHit);
			  	swapRowHit = 0;
		  	}
		  	tempBox.color = Color.cyan;
		}		
		
      
		// Check is user clicked did a valid move drag      
		tempBox = (BoxButton) grayRowVector.elementAt(0);
		if ((tempBox.InsideBox(x, y)) && (moveRowHit >= 2)){
			  	MoveRow(moveRowHit, 1);
		}
      
		tempBox = (BoxButton) grayRowVector.elementAt(1);
		if ((tempBox.InsideBox(x, y)) && (moveRowHit >= 3)){
			  	MoveRow(moveRowHit, 2);
		}
      
		tempBox = (BoxButton) grayRowVector.elementAt(2);
		if ((tempBox.InsideBox(x, y)) && (moveRowHit == 4)){
		  	MoveRow(moveRowHit, 3);
		}else if ((tempBox.InsideBox(x, y)) && (moveRowHit == 1)){
		  	MoveRow(moveRowHit, 2);
		}
      
		tempBox = (BoxButton) grayRowVector.elementAt(3);
		if ((tempBox.InsideBox(x, y)) && (moveRowHit <= 2) && (moveRowHit != 0)){
			  	MoveRow(moveRowHit, 3);
		}
      
		tempBox = (BoxButton) grayRowVector.elementAt(4);
		if ((tempBox.InsideBox(x, y)) && (moveRowHit <= 3) && (moveRowHit != 0)){
			  	MoveRow(moveRowHit, 4);
		}
		
		if (moveRowHit != 0){
			tempBox = (BoxButton) moveRowVector.elementAt(moveRowHit - 1);
			tempBox.color = Color.yellow;
			if ((currentBox != null)){
				currentBox.color = Color.gray;
				currentBox = null;
			}

			moveRowHit = 0;
		}

	  // Check is user clicked did a valid move drag
		tempBox = (BoxButton) grayColumnVector.elementAt(0);
		if ((tempBox.InsideBox(x, y)) && (moveColumnHit >= 2)){
			  	MoveColumn(moveColumnHit, 1);
		}
      
		tempBox = (BoxButton) grayColumnVector.elementAt(1);
		if ((tempBox.InsideBox(x, y)) && (moveColumnHit >= 3)){
			  	MoveColumn(moveColumnHit, 2);
		}
      
		tempBox = (BoxButton) grayColumnVector.elementAt(2);
		if ((tempBox.InsideBox(x, y)) && (moveColumnHit == 4)){
		  	MoveColumn(moveColumnHit, 3);
		  	tempBox.color = Color.gray;
		}else if ((tempBox.InsideBox(x, y)) && (moveColumnHit == 1)){
		  	MoveColumn(moveColumnHit, 2);
		}
      
		tempBox = (BoxButton) grayColumnVector.elementAt(3);
		if ((tempBox.InsideBox(x, y)) && (moveColumnHit <= 2) && (moveColumnHit != 0)){
			  	MoveColumn(moveColumnHit, 3);
		}
      
		tempBox = (BoxButton) grayColumnVector.elementAt(4);
		if ((tempBox.InsideBox(x, y)) && (moveColumnHit <= 3) && (moveColumnHit != 0)){
			  	MoveColumn(moveColumnHit, 4);
		}
		
		if (moveColumnHit != 0){
			tempBox = (BoxButton) moveColumnVector.elementAt(moveColumnHit - 1);
			tempBox.color = Color.yellow;
			if ((currentBox != null)){
				currentBox.color = Color.gray;
				currentBox = null;
			}

			moveColumnHit = 0;
		}
	
	  //handle mouse up in a grid cell
		for (i = 1; i <= 16; i++){
			tempCell = (GridCell) gridCellVector.elementAt(i - 1);
			if ((tempCell.InsideBox(x, y)) && (i != swapCellHit) && (swapCellHit != 0)){
			  	SwapCells(i, swapCellHit);
			  	swapCellHit = 0;
		  	}
		  	tempCell.cellFillColor = Color.white;
		  	tempCell.cellTextColor = Color.black;
		}		
	  	
		
	  currentBox = null;
      repaint();
      
      return true;
   }


   public void SetTotals(){
   int i;
   TotalGridCell tempGridCell;
   
	   	// Calculate totals for row and column total cells	
	  	for (i = 1; i <= 4; i++){ //for each column
	  		tempGridCell = (TotalGridCell) columnTotalVector.elementAt(i -1);
	     	tempGridCell.SetCellTotal(gridCellVector, column, i);
		}
		
	  	for (i = 1; i <= 4; i++){ //for each row
	  		tempGridCell = (TotalGridCell)  rowTotalVector.elementAt(i -1);
	     	tempGridCell.SetCellTotal(gridCellVector, row, i);
		}
		
		// Calculate totals for diagonal total cells	
		    diagonalTLBR.SetCellTotal(gridCellVector, diagonal, 1);
		    diagonalTRBL.SetCellTotal(gridCellVector, diagonal, 2);
   }
   
   public void SetToSolution(){
   GridCell tempCell;
		//set Grid to solution
		tempCell = (GridCell) gridCellVector.elementAt(0);
		tempCell.cellValue = 1;
		tempCell = (GridCell) gridCellVector.elementAt(1);
		tempCell.cellValue = 11;
		tempCell = (GridCell) gridCellVector.elementAt(2);
		tempCell.cellValue = 6;
		tempCell = (GridCell) gridCellVector.elementAt(3);
		tempCell.cellValue = 16;
		tempCell = (GridCell) gridCellVector.elementAt(4);
		tempCell.cellValue = 8;
		tempCell = (GridCell) gridCellVector.elementAt(5);
		tempCell.cellValue = 14;
		tempCell = (GridCell) gridCellVector.elementAt(6);
		tempCell.cellValue = 3;
		tempCell = (GridCell) gridCellVector.elementAt(7);
		tempCell.cellValue = 9;
		tempCell = (GridCell) gridCellVector.elementAt(8);
		tempCell.cellValue = 15;
		tempCell = (GridCell) gridCellVector.elementAt(9);
		tempCell.cellValue = 5;
		tempCell = (GridCell) gridCellVector.elementAt(10);
		tempCell.cellValue = 12;
		tempCell = (GridCell) gridCellVector.elementAt(11);
		tempCell.cellValue = 2;
		tempCell = (GridCell) gridCellVector.elementAt(12);
		tempCell.cellValue = 10;
		tempCell = (GridCell) gridCellVector.elementAt(13);
		tempCell.cellValue = 4;
		tempCell = (GridCell) gridCellVector.elementAt(14);
		tempCell.cellValue = 13;
		tempCell = (GridCell) gridCellVector.elementAt(15);
		tempCell.cellValue = 7;
		SetTotals(); // calculate and set the total cell values

   }
   
   public void ResetGrid(){
   GridCell tempCell;
		//set Grid to solution
		tempCell = (GridCell) gridCellVector.elementAt(0);
		tempCell.cellValue = 1;
		tempCell = (GridCell) gridCellVector.elementAt(1);
		tempCell.cellValue = 2;
		tempCell = (GridCell) gridCellVector.elementAt(2);
		tempCell.cellValue = 3;
		tempCell = (GridCell) gridCellVector.elementAt(3);
		tempCell.cellValue = 4;
		tempCell = (GridCell) gridCellVector.elementAt(4);
		tempCell.cellValue = 5;
		tempCell = (GridCell) gridCellVector.elementAt(5);
		tempCell.cellValue = 6;
		tempCell = (GridCell) gridCellVector.elementAt(6);
		tempCell.cellValue = 7;
		tempCell = (GridCell) gridCellVector.elementAt(7);
		tempCell.cellValue = 8;
		tempCell = (GridCell) gridCellVector.elementAt(8);
		tempCell.cellValue = 9;
		tempCell = (GridCell) gridCellVector.elementAt(9);
		tempCell.cellValue = 10;
		tempCell = (GridCell) gridCellVector.elementAt(10);
		tempCell.cellValue = 11;
		tempCell = (GridCell) gridCellVector.elementAt(11);
		tempCell.cellValue = 12;
		tempCell = (GridCell) gridCellVector.elementAt(12);
		tempCell.cellValue = 13;
		tempCell = (GridCell) gridCellVector.elementAt(13);
		tempCell.cellValue = 14;
		tempCell = (GridCell) gridCellVector.elementAt(14);
		tempCell.cellValue = 15;
		tempCell = (GridCell) gridCellVector.elementAt(15);
		tempCell.cellValue = 16;
		SetTotals(); // calculate and set the total cell values

   }
   
   public void FlipRow(int j){
   	  int tempCellValue;
   	  GridCell tempCell1, tempCell2, tempCell3, tempCell4;
   	  
   	  tempCell1 = (GridCell) gridCellVector.elementAt((1 + ((j - 1) * 4) -1));
   	  tempCell2 = (GridCell) gridCellVector.elementAt((2 + ((j - 1) * 4) -1));
   	  tempCell3 = (GridCell) gridCellVector.elementAt((3 + ((j - 1) * 4) -1));
   	  tempCell4 = (GridCell) gridCellVector.elementAt((4 + ((j - 1) * 4) -1));
   	  
   	  tempCellValue = tempCell1.cellValue;
   	  tempCell1.cellValue = tempCell4.cellValue;
   	  tempCell4.cellValue = tempCellValue;
   	  
   	  tempCellValue = tempCell2.cellValue;
   	  tempCell2.cellValue = tempCell3.cellValue;
   	  tempCell3.cellValue = tempCellValue;
   	  
   	  SetTotals(); // calculate and set the total cell values

   }
   
   public void FlipColumn(int i){
   	  int tempCellValue;
   	  GridCell tempCell1, tempCell2, tempCell3, tempCell4;
   	  
   	  tempCell1 = (GridCell) gridCellVector.elementAt((i + ((1 - 1) * 4) -1));
   	  tempCell2 = (GridCell) gridCellVector.elementAt((i + ((2 - 1) * 4) -1));
   	  tempCell3 = (GridCell) gridCellVector.elementAt((i + ((3 - 1) * 4) -1));
   	  tempCell4 = (GridCell) gridCellVector.elementAt((i + ((4 - 1) * 4) -1));
   	  
   	  tempCellValue = tempCell1.cellValue;
   	  tempCell1.cellValue = tempCell4.cellValue;
   	  tempCell4.cellValue = tempCellValue;
   	  
   	  tempCellValue = tempCell2.cellValue;
   	  tempCell2.cellValue = tempCell3.cellValue;
   	  tempCell3.cellValue = tempCellValue;
   	  
   	  SetTotals(); // calculate and set the total cell values

   }
   
   public void SwapRows(int i1, int i2){
   	  int tempCellValue;
   	  GridCell tempCell11, tempCell12, tempCell13, tempCell14;
   	  GridCell tempCell21, tempCell22, tempCell23, tempCell24;
   	  
   	  tempCell11 = (GridCell) gridCellVector.elementAt((1 + ((i1 - 1) * 4) -1));
   	  tempCell12 = (GridCell) gridCellVector.elementAt((2 + ((i1 - 1) * 4) -1));
   	  tempCell13 = (GridCell) gridCellVector.elementAt((3 + ((i1 - 1) * 4) -1));
   	  tempCell14 = (GridCell) gridCellVector.elementAt((4 + ((i1 - 1) * 4) -1));
   	  
   	  tempCell21 = (GridCell) gridCellVector.elementAt((1 + ((i2 - 1) * 4) -1));
   	  tempCell22 = (GridCell) gridCellVector.elementAt((2 + ((i2 - 1) * 4) -1));
   	  tempCell23 = (GridCell) gridCellVector.elementAt((3 + ((i2 - 1) * 4) -1));
   	  tempCell24 = (GridCell) gridCellVector.elementAt((4 + ((i2 - 1) * 4) -1));
   	  
   	  tempCellValue = tempCell11.cellValue;
   	  tempCell11.cellValue = tempCell21.cellValue;
   	  tempCell21.cellValue = tempCellValue;
   	     	  
   	  tempCellValue = tempCell12.cellValue;
   	  tempCell12.cellValue = tempCell22.cellValue;
   	  tempCell22.cellValue = tempCellValue;
   	     	  
   	  tempCellValue = tempCell13.cellValue;
   	  tempCell13.cellValue = tempCell23.cellValue;
   	  tempCell23.cellValue = tempCellValue;
   	     	  
   	  tempCellValue = tempCell14.cellValue;
   	  tempCell14.cellValue = tempCell24.cellValue;
   	  tempCell24.cellValue = tempCellValue;
   	     	  
   	  SetTotals(); // calculate and set the total cell values

   }
   
   public void SwapColumns(int i1, int i2){
   	  int tempCellValue;
   	  GridCell tempCell11, tempCell12, tempCell13, tempCell14;
   	  GridCell tempCell21, tempCell22, tempCell23, tempCell24;
   	  
   	  tempCell11 = (GridCell) gridCellVector.elementAt((i1 + ((1 - 1) * 4) -1));
   	  tempCell12 = (GridCell) gridCellVector.elementAt((i1 + ((2 - 1) * 4) -1));
   	  tempCell13 = (GridCell) gridCellVector.elementAt((i1 + ((3 - 1) * 4) -1));
   	  tempCell14 = (GridCell) gridCellVector.elementAt((i1 + ((4 - 1) * 4) -1));
   	  
   	  tempCell21 = (GridCell) gridCellVector.elementAt((i2 + ((1 - 1) * 4) -1));
   	  tempCell22 = (GridCell) gridCellVector.elementAt((i2 + ((2 - 1) * 4) -1));
   	  tempCell23 = (GridCell) gridCellVector.elementAt((i2 + ((3 - 1) * 4) -1));
   	  tempCell24 = (GridCell) gridCellVector.elementAt((i2 + ((4 - 1) * 4) -1));
   	  
   	  tempCellValue = tempCell11.cellValue;
   	  tempCell11.cellValue = tempCell21.cellValue;
   	  tempCell21.cellValue = tempCellValue;
   	     	  
   	  tempCellValue = tempCell12.cellValue;
   	  tempCell12.cellValue = tempCell22.cellValue;
   	  tempCell22.cellValue = tempCellValue;
   	     	  
   	  tempCellValue = tempCell13.cellValue;
   	  tempCell13.cellValue = tempCell23.cellValue;
   	  tempCell23.cellValue = tempCellValue;
   	     	  
   	  tempCellValue = tempCell14.cellValue;
   	  tempCell14.cellValue = tempCell24.cellValue;
   	  tempCell24.cellValue = tempCellValue;
   	     	  
   	  SetTotals(); // calculate and set the total cell values

   }
   
   public void MoveRow(int oldPosition, int newPosition){
   	
   	 if (oldPosition < newPosition) {
   	 	for (i = oldPosition; i <= (newPosition - 1); i++){
   	 		SwapRows(i, (i + 1));
   	 	}
   	 }else{
   	 	for (i = oldPosition; i >= (newPosition + 1); i--){
   	 		SwapRows(i, (i - 1));
   	 	}   	 
   	 }
   
   }
   
   public void MoveColumn(int oldPosition, int newPosition){
   	
   	 if (oldPosition < newPosition) {
   	 	for (i = oldPosition; i <= (newPosition - 1); i++){
   	 		SwapColumns(i, (i + 1));
   	 	}
   	 }else{
   	 	for (i = oldPosition; i >= (newPosition + 1); i--){
   	 		SwapColumns(i, (i - 1));
   	 	}   	 
   	 }
   
   }
   
   public void SwapCells(int i1, int i2){
   int tempCellValue;
   GridCell tempCell1, tempCell2;
   
	   tempCell1 = (GridCell) gridCellVector.elementAt(i1 - 1);
	   tempCell2 = (GridCell) gridCellVector.elementAt(i2 - 1);

	   tempCellValue = tempCell1.cellValue;
	   tempCell1.cellValue = tempCell2.cellValue;
	   tempCell2.cellValue = tempCellValue;
	   SetTotals(); // calculate and set the total cell values

   }
   
   
    public void destroy()
    {
        if (doubleBuffer)
            gBuf.dispose();
    }

    protected void paintApplet(Graphics g)
    {
    
		int LM = MasterXOffset + bigCellSize * 5 + 24;
		int TM = MasterYOffset - bigCellSize + 20;
		int T1 = 40;
		int LS = 16;
		int LN = 0;
		int BoxHeight = LS - 2;
		int BoxWidth = T1 - 6;
		int BoxHO = ((LS * 2) / 3);
		
        // pre-clear the bitmap or the applet
        // remove this if you paint the entire area anyway
        Dimension d = size();
        //g.setColor(Color.white);
       // g.fillRect(0, 0, d.width, d.height);
 		if ( this.firstTime) {
 			theBG.draw(g);
 			this.firstTime = false;
			//draw the help info
			g.setColor(Color.white);
			//g.drawString("", LM, TM + (LN * LS));
			//g.drawLine(LM, TM + (LN * LS) + 2, LM + 163, TM + (LN * LS) + 2);
			//g.drawLine(LM, TM + (LN * LS) + 3, LM + 163, TM + (LN * LS) + 3);
			LN++;
			LN++;
			
			g.drawString("The Object:", LM, TM + (LN * LS));
			g.drawLine(LM, TM + (LN * LS) + 2, LM + 54, TM + (LN * LS) + 2);
			LN++;
			
			g.drawString("Arrange numbers in white boxes so that", LM, TM + (LN * LS));
			LN++;
			g.drawString("all columns, rows, and diagonals sum 34.", LM, TM + (LN * LS));
			LN++;
			LN++;

			g.drawString("Tools:", LM, TM + (LN * LS));
			g.drawLine(LM, TM + (LN * LS) + 2, LM + 28, TM + (LN * LS) + 2);
			LN++;

			g.setColor(Color.white);
			g.fillRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.black);
			g.drawRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.white);
			g.drawString("Swap two cells (drag to new cell)", LM + T1, TM + (LN * LS));
			LN++;

			g.setColor(Color.yellow);
			g.fillRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.black);
			g.drawRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.white);
			g.drawString("Move row/column (drag to gray cell)", LM + T1, TM + (LN * LS));
			LN++;

			g.setColor(Color.magenta);
			g.fillRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.black);
			g.drawRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.white);
			g.drawString("Flip row/column (click)", LM + T1, TM + (LN * LS));
			LN++;

			g.setColor(Color.cyan);
			g.fillRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.black);
			g.drawRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.white);
			g.drawString("Swap rows/columns (drag to cyan cell)", LM + T1, TM + (LN * LS));
			LN++;

			g.setColor(Color.blue);
			g.fillRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.black);
			g.drawRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.white);
			g.drawString("Reset grid (click)", LM + T1, TM + (LN * LS));
			LN++;

			g.setColor(Color.orange);
			g.fillRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.black);
			g.drawRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.white);
			g.drawString("One solution (click)", LM + T1, TM + (LN * LS));
			LN++;

			g.setColor(Color.red);
			g.fillRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.black);
			g.drawRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.white);
			g.drawString("Row/column/diagonal sum not = 34", LM + T1, TM + (LN * LS));
			LN++;

			g.setColor(Color.green);
			g.fillRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.black);
			g.drawRect(LM, TM + (LN * LS) - BoxHO, BoxWidth, BoxHeight);
			g.setColor(Color.white);
			g.drawString("Row/column/diagonal sum = 34", LM + T1, TM + (LN * LS));
			LN++;
			LN++;
			LN++;

			g.setColor(Color.black);
			g.drawString("by Rick Reed ©1997 all rights reserved", LM, TM + (LN * LS));
 			
 			
 			
 			
 		}
      //g.drawImage(theImage,0,0,583,320, this); removed cuz its too slow

      GridCell tempGridCell;
      int i, j;
                     
     
      for (i = 1; i <= 4; i++) {
	      for (j = 1; j <= 4; j++) {
	         tempGridCell = (GridCell) gridCellVector.elementAt(i + ((j - 1) * 4) - 1);
	         tempGridCell.draw(g);  
	      }
      }
      
      
     for (i = 1; i <= 4; i++) {
	         tempGridCell = (GridCell) columnTotalVector.elementAt(i-1);
	         tempGridCell.draw(g);  
	 }
	 
     for (i = 1; i <= 4; i++) {
	         tempGridCell = (GridCell) rowTotalVector.elementAt(i-1);
	         tempGridCell.draw(g);  
	 }
	 
     for (i = 1; i <= 4; i++) {
	         tempBox = (BoxButton) flipRowVector.elementAt(i-1);
	         tempBox.draw(g);  
	 }

     for (i = 1; i <= 4; i++) {
	         tempBox = (BoxButton) moveRowVector.elementAt(i-1);
	         tempBox.draw(g);  
	 }

     for (i = 1; i <= 4; i++) {
	         tempBox = (BoxButton) swapRowVector.elementAt(i-1);
	         tempBox.draw(g);  
	 }

     for (i = 1; i <= 5; i++) {
	         tempBox = (BoxButton) grayRowVector.elementAt(i-1);
	         tempBox.draw(g);  
	 }

     for (i = 1; i <= 4; i++) {
	         tempBox = (BoxButton) flipColumnVector.elementAt(i-1);
	         tempBox.draw(g);  
	 }

     for (i = 1; i <= 4; i++) {
	         tempBox = (BoxButton) moveColumnVector.elementAt(i-1);
	         tempBox.draw(g);  
	 }

     for (i = 1; i <= 4; i++) {
	         tempBox = (BoxButton) swapColumnVector.elementAt(i-1);
	         tempBox.draw(g);  
	 }

     for (i = 1; i <= 5; i++) {
	         tempBox = (BoxButton) grayColumnVector.elementAt(i-1);
	         tempBox.draw(g);  
	 }

     diagonalTLBR.draw(g);
     diagonalTRBL.draw(g);
     solutionButton.draw(g);
	 resetButton.draw(g);
	 
    }

    public void paint(Graphics g)
    {
        if (doubleBuffer)
        {
            paintApplet(gBuf);
            g.drawImage(buf, 0, 0, this);
        }
        else
        {
            paintApplet(g);
        }
    }

    public void update(Graphics g)
    {
        // override this because the default implementation always
        // calls clearRect first, causing unwanted flicker
        paint(g);
    }
   
   
   
   
}


/** Draws and maintains GridCell information. */
class GridCell {
	Color cellFillColor;				// color of the cell
	Color cellTextColor;				// color of the text
	int	cellHeight;				// height of the cell
	int	cellWidth;				// width of the cell
	int	cellTop;					// top left corner of the cell
	int	cellLeft;				// top left corner of the cell
	boolean cellTopBorder; 		// border flag for top side of cell
	boolean cellLeftBorder; 	// border flag for left side of cell
	boolean cellBottomBorder;	// border flag for bottom side of cell
	boolean cellRightBorder; 	// border flag for right side of cell
	int	cellValue;				// value to be displayed in the cell

	public void SetCellFillColor(Color theColor){
		this.cellFillColor =  theColor;
	}
	
	public void SetCellTextColor(Color theColor){
		this.cellTextColor =  theColor;
	}
	
	public void SetCellSize(int height, int width){
		this.cellHeight =  height;
		this.cellWidth =  width;
	}

	public void SetCellPosition(int top, int left){
		this.cellTop =  top;
		this.cellLeft =  left;
	}
	
	public void SetCellBorder(boolean top, boolean left, boolean bottom, boolean right){
		this.cellTopBorder =  top;
		this.cellLeftBorder =  left;
		this.cellBottomBorder =  bottom;
		this.cellRightBorder =  right;
	}
	
	public void SetCellValue(int theValue){
		this.cellValue =  theValue;
	}
	
	public void SetCellTotal(Vector theGrid, int columnRowDiagonal, int index){
		int i; 
		int column = 1;
   		int row = 2;
   		int diagonal = 3;
		GridCell tempCell;
		
		this.cellValue = 0;
		for (i = 1; i <= 4; i++){
			if (columnRowDiagonal == column){ //handle a column total
				tempCell = (GridCell) theGrid.elementAt(index + ((i - 1) * 4) - 1);
				this.cellValue = this.cellValue + tempCell.cellValue;
			}else if (columnRowDiagonal == row){ //handle a row total
				tempCell = (GridCell) theGrid.elementAt(i + ((index - 1) * 4) - 1);
				this.cellValue = this.cellValue + tempCell.cellValue;
			}else{ // handle a diagonal total
				if (index == 1){ // handle \ diagonal
					tempCell = (GridCell) theGrid.elementAt(i + ((i - 1) * 4) - 1);
					this.cellValue = this.cellValue + tempCell.cellValue;
				}else{ // handle / diagonal
					tempCell = (GridCell) theGrid.elementAt(i + (((5 - i) - 1) * 4) - 1);
					this.cellValue = this.cellValue + tempCell.cellValue;
				}
			}
		}
	} 

	boolean InsideBox(int x, int y){
		return ((x >= this.cellLeft) && (x <= (this.cellLeft + this.cellWidth)) && (y >= this.cellTop) && (y <= (this.cellTop + this.cellHeight)));
	}

	
	void draw(Graphics g) {
      g.setColor(this.cellFillColor);
      g.fillRect(this.cellLeft, this.cellTop, this.cellWidth, this.cellHeight);
      g.setColor(Color.black);
      if (this.cellTopBorder){
      	g.drawLine(this.cellLeft, this.cellTop , this.cellLeft + this.cellWidth,this.cellTop);
      }
      if (this.cellLeftBorder){
      	g.drawLine(this.cellLeft, this.cellTop , this.cellLeft ,this.cellTop + this.cellHeight);
      }
      if (this.cellBottomBorder){
      	g.drawLine(this.cellLeft, this.cellTop + this.cellHeight , this.cellLeft + this.cellWidth,this.cellTop + this.cellHeight);
      }
      if (this.cellRightBorder){
      	g.drawLine(this.cellLeft + this.cellWidth, this.cellTop , this.cellLeft + this.cellWidth,this.cellTop + this.cellHeight);
      }
      g.setColor(this.cellTextColor);
      g.drawString((this.cellValue) + "", this.cellLeft + (this.cellWidth * 1 / 3), this.cellTop + (this.cellHeight * 2 / 3));
   }
}

class TotalGridCell extends GridCell{

	void draw(Graphics g) {
	  if (this.cellValue == 34){
	  	g.setColor(Color.green);
	  }else{
	  	g.setColor(Color.red);
	  }
      g.fillRect(this.cellLeft, this.cellTop, this.cellWidth, this.cellHeight);
      g.setColor(Color.black);
      if (this.cellTopBorder){
      	g.drawLine(this.cellLeft, this.cellTop , this.cellLeft + this.cellWidth,this.cellTop);
      }
      if (this.cellLeftBorder){
      	g.drawLine(this.cellLeft, this.cellTop , this.cellLeft ,this.cellTop + this.cellHeight);
      }
      if (this.cellBottomBorder){
      	g.drawLine(this.cellLeft, this.cellTop + this.cellHeight , this.cellLeft + this.cellWidth,this.cellTop + this.cellHeight);
      }
      if (this.cellRightBorder){
      	g.drawLine(this.cellLeft + this.cellWidth, this.cellTop , this.cellLeft + this.cellWidth,this.cellTop + this.cellHeight);
      }
      g.setColor(this.cellTextColor);
      g.drawString((this.cellValue) + "", this.cellLeft + (this.cellWidth * 1 / 3), this.cellTop + (this.cellHeight * 2 / 3));
   }
}

class BoxButton{
int top, left, width, height;
Color color;

boolean InsideBox(int x, int y){
	return ((x >= this.left) && (x <= (this.left + this.width)) && (y >= this.top) && (y <= (this.top + this.height)));
}

void draw(Graphics g) {
      g.setColor(this.color);
      g.fillRect(this.left, this.top, this.width, this.height);
      g.setColor(Color.black);
      g.drawRect(this.left, this.top, this.width, this.height);
   }

}

class BoxButton3D extends BoxButton{
Color hitColor;
boolean buttonHit;
int bevel;

	void setColors(int red, int green, int blue, int hitRed, int hitGreen, int hitBlue){
		this.color = new Color(red, green, blue);
		this.hitColor = new Color(hitRed, hitGreen, hitBlue);
	}

	void setBevel(int bevel){
		this.bevel = bevel;
	}
	
	void setState(boolean hit){
		this.buttonHit = hit;
	}

	void draw(Graphics g) {
		Color topColor, leftColor, bottomColor, rightColor;
		Color saveColor, tempColor;
		int[] xPoints, yPoints;
		int tempRed, tempGreen, tempBlue;

		// lets save the current color and restore it later
		saveColor = g.getColor(); //save the current color
		xPoints = new int[4];
		yPoints = new int[4];
		
		if (this.buttonHit) {
			// draw with hitColor
			tempRed = hitColor.getRed();
			tempGreen = hitColor.getGreen();
			tempBlue = hitColor.getBlue();
		}else{
			// draw with color
			tempRed = color.getRed();
			tempGreen = color.getGreen();
			tempBlue = color.getBlue();		
		}
		//draw whole button
		tempColor = new Color(tempRed, tempGreen, tempBlue);
		g.setColor(tempColor);
		g.fillRect(this.left, this.top, this.width, this.height);
		
		//draw left bevel
		if (!this.buttonHit) {
			tempColor = BrightenColor(tempRed, tempGreen, tempBlue, 30);
		}else{
			tempColor = DarkenColor(tempRed, tempGreen, tempBlue, 30);
		}
		g.setColor(tempColor);
		xPoints[0] = this.left;
		yPoints[0] = this.top;
		xPoints[1] = this.left + this.bevel;
		yPoints[1] = this.top + this.bevel;
		xPoints[2] = this.left + this.bevel;
		yPoints[2] = this.top + this.height - this.bevel;
		xPoints[3] = this.left ;
		yPoints[3] = this.top + this.height;
		g.fillPolygon(xPoints, yPoints, 4);		
		
		//draw top bevel
		if (!this.buttonHit) {
			tempColor = BrightenColor(tempRed, tempGreen, tempBlue, 50);
		}else{
			tempColor = DarkenColor(tempRed, tempGreen, tempBlue, 50);
		}
		g.setColor(tempColor);
		xPoints[0] = this.left;
		yPoints[0] = this.top;
		xPoints[1] = this.left + this.width;
		yPoints[1] = this.top;
		xPoints[2] = this.left + this.width - this.bevel;
		yPoints[2] = this.top + this.bevel;
		xPoints[3] = this.left + this.bevel ;
		yPoints[3] = this.top + this.bevel;
		g.fillPolygon(xPoints, yPoints, 4);		

		//draw right bevel
		if (!this.buttonHit) {
			tempColor = DarkenColor(tempRed, tempGreen, tempBlue, 30);
		}else{
			tempColor = BrightenColor(tempRed, tempGreen, tempBlue, 30);
		}
		g.setColor(tempColor);
		xPoints[0] = this.left  + this.width - this.bevel ;
		yPoints[0] = this.top + this.bevel;
		xPoints[1] = this.left + this.width;
		yPoints[1] = this.top;
		xPoints[2] = this.left + this.width;
		yPoints[2] = this.top + this.height;
		xPoints[3] = this.left + this.width - this.bevel;
		yPoints[3] = this.top + this.height - this.bevel;
		g.fillPolygon(xPoints, yPoints, 4);		

		//draw bottom bevel
		if (!this.buttonHit) {
			tempColor = DarkenColor(tempRed, tempGreen, tempBlue, 50);
		}else{
			tempColor = BrightenColor(tempRed, tempGreen, tempBlue, 50);
		}
		g.setColor(tempColor);
		xPoints[0] = this.left + this.bevel;
		yPoints[0] = this.top + this.height - this.bevel;
		xPoints[1] = this.left + this.width - this.bevel;
		yPoints[1] = this.top + this.height - this.bevel;
		xPoints[2] = this.left + this.width;
		yPoints[2] = this.top + this.height;
		xPoints[3] = this.left;
		yPoints[3] = this.top + this.height;
		g.fillPolygon(xPoints, yPoints, 4);		

		g.setColor(Color.black);
		g.drawRect(this.left, this.top, this.width, this.height);
		
		//restore original color
		g.setColor(saveColor);
	}
	
	//method to brighten a color where amount is a percentage
	Color BrightenColor(int red, int green, int blue, int amount){
		Color newColor;
		
		newColor = new Color(red + (((255 - red) * amount)/ 100), 
							 green + (((255 - green) * amount) / 100),
							 blue + (((255 - blue) * amount) / 100));
		return newColor;
	
	}
	//method to darken a color where amount is a percentage

	Color DarkenColor(int red, int green, int blue, int amount){
		Color newColor;
		
		newColor = new Color(red - ((red * amount)/ 100), 
							 green - ((green * amount) / 100),
							 blue - ((blue * amount) / 100));
		return newColor;
	
	}
}

//