Minggu, 03 Agustus 2025

JAVA - MEMBUAT SOFTWARE SEPERTI EXCEL

 


DAFTAR FILE-FILE MEMBUAT EXCEL (FOLDER DIAMBIL DARI
NETBEANS PROJECT)



ArgValue.java

package spreadsheetapplet;


/* ArgValue.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/


import java.lang.*;


// This object contains variables that are used to define
// parameters about an argument value...
public class ArgValue {
public final static int UNDEFINED = 0;
public final static int LITERAL = 1;
public final static int CELL = 2;
   int type;
double litValue;  // For literal values...
int row;     // For cell values...
int column;
public ArgValue() {
type = UNDEFINED;
}

// Set arguments if it is literal...
public void setLiteral(double val) {
type = LITERAL;
      litValue = val;
}
// Set arguments if it is a cell...
public void setCell(int row, int column) {
type = CELL;
this.row = row;
      this.column = column;
}
// Return literal...
public double getLiteral() {
    return litValue;
}
// Return cell values...
public int getRow() {
return row;
}
public int getColumn() {
return column;
}
// Get the type...
public int getType() {
    return type;
}
}

==================================================
Cell.java

package spreadsheetapplet;


/* Cell.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/


// This file describes the Cell class that contains
// a string formula and evaluated value for an individual cell

import java.lang.*;


// A cell contains the formula about for an individual cell
// However, it does not know what to do with it and simply
// returns its contents...
public class Cell {
String s;
double evaluatedValue;
boolean evaluated;       // True if the cell has been evaluated
// Constructor creates empty StringBuffer as reference...
public Cell() {
s = "";
evaluatedValue = 0.0;
      evaluated = true;
}
// Takes a StringBuffer and makes it the cell's data...
public void setCellString(StringBuffer s) {
this.s = new String(s);
evaluated = false;
}
// Takes a StringBuffer and makes it the cell's data...
public void setCellString(String s) {
this.s = s;
evaluated = false;
}
// Return the current contents of the Cell
public String getCellString() {
return s;
}
// Set the evaluated value of a cell...
public void setEvalValue(double val) {
evaluated = true;
evaluatedValue = val;
}
// Set the evaluated value of a cell...
public void setEvalValue(int val) {
setEvalValue((double)val);
}
// See if a cell has been evaluated...
public boolean getEvaluated() {
    return evaluated;
}
// Get the evaluated value of a cell...
public double getEvalValue() {
    return evaluatedValue;
}
// Set a cell to unevaluated...
public void setEvaluated(boolean eval) {
evaluated = eval;
}
}

===========================================
CellContainer.java

package spreadsheetapplet;


/* CellContainer.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/



// This file describes the CellContainer class that contains
// a matrix of Cell data.  It is responsible for making sure
// that the formulas in the cells are evaluated properly...

import java.lang.*;
import java.io.*;


// The CellContainer class contains a matrix of Cell data.
// The class is responsible for making sure
// that the formulas in the cells are evaluated properly...
public class CellContainer {
int numRows;    // Number of rows in container...
int numColumns; // Number of columns...
Cell matrix[];  // Matrix of row/column Cells...
   int magicNumber = 0xF1082920;
   char delimiter = '\t'; // Save files a tab delimited...
   int maxRows = 25;  // Default maximum sizes...
   int maxColumns = 40;

// Constructs an empty container...
public CellContainer() {
numRows = 0;
numColumns = 0;
matrix = null;
}
// Constructs a matrix of cells [rows X columns]
public CellContainer(int rows,int columns) throws IllegalArgumentException {
numRows = rows;
numColumns = columns;
// Throw an exception if the row/col values are no good...
if ((numRows <= 0) || (numColumns <=0) ||
         (numRows > maxRows) || (numColumns > maxColumns) ) {
numRows = 0;
numColumns = 0;
matrix = null;
throw new IllegalArgumentException();
}

// Create the Cell matrix...
int numCells = numRows * numColumns;
matrix = new Cell[numCells];
for (int i = 0; i < numCells; ++i)
matrix[i] = new Cell();
}

   // Save the cell container to a file...
// Constructs the matrix by reading in data from the
   // given filename...
public CellContainer(String filename) throws IOException {
    // Call the code to read in a file
    // It will throw an exception if the data is bad...
    readFile(filename);
   }

// Sets the new value of a cell...
public void setCellFormula(StringBuffer s,int row,int col) {
setCellFormula(s.toString(),row,col);
}
// Sets the new value of a cell...
public void setCellFormula(String s,int row,int col) {
// Get the index into the matrix...
int index;
try {
index = getMatrixIndex(row,col);
}
catch (IllegalArgumentException e) {
System.out.println("Invalid CellContainer index.");
return;
}
// Set the value of the cell...
matrix[index].setCellString(s);
}


// Get the string contents of a cell...
public String getCellFormula(int row,int col)  throws IllegalArgumentException {
// Get the index into the matrix...
int index;
try {
index = getMatrixIndex(row,col);
}
catch (IllegalArgumentException e) {
throw e;
}
// Good index. Return string...
return matrix[index].getCellString();
}


// Get the cell at certain index...
public Cell getCell(int row,int col)  throws IllegalArgumentException {
// Get the index into the matrix...
int index;
try {
index = getMatrixIndex(row,col);
}
catch (IllegalArgumentException e) {
throw e;
}
// Good index. Return Cell...
return matrix[index];
}


// Calculate the matrix index given a row and column...
// Throw an exception if it is bad...
int getMatrixIndex(int row,int col) throws IllegalArgumentException {
// Kick out if there are negative indexes...
if ((row < 0) || (col <0))
throw new IllegalArgumentException();
// Also reject too large indexes...
if ((row >= numRows) || (col >= numColumns))
throw new IllegalArgumentException();
// Everything is ok.  Calculate index...
return ((numColumns * row) + col);
}

// Validate a formula by seeing if it matches the basic syntax...
public String validateFormula(Cell c,String newFormula) throws FormulaParserException {
// Convert all alphas to Upper Case
String convertedFormula = newFormula.toUpperCase();
// Get old formula of cell and temporarily set cell value there...
String oldFormula = c.getCellString();
// Setup the parser to validate the cell...
FormulaParser f = new FormulaParser(convertedFormula);
// Validate the cell...
try {  // Set up the formula parser...
// Get the type of formula it is...
int typeFormula = f.getType();
// If its empty return Success...
if (typeFormula == f.EMPTY)
return convertedFormula;
// Check to see if literal is valid...
if (typeFormula == f.LITERAL) {
f.getLiteral();  // Ignore the return value...
return convertedFormula;
} // end if
// If its a formula we need to parse it...
parseFormula(c,f);
}
catch (Exception e) {
throw new FormulaParserException();
}
// Return the converted string...
return convertedFormula;
}

// Recalculate the values in all of the cells...
public void recalculateAll() {
if (matrix == null)
return;
// Invalidate the formulas...
invalidateFormulas();
// Go through each cell and calculate its value...
// Go row-wise across as this is how things probably are setup
int i,j;
for (i = 0; i < numRows; ++i) {
for (j = 0; j < numColumns; ++j) {
if (matrix[(i * numColumns) + j].getEvaluated() == false) {
calculateCell(i,j);
}
} // end column for
} // end row for
}

// Recalculate an individual cell...
// Update its evaluation when complete...
double calculateCell(int row,int col) {
// Get the index of the calculation...
int index;
try {
index = getMatrixIndex(row,col);
}
catch (IllegalArgumentException e) {
return 0.0;  // Bad index...
}

// Setup the parser to recalculate the cell...
FormulaParser f = new FormulaParser(matrix[index].getCellString());
// First get the type...
int typeFormula = f.getType();
// If its empty, we're done...
if (typeFormula == f.EMPTY) {
matrix[index].setEvalValue(0.0);
return 0.0;
}
// If its a literal, we can also finish quickly...
if (typeFormula == f.LITERAL) {
// It better be some kind of number...
try {
double dbl = f.getLiteral(); // Get the double value...
matrix[index].setEvalValue(dbl);
return dbl;
}
// Some kind of invalid string...
catch(FormulaParserException e) {
System.out.println("Invalid literal at [" + row + "," + col + "]");
matrix[index].setEvalValue(0.0);
return 0.0;
}
}
// Formulas got to be parsed and maybe recurse, however...
double dbl;
try {
dbl = parseFormula(matrix[index],f);
}
catch (Exception e) {
System.out.println("Invalid formula at [ " + row + "," + col + "]");
dbl = 0.0;
}
matrix[index].setEvalValue(dbl);
System.out.println("Eval at [ " + row + "," + col + "] = " + dbl);
return dbl;
}

// Parse out a formula...
// Assumes formula parser is set to a certain formula...
double parseFormula(Cell c, FormulaParser f) throws FormulaParserException {
// Figure out what type of formula it is...
try {
int op = f.getOperation();
// Get the arguments...
ArgValue arg1 = new ArgValue();
ArgValue arg2 = new ArgValue();
f.getOpArgs(arg1,arg2);
// Sum operation is different from rest...
if (op != f.SUM) { // SUM is even worse...
double val1,val2;
// Get the values...
// See if we have to recurse...
if (arg1.getType() == arg1.CELL)
val1 = calculateCell(arg1.getRow(),arg1.getColumn());
else
val1 = arg1.getLiteral();
if (arg2.getType() == arg1.CELL)
val2 = calculateCell(arg2.getRow(),arg2.getColumn());
else
val2 = arg2.getLiteral();
System.out.println("Val1 = " + val1 + " Val2 = " + val2);
// Perform the operation...
switch (op) {
case FormulaParser.ADD:
return (val1 + val2);
case FormulaParser.MULT:
return (val1 * val2);
case FormulaParser.DIV:
try {
double ret = val1 / val2;
return ret;
}
catch (ArithmeticException e) {
// Divide by zero!
return 0.0;
}
case FormulaParser.SUB:
return (val1 - val2);
default:
break;
}  // end switch...
} // end if
else {  // Sum...
double dbl = 0.0;
int index;
if ((arg1.getType() != arg1.CELL) || (arg2.getType() != arg2.CELL))
throw new FormulaParserException();
// Row-wise or column wise...
if (arg1.getRow() == arg2.getRow()) {
if (arg2.getColumn() < arg1.getColumn())
throw new FormulaParserException();
for (int i = arg1.getColumn(); i <= arg2.getColumn(); ++i) {
// Skip cases where the cells are the same...
index = getMatrixIndex(arg2.getRow(),i);
if (matrix[index] == c)
continue;
                     // If Ok, then recurse...
dbl += calculateCell(arg2.getRow(),i);
} // end for
return dbl;
}
else if (arg1.getColumn() == arg2.getColumn()) {
if (arg2.getRow() < arg1.getRow())
throw new FormulaParserException();
for (int i = arg1.getRow(); i <= arg2.getRow(); ++i) {
// Skip cases where the cells are the same...
index = getMatrixIndex(i,arg2.getColumn());
if (matrix[index] == c)
continue;
                     // If Ok, then recurse...
dbl += calculateCell(i,arg2.getColumn());
               } // end for
return dbl;
}
throw new FormulaParserException();
}
return 0.0;
}
catch (FormulaParserException e) {
throw e;
}
}

           
// Invalidate all cells that are formulas to force recalculation...
void invalidateFormulas() {
// Setup the parser to get the cell type...
FormulaParser f = new FormulaParser();
int numCells = numRows * numColumns;
for (int i = 0; i < numCells; ++i) {
f.setFormula(matrix[i].getCellString());
if (f.getType() == f.FORMULA)
matrix[i].setEvaluated(false);
} // end for
}

// Get the number of rows in the container
int getNumRows() {
return numRows;
}

// Get the number of columns in the container
int getNumColumns() {
return numColumns;
}

   // Read in a file and create a new matrix to
   // accomodate the data...
   public void readFile(String filename) throws IOException {
      // Set everything to empty...
numRows = 0;
numColumns = 0;
      int magic;
      byte b;
      DataInputStream fs;
      try {
         // Open the file...
         fs = new DataInputStream(new BufferedInputStream(
            new FileInputStream(filename)) );
      }
      // Can't open file, quit out...
      catch (IOException e) {
         throw e;
      }
      // Now try to load the data...
      try {
           // Check the magic number
           magic  = fs.readInt();
           if (magic != magicNumber)
               throw (new IOException("Invalid magic number"));
           // Get the rows and columns...
           numRows = fs.readInt();
           numColumns = fs.readInt();
           if ((numRows <= 0) || (numColumns <=0) ||
            (numRows > maxRows) || (numColumns > maxColumns) )
               throw (new IOException("Invalid row/col settings"));
           int numCells = numRows * numColumns;
           // Allocate matrix...
           matrix = new Cell[numCells];
           // Now load the individual cells...
           for (int i = 0; i < numCells; ++i) {
               // Load the string up until delimited...
               StringBuffer s = new StringBuffer();
               while ((b = fs.readByte()) != delimiter)
                     s.append((char)b);
               // Add it to new Cell...
               matrix[i] = new Cell();
               matrix[i].setCellString(s);
           } // end for
           // Success! Close the file and leave...
           fs.close();
      }
      // If exception then close file,
      // and reset everything...
      catch (IOException e) {
    numRows = 0;
    numColumns = 0;
         fs.close();
         throw e;
      }
   }

   // Save the cell container to a file...
   public void saveFile(String filename) throws IOException {
      // Perform these file operations.  If anything goes wrong
      // an exception will be thrown.  This must be caught
      // by the calling method...
      // Open the file...
      DataOutputStream fs = new DataOutputStream(
// !! Insert BufferedOutput here!!
            new FileOutputStream(filename));
      // Write out magic number
      fs.writeInt(magicNumber);
      // Write out row and column sizes
      fs.writeInt(numRows);
      fs.writeInt(numColumns);

      // Now go through each row and column and save...
      // Write out literal value followed by delimited...
int numCells = numRows * numColumns;
    for (int i = 0; i < numCells; ++i) {
         fs.writeBytes(matrix[i].getCellString());
         fs.writeByte(delimiter);
      } // end for
 
      // Close the file. We're done!
      fs.close();
   }
}
================================
ChooseColorDialog.java


package spreadsheetapplet;


/* ChooseColorDialog.java Author Casey Hopson
   Geist Software and Services, Inc. 
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/



import java.awt.*;
import java.lang.*;



// Dialog box for choosing display colors...
public class ChooseColorDialog extends Dialog {
SpreadsheetFrame fr;   // What to update...
   ColoredCheckboxGroup colorGrp;  // To hold radio buttons of colors...
   SpreadsheetContainer s;
   List choiceList;  // List of color choices...
   colorDisplay d; // This is the text display...
   // Defines for listbox values...
   static int NORMAL_FORE = 0;
   static int NORMAL_BACK = 1;
   static int HILITE_FORE = 2;
   static int HILITE_BACK = 3;
   // Construct dialog to allow color to be chosen...
public ChooseColorDialog(Frame parent,boolean modal) {
// Create dialog with title
super(parent,"Color Dialog",modal);
fr = (SpreadsheetFrame)parent;
      // Create the dialog components...
      createComponents();
pack();  // Compact...
      // Resize to fit everything...
      resize(preferredSize());
}

   // Wait for Cancel or OK buttons to be chosen...
public boolean handleEvent(Event e) {
switch(e.id) {
       case Event.ACTION_EVENT:
         // Kill the dialog...
    if (e.arg.equals("Cancel")) {
    dispose();  // Remove Dialog...
    return true;
    }  // end if
         // Update colors on the spreadsheet...
    if (e.arg.equals("Update")) {
            setSpreadsheetColors();
    return true;
    }  // end if
         if (e.target instanceof Checkbox) {
            selectedRadioItem();
            return false;
         }
         return false;
       // User selected a listbox item...
       case Event.LIST_SELECT:
         // Set up caption colors and color choice highlight...
         if (e.target instanceof List) {
            selectedChoiceListItem();
            return false;
         }  // end list if
         return false;
       default:
         return false;
      } // end switch
}

   // The layout will call this to get the preferred size
   // of the dialog.  Make it big enough for the listbox text
   // the checkboxes, canvas, and buttons...
   public Dimension preferredSize() {
      // Get the metrics of the current font...
      FontMetrics fm = getFontMetrics(getFont());
      int width = 3 * fm.stringWidth("Highlighted foreground");
      int height = 24 * fm.getHeight();
      return new Dimension(width,height);
   }

   // Create the main display panel...
   void createComponents() {
    // Use gridbag constraints...
    GridBagLayout g = new GridBagLayout();
    setLayout(g);
GridBagConstraints gbc = new GridBagConstraints();
    // Set the constraints for the top objects...
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.gridheight = 10;

    // Add the listbox of choices...
    choiceList = new List();
    choiceList.addItem("Normal foreground");
    choiceList.addItem("Normal background");
    choiceList.addItem("Highlighted foreground");
    choiceList.addItem("Highlighted background");
g.setConstraints(choiceList,gbc);
add(choiceList);

    // Create the checkbox panel
    Panel checkboxPanel = new Panel();
    checkboxPanel.setLayout(new GridLayout(12,1));
    // Create the checkbox group and add radio buttons...
    colorGrp = new ColoredCheckboxGroup(checkboxPanel);
    colorGrp.setMatchingColor(Color.magenta);

    // Create add checkbox panel to right...
gbc.gridwidth = GridBagConstraints.REMAINDER;
g.setConstraints(checkboxPanel,gbc);
add(checkboxPanel);

    // Display the color chosen...
    d = new colorDisplay("This is how the text looks.");

    // Add to grid bag...
gbc.weighty = 0.0;
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
g.setConstraints(d,gbc);
    add(d);

    // Two buttons: "Update" and "Cancel"
    Panel p = new Panel();
    p.add(new Button("Update"));
    p.add(new Button("Cancel"));

    // Add to grid bag...
gbc.gridwidth = GridBagConstraints.REMAINDER;
g.setConstraints(p,gbc);
    add(p);
   }

// Setup defaults upon showing...
public synchronized void show() {
super.show(); // Call the default constructor...
      // Get the spreadsheet container...
      s = fr.getSpreadsheetContainer();
      // Set the listbox default...
      choiceList.select(0);
      // Set up caption colors and color choice highlight...
      selectedChoiceListItem();
}

   // Set up caption colors and color choice highlight
   // according to current listbox value...
   private void selectedChoiceListItem() {
      Color fore,back;  // Display canvas colors
      // If normal set canvas colors...
      int index = choiceList.getSelectedIndex();
      if ((index == NORMAL_FORE) || (index == NORMAL_BACK)) {
         fore = s.getNormalForeColor();
         back = s.getNormalBackColor();
      }
      // Otherwise its the background...
      else {
         fore = s.getHighlightedForeColor();
         back = s.getHighlightedBackColor();
      }
      // Update the canvas...
      d.setForeColor(fore);
      d.setBackColor(back);
      d.repaint();
      // Update the color radio buttons...
      Color radioColor;
      // Even numbers are fore, odd are back...
      if ((index % 2) == 0)
         radioColor = fore;
      else
         radioColor = back;
      colorGrp.setMatchingColor(radioColor);
   }

   // Update display canvas when radio color changes...
   private void selectedRadioItem() {
      // Get choice from Color box...
      ColoredCheckbox box = (ColoredCheckbox)colorGrp.getCurrent();
      Color color = box.getColor();
      // If normal set canvas colors...
      Color fore,back;
      int index = choiceList.getSelectedIndex();
      // Set background or foreground color based on
      // current listbox selection...
      if ((index == NORMAL_FORE) || (index == HILITE_FORE))
         d.setForeColor(color);
      else
         d.setBackColor(color);
      // Repaint the canvas...
      d.repaint();
   }

   // Update the spreadsheet colors...
   public void setSpreadsheetColors() {
      // Store all the default colors...
      Color normalFore,normalBack;
      Color hiliteFore,hiliteBack;
      normalFore = s.getNormalForeColor();
      normalBack = s.getNormalBackColor();
      hiliteFore = s.getHighlightedForeColor();
      hiliteBack = s.getHighlightedBackColor();
      // Get choice from Color box...
      ColoredCheckbox box = (ColoredCheckbox)colorGrp.getCurrent();
      Color color = box.getColor();
      // Get the current selection...
      int index = choiceList.getSelectedIndex();
      if (index == NORMAL_FORE)
            normalFore = color;
      else if (index == NORMAL_BACK)
            normalBack = color;
      else if (index == HILITE_FORE)
            hiliteFore = color;
      else
            hiliteBack = color;
      // Update the spreadsheet!
      s.setNewColors(normalFore,normalBack,hiliteFore,hiliteBack);
   }

}

// A small class that illustrates the
// current highlight and background
class colorDisplay extends Canvas {
   String displayText;
   Color foreground;  // The colors to be displayed...
   Color background;
   // Construct the display by storing the
   // text to be displayed...
   public colorDisplay(String displayText) {
      super();
      this.displayText = displayText;
      foreground = null;
      background = null;
   }
   // Set the foreground and background display
   public void setForeColor(Color fgd) {
      foreground = fgd;
   }
   public void setBackColor(Color bgd) {
      background = bgd;
   }

   // The layout will call this to get the minimum size
   // of the object.  In this case we want it to be at
   // least big enough to fit the display test...
   public Dimension minimumSize() {
      // Get the metrics of the current font...
      FontMetrics fm = getFontMetrics(getFont());
      return new Dimension(fm.stringWidth(displayText),
         2 * fm.getHeight());
   }

   // Paint the colors and text...
   public synchronized void paint(Graphics g) {
      if ((foreground == null) || (background == null))
         return;
      // Set background...
Dimension dm = size();
g.setColor(background);
g.fillRect(0,0,dm.width,dm.height);
// Draw the string
g.setColor(foreground);
      // Set dimensions. Move just from left...
      FontMetrics fm = getFontMetrics(getFont());
      int x = fm.charWidth('W');
      // And center in height...
      int y = fm.getHeight();
g.drawString(displayText,x,y);
   }
}


// Class that creates a series of radio buttons
// for Colors to choose....
class ColoredCheckboxGroup extends CheckboxGroup {
   // Array to hold checkboxes...
   ColoredCheckbox c[] = new ColoredCheckbox[12];
   // Constructor. Create the checkboxes with
   // no default color chosen...
   public ColoredCheckboxGroup(Panel p) {
      // Call the default constructor...
      super();
      // Create the checkboxes and store references...
      c[0] = new ColoredCheckbox(Color.black,"Black",this,false);
      p.add(c[0]);
      c[1] = new ColoredCheckbox(Color.cyan,"Cyan",this,false);
      p.add(c[1]);
      c[2] = new ColoredCheckbox(Color.blue,"Blue",this,false);
      p.add(c[2]);
      c[3] = new ColoredCheckbox(Color.darkGray,"Dark Gray",this,false);
      p.add(c[3]);
      c[4] = new ColoredCheckbox(Color.pink,"Pink",this,false);
      p.add(c[4]);
      c[5] = new ColoredCheckbox(Color.green,"Green",this,false);
      p.add(c[5]);
      c[6] = new ColoredCheckbox(Color.lightGray,"Light Gray",this,false);
      p.add(c[6]);
      c[7] = new ColoredCheckbox(Color.magenta,"Magenta",this,false);
      p.add(c[7]);
      c[8] = new ColoredCheckbox(Color.red,"Red",this,false);
      p.add(c[8]);
      c[9] = new ColoredCheckbox(Color.white,"White",this,false);
      p.add(c[9]);
      c[10] = new ColoredCheckbox(Color.orange,"Orange",this,false);
      p.add(c[10]); 
      c[11] = new ColoredCheckbox(Color.yellow,"Yellow",this,false);
      p.add(c[11]);
   }

   // Set the radio button of the checkbox that
   // matches the color
   public void setMatchingColor(Color match) {
      for (int i = 0; i < c.length; ++i)
         c[i].setIfColorMatches(match);
   }
}


// Class for creating a checkbox associated
// with a given color...
class ColoredCheckbox extends Checkbox {
   Color color;  // The color of this checkbox...
   // Constructor creates checkbox with specified color...
   public ColoredCheckbox(Color color, String label,
         CheckboxGroup grp, boolean set) {
         // Call the default constructor...
         super(label,grp,set);
         this.color = color;
         setBackground(color);
   }
   // Sets itself to true if it matches the color
   public void setIfColorMatches(Color match) {
      if (color == match)
         setState(true);
      else
         setState(false);
   }
   // Return the color matching this box...
   public Color getColor() {
      return color;
   }
}



======================================================
 ChooseFontDialog.java

package spreadsheetapplet;


/* ChooseFontDialog.java Author Casey Hopson
   Geist Software and Services, Inc. 
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/



import java.awt.*;
import java.lang.*;



// Dialog box for choosing display colors...
public class ChooseFontDialog extends Dialog {
SpreadsheetFrame fr;   // What to update...
   SpreadsheetContainer s;
   List choiceList;  // List of color choices...
   fontDisplay d; // This is the text display...
   Choice choiceSize;  // Size of font...
   Checkbox checkItalics;
   Checkbox checkBold;
   Font currentFont;  // Current font in sample...
   Font defaultFont; // Store font dialog was created with...
   // Construct dialog to allow color to be chosen...
public ChooseFontDialog(Frame parent,boolean modal) {
// Create dialog with title
super(parent,"Font Dialog",modal);
fr = (SpreadsheetFrame)parent;
      defaultFont = getFont();
      // Create the dialog components...
      createComponents();
}

   // Get the default font and set up display...
   private void setDefaultFont() {
      // Get the latest spreadsheet font...
      currentFont = s.getFont();
      // Get default list...
      String s = currentFont.getName();
      int index = findListString(choiceList,s);
      if (index >= 0)
            choiceList.select(index);
      else
            choiceList.select(0);
      // Get default size
      int sizeFont = currentFont.getSize();
      index = findChoiceString(choiceSize,
         String.valueOf(sizeFont));
      if (index >= 0)
            choiceSize.select(index);
      else
            choiceSize.select(0);
      // Set the style displays...
      int styleFont = currentFont.getStyle();
      if ((styleFont & Font.BOLD) != 0)
             checkBold.setState(true);
      else
             checkBold.setState(false);
      if ((styleFont & Font.ITALIC) != 0)
             checkItalics.setState(true);
      else
             checkItalics.setState(false);
      // Set the canvas style...
      d.setFont(currentFont);
   }


   // Wait for Cancel or OK buttons to be chosen...
public boolean handleEvent(Event e) {
switch(e.id) {
       case Event.ACTION_EVENT:
         // Kill the dialog...
    if (e.arg.equals("Cancel")) {
    dispose();  // Remove Dialog...
    return true;
    }  // end if
         // Update colors on the spreadsheet...
    if (e.arg.equals("OK")) {
            s.setFont(currentFont);
            dispose();
    return true;
    }  // end if
         if (e.target instanceof Choice) {
            paintSample();
            return false;
         }  // end list if
         if (e.target instanceof Checkbox) {
            paintSample();
            return false;
         }  // end list if
         return false;
       // User selected a listbox item...
       case Event.LIST_SELECT:
         // Set up caption colors and color choice highlight...
         if (e.target instanceof List) {
            paintSample();
            return false;
         }  // end list if
         return false;
       default:
         return false;
      } // end switch
}

   // The layout will call this to get the preferred size
   // of the dialog.  Make it big enough for the listbox text
   // the checkboxes, canvas, and buttons...
   public Dimension preferredSize() {
      // Get the metrics of the current font...
      FontMetrics fm = getFontMetrics(getFont());
      int width = 3 * fm.stringWidth("Highlighted foreground");
      int height = 14 * fm.getHeight();
      return new Dimension(width,height);
   }

   // Create the main display panel...
   private void createComponents() {
    // Use gridbag constraints...
    GridBagLayout g = new GridBagLayout();
    setLayout(g);
GridBagConstraints gbc = new GridBagConstraints();
    // Set the constraints for the top objects...
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.gridheight = 10;

    // Add the listbox of choices...
    // Get the selection from the toolkit...
    choiceList = new List();
    String fontList[] = Toolkit.getDefaultToolkit().getFontList();
    for (int i = 0; i < fontList.length; ++i)
       choiceList.addItem(fontList[i]); 
g.setConstraints(choiceList,gbc);
add(choiceList);

    // Set the default values...
gbc.weighty = 0.0;
gbc.weightx = 1.0;
gbc.gridheight = 1;
gbc.gridwidth = GridBagConstraints.REMAINDER;

    // Create a label for display...
    Label l = new Label("Size:");

    // Add to grid bag...
g.setConstraints(l,gbc);
    add(l);

    // Create the choice box...
    choiceSize = new Choice();
    choiceSize.addItem("8");
    choiceSize.addItem("10");
    choiceSize.addItem("12");
    choiceSize.addItem("14");
    choiceSize.addItem("16");
    choiceSize.addItem("20");

    // Add to grid bag...
g.setConstraints(choiceSize,gbc);
    add(choiceSize);

    // Add Italics...
    checkItalics = new Checkbox("Italics");
g.setConstraints(checkItalics,gbc);
    add(checkItalics);

    // Add Bold...
    checkBold = new Checkbox("Bold");
g.setConstraints(checkBold,gbc);
    add(checkBold);

    // Display the color chosen...
    d = new fontDisplay("Sample Text");

    // Add to grid bag...
g.setConstraints(d,gbc);
    add(d);

    // Two buttons: "OK" and "Cancel"
    Panel p = new Panel();
    p.add(new Button("OK"));
    p.add(new Button("Cancel"));

    // Add to grid bag...
gbc.gridwidth = GridBagConstraints.REMAINDER;
g.setConstraints(p,gbc);
    add(p);
   }

// Setup defaults upon showing...
public synchronized void show() {
super.show(); // Call the default constructor...
      // Get the spreadsheet container...
      s = fr.getSpreadsheetContainer();
      // Set the font dialog started off with...
      setFont(defaultFont);
      // Set up defaults...
      setDefaultFont();
pack();  // Compact...
      // Resize to fit everything...
      resize(preferredSize());
}

   // Repaint the sample canvas...
   private synchronized void paintSample() {
      // Get all the users selections....
      String fontName = choiceList.getSelectedItem();
      String fontSize = choiceSize.getSelectedItem();
      int fontStyle = Font.PLAIN;
      if (checkItalics.getState())
            fontStyle += Font.ITALIC;
      if (checkBold.getState())
            fontStyle += Font.BOLD;
      // Set the new font on the canvas...
      currentFont = new Font(fontName,fontStyle,
            Integer.parseInt(fontSize));
      d.setFont(currentFont);
      d.repaint();
   }

   // Return index of string in list...
   // -1 means not found
   public int findListString(List l,String s) {
      for (int i = 0; i < l.countItems(); ++i) {
         if (s.equals(l.getItem(i)) )
            return i;
      }
      return -1;
   }

   // Return index of string in choice...
   // -1 means not found
   public int findChoiceString(Choice c,String s) {
      for (int i = 0; i < c.countItems(); ++i) {
         if (s.equals(c.getItem(i)) )
            return i;
      }
      return -1;
   }
}

// A small class that illustrates the
// current highlight and background
class fontDisplay extends Canvas {
   String displayText;
   // Construct the display by storing the
   // text to be displayed...
   public fontDisplay(String displayText) {
      super();
      this.displayText = displayText;
   }
   // The layout will call this to get the minimum size
   // of the object.  In this case we want it to be at
   // least big enough to fit the display test...
   public Dimension minimumSize() {
      // Get the metrics of the current font...
      FontMetrics fm = getFontMetrics(getFont());
      return new Dimension(fm.stringWidth(displayText),
         4 * fm.getHeight());
   }

   // Paint the colors and text...
   public synchronized void paint(Graphics g) {
      // Set background...
Dimension dm = size();
g.setColor(Color.white);
g.fillRect(0,0,dm.width,dm.height);
// Draw the string
g.setColor(Color.black);
      // Set dimensions. Move just from left...
      FontMetrics fm = getFontMetrics(getFont());
      int x = fm.charWidth('I');
      // And center in height...
      int y = fm.getHeight();
g.drawString(displayText,x,y);
   }
}


========================================================
FormulaParser.java

package spreadsheetapplet;


/* FormulaParser.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/


// This file holds the class that is used for parsing
// Cell formulas...

import java.lang.*;


// This class is used to parse a single formula at a time.
// It uses internal hints to keep track of the current position
// in the name of performance.  Misuse of this parser could result
// in unexpected results.
public class FormulaParser {
// Set up codes for types of formulas
public final static int EMPTY = 0;
public final static int LITERAL = 1;
public final static int FORMULA = 2;
// Here are the formula operations...
final static String sSUM = "SUM";
final static String sADD = "ADD";
final static String sSUB = "SUB";
final static String sMULT = "MULT";
final static String sDIV= "DIV";
public final static int INVALID_OPERATION = 0;
public final static int SUM = 1;
public final static int ADD = 2;
public final static int SUB = 3;
public final static int MULT = 4;
public final static int DIV = 5;

// Internal fields...
String formula;
int index;  // Last char looked at...
   int lParen;  // First lParen in the expression...
int operation;  // The current operations
// Constructors...
public FormulaParser() {
formula = null;
}
public FormulaParser(String formula) {
setFormula(formula);
}
//  Set a new formula to use...
public void setFormula(String formula) {
    // Remove white spaces...
this.formula = formula.trim();
index = 0;
}

// Figure out what type of Formula this is...
public int getType() {
// Return empty if there is nothing there...
if (formula.length() == 0)
return EMPTY;
// See if it is a formula by looking for lparen...
if ((lParen = formula.indexOf( '(' ) ) > 0) {
return FORMULA;
      } // end if
return LITERAL;
}

// Find the type of operation being performed...
public int getOperation() throws FormulaParserException {
String op = formula.substring(0,lParen);
if (op.compareTo(sSUM) == 0) {
operation = SUM;
return operation;
} // end if
if (op.compareTo(sADD) == 0) {
operation = ADD;
return operation;
} // end if
if (op.compareTo(sSUB) == 0) {
operation = SUB;
return operation;
} // end if
if (op.compareTo(sMULT) == 0) {
operation = MULT;
return operation;
} // end if
if (op.compareTo(sDIV) == 0) {
operation = DIV;
return operation;
} // end if

operation = INVALID_OPERATION;
throw new FormulaParserException();
}

// Get arguments for a simple numeric operation...
public void getOpArgs(ArgValue arg1,ArgValue arg2) throws FormulaParserException {
int sep, rParen;
// Find where separator is...
if ((sep = formula.indexOf(',',lParen)) < 0)
throw new FormulaParserException();
// Find the rparen
if ((rParen = formula.indexOf(')',sep)) < 0)
throw new FormulaParserException();
// See what between these...
try {
setArg(arg1,formula.substring(lParen + 1,sep).trim());
setArg(arg2,formula.substring(sep + 1,rParen).trim());
}
catch (FormulaParserException e){
throw e;
}
}

// Set the argument values for part of a formula
void setArg(ArgValue arg,String s) throws FormulaParserException {
// If first char is a digit then it needs to be a literal...
if (Character.isDigit(s.charAt(0)) ) {
// Convert to a number!
try {
Double d = new Double(s);  // Parse the string...
arg.setLiteral(d.doubleValue()); // Get the double value..
return;
}
// Some kind of invalid string...
catch(NumberFormatException e) {
throw new FormulaParserException();
}
}  // end # if
else {
// Convert the alpha to the row...
try {
int row = ((int)(s.charAt(0))) - 'A';
Integer iCol = new Integer(s.substring(1));
int col = iCol.intValue();
            arg.setCell(row,col);
// Some kind of invalid string...
catch(NumberFormatException e) {
throw new FormulaParserException();
}
} // end else
}

// Get a literal value...
public double getLiteral() throws FormulaParserException {
try {
Double d = new Double(formula);  // Parse the string...
double dbl = d.doubleValue(); // Get the double value...
return dbl;
}
// Some kind of invalid string...
catch(NumberFormatException e) {
throw new FormulaParserException();
}
}

}

==================================

FormulaParserException.java

package spreadsheetapplet;


/* FormulaParserException.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/



import java.lang.*;

// This class is an Exception thrown when a
// formula is an invalid format...
public class FormulaParserException extends IllegalArgumentException { }

=======================================

GraphData.java


package spreadsheetapplet;


/* GraphData.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/



import java.lang.*;

// This class encapsulates the data that is used to
// create graphs...
// Assumes data and headings arrays are the same size...
public class GraphData {
   double data[];   // The data to be plotted
   String headings[];  // The headings associated with the data...
   // Constructor stores data created elsewhere...
   public GraphData(double data[],String headings[]) {
      this.data = data;
      this.headings = headings;
   }
   // Accessor functions...
   public int size() {
      return data.length;
   }
   // Return double value at an index...
   public double getData(int index) {
      return data[index];
   }
   // Return heading at an index...
   public String getHeading(int index) {
      return headings[index];
   }
}

===================================================
GraphDialog.java


package spreadsheetapplet;


/* GraphDialog.java Author Casey Hopson
   Geist Software and Services, Inc. 
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/



import java.awt.*;
import java.lang.*;



// Dialog box for choosing display colors...
public class GraphDialog extends Dialog {
    // Types of graphs...
   static final int LINE_GRAPH = 0;
   static final int BAR_GRAPH = 1;
   GraphCanvas gc;

   // Construct dialog that shows a graph of data...
public GraphDialog(Frame parent,boolean modal) {
// Create dialog with title
super(parent,"Display Graph",modal);
      setLayout(new BorderLayout());

      // Create Graphic display object and Button
      gc = new GraphCanvas();
      add("Center",gc);
      add("South",new Button("Done"));
      // Pack and set to be most of the screen...
      pack();
      // Get the screen dimensions...
      Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
      // Get the font and use to calculate some margins...
      FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(getFont());
      resize(screen.width,screen.height - (4 * fm.getHeight()) );
}


   // Wait for Cancel or OK buttons to be chosen...
public boolean handleEvent(Event e) {
switch(e.id) {
       case Event.ACTION_EVENT:
         // Kill the dialog...
    if (e.arg.equals("Done")) {
    dispose();  // Remove Dialog...
    return true;
    }  // end if
         return false;
       default:
         return false;
      } // end switch
}


// Setup defaults upon showing...
public synchronized void show(GraphData gphData,int graphMode) {
      // Set up the appropriate graph...
      gc.prepareNewGraph(gphData,graphMode);
      // Show the graph...
      super.show();
}

}


// This paints a graph on a canvas...
class GraphCanvas extends Canvas {
    // Types of graphs...
   static final int LINE_GRAPH = 0;
   static final int BAR_GRAPH = 1;
   int graphMode;
   Color randomColors[];
   // This is the data for the display..
   GraphData gd;
   // Maximum scale of graph...
   int maxValue;

   // Constructor just inits data...
public GraphCanvas() {
      gd = null;
      // Store the random colors...
      randomColors = new Color[6];
      randomColors[0] = Color.yellow;
      randomColors[1] = Color.red;
      randomColors[2] = Color.green;
      randomColors[3] = Color.magenta;
      randomColors[4] = Color.cyan;
      randomColors[5] = Color.blue;
   }
   // Set up graphics display...
   void prepareNewGraph(GraphData gphData,int graphMode) {
      // Store the data and string values...
      gd = gphData;
      this.graphMode = graphMode;
      // First calculate maximum value of graph...
      maxValue = calculateMaxValue();
   }

   // Calculate the maximum value of the graph...
   int calculateMaxValue() {
      double maximum = 0.0;
      double data;
      int temp,roundMax;
      // First get maximum figure...
      int length = gd.size();
      for (int i = 0; i < length; ++i) {
         data = gd.getData(i);
         if (data > maximum)
            maximum = data;
      } // end for
      // Now round it up to nearest power of 10
      roundMax = 1;
      for (temp = (int)maximum;temp > 0; temp /= 10)
         roundMax *= 10;
      return roundMax;
   }


   //  Draw the graph...
   public synchronized void paint (Graphics g) {
      if (gd == null)
         return;
      Dimension dm = size();

      // Calculate margins...
      int height = g.getFontMetrics().getHeight();
      int ymargin = 3 * height;
      int xmargin = g.getFontMetrics().stringWidth("1112345.67");
      int length = gd.size();

      // Select bottom-left origin
      Point origin = new Point(xmargin,dm.height - ymargin);

      // Draw X-Axis line
      int endx = dm.width - xmargin;
      g.drawLine(origin.x,origin.y,endx,origin.y);

      // Draw Y-Axis line
      g.drawLine(origin.x,ymargin,origin.x,origin.y);

      // Calculate how headers are spread out...
      int yIncrement = (origin.y - ymargin)/10;
      int xIncrement = (endx - origin.x) / (length + 1);

      // Draw horizontal axis headers
      int i,x;
      int yMarkStart = origin.y + height;
      int yTextStart = yMarkStart + height;
      for (i = 1; i < (length + 1); ++i) {
         // Draw marker...
         x = origin.x + (xIncrement * i);
         g.drawLine(x,yMarkStart,x,origin.y);
         // Print value header...
         g.drawString(gd.getHeading(i - 1),x,yTextStart);
      }

      // Draw vertical axis headers...
      int y;
      int inset = g.getFontMetrics().charWidth('W');
      int xMarkStart = origin.x - inset;
      int xTextStart = inset;
      int dataIncrement = maxValue / 10;
      String yHeader;
      for (i = 0; i <= 10; ++i) {
         // Draw marker...
         y = origin.y - (i * yIncrement);
         g.drawLine(xMarkStart,y,origin.x,y);
         // Print increment header...
         yHeader = String.valueOf(dataIncrement * i);
         g.drawString(yHeader,xTextStart,y);
      }

      // Call Graphic specific drawing..
      int vertLength = origin.y - ymargin;
      double dbLen = (double)randomColors.length;
      int index;
      int rectOffset = xIncrement / 2; // For bar graphs...
      Point lastPt = null;
      for (i = 1; i < (length + 1); ++i) {
         // Plot points, connecting points with lines...
         x = origin.x + (xIncrement * i);
         y = origin.y - (int)((gd.getData(i - 1)/maxValue) * vertLength);
         // Randomize colors...
         index = (int)(dbLen * Math.random());
         g.setColor(randomColors[index]);
         // If line graph draw connecting lines...
         if (graphMode == LINE_GRAPH) {
              if (lastPt != null)
                  g.drawLine(lastPt.x,lastPt.y,x,y);
              lastPt = new Point(x,y);
         }
         // Otherwise, bar graph draw rectangle...
         else {
              g.fillRect(x - rectOffset,y,xIncrement,origin.y - y);
         }
      } // end for
   }
}




=======================================================
Spreadsheet.html

<title>Spreadsheet Applet A</title>

<hr>

<applet code="SpreadsheetApplet" width=300 height=20>

<PARAM NAME=filesEnabled VALUE="true">

</applet>

<hr>

<a href="SpreadsheetApplet.java">The source.</a>

=======================================================

SpreadsheetApplet.java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package spreadsheetapplet;

/* SpreadsheetApplet.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/



// This file describes the applet class that manages the
// spreadsheet program.

import java.awt.*;
import java.io.*;
import java.lang.*;
import java.applet.*;


//  This applet kicks off the SpreadsheetFrame
//  which manages the spreadsheet program.


// This is the frame that controls that user interaction
// with the applet.  It creates the initial spreadsheet data
// and visual container, along with the input field for
// changing values of a cell, the scrollbars, and the menus
public class SpreadsheetApplet extends Applet  {
  SpreadsheetFrame fr;
  public void init() {
int rows = 25;  // Default sizes...
int cols = 40;
    // Get parameter to see if we should enable
    // local file enabling...
    boolean enableFiles = false;
    try {
       String s = getParameter("filesEnabled");
       if (s.equals("true"))
            enableFiles = true;
    }
    // If error, use false default...
    catch (Exception e) { }
// Create the spreadsheet frame
fr = new SpreadsheetFrame(this,rows,cols,enableFiles);
  }

// If returning to screen for first time show frame...
public void start() {
// Redisplay the applet...
try {
fr.show();
}
// Handle any problem...
catch(Exception e) { }
}

// Hide the frame upon leaving...
public void stop() {
  // Handle where it may have been disposed...
try {
fr.hide();
}
// Handle any problem...
catch(Exception e) { }
}


}
class SpreadsheetFrame extends Frame {
  CellContainer c;   // The actual spreadsheet data...
  SpreadsheetContainer s;  // The spreadsheet view
  Scrollbar hScroll;  // The scrollbars...
  Scrollbar vScroll;
  GridBagLayout g;   // Layout for Frame
  MenuBar mbar;  // The frames menu...
  TextField t;  // The text field for the spreadsheet...
  SpreadsheetCell currHighlight;  // The currently highlighted cell...
  Applet appl; // The applet...
  int numRows;  // Keep the initial parameters...
  int numCols;
  ChooseColorDialog colorDialog;  // Color Dialog...
  ChooseFontDialog fontDialog;  // Font Dialog...
  GraphDialog graphDialog;  // For displaying graphs...
  FileDialog openFileDialog;  // File Open Dialog...
  FileDialog saveFileDialog;  // File Save Dialog...
  // Don't use File Dialogs if this is a Network
  // version of the spreadsheet...
  boolean enableFiles = false;

// The constructor for the spreadsheet frame takes the
// values of the size of the Spreadsheet...
public SpreadsheetFrame(Applet a,int rows, int cols,
     boolean enableFiles) {
super("Spreadsheet Applet");

// Set the initial size and layouts...
resize(300,200);
g = new GridBagLayout();
setLayout(g);
appl = a;  // Store the applet...
      this.enableFiles = enableFiles;
numRows = rows;
numCols = cols;

// Create the new container based on the applet parameters...
try {
c = new CellContainer(rows,cols);
}
catch (IllegalArgumentException e) {
System.out.println("Invalid Spreadsheet parameters");
dispose();
}

addTestData();

// Create display components...
addDisplayComponents();

// Add the menu choices to the frames
addMenuItems();

      // Create the dialogs...
      colorDialog = new ChooseColorDialog(this,true);
      fontDialog = new ChooseFontDialog(this,true);
      openFileDialog = new FileDialog(this,"Open File",
               FileDialog.LOAD);
      saveFileDialog = new FileDialog(this,"Save File",
               FileDialog.SAVE);
      graphDialog = new GraphDialog(this,true);

// Pack before display...
pack();
resize(300,200);  // Then reset to default value...
show();
}


// Handle system and user events...
public boolean handleEvent(Event evt) {
switch(evt.id) {
case Event.WINDOW_DESTROY: {
dispose();   // Kill the frame...
return true;
}
// This can be handled
case Event.ACTION_EVENT: {
String menu_name = evt.arg.toString();
if (evt.target instanceof MenuItem) {
// Exit...
if(menu_name.equals("Quit"))
dispose();  // Kill the frame...
// New Spreadsheet...
if(menu_name.equals("New"))
newSpreadsheet();
// Open a Spreadsheet...
if(menu_name.equals("Open"))
                        openSpreadsheetDialog();
// Save a Spreadsheet...
if(menu_name.equals("Save"))
                        saveSpreadsheetDialog();
// Set colors...
if(menu_name.equals("Colors..."))
colorDialog.show();
// Set fonts...
if(menu_name.equals("Fonts..."))
fontDialog.show();
                  // Show line graph...
                  if((menu_name.equals("Line Graph...")) ||
                     (menu_name.equals("Bar Graph...")) )
                        launchGraphicsDialog(menu_name);
}  // end if
            // Handle entry of new text data entered...
if (evt.target instanceof TextField) {
validateNewFormula();
return true;
}  // end if
            // Notification of a new cell highlighted
if (evt.target instanceof SpreadsheetContainer) {
changeInputFormula((SpreadsheetCell)evt.arg);
               return true;
}
return false;
}
         case Event.SCROLL_LINE_UP:
         case Event.SCROLL_ABSOLUTE:
         case Event.SCROLL_LINE_DOWN:
         case Event.SCROLL_PAGE_UP:
         case Event.SCROLL_PAGE_DOWN:
if (evt.target instanceof Scrollbar) {
               scrollbarAction((Scrollbar)evt.target);
}  // end if
            return true;
default:
return false;
}
}


// Add the menu choices to the frames
void addMenuItems() {
mbar = new MenuBar();
      // Add the File menu items......
Menu m = new Menu("File");
m.add(new MenuItem("New"));
      if (enableFiles) {
    m.add(new MenuItem("Open"));
    m.add(new MenuItem("Save"));
      }
m.addSeparator();
m.add(new MenuItem("Quit"));
mbar.add(m);

      // Add the Graph displays......
m = new Menu("Graphs");
  m.add(new MenuItem("Line Graph..."));
m.add(new MenuItem("Bar Graph..."));
mbar.add(m);

      // Add the Options menu items......
m = new Menu("Options");
m.add(new MenuItem("Colors..."));
m.add(new MenuItem("Fonts..."));
mbar.add(m);

setMenuBar(mbar);
}

// Add the spreadsheet, input field and scrollbars
// to display...
void addDisplayComponents() {
GridBagConstraints gbc = new GridBagConstraints();
    // Create an input field across the top...
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
t = new TextField();
g.setConstraints(t,gbc);
add(t);

// Create the spreadsheet display...
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.gridwidth = GridBagConstraints.RELATIVE;
gbc.gridheight = 10;
s = new SpreadsheetContainer(c);
g.setConstraints(s,gbc);
add(s);

// Add vertical scrollbar...
gbc.gridwidth = GridBagConstraints.REMAINDER;
vScroll = new Scrollbar(Scrollbar.VERTICAL,1,1,1,numRows);
g.setConstraints(vScroll,gbc);
add(vScroll);

// Add horizontal scrollbar...
hScroll = new Scrollbar(Scrollbar.HORIZONTAL,1,1,1,numCols);
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
g.setConstraints(hScroll,gbc);
add(hScroll);

// Set initial formula for text field...
changeInputFormula(s.getHighlight());
}


// Change the formula of the input field to that of
// the Object argument, which is a spreadsheet cell...
void changeInputFormula(SpreadsheetCell sc) {
// Set the text box with the formula...
if (sc != null)
t.setText(sc.getString());
else
t.setText("");
// Store the currently highlighted cell...
currHighlight = sc;
}

// A text field formula has been entered...
// Validate it and update spreadsheet...
// Update text field where necessary...
void validateNewFormula() {
// Put up wait icon for calculations...
int oldCursor = getCursorType();
setCursor(WAIT_CURSOR);
try {
// Replace the formula.  If no problem then
// spreadsheet will be recalculated...
s.replaceFormula(currHighlight, t.getText());
appl.getAppletContext().showStatus("Formula accepted.");
}
catch (Exception e) {  // Handle illegal exception...
// Let browser status bar know about error...
// Get the status bar from the AppletContext...
appl.getAppletContext().showStatus("Illegal Formula syntax: Use SUM,ADD,SUB,MULT,DIV");
}
// Always place the converted formula in the text field...
changeInputFormula(s.getHighlight());
setCursor(oldCursor);
}

// Reload spreadsheet with blank data...
void newSpreadsheet() {
// Create the new container based on the applet parameters...
try {
c = new CellContainer(numRows,numCols);
s.newCellContainer(c);
// Set initial formula for text field...
changeInputFormula(s.getHighlight());
          // Reset scrollbars...
          vScroll.setValue(vScroll.getMinimum());
          hScroll.setValue(hScroll.getMinimum());
}
catch (IllegalArgumentException e) {
System.out.println("Invalid Spreadsheet parameters");
dispose();
}
   }

   // Return a reference to the spreadsheet container...
   public SpreadsheetContainer getSpreadsheetContainer() {
     return s;
   }

   // Call Open Dialog, and load a file if a choice
   // was made...
   void openSpreadsheetDialog() {
      // Show the dialog
      openFileDialog.show();
      // If a file was chosen then open it...
      if (openFileDialog.getFile() != null) {
         String filename,fullname;
         filename = openFileDialog.getFile();
         // Hack for Win 95 Java bug...
         int index = filename.indexOf(".*.*");
         if (index >= 0)
            filename = filename.substring(0,index);
         // Get the name of the file to save...
         if (openFileDialog.getDirectory() != null)
            fullname = openFileDialog.getDirectory() + filename;
         else
            fullname = filename;
         // Open the file into new Cell container...
      int oldCursor = getCursorType();  // Put up an hourglass...
    setCursor(WAIT_CURSOR);
         try {
            c = new CellContainer(fullname);
            c.recalculateAll();  // Recalculate the values...
            // Load it into the spreadsheet...
   s.newCellContainer(c);
   // Set initial formula for text field...
            changeInputFormula(s.getHighlight());
            // Reset scrollbars...
            vScroll.setValue(vScroll.getMinimum());
            hScroll.setValue(hScroll.getMinimum());
    appl.getAppletContext().showStatus("Opened file " + filename);
         }
         // Handle error saving file...
         // Print out reason for failure...
         catch (IOException e) {
    appl.getAppletContext().showStatus("Unable to open: "
               + e.getMessage());
         }
    setCursor(oldCursor);
      } // end if
   }

   // Call Save Dialog, and load a file if a choice
   // was made...
   void saveSpreadsheetDialog() {
      saveFileDialog.show();
      // If a file was chosen then save it...
      if (saveFileDialog.getFile() != null) {
         String filename,fullname;
         filename = saveFileDialog.getFile();
         // Hack for Win 95 Java bug...
         int index = filename.indexOf(".*.*");
         if (index >= 0)
            filename = filename.substring(0,index);
         // Get the name of the file to save...
         if (saveFileDialog.getDirectory() != null)
            fullname = saveFileDialog.getDirectory() + filename;
         else
            fullname = filename;
         // Save the file!
      int oldCursor = getCursorType();  // Put up an hourglass...
    setCursor(WAIT_CURSOR);
         try {
            c.saveFile(fullname);
         }
         // Handle error saving file...
         catch (IOException e) {
    appl.getAppletContext().showStatus("Unable to save file " + filename);
         }
    setCursor(oldCursor); // Back to arrow..
      } // end if
   }


   // Launch the graphics dialog.  Load the double
   // and headers
   public void launchGraphicsDialog(String graphType) {
      // Get the graphics data to be displayed...
      try {
         GraphData gd = s.getGraphData();
         // Show it if there is something...
         if (graphType.equals("Line Graph...") )
            graphDialog.show(gd,graphDialog.LINE_GRAPH);
         else
            graphDialog.show(gd,graphDialog.BAR_GRAPH);
      }
      // Catch error if nothing marked...
      catch (IllegalArgumentException e) {
         appl.getAppletContext().showStatus(e.getMessage());
      }
   }


   // Handle scroll bar actions...
   void scrollbarAction(Scrollbar sb) {
      if (sb.getOrientation() == Scrollbar.VERTICAL)
         s.setNewTop(sb.getValue());
      else
         s.setNewLeft(sb.getValue());
   }



void addTestData() {
c.setCellFormula("1",0,0);
c.setCellFormula("2",0,1);
c.setCellFormula("3",0,2);
c.setCellFormula("4",0,3);
c.setCellFormula("SUM(A0,A3)",0,4); // Should be 10
c.recalculateAll();
}
}

======================================
SpreadsheetCell.java

package spreadsheetapplet;


/* SpreadsheetCell.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/



import java.awt.*;
import java.lang.*;

// This class ties the contents of an individual
// SpreadsheetCell to a single data Cell.
// The evaluated contents of
// that cell are returned to the SpreadsheetContainer...
public class SpreadsheetCell extends Canvas {
Cell c;  // The cell this is tied to...
boolean literal;  // If set to true, automatically paint what's in cell string...
Color fillColor;
Color textColor;
   // Store positions of last repaint...
   boolean validCoor = false;  // True if we have valid coordinates...
   int lastX,lastY,lastWidth,lastHeight;
public SpreadsheetCell(Cell c,boolean literal) {
super();
this.c = c;
this.literal = literal;
      // Set the color defaults...
fillColor = Color.white;
textColor = Color.black;
}

// Set the fill color
public void setFillColor(Color clr) {
fillColor = clr;
}

// Set the text color
public void setTextColor(Color clr) {
textColor = clr;
}

// Return the reference to the cell...
public Cell getCell() {
    return c;
}

// Set the cell string...
public void setString(String s) {
c.setCellString(s);
}

// Get the current string value in the cell...
public String getString() {
return c.getCellString();
}

   // Get evaluated value
public double getEvalValue() {
      return c.getEvalValue();
   }

// This will return the text to the current evaluated contents
// of the cell...
public synchronized void paint(Graphics g,int x,int y,int width,int height) {
String s = c.getCellString();
String textPaint;
// If this is a literal value then print what it has...
if (literal == true)
textPaint = s;
else {
// Otherwise, display formula only if cell is not empty...
if (s.compareTo("") == 0)
textPaint = s;
else  // Otherwise show evaluate value...
textPaint = String.valueOf(c.getEvalValue()) ;
} // end else
// Set up drawing rectangle...
g.setColor(Color.blue);
g.drawRect(x,y,width,height);
g.setColor(fillColor);
g.fillRect(x + 1,y + 1,width - 2,height - 2);
// Clip the text if necessary...
int textWidth;
int len = textPaint.length();    
int effWidth = width - 4;
// Loop until text is small enough to fit...
while (len > 0) {
textWidth = g.getFontMetrics().stringWidth(textPaint);
if (textWidth < effWidth)
break;
--len;
textPaint = textPaint.substring(0,len);
} // end while
// Draw the string
g.setColor(textColor);
g.drawString(textPaint,x + 4,y + (height - 2));
      // Store the coordinates...
      validCoor = true;
      lastX = x;
      lastY = y;
      lastWidth = width;
      lastHeight = height;
}

   // Return the literal value...
public boolean getLiteral() {
    return literal;
}

   // Get last coordinates painted...
   public Rectangle getLastCoordinates() {
      // If not valid yet return null
      if (validCoor == false)
         return null;
      // Otherwise return a rectangle with the values...
      return new Rectangle(lastX,lastY,lastWidth,lastHeight);
   }

}

======================================

SpreadsheetContainer.java

package spreadsheetapplet;


/* SpreadsheetContainer.java Author Casey Hopson
   Geist Software and Services, Inc.
*
* Permission to use, copy, modify, and distribute
* this software for NON_COMMERCIAL purposes and without
*  fee is hereby granted provided that this copyright notice
*  appears in all copies.
*
* The creators of this software make no representations or
* warranties about the suitability of the software, either
*  express or implied.  The creators shall not be liable for
*  any damages suffered by licensee as a result of using,
*  modifying or distributing this software or its derivatives.
*/


import java.awt.*;
import java.lang.*;

// This class contains the cells that make up a spreadsheet...
public class SpreadsheetContainer extends Canvas {
   // The actual spreadsheet data...
CellContainer c;
int numRows;
int numColumns;
SpreadsheetCell matrix[];
   SpreadsheetCell emptyCell;  // Empty cell for repainting blank areas...
   // Graphic elements set in the paint routine...
int cellWidth;
int cellHeight;
   // Keep track of what is highlighted...
SpreadsheetCell newHighlight;
SpreadsheetCell oldHighlight;
   // Display colors
   Color normalForeColor = Color.black;
   Color normalBackColor = Color.white;
   Color highlightedForeColor = Color.white;
   Color highlightedBackColor = Color.red;
   Color markedForeColor = Color.white;
   Color markedBackColor = Color.blue;
   // Keep track of scrolling positions...
   int topCell; // Top cell displayed...
   int leftCell; // Leftmost cell displayed...
   // Use to keep track of paint data in test calculations...
   int paintIndex = 0;
   int paintX = 0;
   int paintY = 0;
   // More variables for temp storage...
   int tempRow;
   int tempCol;

// Construct container.  Create internal paint matrix tied to
// the data container...
public SpreadsheetContainer(CellContainer ctnr) {
super();
// Load the container and set up the display...
loadContainer(ctnr);
}


// Take a cell container and load set the spreadsheet
// to use it. Put the highlight in the first cell...
void loadContainer(CellContainer ctnr) {
c = ctnr; // Store the CellContainer...

// Get size of spreadsheet...
numRows = c.getNumRows() + 1;
numColumns = c.getNumColumns() + 1;

// Create the SpreadsheetCell matrix...
matrix = new SpreadsheetCell[numRows * numColumns];

// Add the cells to the grid...
int i,j,index;
char ch;

// Add the column labels across the top...
for (j = 0; j < numColumns; ++j) {
// Create a literal cell for each column...
matrix[j] = new SpreadsheetCell(new Cell(),true);
// Set the cell contents and color...
if (j > 0)
matrix[j].setString(String.valueOf((j - 1)) );
matrix[j].setFillColor(Color.lightGray);
matrix[j].setTextColor(Color.blue);
} // end for

// Create the individual rows...
for (i = 1; i < numRows; ++i) {
// Set up the row header...
index = (i * (numColumns));
matrix[index] = new SpreadsheetCell(new Cell(),true);
ch = (char)('A' + (i - 1));
matrix[index].setString(String.valueOf(ch) );
matrix[index].setFillColor(Color.lightGray);
matrix[index].setTextColor(Color.blue);
// Now set the container cells...
for (j = 1; j < numColumns; ++j) {
index = (i * (numColumns)) + j;
matrix[index] = new SpreadsheetCell(c.getCell(i - 1,j - 1),false);
// Set the colors...
matrix[index].setFillColor(normalBackColor);
matrix[index].setTextColor(normalForeColor);
}  // end inner for...
} // end outer for

      // Create empty cell for painting blank areas...
      emptyCell = new SpreadsheetCell(new Cell(),true);
emptyCell.setFillColor(Color.lightGray);
emptyCell.setTextColor(Color.blue);

      // Marking is initially off...
      setupMarking();

      // Set scroll positions
      topCell = 1;
      leftCell = 1;

// Highlight the upper left cell...
index = getIndex(1,1);
newHighlight = matrix[index];
oldHighlight = newHighlight;
setCellHighlight(newHighlight,true);
}

// Attach a new container to the spreadsheet...
public void newCellContainer(CellContainer ctnr) {
// Load the container and set up the display...
loadContainer(ctnr);
repaint();
}


// Return the currently highlighted row...
public SpreadsheetCell getHighlight() {
    return newHighlight;
}

// Get the index into the matrix for a row or column...
int getIndex(int row, int col) {
return ((row * numColumns) + col);
}

// Handle mouse clicks...
void setMouseHighlight(int x, int y) {
      SpreadsheetCell tempHighlight;
// First figure out what cell is at those coordinates...
tempHighlight = calculatePaint(null,false,x,y);
// Make it the new highlight if it is not a border element...
if ((tempHighlight != null) && (tempHighlight.getLiteral() == false) ) {
         newHighlight = tempHighlight;
// Turn off old highlight...
if ((oldHighlight != null) && (oldHighlight != newHighlight))
setCellHighlight(oldHighlight,false);
// Set new highlight...
setCellHighlight(newHighlight,true);
oldHighlight = newHighlight;
// Notify parent of change...
notifyParentOfHighlight(newHighlight);
}
}

// Highlight a cell
// If boolean is on then highlight, else set to normal...
void setCellHighlight(SpreadsheetCell sc,boolean on) {
if (on == true) {   // Highlight it!
sc.setFillColor(highlightedBackColor);
sc.setTextColor(highlightedForeColor);
} // end if
else {   // Set to normal...
sc.setFillColor(normalBackColor);
sc.setTextColor(normalForeColor);
} // end else...
// Force the cell to repaint...
      // See if we can repaint just what is needed...
      Rectangle r = sc.getLastCoordinates();
      if (r != null)
         repaint(r.x,r.y,r.width,r.height);
      else
    repaint();
}

   // Handle scrolling by setting new top...
   public void setNewTop(int newTop) {
      // Set top taking into account headings and constraints...
      if (newTop < numRows)
         topCell = newTop;
      else
         topCell = numRows - 1;
      resetMarking();
      repaint();
   }

   // Set new leftmost column...
   public void  setNewLeft(int newLeft) {
      // Set new left taking into account headings and constraints...
      if (newLeft < numColumns)
         leftCell = newLeft;
      else
         leftCell = numColumns - 1;
      resetMarking();
      repaint();
   }


   // Update message sent when repainting is needed...
   // Prevent paint from getting cleared out...
   public void update(Graphics g) {
      paint(g);
   }

// Draw the displayable spreadsheet contents...
public synchronized void paint (Graphics g) {
// Go through the calculations of the paint while painting...
calculatePaint(g,true,0,0);
}

// This goes through the motions of calculating what is on the
// screen and either calculates coordinates or paints...
   // If it is not paint, returns cell that fits in hit region...
SpreadsheetCell calculatePaint(Graphics g,boolean bPaint,int xHit,int yHit) {
// Get the current size of the display area...
Dimension dm = size();
      Rectangle r = null;  //   The clipping rectangle...
      Rectangle cellRect = null; // The cell clipping rectangle...
// Calculate the cell width and height
// Cell should be wide enough to show 8 digits...
if (bPaint == true) {
cellWidth = g.getFontMetrics().stringWidth("12345.67");
cellHeight = g.getFontMetrics().getHeight();
       r = g.getClipRect();
} // end if

// Figure out how many rows and cols can be displayed
int nCol = Math.min(numColumns,dm.width / cellWidth);
int nRow = Math.min((numRows + 1),dm.height / cellHeight);

// Draw the cells...
int index,i,x,j,y,currentRow,currentCol;
--nRow;
// Go across the rows...
      // Show the headers and adjust for top and left cell...
for (currentRow = i = 0; i < nRow; ++i) {
y = cellHeight + (i * cellHeight);
// Go across the colomns...
for (currentCol = j = 0; j < nCol; ++j) {
index = (currentRow * numColumns) + currentCol;
               x = (j * cellWidth);
// Paint if told to...
if (bPaint == true) {
                 // See if it is in the intersection of the
                 // clipping rectangle
                 cellRect = new Rectangle(x,y,cellWidth,cellHeight);
                 if (r.intersects(cellRect)) {
                   // Paint if we are at a valid row...
                   if ((currentRow < numRows) && (currentCol < numColumns)) {
    matrix[index].paint(g,x,y,
    cellWidth,cellHeight);
                   } // end inner if
                   else {  // Otherwise fill it in with grey...
                     emptyCell.paint(g,x,y,cellWidth,cellHeight);
                   } // end else
                 } // end if
} // end if
else { // Otherwise see if cell fits...
                if ((currentRow < numRows) && (currentCol < numColumns)) {
// See if it fits in the column...
if ((xHit >= x) && (xHit < (x + cellWidth))) {
  // See if it fits in the row...
  if ((yHit >= y) && (yHit < (y + cellHeight))) {
                        paintIndex = index;
                        paintX = x;
                        paintY = y;
return matrix[index];
  } // end if
} // end if
                } // end inner if
               } // end else
               if (j == 0)
                  currentCol = leftCell;
               else
                  ++currentCol;
}  // end column for
         // Now start data cells at appropriate top...
         if (i == 0)
            currentRow = topCell;
         else
            ++currentRow;
} // end row for
      return null;  // Only used if paint is false...
}

// Notify parent that there is a new Highlight...
void notifyParentOfHighlight(SpreadsheetCell sc) {
// Create new event with highlight cell as arg
Event ev = new Event(this,Event.ACTION_EVENT,sc);
// Send it to the parent...
      getParent().deliverEvent(ev);
   }

// Handle mouse clicks to spreadsheet...
public boolean handleEvent(Event evt) {
switch(evt.id) {
// Mouse clicks. See if we should highlight
// cell on spreadsheet...
case Event.MOUSE_DOWN: {
if (evt.target instanceof SpreadsheetContainer) {
setMouseHighlight(evt.x,evt.y);
                  // Handle cell marking...
                  toggleMarking(evt.x,evt.y);
            } // end if
return false;
}
case Event.MOUSE_DRAG: {
            // Select cells if marking...
if (evt.target instanceof SpreadsheetContainer)
               dragMarking(evt.x,evt.y);
return false;
}
case Event.MOUSE_UP: {
            // If marking then we are done!
if (evt.target instanceof SpreadsheetContainer)
               stopMarking(evt.x,evt.y);
return false;
}
default:
return false;
}
}

   // Keep track of drag marking....
   boolean marking = false;
   // Keep track of whether anything is marked...
   boolean markedCells = false;
   // Variables to support marking operations...
SpreadsheetCell scStartMarked;
SpreadsheetCell scEndMarked;
SpreadsheetCell scCurrentMarked;
   // Keep track of last marked index...
   int lastTrackedIndex;
   int lastMarkedIndex;
   // Use for tracking painting coordinates...
   int startX;
   int startY;
   int endX;
   int endY;
   int trackedX;
   int trackedY;
   int startMarkedRow;
   int endMarkedRow;
   int startMarkedCol;
   int endMarkedCol;

   // Return the spreadsheet cell reference if it is
   // markable...
   SpreadsheetCell getMarkable(int x,int y) {
    SpreadsheetCell scMark = calculatePaint(null,false,x,y);
    // Can't be one of the headers...
    if ((scMark != null) && (scMark.getLiteral() == false) ) {
      lastTrackedIndex = paintIndex;
      trackedX = paintX;
      trackedY = paintY;
      return scMark;
    }
    return null;
   }

   // Setup marking by setting marking to false...
   void setupMarking() {
      marking = false;
      markedCells = false;
      scStartMarked = null;
      scEndMarked = null;
      scCurrentMarked = null;
      lastTrackedIndex = -1;
      lastMarkedIndex = -1;
   }

   // Toggle marking state...
   // Either start tracking the mouse or
   // Reset marking...
   void toggleMarking(int x,int y) {
      // If stuff has been marked before then
      // turn all the marking cells off...
      if (markedCells) {
         resetMarking();
      }
      // Otherwise, start tracking the mouse...
      else {
         startMarking(x,y);
      }
   }

   // Turn all the marked cells highlighting off...
   void resetMarking() {
     // Return if no marking...
     if (markedCells == false)
         return;
     // Just call setNewColors with current colors..
     setNewColors(normalForeColor, normalBackColor,
        highlightedForeColor, highlightedBackColor);
     // Set marking to false...
     marking = false;
     markedCells = false;
System.out.println("Reset marking");
   }

   // Start marking at current cell...
   void startMarking(int x,int y) {
         scCurrentMarked = getMarkable(x,y);
         if (scCurrentMarked != null) {
   System.out.println("Start marking");
            scStartMarked = scCurrentMarked;
            scEndMarked = scCurrentMarked;
            lastMarkedIndex = lastTrackedIndex;
            startX = trackedX;
            startY = trackedY;
            marking = true;
         } // end if
         // Otherwise, it is a bad cell and don't mark...
         else {
   System.out.println("Bad Cell: No marking");
            marking = false;
            markedCells = false;
         }
   }


   // If marking is on then we need to see if a new cell
   // was entered.  If so, then add it the endpoint of the
   // marking.  If a bad cell was entered, then we are done...
   void dragMarking(int x,int y) {
      // Just return if marking is false...
      if (!marking)
         return;
      // See if we entered a new cell...
      if (insideCell(scCurrentMarked,x,y)) {
         return;
      } // end if
      // If still good, see if the cell is valid
      // and get its reference...
      scCurrentMarked = getMarkable(x,y);
      // If invalid mark is found stop marking...
      if (scCurrentMarked == null) {
System.out.println("Out of bounds! Stop marking...");
         marking = false;
         // Make sure more than one cell is marked,
         // else we have no marking...
         validateMarking();
         return;
      }
      // Validate the direction. Only let use move south eastward...
      if (lastMarkedIndex >= lastTrackedIndex) {
System.out.println("Bad change of direction! Stop marking...");
         marking = false;
         // Make sure more than one cell is marked,
         // else we have no marking...
         validateMarking();
         return;
      }
      // Otherwise, store the new cell...
      scEndMarked = scCurrentMarked;
      lastMarkedIndex = lastTrackedIndex;
      endX = trackedX + cellWidth;
      endY = trackedY + cellHeight;
System.out.println("Drag");
      // Paint marked rectangle...
      paintMarked();
   }

   // When stop marking see if more than one cell has been
   // marked. If not set marking = false
   public void stopMarking(int x, int y) {
      // Just return if marking is false...
      if (!marking)
         return;
      // Validate marking to see if more than one cell has been markedd...
      validateMarking();
      marking = false;
System.out.println("Marking done!");
   }

   // Make sure more than one cell is marked,
   // else we have no marking...
   void validateMarking() {
    // If any of the pointer are null,nothing has been done...
    if ((scStartMarked == null) ||  (scEndMarked == null) ||
      (scStartMarked == scEndMarked) ){
System.out.println("No marked cells...");
      markedCells = false;
      return;
    }
    // Otherwise, we have something...
System.out.println("Validated marked cells...");
    markedCells = true;
   }

   // Paint marked rectangle. Figure out what cells are in
   // the highlighted area.  Set their colors and repaint
   // the area...
   void paintMarked() {
      // Get the starting and ending indexes into the
      // matrix array...
      int startIndex = getIndexFromCell(scStartMarked);
      int startRow = tempRow;
      int startCol = tempCol;
      int endIndex = getIndexFromCell(scEndMarked);
      int endRow = tempRow;
      int endCol = tempCol;
      startMarkedRow = startRow;
      endMarkedRow = endRow;
      startMarkedCol = startCol;
      endMarkedCol = endCol;
      if ((startIndex < 0) || (endIndex < 0)) {
         return;
      }
      // Now go over and highlight each cell!!
      int i,j,index;
      // Go through the marked rows and columns...
      for (i = startRow; i <= endRow; ++i) {
         for (j = startCol; j <= endCol; ++j) {
               index = (i * (numColumns)) + j;
               // Skip over highlighted cell...
               if (matrix[index] != newHighlight) {
    matrix[index].setFillColor(markedBackColor);
    matrix[index].setTextColor(markedForeColor);
               } // end if
         } // end for
      } // end row for
      // Repaint to force new colors to appear...
      repaint(startX,startY,endX-startX,endY-startY);
   }

   // This is used for creating the double data and
   // string values that are used to convert the cell
   // container data into a graph...
   // Throws an exception if nothing is marked or something
   // else is wrong with the marked data...
   public GraphData getGraphData() throws IllegalArgumentException {
      // No cells marked is a problem...
      if (!markedCells)
         throw new IllegalArgumentException("No cells marked");
      // Figure out how many rows were marked...
      int numMarkedRows = (endMarkedRow - startMarkedRow) + 1;
      int numMarkedCols = (endMarkedCol - startMarkedCol) + 1;

      // Set up headings.  If one row, then its the row and column
      // else its the top row values...
      int i,j,index;
      String headings[] = new String[numMarkedCols];
      // Set up using marked data in top row as headings....
      if (numMarkedRows > 1) {
         for (i = 0,j = startMarkedCol; j <= endMarkedCol; ++j,++i) {
            index = (startMarkedRow * (numColumns)) + j;
            headings[i] = matrix[index].getString();
         }
      }
      // Otherwise use cell names as headers...
      else {
         index = (startMarkedRow * (numColumns));
         String rowName = matrix[index].getString();
         for (i = 0,j = startMarkedCol; j <= endMarkedCol; ++j,++i) {
            // Take column number and convert to string...
            headings[i] = rowName + String.valueOf(j - 1);
         }
      }
      // Now load up the data.  Just look at the last row...
      double data[] = new double[numMarkedCols];
      for (i = 0,j = startMarkedCol; j <= endMarkedCol; ++j,++i) {
            index = (endMarkedRow * (numColumns)) + j;
            data[i] = matrix[index].getEvalValue();
      } // end for

      return new GraphData(data,headings);
   }


   // Returns whether coordinates are within a cell...
   boolean insideCell(SpreadsheetCell testCell,int x,int y) {
      // Get the last coodinates of the testCell...
      Rectangle r = testCell.getLastCoordinates();
      if (r == null)
         return false;
      // Just make a rectangle and do an intersection...
      Rectangle testRect = new Rectangle(x,y,0,0);
      return r.intersects(testRect);
   }

   // Get an index from a spreadsheet cell...
   int getIndexFromCell(SpreadsheetCell testCell) {
     int index,i,j;
     tempRow = tempCol = 0;
     for (i = 0; i < numRows; ++i) {
for (j = 0; j < numColumns; ++j) {
index = (i * (numColumns)) + j;
               // See if the cells match...
if (matrix[index] == testCell) {
                  tempRow = i;
                  tempCol = j;
                  return index;
               } // end if
}  // end inner for...
     } // end outer for
     return -1;
   }

// Handle to change to a formula...
// Throws an exception if the formula is invalid...
public void replaceFormula(SpreadsheetCell sc,String newFormula) throws IllegalArgumentException {
String convertedFormula;
// First validate the formula...
try {
convertedFormula = c.validateFormula(sc.getCell(),newFormula);
}
// If formula is invalid, rethrow an exception...
catch (FormulaParserException e) {
throw new IllegalArgumentException();
}
// Add converted formula to cell...
sc.setString(convertedFormula);
// Recalc... Set hourglass...
c.recalculateAll();
// Repaint...
repaint();
}

   // Routines for getting the various color display values...
   public Color getNormalForeColor()  {
      return normalForeColor;
   }
   public Color getNormalBackColor() {
      return normalBackColor;
   }
   public Color getHighlightedForeColor() {
      return highlightedForeColor;
   }
   public Color getHighlightedBackColor() {
      return highlightedBackColor;
   }

   // Set the new colors for the spreadsheet
   // Set for each cell and then repaint...
   public void setNewColors(Color normalFore, Color normalBack,
      Color highlightFore, Color highlightBack) {
     // Set the internal color variables...
     normalForeColor = normalFore;
     normalBackColor = normalBack;
     highlightedForeColor = highlightFore;
     highlightedBackColor = highlightBack;

     // Reload the colors for the matrix
     int index;
     for (int i = 1; i < numRows; ++i) {
for (int j = 1; j < numColumns; ++j) {
index = (i * (numColumns)) + j;
// Set the colors...
matrix[index].setFillColor(normalBackColor);
matrix[index].setTextColor(normalForeColor);
}  // end inner for...
     } // end outer for

     // Reload the color for the highlight...
     newHighlight.setFillColor(highlightedBackColor);
     newHighlight.setTextColor(highlightedForeColor);

     // Now repaint everything...
     repaint();
   }

   // Set the font for all the individual
   // spreadsheet cells...
   public synchronized void setFont(Font f) {
     super.setFont(f);
     int index;
     // Reload the font for each cell...
     for (int i = 0; i < numRows; ++i) {
for (int j = 0; j < numColumns; ++j) {
index = (i * (numColumns)) + j;
// Set the colors...
matrix[index].setFont(f);
}  // end inner for...
     } // end outer for
     // Repaint to show new font...
     repaint();
   }

}

=============================





Tidak ada komentar: