home *** CD-ROM | disk | FTP | other *** search
- /*
- * A simple spread_sheet using sub_arctic.
- * I took out all of the business with URLs & threads because I couldn't
- * figure out what that was trying to do. All of the parsing and calculating
- * code is identical to the original.
- * 9/24/96 Colleen Kehoe
- *
- * Based on:
- * @(#)SpreadSheet.java 1.17 95/03/09 Sami Shaio
- * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
- *
- */
-
- package sub_arctic.demo_apps;
-
- import java.awt.*;
- import java.io.*;
- import java.lang.*;
- import java.net.*;
-
- import sub_arctic.lib.*;
- import sub_arctic.output.*;
- import sub_arctic.input.*;
- import sub_arctic.constraints.std_function;
-
- public class spread_sheet extends interactor_applet {
- String title;
- Font titleFont;
- int cellWidth = 100;
- Font inputFont;
- int rows;
- int columns;
- SpreadSheetInput inputArea;
- Cell cells[][];
- Cell current = null;
- grid ss_grid;
- boolean isStopped = false;
- label titleLabel;
-
- public void build_ui(base_parent_interactor top) {
- String rs;
-
- 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);
- }
-
- // set up title
- titleLabel = new label(title,titleFont);
- titleLabel.set_x_constraint(std_function.eq(PARENT.X1()));
- titleLabel.set_y_constraint(std_function.eq(PARENT.Y1()));
- top.add_child(titleLabel);
-
- // inputArea is the bar you type into at the top
- inputArea = new SpreadSheetInput(null,this);
- inputArea.set_w_constraint(std_function.eq(PARENT.X2()));
- inputArea.set_y_constraint(std_function.eq(PREV_SIBLING.Y2()));
- top.add_child(inputArea);
-
- // set up labels--use the 0th row & column to store them
- ss_grid = new grid(rows+1,columns+1);
- char l[] = new char[1];
- ss_grid.set_element_at(0,0,new label(""));
- for (int i=1; i<=rows; i++) {
- ss_grid.set_element_at(i,0,new label(String.valueOf(i)));
- }
- for (int j=1; j<=columns; j++) {
- l[0] = (char)((int)'A' + j-1);
- String s = new String(l);
- // cheezy, I know
- ss_grid.set_element_at(0,j,
- new label(" "+s,cellWidth-2));
- }
-
- // create all cells first
- for (int i=1; i <= rows; i++) {
- for (int j=1; j <= columns; j++) {
- ss_grid.set_element_at(i,j, new Cell(this,
- Color.yellow,
- Color.black,
- cellWidth - 2));
- }
- }
-
- // initialize cells with applet parameters
- for (int i=1; i <= rows; i++) {
- for (int j=1; j <= columns; j++) {
- l[0] = (char)((int)'a' + j-1);
- rs = getParameter("" + new String(l) + i);
- if (rs != null) {
- ((Cell)ss_grid.element_at(i,j)).setUnparsedValue(rs);
- }
- }
- }
-
- ss_grid.set_y_constraint(std_function.eq(PREV_SIBLING.Y2()));
- top.add_child(ss_grid);
-
-
- }
-
- public void setCurrentValue(float val) {
- current.setValue(val);
- }
-
- public void stop() {
- isStopped = true;
- }
-
- public void start() {
- isStopped = false;
- }
-
- public void destroy() {
- }
-
-
- public void setCurrentCell(Cell c) {
- unsetCurrentCell();
- current = c;
- current.select();
- // display the value of the current cell in the inputArea
- inputArea.set_text(new String(c.getPrintString()));
- // set the selection point so it is not beyond the end of the text
- inputArea.set_selection(oneline_text_display.SELECT_END,
- oneline_text_display.SELECT_END);
- }
-
- public void unsetCurrentCell() {
- if (current != null) {
- current.deselect();
- current = null;
- }
- }
-
- public void setCurrentValue(int type, String val) {
- current.setValue(type,val);
- }
-
- public void recalculate() {
- int i,j;
-
- for (i=1; i <= rows; i++) {
- for (j=1; j <= columns; j++) {
- if (((Cell)ss_grid.element_at(i,j)) != null && ((Cell)ss_grid.element_at(i,j)).type == Cell.FORMULA) {
- ((Cell)ss_grid.element_at(i,j)).setRawValue(evaluateFormula(((Cell)ss_grid.element_at(i,j)).parseRoot));
- }
- }
- }
- }
-
- public float evaluateFormula(Node n) {
- float val = 0.0f;
-
- if (n == null) {
- 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:
- return n.value;
- case Node.CELL:
- if (n == null) {
- } else {
- if (ss_grid.element_at(n.row+1,n.column+1) == null) {
- } else {
- return ((Cell)ss_grid.element_at(n.row+1,n.column+1)).value;
- }
- }
- }
-
- return val;
- }
-
-
- }
-
-
- class Cell extends oneline_text_display implements pressable {
- 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 selected = false;
- boolean transientValue = false;
- public int type = Cell.VALUE;
- String valueString = "";
- String printString = "v";
- float value;
- spread_sheet app;
- // the color to use when this cell is selected
- color_pair selected_cp;
-
-
- public Cell(spread_sheet app,
- Color bgColor,
- Color fgColor,
- int width) {
- super(0,0,width,null,null,false);
- this.app = app;
- selected_cp = new color_pair(fgColor,bgColor);
- }
-
- public void setRawValue(float f) {
- valueString = Float.toString(f);
- value = f;
- set_text(valueString);
- }
- public void setValue(float f) {
- setRawValue(f);
- set_text(valueString);
- printString = "v" + valueString;
- type = Cell.VALUE;
- app.recalculate();
- }
-
- public void setTransientValue(float f) {
- transientValue = true;
- value = f;
- 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;
- }
- }
-
- /**
- * 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);
- if (subformula == null || subformula.length() == 0) {
- return null;
- }
- if (subformula == formula) {
- return formula;
- }
-
- // parse an operator and then another value
- 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 e) {
- 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) {
- valueString = new String(s);
- this.type = type;
- switch (type) {
- case Cell.VALUE:
- setValue(Float.valueOf(s).floatValue());
- break;
- case Cell.LABEL:
- set_text(valueString);
- printString = "l" + valueString;
- break;
- case Cell.FORMULA:
- parseFormula(valueString, parseRoot = new Node());
- printString = "f" + valueString;
- set_text(valueString);
- break;
- }
- app.recalculate();
- }
-
- public String getValueString() {
- return valueString;
- }
-
- public String getPrintString() {
- return printString;
- }
-
- public void select() {
- selected = true;
- set_colors(selected_cp);
- }
- public void deselect() {
- selected = false;
- set_colors(null);
- }
-
- public boolean press(event evt,
- Object user_info) {
- return true;
- }
-
- public boolean release(event evt,
- Object user_info) {
- // selection only takes effect on release, so that the
- // user can back out if they want to
- app.setCurrentCell(this);
- return true;
- }
-
-
-
- }
-
- 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 SpreadSheetInput extends oneline_text_edit {
-
- spread_sheet app;
-
- public SpreadSheetInput(String initValue,
- spread_sheet app) {
- super(initValue);
- this.app = app;
- }
-
-
- // this means to consider the "eol" (i.e. return) character to be a
- // special action character
- public int char_filter(int input_char, int modifiers) {
- return text_focus_agent.eol_action(input_char);
- }
-
- // when we get the action character (i.e. return) we update the value of
- // the current cell with what was typed in
- public boolean action_char(event evt, char ch, Object user_info) {
- float f;
-
- switch (text().charAt(0)) {
- case 'v':
- try {
- f = Float.valueOf(text().substring(1)).floatValue();
- ((spread_sheet)app).setCurrentValue(f);
- } catch (NumberFormatException e) {
- System.out.println("Not a float...");
- }
- break;
- case 'l':
- ((spread_sheet)app).setCurrentValue(Cell.LABEL, text().substring(1));
- break;
- case 'f':
- ((spread_sheet)app).setCurrentValue(Cell.FORMULA, text().substring(1));
- break;
- }
- return true;
- }
- }
-
-
-
-
-
-
-
- /*=========================== COPYRIGHT NOTICE ===========================
-
- This file is part of the subArctic user interface toolkit.
-
- Copyright (c) 1996 Scott Hudson and Ian Smith
- All rights reserved.
-
- The subArctic system is freely available for most uses under the terms
- and conditions described in
- http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html
- and appearing in full in the lib/interactor.java source file.
-
- The current release and additional information about this software can be
- found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
-
- ========================================================================*/
-