View Javadoc
1 /* 2 * GeoVISTA Center (Penn State, Dept. of Geography) 3 * Copyright (c), 1999 - 2002, GeoVISTA Center 4 * All Rights Researved. 5 * 6 * Description: 7 * This is a wrapper class for all objects in the table. 8 * A cell has a value which is either text or a number. 9 * 10 * Date: Apr 2, 2003 11 * Time: 10:42:12 PM 12 * @author Jin Chen 13 */ 14 15 package edu.psu.geovista.app.spreadsheet.formula; 16 17 18 import edu.psu.geovista.app.spreadsheet.util.Debug; 19 20 import javax.swing.table.TableModel; 21 import javax.swing.table.DefaultTableModel; 22 import javax.swing.table.TableColumnModel; 23 import javax.swing.table.TableColumn; 24 import javax.swing.*; 25 import java.util.*; 26 import java.awt.*; 27 28 import edu.psu.geovista.app.spreadsheet.exception.ParserException; 29 import edu.psu.geovista.app.spreadsheet.exception.NoReferenceException; 30 import edu.psu.geovista.app.spreadsheet.table.SSTableModel; 31 import edu.psu.geovista.app.spreadsheet.SpreadSheetBean; 32 import edu.psu.geovista.app.spreadsheet.table.SSTable; 33 34 35 36 public class Cell { 37 38 /*** Value Type ***/ 39 public static final int NULL = 0; 40 41 /*** The integer code that denotes the cell holds text. */ 42 public static final int TEXT = 1; 43 44 /*** The integer code that denotes the cell holds numbers. */ 45 public static final int NUMBER = 2; 46 47 /*** The integer code that denotes the cell holds a edu.psu.geovista.app.spreadsheet.formula. */ 48 // public static final int FORMULA = 2; 49 50 public static final int UNKNOWN = 3; 51 52 private int valueType=0; 53 54 /*** Value of the cell. In a edu.psu.geovista.app.spreadsheet.formula, value holds the evaluated value. */ 55 private Object value; 56 57 /*** 58 * This expression contains the string and internal representation 59 * of the edu.psu.geovista.app.spreadsheet.formula if it exists. 60 */ 61 private Formula expression; 62 63 /*** 64 * The list of cells that reference this cell. When a cell is changes, 65 * all cells on this list should notified. 66 */ 67 private TreeSet refs; 68 69 //Jin 70 private boolean isformula=false;// 71 private boolean deleted=false;//if the cell has been deleted 72 private SSTableModel dataModel; 73 private Vector container;// the row vector that contain the cell object 74 75 76 /*** 77 * This constructor constructs a cell that will not have cells 78 * referencing it and are not formulas. Basically only used for creating 79 * the row and column labels. 80 * <P> 81 * <b>Warning:</b> Do not use this with Formulas 82 * @param datum the value of the "label" cell (not a edu.psu.geovista.app.spreadsheet.formula.Formula) 83 */ 84 public Cell(Vector _container,SSTableModel tm) { 85 this.container =_container; 86 this.dataModel=tm; 87 expression = null; 88 refs = null; 89 } 90 /*** 91 * protect against loop reference 92 */ 93 public boolean addOwner(Cell cell) { 94 Debug.println("this address:"+this.getViewAddress() ); 95 Debug.println("cell address:"+cell.getViewAddress() ); 96 return this.getFormula().addOwner(cell); 97 } 98 99 public void evaluate(){ 100 if (this.isFormula() ){ 101 102 Object value=null; 103 try { 104 Formula form=this.getFormula() ; 105 if (form.isBad() ){ //invalid edu.psu.geovista.app.spreadsheet.formula 106 this.setValue("#NAME?"); 107 } 108 else{ 109 //SSTableModel.getInstance().get 110 111 //Debug.println(" A1:"+SpreadSheetBean4.getTableInstance().getValueAtIndex(1,1)); 112 value = form.evaluate(); 113 /*Debug.println("edu.psu.geovista.app.spreadsheet.formula.Cell.evaluate():"+value); 114 Debug.println("Cell.getViewAddress()"+this.getViewAddress() ); 115 Thread.dumpStack() ; */ 116 this.setValue(value); 117 } 118 } catch (ParserException e) { 119 120 this.setValue(e.toString() ); 121 //SpreadSheetBean.getTableInstance().revaluate() ;//remove the loop dialog box 122 this.getDataModel().getTable().revaluate() ; 123 //e.printStackTrace() ; 124 } catch(NoReferenceException e){ 125 //e.printStackTrace() ;//only for debug 126 this.setValue("#REF!"); 127 } 128 129 } //if 130 } 131 132 /*** 133 * This method returns the edu.psu.geovista.app.spreadsheet.formula associated with the cell or null if it 134 * does not exist. 135 * 136 * @return the edu.psu.geovista.app.spreadsheet.formula (string and internal object) or null if does not 137 * exist 138 */ 139 public Formula getFormula() { 140 if (this.deleted ) return null; 141 else return expression; 142 } 143 public void setFormula(Formula form) { 144 expression = form; 145 //this.setAsFormula(true); 146 147 } 148 149 150 151 152 153 154 155 /*** 156 * If it is a data cell, it returns the data of the cell. If it is a 157 * edu.psu.geovista.app.spreadsheet.formula, it returns the previously evaluated value of the edu.psu.geovista.app.spreadsheet.formula. 158 * 159 * @return the value (data or evaluated) of the cell 160 */ 161 public Object getValue() { 162 //Debug.println("Cell.getValue:"+value+" at"+this.getViewAddress() ); 163 /*if (this.isFormula() ){ 164 this.evaluate() ; 165 } */ 166 167 if (this.isDeleted() ) { 168 return "#REF!"; 169 } 170 else return value; 171 } 172 173 174 /*** 175 * Sets the value field of the cell. 176 * 177 * @param datum the object to set the value of cell to 178 */ 179 public void setValue(Object datum) { 180 /*Point p=this.getViewAddress() ; 181 if (p.getX() ==1&&p.getY() ==0){ 182 Debug.println("view(1,0)="+this.getValue() ); 183 } */ 184 185 if (datum==null){ 186 this.setValueType(Cell.NULL ); 187 } 188 else if(datum!=null){ 189 if (datum instanceof String ){ 190 String s=(String)datum; 191 this.setValueType(Cell.TEXT); 192 if (s.trim().equals("")){ 193 datum=null; 194 this.setValueType(Cell.NULL ); 195 } 196 } 197 else if (datum instanceof Number){ 198 this.setValueType(Cell.NUMBER ); 199 } 200 else{ 201 this.setValueType(Cell.UNKNOWN ); 202 } 203 } 204 205 value = datum; 206 //this.setAsFormula(false); 207 208 } 209 210 211 212 /*** 213 * This method sets the cell to be a edu.psu.geovista.app.spreadsheet.formula cell. It puts the edu.psu.geovista.app.spreadsheet.formula 214 * object into the expression field. The Table of Cells is responsible 215 * for recalculating and setting the appropriate value in the value 216 * field of this cell. 217 * 218 * @param form the internal representation of edu.psu.geovista.app.spreadsheet.formula to set this cell to 219 */ 220 public void setAsFormula(boolean isf) { 221 222 this.isformula =isf; 223 } 224 225 226 227 /*** 228 * This method is useful for determining what information a cell holds. To 229 * check if a cell holds a certain type just see if 230 * getType() == edu.psu.geovista.app.spreadsheet.formula.Cell.CODE where CODE is any of the cell constants. 231 * 232 * @return the integer code of the type of data this cell holds 233 */ 234 public int getValueType() { 235 if (value==null) valueType= Cell.NULL ; 236 ///if (expression != null) return edu.psu.geovista.app.spreadsheet.formula.Cell.FORMULA; //jin: no use 237 else if (value instanceof Number) valueType= Cell.NUMBER; 238 else if(value instanceof String)valueType= Cell.TEXT; 239 else valueType= Cell.UNKNOWN ; 240 241 return valueType; 242 } 243 244 public void setValueType(int t){ 245 this.valueType =t; 246 } 247 248 /*** 249 * This method returns true IFF it is a edu.psu.geovista.app.spreadsheet.formula cell 250 * 251 * @return true iff a edu.psu.geovista.app.spreadsheet.formula cell 252 */ 253 public boolean isFormula() { 254 return this.isformula ; 255 } 256 257 /*** 258 * If the column or row contain the cell is deleted, the cell is set "deleted" 259 * 260 */ 261 public boolean isDeleted(){ 262 return this.deleted ; 263 } 264 265 public void setDeleted(boolean d){ 266 this.deleted =d; 267 } 268 269 public SSTableModel getDataModel() { 270 return dataModel; 271 } 272 273 /*** 274 * This method determines a cell is a edu.psu.geovista.app.spreadsheet.formula cell that has a error. 275 * 276 * @return true if cell is an error cell 277 278 public boolean isErrorCell() { 279 return ((isFormula()) && (value instanceof ParserException)); 280 } */ 281 282 283 284 public Vector getContainer() { 285 return container; 286 } 287 /*** 288 * toString() method return same data as getValue(), but in different format 289 * toString() return String format for table.getValue() to paintCell() 290 * getValue() return Number for evaluate edu.psu.geovista.app.spreadsheet.formula 291 * called when paint cell 292 */ 293 public String toString() { 294 /*if (this.isFormula() ) 295 return "="+expression.toString(); 296 else*/ 297 /* Because all values stored in TableModel is in form of edu.psu.geovista.app.spreadsheet.formula.Cell object, 298 * TableModel.getValueAt() will call object.toString() to get actual value 299 *, so toString() only return the evaluted value, not edu.psu.geovista.app.spreadsheet.formula expression*/ 300 if (this.isDeleted() ){ 301 return "#REF!"; 302 } 303 if (this.isFormula()&&!this.getFormula().isBad() ){ 304 this.evaluate() ; 305 } 306 if(value !=null) 307 return value.toString(); 308 else 309 return null; //means empty value"" 310 } 311 /*** 312 * not finish yet, just for treeset 313 * String: if can't convert to number, alway on the top ."" is set to null in cell 314 * null<"": alway at the bottom 315 * number: always in middle 316 * @return a negative integer, zero, or a positive integer as 317 * this object is less than, equal to, or greater than 318 * the specified object. 319 */ 320 public int compareTo( Cell x, boolean ascend){ 321 final int over=2000000; //doesnot matter if ascend or descend, this cell always over the given cell 322 final int under=-2000000; //doesnot matter if ascend or descend, this cell always under the given cell 323 //Note:??? Use big number cause compareToIgnoreCase() will return some small number(like 2,11,20...), which may cause bug 324 325 int r;//return 326 //if this is blank which is lowest value 327 assert (x!=null); 328 int xt=x.getValueType();//x's value type 329 int tt=this.getValueType() ;//this value type 330 331 Object tvalue=this.value; 332 Object xvalue=x.getValue() ; 333 if (tt==Cell.NULL ){ 334 //r= under; 335 return 1; 336 } 337 if (xt==Cell.NULL ){ 338 //r= over; 339 return -1; 340 } 341 342 if (tt==Cell.TEXT ){ 343 String tvs=(String)tvalue; 344 if (xt==Cell.TEXT ){ 345 String xvs=(String)xvalue; 346 r= tvs.compareToIgnoreCase(xvs); 347 if (tvs!=null&&xvs!=null) 348 Debug.println( tvs +" compareToIgnoreCase "+xvs+ " = "+r); 349 } 350 else if(xt==Cell.NUMBER ){ 351 352 try { 353 Number xvn=(Number)xvalue; 354 double xvd=xvn.doubleValue() ; 355 double tvd=Double.parseDouble(tvs); //??throw NumberFormatException 356 if(tvd>xvd) r= 1; 357 else if (tvd<xvd)r= -1; 358 else r= 0; 359 } catch (NumberFormatException e) {//String can't convert to number 360 r= over; 361 } 362 } 363 else if (xt==Cell.UNKNOWN ){ 364 Comparable tvc=(Comparable)tvs; 365 Comparable xvc=(Comparable)xvalue; 366 r= tvc.compareTo(xvc); //??? throw ClassCastException 367 368 } 369 else{ //xt=edu.psu.geovista.app.spreadsheet.formula.Cell.Null, should never reach, just for compile purpose 370 assert false; 371 r= over; 372 } 373 374 } 375 else if(tt==Cell.NUMBER){ 376 Number tvn=(Number)tvalue; 377 if (xt==Cell.TEXT ){ 378 try { 379 String xvs=(String)xvalue; 380 double xvd=Double.parseDouble(xvs); //??throw NumberFormatException 381 double tvd=tvn.doubleValue() ; 382 if(tvd>xvd) r= 1; 383 else if (tvd<xvd)r= -1; 384 else r= 0; 385 } catch (NumberFormatException e) { 386 r=under; 387 } 388 } 389 else if(xt==Cell.NUMBER ){ 390 391 Number xvn=(Number)xvalue; 392 double tvd=tvn.doubleValue() ; 393 double xvd=xvn.doubleValue() ; 394 if(tvd>xvd) r= 1; 395 else if (tvd<xvd)r= -1; 396 else r= 0; 397 } 398 else if (xt==Cell.UNKNOWN ){ 399 r= 0 ; 400 401 //throw new ClassCastException(); 402 } 403 else{ //xt =edu.psu.geovista.app.spreadsheet.formula.Cell.Null, should never reach, just for compile purpose 404 assert false; 405 r= over; 406 } 407 408 } 409 else { //unknow type 410 Debug.println("this cell value type:"+tt); 411 Comparable tvc=(Comparable)tvalue; 412 Comparable xvc=(Comparable)xvalue; 413 r= tvc.compareTo(xvc); //??? throw ClassCastException 414 415 } 416 417 if (r==over){ 418 return -1; 419 } 420 else if (r==under){ 421 return 1; 422 } 423 else{ 424 if (ascend){ 425 return r; 426 } 427 else{ 428 return -r; 429 } 430 } 431 432 433 } 434 435 /********************************************************************* 436 * Address * 437 ********************************************************************/ 438 439 /*** 440 * return the address of the cell in Table in form of (x,y) 441 * Need translate. e.g. Row1 in Table is Row0 in TableModel 442 */ 443 public Point getViewAddress(){ 444 //Point address=this.getModelAddress() ; 445 //SSTableModel tm=SSTableModel.getInstance() ; 446 Point address=this.getDataModel().getCellAddress(this) ; //address in TableModel 447 if (address==null) return null; 448 int x=(int)address.getX() ; //edu.psu.geovista.app.spreadsheet.model index (sort edu.psu.geovista.app.spreadsheet.model if sort) 449 int y=(int)address.getY(); //edu.psu.geovista.app.spreadsheet.model index (sort edu.psu.geovista.app.spreadsheet.model if sort) 450 451 452 453 454 //For now Model row is same as table row. May not the case if implement Sort on row 455 int row=SSTable.transRowTableToView(x); 456 //int col=Cell.transColModelToView(y); 457 int col=this.getDataModel().getTable().transColModelToView(y); 458 //String col=edu.psu.geovista.app.spreadsheet.formula.Node.translateColumn(y ); 459 return new Point(row,col); 460 461 462 } 463 public String getViewAddressText(){ 464 String addrs=null; 465 Point address=getViewAddress() ; //address in Table 466 if (address!=null){ 467 int x=(int)address.getX() ; 468 int y=(int)address.getY(); 469 //String row=edu.psu.geovista.app.spreadsheet.formula.Node.translateRow(x ); 470 String row=Integer.toString(x); 471 String col=SSTable.translateVVColumn(y);//translate to String. e.g. 1=>A 472 addrs=col+row; 473 474 } 475 return addrs; 476 } 477 /*** 478 * return the address of the cell in TableModel in form of (x,y) 479 * 480 */ 481 private Point getModelAddress(){ 482 //SSTableModel tmd=SSTableModel.getInstance() ; 483 int row=this.getDataModel().getDataVector().indexOf(this.container ); 484 int col=this.container.indexOf(this); 485 if (row>=0&&col>=0){ 486 return new Point(row,col); 487 } 488 else{//happen when you delete a column which is referenced by other columns 489 return null; 490 } 491 } 492 493 494 495 /*** 496 * Given a cell's address in View(table) return relative address in String format 497 */ 498 public static String getRelCellAddress(Point p){ 499 StringBuffer address = new StringBuffer(); 500 String addr = null; 501 int x = (int) p.getX(); 502 int y = (int) p.getY(); 503 addr = SSTable.translateVVColumn(y); 504 address.append(addr); 505 addr = String.valueOf(x); 506 address.append(addr);//e.g.: A1 507 String a=address.toString(); 508 Debug.println("Cell address :" + a); 509 return a; 510 511 } 512 /*** 513 * Given a cell's address in View(table) return absolute address in String format 514 */ 515 public static String getAbsCellAddress(Point p){ 516 StringBuffer address = new StringBuffer(); 517 String addr = null; 518 int x = (int) p.getX(); 519 int y = (int) p.getY(); 520 addr = SSTable.translateVVColumn(y); 521 address.append("$"); 522 address.append(addr); 523 addr = String.valueOf(x); 524 address.append("$"); 525 address.append(addr);//e.g.: A1 526 String a=address.toString(); 527 Debug.println("Cell address :" + a); 528 return a; 529 530 } 531 532 } 533

This page was automatically generated by Maven