spreadsheet.java

来自「《移动Agent技术》一书的所有章节源代码。」· Java 代码 · 共 925 行 · 第 1/2 页

JAVA
925
字号
/*
 * @(#)SpreadSheet.java	1.6 97/07/30
 *
 * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 */

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.*;
import java.net.*;

public class SpreadSheet 
    extends Applet
    implements MouseListener, KeyListener {
    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 = getSize();
	inputArea = new SpreadSheetInput(null, this, d.width - 2, cellHeight - 1,
					 inputColor, Color.white);
	resize(columns * cellWidth + rowLabelWidth,
	       (rows + 3) * cellHeight + titleHeight);
	addMouseListener(this);
	addKeyListener(this);
    }

    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 = getSize();

	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);
	cy = (rows+3) * cellHeight + (cellHeight / 2);
	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),
			     cy);
	    }
	}

	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);
    }

      //1.1 event handling
      
  public void mouseClicked(MouseEvent e)
  {}
      
  public void mousePressed(MouseEvent e)
  {
    int x = e.getX();
    int y = e.getY();
    Cell cell;
    if (y < (titleHeight + cellHeight)) {
      selectedRow = -1;
      if (y <= titleHeight && current != null) {
	current.deselect();
	current = null;
      }
      e.consume();
    }
    if (x < rowLabelWidth) {
      selectedRow = -1;
      if (current != null) {
	current.deselect();
		current = null;
      }
      e.consume();
      
    }
    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;
	}
	e.consume();
      }
      cell = cells[selectedRow][selectedColumn];
      inputArea.setText(new String(cell.getPrintString()));
      if (current != null) {
	current.deselect();
      }
      current = cell;
      current.select();
      requestFocus();
      fullUpdate = true;
      repaint();
    }
    e.consume();
  }

  public void mouseReleased(MouseEvent e) 
  {}
      
  public void mouseEntered(MouseEvent e)
  {}
      
  public void mouseExited(MouseEvent e) 	
  {}

  public void keyPressed(KeyEvent e)
  {
    fullUpdate=true;
    inputArea.processKey(e);
    e.consume();
  }
  
  public void keyTyped(KeyEvent e) {
  }
  
  public void keyReleased(KeyEvent e)
  {}   
      
  public String getAppletInfo() {
    return "Title: SpreadSheet \nAuthor: Sami Shaio \nA simple spread sheet.";
  }
      
  public String[][] getParameterInfo() {
    String[][] info = {
      {"title", "string", "The title of the spread sheet.  Default is 'Spreadsheet'"},
      {"rows", "int", "The number of rows.  Default is 9."},
      {"columns", "int", "The number of columns.  Default is 5."}
    };
    return info;
  }


}

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(new BufferedReader(new InputStreamReader(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;
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?