This commit is contained in:
2024-08-07 09:16:27 -04:00
parent fdfadd5c7e
commit 5f971cf684
5200 changed files with 731717 additions and 0 deletions

BIN
java/SPREAD/CASHFL~1.CLA Normal file

Binary file not shown.

312
java/SPREAD/CASHFL~1.JAV Normal file
View File

@@ -0,0 +1,312 @@
import java.awt.*;
public class Cashflow extends java.applet.Applet
{
SpreadSheetInterface mSpreadSheet;
PurePassThru mPurePassThru=new PurePassThru();
PureCashflow mPureCashflows[];
TextField mCtlPrincipal;
TextField mCtlInterest;
TextField mCtlTerm;
TextField mCtlPrepayment;
TextField mCtlIncrement;
TextField mCtlFrequency;
Label mCtlCost;
Label mCtlMsg;
Button mCtlButton;
public void init()
{
performLayout();
mSpreadSheet=new SpreadSheetInterface(this,361,10,new Dimension(630,200));
mSpreadSheet.setDocumentTitle("Paydown Calculator v1.00");
mSpreadSheet.gridLock(true);
repaint();
}
public void update(Graphics graphics)
{
if(null!=mSpreadSheet)mSpreadSheet.update(graphics);
}
public void paint(Graphics graphics)
{
if(null!=mSpreadSheet)mSpreadSheet.paint(graphics);
}
public boolean mouseDown(Event event,int x,int y)
{
if(null!=mCtlPrincipal&&mCtlPrincipal==event.target)return false;
else if(null!=mCtlInterest&&mCtlInterest==event.target)return false;
else if(null!=mCtlTerm&&mCtlTerm==event.target)return false;
else if(null!=mCtlButton&&mCtlButton==event.target)return false;
else if(null!=mCtlPrepayment&&mCtlPrepayment==event.target)return false;
else if(null!=mCtlIncrement&&mCtlIncrement==event.target)return false;
else if(null!=mCtlFrequency&&mCtlFrequency==event.target)return false;
else if(null!=mSpreadSheet)return mSpreadSheet.mouseDown(event,x,y);
return true;
}
public boolean keyDown(Event event,int key)
{
if(null!=mCtlPrincipal&&mCtlPrincipal==event.target)return false;
else if(null!=mCtlInterest&&mCtlInterest==event.target)return false;
else if(null!=mCtlTerm&&mCtlTerm==event.target)return false;
else if(null!=mCtlButton&&mCtlButton==event.target)return false;
else if(null!=mCtlPrepayment&&mCtlPrepayment==event.target)return false;
else if(null!=mCtlIncrement&&mCtlIncrement==event.target)return false;
else if(null!=mCtlFrequency&&mCtlFrequency==event.target)return false;
else if(null!=mSpreadSheet)return mSpreadSheet.keyDown(event,key);
return true;
}
public void performLayout()
{
GridBagLayout layout=new GridBagLayout();
GridBagConstraints constraints=new GridBagConstraints();
setFont(new Font("Fixed",Font.BOLD,12));
setLayout(layout);
constraints.fill=GridBagConstraints.BOTH;
constraints.weightx=0.25;
Label prnLabel=new Label("Principal",Label.LEFT);
layout.setConstraints(prnLabel,constraints);
add(prnLabel);
mCtlPrincipal=new TextField("$100000.00");
layout.setConstraints(mCtlPrincipal,constraints);
add(mCtlPrincipal);
Label intLabel=new Label("Interest",Label.LEFT);
layout.setConstraints(intLabel,constraints);
add(intLabel);
mCtlInterest=new TextField("8.00%");
layout.setConstraints(mCtlInterest,constraints);
add(mCtlInterest);
Label trmLabel=new Label("Term",Label.LEFT);
layout.setConstraints(trmLabel,constraints);
add(trmLabel);
mCtlTerm=new TextField("360");
layout.setConstraints(mCtlTerm,constraints);
add(mCtlTerm);
constraints.gridwidth=GridBagConstraints.REMAINDER;
mCtlButton=new Button("Calculate");
layout.setConstraints(mCtlButton,constraints);
add(mCtlButton);
constraints.fill=GridBagConstraints.BOTH;
constraints.gridwidth=1;
Label ppyLabel=new Label("Prepayment",Label.LEFT);
layout.setConstraints(ppyLabel,constraints);
add(ppyLabel);
mCtlPrepayment=new TextField("$0.00");
layout.setConstraints(mCtlPrepayment,constraints);
add(mCtlPrepayment);
constraints.gridwidth=GridBagConstraints.REMAINDER;
Label ppyHlpLabel=new Label("Enter the amount of your prepayment(s).");
layout.setConstraints(ppyHlpLabel,constraints);
add(ppyHlpLabel);
constraints.fill=GridBagConstraints.BOTH;
constraints.gridwidth=1;
Label incLabel=new Label("Increment",Label.LEFT);
layout.setConstraints(incLabel,constraints);
add(incLabel);
mCtlIncrement=new TextField("$0.00");
layout.setConstraints(mCtlIncrement,constraints);
add(mCtlIncrement);
constraints.gridwidth=GridBagConstraints.REMAINDER;
Label incHlpLabel=new Label("Increment the prepayment(s) by this amount.");
layout.setConstraints(incHlpLabel,constraints);
add(incHlpLabel);
constraints.fill=GridBagConstraints.BOTH;
constraints.gridwidth=1;
Label frqLabel=new Label("Frequency",Label.LEFT);
layout.setConstraints(frqLabel,constraints);
add(frqLabel);
mCtlFrequency=new TextField("0.00");
layout.setConstraints(mCtlFrequency,constraints);
add(mCtlFrequency);
constraints.gridwidth=GridBagConstraints.REMAINDER;
Label frqHlpLabel=new Label("Frequency at which to increment the prepayments (ie) number of months.");
layout.setConstraints(frqHlpLabel,constraints);
add(frqHlpLabel);
constraints.fill=GridBagConstraints.BOTH;
constraints.gridwidth=1;
Label costLabel=new Label("Cost Of Capital:",Label.LEFT);
layout.setConstraints(costLabel,constraints);
add(costLabel);
mCtlCost=new Label("$0.00",Label.LEFT);
// constraints.gridwidth=GridBagConstraints.REMAINDER;
layout.setConstraints(mCtlCost,constraints);
add(mCtlCost);
mCtlMsg=new Label("",Label.LEFT);
constraints.gridwidth=GridBagConstraints.REMAINDER;
layout.setConstraints(mCtlMsg,constraints);
add(mCtlMsg);
}
public boolean action(Event event,Object object)
{
if(null!=mCtlButton&&mCtlButton==event.target)performCalc();
return true;
}
public void performCalc()
{
Prepayment prepayment=new Prepayment();
String strPrincipal=mCtlPrincipal.getText();
String strInterest=mCtlInterest.getText();
String strTerm=mCtlTerm.getText();
String strPrepayment=mCtlPrepayment.getText();
String strIncrement=mCtlIncrement.getText();
String strFrequency=mCtlFrequency.getText();
Double workDouble;
double principal;
double interest;
int term;
int itemIndex;
workDouble=new Double(0);
strPrincipal=strPrincipal.replace('$',' ');
workDouble=workDouble.valueOf(strPrincipal);
principal=workDouble.doubleValue();
strInterest=strInterest.replace('%',' ');
workDouble=workDouble.valueOf(strInterest);
interest=workDouble.doubleValue();
term=Integer.parseInt(strTerm);
strPrepayment=strPrepayment.replace('$',' ');
workDouble=workDouble.valueOf(strPrepayment);
prepayment.amount(workDouble.doubleValue());
strIncrement=strIncrement.replace('$',' ');
workDouble=workDouble.valueOf(strIncrement);
prepayment.increment(workDouble.doubleValue());
workDouble=workDouble.valueOf(strFrequency);
prepayment.frequency(workDouble.doubleValue());
mPurePassThru.issBal(principal);
mPurePassThru.wac(interest);
mPurePassThru.coupon(interest);
mPurePassThru.wam((short)term);
mPurePassThru.origTerm((short)term);
mPurePassThru.psa(0.00);
mCtlMsg.setText("Please wait a few moments...");
mCtlMsg.repaint();
if(0.00!=prepayment.amount()||0.00!=prepayment.increment())generateFlows(prepayment);
else generateFlows();
Money money=new Money(0);
mSpreadSheet.clear();
repaint();
mSpreadSheet.setCellData(0,0,"BeginBal");
mSpreadSheet.setCellData(0,1,"SMM");
mSpreadSheet.setCellData(0,2,"MtgPay");
mSpreadSheet.setCellData(0,3,"NetIntPay");
mSpreadSheet.setCellData(0,4,"GrossIntPay");
mSpreadSheet.setCellData(0,5,"SchedPrinPay");
mSpreadSheet.setCellData(0,6,"Prepayment");
mSpreadSheet.setCellData(0,7,"TotPrin");
mSpreadSheet.setCellData(0,8,"Cashflow");
mSpreadSheet.setCellData(0,9,"Factor");
for(itemIndex=0;itemIndex<mPurePassThru.wam();itemIndex++)
{
if(mPureCashflows[itemIndex]==null)break;
money.setValue(mPureCashflows[itemIndex].beginBal());
mSpreadSheet.setCellData(itemIndex+1,0,money.toString());
money.setValue(mPureCashflows[itemIndex].smm());
mSpreadSheet.setCellData(itemIndex+1,1,money.toString());
money.setValue(mPureCashflows[itemIndex].mtgPay());
mSpreadSheet.setCellData(itemIndex+1,2,money.toString());
money.setValue(mPureCashflows[itemIndex].netIntPay());
mSpreadSheet.setCellData(itemIndex+1,3,money.toString());
money.setValue(mPureCashflows[itemIndex].grossIntPay());
mSpreadSheet.setCellData(itemIndex+1,4,money.toString());
money.setValue(mPureCashflows[itemIndex].schedPrinPay());
mSpreadSheet.setCellData(itemIndex+1,5,money.toString());
money.setValue(mPureCashflows[itemIndex].prepayment());
mSpreadSheet.setCellData(itemIndex+1,6,money.toString());
money.setValue(mPureCashflows[itemIndex].totPrin());
mSpreadSheet.setCellData(itemIndex+1,7,money.toString());
money.setValue(mPureCashflows[itemIndex].cashflow());
mSpreadSheet.setCellData(itemIndex+1,8,money.toString());
mSpreadSheet.setCellData(itemIndex+1,9,String.valueOf(mPureCashflows[itemIndex].factor()));
}
money.setValue(mPureCashflows[itemIndex-1].grossIntPay());
mCtlCost.setText(money.toString());
mCtlMsg.setText("Calculations complete.");
repaint();
}
public void generateFlows()
{
double issBal;
double tmpCPR;
int actualMonth;
int indexFlows;
indexFlows=0;
mPureCashflows=new PureCashflow[mPurePassThru.wam()];
issBal=mPurePassThru.issBal();
for(int wam=mPurePassThru.wam();wam>0&&issBal>0.00;wam--)
{
mPureCashflows[indexFlows]=new PureCashflow();
actualMonth=(mPurePassThru.origTerm()-wam)+1;
if(actualMonth<=30)tmpCPR=.002*(double)actualMonth;
else tmpCPR=.06;
mPureCashflows[indexFlows].beginBal(issBal);
mPureCashflows[indexFlows].smm(1.00-Math.pow(1.00-(tmpCPR*mPurePassThru.psa()/100.00),1.00/12.00));
if(0==indexFlows)mPureCashflows[indexFlows].mtgPay((issBal*(mPurePassThru.wac()/1200.00))/
(1.00-Math.pow(1.00/(1.00+(mPurePassThru.wac()/1200.00)),(double)wam)));
else mPureCashflows[indexFlows].mtgPay(mPureCashflows[indexFlows-1].mtgPay());
if(issBal<=mPureCashflows[indexFlows].mtgPay())mPureCashflows[indexFlows].mtgPay(issBal);
mPureCashflows[indexFlows].netIntPay(issBal*(mPurePassThru.coupon()/1200.00));
if(0==indexFlows)mPureCashflows[indexFlows].grossIntPay(mPureCashflows[indexFlows].netIntPay());
else mPureCashflows[indexFlows].grossIntPay(mPureCashflows[indexFlows-1].grossIntPay()+mPureCashflows[indexFlows].netIntPay());
mPureCashflows[indexFlows].schedPrinPay(mPureCashflows[indexFlows].mtgPay()-mPureCashflows[indexFlows].netIntPay());
mPureCashflows[indexFlows].prepayment(0.00);
mPureCashflows[indexFlows].totPrin(mPureCashflows[indexFlows].schedPrinPay()+mPureCashflows[indexFlows].prepayment());
mPureCashflows[indexFlows].cashflow(mPureCashflows[indexFlows].netIntPay()+mPureCashflows[indexFlows].totPrin());
mPureCashflows[indexFlows].factor(issBal/mPurePassThru.issBal());
issBal-=mPureCashflows[indexFlows].totPrin();
indexFlows++;
}
}
public void generateFlows(Prepayment prepayment)
{
double issBal;
double tmpCPR;
int actualMonth;
int indexFlows;
indexFlows=0;
mPureCashflows=new PureCashflow[mPurePassThru.wam()];
issBal=mPurePassThru.issBal();
for(int wam=mPurePassThru.wam();wam>0&&issBal>0.00;wam--)
{
mPureCashflows[indexFlows]=new PureCashflow();
actualMonth=(mPurePassThru.origTerm()-wam)+1;
if(actualMonth<=30)tmpCPR=.002*(double)actualMonth;
else tmpCPR=.06;
mPureCashflows[indexFlows].beginBal(issBal);
mPureCashflows[indexFlows].smm(1.00-Math.pow(1.00-(tmpCPR*mPurePassThru.psa()/100.00),1.00/12.00));
if(0==indexFlows)mPureCashflows[indexFlows].mtgPay((issBal*(mPurePassThru.wac()/1200.00))/
(1.00-Math.pow(1.00/(1.00+(mPurePassThru.wac()/1200.00)),(double)wam)));
else mPureCashflows[indexFlows].mtgPay(mPureCashflows[indexFlows-1].mtgPay());
if(issBal<=mPureCashflows[indexFlows].mtgPay())mPureCashflows[indexFlows].mtgPay(issBal);
mPureCashflows[indexFlows].netIntPay(issBal*(mPurePassThru.coupon()/1200.00));
if(0==indexFlows)mPureCashflows[indexFlows].grossIntPay(mPureCashflows[indexFlows].netIntPay());
else mPureCashflows[indexFlows].grossIntPay(mPureCashflows[indexFlows-1].grossIntPay()+mPureCashflows[indexFlows].netIntPay());
mPureCashflows[indexFlows].schedPrinPay(mPureCashflows[indexFlows].mtgPay()-mPureCashflows[indexFlows].netIntPay());
mPureCashflows[indexFlows].prepayment(prepayment.amount());
prepayment.period(prepayment.period()+1);
if(prepayment.period()>prepayment.frequency())
{
prepayment.amount(prepayment.amount()+prepayment.increment());
prepayment.period(1);
}
mPureCashflows[indexFlows].totPrin(mPureCashflows[indexFlows].schedPrinPay()+mPureCashflows[indexFlows].prepayment());
mPureCashflows[indexFlows].cashflow(mPureCashflows[indexFlows].netIntPay()+mPureCashflows[indexFlows].totPrin());
mPureCashflows[indexFlows].factor(issBal/mPurePassThru.issBal());
issBal-=mPureCashflows[indexFlows].totPrin();
indexFlows++;
}
}
}

BIN
java/SPREAD/CELL~1.CLA Normal file

Binary file not shown.

View File

@@ -0,0 +1,897 @@
/*
* Adapted 10/98 by Sean Kessler
* Added arrow key navigation
* Added cell scrolling
* Class no longer extends of applet
*
* @(#)SpreadSheet.java 1.17 95/03/09 Sami Shaio
*
* Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.net.*;
//******************************************************************************************************
// ***************************************** SPREADSHEET ***********************************************
//******************************************************************************************************
public class SpreadSheetInterface
{
SpreadSheet mSpreadSheet;
SpreadSheetInteraface(Applet applet)
{
mSpreadSheet=new SpreadSheet(applet,applet.size());
}
SpreadSheetInterface(Applet applet,Dimension controlDimension)
{
mSpreadSheet=new SpreadSheet(applet,controlDimension);
}
}
//public class SpreadSheet
class SpreadSheet
{
private final Dimension mCellDimension=new Dimension(100,15);
private Dimension mControlDimension;
private String mStrTitle;
private Font mTitleFont;
private Color mCellColor;
private Color mInputColor;
private int mTitleHeight=15;
private int mRowLabelWidth=15;
private boolean mIsStopped=false;
private boolean mFullUpdate=true;
private int mRows;
private int mColumns;
private int mSelectedRow = -1;
private int mSelectedColumn = -1;
private SpreadSheetInput mInputArea;
private Cell mCells[][];
private Cell mCurrent=null;
private int mStartDisplayRow;
private int mStartDisplayColumn;
private Applet mApplet;
public SpreadSheet(Applet applet,Dimension controlDimension)
{
String strParam;
mApplet=applet;
mControlDimension=controlDimension;
mStartDisplayRow=0;
mStartDisplayColumn=0;
mCellColor=Color.white;
mInputColor=new Color(100, 100, 225);
mTitleFont=new Font("Courier", Font.BOLD, 12);
mStrTitle=mApplet.getParameter("title");
if(null==mStrTitle)mStrTitle="SpreadSheet";
strParam=mApplet.getParameter("rows");
if(null==strParam)mRows=9;
else mRows=Integer.parseInt(strParam);
strParam=mApplet.getParameter("columns");
if(null==strParam)mColumns=5;
else mColumns=Integer.parseInt(strParam);
mCells=new Cell[mRows][mColumns];
char strLabel[]=new char[1];
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
mCells[row][col]=new Cell(this,Color.lightGray,Color.black,mCellColor,mCellDimension.width-2,mCellDimension.height-2);
strLabel[0]=(char)((int)'a'+col);
strParam=mApplet.getParameter(""+new String(strLabel)+(row+1));
if(null!=strParam)mCells[row][col].setUnparsedValue(strParam);
}
}
mInputArea=new SpreadSheetInput(null,mApplet,this,mControlDimension.width-2,mCellDimension.height-1,mInputColor,Color.white);
mApplet.resize(mColumns*mCellDimension.width+mRowLabelWidth,((mRows+1)*mCellDimension.height)+mCellDimension.height+mTitleHeight);
}
public void setCurrentValue(float val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(val);
mApplet.repaint();
}
public void stop()
{
stopped(true);
}
public void start()
{
stopped(false);
}
public void stopped(boolean stopped)
{
mIsStopped=stopped;
}
public boolean stopped()
{
return mIsStopped;
}
public void destroy()
{
}
public void setCurrentValue(int type,String val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(type,val);
mApplet.repaint();
}
public void update(Graphics graphics)
{
int cx;
int cy;
if(mFullUpdate)
{
paint(graphics);
mFullUpdate=false;
return;
}
graphics.setFont(mTitleFont);
graphics.clipRect(0,0,mControlDimension.width,mControlDimension.height);
for(int row=mStartDisplayRow;row<mRows;row++)
{
for(int col=mStartDisplayColumn;col<mColumns;col++)
{
if(mCells[row][col].needRedisplay())
{
cx=(col*mCellDimension.width)+2+mRowLabelWidth;
cy=((row+1)*mCellDimension.height)+2+mTitleHeight;
mCells[row][col].paint(graphics,cx,cy);
}
}
}
}
public synchronized void paint(Graphics graphics)
{
char strLabel[]=new char[1];
int i;
int j;
int cx;
int cy;
graphics.clipRect(0,0,mControlDimension.width,mControlDimension.height);
graphics.setFont(mTitleFont);
graphics.drawString(mStrTitle,(mControlDimension.width-graphics.getFontMetrics().stringWidth(mStrTitle))/2,12);
graphics.setColor(mInputColor);
graphics.fillRect(0,mCellDimension.height,mControlDimension.width,mCellDimension.height);
graphics.setFont(mTitleFont);
for(i=0;i<mRows+1;i++)
{
cy=(i+2)*mCellDimension.height;
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,cy,mControlDimension.width,2,true);
if(i<mRows)
{
graphics.setColor(mApplet.getBackground());
graphics.fillRect(1,cy+1,mRowLabelWidth-1,(2*mCellDimension.height)-2);
graphics.setColor(Color.red);
graphics.drawString(""+(i+1+mStartDisplayRow),2,cy+12);
}
}
graphics.setColor(Color.red);
for(i=0;i<mColumns;i++)
{
cx=i*mCellDimension.width;
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(cx+mRowLabelWidth,2*mCellDimension.height,1,mControlDimension.height,true);
}
for(i=mStartDisplayRow;i<mRows;i++)
{
for(j=mStartDisplayColumn;j<mColumns;j++)
{
cx=((j-mStartDisplayColumn)*mCellDimension.width)+2+mRowLabelWidth;
cy=((i+1-mStartDisplayRow)*mCellDimension.height)+2+mTitleHeight;
if(mCells[i][j]!=null)mCells[i][j].paint(graphics,cx,cy);
}
}
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,mTitleHeight,mControlDimension.width,mControlDimension.height-mTitleHeight,false);
mInputArea.paint(graphics,1,mTitleHeight+1);
}
public void recalculate()
{
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row+mStartDisplayRow][col+mStartDisplayColumn]!=null&&mCells[row+mStartDisplayRow][col+mStartDisplayColumn].type()==Cell.FORMULA)
{
mCells[row+mStartDisplayRow][col+mStartDisplayColumn].setRawValue(evaluateFormula(mCells[row+mStartDisplayRow][col+mStartDisplayColumn].parseRoot()));
mCells[row+mStartDisplayRow][col+mStartDisplayColumn].needRedisplay(true);
}
}
}
mApplet.repaint();
}
private float evaluateFormula(Node node)
{
float val=0.0f;
if(null==node)return val;
switch(node.type())
{
case Node.OP:
val=evaluateFormula(node.left());
switch(node.op())
{
case '+':
val += evaluateFormula(node.right());
break;
case '*':
val *= evaluateFormula(node.right());
break;
case '-':
val -= evaluateFormula(node.right());
break;
case '/':
val /= evaluateFormula(node.right());
break;
}
break;
case Node.VALUE:
val=node.value();
break;
case Node.CELL:
if(null==node)break;
if(null==mCells[node.row()][node.column()])break;
val=mCells[node.row()][node.column()].value();
break;
}
return val;
}
public boolean mouseDown(Event evt,int x,int y)
{
if(y<(mTitleHeight+mCellDimension.height))
{
mSelectedRow=-1;
if(y<=mTitleHeight)deselect(true);
return true;
}
if(x<mRowLabelWidth)
{
mSelectedRow=-1;
deselect(true);
return true;
}
mSelectedRow=((y-mCellDimension.height-mTitleHeight)/mCellDimension.height)+mStartDisplayRow;
mSelectedColumn=(x-mRowLabelWidth)/mCellDimension.width;
if(mSelectedRow>=mRows||mSelectedColumn>=mColumns)
{
mSelectedRow = -1;
deselect(true);
return true;
}
select();
return true;
}
public boolean keyDown(Event evt, int key)
{
mFullUpdate=true;
if(Key.LeftArrow==key||Key.RightArrow==key||Key.UpArrow==key||Key.DownArrow==key)
{
mInputArea.keyDown(Key.Return);
navigate(key);
}
else mInputArea.keyDown(key);
return true;
}
private void navigate(int key)
{
switch(key)
{
case Key.LeftArrow :
if(mSelectedColumn<=0)break;
mSelectedColumn--;
ensureVisible();
select();
break;
case Key.RightArrow :
if(mSelectedColumn+1>=mColumns)break;
mSelectedColumn++;
ensureVisible();
select();
break;
case Key.UpArrow :
if(mSelectedRow<=0)break;
mSelectedRow--;
ensureVisible();
select();
break;
case Key.DownArrow :
if(mSelectedRow+1>=mRows)break;
mSelectedRow++;
ensureVisible();
select();
break;
}
}
private void select()
{
Cell cell=mCells[mSelectedRow][mSelectedColumn];
if(null!=cell.getPrintString())mInputArea.setText(new String(cell.getPrintString()));
else mInputArea.setText(new String(""));
if(mCurrent!=null)mCurrent.deselect();
mCurrent=cell;
mCurrent.select();
mApplet.requestFocus();
mFullUpdate=true;
mApplet.repaint();
}
private void deselect(boolean destroy)
{
if(null==mCurrent)return;
mCurrent.deselect();
if(destroy)mCurrent=null;
}
public Applet applet()
{
return mApplet;
}
private void ensureVisible()
{
int yMin=(2*mCellDimension.height)+2+mTitleHeight;
int xMin=2+mRowLabelWidth+mCellDimension.width;
Point currPoint=new Point(0,0);
currPoint.y=((mSelectedRow-mStartDisplayRow+2)*mCellDimension.height)+2+mTitleHeight;
currPoint.x=((mSelectedColumn-mStartDisplayColumn)*mCellDimension.width)+2+mRowLabelWidth+mCellDimension.width;
if(currPoint.y>mControlDimension.height)mStartDisplayRow++;
else if(currPoint.y<yMin)mStartDisplayRow--;
if(currPoint.x>mControlDimension.width)mStartDisplayColumn++;
else if(currPoint.x<xMin)mStartDisplayColumn--;
}
}
//******************************************************************************************************
// ******************************************** CELL ***************************************************
//******************************************************************************************************
class Cell
{
public static final int VALUE = 0;
public static final int LABEL = 1;
public static final int URL = 2;
public static final int FORMULA = 3;
private Node mParseRoot;
private boolean mNeedRedisplay;
private boolean mSelected = false;
private boolean mTransientValue = false;
private int mType=Cell.VALUE;
private String mValueString = "";
private String mPrintString = "v";
private float mValue;
private Color mBgColor;
private Color mFgColor;
private Color mHighlightColor;
private int mWidth;
private int mHeight;
private SpreadSheet mSpreadSheet;
private boolean mPaused=false;
public Cell(SpreadSheet spreadSheet,Color bgColor,Color fgColor,Color highlightColor,int width,int height)
{
mSpreadSheet=spreadSheet;
mBgColor=bgColor;
mFgColor=fgColor;
mHighlightColor=highlightColor;
mWidth=width;
mHeight=height;
mNeedRedisplay=true;
}
public void setRawValue(float value)
{
mValueString=Float.toString(value);
mValue=value;
}
public void setValue(float value)
{
setRawValue(value);
mPrintString="v"+mValueString;
mType=Cell.VALUE;
mPaused=false;
mSpreadSheet.recalculate();
mNeedRedisplay=true;
}
public void setTransientValue(float value)
{
mTransientValue=true;
mValue=value;
mNeedRedisplay=true;
mSpreadSheet.recalculate();
}
public void setUnparsedValue(String s)
{
switch (s.charAt(0))
{
case 'v':
setValue(Cell.VALUE, s.substring(1));
break;
case 'f':
setValue(Cell.FORMULA, s.substring(1));
break;
case 'l':
setValue(Cell.LABEL, s.substring(1));
break;
case 'u':
setValue(Cell.URL, s.substring(1));
break;
}
}
public String parseFormula(String formula, Node node)
{
String subformula;
String restFormula;
float value;
int length = formula.length();
Node left;
Node right;
char op;
if(null==formula)return null;
subformula=parseValue(formula, node);
if(null==subformula||0==subformula.length())return null;
if(subformula==formula)return formula;
switch(op=subformula.charAt(0))
{
case 0:
return null;
case ')':
return subformula;
case '+':
case '*':
case '-':
case '/':
restFormula = subformula.substring(1);
subformula = parseValue(restFormula, right=new Node());
if(subformula != restFormula)
{
left = new Node(node);
node.left(left);
node.right(right);
node.op(op);
node.type(Node.OP);
return subformula;
}
else return formula;
default:
return formula;
}
}
public String parseValue(String formula, Node node)
{
char c=formula.charAt(0);
String subformula;
String restFormula;
float value;
int row;
int column;
restFormula = formula;
if (c == '(')
{
restFormula = formula.substring(1);
subformula = parseFormula(restFormula, node);
if(subformula == null || subformula.length() == restFormula.length())return formula;
else if (! (subformula.charAt(0) == ')'))return formula;
restFormula = subformula;
}
else if (c >= '0' && c <= '9')
{
int i;
try{value = Float.valueOf(formula).floatValue();}
catch (NumberFormatException exception){return formula;}
for (i=0; i < formula.length(); i++)
{
c = formula.charAt(i);
if ((c < '0' || c > '9') && c != '.')break;
}
node.type(Node.VALUE);
node.value(value);
restFormula = formula.substring(i);
return restFormula;
}
else if (c >= 'A' && c <= 'Z')
{
int i;
column = c - 'A';
restFormula = formula.substring(1);
row = Float.valueOf(restFormula).intValue();
for(i=0; i < restFormula.length(); i++)
{
c = restFormula.charAt(i);
if (c < '0' || c > '9')break;
}
node.row(row-1);
node.column(column);
node.type(Node.CELL);
if (i == restFormula.length())restFormula=null;
else
{
restFormula = restFormula.substring(i);
if (restFormula.charAt(0) == 0)return null;
}
}
return restFormula;
}
public void setValue(int type, String s)
{
mPaused=false;
mValueString=new String(s);
mType=type;
mNeedRedisplay=true;
switch(mType)
{
case Cell.VALUE:
setValue(Float.valueOf(s).floatValue());
break;
case Cell.LABEL:
mPrintString = "l" + mValueString;
break;
case Cell.URL:
mPrintString = "u" + mValueString;
break;
case Cell.FORMULA:
parseFormula(mValueString,mParseRoot=new Node());
mPrintString = "f" + mValueString;
break;
}
mSpreadSheet.recalculate();
}
public String getValueString()
{
return mValueString;
}
public String getPrintString()
{
return mPrintString;
}
public void select()
{
mSelected=true;
mPaused=true;
}
public void deselect()
{
mSelected=false;
mPaused=false;
mNeedRedisplay=true;
mSpreadSheet.applet().repaint();
}
public void paint(Graphics graphics,int x,int y)
{
if(mSelected)graphics.setColor(mHighlightColor);
else graphics.setColor(mBgColor);
graphics.fillRect(x+1,y+1,mWidth-1,mHeight-1);
if(null!=mValueString)
{
switch(mType)
{
case Cell.VALUE:
case Cell.LABEL:
graphics.setColor(mFgColor);
break;
case Cell.FORMULA:
graphics.setColor(Color.red);
break;
case Cell.URL:
graphics.setColor(Color.blue);
break;
}
if(!mTransientValue)
{
if(mValueString.length()>14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
}
else graphics.drawString(""+mValue,x,y+(mHeight/2)+5);
mNeedRedisplay=false;
}
}
public int type()
{
return mType;
}
public Node parseRoot()
{
return mParseRoot;
}
public void needRedisplay(boolean needRedisplay)
{
mNeedRedisplay=needRedisplay;
}
public boolean needRedisplay()
{
return mNeedRedisplay;
}
public float value()
{
return mValue;
}
public SpreadSheet spreadSheet()
{
return mSpreadSheet;
}
public boolean paused()
{
return mPaused;
}
}
//******************************************************************************************************
// *************************************** NODE *******************************************************
//******************************************************************************************************
class Node
{
public static final int OP = 0;
public static final int VALUE = 1;
public static final int CELL = 2;
private int mType;
private Node mLeft;
private Node mRight;
private int mRow;
private int mColumn;
private float mValue;
private char mOp;
public Node()
{
mLeft=null;
mRight=null;
mValue=0;
mRow=-1;
mColumn=-1;
mOp=0;
mType=Node.VALUE;
}
public Node(Node node)
{
mLeft=node.mLeft;
mRight=node.mRight;
mValue=node.mValue;
mRow=node.mRow;
mColumn=node.mColumn;
mOp=node.mOp;
mType=node.mType;
}
public void print(int indentLevel)
{
char l[] = new char[1];
switch(mType)
{
case Node.VALUE:
break;
case Node.CELL:
l[0] = (char)((int)'A' + column());
break;
case Node.OP:
mLeft.print(indentLevel + 3);
mRight.print(indentLevel + 3);
break;
}
}
public int type()
{
return mType;
}
public void type(int type)
{
mType=type;
}
public float value()
{
return mValue;
}
public void value(float value)
{
mValue=value;
}
public Node left()
{
return mLeft;
}
public void left(Node left)
{
mLeft=left;
}
public Node right()
{
return mRight;
}
public void right(Node right)
{
mRight=right;
}
public char op()
{
return mOp;
}
public void op(char op)
{
mOp=op;
}
public int row()
{
return mRow;
}
public void row(int row)
{
mRow=row;
}
public int column()
{
return mColumn;
}
public void column(int column)
{
mColumn=column;
}
}
class InputField
{
private int mMaxchars = 50;
private Applet mApplet;
private String mStringValue;
private char mBuffer[];
private int mChars;
private int mWidth;
private int mHeight;
private Color mBgColor;
private Color mFgColor;
public InputField(String initValue,Applet applet,int width,int height,Color bgColor, Color fgColor)
{
mWidth=width;
mHeight=height;
mBgColor=bgColor;
mFgColor=fgColor;
mApplet=applet;
mBuffer = new char[mMaxchars];
mChars = 0;
if(initValue != null)
{
initValue.getChars(0, initValue.length(),mBuffer, 0);
mChars = initValue.length();
}
mStringValue=initValue;
}
public void setText(String val)
{
int i;
for(i=0; i < mMaxchars; i++)mBuffer[i] = 0;
mStringValue=new String(val);
if (val == null)
{
mStringValue= "";
mChars = 0;
mBuffer[0] = 0;
}
else
{
mStringValue.getChars(0,mStringValue.length(), mBuffer, 0);
mChars = val.length();
mStringValue = new String(mBuffer);
}
}
public String getValue()
{
return mStringValue;
}
public void paint(Graphics g, int x, int y)
{
g.setColor(mBgColor);
g.fillRect(x, y,mWidth,mHeight);
if(mStringValue!= null)
{
g.setColor(mFgColor);
g.drawString(mStringValue, x, y + (mHeight / 2) + 3);
}
}
public void mouseUp(int x, int y)
{
}
public void keyDown(int key)
{
if(mChars<mMaxchars)
{
switch(key)
{
case Key.BackSpace :
--mChars;
if(mChars<0)mChars=0;
mBuffer[mChars] = 0;
mStringValue = new String(new String(mBuffer));
break;
case Key.Return :
selected();
break;
default:
mBuffer[mChars++] = (char)key;
mStringValue = new String(new String(mBuffer));
break;
}
}
mApplet.repaint();
}
public void selected()
{
}
public Applet applet()
{
return mApplet;
}
}
class SpreadSheetInput extends InputField
{
SpreadSheet mSpreadSheet;
public SpreadSheetInput(String initValue,Applet app,SpreadSheet spreadSheet,int width,int height,Color bgColor,Color fgColor)
{
super(initValue,app,width,height,bgColor,fgColor);
mSpreadSheet=spreadSheet;
}
public void selected()
{
float f;
switch(getValue().charAt(0))
{
case 'v':
try{f=Float.valueOf(getValue().substring(1)).floatValue();mSpreadSheet.setCurrentValue(f);}
catch(Exception exception){;}
break;
case 'l':
mSpreadSheet.setCurrentValue(Cell.LABEL,getValue().substring(1));
break;
case 'u':
mSpreadSheet.setCurrentValue(Cell.URL,getValue().substring(1));
break;
case 'f':
mSpreadSheet.setCurrentValue(Cell.FORMULA,getValue().substring(1));
break;
}
}
}
class Key
{
public static final int LeftArrow=1006;
public static final int RightArrow=1007;
public static final int UpArrow=1004;
public static final int DownArrow=1005;
public static final int BackSpace=8;
public static final int Return=10;
public Key()
{
}
};

View File

@@ -0,0 +1,869 @@
/*
* @(#)SpreadSheet.java 1.17 95/03/09 Sami Shaio
*
* Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.lang.*;
import java.net.*;
public class SpreadSheet extends Applet {
String title;
Font titleFont;
Color cellColor;
Color inputColor;
int cellWidth = 100;
int cellHeight = 15;
int titleHeight = 15;
int rowLabelWidth = 15;
Font inputFont;
boolean isStopped = false;
boolean fullUpdate = true;
int rows;
int columns;
int currentKey = -1;
int selectedRow = -1;
int selectedColumn = -1;
SpreadSheetInput inputArea;
Cell cells[][];
Cell current = null;
public synchronized void init() {
String rs;
cellColor = Color.white;
inputColor = new Color(100, 100, 225);
inputFont = new Font("Courier", Font.PLAIN, 10);
titleFont = new Font("Courier", Font.BOLD, 12);
title = getParameter("title");
if (title == null) {
title = "Spreadsheet";
}
rs = getParameter("rows");
if (rs == null) {
rows = 9;
} else {
rows = Integer.parseInt(rs);
}
rs = getParameter("columns");
if (rs == null) {
columns = 5;
} else {
columns = Integer.parseInt(rs);
}
cells = new Cell[rows][columns];
char l[] = new char[1];
for (int i=0; i < rows; i++) {
for (int j=0; j < columns; j++) {
cells[i][j] = new Cell(this,
Color.lightGray,
Color.black,
cellColor,
cellWidth - 2,
cellHeight - 2);
l[0] = (char)((int)'a' + j);
rs = getParameter("" + new String(l) + (i+1));
if (rs != null) {
cells[i][j].setUnparsedValue(rs);
}
}
}
Dimension d = size();
inputArea = new SpreadSheetInput(null, this, d.width - 2, cellHeight - 1,
inputColor, Color.white);
resize(columns * cellWidth + rowLabelWidth,
((rows + 1) * cellHeight) + cellHeight + titleHeight);
}
public void setCurrentValue(float val) {
if (selectedRow == -1 || selectedColumn == -1) {
return;
}
cells[selectedRow][selectedColumn].setValue(val);
repaint();
}
public void stop() {
isStopped = true;
}
public void start() {
isStopped = false;
}
public void destroy() {
for (int i=0; i < rows; i++) {
for (int j=0; j < columns; j++) {
if (cells[i][j].type == Cell.URL) {
cells[i][j].updaterThread.stop();
}
}
}
}
public void setCurrentValue(int type, String val) {
if (selectedRow == -1 || selectedColumn == -1) {
return;
}
cells[selectedRow][selectedColumn].setValue(type, val);
repaint();
}
public void update(Graphics g) {
if (! fullUpdate) {
int cx, cy;
g.setFont(titleFont);
for (int i=0; i < rows; i++) {
for (int j=0; j < columns; j++) {
if (cells[i][j].needRedisplay) {
cx = (j * cellWidth) + 2 + rowLabelWidth;
cy = ((i+1) * cellHeight) + 2 + titleHeight;
cells[i][j].paint(g, cx, cy);
}
}
}
} else {
paint(g);
fullUpdate = false;
}
}
public void recalculate() {
int i,j;
//System.out.println("SpreadSheet.recalculate");
for (i=0; i < rows; i++) {
for (j=0; j < columns; j++) {
if (cells[i][j] != null && cells[i][j].type == Cell.FORMULA) {
cells[i][j].setRawValue(evaluateFormula(cells[i][j].parseRoot));
cells[i][j].needRedisplay = true;
}
}
}
repaint();
}
public float evaluateFormula(Node n) {
float val = 0.0f;
//System.out.println("evaluateFormula:");
//n.print(3);
if (n == null) {
//System.out.println("Null node");
return val;
}
switch (n.type) {
case Node.OP:
val = evaluateFormula(n.left);
switch (n.op) {
case '+':
val += evaluateFormula(n.right);
break;
case '*':
val *= evaluateFormula(n.right);
break;
case '-':
val -= evaluateFormula(n.right);
break;
case '/':
val /= evaluateFormula(n.right);
break;
}
break;
case Node.VALUE:
//System.out.println("=>" + n.value);
return n.value;
case Node.CELL:
if (n == null) {
//System.out.println("NULL at 192");
} else {
if (cells[n.row][n.column] == null) {
//System.out.println("NULL at 193");
} else {
//System.out.println("=>" + cells[n.row][n.column].value);
return cells[n.row][n.column].value;
}
}
}
//System.out.println("=>" + val);
return val;
}
public synchronized void paint(Graphics g) {
int i, j;
int cx, cy;
char l[] = new char[1];
Dimension d = size();
g.setFont(titleFont);
i = g.getFontMetrics().stringWidth(title);
g.drawString((title == null) ? "Spreadsheet" : title,
(d.width - i) / 2, 12);
g.setColor(inputColor);
g.fillRect(0, cellHeight, d.width, cellHeight);
g.setFont(titleFont);
for (i=0; i < rows+1; i++) {
cy = (i+2) * cellHeight;
g.setColor(getBackground());
g.draw3DRect(0, cy, d.width, 2, true);
if (i < rows) {
g.setColor(Color.red);
g.drawString("" + (i+1), 2, cy + 12);
}
}
g.setColor(Color.red);
for (i=0; i < columns; i++) {
cx = i * cellWidth;
g.setColor(getBackground());
g.draw3DRect(cx + rowLabelWidth,
2 * cellHeight, 1, d.height, true);
if (i < columns) {
g.setColor(Color.red);
l[0] = (char)((int)'A' + i);
g.drawString(new String(l),
cx + rowLabelWidth + (cellWidth / 2),
d.height - 3);
}
}
for (i=0; i < rows; i++) {
for (j=0; j < columns; j++) {
cx = (j * cellWidth) + 2 + rowLabelWidth;
cy = ((i+1) * cellHeight) + 2 + titleHeight;
if (cells[i][j] != null) {
cells[i][j].paint(g, cx, cy);
}
}
}
g.setColor(getBackground());
g.draw3DRect(0, titleHeight,
d.width,
d.height - titleHeight,
false);
inputArea.paint(g, 1, titleHeight + 1);
}
public boolean mouseDown(Event evt, int x, int y)
{
Cell cell;
if (y < (titleHeight + cellHeight))
{
selectedRow = -1;
if (y <= titleHeight && current != null)
{
current.deselect();
current = null;
}
return true;
}
if (x < rowLabelWidth)
{
selectedRow = -1;
if (current != null) {
current.deselect();
current = null;
}
return true;
}
selectedRow = ((y - cellHeight - titleHeight) / cellHeight);
selectedColumn = (x - rowLabelWidth) / cellWidth;
if (selectedRow > rows || selectedColumn >= columns)
{
selectedRow = -1;
if(current != null)
{
current.deselect();
current = null;
}
}
else
{
if (selectedRow >= rows)
{
selectedRow = -1;
if (current != null)
{
current.deselect();
current = null;
}
return true;
}
cell = cells[selectedRow][selectedColumn];
// inputArea.setText(new String(cell.getPrintString()));
// smk
if(null!=cell.getPrintString())inputArea.setText(new String(cell.getPrintString()));
else inputArea.setText(new String(""));
if (current != null)current.deselect();
current = cell;
current.select();
requestFocus();
fullUpdate = true;
repaint();
}
return true;
}
public boolean keyDown(Event evt, int key)
{
fullUpdate=true;
inputArea.keyDown(key);
return true;
}
}
class CellUpdater extends Thread {
Cell target;
InputStream dataStream = null;
StreamTokenizer tokenStream;
public CellUpdater(Cell c) {
super("cell updater");
target = c;
}
public void run() {
try {
dataStream = new URL(target.app.getDocumentBase(),
target.getValueString()).openStream();
tokenStream = new StreamTokenizer(dataStream);
tokenStream.eolIsSignificant(false);
while (true) {
switch (tokenStream.nextToken()) {
case tokenStream.TT_EOF:
dataStream.close();
return;
default:
break;
case tokenStream.TT_NUMBER:
target.setTransientValue((float)tokenStream.nval);
if (! target.app.isStopped && ! target.paused) {
target.app.repaint();
}
break;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
break;
}
}
} catch (IOException e) {
return;
}
}
}
class Cell {
public static final int VALUE = 0;
public static final int LABEL = 1;
public static final int URL = 2;
public static final int FORMULA = 3;
Node parseRoot;
boolean needRedisplay;
boolean selected = false;
boolean transientValue = false;
public int type = Cell.VALUE;
String valueString = "";
String printString = "v";
float value;
Color bgColor;
Color fgColor;
Color highlightColor;
int width;
int height;
SpreadSheet app;
CellUpdater updaterThread;
boolean paused = false;
public Cell(SpreadSheet app,Color bgColor,Color fgColor,Color highlightColor,int width,int height)
{
this.app = app;
this.bgColor = bgColor;
this.fgColor = fgColor;
this.highlightColor = highlightColor;
this.width = width;
this.height = height;
needRedisplay = true;
}
public void setRawValue(float f)
{
valueString=Float.toString(f);
value = f;
}
public void setValue(float f) {
setRawValue(f);
printString = "v" + valueString;
type = Cell.VALUE;
paused = false;
app.recalculate();
needRedisplay = true;
}
public void setTransientValue(float f) {
transientValue = true;
value = f;
needRedisplay = true;
app.recalculate();
}
public void setUnparsedValue(String s) {
switch (s.charAt(0)) {
case 'v':
setValue(Cell.VALUE, s.substring(1));
break;
case 'f':
setValue(Cell.FORMULA, s.substring(1));
break;
case 'l':
setValue(Cell.LABEL, s.substring(1));
break;
case 'u':
setValue(Cell.URL, s.substring(1));
break;
}
}
/**
* Parse a spreadsheet formula. The syntax is defined as:
*
* formula -> value
* formula -> value op value
* value -> '(' formula ')'
* value -> cell
* value -> <number>
* op -> '+' | '*' | '/' | '-'
* cell -> <letter><number>
*/
public String parseFormula(String formula, Node node) {
String subformula;
String restFormula;
float value;
int length = formula.length();
Node left;
Node right;
char op;
if (formula == null) {
return null;
}
subformula = parseValue(formula, node);
//System.out.println("subformula = " + subformula);
if (subformula == null || subformula.length() == 0) {
//System.out.println("Parse succeeded");
return null;
}
if (subformula == formula) {
//System.out.println("Parse failed");
return formula;
}
// parse an operator and then another value
switch (op = subformula.charAt(0)) {
case 0:
//System.out.println("Parse succeeded");
return null;
case ')':
//System.out.println("Returning subformula=" + subformula);
return subformula;
case '+':
case '*':
case '-':
case '/':
restFormula = subformula.substring(1);
subformula = parseValue(restFormula, right=new Node());
//System.out.println("subformula(2) = " + subformula);
if (subformula != restFormula) {
//System.out.println("Parse succeeded");
left = new Node(node);
node.left = left;
node.right = right;
node.op = op;
node.type = Node.OP;
//node.print(3);
return subformula;
} else {
//System.out.println("Parse failed");
return formula;
}
default:
//System.out.println("Parse failed (bad operator): " + subformula);
return formula;
}
}
public String parseValue(String formula, Node node) {
char c = formula.charAt(0);
String subformula;
String restFormula;
float value;
int row;
int column;
//System.out.println("parseValue: " + formula);
restFormula = formula;
if (c == '(') {
//System.out.println("parseValue(" + formula + ")");
restFormula = formula.substring(1);
subformula = parseFormula(restFormula, node);
//System.out.println("rest=(" + subformula + ")");
if (subformula == null ||
subformula.length() == restFormula.length()) {
//System.out.println("Failed");
return formula;
} else if (! (subformula.charAt(0) == ')')) {
//System.out.println("Failed (missing parentheses)");
return formula;
}
restFormula = subformula;
} else if (c >= '0' && c <= '9') {
int i;
//System.out.println("formula=" + formula);
try {
value = Float.valueOf(formula).floatValue();
} catch (NumberFormatException e) {
//System.out.println("Failed (number format error)");
return formula;
}
for (i=0; i < formula.length(); i++) {
c = formula.charAt(i);
if ((c < '0' || c > '9') && c != '.') {
break;
}
}
node.type = Node.VALUE;
node.value = value;
//node.print(3);
restFormula = formula.substring(i);
//System.out.println("value= " + value + " i=" + i +
// " rest = " + restFormula);
return restFormula;
} else if (c >= 'A' && c <= 'Z') {
int i;
column = c - 'A';
restFormula = formula.substring(1);
row = Float.valueOf(restFormula).intValue();
//System.out.println("row = " + row + " column = " + column);
for (i=0; i < restFormula.length(); i++) {
c = restFormula.charAt(i);
if (c < '0' || c > '9') {
break;
}
}
node.row = row - 1;
node.column = column;
node.type = Node.CELL;
//node.print(3);
if (i == restFormula.length()) {
restFormula = null;
} else {
restFormula = restFormula.substring(i);
if (restFormula.charAt(0) == 0) {
return null;
}
}
}
return restFormula;
}
public void setValue(int type, String s) {
paused = false;
if (this.type == Cell.URL) {
updaterThread.stop();
updaterThread = null;
}
valueString = new String(s);
this.type = type;
needRedisplay = true;
switch (type) {
case Cell.VALUE:
setValue(Float.valueOf(s).floatValue());
break;
case Cell.LABEL:
printString = "l" + valueString;
break;
case Cell.URL:
printString = "u" + valueString;
updaterThread = new CellUpdater(this);
updaterThread.start();
break;
case Cell.FORMULA:
parseFormula(valueString, parseRoot = new Node());
printString = "f" + valueString;
break;
}
app.recalculate();
}
public String getValueString() {
return valueString;
}
public String getPrintString() {
return printString;
}
public void select() {
selected = true;
paused = true;
}
public void deselect() {
selected = false;
paused = false;
needRedisplay = true;
app.repaint();
}
public void paint(Graphics g, int x, int y) {
if (selected) {
g.setColor(highlightColor);
} else {
g.setColor(bgColor);
}
g.fillRect(x, y, width - 1, height);
if (valueString != null)
{
switch (type) {
case Cell.VALUE:
case Cell.LABEL:
g.setColor(fgColor);
break;
case Cell.FORMULA:
g.setColor(Color.red);
break;
case Cell.URL:
g.setColor(Color.blue);
break;
}
if (transientValue){
g.drawString("" + value, x, y + (height / 2) + 5);
} else {
if (valueString.length() > 14) {
g.drawString(valueString.substring(0, 14),
x, y + (height / 2) + 5);
} else {
g.drawString(valueString, x, y + (height / 2) + 5);
}
}
}
needRedisplay = false;
}
}
class Node {
public static final int OP = 0;
public static final int VALUE = 1;
public static final int CELL = 2;
int type;
Node left;
Node right;
int row;
int column;
float value;
char op;
public Node() {
left = null;
right = null;
value = 0;
row = -1;
column = -1;
op = 0;
type = Node.VALUE;
}
public Node(Node n) {
left = n.left;
right = n.right;
value = n.value;
row = n.row;
column = n.column;
op = n.op;
type = n.type;
}
public void indent(int ind) {
for (int i = 0; i < ind; i++) {
System.out.print(" ");
}
}
public void print(int indentLevel) {
char l[] = new char[1];
indent(indentLevel);
System.out.println("NODE type=" + type);
indent(indentLevel);
switch (type) {
case Node.VALUE:
System.out.println(" value=" + value);
break;
case Node.CELL:
l[0] = (char)((int)'A' + column);
System.out.println(" cell=" + new String(l) + (row+1));
break;
case Node.OP:
System.out.println(" op=" + op);
left.print(indentLevel + 3);
right.print(indentLevel + 3);
break;
}
}
}
class InputField
{
int maxchars = 50;
int cursorPos = 0;
Applet app;
String sval;
char buffer[];
int nChars;
int width;
int height;
Color bgColor;
Color fgColor;
public InputField(String initValue, Applet app, int width, int height,Color bgColor, Color fgColor) {
this.width = width;
this.height = height;
this.bgColor = bgColor;
this.fgColor = fgColor;
this.app = app;
buffer = new char[maxchars];
nChars = 0;
if (initValue != null) {
initValue.getChars(0, initValue.length(), this.buffer, 0);
nChars = initValue.length();
}
sval = initValue;
}
public void setText(String val) {
int i;
for (i=0; i < maxchars; i++) {
buffer[i] = 0;
}
sval = new String(val);
if (val == null) {
sval = "";
nChars = 0;
buffer[0] = 0;
} else {
sval.getChars(0, sval.length(), buffer, 0);
nChars = val.length();
sval = new String(buffer);
}
}
public String getValue() {
return sval;
}
public void paint(Graphics g, int x, int y) {
g.setColor(bgColor);
g.fillRect(x, y, width, height);
if (sval != null) {
g.setColor(fgColor);
g.drawString(sval, x, y + (height / 2) + 3);
}
}
public void mouseUp(int x, int y) {
// set the edit position
}
public void keyDown(int key) {
if (nChars < maxchars) {
switch (key) {
case 8: // delete
--nChars;
if (nChars < 0) {
nChars = 0;
}
buffer[nChars] = 0;
sval = new String(new String(buffer));
break;
case 10: // return
selected();
break;
default:
buffer[nChars++] = (char)key;
sval = new String(new String(buffer));
break;
}
}
app.repaint();
}
public void selected() {
}
}
class SpreadSheetInput extends InputField
{
public SpreadSheetInput(String initValue,SpreadSheet app,int width,int height,Color bgColor,Color fgColor)
{
super(initValue, app, width, height, bgColor, fgColor);
}
public void selected()
{
float f;
switch (sval.charAt(0))
{
case 'v':
try
{
f = Float.valueOf(sval.substring(1)).floatValue();
((SpreadSheet)app).setCurrentValue(f);
}
catch(NumberFormatException e){System.out.println("Not a float...");}
break;
case 'l':
((SpreadSheet)app).setCurrentValue(Cell.LABEL, sval.substring(1));
break;
case 'u':
((SpreadSheet)app).setCurrentValue(Cell.URL, sval.substring(1));
break;
case 'f':
((SpreadSheet)app).setCurrentValue(Cell.FORMULA, sval.substring(1));
break;
}
}
}

View File

@@ -0,0 +1,971 @@
/*
* Adapted 10/98 by Sean Kessler
* Added arrow key navigation
* Added cell scrolling
*
* @(#)SpreadSheet.java 1.17 95/03/09 Sami Shaio
*
* Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.net.*;
//******************************************************************************************************
// ***************************************** SPREADSHEET ***********************************************
//******************************************************************************************************
public class SpreadSheet extends Applet
{
private final Dimension mCellDimension=new Dimension(100,15);
private final int mLeftArrow=1006;
private final int mRightArrow=1007;
private final int mUpArrow=1004;
private final int mDownArrow=1005;
private String mStrTitle;
private Font mTitleFont;
private Color mCellColor;
private Color mInputColor;
private int mTitleHeight=15;
private int mRowLabelWidth=15;
private boolean mIsStopped=false;
private boolean mFullUpdate=true;
private int mRows;
private int mColumns;
private int mSelectedRow = -1;
private int mSelectedColumn = -1;
private SpreadSheetInput mInputArea;
private Cell mCells[][];
private Cell mCurrent=null;
private int mStartDisplayRow;
public synchronized void init()
{
String strParam;
mStartDisplayRow=0;
mCellColor=Color.white;
mInputColor=new Color(100, 100, 225);
mTitleFont=new Font("Courier", Font.BOLD, 12);
mStrTitle=getParameter("title");
if(null==mStrTitle)mStrTitle="SpreadSheet";
strParam=getParameter("rows");
if(null==strParam)mRows=9;
else mRows=Integer.parseInt(strParam);
strParam=getParameter("columns");
if(null==strParam)mColumns=5;
else mColumns=Integer.parseInt(strParam);
mCells=new Cell[mRows][mColumns];
char strLabel[]=new char[1];
for(int i=0; i < mRows; i++)
{
for (int j=0; j < mColumns; j++)
{
mCells[i][j]=new Cell(this,Color.lightGray,Color.black,mCellColor,mCellDimension.width-2,mCellDimension.height-2);
strLabel[0]=(char)((int)'a'+j);
strParam=getParameter(""+new String(strLabel)+(i+1));
if(null!=strParam)mCells[i][j].setUnparsedValue(strParam);
}
}
Dimension workArea=size();
mInputArea=new SpreadSheetInput(null, this,workArea.width-2,mCellDimension.height-1,mInputColor,Color.white);
resize(mColumns*mCellDimension.width+mRowLabelWidth,((mRows+1)*mCellDimension.height)+mCellDimension.height+mTitleHeight);
}
public void setCurrentValue(float val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[selectedRow()][mSelectedColumn].setValue(val);
// mCells[mSelectedRow][mSelectedColumn].setValue(val);
repaint();
}
public void stop()
{
stopped(true);
}
public void start()
{
stopped(false);
}
public void stopped(boolean stopped)
{
mIsStopped=stopped;
}
public boolean stopped()
{
return mIsStopped;
}
public void destroy()
{
for(int i=0;i<mRows;i++)for(int j=0;j<mColumns;j++)if(mCells[i][j].type()==Cell.URL)mCells[i][j].cellThread().stop();
}
public void setCurrentValue(int type,String val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
// mCells[mSelectedRow][mSelectedColumn].setValue(type,val);
mCells[selectedRow()][mSelectedColumn].setValue(type,val);
repaint();
}
public void update(Graphics graphics)
{
if(!mFullUpdate)
{
int cx;
int cy;
graphics.setFont(mTitleFont);
// for(int row=0;row<mRows;row++)
for(int row=mStartDisplayRow;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row][col].needRedisplay())
{
cx=(col*mCellDimension.width)+2+mRowLabelWidth;
cy=((row+1)*mCellDimension.height)+2+mTitleHeight;
mCells[row][col].paint(graphics,cx,cy);
}
}
}
}
else
{
paint(graphics);
mFullUpdate = false;
}
}
public synchronized void paint(Graphics graphics)
{
int i;
int j;
int cx;
int cy;
char strLabel[]=new char[1];
Dimension clientRect=size();
graphics.setFont(mTitleFont);
graphics.drawString(mStrTitle,(clientRect.width-graphics.getFontMetrics().stringWidth(mStrTitle))/2,12);
graphics.setColor(mInputColor);
graphics.fillRect(0,mCellDimension.height,clientRect.width,mCellDimension.height);
graphics.setFont(mTitleFont);
for(i=0;i<mRows+1;i++)
{
cy=(i+2)*mCellDimension.height;
graphics.setColor(getBackground());
graphics.draw3DRect(0,cy,clientRect.width,2,true);
if(i<mRows)
{
graphics.setColor(getBackground());
graphics.fillRect(1,cy+1,mRowLabelWidth-1,(2*mCellDimension.height)-2);
graphics.setColor(Color.red);
graphics.drawString(""+(i+1+mStartDisplayRow),2,cy+12);
}
}
graphics.setColor(Color.red);
for(i=0;i<mColumns;i++)
{
cx=i*mCellDimension.width;
graphics.setColor(getBackground());
graphics.draw3DRect(cx+mRowLabelWidth,2*mCellDimension.height,1,clientRect.height,true);
}
for(i=0;i<mRows;i++) // for(i=mStartDisplayRow;i<mRows;i++)
{
for(j=0;j<mColumns;j++)
{
cx=(j*mCellDimension.width)+2+mRowLabelWidth;
cy=((i+1)*mCellDimension.height)+2+mTitleHeight;
if(mCells[i+mStartDisplayRow][j]!=null)mCells[i+mStartDisplayRow][j].paint(graphics,cx,cy);
}
}
graphics.setColor(getBackground());
graphics.draw3DRect(0,mTitleHeight,clientRect.width,clientRect.height-mTitleHeight,false);
mInputArea.paint(graphics,1,mTitleHeight+1);
}
public void recalculate()
{
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row+mStartDisplayRow][col]!=null&&mCells[row+mStartDisplayRow][col].type()==Cell.FORMULA)
{
mCells[row+mStartDisplayRow][col].setRawValue(evaluateFormula(mCells[row+mStartDisplayRow][col].parseRoot()));
mCells[row+mStartDisplayRow][col].needRedisplay(true);
}
// if(mCells[row][col]!=null&&mCells[row][col].type()==Cell.FORMULA)
// {
// mCells[row][col].setRawValue(evaluateFormula(mCells[row][col].parseRoot()));
// mCells[row][col].needRedisplay(true);
// }
}
}
repaint();
}
private float evaluateFormula(Node node)
{
float val=0.0f;
if(null==node)return val;
switch(node.type())
{
case Node.OP:
val=evaluateFormula(node.left());
switch(node.op())
{
case '+':
val += evaluateFormula(node.right());
break;
case '*':
val *= evaluateFormula(node.right());
break;
case '-':
val -= evaluateFormula(node.right());
break;
case '/':
val /= evaluateFormula(node.right());
break;
}
break;
case Node.VALUE:
val=node.value();
break;
case Node.CELL:
if(null==node)break;
if(null==mCells[node.row()][node.column()])break;
val=mCells[node.row()][node.column()].value();
break;
}
return val;
}
public boolean mouseDown(Event evt, int x, int y)
{
Cell cell;
if(y<(mTitleHeight+mCellDimension.height))
{
mSelectedRow=-1;
if(y<=mTitleHeight)deselect(true);
return true;
}
if(x<mRowLabelWidth)
{
mSelectedRow=-1;
deselect(true);
return true;
}
mSelectedRow=((y-mCellDimension.height-mTitleHeight)/mCellDimension.height);
mSelectedColumn=(x-mRowLabelWidth)/mCellDimension.width;
if(mSelectedRow>mRows||mSelectedColumn>=mColumns)
{
mSelectedRow = -1;
deselect(true);
}
else
{
if(mSelectedRow>=mRows)
{
mSelectedRow = -1;
deselect(true);
return true;
}
select();
}
return true;
}
public boolean keyDown(Event evt, int key)
{
mFullUpdate=true;
if(mLeftArrow==key||mRightArrow==key||mUpArrow==key||mDownArrow==key)navigate(key);
else mInputArea.keyDown(key);
return true;
}
private void navigate(int key)
{
switch(key)
{
case mLeftArrow :
if(mSelectedColumn<=0)break;
mSelectedColumn--;
select();
break;
case mRightArrow :
if(mSelectedColumn>=mColumns)break;
mSelectedColumn++;
select();
break;
case mUpArrow :
if(mSelectedRow<=0)break;
mSelectedRow--;
ensureVisible();
select();
break;
case mDownArrow :
if(mSelectedRow+1>=mRows)break;
mSelectedRow++;
ensureVisible();
select();
break;
}
}
private int selectedRow()
{
return mSelectedRow+mStartDisplayRow;
}
private int selectedColumn()
{
return mSelectedColumn;
}
private void select()
{
Cell cell;
// String strString="select selRow:"+String.valueOf(mSelectedRow);
// showStatus(strString);
cell=mCells[mSelectedRow][mSelectedColumn];
if(null!=cell.getPrintString())mInputArea.setText(new String(cell.getPrintString()));
else mInputArea.setText(new String(""));
if(mCurrent!=null)mCurrent.deselect();
mCurrent=cell;
mCurrent.select();
requestFocus();
mFullUpdate=true;
repaint();
}
private void deselect(boolean destroy)
{
if(null==mCurrent)return;
mCurrent.deselect();
if(destroy)mCurrent=null;
}
private boolean ensureVisible()
{
Point currPoint=new Point(0,0);
Dimension workArea=size();
boolean adjusted=false;
// currPoint.y=((mSelectedRow+1)*mCellDimension.height)+2+mTitleHeight;
// int firstVisibleRowx=((mStartDisplayRow+2)*mCellDimension.height)+2+mTitleHeight;
// int firstVisibleRowx=(2*mCellDimension.height)+2+mTitleHeight;
int yMin=(2*mCellDimension.height)+2+mTitleHeight;
currPoint.y=((mSelectedRow-mStartDisplayRow+2)*mCellDimension.height)+2+mTitleHeight;
currPoint.x=(mSelectedColumn*mCellDimension.width)+2+mRowLabelWidth;
String strString=new String(" ");
if(currPoint.y>workArea.height)
{
mStartDisplayRow++;
strString+="incrementing startdisplayRow";
adjusted=true;
}
else if(currPoint.y<yMin) // ||currPoint.y<firstVisibleRowx
{
mStartDisplayRow--;
strString+="decrementing startdisplayRow";
adjusted=true;
}
strString+=" (x,y)"+"("+String.valueOf(currPoint.x)+","+String.valueOf(currPoint.y)+")";
strString+=" yMin:"+String.valueOf(yMin);
showStatus(strString);
return adjusted;
}
}
//******************************************************************************************************
// ***************************************** CELLTHREAD ***********************************************
//******************************************************************************************************
class CellThread extends Thread
{
private Cell mTarget;
private InputStream mDataStream=null;
private StreamTokenizer mTokenStream;
public CellThread(Cell cell)
{
super("CellThread");
mTarget=cell;
}
public void run()
{
try
{
mDataStream = new URL(mTarget.spreadSheet().getDocumentBase(),mTarget.getValueString()).openStream();
mTokenStream = new StreamTokenizer(mDataStream);
mTokenStream.eolIsSignificant(false);
while(true)
{
switch(mTokenStream.nextToken())
{
case mTokenStream.TT_EOF:
mDataStream.close();
return;
default:
break;
case mTokenStream.TT_NUMBER:
mTarget.setTransientValue((float)mTokenStream.nval);
if(!mTarget.spreadSheet().stopped()&&!mTarget.paused())mTarget.spreadSheet().repaint();
break;
}
try {Thread.sleep(2000);}
catch(InterruptedException exception){break;}
}
}
catch (IOException exception){return;}
}
}
//******************************************************************************************************
// ******************************************** CELL ***************************************************
//******************************************************************************************************
class Cell
{
public static final int VALUE = 0;
public static final int LABEL = 1;
public static final int URL = 2;
public static final int FORMULA = 3;
private Node mParseRoot;
private boolean mNeedRedisplay;
private boolean mSelected = false;
private boolean mTransientValue = false;
private int mType=Cell.VALUE;
private String mValueString = "";
private String mPrintString = "v";
private float mValue;
private Color mBgColor;
private Color mFgColor;
private Color mHighlightColor;
private int mWidth;
private int mHeight;
private SpreadSheet mSpreadSheet;
private CellThread mCellThread;
private boolean mPaused=false;
public Cell(SpreadSheet spreadSheet,Color bgColor,Color fgColor,Color highlightColor,int width,int height)
{
mSpreadSheet=spreadSheet;
mBgColor=bgColor;
mFgColor=fgColor;
mHighlightColor=highlightColor;
mWidth=width;
mHeight=height;
mNeedRedisplay=true;
}
public void setRawValue(float value)
{
mValueString=Float.toString(value);
mValue=value;
}
public void setValue(float value)
{
setRawValue(value);
mPrintString="v"+mValueString;
mType=Cell.VALUE;
mPaused=false;
mSpreadSheet.recalculate();
mNeedRedisplay=true;
}
public void setTransientValue(float value)
{
mTransientValue=true;
mValue=value;
mNeedRedisplay=true;
mSpreadSheet.recalculate();
}
public void setUnparsedValue(String s)
{
switch (s.charAt(0))
{
case 'v':
setValue(Cell.VALUE, s.substring(1));
break;
case 'f':
setValue(Cell.FORMULA, s.substring(1));
break;
case 'l':
setValue(Cell.LABEL, s.substring(1));
break;
case 'u':
setValue(Cell.URL, s.substring(1));
break;
}
}
public String parseFormula(String formula, Node node)
{
String subformula;
String restFormula;
float value;
int length = formula.length();
Node left;
Node right;
char op;
if(null==formula)return null;
subformula=parseValue(formula, node);
if(null==subformula||0==subformula.length())return null;
if(subformula==formula)return formula;
switch(op=subformula.charAt(0))
{
case 0:
return null;
case ')':
return subformula;
case '+':
case '*':
case '-':
case '/':
restFormula = subformula.substring(1);
subformula = parseValue(restFormula, right=new Node());
if(subformula != restFormula)
{
left = new Node(node);
node.left(left);
node.right(right);
node.op(op);
node.type(Node.OP);
return subformula;
}
else return formula;
default:
return formula;
}
}
public String parseValue(String formula, Node node)
{
char c=formula.charAt(0);
String subformula;
String restFormula;
float value;
int row;
int column;
restFormula = formula;
if (c == '(')
{
restFormula = formula.substring(1);
subformula = parseFormula(restFormula, node);
if(subformula == null || subformula.length() == restFormula.length())return formula;
else if (! (subformula.charAt(0) == ')'))return formula;
restFormula = subformula;
}
else if (c >= '0' && c <= '9')
{
int i;
try{value = Float.valueOf(formula).floatValue();}
catch (NumberFormatException exception){return formula;}
for (i=0; i < formula.length(); i++)
{
c = formula.charAt(i);
if ((c < '0' || c > '9') && c != '.')break;
}
node.type(Node.VALUE);
node.value(value);
restFormula = formula.substring(i);
return restFormula;
}
else if (c >= 'A' && c <= 'Z')
{
int i;
column = c - 'A';
restFormula = formula.substring(1);
row = Float.valueOf(restFormula).intValue();
for(i=0; i < restFormula.length(); i++)
{
c = restFormula.charAt(i);
if (c < '0' || c > '9')break;
}
node.row(row-1);
node.column(column);
node.type(Node.CELL);
if (i == restFormula.length())restFormula=null;
else
{
restFormula = restFormula.substring(i);
if (restFormula.charAt(0) == 0)return null;
}
}
return restFormula;
}
public void setValue(int type, String s)
{
mPaused=false;
if(mType == Cell.URL)
{
mCellThread.stop();
mCellThread=null;
}
mValueString=new String(s);
mType=type;
mNeedRedisplay=true;
switch(mType)
{
case Cell.VALUE:
setValue(Float.valueOf(s).floatValue());
break;
case Cell.LABEL:
mPrintString = "l" + mValueString;
break;
case Cell.URL:
mPrintString = "u" + mValueString;
mCellThread = new CellThread(this);
mCellThread.start();
break;
case Cell.FORMULA:
parseFormula(mValueString,mParseRoot=new Node());
mPrintString = "f" + mValueString;
break;
}
mSpreadSheet.recalculate();
}
public String getValueString()
{
return mValueString;
}
public String getPrintString()
{
return mPrintString;
}
public void select()
{
mSelected = true;
mPaused=true;
}
public void deselect()
{
mSelected = false;
mPaused=false;
mNeedRedisplay = true;
mSpreadSheet.repaint();
}
public void paint(Graphics graphics,int x,int y)
{
if(mSelected)graphics.setColor(mHighlightColor);
else graphics.setColor(mBgColor);
graphics.fillRect(x+1,y+1,mWidth-2,mHeight-2);
if(null!=mValueString)
{
switch(mType)
{
case Cell.VALUE:
case Cell.LABEL:
graphics.setColor(mFgColor);
break;
case Cell.FORMULA:
graphics.setColor(Color.red);
break;
case Cell.URL:
graphics.setColor(Color.blue);
break;
}
if(!mTransientValue)
{
if(mValueString.length()>14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
}
else graphics.drawString(""+mValue,x,y+(mHeight/2)+5);
mNeedRedisplay=false;
}
}
public int type()
{
return mType;
}
public Node parseRoot()
{
return mParseRoot;
}
public void needRedisplay(boolean needRedisplay)
{
mNeedRedisplay=needRedisplay;
}
public boolean needRedisplay()
{
return mNeedRedisplay;
}
public float value()
{
return mValue;
}
public CellThread cellThread()
{
return mCellThread;
}
public SpreadSheet spreadSheet()
{
return mSpreadSheet;
}
public boolean paused()
{
return mPaused;
}
}
//******************************************************************************************************
// *************************************** NODE *******************************************************
//******************************************************************************************************
class Node
{
public static final int OP = 0;
public static final int VALUE = 1;
public static final int CELL = 2;
private int mType;
private Node mLeft;
private Node mRight;
private int mRow;
private int mColumn;
private float mValue;
private char mOp;
public Node()
{
mLeft=null;
mRight=null;
mValue=0;
mRow=-1;
mColumn=-1;
mOp=0;
mType=Node.VALUE;
}
public Node(Node node)
{
mLeft=node.mLeft;
mRight=node.mRight;
mValue=node.mValue;
mRow=node.mRow;
mColumn=node.mColumn;
mOp=node.mOp;
mType=node.mType;
}
public void print(int indentLevel)
{
char l[] = new char[1];
switch(mType)
{
case Node.VALUE:
break;
case Node.CELL:
l[0] = (char)((int)'A' + column());
break;
case Node.OP:
mLeft.print(indentLevel + 3);
mRight.print(indentLevel + 3);
break;
}
}
public int type()
{
return mType;
}
public void type(int type)
{
mType=type;
}
public float value()
{
return mValue;
}
public void value(float value)
{
mValue=value;
}
public Node left()
{
return mLeft;
}
public void left(Node left)
{
mLeft=left;
}
public Node right()
{
return mRight;
}
public void right(Node right)
{
mRight=right;
}
public char op()
{
return mOp;
}
public void op(char op)
{
mOp=op;
}
public int row()
{
return mRow;
}
public void row(int row)
{
mRow=row;
}
public int column()
{
return mColumn;
}
public void column(int column)
{
mColumn=column;
}
}
class InputField
{
private int mMaxchars = 50;
private Applet mApplet;
private String mStringValue;
private char mBuffer[];
private int mChars;
private int mWidth;
private int mHeight;
private Color mBgColor;
private Color mFgColor;
public InputField(String initValue,Applet applet, int width, int height,Color bgColor, Color fgColor)
{
mWidth=width;
mHeight=height;
mBgColor=bgColor;
mFgColor=fgColor;
mApplet=applet;
mBuffer = new char[mMaxchars];
mChars = 0;
if(initValue != null)
{
initValue.getChars(0, initValue.length(),mBuffer, 0);
mChars = initValue.length();
}
mStringValue=initValue;
}
public void setText(String val)
{
int i;
for(i=0; i < mMaxchars; i++)mBuffer[i] = 0;
mStringValue=new String(val);
if (val == null)
{
mStringValue= "";
mChars = 0;
mBuffer[0] = 0;
}
else
{
mStringValue.getChars(0,mStringValue.length(), mBuffer, 0);
mChars = val.length();
mStringValue = new String(mBuffer);
}
}
public String getValue()
{
return mStringValue;
}
public void paint(Graphics g, int x, int y)
{
g.setColor(mBgColor);
g.fillRect(x, y,mWidth,mHeight);
if (mStringValue!= null)
{
g.setColor(mFgColor);
g.drawString(mStringValue, x, y + (mHeight / 2) + 3);
}
}
public void mouseUp(int x, int y)
{
}
public void keyDown(int key)
{
if(mChars<mMaxchars)
{
switch(key)
{
case 8: // delete
--mChars;
if(mChars<0)mChars=0;
mBuffer[mChars] = 0;
mStringValue = new String(new String(mBuffer));
break;
case 10: // return
selected();
break;
default:
mBuffer[mChars++] = (char)key;
mStringValue = new String(new String(mBuffer));
break;
}
}
mApplet.repaint();
}
public void selected()
{
}
public Applet applet()
{
return mApplet;
}
}
class SpreadSheetInput extends InputField
{
public SpreadSheetInput(String initValue,SpreadSheet app,int width,int height,Color bgColor,Color fgColor)
{
super(initValue,app,width,height,bgColor,fgColor);
}
public void selected()
{
float f;
switch(getValue().charAt(0))
{
case 'v':
try{f=Float.valueOf(getValue().substring(1)).floatValue();((SpreadSheet)applet()).setCurrentValue(f);}
catch(NumberFormatException exception){;}
break;
case 'l':
((SpreadSheet)applet()).setCurrentValue(Cell.LABEL,getValue().substring(1));
break;
case 'u':
((SpreadSheet)applet()).setCurrentValue(Cell.URL,getValue().substring(1));
break;
case 'f':
((SpreadSheet)applet()).setCurrentValue(Cell.FORMULA,getValue().substring(1));
break;
}
}
}

View File

@@ -0,0 +1,941 @@
/*
* Adapted 10/98 by Sean Kessler
* Added arrow key navigation
* Added cell scrolling
* Class no longer extends of applet
*
* @(#)SpreadSheet.java 1.17 95/03/09 Sami Shaio
*
* Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.net.*;
//******************************************************************************************************
// ***************************************** SPREADSHEET ***********************************************
//******************************************************************************************************
public class SpreadSheetInterface
{
SpreadSheet mSpreadSheet;
public SpreadSheetInterface(Applet applet)
{
mSpreadSheet=new SpreadSheet(applet,applet.size());
}
public SpreadSheetInterface(Applet applet,Dimension controlDimension)
{
mSpreadSheet=new SpreadSheet(applet,controlDimension);
}
public void update(Graphics graphics)
{
mSpreadSheet.update(graphics);
}
public void paint(Graphics graphics)
{
mSpreadSheet.paint(graphics);
}
public boolean mouseDown(Event event,int x,int y)
{
return mSpreadSheet.mouseDown(event,x,y);
}
public boolean keyDown(Event event,int key)
{
return mSpreadSheet.keyDown(event,key);
}
public boolean setCellData(int row,int col,String strData)
{
return mSpreadSheet.setCellData(row,col,strData);
}
public void setDocumentTitle(String strDocumentTitle)
{
mSpreadSheet.setDocumentTitle(strDocumentTitle);
}
}
class SpreadSheet
{
private final Dimension mCellDimension=new Dimension(100,15);
private Dimension mControlDimension;
private String mStrTitle;
private Font mTitleFont;
private Color mCellColor;
private Color mInputColor;
private int mTitleHeight=15;
private int mRowLabelWidth=15;
private boolean mIsStopped=false;
private boolean mFullUpdate=true;
private int mRows;
private int mColumns;
private int mSelectedRow = -1;
private int mSelectedColumn = -1;
private SpreadSheetInput mInputArea;
private Cell mCells[][];
private Cell mCurrent=null;
private int mStartDisplayRow;
private int mStartDisplayColumn;
private Applet mApplet;
public SpreadSheet(Applet applet,Dimension controlDimension)
{
String strParam;
mApplet=applet;
mControlDimension=controlDimension;
mStartDisplayRow=0;
mStartDisplayColumn=0;
mCellColor=Color.white;
mInputColor=new Color(100, 100, 225);
mTitleFont=new Font("Courier", Font.BOLD, 12);
mStrTitle=mApplet.getParameter("title");
if(null==mStrTitle)mStrTitle="SpreadSheet";
strParam=mApplet.getParameter("rows");
if(null==strParam)mRows=9;
else mRows=Integer.parseInt(strParam);
strParam=mApplet.getParameter("columns");
if(null==strParam)mColumns=5;
else mColumns=Integer.parseInt(strParam);
mCells=new Cell[mRows][mColumns];
char strLabel[]=new char[1];
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
mCells[row][col]=new Cell(this,Color.lightGray,Color.black,mCellColor,mCellDimension.width-2,mCellDimension.height-2);
strLabel[0]=(char)((int)'a'+col);
strParam=mApplet.getParameter(""+new String(strLabel)+(row+1));
if(null!=strParam)mCells[row][col].setUnparsedValue(strParam);
}
}
mInputArea=new SpreadSheetInput(null,mApplet,this,mControlDimension.width-2,mCellDimension.height-1,mInputColor,Color.white);
mApplet.resize(mColumns*mCellDimension.width+mRowLabelWidth,((mRows+1)*mCellDimension.height)+mCellDimension.height+mTitleHeight);
}
public void setCurrentValue(float val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(val);
mApplet.repaint();
}
public void stop()
{
stopped(true);
}
public void start()
{
stopped(false);
}
public void stopped(boolean stopped)
{
mIsStopped=stopped;
}
public boolean stopped()
{
return mIsStopped;
}
public void destroy()
{
}
public void setCurrentValue(int type,String val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(type,val);
mApplet.repaint();
}
public void update(Graphics graphics)
{
int cx;
int cy;
if(mFullUpdate)
{
paint(graphics);
mFullUpdate=false;
return;
}
graphics.setFont(mTitleFont);
for(int row=mStartDisplayRow;row<mRows;row++)
{
for(int col=mStartDisplayColumn;col<mColumns;col++)
{
if(mCells[row][col].needRedisplay())
{
cx=(col*mCellDimension.width)+2+mRowLabelWidth;
cy=((row+1)*mCellDimension.height)+2+mTitleHeight;
mCells[row][col].paint(graphics,cx,cy);
}
}
}
}
public synchronized void paint(Graphics graphics)
{
char strLabel[]=new char[1];
int i;
int j;
int cx;
int cy;
graphics.setFont(mTitleFont);
graphics.drawString(mStrTitle,(mControlDimension.width-graphics.getFontMetrics().stringWidth(mStrTitle))/2,12);
graphics.setColor(mInputColor);
graphics.fillRect(0,mCellDimension.height,mControlDimension.width,mCellDimension.height);
graphics.setFont(mTitleFont);
for(i=0;i<mRows+1;i++)
{
cy=(i+2)*mCellDimension.height;
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,cy,mControlDimension.width,2,true);
if(i<mRows)
{
graphics.setColor(mApplet.getBackground());
graphics.fillRect(1,cy+1,mRowLabelWidth-1,(2*mCellDimension.height)-2);
graphics.setColor(Color.red);
graphics.drawString(""+(i+1+mStartDisplayRow),2,cy+12);
}
}
graphics.setColor(Color.red);
for(i=0;i<mColumns;i++)
{
cx=i*mCellDimension.width;
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(cx+mRowLabelWidth,2*mCellDimension.height,1,mControlDimension.height,true);
}
for(i=mStartDisplayRow;i<mRows;i++)
{
for(j=mStartDisplayColumn;j<mColumns;j++)
{
cx=((j-mStartDisplayColumn)*mCellDimension.width)+2+mRowLabelWidth;
cy=((i+1-mStartDisplayRow)*mCellDimension.height)+2+mTitleHeight;
if(mCells[i][j]!=null)mCells[i][j].paint(graphics,cx,cy);
}
}
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,mTitleHeight,mControlDimension.width,mControlDimension.height-mTitleHeight,false);
mInputArea.paint(graphics,1,mTitleHeight+1);
}
public void recalculate()
{
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row+mStartDisplayRow][col+mStartDisplayColumn]!=null&&mCells[row+mStartDisplayRow][col+mStartDisplayColumn].type()==Cell.FORMULA)
{
mCells[row+mStartDisplayRow][col+mStartDisplayColumn].setRawValue(evaluateFormula(mCells[row+mStartDisplayRow][col+mStartDisplayColumn].parseRoot()));
mCells[row+mStartDisplayRow][col+mStartDisplayColumn].needRedisplay(true);
}
}
}
mApplet.repaint();
}
private float evaluateFormula(Node node)
{
float val=0.0f;
if(null==node)return val;
switch(node.type())
{
case Node.OP:
val=evaluateFormula(node.left());
switch(node.op())
{
case '+':
val += evaluateFormula(node.right());
break;
case '*':
val *= evaluateFormula(node.right());
break;
case '-':
val -= evaluateFormula(node.right());
break;
case '/':
val /= evaluateFormula(node.right());
break;
}
break;
case Node.VALUE:
val=node.value();
break;
case Node.CELL:
if(null==node)break;
if(null==mCells[node.row()][node.column()])break;
val=mCells[node.row()][node.column()].value();
break;
}
return val;
}
public boolean mouseDown(Event evt,int x,int y)
{
if(y<(mTitleHeight+mCellDimension.height))
{
mSelectedRow=-1;
if(y<=mTitleHeight)deselect(true);
return true;
}
if(x<mRowLabelWidth)
{
mSelectedRow=-1;
deselect(true);
return true;
}
mSelectedRow=((y-mCellDimension.height-mTitleHeight)/mCellDimension.height)+mStartDisplayRow;
mSelectedColumn=(x-mRowLabelWidth)/mCellDimension.width;
if(mSelectedRow>=mRows||mSelectedColumn>=mColumns)
{
mSelectedRow = -1;
deselect(true);
return true;
}
select();
return true;
}
public boolean keyDown(Event evt, int key)
{
mFullUpdate=true;
if(Key.LeftArrow==key||Key.RightArrow==key||Key.UpArrow==key||Key.DownArrow==key)
{
mInputArea.keyDown(Key.Return);
navigate(key);
}
else mInputArea.keyDown(key);
return true;
}
private void navigate(int key)
{
switch(key)
{
case Key.LeftArrow :
if(mSelectedColumn<=0)break;
mSelectedColumn--;
ensureVisible();
select();
break;
case Key.RightArrow :
if(mSelectedColumn+1>=mColumns)break;
mSelectedColumn++;
ensureVisible();
select();
break;
case Key.UpArrow :
if(mSelectedRow<=0)break;
mSelectedRow--;
ensureVisible();
select();
break;
case Key.DownArrow :
if(mSelectedRow+1>=mRows)break;
mSelectedRow++;
ensureVisible();
select();
break;
}
}
private void select()
{
Cell cell=mCells[mSelectedRow][mSelectedColumn];
if(null!=cell.getPrintString())mInputArea.setText(new String(cell.getPrintString()));
else mInputArea.setText(new String(""));
if(mCurrent!=null)mCurrent.deselect();
mCurrent=cell;
mCurrent.select();
mApplet.requestFocus();
mFullUpdate=true;
mApplet.repaint();
}
private void deselect(boolean destroy)
{
if(null==mCurrent)return;
mCurrent.deselect();
if(destroy)mCurrent=null;
}
private void ensureVisible()
{
int yMin=(2*mCellDimension.height)+2+mTitleHeight;
int xMin=2+mRowLabelWidth+mCellDimension.width;
Point currPoint=new Point(0,0);
currPoint.y=((mSelectedRow-mStartDisplayRow+2)*mCellDimension.height)+2+mTitleHeight;
currPoint.x=((mSelectedColumn-mStartDisplayColumn)*mCellDimension.width)+2+mRowLabelWidth+mCellDimension.width;
if(currPoint.y>mControlDimension.height)mStartDisplayRow++;
else if(currPoint.y<yMin)mStartDisplayRow--;
if(currPoint.x>mControlDimension.width)mStartDisplayColumn++;
else if(currPoint.x<xMin)mStartDisplayColumn--;
}
public Applet applet()
{
return mApplet;
}
public int rows()
{
return mRows;
}
public int columns()
{
return mColumns;
}
public boolean setCellData(int row,int col,String strData)
{
String strCellData;
if(row>=mRows||col>=mColumns)return false;
strCellData="l";
strCellData+=strData;
mCells[row][col].setUnparsedValue(strCellData);
mApplet.repaint();
return true;
}
public void setDocumentTitle(String strDocumentTitle)
{
mStrTitle=strDocumentTitle;
}
}
//******************************************************************************************************
// ******************************************** CELL ***************************************************
//******************************************************************************************************
class Cell
{
public static final int VALUE = 0;
public static final int LABEL = 1;
public static final int URL = 2;
public static final int FORMULA = 3;
private Node mParseRoot;
private boolean mNeedRedisplay;
private boolean mSelected = false;
private boolean mTransientValue = false;
private int mType=Cell.VALUE;
private String mValueString = "";
private String mPrintString = "v";
private float mValue;
private Color mBgColor;
private Color mFgColor;
private Color mHighlightColor;
private int mWidth;
private int mHeight;
private SpreadSheet mSpreadSheet;
private boolean mPaused=false;
public Cell(SpreadSheet spreadSheet,Color bgColor,Color fgColor,Color highlightColor,int width,int height)
{
mSpreadSheet=spreadSheet;
mBgColor=bgColor;
mFgColor=fgColor;
mHighlightColor=highlightColor;
mWidth=width;
mHeight=height;
mNeedRedisplay=true;
}
public void setRawValue(float value)
{
mValueString=Float.toString(value);
mValue=value;
}
public void setValue(float value)
{
setRawValue(value);
mPrintString="v"+mValueString;
mType=Cell.VALUE;
mPaused=false;
mSpreadSheet.recalculate();
mNeedRedisplay=true;
}
public void setTransientValue(float value)
{
mTransientValue=true;
mValue=value;
mNeedRedisplay=true;
mSpreadSheet.recalculate();
}
public void setUnparsedValue(String s)
{
switch (s.charAt(0))
{
case 'v':
setValue(Cell.VALUE, s.substring(1));
break;
case 'f':
setValue(Cell.FORMULA, s.substring(1));
break;
case 'l':
setValue(Cell.LABEL, s.substring(1));
break;
case 'u':
setValue(Cell.URL, s.substring(1));
break;
}
}
public String parseFormula(String formula, Node node)
{
String subformula;
String restFormula;
float value;
int length = formula.length();
Node left;
Node right;
char op;
if(null==formula)return null;
subformula=parseValue(formula, node);
if(null==subformula||0==subformula.length())return null;
if(subformula==formula)return formula;
switch(op=subformula.charAt(0))
{
case 0:
return null;
case ')':
return subformula;
case '+':
case '*':
case '-':
case '/':
restFormula = subformula.substring(1);
subformula = parseValue(restFormula, right=new Node());
if(subformula != restFormula)
{
left = new Node(node);
node.left(left);
node.right(right);
node.op(op);
node.type(Node.OP);
return subformula;
}
else return formula;
default:
return formula;
}
}
public String parseValue(String formula, Node node)
{
char c=formula.charAt(0);
String subformula;
String restFormula;
float value;
int row;
int column;
restFormula = formula;
if (c == '(')
{
restFormula = formula.substring(1);
subformula = parseFormula(restFormula, node);
if(subformula == null || subformula.length() == restFormula.length())return formula;
else if (! (subformula.charAt(0) == ')'))return formula;
restFormula = subformula;
}
else if (c >= '0' && c <= '9')
{
int i;
try{value = Float.valueOf(formula).floatValue();}
catch (NumberFormatException exception){return formula;}
for (i=0; i < formula.length(); i++)
{
c = formula.charAt(i);
if ((c < '0' || c > '9') && c != '.')break;
}
node.type(Node.VALUE);
node.value(value);
restFormula = formula.substring(i);
return restFormula;
}
else if (c >= 'A' && c <= 'Z')
{
int i;
column = c - 'A';
restFormula = formula.substring(1);
row = Float.valueOf(restFormula).intValue();
for(i=0; i < restFormula.length(); i++)
{
c = restFormula.charAt(i);
if (c < '0' || c > '9')break;
}
node.row(row-1);
node.column(column);
node.type(Node.CELL);
if (i == restFormula.length())restFormula=null;
else
{
restFormula = restFormula.substring(i);
if (restFormula.charAt(0) == 0)return null;
}
}
return restFormula;
}
public void setValue(int type, String s)
{
mPaused=false;
mValueString=new String(s);
mType=type;
mNeedRedisplay=true;
switch(mType)
{
case Cell.VALUE:
setValue(Float.valueOf(s).floatValue());
break;
case Cell.LABEL:
mPrintString = "l" + mValueString;
break;
case Cell.URL:
mPrintString = "u" + mValueString;
break;
case Cell.FORMULA:
parseFormula(mValueString,mParseRoot=new Node());
mPrintString = "f" + mValueString;
break;
}
mSpreadSheet.recalculate();
}
public String getValueString()
{
return mValueString;
}
public String getPrintString()
{
return mPrintString;
}
public void select()
{
mSelected=true;
mPaused=true;
}
public void deselect()
{
mSelected=false;
mPaused=false;
mNeedRedisplay=true;
mSpreadSheet.applet().repaint();
}
public void paint(Graphics graphics,int x,int y)
{
if(mSelected)graphics.setColor(mHighlightColor);
else graphics.setColor(mBgColor);
graphics.fillRect(x+1,y+1,mWidth-1,mHeight-1);
if(null!=mValueString)
{
switch(mType)
{
case Cell.VALUE:
case Cell.LABEL:
graphics.setColor(mFgColor);
break;
case Cell.FORMULA:
graphics.setColor(Color.red);
break;
case Cell.URL:
graphics.setColor(Color.blue);
break;
}
if(!mTransientValue)
{
if(mValueString.length()>14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
}
else graphics.drawString(""+mValue,x,y+(mHeight/2)+5);
mNeedRedisplay=false;
}
}
public int type()
{
return mType;
}
public Node parseRoot()
{
return mParseRoot;
}
public void needRedisplay(boolean needRedisplay)
{
mNeedRedisplay=needRedisplay;
}
public boolean needRedisplay()
{
return mNeedRedisplay;
}
public float value()
{
return mValue;
}
public SpreadSheet spreadSheet()
{
return mSpreadSheet;
}
public boolean paused()
{
return mPaused;
}
}
//******************************************************************************************************
// *************************************** NODE *******************************************************
//******************************************************************************************************
class Node
{
public static final int OP = 0;
public static final int VALUE = 1;
public static final int CELL = 2;
private int mType;
private Node mLeft;
private Node mRight;
private int mRow;
private int mColumn;
private float mValue;
private char mOp;
public Node()
{
mLeft=null;
mRight=null;
mValue=0;
mRow=-1;
mColumn=-1;
mOp=0;
mType=Node.VALUE;
}
public Node(Node node)
{
mLeft=node.mLeft;
mRight=node.mRight;
mValue=node.mValue;
mRow=node.mRow;
mColumn=node.mColumn;
mOp=node.mOp;
mType=node.mType;
}
public void print(int indentLevel)
{
char l[] = new char[1];
switch(mType)
{
case Node.VALUE:
break;
case Node.CELL:
l[0] = (char)((int)'A' + column());
break;
case Node.OP:
mLeft.print(indentLevel + 3);
mRight.print(indentLevel + 3);
break;
}
}
public int type()
{
return mType;
}
public void type(int type)
{
mType=type;
}
public float value()
{
return mValue;
}
public void value(float value)
{
mValue=value;
}
public Node left()
{
return mLeft;
}
public void left(Node left)
{
mLeft=left;
}
public Node right()
{
return mRight;
}
public void right(Node right)
{
mRight=right;
}
public char op()
{
return mOp;
}
public void op(char op)
{
mOp=op;
}
public int row()
{
return mRow;
}
public void row(int row)
{
mRow=row;
}
public int column()
{
return mColumn;
}
public void column(int column)
{
mColumn=column;
}
}
class InputField
{
private int mMaxchars = 50;
private Applet mApplet;
private String mStringValue;
private char mBuffer[];
private int mChars;
private int mWidth;
private int mHeight;
private Color mBgColor;
private Color mFgColor;
public InputField(String initValue,Applet applet,int width,int height,Color bgColor, Color fgColor)
{
mWidth=width;
mHeight=height;
mBgColor=bgColor;
mFgColor=fgColor;
mApplet=applet;
mBuffer = new char[mMaxchars];
mChars = 0;
if(initValue != null)
{
initValue.getChars(0, initValue.length(),mBuffer, 0);
mChars = initValue.length();
}
mStringValue=initValue;
}
public void setText(String val)
{
int i;
for(i=0; i < mMaxchars; i++)mBuffer[i] = 0;
mStringValue=new String(val);
if (val == null)
{
mStringValue= "";
mChars = 0;
mBuffer[0] = 0;
}
else
{
mStringValue.getChars(0,mStringValue.length(), mBuffer, 0);
mChars = val.length();
mStringValue = new String(mBuffer);
}
}
public String getValue()
{
return mStringValue;
}
public void paint(Graphics g, int x, int y)
{
g.setColor(mBgColor);
g.fillRect(x, y,mWidth,mHeight);
if(mStringValue!= null)
{
g.setColor(mFgColor);
g.drawString(mStringValue, x, y + (mHeight / 2) + 3);
}
}
public void mouseUp(int x, int y)
{
}
public void keyDown(int key)
{
if(mChars<mMaxchars)
{
switch(key)
{
case Key.BackSpace :
--mChars;
if(mChars<0)mChars=0;
mBuffer[mChars] = 0;
mStringValue = new String(new String(mBuffer));
break;
case Key.Return :
selected();
break;
default:
mBuffer[mChars++] = (char)key;
mStringValue = new String(new String(mBuffer));
break;
}
}
mApplet.repaint();
}
public void selected()
{
}
public Applet applet()
{
return mApplet;
}
}
class SpreadSheetInput extends InputField
{
SpreadSheet mSpreadSheet;
public SpreadSheetInput(String initValue,Applet app,SpreadSheet spreadSheet,int width,int height,Color bgColor,Color fgColor)
{
super(initValue,app,width,height,bgColor,fgColor);
mSpreadSheet=spreadSheet;
}
public void selected()
{
float f;
switch(getValue().charAt(0))
{
case 'v':
try{f=Float.valueOf(getValue().substring(1)).floatValue();mSpreadSheet.setCurrentValue(f);}
catch(Exception exception){;}
break;
case 'l':
mSpreadSheet.setCurrentValue(Cell.LABEL,getValue().substring(1));
break;
case 'u':
mSpreadSheet.setCurrentValue(Cell.URL,getValue().substring(1));
break;
case 'f':
mSpreadSheet.setCurrentValue(Cell.FORMULA,getValue().substring(1));
break;
}
}
}
class Key
{
public static final int LeftArrow=1006;
public static final int RightArrow=1007;
public static final int UpArrow=1004;
public static final int DownArrow=1005;
public static final int BackSpace=8;
public static final int Return=10;
public Key()
{
}
};

View File

@@ -0,0 +1,933 @@
/*
* Adapted 10/98 by Sean Kessler
* Added arrow key navigation
* Added cell scrolling
*
* @(#)SpreadSheet.java 1.17 95/03/09 Sami Shaio
*
* Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.net.*;
//******************************************************************************************************
// ***************************************** SPREADSHEET ***********************************************
//******************************************************************************************************
//public class SpreadSheet extends Applet
public class SpreadSheet
{
private final Dimension mCellDimension=new Dimension(100,15);
private String mStrTitle;
private Font mTitleFont;
private Color mCellColor;
private Color mInputColor;
private int mTitleHeight=15;
private int mRowLabelWidth=15;
private boolean mIsStopped=false;
private boolean mFullUpdate=true;
private int mRows;
private int mColumns;
private int mSelectedRow = -1;
private int mSelectedColumn = -1;
private SpreadSheetInput mInputArea;
private Cell mCells[][];
private Cell mCurrent=null;
private int mStartDisplayRow;
private Applet mApplet;
public SpreadSheet(Applet applet)
{
String strParam;
mApplet=applet;
mStartDisplayRow=0;
mCellColor=Color.white;
mInputColor=new Color(100, 100, 225);
mTitleFont=new Font("Courier", Font.BOLD, 12);
mStrTitle=mApplet.getParameter("title");
if(null==mStrTitle)mStrTitle="SpreadSheet";
strParam=mApplet.getParameter("rows");
if(null==strParam)mRows=9;
else mRows=Integer.parseInt(strParam);
strParam=mApplet.getParameter("columns");
if(null==strParam)mColumns=5;
else mColumns=Integer.parseInt(strParam);
mCells=new Cell[mRows][mColumns];
char strLabel[]=new char[1];
for(int i=0; i < mRows; i++)
{
for (int j=0; j < mColumns; j++)
{
mCells[i][j]=new Cell(this,Color.lightGray,Color.black,mCellColor,mCellDimension.width-2,mCellDimension.height-2);
strLabel[0]=(char)((int)'a'+j);
strParam=mApplet.getParameter(""+new String(strLabel)+(i+1));
if(null!=strParam)mCells[i][j].setUnparsedValue(strParam);
}
}
Dimension workArea=mApplet.size();
mInputArea=new SpreadSheetInput(null,mApplet,this,workArea.width-2,mCellDimension.height-1,mInputColor,Color.white);
mApplet.resize(mColumns*mCellDimension.width+mRowLabelWidth,((mRows+1)*mCellDimension.height)+mCellDimension.height+mTitleHeight);
}
public void setCurrentValue(float val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(val);
mApplet.repaint();
}
public void stop()
{
stopped(true);
}
public void start()
{
stopped(false);
}
public void stopped(boolean stopped)
{
mIsStopped=stopped;
}
public boolean stopped()
{
return mIsStopped;
}
public void destroy()
{
for(int i=0;i<mRows;i++)for(int j=0;j<mColumns;j++)if(mCells[i][j].type()==Cell.URL)mCells[i][j].cellThread().stop();
}
public void setCurrentValue(int type,String val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(type,val);
mApplet.repaint();
}
public void update(Graphics graphics)
{
int cx;
int cy;
if(mFullUpdate)
{
paint(graphics);
mFullUpdate=false;
return;
}
graphics.setFont(mTitleFont);
for(int row=mStartDisplayRow;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row][col].needRedisplay())
{
cx=(col*mCellDimension.width)+2+mRowLabelWidth;
cy=((row+1)*mCellDimension.height)+2+mTitleHeight;
mCells[row][col].paint(graphics,cx,cy);
}
}
}
}
public synchronized void paint(Graphics graphics)
{
int i;
int j;
int cx;
int cy;
char strLabel[]=new char[1];
Dimension clientRect=mApplet.size();
graphics.setFont(mTitleFont);
graphics.drawString(mStrTitle,(clientRect.width-graphics.getFontMetrics().stringWidth(mStrTitle))/2,12);
graphics.setColor(mInputColor);
graphics.fillRect(0,mCellDimension.height,clientRect.width,mCellDimension.height);
graphics.setFont(mTitleFont);
for(i=0;i<mRows+1;i++)
{
cy=(i+2)*mCellDimension.height;
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,cy,clientRect.width,2,true);
if(i<mRows)
{
graphics.setColor(mApplet.getBackground());
graphics.fillRect(1,cy+1,mRowLabelWidth-1,(2*mCellDimension.height)-2);
graphics.setColor(Color.red);
graphics.drawString(""+(i+1+mStartDisplayRow),2,cy+12);
}
}
graphics.setColor(Color.red);
for(i=0;i<mColumns;i++)
{
cx=i*mCellDimension.width;
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(cx+mRowLabelWidth,2*mCellDimension.height,1,clientRect.height,true);
}
for(i=mStartDisplayRow;i<mRows;i++)
{
for(j=0;j<mColumns;j++)
{
cx=(j*mCellDimension.width)+2+mRowLabelWidth;
cy=((i+1-mStartDisplayRow)*mCellDimension.height)+2+mTitleHeight;
if(mCells[i][j]!=null)mCells[i][j].paint(graphics,cx,cy);
}
}
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,mTitleHeight,clientRect.width,clientRect.height-mTitleHeight,false);
mInputArea.paint(graphics,1,mTitleHeight+1);
}
public void recalculate()
{
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row+mStartDisplayRow][col]!=null&&mCells[row+mStartDisplayRow][col].type()==Cell.FORMULA)
{
mCells[row+mStartDisplayRow][col].setRawValue(evaluateFormula(mCells[row+mStartDisplayRow][col].parseRoot()));
mCells[row+mStartDisplayRow][col].needRedisplay(true);
}
}
}
mApplet.repaint();
}
private float evaluateFormula(Node node)
{
float val=0.0f;
if(null==node)return val;
switch(node.type())
{
case Node.OP:
val=evaluateFormula(node.left());
switch(node.op())
{
case '+':
val += evaluateFormula(node.right());
break;
case '*':
val *= evaluateFormula(node.right());
break;
case '-':
val -= evaluateFormula(node.right());
break;
case '/':
val /= evaluateFormula(node.right());
break;
}
break;
case Node.VALUE:
val=node.value();
break;
case Node.CELL:
if(null==node)break;
if(null==mCells[node.row()][node.column()])break;
val=mCells[node.row()][node.column()].value();
break;
}
return val;
}
public boolean mouseDown(Event evt,int x,int y)
{
if(y<(mTitleHeight+mCellDimension.height))
{
mSelectedRow=-1;
if(y<=mTitleHeight)deselect(true);
return true;
}
if(x<mRowLabelWidth)
{
mSelectedRow=-1;
deselect(true);
return true;
}
mSelectedRow=((y-mCellDimension.height-mTitleHeight)/mCellDimension.height)+mStartDisplayRow;
mSelectedColumn=(x-mRowLabelWidth)/mCellDimension.width;
if(mSelectedRow>=mRows||mSelectedColumn>=mColumns)
{
mSelectedRow = -1;
deselect(true);
return true;
}
select();
return true;
}
public boolean keyDown(Event evt, int key)
{
mFullUpdate=true;
if(Key.LeftArrow==key||Key.RightArrow==key||Key.UpArrow==key||Key.DownArrow==key)
{
mInputArea.keyDown(Key.Return);
navigate(key);
}
else mInputArea.keyDown(key);
return true;
}
private void navigate(int key)
{
switch(key)
{
case Key.LeftArrow :
if(mSelectedColumn<=0)break;
mSelectedColumn--;
select();
break;
case Key.RightArrow :
if(mSelectedColumn>=mColumns)break;
mSelectedColumn++;
select();
break;
case Key.UpArrow :
if(mSelectedRow<=0)break;
mSelectedRow--;
ensureVisible();
select();
break;
case Key.DownArrow :
if(mSelectedRow+1>=mRows)break;
mSelectedRow++;
ensureVisible();
select();
break;
}
}
private void select()
{
Cell cell=mCells[mSelectedRow][mSelectedColumn];
if(null!=cell.getPrintString())mInputArea.setText(new String(cell.getPrintString()));
else mInputArea.setText(new String(""));
if(mCurrent!=null)mCurrent.deselect();
mCurrent=cell;
mCurrent.select();
mApplet.requestFocus();
mFullUpdate=true;
mApplet.repaint();
}
private void deselect(boolean destroy)
{
if(null==mCurrent)return;
mCurrent.deselect();
if(destroy)mCurrent=null;
}
public Applet applet()
{
return mApplet;
}
private boolean ensureVisible()
{
int yMin=(2*mCellDimension.height)+2+mTitleHeight;
Point currPoint=new Point(0,0);
Dimension workArea=mApplet.size();
boolean adjusted=false;
yMin=(2*mCellDimension.height)+2+mTitleHeight;
currPoint.y=((mSelectedRow-mStartDisplayRow+2)*mCellDimension.height)+2+mTitleHeight;
currPoint.x=(mSelectedColumn*mCellDimension.width)+2+mRowLabelWidth;
if(currPoint.y>workArea.height){mStartDisplayRow++;adjusted=true;}
else if(currPoint.y<yMin){mStartDisplayRow--;adjusted=true;}
return adjusted;
}
}
//******************************************************************************************************
// ***************************************** CELLTHREAD ***********************************************
//******************************************************************************************************
class CellThread extends Thread
{
private Cell mTarget;
private InputStream mDataStream=null;
private StreamTokenizer mTokenStream;
public CellThread(Cell cell)
{
super("CellThread");
mTarget=cell;
}
public void run()
{
try
{
mDataStream = new URL(mTarget.spreadSheet().applet().getDocumentBase(),mTarget.getValueString()).openStream();
mTokenStream = new StreamTokenizer(mDataStream);
mTokenStream.eolIsSignificant(false);
while(true)
{
switch(mTokenStream.nextToken())
{
case mTokenStream.TT_EOF:
mDataStream.close();
return;
default:
break;
case mTokenStream.TT_NUMBER:
mTarget.setTransientValue((float)mTokenStream.nval);
if(!mTarget.spreadSheet().stopped()&&!mTarget.paused())mTarget.spreadSheet().applet().repaint();
break;
}
try {Thread.sleep(2000);}
catch(InterruptedException exception){break;}
}
}
catch (IOException exception){return;}
}
}
//******************************************************************************************************
// ******************************************** CELL ***************************************************
//******************************************************************************************************
class Cell
{
public static final int VALUE = 0;
public static final int LABEL = 1;
public static final int URL = 2;
public static final int FORMULA = 3;
private Node mParseRoot;
private boolean mNeedRedisplay;
private boolean mSelected = false;
private boolean mTransientValue = false;
private int mType=Cell.VALUE;
private String mValueString = "";
private String mPrintString = "v";
private float mValue;
private Color mBgColor;
private Color mFgColor;
private Color mHighlightColor;
private int mWidth;
private int mHeight;
private SpreadSheet mSpreadSheet;
private CellThread mCellThread;
private boolean mPaused=false;
public Cell(SpreadSheet spreadSheet,Color bgColor,Color fgColor,Color highlightColor,int width,int height)
{
mSpreadSheet=spreadSheet;
mBgColor=bgColor;
mFgColor=fgColor;
mHighlightColor=highlightColor;
mWidth=width;
mHeight=height;
mNeedRedisplay=true;
}
public void setRawValue(float value)
{
mValueString=Float.toString(value);
mValue=value;
}
public void setValue(float value)
{
setRawValue(value);
mPrintString="v"+mValueString;
mType=Cell.VALUE;
mPaused=false;
mSpreadSheet.recalculate();
mNeedRedisplay=true;
}
public void setTransientValue(float value)
{
mTransientValue=true;
mValue=value;
mNeedRedisplay=true;
mSpreadSheet.recalculate();
}
public void setUnparsedValue(String s)
{
switch (s.charAt(0))
{
case 'v':
setValue(Cell.VALUE, s.substring(1));
break;
case 'f':
setValue(Cell.FORMULA, s.substring(1));
break;
case 'l':
setValue(Cell.LABEL, s.substring(1));
break;
case 'u':
setValue(Cell.URL, s.substring(1));
break;
}
}
public String parseFormula(String formula, Node node)
{
String subformula;
String restFormula;
float value;
int length = formula.length();
Node left;
Node right;
char op;
if(null==formula)return null;
subformula=parseValue(formula, node);
if(null==subformula||0==subformula.length())return null;
if(subformula==formula)return formula;
switch(op=subformula.charAt(0))
{
case 0:
return null;
case ')':
return subformula;
case '+':
case '*':
case '-':
case '/':
restFormula = subformula.substring(1);
subformula = parseValue(restFormula, right=new Node());
if(subformula != restFormula)
{
left = new Node(node);
node.left(left);
node.right(right);
node.op(op);
node.type(Node.OP);
return subformula;
}
else return formula;
default:
return formula;
}
}
public String parseValue(String formula, Node node)
{
char c=formula.charAt(0);
String subformula;
String restFormula;
float value;
int row;
int column;
restFormula = formula;
if (c == '(')
{
restFormula = formula.substring(1);
subformula = parseFormula(restFormula, node);
if(subformula == null || subformula.length() == restFormula.length())return formula;
else if (! (subformula.charAt(0) == ')'))return formula;
restFormula = subformula;
}
else if (c >= '0' && c <= '9')
{
int i;
try{value = Float.valueOf(formula).floatValue();}
catch (NumberFormatException exception){return formula;}
for (i=0; i < formula.length(); i++)
{
c = formula.charAt(i);
if ((c < '0' || c > '9') && c != '.')break;
}
node.type(Node.VALUE);
node.value(value);
restFormula = formula.substring(i);
return restFormula;
}
else if (c >= 'A' && c <= 'Z')
{
int i;
column = c - 'A';
restFormula = formula.substring(1);
row = Float.valueOf(restFormula).intValue();
for(i=0; i < restFormula.length(); i++)
{
c = restFormula.charAt(i);
if (c < '0' || c > '9')break;
}
node.row(row-1);
node.column(column);
node.type(Node.CELL);
if (i == restFormula.length())restFormula=null;
else
{
restFormula = restFormula.substring(i);
if (restFormula.charAt(0) == 0)return null;
}
}
return restFormula;
}
public void setValue(int type, String s)
{
mPaused=false;
if(mType == Cell.URL)
{
mCellThread.stop();
mCellThread=null;
}
mValueString=new String(s);
mType=type;
mNeedRedisplay=true;
switch(mType)
{
case Cell.VALUE:
setValue(Float.valueOf(s).floatValue());
break;
case Cell.LABEL:
mPrintString = "l" + mValueString;
break;
case Cell.URL:
mPrintString = "u" + mValueString;
mCellThread = new CellThread(this);
mCellThread.start();
break;
case Cell.FORMULA:
parseFormula(mValueString,mParseRoot=new Node());
mPrintString = "f" + mValueString;
break;
}
mSpreadSheet.recalculate();
}
public String getValueString()
{
return mValueString;
}
public String getPrintString()
{
return mPrintString;
}
public void select()
{
mSelected=true;
mPaused=true;
}
public void deselect()
{
mSelected=false;
mPaused=false;
mNeedRedisplay=true;
mSpreadSheet.applet().repaint();
}
public void paint(Graphics graphics,int x,int y)
{
if(mSelected)graphics.setColor(mHighlightColor);
else graphics.setColor(mBgColor);
graphics.fillRect(x+1,y+1,mWidth-1,mHeight-1);
if(null!=mValueString)
{
switch(mType)
{
case Cell.VALUE:
case Cell.LABEL:
graphics.setColor(mFgColor);
break;
case Cell.FORMULA:
graphics.setColor(Color.red);
break;
case Cell.URL:
graphics.setColor(Color.blue);
break;
}
if(!mTransientValue)
{
if(mValueString.length()>14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
}
else graphics.drawString(""+mValue,x,y+(mHeight/2)+5);
mNeedRedisplay=false;
}
}
public int type()
{
return mType;
}
public Node parseRoot()
{
return mParseRoot;
}
public void needRedisplay(boolean needRedisplay)
{
mNeedRedisplay=needRedisplay;
}
public boolean needRedisplay()
{
return mNeedRedisplay;
}
public float value()
{
return mValue;
}
public CellThread cellThread()
{
return mCellThread;
}
public SpreadSheet spreadSheet()
{
return mSpreadSheet;
}
public boolean paused()
{
return mPaused;
}
}
//******************************************************************************************************
// *************************************** NODE *******************************************************
//******************************************************************************************************
class Node
{
public static final int OP = 0;
public static final int VALUE = 1;
public static final int CELL = 2;
private int mType;
private Node mLeft;
private Node mRight;
private int mRow;
private int mColumn;
private float mValue;
private char mOp;
public Node()
{
mLeft=null;
mRight=null;
mValue=0;
mRow=-1;
mColumn=-1;
mOp=0;
mType=Node.VALUE;
}
public Node(Node node)
{
mLeft=node.mLeft;
mRight=node.mRight;
mValue=node.mValue;
mRow=node.mRow;
mColumn=node.mColumn;
mOp=node.mOp;
mType=node.mType;
}
public void print(int indentLevel)
{
char l[] = new char[1];
switch(mType)
{
case Node.VALUE:
break;
case Node.CELL:
l[0] = (char)((int)'A' + column());
break;
case Node.OP:
mLeft.print(indentLevel + 3);
mRight.print(indentLevel + 3);
break;
}
}
public int type()
{
return mType;
}
public void type(int type)
{
mType=type;
}
public float value()
{
return mValue;
}
public void value(float value)
{
mValue=value;
}
public Node left()
{
return mLeft;
}
public void left(Node left)
{
mLeft=left;
}
public Node right()
{
return mRight;
}
public void right(Node right)
{
mRight=right;
}
public char op()
{
return mOp;
}
public void op(char op)
{
mOp=op;
}
public int row()
{
return mRow;
}
public void row(int row)
{
mRow=row;
}
public int column()
{
return mColumn;
}
public void column(int column)
{
mColumn=column;
}
}
class InputField
{
private int mMaxchars = 50;
private Applet mApplet;
private String mStringValue;
private char mBuffer[];
private int mChars;
private int mWidth;
private int mHeight;
private Color mBgColor;
private Color mFgColor;
public InputField(String initValue,Applet applet,int width,int height,Color bgColor, Color fgColor)
{
mWidth=width;
mHeight=height;
mBgColor=bgColor;
mFgColor=fgColor;
mApplet=applet;
mBuffer = new char[mMaxchars];
mChars = 0;
if(initValue != null)
{
initValue.getChars(0, initValue.length(),mBuffer, 0);
mChars = initValue.length();
}
mStringValue=initValue;
}
public void setText(String val)
{
int i;
for(i=0; i < mMaxchars; i++)mBuffer[i] = 0;
mStringValue=new String(val);
if (val == null)
{
mStringValue= "";
mChars = 0;
mBuffer[0] = 0;
}
else
{
mStringValue.getChars(0,mStringValue.length(), mBuffer, 0);
mChars = val.length();
mStringValue = new String(mBuffer);
}
}
public String getValue()
{
return mStringValue;
}
public void paint(Graphics g, int x, int y)
{
g.setColor(mBgColor);
g.fillRect(x, y,mWidth,mHeight);
if(mStringValue!= null)
{
g.setColor(mFgColor);
g.drawString(mStringValue, x, y + (mHeight / 2) + 3);
}
}
public void mouseUp(int x, int y)
{
}
public void keyDown(int key)
{
if(mChars<mMaxchars)
{
switch(key)
{
case Key.BackSpace :
--mChars;
if(mChars<0)mChars=0;
mBuffer[mChars] = 0;
mStringValue = new String(new String(mBuffer));
break;
case Key.Return :
selected();
break;
default:
mBuffer[mChars++] = (char)key;
mStringValue = new String(new String(mBuffer));
break;
}
}
mApplet.repaint();
}
public void selected()
{
}
public Applet applet()
{
return mApplet;
}
}
class SpreadSheetInput extends InputField
{
SpreadSheet mSpreadSheet;
public SpreadSheetInput(String initValue,Applet app,SpreadSheet spreadSheet,int width,int height,Color bgColor,Color fgColor)
{
super(initValue,app,width,height,bgColor,fgColor);
mSpreadSheet=spreadSheet;
}
public void selected()
{
float f;
switch(getValue().charAt(0))
{
case 'v':
try{f=Float.valueOf(getValue().substring(1)).floatValue();mSpreadSheet.setCurrentValue(f);}
catch(Exception exception){;}
break;
case 'l':
mSpreadSheet.setCurrentValue(Cell.LABEL,getValue().substring(1));
break;
case 'u':
mSpreadSheet.setCurrentValue(Cell.URL,getValue().substring(1));
break;
case 'f':
mSpreadSheet.setCurrentValue(Cell.FORMULA,getValue().substring(1));
break;
}
}
}
class Key
{
public static final int LeftArrow=1006;
public static final int RightArrow=1007;
public static final int UpArrow=1004;
public static final int DownArrow=1005;
public static final int BackSpace=8;
public static final int Return=10;
public Key()
{
}
};

View File

@@ -0,0 +1,876 @@
/*
* Adapted 10/98 by Sean Kessler
* Added arrow key navigation
* Added cell scrolling
* Class no longer extends of applet
*
* @(#)SpreadSheet.java 1.17 95/03/09 Sami Shaio
*
* Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.net.*;
//******************************************************************************************************
// ***************************************** SPREADSHEET ***********************************************
//******************************************************************************************************
//public class SpreadSheet extends Applet
public class SpreadSheet
{
private final Dimension mCellDimension=new Dimension(100,15);
private Dimension mControlDimension;
private String mStrTitle;
private Font mTitleFont;
private Color mCellColor;
private Color mInputColor;
private int mTitleHeight=15;
private int mRowLabelWidth=15;
private boolean mIsStopped=false;
private boolean mFullUpdate=true;
private int mRows;
private int mColumns;
private int mSelectedRow = -1;
private int mSelectedColumn = -1;
private SpreadSheetInput mInputArea;
private Cell mCells[][];
private Cell mCurrent=null;
private int mStartDisplayRow;
private Applet mApplet;
public SpreadSheet(Applet applet,Dimension controlDimension)
{
String strParam;
mApplet=applet;
mControlDimension=controlDimension;
mStartDisplayRow=0;
mCellColor=Color.white;
mInputColor=new Color(100, 100, 225);
mTitleFont=new Font("Courier", Font.BOLD, 12);
mStrTitle=mApplet.getParameter("title");
if(null==mStrTitle)mStrTitle="SpreadSheet";
strParam=mApplet.getParameter("rows");
if(null==strParam)mRows=9;
else mRows=Integer.parseInt(strParam);
strParam=mApplet.getParameter("columns");
if(null==strParam)mColumns=5;
else mColumns=Integer.parseInt(strParam);
mCells=new Cell[mRows][mColumns];
char strLabel[]=new char[1];
for(int i=0; i < mRows; i++)
{
for (int j=0; j < mColumns; j++)
{
mCells[i][j]=new Cell(this,Color.lightGray,Color.black,mCellColor,mCellDimension.width-2,mCellDimension.height-2);
strLabel[0]=(char)((int)'a'+j);
strParam=mApplet.getParameter(""+new String(strLabel)+(i+1));
if(null!=strParam)mCells[i][j].setUnparsedValue(strParam);
}
}
mInputArea=new SpreadSheetInput(null,mApplet,this,mControlDimension.width-2,mCellDimension.height-1,mInputColor,Color.white);
mApplet.resize(mColumns*mCellDimension.width+mRowLabelWidth,((mRows+1)*mCellDimension.height)+mCellDimension.height+mTitleHeight);
}
public void setCurrentValue(float val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(val);
mApplet.repaint();
}
public void stop()
{
stopped(true);
}
public void start()
{
stopped(false);
}
public void stopped(boolean stopped)
{
mIsStopped=stopped;
}
public boolean stopped()
{
return mIsStopped;
}
public void destroy()
{
}
public void setCurrentValue(int type,String val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(type,val);
mApplet.repaint();
}
public void update(Graphics graphics)
{
int cx;
int cy;
if(mFullUpdate)
{
paint(graphics);
mFullUpdate=false;
return;
}
graphics.setFont(mTitleFont);
for(int row=mStartDisplayRow;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row][col].needRedisplay())
{
cx=(col*mCellDimension.width)+2+mRowLabelWidth;
cy=((row+1)*mCellDimension.height)+2+mTitleHeight;
mCells[row][col].paint(graphics,cx,cy);
}
}
}
}
public synchronized void paint(Graphics graphics)
{
char strLabel[]=new char[1];
int i;
int j;
int cx;
int cy;
graphics.setFont(mTitleFont);
graphics.drawString(mStrTitle,(mControlDimension.width-graphics.getFontMetrics().stringWidth(mStrTitle))/2,12);
graphics.setColor(mInputColor);
graphics.fillRect(0,mCellDimension.height,mControlDimension.width,mCellDimension.height);
graphics.setFont(mTitleFont);
for(i=0;i<mRows+1;i++)
{
cy=(i+2)*mCellDimension.height;
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,cy,mControlDimension.width,2,true);
if(i<mRows)
{
graphics.setColor(mApplet.getBackground());
graphics.fillRect(1,cy+1,mRowLabelWidth-1,(2*mCellDimension.height)-2);
graphics.setColor(Color.red);
graphics.drawString(""+(i+1+mStartDisplayRow),2,cy+12);
}
}
graphics.setColor(Color.red);
for(i=0;i<mColumns;i++)
{
cx=i*mCellDimension.width;
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(cx+mRowLabelWidth,2*mCellDimension.height,1,mControlDimension.height,true);
}
for(i=mStartDisplayRow;i<mRows;i++)
{
for(j=0;j<mColumns;j++)
{
cx=(j*mCellDimension.width)+2+mRowLabelWidth;
cy=((i+1-mStartDisplayRow)*mCellDimension.height)+2+mTitleHeight;
if(mCells[i][j]!=null)mCells[i][j].paint(graphics,cx,cy);
}
}
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,mTitleHeight,mControlDimension.width,mControlDimension.height-mTitleHeight,false);
mInputArea.paint(graphics,1,mTitleHeight+1);
}
public void recalculate()
{
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row+mStartDisplayRow][col]!=null&&mCells[row+mStartDisplayRow][col].type()==Cell.FORMULA)
{
mCells[row+mStartDisplayRow][col].setRawValue(evaluateFormula(mCells[row+mStartDisplayRow][col].parseRoot()));
mCells[row+mStartDisplayRow][col].needRedisplay(true);
}
}
}
mApplet.repaint();
}
private float evaluateFormula(Node node)
{
float val=0.0f;
if(null==node)return val;
switch(node.type())
{
case Node.OP:
val=evaluateFormula(node.left());
switch(node.op())
{
case '+':
val += evaluateFormula(node.right());
break;
case '*':
val *= evaluateFormula(node.right());
break;
case '-':
val -= evaluateFormula(node.right());
break;
case '/':
val /= evaluateFormula(node.right());
break;
}
break;
case Node.VALUE:
val=node.value();
break;
case Node.CELL:
if(null==node)break;
if(null==mCells[node.row()][node.column()])break;
val=mCells[node.row()][node.column()].value();
break;
}
return val;
}
public boolean mouseDown(Event evt,int x,int y)
{
if(y<(mTitleHeight+mCellDimension.height))
{
mSelectedRow=-1;
if(y<=mTitleHeight)deselect(true);
return true;
}
if(x<mRowLabelWidth)
{
mSelectedRow=-1;
deselect(true);
return true;
}
mSelectedRow=((y-mCellDimension.height-mTitleHeight)/mCellDimension.height)+mStartDisplayRow;
mSelectedColumn=(x-mRowLabelWidth)/mCellDimension.width;
if(mSelectedRow>=mRows||mSelectedColumn>=mColumns)
{
mSelectedRow = -1;
deselect(true);
return true;
}
select();
return true;
}
public boolean keyDown(Event evt, int key)
{
mFullUpdate=true;
if(Key.LeftArrow==key||Key.RightArrow==key||Key.UpArrow==key||Key.DownArrow==key)
{
mInputArea.keyDown(Key.Return);
navigate(key);
}
else mInputArea.keyDown(key);
return true;
}
private void navigate(int key)
{
switch(key)
{
case Key.LeftArrow :
if(mSelectedColumn<=0)break;
mSelectedColumn--;
select();
break;
case Key.RightArrow :
if(mSelectedColumn>=mColumns)break;
mSelectedColumn++;
select();
break;
case Key.UpArrow :
if(mSelectedRow<=0)break;
mSelectedRow--;
ensureVisible();
select();
break;
case Key.DownArrow :
if(mSelectedRow+1>=mRows)break;
mSelectedRow++;
ensureVisible();
select();
break;
}
}
private void select()
{
Cell cell=mCells[mSelectedRow][mSelectedColumn];
if(null!=cell.getPrintString())mInputArea.setText(new String(cell.getPrintString()));
else mInputArea.setText(new String(""));
if(mCurrent!=null)mCurrent.deselect();
mCurrent=cell;
mCurrent.select();
mApplet.requestFocus();
mFullUpdate=true;
mApplet.repaint();
}
private void deselect(boolean destroy)
{
if(null==mCurrent)return;
mCurrent.deselect();
if(destroy)mCurrent=null;
}
public Applet applet()
{
return mApplet;
}
private void ensureVisible()
{
int yMin=(2*mCellDimension.height)+2+mTitleHeight;
Point currPoint=new Point(0,0);
yMin=(2*mCellDimension.height)+2+mTitleHeight;
currPoint.y=((mSelectedRow-mStartDisplayRow+2)*mCellDimension.height)+2+mTitleHeight;
currPoint.x=(mSelectedColumn*mCellDimension.width)+2+mRowLabelWidth;
if(currPoint.y>mControlDimension.height)mStartDisplayRow++;
else if(currPoint.y<yMin)mStartDisplayRow--;
}
}
//******************************************************************************************************
// ******************************************** CELL ***************************************************
//******************************************************************************************************
class Cell
{
public static final int VALUE = 0;
public static final int LABEL = 1;
public static final int URL = 2;
public static final int FORMULA = 3;
private Node mParseRoot;
private boolean mNeedRedisplay;
private boolean mSelected = false;
private boolean mTransientValue = false;
private int mType=Cell.VALUE;
private String mValueString = "";
private String mPrintString = "v";
private float mValue;
private Color mBgColor;
private Color mFgColor;
private Color mHighlightColor;
private int mWidth;
private int mHeight;
private SpreadSheet mSpreadSheet;
private boolean mPaused=false;
public Cell(SpreadSheet spreadSheet,Color bgColor,Color fgColor,Color highlightColor,int width,int height)
{
mSpreadSheet=spreadSheet;
mBgColor=bgColor;
mFgColor=fgColor;
mHighlightColor=highlightColor;
mWidth=width;
mHeight=height;
mNeedRedisplay=true;
}
public void setRawValue(float value)
{
mValueString=Float.toString(value);
mValue=value;
}
public void setValue(float value)
{
setRawValue(value);
mPrintString="v"+mValueString;
mType=Cell.VALUE;
mPaused=false;
mSpreadSheet.recalculate();
mNeedRedisplay=true;
}
public void setTransientValue(float value)
{
mTransientValue=true;
mValue=value;
mNeedRedisplay=true;
mSpreadSheet.recalculate();
}
public void setUnparsedValue(String s)
{
switch (s.charAt(0))
{
case 'v':
setValue(Cell.VALUE, s.substring(1));
break;
case 'f':
setValue(Cell.FORMULA, s.substring(1));
break;
case 'l':
setValue(Cell.LABEL, s.substring(1));
break;
case 'u':
setValue(Cell.URL, s.substring(1));
break;
}
}
public String parseFormula(String formula, Node node)
{
String subformula;
String restFormula;
float value;
int length = formula.length();
Node left;
Node right;
char op;
if(null==formula)return null;
subformula=parseValue(formula, node);
if(null==subformula||0==subformula.length())return null;
if(subformula==formula)return formula;
switch(op=subformula.charAt(0))
{
case 0:
return null;
case ')':
return subformula;
case '+':
case '*':
case '-':
case '/':
restFormula = subformula.substring(1);
subformula = parseValue(restFormula, right=new Node());
if(subformula != restFormula)
{
left = new Node(node);
node.left(left);
node.right(right);
node.op(op);
node.type(Node.OP);
return subformula;
}
else return formula;
default:
return formula;
}
}
public String parseValue(String formula, Node node)
{
char c=formula.charAt(0);
String subformula;
String restFormula;
float value;
int row;
int column;
restFormula = formula;
if (c == '(')
{
restFormula = formula.substring(1);
subformula = parseFormula(restFormula, node);
if(subformula == null || subformula.length() == restFormula.length())return formula;
else if (! (subformula.charAt(0) == ')'))return formula;
restFormula = subformula;
}
else if (c >= '0' && c <= '9')
{
int i;
try{value = Float.valueOf(formula).floatValue();}
catch (NumberFormatException exception){return formula;}
for (i=0; i < formula.length(); i++)
{
c = formula.charAt(i);
if ((c < '0' || c > '9') && c != '.')break;
}
node.type(Node.VALUE);
node.value(value);
restFormula = formula.substring(i);
return restFormula;
}
else if (c >= 'A' && c <= 'Z')
{
int i;
column = c - 'A';
restFormula = formula.substring(1);
row = Float.valueOf(restFormula).intValue();
for(i=0; i < restFormula.length(); i++)
{
c = restFormula.charAt(i);
if (c < '0' || c > '9')break;
}
node.row(row-1);
node.column(column);
node.type(Node.CELL);
if (i == restFormula.length())restFormula=null;
else
{
restFormula = restFormula.substring(i);
if (restFormula.charAt(0) == 0)return null;
}
}
return restFormula;
}
public void setValue(int type, String s)
{
mPaused=false;
mValueString=new String(s);
mType=type;
mNeedRedisplay=true;
switch(mType)
{
case Cell.VALUE:
setValue(Float.valueOf(s).floatValue());
break;
case Cell.LABEL:
mPrintString = "l" + mValueString;
break;
case Cell.URL:
mPrintString = "u" + mValueString;
break;
case Cell.FORMULA:
parseFormula(mValueString,mParseRoot=new Node());
mPrintString = "f" + mValueString;
break;
}
mSpreadSheet.recalculate();
}
public String getValueString()
{
return mValueString;
}
public String getPrintString()
{
return mPrintString;
}
public void select()
{
mSelected=true;
mPaused=true;
}
public void deselect()
{
mSelected=false;
mPaused=false;
mNeedRedisplay=true;
mSpreadSheet.applet().repaint();
}
public void paint(Graphics graphics,int x,int y)
{
if(mSelected)graphics.setColor(mHighlightColor);
else graphics.setColor(mBgColor);
graphics.fillRect(x+1,y+1,mWidth-1,mHeight-1);
if(null!=mValueString)
{
switch(mType)
{
case Cell.VALUE:
case Cell.LABEL:
graphics.setColor(mFgColor);
break;
case Cell.FORMULA:
graphics.setColor(Color.red);
break;
case Cell.URL:
graphics.setColor(Color.blue);
break;
}
if(!mTransientValue)
{
if(mValueString.length()>14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
}
else graphics.drawString(""+mValue,x,y+(mHeight/2)+5);
mNeedRedisplay=false;
}
}
public int type()
{
return mType;
}
public Node parseRoot()
{
return mParseRoot;
}
public void needRedisplay(boolean needRedisplay)
{
mNeedRedisplay=needRedisplay;
}
public boolean needRedisplay()
{
return mNeedRedisplay;
}
public float value()
{
return mValue;
}
public SpreadSheet spreadSheet()
{
return mSpreadSheet;
}
public boolean paused()
{
return mPaused;
}
}
//******************************************************************************************************
// *************************************** NODE *******************************************************
//******************************************************************************************************
class Node
{
public static final int OP = 0;
public static final int VALUE = 1;
public static final int CELL = 2;
private int mType;
private Node mLeft;
private Node mRight;
private int mRow;
private int mColumn;
private float mValue;
private char mOp;
public Node()
{
mLeft=null;
mRight=null;
mValue=0;
mRow=-1;
mColumn=-1;
mOp=0;
mType=Node.VALUE;
}
public Node(Node node)
{
mLeft=node.mLeft;
mRight=node.mRight;
mValue=node.mValue;
mRow=node.mRow;
mColumn=node.mColumn;
mOp=node.mOp;
mType=node.mType;
}
public void print(int indentLevel)
{
char l[] = new char[1];
switch(mType)
{
case Node.VALUE:
break;
case Node.CELL:
l[0] = (char)((int)'A' + column());
break;
case Node.OP:
mLeft.print(indentLevel + 3);
mRight.print(indentLevel + 3);
break;
}
}
public int type()
{
return mType;
}
public void type(int type)
{
mType=type;
}
public float value()
{
return mValue;
}
public void value(float value)
{
mValue=value;
}
public Node left()
{
return mLeft;
}
public void left(Node left)
{
mLeft=left;
}
public Node right()
{
return mRight;
}
public void right(Node right)
{
mRight=right;
}
public char op()
{
return mOp;
}
public void op(char op)
{
mOp=op;
}
public int row()
{
return mRow;
}
public void row(int row)
{
mRow=row;
}
public int column()
{
return mColumn;
}
public void column(int column)
{
mColumn=column;
}
}
class InputField
{
private int mMaxchars = 50;
private Applet mApplet;
private String mStringValue;
private char mBuffer[];
private int mChars;
private int mWidth;
private int mHeight;
private Color mBgColor;
private Color mFgColor;
public InputField(String initValue,Applet applet,int width,int height,Color bgColor, Color fgColor)
{
mWidth=width;
mHeight=height;
mBgColor=bgColor;
mFgColor=fgColor;
mApplet=applet;
mBuffer = new char[mMaxchars];
mChars = 0;
if(initValue != null)
{
initValue.getChars(0, initValue.length(),mBuffer, 0);
mChars = initValue.length();
}
mStringValue=initValue;
}
public void setText(String val)
{
int i;
for(i=0; i < mMaxchars; i++)mBuffer[i] = 0;
mStringValue=new String(val);
if (val == null)
{
mStringValue= "";
mChars = 0;
mBuffer[0] = 0;
}
else
{
mStringValue.getChars(0,mStringValue.length(), mBuffer, 0);
mChars = val.length();
mStringValue = new String(mBuffer);
}
}
public String getValue()
{
return mStringValue;
}
public void paint(Graphics g, int x, int y)
{
g.setColor(mBgColor);
g.fillRect(x, y,mWidth,mHeight);
if(mStringValue!= null)
{
g.setColor(mFgColor);
g.drawString(mStringValue, x, y + (mHeight / 2) + 3);
}
}
public void mouseUp(int x, int y)
{
}
public void keyDown(int key)
{
if(mChars<mMaxchars)
{
switch(key)
{
case Key.BackSpace :
--mChars;
if(mChars<0)mChars=0;
mBuffer[mChars] = 0;
mStringValue = new String(new String(mBuffer));
break;
case Key.Return :
selected();
break;
default:
mBuffer[mChars++] = (char)key;
mStringValue = new String(new String(mBuffer));
break;
}
}
mApplet.repaint();
}
public void selected()
{
}
public Applet applet()
{
return mApplet;
}
}
class SpreadSheetInput extends InputField
{
SpreadSheet mSpreadSheet;
public SpreadSheetInput(String initValue,Applet app,SpreadSheet spreadSheet,int width,int height,Color bgColor,Color fgColor)
{
super(initValue,app,width,height,bgColor,fgColor);
mSpreadSheet=spreadSheet;
}
public void selected()
{
float f;
switch(getValue().charAt(0))
{
case 'v':
try{f=Float.valueOf(getValue().substring(1)).floatValue();mSpreadSheet.setCurrentValue(f);}
catch(Exception exception){;}
break;
case 'l':
mSpreadSheet.setCurrentValue(Cell.LABEL,getValue().substring(1));
break;
case 'u':
mSpreadSheet.setCurrentValue(Cell.URL,getValue().substring(1));
break;
case 'f':
mSpreadSheet.setCurrentValue(Cell.FORMULA,getValue().substring(1));
break;
}
}
}
class Key
{
public static final int LeftArrow=1006;
public static final int RightArrow=1007;
public static final int UpArrow=1004;
public static final int DownArrow=1005;
public static final int BackSpace=8;
public static final int Return=10;
public Key()
{
}
};

BIN
java/SPREAD/INPUTF~1.CLA Normal file

Binary file not shown.

BIN
java/SPREAD/KEY~1.CLA Normal file

Binary file not shown.

BIN
java/SPREAD/MONEY~1.CLA Normal file

Binary file not shown.

85
java/SPREAD/MONEY~1.JAV Normal file
View File

@@ -0,0 +1,85 @@
class Money
{
private double mValue;
public Money()
{
setValue(0.00);
}
public Money(double value)
{
setValue(value);
}
public Money(Money money)
{
setValue(money.getValue());
}
public double getValue()
{
return mValue;
}
public void setValue(double value)
{
mValue=value;
}
public String toString()
{
String strDouble;
String strFixed;
String strFinal;
String strFraction;
int strLength;
int commaCount;
int initPos;
int lastPos;
int ptIndex;
lastPos=0;
strFraction=new String();
strFinal=new String();
strDouble=stringRep(getValue()); // strDouble=String.valueOf(getValue());
strLength=strDouble.length();
for(ptIndex=0;ptIndex<strLength&&strDouble.charAt(ptIndex)!='.';ptIndex++);
if(ptIndex>=strLength)strFraction=".00";
else strFraction=strDouble.substring(ptIndex,strLength);
if(2==strFraction.length())strFraction+="0";
strFixed=strDouble.substring(0,ptIndex);
strLength=strFixed.length();
initPos=strLength%3;
commaCount=strLength/3;
if(0==initPos)
{
initPos+=3;
commaCount--;
}
strFinal+="$";
for(int count=0;count<commaCount;count++)
{
strFinal+=strFixed.substring(lastPos,initPos);
strFinal+=",";
lastPos=initPos;
initPos+=3;
}
strFinal+=strFixed.substring(lastPos,initPos);
strFinal+=strFraction;
return strFinal;
}
private String stringRep(double value)
{
int ptIndex;
int strLength;
int strFractionLength;
String strRep;
String strFraction;
String strWhole;
strRep=String.valueOf(value+.005);
strLength=strRep.length();
for(ptIndex=0;ptIndex<strLength&&strRep.charAt(ptIndex)!='.';ptIndex++);
if(ptIndex>=strLength)return String.valueOf(value);
strFraction=strRep.substring(ptIndex+1,strLength);
strFractionLength=strFraction.length();
if(strFractionLength>2)strFraction=strRep.substring(ptIndex+1,strLength-(strFractionLength-2));
strWhole=strRep.substring(0,ptIndex);
return strWhole+"."+strFraction;
}
};

BIN
java/SPREAD/NODE~1.CLA Normal file

Binary file not shown.

11
java/SPREAD/NOTES.TXT Normal file
View File

@@ -0,0 +1,11 @@
//
// * Parse a spreadsheet formula. The syntax is defined as:
// *
// * formula -> value
// * formula -> value op value
// * value -> '(' formula ')'
// * value -> cell
// * value -> <number>
// * op -> '+' | '*' | '/' | '-'
// * cell -> <letter><number>
// */

BIN
java/SPREAD/PREPAY~1.CLA Normal file

Binary file not shown.

55
java/SPREAD/PREPAY~1.JAV Normal file
View File

@@ -0,0 +1,55 @@
public class Prepayment
{
double mAmount;
double mIncrement;
double mFrequency;
int mPeriod;
public Prepayment()
{
mAmount=0.00;
mIncrement=0.00;
mFrequency=0.00;
mPeriod=1;
}
public Prepayment(double amount,double increment,double frequency)
{
mAmount=amount;
mIncrement=increment;
mFrequency=frequency;
mPeriod=1;
}
public double amount()
{
return mAmount;
}
public void amount(double amount)
{
mAmount=amount;
}
public double increment()
{
return mIncrement;
}
public void increment(double increment)
{
mIncrement=increment;
}
public double frequency()
{
return mFrequency;
}
public void frequency(double frequency)
{
mFrequency=frequency;
}
public int period()
{
return mPeriod;
}
public void period(int period)
{
mPeriod=period;
}
};

306
java/SPREAD/PROTO~1.JAV Normal file
View File

@@ -0,0 +1,306 @@
import java.awt.*;
public class Proto extends java.applet.Applet
{
SpreadSheetInterface mSpreadSheet;
PurePassThru mPurePassThru=new PurePassThru();
PureCashflow mPureCashflows[];
TextField mCtlPrincipal;
TextField mCtlInterest;
TextField mCtlTerm;
TextField mCtlPrepayment;
TextField mCtlIncrement;
TextField mCtlFrequency;
Label mCtlCost;
Button mCtlButton;
public void init()
{
performLayout();
mSpreadSheet=new SpreadSheetInterface(this,361,10,new Dimension(630,200));
mSpreadSheet.setDocumentTitle("Paydown Calculator v1.00");
mSpreadSheet.gridLock(true);
repaint();
}
public void update(Graphics graphics)
{
if(null!=mSpreadSheet)mSpreadSheet.update(graphics);
}
public void paint(Graphics graphics)
{
if(null!=mSpreadSheet)mSpreadSheet.paint(graphics);
}
public boolean mouseDown(Event event,int x,int y)
{
if(null!=mCtlPrincipal&&mCtlPrincipal==event.target)return false;
else if(null!=mCtlInterest&&mCtlInterest==event.target)return false;
else if(null!=mCtlTerm&&mCtlTerm==event.target)return false;
else if(null!=mCtlButton&&mCtlButton==event.target)return false;
else if(null!=mCtlPrepayment&&mCtlPrepayment==event.target)return false;
else if(null!=mCtlIncrement&&mCtlIncrement==event.target)return false;
else if(null!=mCtlFrequency&&mCtlFrequency==event.target)return false;
else if(null!=mSpreadSheet)return mSpreadSheet.mouseDown(event,x,y);
return true;
}
public boolean keyDown(Event event,int key)
{
if(null!=mCtlPrincipal&&mCtlPrincipal==event.target)return false;
else if(null!=mCtlInterest&&mCtlInterest==event.target)return false;
else if(null!=mCtlTerm&&mCtlTerm==event.target)return false;
else if(null!=mCtlButton&&mCtlButton==event.target)return false;
else if(null!=mCtlPrepayment&&mCtlPrepayment==event.target)return false;
else if(null!=mCtlIncrement&&mCtlIncrement==event.target)return false;
else if(null!=mCtlFrequency&&mCtlFrequency==event.target)return false;
else if(null!=mSpreadSheet)return mSpreadSheet.keyDown(event,key);
return true;
}
public void performLayout()
{
GridBagLayout layout=new GridBagLayout();
GridBagConstraints constraints=new GridBagConstraints();
setFont(new Font("Fixed",Font.BOLD,12));
setLayout(layout);
constraints.fill=GridBagConstraints.BOTH;
constraints.weightx=0.25;
Label prnLabel=new Label("Principal",Label.LEFT);
layout.setConstraints(prnLabel,constraints);
add(prnLabel);
mCtlPrincipal=new TextField("$100000.00");
layout.setConstraints(mCtlPrincipal,constraints);
add(mCtlPrincipal);
Label intLabel=new Label("Interest",Label.LEFT);
layout.setConstraints(intLabel,constraints);
add(intLabel);
mCtlInterest=new TextField("8.00%");
layout.setConstraints(mCtlInterest,constraints);
add(mCtlInterest);
Label trmLabel=new Label("Term",Label.LEFT);
layout.setConstraints(trmLabel,constraints);
add(trmLabel);
mCtlTerm=new TextField("360");
layout.setConstraints(mCtlTerm,constraints);
add(mCtlTerm);
constraints.gridwidth=GridBagConstraints.REMAINDER;
mCtlButton=new Button("Calculate");
layout.setConstraints(mCtlButton,constraints);
add(mCtlButton);
constraints.fill=GridBagConstraints.BOTH;
constraints.gridwidth=1;
Label ppyLabel=new Label("Prepayment",Label.LEFT);
layout.setConstraints(ppyLabel,constraints);
add(ppyLabel);
mCtlPrepayment=new TextField("$0.00");
layout.setConstraints(mCtlPrepayment,constraints);
add(mCtlPrepayment);
constraints.gridwidth=GridBagConstraints.REMAINDER;
Label ppyHlpLabel=new Label("Enter the amount of your prepayment(s).");
layout.setConstraints(ppyHlpLabel,constraints);
add(ppyHlpLabel);
constraints.fill=GridBagConstraints.BOTH;
constraints.gridwidth=1;
Label incLabel=new Label("Increment",Label.LEFT);
layout.setConstraints(incLabel,constraints);
add(incLabel);
mCtlIncrement=new TextField("$0.00");
layout.setConstraints(mCtlIncrement,constraints);
add(mCtlIncrement);
constraints.gridwidth=GridBagConstraints.REMAINDER;
Label incHlpLabel=new Label("Increment the prepayment(s) by this amount.");
layout.setConstraints(incHlpLabel,constraints);
add(incHlpLabel);
constraints.fill=GridBagConstraints.BOTH;
constraints.gridwidth=1;
Label frqLabel=new Label("Frequency",Label.LEFT);
layout.setConstraints(frqLabel,constraints);
add(frqLabel);
mCtlFrequency=new TextField("0.00");
layout.setConstraints(mCtlFrequency,constraints);
add(mCtlFrequency);
constraints.gridwidth=GridBagConstraints.REMAINDER;
Label frqHlpLabel=new Label("Frequency at which to increment the prepayments (ie) number of months.");
layout.setConstraints(frqHlpLabel,constraints);
add(frqHlpLabel);
constraints.fill=GridBagConstraints.BOTH;
constraints.gridwidth=1;
Label costLabel=new Label("Cost Of Capital:",Label.LEFT);
layout.setConstraints(costLabel,constraints);
add(costLabel);
mCtlCost=new Label("$0.00",Label.LEFT);
constraints.gridwidth=GridBagConstraints.REMAINDER;
layout.setConstraints(mCtlCost,constraints);
add(mCtlCost);
}
public boolean action(Event event,Object object)
{
if(null!=mCtlButton&&mCtlButton==event.target)performCalc();
return true;
}
public void performCalc()
{
Prepayment prepayment=new Prepayment();
String strPrincipal=mCtlPrincipal.getText();
String strInterest=mCtlInterest.getText();
String strTerm=mCtlTerm.getText();
String strPrepayment=mCtlPrepayment.getText();
String strIncrement=mCtlIncrement.getText();
String strFrequency=mCtlFrequency.getText();
Double workDouble;
double principal;
double interest;
int term;
int itemIndex;
workDouble=new Double(0);
strPrincipal=strPrincipal.replace('$',' ');
workDouble=workDouble.valueOf(strPrincipal);
principal=workDouble.doubleValue();
strInterest=strInterest.replace('%',' ');
workDouble=workDouble.valueOf(strInterest);
interest=workDouble.doubleValue();
term=Integer.parseInt(strTerm);
strPrepayment=strPrepayment.replace('$',' ');
workDouble=workDouble.valueOf(strPrepayment);
prepayment.amount(workDouble.doubleValue());
strIncrement=strIncrement.replace('$',' ');
workDouble=workDouble.valueOf(strIncrement);
prepayment.increment(workDouble.doubleValue());
workDouble=workDouble.valueOf(strFrequency);
prepayment.frequency(workDouble.doubleValue());
mPurePassThru.issBal(principal);
mPurePassThru.wac(interest);
mPurePassThru.coupon(interest);
mPurePassThru.wam((short)term);
mPurePassThru.origTerm((short)term);
mPurePassThru.psa(0.00);
if(0.00!=prepayment.amount()||0.00!=prepayment.increment())generateFlows(prepayment);
else generateFlows();
Money money=new Money(0);
mSpreadSheet.clear();
repaint();
mSpreadSheet.setCellData(0,0,"BeginBal");
mSpreadSheet.setCellData(0,1,"SMM");
mSpreadSheet.setCellData(0,2,"MtgPay");
mSpreadSheet.setCellData(0,3,"NetIntPay");
mSpreadSheet.setCellData(0,4,"GrossIntPay");
mSpreadSheet.setCellData(0,5,"SchedPrinPay");
mSpreadSheet.setCellData(0,6,"Prepayment");
mSpreadSheet.setCellData(0,7,"TotPrin");
mSpreadSheet.setCellData(0,8,"Cashflow");
mSpreadSheet.setCellData(0,9,"Factor");
for(itemIndex=0;itemIndex<mPurePassThru.wam();itemIndex++)
{
if(mPureCashflows[itemIndex]==null)break;
money.setValue(mPureCashflows[itemIndex].beginBal());
mSpreadSheet.setCellData(itemIndex+1,0,money.toString());
money.setValue(mPureCashflows[itemIndex].smm());
mSpreadSheet.setCellData(itemIndex+1,1,money.toString());
money.setValue(mPureCashflows[itemIndex].mtgPay());
mSpreadSheet.setCellData(itemIndex+1,2,money.toString());
money.setValue(mPureCashflows[itemIndex].netIntPay());
mSpreadSheet.setCellData(itemIndex+1,3,money.toString());
money.setValue(mPureCashflows[itemIndex].grossIntPay());
mSpreadSheet.setCellData(itemIndex+1,4,money.toString());
money.setValue(mPureCashflows[itemIndex].schedPrinPay());
mSpreadSheet.setCellData(itemIndex+1,5,money.toString());
money.setValue(mPureCashflows[itemIndex].prepayment());
mSpreadSheet.setCellData(itemIndex+1,6,money.toString());
money.setValue(mPureCashflows[itemIndex].totPrin());
mSpreadSheet.setCellData(itemIndex+1,7,money.toString());
money.setValue(mPureCashflows[itemIndex].cashflow());
mSpreadSheet.setCellData(itemIndex+1,8,money.toString());
mSpreadSheet.setCellData(itemIndex+1,9,String.valueOf(mPureCashflows[itemIndex].factor()));
}
money.setValue(mPureCashflows[itemIndex-1].grossIntPay());
mCtlCost.setText(money.toString());
repaint();
}
public void generateFlows()
{
double issBal;
double tmpCPR;
int actualMonth;
int indexFlows;
indexFlows=0;
mPureCashflows=new PureCashflow[mPurePassThru.wam()];
issBal=mPurePassThru.issBal();
for(int wam=mPurePassThru.wam();wam>0&&issBal>0.00;wam--)
{
mPureCashflows[indexFlows]=new PureCashflow();
actualMonth=(mPurePassThru.origTerm()-wam)+1;
if(actualMonth<=30)tmpCPR=.002*(double)actualMonth;
else tmpCPR=.06;
mPureCashflows[indexFlows].beginBal(issBal);
mPureCashflows[indexFlows].smm(1.00-Math.pow(1.00-(tmpCPR*mPurePassThru.psa()/100.00),1.00/12.00));
if(0==indexFlows)mPureCashflows[indexFlows].mtgPay((issBal*(mPurePassThru.wac()/1200.00))/
(1.00-Math.pow(1.00/(1.00+(mPurePassThru.wac()/1200.00)),(double)wam)));
else mPureCashflows[indexFlows].mtgPay(mPureCashflows[indexFlows-1].mtgPay());
if(issBal<=mPureCashflows[indexFlows].mtgPay())mPureCashflows[indexFlows].mtgPay(issBal);
mPureCashflows[indexFlows].netIntPay(issBal*(mPurePassThru.coupon()/1200.00));
if(0==indexFlows)mPureCashflows[indexFlows].grossIntPay(mPureCashflows[indexFlows].netIntPay());
else mPureCashflows[indexFlows].grossIntPay(mPureCashflows[indexFlows-1].grossIntPay()+mPureCashflows[indexFlows].netIntPay());
mPureCashflows[indexFlows].schedPrinPay(mPureCashflows[indexFlows].mtgPay()-mPureCashflows[indexFlows].netIntPay());
mPureCashflows[indexFlows].prepayment(0.00);
mPureCashflows[indexFlows].totPrin(mPureCashflows[indexFlows].schedPrinPay()+mPureCashflows[indexFlows].prepayment());
mPureCashflows[indexFlows].cashflow(mPureCashflows[indexFlows].netIntPay()+mPureCashflows[indexFlows].totPrin());
mPureCashflows[indexFlows].factor(issBal/mPurePassThru.issBal());
issBal-=mPureCashflows[indexFlows].totPrin();
indexFlows++;
}
}
public void generateFlows(Prepayment prepayment)
{
double issBal;
double tmpCPR;
int actualMonth;
int indexFlows;
indexFlows=0;
mPureCashflows=new PureCashflow[mPurePassThru.wam()];
issBal=mPurePassThru.issBal();
for(int wam=mPurePassThru.wam();wam>0&&issBal>0.00;wam--)
{
mPureCashflows[indexFlows]=new PureCashflow();
actualMonth=(mPurePassThru.origTerm()-wam)+1;
if(actualMonth<=30)tmpCPR=.002*(double)actualMonth;
else tmpCPR=.06;
mPureCashflows[indexFlows].beginBal(issBal);
mPureCashflows[indexFlows].smm(1.00-Math.pow(1.00-(tmpCPR*mPurePassThru.psa()/100.00),1.00/12.00));
if(0==indexFlows)mPureCashflows[indexFlows].mtgPay((issBal*(mPurePassThru.wac()/1200.00))/
(1.00-Math.pow(1.00/(1.00+(mPurePassThru.wac()/1200.00)),(double)wam)));
else mPureCashflows[indexFlows].mtgPay(mPureCashflows[indexFlows-1].mtgPay());
if(issBal<=mPureCashflows[indexFlows].mtgPay())mPureCashflows[indexFlows].mtgPay(issBal);
mPureCashflows[indexFlows].netIntPay(issBal*(mPurePassThru.coupon()/1200.00));
if(0==indexFlows)mPureCashflows[indexFlows].grossIntPay(mPureCashflows[indexFlows].netIntPay());
else mPureCashflows[indexFlows].grossIntPay(mPureCashflows[indexFlows-1].grossIntPay()+mPureCashflows[indexFlows].netIntPay());
mPureCashflows[indexFlows].schedPrinPay(mPureCashflows[indexFlows].mtgPay()-mPureCashflows[indexFlows].netIntPay());
mPureCashflows[indexFlows].prepayment(prepayment.amount());
prepayment.period(prepayment.period()+1);
if(prepayment.period()>prepayment.frequency())
{
prepayment.amount(prepayment.amount()+prepayment.increment());
prepayment.period(1);
}
mPureCashflows[indexFlows].totPrin(mPureCashflows[indexFlows].schedPrinPay()+mPureCashflows[indexFlows].prepayment());
mPureCashflows[indexFlows].cashflow(mPureCashflows[indexFlows].netIntPay()+mPureCashflows[indexFlows].totPrin());
mPureCashflows[indexFlows].factor(issBal/mPurePassThru.issBal());
issBal-=mPureCashflows[indexFlows].totPrin();
indexFlows++;
}
}
}

BIN
java/SPREAD/PURECA~1.CLA Normal file

Binary file not shown.

140
java/SPREAD/PURECA~1.JAV Normal file
View File

@@ -0,0 +1,140 @@
class PureCashflow
{
double mBeginBal;
double mSMM;
double mMtgPay;
double mNetIntPay;
double mGrossIntPay;
double mSchedPrinPay;
double mPrepayment;
double mTotPrin;
double mCashFlow;
double mFactor;
public PureCashflow()
{
mBeginBal=0.00;
mSMM=0.00;
mMtgPay=0.00;
mNetIntPay=0.00;
mGrossIntPay=0.00;
mSchedPrinPay=0.00;
mPrepayment=0.00;
mTotPrin=0.00;
mCashFlow=0.00;
mFactor=0.00;
}
public PureCashflow(PureCashflow pureCashflow)
{
beginBal(pureCashflow.beginBal());
smm(pureCashflow.smm());
mtgPay(pureCashflow.mtgPay());
netIntPay(pureCashflow.netIntPay());
grossIntPay(pureCashflow.grossIntPay());
schedPrinPay(pureCashflow.schedPrinPay());
prepayment(pureCashflow.prepayment());
totPrin(pureCashflow.totPrin());
cashflow(pureCashflow.cashflow());
factor(pureCashflow.factor());
}
public double beginBal()
{
return mBeginBal;
}
public void beginBal(double beginBal)
{
mBeginBal=beginBal;
}
public double smm()
{
return mSMM;
}
public void smm(double smm)
{
mSMM=smm;
}
public double mtgPay()
{
return mMtgPay;
}
public void mtgPay(double mtgPay)
{
mMtgPay=mtgPay;
}
public double netIntPay()
{
return mNetIntPay;
}
public void netIntPay(double netIntPay)
{
mNetIntPay=netIntPay;
}
public double grossIntPay()
{
return mGrossIntPay;
}
public void grossIntPay(double grossIntPay)
{
mGrossIntPay=grossIntPay;
}
public double schedPrinPay()
{
return mSchedPrinPay;
}
public void schedPrinPay(double schedPrinPay)
{
mSchedPrinPay=schedPrinPay;
}
public double prepayment()
{
return mPrepayment;
}
public void prepayment(double prepayment)
{
mPrepayment=prepayment;
}
public double totPrin()
{
return mTotPrin;
}
public void totPrin(double totPrin)
{
mTotPrin=totPrin;
}
public double cashflow()
{
return mCashFlow;
}
public void cashflow(double cashFlow)
{
mCashFlow=cashFlow;
}
public double factor()
{
return mFactor;
}
public void factor(double factor)
{
mFactor=factor;
}
public String toString()
{
String strReturn;
Money money;
strReturn=new String();
money=new Money();
strReturn+=(new Money(beginBal())).toString();
// strReturn+=(new Money(smm())).toString();
strReturn+=(new Money(mtgPay())).toString();
strReturn+=(new Money(netIntPay())).toString();
strReturn+=(new Money(grossIntPay())).toString();
strReturn+=(new Money(schedPrinPay())).toString();
strReturn+=(new Money(prepayment())).toString();
strReturn+=(new Money(totPrin())).toString();
strReturn+=(new Money(cashflow())).toString()+" ";
// strReturn+=String.valueOf(factor());
return strReturn;
}
}

BIN
java/SPREAD/PUREPA~1.CLA Normal file

Binary file not shown.

86
java/SPREAD/PUREPA~1.JAV Normal file
View File

@@ -0,0 +1,86 @@
class PurePassThru
{
int mSanity;
double mIssBal;
double mWAC;
double mCoupon;
short mWAM;
short mOrigTerm;
double mPSA;
public PurePassThru()
{
mSanity=0;
mIssBal=0.00;
mWAC=0.00;
mCoupon=0.00;
mWAM=0;
mOrigTerm=0;
mPSA=0.00;
}
public PurePassThru(PurePassThru purePassThru)
{
sanity(purePassThru.sanity());
issBal(purePassThru.issBal());
wac(purePassThru.wac());
coupon(purePassThru.coupon());
wam(purePassThru.wam());
origTerm(purePassThru.origTerm());
psa(purePassThru.psa());
}
public int sanity()
{
return mSanity;
}
public void sanity(int sanity)
{
mSanity=sanity;
}
public double issBal()
{
return mIssBal;
}
public void issBal(double issBal)
{
mIssBal=issBal;
}
public double wac()
{
return mWAC;
}
public void wac(double wac)
{
mWAC=wac;
}
public double coupon()
{
return mCoupon;
}
public void coupon(double coupon)
{
mCoupon=coupon;
}
public short wam()
{
return mWAM;
}
public void wam(short wam)
{
mWAM=wam;
}
public short origTerm()
{
return mOrigTerm;
}
public void origTerm(short origTerm)
{
mOrigTerm=origTerm;
}
public double psa()
{
return mPSA;
}
public void psa(double psa)
{
mPSA=psa;
}
}

293
java/SPREAD/SCRAPS.TXT Normal file
View File

@@ -0,0 +1,293 @@
// cell = mCells[mSelectedRow][mSelectedColumn];
// if(null!=cell.getPrintString())mInputArea.setText(new String(cell.getPrintString()));
// else mInputArea.setText(new String(""));
// if(mCurrent!=null)mCurrent.deselect();
// mCurrent=cell;
// mCurrent.select();
// requestFocus();
// mFullUpdate = true;
// repaint();
// graphics.fillRect(x,y,mWidth-1,mHeight);
if(mTransientValue)graphics.drawString("" + mValue,x,y+(mHeight/2)+5);
else
{
if(mValueString.length() > 14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
}
public synchronized void paint(Graphics graphics)
{
int i;
int j;
int cx;
int cy;
char strLabel[]=new char[1];
Dimension clientRect=size();
graphics.setFont(mTitleFont);
graphics.drawString(mStrTitle,(clientRect.width-graphics.getFontMetrics().stringWidth(mStrTitle))/2,12);
graphics.setColor(mInputColor);
graphics.fillRect(0,mCellDimension.height,clientRect.width,mCellDimension.height);
graphics.setFont(mTitleFont);
for(i=0;i<mRows+1;i++)
// for(i=mStartDisplayRow;i<mRows;i++)
{
cy=(i+2)*mCellDimension.height;
graphics.setColor(getBackground());
graphics.draw3DRect(0,cy,clientRect.width,2,true);
if(i<mRows)
{
// graphics.setColor(Color.red);
// graphics.drawString(""+(i+1),2,cy+12);
graphics.setColor(getBackground());
graphics.fillRect(1,cy+1,mRowLabelWidth-1,(2*mCellDimension.height)-2);
graphics.setColor(Color.red);
graphics.drawString(""+(i+1+mStartDisplayRow),2,cy+12);
}
}
graphics.setColor(Color.red);
for(i=0;i<mColumns;i++)
{
cx=i*mCellDimension.width;
graphics.setColor(getBackground());
graphics.draw3DRect(cx+mRowLabelWidth,2*mCellDimension.height,1,clientRect.height,true);
// if(i<mColumns)
// {
// graphics.setColor(Color.red);
// strLabel[0]=(char)((int)'A'+i);
// l[0]=(char)((int)'A'+i);
// graphics.drawString(new String(strLabel),cx+mRowLabelWidth+(mCellDimension.width/2),clientRect.height-3);
// }
}
for(i=0;i<mRows;i++) // for(i=mStartDisplayRow;i<mRows;i++)
{
for(j=0;j<mColumns;j++)
{
cx=(j*mCellDimension.width)+2+mRowLabelWidth;
cy=((i+1)*mCellDimension.height)+2+mTitleHeight;
if(mCells[i+mStartDisplayRow][j]!=null)mCells[i+mStartDisplayRow][j].paint(graphics,cx,cy);
}
}
graphics.setColor(getBackground());
graphics.draw3DRect(0,mTitleHeight,clientRect.width,clientRect.height-mTitleHeight,false);
mInputArea.paint(graphics,1,mTitleHeight+1);
}
-c
graphics.setColor(Color.red);
for(i=0;i<mColumns;i++)
{
cx=i*mCellDimension.width;
graphics.setColor(getBackground());
graphics.draw3DRect(cx+mRowLabelWidth,2*mCellDimension.height,1,clientRect.height,true);
// if(i<mColumns)
// {
// graphics.setColor(Color.red);
// strLabel[0]=(char)((int)'A'+i);
// l[0]=(char)((int)'A'+i);
// graphics.drawString(new String(strLabel),cx+mRowLabelWidth+(mCellDimension.width/2),clientRect.height-3);
// }
}
// for(i=0;i<mRows;i++) // for(i=mStartDisplayRow;i<mRows;i++)
// {
// for(j=0;j<mColumns;j++)
// {
// cx=(j*mCellDimension.width)+2+mRowLabelWidth;
// cy=((i+1)*mCellDimension.height)+2+mTitleHeight;
// if(mCells[i+mStartDisplayRow][j]!=null)mCells[i+mStartDisplayRow][j].paint(graphics,cx,cy);
// }
// }
public void paint(Graphics graphics,int x,int y)
{
if(mSelected)graphics.setColor(mHighlightColor);
else graphics.setColor(mBgColor);
// graphics.fillRect(x+1,y+1,mWidth-2,mHeight-2);
graphics.fillRect(x+1,y+1,mWidth-1,mHeight-1);
if(null!=mValueString)
{
switch(mType)
{
case Cell.VALUE:
case Cell.LABEL:
graphics.setColor(mFgColor);
break;
case Cell.FORMULA:
graphics.setColor(Color.red);
break;
case Cell.URL:
graphics.setColor(Color.blue);
break;
}
if(!mTransientValue)
{
if(mValueString.length()>14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
}
else graphics.drawString(""+mValue,x,y+(mHeight/2)+5);
mNeedRedisplay=false;
}
}
//******************************************************************************************************
// ***************************************** CELLTHREAD ***********************************************
//******************************************************************************************************
class CellThread extends Thread
{
private Cell mTarget;
private InputStream mDataStream=null;
private StreamTokenizer mTokenStream;
public CellThread(Cell cell)
{
super("CellThread");
mTarget=cell;
}
public void run()
{
try
{
mDataStream = new URL(mTarget.spreadSheet().applet().getDocumentBase(),mTarget.getValueString()).openStream();
mTokenStream = new StreamTokenizer(mDataStream);
mTokenStream.eolIsSignificant(false);
while(true)
{
switch(mTokenStream.nextToken())
{
case mTokenStream.TT_EOF:
mDataStream.close();
return;
default:
break;
case mTokenStream.TT_NUMBER:
mTarget.setTransientValue((float)mTokenStream.nval);
if(!mTarget.spreadSheet().stopped()&&!mTarget.paused())mTarget.spreadSheet().applet().repaint();
break;
}
try {Thread.sleep(2000);}
catch(InterruptedException exception){break;}
}
}
catch (IOException exception){return;}
}
}
// if(mType == Cell.URL)
// {
// mCellThread.stop();
// mCellThread=null;
// }
// mCellThread = new CellThread(this);
// mCellThread.start();
// public CellThread cellThread()
// {
// return mCellThread;
// }
//import java.awt.Font;
//import java.awt.Graphics;
//import java.awt.Color;
//import java.util.Date;
//import java.awt.Frame;
//import java.awt.image.*;
//import java.applet.*;
//import java.util.*;
//import java.net.*;
public synchronized void paint(Graphics graphics)
{
char strLabel[]=new char[1];
int i;
int j;
int cx;
int cy;
graphics.setFont(mTitleFont);
graphics.drawString(mStrTitle,(mControlDimension.width-graphics.getFontMetrics().stringWidth(mStrTitle))/2,12);
graphics.setColor(mInputColor);
// graphics.fillRect(0,mCellDimension.height,mControlDimension.width,mCellDimension.height);
// graphics.setFont(mTitleFont);
// drawGrid(graphics);
for(i=mStartDisplayRow;i<mRows;i++)
{
for(j=mStartDisplayColumn;j<mColumns;j++)
{
cx=((j-mStartDisplayColumn)*mCellDimension.width)+2+mRowLabelWidth;
cy=((i+1-mStartDisplayRow)*mCellDimension.height)+2+mTitleHeight;
if(mCells[i][j]!=null)mCells[i][j].paint(graphics,cx,cy);
}
}
graphics.setColor(mApplet.getBackground());
graphics.draw3DRect(0,mTitleHeight,mControlDimension.width,mControlDimension.height-mTitleHeight,false);
mInputArea.paint(graphics,1,mTitleHeight+1);
}
// if(!mTransientValue)
// {
//
// if(mValueString.length()>14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
// else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
//
// String printString;
// if(mValueString.length()>14)printString=new String(mValueString.substring(0,14));
// else printString=mValueString;
// FontMetrics metrics=graphics.getFontMetrics();
// int stringWidth=metrics.stringWidth(printString);
// if(x+stringWidth<mSpreadSheet.controlDimension().width)graphics.drawString(printString,x,y+(mHeight/2)+5);
//
// }
// else graphics.drawString(""+mValue,x,y+(mHeight/2)+5);
public void setText(String val)
{
int i;
if(val==null)
{
mStringValue=new String("");
mChars=0;
mBuffer[0]=0;
}
else
{
for(i=0;i<mMaxChars;i++)mBuffer[i]=0;
mStringValue=new String(val);
mStringValue.getChars(0,mStringValue.length(),mBuffer,0);
// mChars=val.length();
// mStringValue=new String(mBuffer);
for(i=0;mBuffer[i]!=0&&i<mMaxChars;i++);
mChars=i;
mStringValue=new String(mBuffer).substring(0,i);
}
}

288
java/SPREAD/SPREAD.MAK Normal file
View File

@@ -0,0 +1,288 @@
# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
# ** DO NOT EDIT **
# TARGTYPE "Java Virtual Machine Java Workspace" 0x0809
!IF "$(CFG)" == ""
CFG=spread - Java Virtual Machine Debug
!MESSAGE No configuration specified. Defaulting to spread - Java Virtual\
Machine Debug.
!ENDIF
!IF "$(CFG)" != "spread - Java Virtual Machine Release" && "$(CFG)" !=\
"spread - Java Virtual Machine Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE on this makefile
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "spread.mak" CFG="spread - Java Virtual Machine Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "spread - Java Virtual Machine Release" (based on\
"Java Virtual Machine Java Workspace")
!MESSAGE "spread - Java Virtual Machine Debug" (based on\
"Java Virtual Machine Java Workspace")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
################################################################################
# Begin Project
# PROP Target_Last_Scanned "spread - Java Virtual Machine Debug"
JAVA=jvc.exe
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ""
# PROP BASE Intermediate_Dir ""
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir ""
# PROP Target_Dir ""
OUTDIR=.
INTDIR=.
ALL : "$(OUTDIR)\Key.class" "$(OUTDIR)\SpreadSheetInput.class"\
"$(OUTDIR)\InputField.class" "$(OUTDIR)\Node.class" "$(OUTDIR)\Cell.class"\
"$(OUTDIR)\SpreadSheet.class" "$(OUTDIR)\SpreadSheetInterface.class"\
"$(OUTDIR)\PurePassThru.class" "$(OUTDIR)\PureCashflow.class"\
"$(OUTDIR)\Money.class" "$(OUTDIR)\Prepayment.class" "$(OUTDIR)\Proto.class"
CLEAN :
-@erase "$(INTDIR)\Cell.class"
-@erase "$(INTDIR)\InputField.class"
-@erase "$(INTDIR)\Key.class"
-@erase "$(INTDIR)\Money.class"
-@erase "$(INTDIR)\Node.class"
-@erase "$(INTDIR)\Prepayment.class"
-@erase "$(INTDIR)\Proto.class"
-@erase "$(INTDIR)\PureCashflow.class"
-@erase "$(INTDIR)\PurePassThru.class"
-@erase "$(INTDIR)\SpreadSheet.class"
-@erase "$(INTDIR)\SpreadSheetInput.class"
-@erase "$(INTDIR)\SpreadSheetInterface.class"
# ADD BASE JAVA /O
# ADD JAVA /O
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ""
# PROP BASE Intermediate_Dir ""
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir ""
# PROP Target_Dir ""
OUTDIR=.
INTDIR=.
ALL : "$(OUTDIR)\Key.class" "$(OUTDIR)\SpreadSheetInput.class"\
"$(OUTDIR)\InputField.class" "$(OUTDIR)\Node.class" "$(OUTDIR)\Cell.class"\
"$(OUTDIR)\SpreadSheet.class" "$(OUTDIR)\SpreadSheetInterface.class"\
"$(OUTDIR)\PurePassThru.class" "$(OUTDIR)\PureCashflow.class"\
"$(OUTDIR)\Money.class" "$(OUTDIR)\Prepayment.class" "$(OUTDIR)\Cashflow.class"
CLEAN :
-@erase "$(INTDIR)\Cashflow.class"
-@erase "$(INTDIR)\Cell.class"
-@erase "$(INTDIR)\InputField.class"
-@erase "$(INTDIR)\Key.class"
-@erase "$(INTDIR)\Money.class"
-@erase "$(INTDIR)\Node.class"
-@erase "$(INTDIR)\Prepayment.class"
-@erase "$(INTDIR)\PureCashflow.class"
-@erase "$(INTDIR)\PurePassThru.class"
-@erase "$(INTDIR)\SpreadSheet.class"
-@erase "$(INTDIR)\SpreadSheetInput.class"
-@erase "$(INTDIR)\SpreadSheetInterface.class"
# ADD BASE JAVA /g
# ADD JAVA /g
!ENDIF
################################################################################
# Begin Target
# Name "spread - Java Virtual Machine Release"
# Name "spread - Java Virtual Machine Debug"
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
!ENDIF
################################################################################
# Begin Source File
SOURCE=.\spread.html
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\SpreadSheetInterface.java
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
"$(INTDIR)\Key.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\SpreadSheetInput.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\InputField.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\Node.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\Cell.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\SpreadSheet.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\SpreadSheetInterface.class" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
"$(INTDIR)\Key.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\SpreadSheetInput.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\InputField.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\Node.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\Cell.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\SpreadSheet.class" : $(SOURCE) "$(INTDIR)"
"$(INTDIR)\SpreadSheetInterface.class" : $(SOURCE) "$(INTDIR)"
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\PurePassThru.java
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
"$(INTDIR)\PurePassThru.class" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
"$(INTDIR)\PurePassThru.class" : $(SOURCE) "$(INTDIR)"
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\PureCashflow.java
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
"$(INTDIR)\PureCashflow.class" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
"$(INTDIR)\PureCashflow.class" : $(SOURCE) "$(INTDIR)"
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\money.java
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
"$(INTDIR)\Money.class" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
"$(INTDIR)\Money.class" : $(SOURCE) "$(INTDIR)"
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\Prepayment.java
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
"$(INTDIR)\Prepayment.class" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
"$(INTDIR)\Prepayment.class" : $(SOURCE) "$(INTDIR)"
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\Cashflow.java
!IF "$(CFG)" == "spread - Java Virtual Machine Release"
"$(INTDIR)\Proto.class" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "spread - Java Virtual Machine Debug"
"$(INTDIR)\Cashflow.class" : $(SOURCE) "$(INTDIR)"
!ENDIF
# End Source File
# End Target
# End Project
################################################################################

BIN
java/SPREAD/SPREAD.MDP Normal file

Binary file not shown.

BIN
java/SPREAD/SPREAD~1.CLA Normal file

Binary file not shown.

21
java/SPREAD/SPREAD~1.HTM Normal file
View File

@@ -0,0 +1,21 @@
<html>
<head>
<title>Paydown Calculator</title>
</head>
<body>
<center>
<font COLOR="#000080" size=+1>Diversified Software Solutions.</font>
</center>
<hr>
<font COLOR="#000080" size=+1>Try the Paydown Calculator JAVA applet.</font>
<font COLOR="#000080" size=0>
<br>Inquiries, comments are welcome. We also provide customization services to meet your special needs. Please send email to
</font>
<A HREF="mailto:europa@li.net">europa@li.net</A>
<hr>
<applet code=Cashflow.class id=SpreadSheet width=640 height=520>
</applet>
<pr>
<hr>
</body>
</html>

930
java/SPREAD/SPREAD~1.SAF Normal file
View File

@@ -0,0 +1,930 @@
/*
* @(#)SpreadSheet.java 1.17 95/03/09 Sami Shaio
*
* Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.net.*;
//******************************************************************************************************
// ***************************************** SPREADSHEET ***********************************************
//******************************************************************************************************
public class SpreadSheet extends Applet
{
private final int mLeftArrow=1006;
private final int mRightArrow=1007;
private final int mUpArrow=1004;
private final int mDownArrow=1005;
private String mStrTitle;
private Font mTitleFont;
private Color mCellColor;
private Color mInputColor;
private int mCellWidth=100;
private int mCellHeight=15;
private int mTitleHeight=15;
private int mRowLabelWidth=15;
private boolean mIsStopped=false;
private boolean mFullUpdate=true;
private int mRows;
private int mColumns;
private int mSelectedRow = -1;
private int mSelectedColumn = -1;
private SpreadSheetInput mInputArea;
private Cell mCells[][];
private Cell mCurrent=null;
public synchronized void init()
{
String strParam;
mCellColor=Color.white;
mInputColor=new Color(100, 100, 225);
mTitleFont=new Font("Courier", Font.BOLD, 12);
mStrTitle=getParameter("title");
if(null==mStrTitle)mStrTitle="SpreadSheet";
strParam=getParameter("rows");
if(null==strParam)mRows=9;
else mRows=Integer.parseInt(strParam);
strParam=getParameter("columns");
if(null==strParam)mColumns=5;
else mColumns=Integer.parseInt(strParam);
mCells=new Cell[mRows][mColumns];
char l[]=new char[1];
for(int i=0; i < mRows; i++)
{
for (int j=0; j < mColumns; j++)
{
mCells[i][j]=new Cell(this,Color.lightGray,Color.black,mCellColor,mCellWidth-2,mCellHeight-2);
l[0]=(char)((int)'a'+j);
strParam=getParameter(""+new String(l)+(i+1));
if(null!=strParam)mCells[i][j].setUnparsedValue(strParam);
}
}
Dimension workArea=size();
mInputArea=new SpreadSheetInput(null, this,workArea.width-2,mCellHeight-1,mInputColor,Color.white);
resize(mColumns*mCellWidth+mRowLabelWidth,((mRows+1)*mCellHeight)+mCellHeight+mTitleHeight);
}
public void setCurrentValue(float val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(val);
repaint();
}
public void stop()
{
stopped(true);
}
public void start()
{
stopped(false);
}
public void stopped(boolean stopped)
{
mIsStopped=stopped;
}
public boolean stopped()
{
return mIsStopped;
}
public void destroy()
{
for(int i=0;i<mRows;i++)for(int j=0;j<mColumns;j++)if(mCells[i][j].type()==Cell.URL)mCells[i][j].cellThread().stop();
}
public void setCurrentValue(int type,String val)
{
if(-1==mSelectedRow||-1==mSelectedColumn)return;
mCells[mSelectedRow][mSelectedColumn].setValue(type,val);
repaint();
}
public void update(Graphics graphics)
{
if(!mFullUpdate)
{
int cx;
int cy;
graphics.setFont(mTitleFont);
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row][col].needRedisplay())
{
cx=(col*mCellWidth)+2+mRowLabelWidth;
cy=((row+1)*mCellHeight)+2+mTitleHeight;
mCells[row][col].paint(graphics,cx,cy);
}
}
}
}
else
{
paint(graphics);
mFullUpdate = false;
}
}
public synchronized void paint(Graphics graphics)
{
int i;
int j;
int cx;
int cy;
char strLabel[]=new char[1];
Dimension clientRect=size();
graphics.setFont(mTitleFont);
graphics.drawString(mStrTitle,(clientRect.width-graphics.getFontMetrics().stringWidth(mStrTitle))/2,12);
graphics.setColor(mInputColor);
graphics.fillRect(0,mCellHeight,clientRect.width,mCellHeight);
graphics.setFont(mTitleFont);
for(i=0;i<mRows+1;i++)
{
cy=(i+2)*mCellHeight;
graphics.setColor(getBackground());
graphics.draw3DRect(0,cy,clientRect.width,2,true);
if(i<mRows)
{
graphics.setColor(Color.red);
graphics.drawString(""+(i+1),2,cy+12);
}
}
graphics.setColor(Color.red);
for(i=0;i<mColumns;i++)
{
cx=i*mCellWidth;
graphics.setColor(getBackground());
graphics.draw3DRect(cx+mRowLabelWidth,2*mCellHeight,1,clientRect.height,true);
// if(i<mColumns)
// {
// graphics.setColor(Color.red);
// strLabel[0]=(char)((int)'A'+i);
// l[0]=(char)((int)'A'+i);
// graphics.drawString(new String(strLabel),cx+mRowLabelWidth+(mCellWidth/2),clientRect.height-3);
// }
}
for(i=0;i<mRows;i++)
{
for(j=0;j<mColumns;j++)
{
cx=(j*mCellWidth)+2+mRowLabelWidth;
cy=((i+1)*mCellHeight)+2+mTitleHeight;
if(mCells[i][j]!=null)mCells[i][j].paint(graphics,cx,cy);
}
}
graphics.setColor(getBackground());
graphics.draw3DRect(0,mTitleHeight,clientRect.width,clientRect.height-mTitleHeight,false);
mInputArea.paint(graphics,1,mTitleHeight+1);
}
public void recalculate()
{
for(int row=0;row<mRows;row++)
{
for(int col=0;col<mColumns;col++)
{
if(mCells[row][col]!=null&&mCells[row][col].type()==Cell.FORMULA)
{
mCells[row][col].setRawValue(evaluateFormula(mCells[row][col].parseRoot()));
mCells[row][col].needRedisplay(true);
}
}
}
repaint();
}
private float evaluateFormula(Node node)
{
float val=0.0f;
if(null==node)return val;
switch(node.type())
{
case Node.OP:
val=evaluateFormula(node.left());
switch(node.op())
{
case '+':
val += evaluateFormula(node.right());
break;
case '*':
val *= evaluateFormula(node.right());
break;
case '-':
val -= evaluateFormula(node.right());
break;
case '/':
val /= evaluateFormula(node.right());
break;
}
break;
case Node.VALUE:
val=node.value();
break;
case Node.CELL:
if(null==node)break;
if(null==mCells[node.row()][node.column()])break;
val=mCells[node.row()][node.column()].value();
break;
}
return val;
}
public boolean mouseDown(Event evt, int x, int y)
{
Cell cell;
if(y<(mTitleHeight+mCellHeight))
{
mSelectedRow=-1;
if(y<=mTitleHeight)deselect(true);
return true;
}
if(x<mRowLabelWidth)
{
mSelectedRow=-1;
deselect(true);
return true;
}
mSelectedRow=((y-mCellHeight-mTitleHeight)/mCellHeight);
mSelectedColumn=(x-mRowLabelWidth)/mCellWidth;
if(mSelectedRow>mRows||mSelectedColumn>=mColumns)
{
mSelectedRow = -1;
deselect(true);
}
else
{
if(mSelectedRow>=mRows)
{
mSelectedRow = -1;
deselect(true);
return true;
}
select();
}
return true;
}
public boolean keyDown(Event evt, int key)
{
mFullUpdate=true;
if(mLeftArrow==key||mRightArrow==key||mUpArrow==key||mDownArrow==key)navigate(key);
else mInputArea.keyDown(key);
return true;
}
private void navigate(int key)
{
switch(key)
{
case mLeftArrow :
if(mSelectedColumn<=0)break;
mSelectedColumn--;
select();
break;
case mRightArrow :
if(mSelectedColumn>=mColumns)break;
mSelectedColumn++;
select();
break;
case mUpArrow :
if(mSelectedRow<=0)break;
mSelectedRow--;
select();
break;
case mDownArrow :
if(mSelectedRow>=mRows)break;
mSelectedRow++;
select();
break;
}
}
private void select()
{
Cell cell;
cell=mCells[mSelectedRow][mSelectedColumn];
if(null!=cell.getPrintString())mInputArea.setText(new String(cell.getPrintString()));
else mInputArea.setText(new String(""));
if(mCurrent!=null)mCurrent.deselect();
mCurrent=cell;
mCurrent.select();
requestFocus();
mFullUpdate=true;
repaint();
}
private void deselect(boolean destroy)
{
if(null==mCurrent)return;
mCurrent.deselect();
if(destroy)mCurrent=null;
}
}
// ******
class ScrollManager
{
private int mFirstVisibleCell;
public ScrollManager()
{
mFirstVisibleCell=0;
}
public int firstVisibleCell()
{
return mFirstVisibleCell;
}
public void firstVisibleCell(int firstVisibleCell)
{
mFirstVisibleCell=firstVisibleCell;
}
}
//******************************************************************************************************
// ***************************************** CELLTHREAD ***********************************************
//******************************************************************************************************
class CellThread extends Thread
{
private Cell mTarget;
private InputStream mDataStream=null;
private StreamTokenizer mTokenStream;
public CellThread(Cell cell)
{
super("CellThread");
mTarget=cell;
}
public void run()
{
try
{
mDataStream = new URL(mTarget.spreadSheet().getDocumentBase(),mTarget.getValueString()).openStream();
mTokenStream = new StreamTokenizer(mDataStream);
mTokenStream.eolIsSignificant(false);
while(true)
{
switch(mTokenStream.nextToken())
{
case mTokenStream.TT_EOF:
mDataStream.close();
return;
default:
break;
case mTokenStream.TT_NUMBER:
mTarget.setTransientValue((float)mTokenStream.nval);
if(!mTarget.spreadSheet().stopped()&&!mTarget.paused())mTarget.spreadSheet().repaint();
break;
}
try {Thread.sleep(2000);}
catch(InterruptedException exception){break;}
}
}
catch (IOException exception){return;}
}
}
//******************************************************************************************************
// ******************************************** CELL ***************************************************
//******************************************************************************************************
class Cell
{
public static final int VALUE = 0;
public static final int LABEL = 1;
public static final int URL = 2;
public static final int FORMULA = 3;
private Node mParseRoot;
private boolean mNeedRedisplay;
private boolean mSelected = false;
private boolean mTransientValue = false;
private int mType=Cell.VALUE;
private String mValueString = "";
private String mPrintString = "v";
private float mValue;
private Color mBgColor;
private Color mFgColor;
private Color mHighlightColor;
private int mWidth;
private int mHeight;
private SpreadSheet mSpreadSheet;
private CellThread mCellThread;
private boolean mPaused=false;
public Cell(SpreadSheet spreadSheet,Color bgColor,Color fgColor,Color highlightColor,int width,int height)
{
mSpreadSheet=spreadSheet;
mBgColor=bgColor;
mFgColor=fgColor;
mHighlightColor=highlightColor;
mWidth=width;
mHeight=height;
mNeedRedisplay=true;
}
public void setRawValue(float value)
{
mValueString=Float.toString(value);
mValue=value;
}
public void setValue(float value)
{
setRawValue(value);
mPrintString="v"+mValueString;
mType=Cell.VALUE;
mPaused=false;
mSpreadSheet.recalculate();
mNeedRedisplay=true;
}
public void setTransientValue(float value)
{
mTransientValue=true;
mValue=value;
mNeedRedisplay=true;
mSpreadSheet.recalculate();
}
public void setUnparsedValue(String s)
{
switch (s.charAt(0))
{
case 'v':
setValue(Cell.VALUE, s.substring(1));
break;
case 'f':
setValue(Cell.FORMULA, s.substring(1));
break;
case 'l':
setValue(Cell.LABEL, s.substring(1));
break;
case 'u':
setValue(Cell.URL, s.substring(1));
break;
}
}
public String parseFormula(String formula, Node node)
{
String subformula;
String restFormula;
float value;
int length = formula.length();
Node left;
Node right;
char op;
if(null==formula)return null;
subformula=parseValue(formula, node);
if(null==subformula||0==subformula.length())return null;
if(subformula==formula)return formula;
switch(op=subformula.charAt(0))
{
case 0:
return null;
case ')':
return subformula;
case '+':
case '*':
case '-':
case '/':
restFormula = subformula.substring(1);
subformula = parseValue(restFormula, right=new Node());
if(subformula != restFormula)
{
left = new Node(node);
node.left(left);
node.right(right);
node.op(op);
node.type(Node.OP);
return subformula;
}
else return formula;
default:
return formula;
}
}
public String parseValue(String formula, Node node)
{
char c=formula.charAt(0);
String subformula;
String restFormula;
float value;
int row;
int column;
restFormula = formula;
if (c == '(')
{
restFormula = formula.substring(1);
subformula = parseFormula(restFormula, node);
if(subformula == null || subformula.length() == restFormula.length())return formula;
else if (! (subformula.charAt(0) == ')'))return formula;
restFormula = subformula;
}
else if (c >= '0' && c <= '9')
{
int i;
try{value = Float.valueOf(formula).floatValue();}
catch (NumberFormatException exception){return formula;}
for (i=0; i < formula.length(); i++)
{
c = formula.charAt(i);
if ((c < '0' || c > '9') && c != '.')break;
}
node.type(Node.VALUE);
node.value(value);
restFormula = formula.substring(i);
return restFormula;
}
else if (c >= 'A' && c <= 'Z')
{
int i;
column = c - 'A';
restFormula = formula.substring(1);
row = Float.valueOf(restFormula).intValue();
for(i=0; i < restFormula.length(); i++)
{
c = restFormula.charAt(i);
if (c < '0' || c > '9')break;
}
node.row(row-1);
node.column(column);
node.type(Node.CELL);
if (i == restFormula.length())restFormula=null;
else
{
restFormula = restFormula.substring(i);
if (restFormula.charAt(0) == 0)return null;
}
}
return restFormula;
}
public void setValue(int type, String s)
{
mPaused=false;
if(mType == Cell.URL)
{
mCellThread.stop();
mCellThread=null;
}
mValueString=new String(s);
mType=type;
mNeedRedisplay=true;
switch(mType)
{
case Cell.VALUE:
setValue(Float.valueOf(s).floatValue());
break;
case Cell.LABEL:
mPrintString = "l" + mValueString;
break;
case Cell.URL:
mPrintString = "u" + mValueString;
mCellThread = new CellThread(this);
mCellThread.start();
break;
case Cell.FORMULA:
parseFormula(mValueString,mParseRoot=new Node());
mPrintString = "f" + mValueString;
break;
}
mSpreadSheet.recalculate();
}
public String getValueString()
{
return mValueString;
}
public String getPrintString()
{
return mPrintString;
}
public void select()
{
mSelected = true;
mPaused=true;
}
public void deselect()
{
mSelected = false;
mPaused=false;
mNeedRedisplay = true;
mSpreadSheet.repaint();
}
public void paint(Graphics graphics,int x,int y)
{
if(mSelected)graphics.setColor(mHighlightColor);
else graphics.setColor(mBgColor);
graphics.fillRect(x+1,y+1,mWidth-2,mHeight-2);
if(null!=mValueString)
{
switch(mType)
{
case Cell.VALUE:
case Cell.LABEL:
graphics.setColor(mFgColor);
break;
case Cell.FORMULA:
graphics.setColor(Color.red);
break;
case Cell.URL:
graphics.setColor(Color.blue);
break;
}
if(!mTransientValue)
{
if(mValueString.length()>14)graphics.drawString(mValueString.substring(0,14),x,y+(mHeight/2)+5);
else graphics.drawString(mValueString,x,y+(mHeight/2)+5);
}
else graphics.drawString(""+mValue,x,y+(mHeight/2)+5);
mNeedRedisplay=false;
}
}
public int type()
{
return mType;
}
public Node parseRoot()
{
return mParseRoot;
}
public void needRedisplay(boolean needRedisplay)
{
mNeedRedisplay=needRedisplay;
}
public boolean needRedisplay()
{
return mNeedRedisplay;
}
public float value()
{
return mValue;
}
public CellThread cellThread()
{
return mCellThread;
}
public SpreadSheet spreadSheet()
{
return mSpreadSheet;
}
public boolean paused()
{
return mPaused;
}
}
//******************************************************************************************************
// *************************************** NODE *******************************************************
//******************************************************************************************************
class Node
{
public static final int OP = 0;
public static final int VALUE = 1;
public static final int CELL = 2;
private int mType;
private Node mLeft;
private Node mRight;
private int mRow;
private int mColumn;
private float mValue;
private char mOp;
public Node()
{
mLeft=null;
mRight=null;
mValue=0;
mRow=-1;
mColumn=-1;
mOp=0;
mType=Node.VALUE;
}
public Node(Node node)
{
mLeft=node.mLeft;
mRight=node.mRight;
mValue=node.mValue;
mRow=node.mRow;
mColumn=node.mColumn;
mOp=node.mOp;
mType=node.mType;
}
public void print(int indentLevel)
{
char l[] = new char[1];
switch(mType)
{
case Node.VALUE:
break;
case Node.CELL:
l[0] = (char)((int)'A' + column());
break;
case Node.OP:
mLeft.print(indentLevel + 3);
mRight.print(indentLevel + 3);
break;
}
}
public int type()
{
return mType;
}
public void type(int type)
{
mType=type;
}
public float value()
{
return mValue;
}
public void value(float value)
{
mValue=value;
}
public Node left()
{
return mLeft;
}
public void left(Node left)
{
mLeft=left;
}
public Node right()
{
return mRight;
}
public void right(Node right)
{
mRight=right;
}
public char op()
{
return mOp;
}
public void op(char op)
{
mOp=op;
}
public int row()
{
return mRow;
}
public void row(int row)
{
mRow=row;
}
public int column()
{
return mColumn;
}
public void column(int column)
{
mColumn=column;
}
}
class InputField
{
private int mMaxchars = 50;
private Applet mApplet;
private String mStringValue;
private char mBuffer[];
private int mChars;
private int mWidth;
private int mHeight;
private Color mBgColor;
private Color mFgColor;
public InputField(String initValue,Applet applet, int width, int height,Color bgColor, Color fgColor)
{
mWidth=width;
mHeight=height;
mBgColor=bgColor;
mFgColor=fgColor;
mApplet=applet;
mBuffer = new char[mMaxchars];
mChars = 0;
if(initValue != null)
{
initValue.getChars(0, initValue.length(),mBuffer, 0);
mChars = initValue.length();
}
mStringValue=initValue;
}
public void setText(String val)
{
int i;
for(i=0; i < mMaxchars; i++)mBuffer[i] = 0;
mStringValue=new String(val);
if (val == null)
{
mStringValue= "";
mChars = 0;
mBuffer[0] = 0;
}
else
{
mStringValue.getChars(0,mStringValue.length(), mBuffer, 0);
mChars = val.length();
mStringValue = new String(mBuffer);
}
}
public String getValue()
{
return mStringValue;
}
public void paint(Graphics g, int x, int y)
{
g.setColor(mBgColor);
g.fillRect(x, y,mWidth,mHeight);
if (mStringValue!= null)
{
g.setColor(mFgColor);
g.drawString(mStringValue, x, y + (mHeight / 2) + 3);
}
}
public void mouseUp(int x, int y)
{
}
public void keyDown(int key)
{
if(mChars<mMaxchars)
{
switch(key)
{
case 8: // delete
--mChars;
if(mChars<0)mChars=0;
mBuffer[mChars] = 0;
mStringValue = new String(new String(mBuffer));
break;
case 10: // return
selected();
break;
default:
mBuffer[mChars++] = (char)key;
mStringValue = new String(new String(mBuffer));
break;
}
}
mApplet.repaint();
}
public void selected()
{
}
public Applet applet()
{
return mApplet;
}
}
class SpreadSheetInput extends InputField
{
public SpreadSheetInput(String initValue,SpreadSheet app,int width,int height,Color bgColor,Color fgColor)
{
super(initValue,app,width,height,bgColor,fgColor);
}
public void selected()
{
float f;
switch(getValue().charAt(0))
{
case 'v':
try{f=Float.valueOf(getValue().substring(1)).floatValue();((SpreadSheet)applet()).setCurrentValue(f);}
catch(NumberFormatException exception){;}
break;
case 'l':
((SpreadSheet)applet()).setCurrentValue(Cell.LABEL,getValue().substring(1));
break;
case 'u':
((SpreadSheet)applet()).setCurrentValue(Cell.URL,getValue().substring(1));
break;
case 'f':
((SpreadSheet)applet()).setCurrentValue(Cell.FORMULA,getValue().substring(1));
break;
}
}
}

BIN
java/SPREAD/SPREAD~2.CLA Normal file

Binary file not shown.

BIN
java/SPREAD/SPREAD~3.CLA Normal file

Binary file not shown.

1007
java/SPREAD/SPREAD~7.JAV Normal file

File diff suppressed because it is too large Load Diff