1 33 package net.sf.jga.swing.spreadsheet; 34 35 import java.awt.Component ; 36 import java.awt.Container ; 37 import java.awt.Dimension ; 38 import java.awt.Font ; 39 import java.awt.FontMetrics ; 40 import java.awt.Graphics ; 41 import java.awt.Insets ; 42 import java.awt.Point ; 43 import java.awt.Rectangle ; 44 import java.io.IOException ; 45 import java.io.InputStream ; 46 import java.io.OutputStream ; 47 import java.text.MessageFormat ; 48 import java.util.HashMap ; 49 import java.util.HashSet ; 50 import java.util.Iterator ; 51 import java.util.Map ; 52 import java.util.Observable ; 53 import java.util.Observer ; 54 import java.util.Set ; 55 import javax.swing.CellRendererPane ; 56 import javax.swing.JComponent ; 57 import javax.swing.JScrollPane ; 58 import javax.swing.JTable ; 59 import javax.swing.JViewport ; 60 import javax.swing.UIManager ; 61 import javax.swing.border.Border ; 62 import javax.swing.event.ListSelectionEvent ; 63 import javax.swing.table.AbstractTableModel ; 64 import javax.swing.table.JTableHeader ; 65 import javax.swing.table.TableCellEditor ; 66 import javax.swing.table.TableCellRenderer ; 67 import javax.swing.table.TableColumn ; 68 import javax.swing.table.TableColumnModel ; 69 import javax.swing.table.TableModel ; 70 import javax.xml.parsers.ParserConfigurationException ; 71 import javax.xml.parsers.SAXParser ; 72 import javax.xml.parsers.SAXParserFactory ; 73 import javax.xml.transform.OutputKeys ; 74 import javax.xml.transform.Transformer ; 75 import javax.xml.transform.TransformerConfigurationException ; 76 import javax.xml.transform.sax.SAXTransformerFactory ; 77 import javax.xml.transform.sax.TransformerHandler ; 78 import javax.xml.transform.stream.StreamResult ; 79 import net.sf.jga.fn.BinaryFunctor; 80 import net.sf.jga.fn.EvaluationException; 81 import net.sf.jga.fn.Generator; 82 import net.sf.jga.fn.UnaryFunctor; 83 import net.sf.jga.fn.adaptor.Constant; 84 import net.sf.jga.fn.adaptor.Identity; 85 import net.sf.jga.parser.IParser; 86 import net.sf.jga.parser.JFXGParser; 87 import net.sf.jga.parser.FunctorRef; 88 import net.sf.jga.parser.GeneratorRef; 89 import net.sf.jga.parser.ParseException; 90 import org.xml.sax.Attributes ; 91 import org.xml.sax.InputSource ; 92 import org.xml.sax.SAXException ; 93 import org.xml.sax.XMLReader ; 94 import org.xml.sax.helpers.AttributesImpl ; 95 import org.xml.sax.helpers.DefaultHandler ; 96 97 109 110 112 114 117 120 123 130 133 138 public class Spreadsheet extends JTable { 139 140 static final long serialVersionUID = -4784933072621672138L; 141 142 transient Parser _parser = new Parser (); 145 146 private SpreadsheetTableModel _model; 148 149 private RowHeader _rowHeader; 151 152 private UnaryFunctor<String ,?> _statusFn = new Identity<String >(); 154 155 private boolean _initialized; 159 160 public Spreadsheet (int rows, int cols){ 161 super(); 162 _model = new SpreadsheetTableModel(rows, cols); 163 super.setModel(_model); 164 165 setAutoCreateColumnsFromModel(false); 166 setAutoResizeMode(AUTO_RESIZE_OFF); 167 setCellSelectionEnabled(true); 168 setCellEditor(new Cell.Editor()); 169 170 TableColumnModel columns = getColumnModel(); 171 for (int i = 0; i < cols; ++i) { 172 columns.getColumn(i).setHeaderValue(String.valueOf(i)); 173 } 174 175 getTableHeader().setReorderingAllowed(false); 176 177 _rowHeader = new RowHeader(this); 178 179 _parser.bindThis(this); 180 181 _initialized = true; 182 } 183 184 188 public void setColumnCount(int width) { 189 int oldWidth = getColumnCount(); 190 doSetColumnCount(oldWidth, width); 191 if (width > 0 && width != oldWidth) { 192 _model.setColumnCount(width); 193 } 194 } 195 196 private void doSetColumnCount(int oldWidth, int width) { 197 if (width > 0 && width != oldWidth) { 198 TableColumnModel columns = getColumnModel(); 199 if (oldWidth < width) { 200 for (int i = oldWidth; i < width; ++i) { 201 TableColumn column = new TableColumn (i); 202 column.setHeaderValue(String.valueOf(i)); 203 addColumn(column); 204 } 205 } 206 else { 207 for (int i = oldWidth - 1; i >= width; --i) { 208 removeColumn(columns.getColumn(i)); 209 } 210 } 211 } 212 } 213 214 public void setRowCount(int height) { 215 if (height > 0 && height != getRowCount()) { 216 _model.setRowCount(height); 217 _rowHeader.setRowCount(height); 218 } 219 } 220 221 224 public IParser getParser() { return _parser; } 225 226 private Class _defaultType = Integer .class; 228 229 230 233 public Class getDefaultCellType() { return _defaultType; } 234 235 236 242 public void setDefaultCellType(Class type) { 243 _defaultType = type; 244 if (_defaultValue != null && !type.isInstance(_defaultValue)) 245 _defaultValue = null; 246 } 247 248 249 private Object _defaultValue = new Integer (0); 251 252 253 256 public Object getDefaultCellValue() { return _defaultValue; } 257 258 259 265 public void setDefaultCellValue(Object value) { 266 _defaultValue = value; 267 if (!_defaultType.isInstance(value)) 268 _defaultType = value.getClass(); 269 } 270 271 272 276 public void setEditableByDefault(boolean b) { _model.setEditableByDefault(b); } 277 278 279 282 public boolean isEditableByDefault() { return _model.isEditableByDefault(); } 283 284 285 private boolean _strictType; 287 288 292 293 public boolean isStrictlyTyped() { return _strictType; } 294 295 296 303 304 public void setStrictTyping(boolean b) { _strictType = b; } 305 306 310 312 public void readSpreadsheet(InputStream is) throws IOException { 313 new Reader ().readSpreadsheet(is); 314 } 315 316 318 public void writeSpreadsheet(OutputStream os) throws IOException { 319 new Writer().writeSpreadsheet(os); 320 } 321 322 326 329 330 public JComponent getRowHeader() { 331 return _rowHeader; 332 } 333 334 339 340 public void setStatusHandler(UnaryFunctor<String ,?> fn) { 341 _statusFn = fn; 342 } 343 344 347 public void setStatus(String status) { 348 _statusFn.fn(status); 349 } 350 351 358 private Generator<?> _updateFn; 359 360 public void setUpdateHandler(Generator<?> fn) { 361 _updateFn = fn; 362 } 363 364 private void fireSpreadsheetUpdated() { 365 if (_updateFn != null) 366 _updateFn.gen(); 367 } 368 369 373 376 377 public void clearCellAt(int row, int col) { 378 Cell cell = getCellIfPresent(row,col); 379 if (cell != null) { 380 cell.clear(); 381 } 382 } 383 384 389 public Cell getCellAt(int row, int col) { 390 Cell cell = getCellIfPresent(row,col); 391 if (cell == null) { 392 cell = _model.setCell(new Cell(this,row,col)); 393 } 394 return cell; 395 } 396 397 401 Cell getCellIfPresent(int row, int col) { 402 return _model.getCellAt(row,col); 403 } 404 405 415 420 public <T> Cell setCellAt(Class <T> type, T value, int row, int col) { 421 return _model.setCellAt(type, new Constant<T>(value), row, col); 422 } 423 424 425 429 433 public <T> Cell setCellAt(Class <T> type, Generator<T> gen, int row, int col) { 434 return _model.setCellAt(type, gen, row, col); 435 } 436 437 438 446 453 459 463 public Cell setCellAt(String formula, int row, int col) { 464 return _model.setCellAt(formula, row, col, _model.isEditableByDefault()); 465 } 466 467 468 472 public Cell setCellAt(String formula, int row, int col, boolean editable) { 473 return _model.setCellAt(formula, row, col, editable); 474 } 475 476 477 486 493 499 506 public <T> void setFormatAt(UnaryFunctor<T,String > formatter, int row, int col) { 507 getCellAt(row,col).setFormat(formatter); 514 } 515 516 519 public Cell getCellByName(String name) { 520 return _model.getCellByName(name); 521 } 522 523 527 public Cell setCellName(String name, int row, int col) { 528 Cell cell = _model.setCellName(name, row, col); 529 setStatus(cell.toString()); 530 return cell; 531 } 532 533 534 537 public <T> Generator<T> getReference(Class <T> type, int row, int col) { 538 return _model.getReference(type, row, col); 539 } 540 541 542 546 public void clear() { 547 _model.clear(); 548 setRowSelectionInterval(0,0); 549 setColumnSelectionInterval(0,0); 550 } 551 552 556 public TableCellEditor getCellEditor(int row, int col) { 557 Cell cell = getCellIfPresent(row,col); 558 if (cell == null) { 559 return super.getCellEditor(row,col); 560 } 561 562 TableCellEditor editor = cell.getEditor(); 563 return (editor != null) ? editor : super.getCellEditor(row,col); 564 } 565 566 private TableCellRenderer _defaultRenderer = new Cell.Renderer(); 567 568 public TableCellRenderer getCellRenderer(int row, int col) { 569 Cell cell = getCellIfPresent(row,col); 570 if (cell == null) 571 return _defaultRenderer; 572 574 TableCellRenderer renderer = cell.getRenderer(); 575 return (renderer != null) ? renderer : _defaultRenderer; } 577 578 579 public void setModel(TableModel model) { 580 if (!_initialized) 584 super.setModel(model); 585 else if (model instanceof SpreadsheetTableModel) { 586 super.setModel(model); 587 SpreadsheetTableModel oldModel = _model; 588 _model = (SpreadsheetTableModel) model; 589 _rowHeader.setRowCount(_model.getRowCount()); 590 doSetColumnCount(oldModel.getColumnCount(),_model.getColumnCount()); 591 } 592 else { 593 String msg = "Spreadsheet requires SpreadsheetTableModel"; 596 throw new IllegalArgumentException (msg); 597 } 598 } 599 600 605 protected void configureEnclosingScrollPane() { 606 super.configureEnclosingScrollPane(); 607 Container p = getParent(); 610 if (p instanceof JViewport ) { 611 Container gp = p.getParent(); 612 if (gp instanceof JScrollPane ) { 613 JScrollPane scrollPane = (JScrollPane )gp; 614 JViewport viewport = scrollPane.getViewport(); 615 if (viewport == null || viewport.getView() != this) { 616 return; 617 } 618 619 scrollPane.setRowHeaderView(getRowHeader()); 620 } 621 } 622 } 623 624 public void valueChanged(ListSelectionEvent e) { 626 if (!e.getValueIsAdjusting()) 627 showSelectionStatus(); 628 629 super.valueChanged(e); 630 } 631 632 633 public void columnSelectionChanged(ListSelectionEvent e) { 635 if (!e.getValueIsAdjusting()) 636 showSelectionStatus(); 637 638 super.columnSelectionChanged(e); 639 } 640 641 private int _lastRow = -1, _lastCol = -1; 643 644 private void showSelectionStatus() { 646 int row = getSelectedRow(); 647 int col = getSelectedColumn(); 648 if (row < 0 || col < 0) 649 return; 650 651 if (row == _lastRow && col == _lastCol) 652 return; 653 654 _lastRow = row; _lastCol = col; 655 Cell cell = getCellIfPresent(row, col); 656 if (cell != null) 657 setStatus(cell.toString()); 658 else 659 setStatus("cell("+row+","+col+")"); 660 } 661 662 666 private class SpreadsheetTableModel extends AbstractTableModel implements Observer { 667 668 static final long serialVersionUID = -6455541616661139146L; 669 670 private Map <Point ,Cell> _cellmap = new HashMap <Point ,Cell>(); 672 673 private Map <String ,Cell> _namemap = new HashMap <String ,Cell>(); 675 676 private int _numRows; 678 679 private int _numCols; 681 682 685 public SpreadsheetTableModel() { 686 this(16, 16); 687 } 688 689 692 public SpreadsheetTableModel(int rows, int cols) { 693 _numRows = rows; 694 _numCols = cols; 695 } 696 697 700 public void clear() { 701 _cellmap = new HashMap <Point ,Cell>(); 702 _namemap = new HashMap <String ,Cell>(); 703 fireTableDataChanged(); 704 } 705 706 712 public Cell getCellAt(int row, int col) throws IndexOutOfBoundsException { 713 if (checkCellAddress(row,col)) 714 return _cellmap.get(new Point (row, col)); 715 716 if (row < 0 || row >= _numRows) { 717 String msg = "Row " +row +" out of range: 0.." +(_numRows - 1); 718 throw new IndexOutOfBoundsException (msg); 719 } 720 721 String msg = "Col " +col +" out of range: 0.." +(_numCols - 1); 722 throw new IndexOutOfBoundsException (msg); 723 } 724 725 731 private <T> Cell setCellAt(Class <T> type, Generator<T> gen, int row, int col) { 732 734 Cell cell = getCellAt(row,col); 737 if (cell != null) { 738 throw new IllegalArgumentException (cell+" has already been set"); 739 } 740 741 if (gen == null) 742 return null; 743 744 return setCell(new Cell(Spreadsheet.this, type, new Point (row, col), gen)); 745 } 746 747 753 private Cell setCellAt(String formula, int row,int col, boolean editable){ 754 Cell cell = getCellAt(row,col); 757 if (cell != null) { 758 throw new IllegalArgumentException (cell+" has already been set"); 759 } 760 761 if (formula == null || "".equals(formula)) 762 return null; 763 764 return setCell(new Cell(Spreadsheet.this, new Point (row, col), formula, editable)); 765 } 766 767 769 private Cell setCell(Cell cell) { 770 String name = cell.getName(); 771 if (name != null) { 772 if (_namemap.get(name) != null) { 773 String err = "Duplicate cell name "+name; 774 throw new IllegalArgumentException (err); 775 } 776 777 _namemap.put(name, cell); 778 } 779 780 cell.addObserver(this); 781 782 Point p = cell.getAddress(); 783 _cellmap.put(p, cell); 784 fireTableCellUpdated(p.x, p.y); 785 return cell; 786 } 787 788 791 private Cell getCellByName(String name) { 792 return _namemap.get(name); 793 } 794 795 798 private Cell setCellName(String name, int row, int col) { 799 if (name != null) { 800 Cell cell = _namemap.get(name); 801 if (cell != null) { 802 String err = "Duplicate cell name "+name; 803 throw new IllegalArgumentException (err); 804 } 805 } 806 807 Cell cell = Spreadsheet.this.getCellAt(row, col); 808 String oldname = cell.getName(); 809 if (oldname != null) 810 _namemap.remove(oldname); 811 812 if (name != null) 813 _namemap.put(name, cell); 814 815 cell.setName(name); 816 817 return cell; 821 822 } 823 824 827 832 835 public <T> Generator<T> getReference(Class <T> type, int row, int col) { 836 Cell cell = getCellAt(row,col); 837 if (cell == null) { 838 String msg = "Cell({0},{1}) is not yet defined"; 839 throw new IllegalArgumentException (MessageFormat.format(msg, new Object []{row,col})); 840 } 841 if (type.isAssignableFrom(cell.getType())) { 842 843 return cell.getReference(); 848 } 849 850 String err = "Cannot return reference of type {0} from {1}, whose type is {2}"; 851 String msg = MessageFormat.format(err, new Object []{ type, cell, cell.getType() }); 852 throw new ClassCastException (msg); 853 } 854 855 856 private boolean _editableByDefault; 858 private void setEditableByDefault(boolean b) { _editableByDefault = b; } 859 private boolean isEditableByDefault() { return _editableByDefault; } 860 861 862 public void setRowCount(int height) { 863 int oldHeight = _numRows; 864 _numRows = height; 865 866 if (oldHeight < height) { 867 fireTableRowsInserted(oldHeight,height-1); 868 } 869 else { 870 removeCells(); 871 fireTableRowsDeleted(height,oldHeight-1); 872 } 873 } 874 875 876 public void setColumnCount(int width) { 877 int oldWidth = _numCols; 878 _numCols = width; 879 if (width < oldWidth) { 880 removeCells(); 881 } 882 883 fireTableStructureChanged(); 884 } 885 886 private void removeCells() { 887 for (Iterator iter = _cellmap.values().iterator(); iter.hasNext(); ) { 888 Cell cell = (Cell) iter.next(); 889 Point p = cell.getAddress(); 890 if (p.x >= _numRows || p.y >= _numCols) { 891 iter.remove(); 892 893 String name = cell.getName(); 894 if(name != null) 895 _namemap.remove(cell.getName()); 896 897 cell.unlink(); 898 } 899 } 900 } 901 902 906 public int getRowCount() { 907 return _numRows; 908 } 909 910 911 public int getColumnCount() { 912 return _numCols; 913 } 914 915 916 public Object getValueAt(int row, int col) { 917 if (!checkCellAddress(row, col)) 918 return Cell.REFERENCE_ERR; 919 920 Cell cell = _cellmap.get(new Point (row, col)); 921 if (cell == null) 922 return null; 923 924 Object obj = cell.getValue(); 925 return cell.isUndefined() ? "" : cell.isValid() ? obj : cell.getErrorMsg(); 926 } 927 928 929 936 public void setValueAt(Object value, int row, int col) { 937 Cell cell = getCellAt(row,col); 938 if (cell != null) { 939 cell.setValue(value); 940 } 941 else if (value != null) { 942 setCellAt(value.toString(), row, col, true); 943 } 944 945 fireSpreadsheetUpdated(); 946 } 947 948 949 public boolean isCellEditable(int row, int col) { 950 Cell cell = getCellAt(row, col); 951 if (cell != null) 952 return cell.isEditable(); 953 954 return _editableByDefault; 955 } 956 957 958 962 public void update(Observable observable, Object object) { 963 Cell cell = (Cell) observable; 964 Point addr = cell.getAddress(); 965 fireTableCellUpdated(addr.x, addr.y); 966 } 967 968 972 private boolean checkCellAddress(int row, int col) { 973 return row >= 0 && row < _numRows && col >=0 && col < _numCols; 974 } 975 } 976 977 981 class Parser extends JFXGParser { 982 private Cell _crntCell; 983 984 private Parser() { super(); } 985 986 public Generator parseGenerator(Cell cell, String str) throws ParseException { 987 _crntCell = cell; 988 try { 989 return super.parseGenerator(str); 990 } 991 finally { 992 _crntCell = null; 993 } 994 995 } 996 997 1001 public void bindThis(Object thisBinding) { 1002 super.bindThis(Spreadsheet.this); 1003 } 1004 1005 1006 1010 protected FunctorRef resolveMethodName(FunctorRef prefix, String name, FunctorRef[] args) 1011 throws ParseException 1012 { 1013 if (prefix.getReferenceType() != FunctorRef.CONSTANT ) 1015 return super.resolveMethodName(prefix, name, args); 1016 1017 if (((GeneratorRef) prefix).getFunctor().gen() != Spreadsheet.this) 1019 return super.resolveMethodName(prefix, name, args); 1020 1021 return super.resolveMethodName(prefix, name, args); 1023 } 1024 1025 1026 1029 protected FunctorRef reservedWord(String word) throws ParseException { 1030 if (word.equals("row")) { 1031 return new GeneratorRef(new Constant(_crntCell.getAddress().x), Integer .class); 1032 } 1033 1034 if (word.equals("col")) { 1035 return new GeneratorRef(new Constant(_crntCell.getAddress().y), Integer .class); 1036 } 1037 1038 return super.reservedWord(word); 1039 } 1040 1041 1042 1045 protected FunctorRef reservedFunction(String name, FunctorRef[] args) throws ParseException { 1046 if (name.equals("cell")) { 1047 if (args.length == 1 && args[0] instanceof GeneratorRef && 1048 args[0].getReturnType().equals(String .class)) 1049 { 1050 String refname = (String ) ((GeneratorRef) args[0]).getFunctor().gen(); 1051 Cell cell = getCellByName(refname); 1052 if (cell == null) { 1053 throw new ParseException("Unknown Cell Name: " + refname); 1054 } 1055 1056 return new GeneratorRef(cell.getReference(), cell.getType()); 1057 } 1058 1059 if (args.length != 2 || 1060 !(args[0] instanceof GeneratorRef) || 1061 !(args[1] instanceof GeneratorRef) || 1062 !(args[0].getReturnType().equals(Integer .class)) || 1063 !(args[1].getReturnType().equals(Integer .class))) 1064 throw new ParseException ("Cell Reference requires row, col arguments"); 1065 1066 int row = ((Integer ) ((GeneratorRef) args[0]).getFunctor().gen()).intValue(); 1067 int col = ((Integer ) ((GeneratorRef) args[1]).getFunctor().gen()).intValue(); 1068 Cell cell = getCellAt(row, col); 1069 return new GeneratorRef(cell.getReference(), cell.getType()); 1070 } 1071 1072 return super.reservedFunction(name, args); 1073 } 1074 } 1075 1076 1080 public class Writer { 1081 private TransformerHandler _handler; 1082 private Transformer _xformer; 1083 private Set <Cell> _cellsWritten; 1084 1085 public Writer() throws IOException { 1086 try { 1087 SAXTransformerFactory tf = (SAXTransformerFactory ) SAXTransformerFactory.newInstance(); 1088 _handler = tf.newTransformerHandler(); 1089 1090 Transformer xformer = _handler.getTransformer(); 1091 xformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1"); 1092 1093 1097 xformer.setOutputProperty(OutputKeys.INDENT,"yes"); 1099 } 1100 catch (TransformerConfigurationException x) { 1101 IOException iox = new IOException (x.getMessage()); 1102 iox.initCause(x); 1103 throw iox; 1104 } 1105 } 1106 1107 1108 public void writeSpreadsheet(OutputStream os) throws IOException { 1109 try { 1110 StreamResult stream = new StreamResult (os); 1112 _handler.setResult(stream); 1113 _handler.startDocument(); 1114 1115 AttributesImpl atts = new AttributesImpl (); 1116 int rows = getRowCount(); 1117 int cols = getColumnCount(); 1118 1119 atts.clear(); 1123 atts.addAttribute("","","vers","", "0.1.0"); 1124 atts.addAttribute("","","rows","", String.valueOf(rows)); 1125 atts.addAttribute("","","cols","", String.valueOf(cols)); 1126 1127 Class defaultType = getDefaultCellType(); 1128 if ( ! defaultType.equals(Integer .class)) { 1129 atts.addAttribute("","","defaultType","",defaultType.getName()); 1130 } 1131 1132 Object defaultValue = getDefaultCellValue(); 1133 if ( ! defaultValue.equals(0)) { 1134 atts.addAttribute("","","defaultValue","",getDefaultCellValue().toString()); 1135 } 1136 1137 _handler.startElement("","","hacksheet",atts); 1138 1139 _cellsWritten = new HashSet <Cell>(_model._cellmap.values().size() * 4 / 3); 1140 writeCells(_model._cellmap.values().iterator()); 1141 1142 _handler.endElement("","","hacksheet"); 1143 _handler.endDocument(); 1144 } 1145 catch (SAXException x) { 1146 IOException iox = new IOException (x.getMessage()); 1147 iox.initCause(x); 1148 throw iox; 1149 } 1150 } 1151 1152 private void writeCells(Iterator <Cell> cells) throws SAXException { 1153 while (cells.hasNext()) { 1154 Cell cell = cells.next(); 1155 if (!_cellsWritten.contains(cell)) { 1156 writeCells(cell.dependsOn()); 1157 writeCell(cell); 1158 } 1159 } 1160 } 1161 1162 private void writeCell(Cell cell) throws SAXException { 1163 AttributesImpl atts = new AttributesImpl (); 1164 1165 String name = cell.getName(); 1166 if (name != null && name.trim().length() != 0) 1167 atts.addAttribute("","","id","",cell.getName()); 1168 1169 Point p = cell.getAddress(); 1170 atts.addAttribute("","","row","", String.valueOf(p.x)); 1171 atts.addAttribute("","","col","", String.valueOf(p.y)); 1172 atts.addAttribute("","","type","", cell.getType().getName()); 1173 atts.addAttribute("","","editable","",String.valueOf(cell.isEditable())); 1174 1175 String formula = cell.getFormula(); 1176 _handler.startElement("","","cell",atts); 1177 1178 atts.clear(); 1179 _handler.startElement("","","formula",atts); 1180 _handler.characters(formula.toCharArray(),0,formula.length()); 1181 _handler.endElement("","","formula"); 1182 _handler.endElement("","","cell"); 1183 1184 _cellsWritten.add(cell); 1185 } 1186 } 1187 1188 1192 public class Reader extends DefaultHandler { 1193 StringBuffer buf = new StringBuffer (); 1194 1195 1196 public void readSpreadsheet(InputStream is) throws IOException { 1197 try { 1198 createParser().parse(new InputSource (is)); 1199 } 1200 catch (SAXException x) { 1201 IOException iox = new IOException (x.getMessage()); 1202 iox.initCause(x); 1203 throw iox; 1204 } 1205 catch (ParserConfigurationException x) { 1206 IOException iox = new IOException (x.getMessage()); 1207 iox.initCause(x); 1208 throw iox; 1209 } 1210 } 1211 1212 1213 private Cell _crntCell; 1214 1215 public void startElement(String nsURI, String localname, String qname, Attributes attr) 1216 throws SAXException 1217 { 1218 if (qname.equals("hacksheet")) { 1219 String vers = attr.getValue("vers"); 1220 1222 int rows = Integer.parseInt(attr.getValue("rows")); 1223 int cols = Integer.parseInt(attr.getValue("cols")); 1224 SpreadsheetTableModel model = new SpreadsheetTableModel(rows, cols); 1225 SpreadsheetTableModel oldModel = _model; 1226 setModel(model); 1227 } 1228 else if (qname.equals("cell")) { 1229 int row = Integer.parseInt(attr.getValue("row")); 1230 int col = Integer.parseInt(attr.getValue("col")); 1231 _crntCell = new Cell(Spreadsheet.this, row, col); 1232 _crntCell.setEditable(Boolean.valueOf(attr.getValue("editable"))); 1233 String name = attr.getValue("id"); 1234 if (name != null) { 1235 _crntCell.setName(name); 1236 } 1237 } 1238 else if (qname.equals("formula")) { 1239 buf.delete(0, buf.length()); 1240 } 1241 else 1242 throw new SAXException ("unknown tag \""+qname+"\""); 1243 } 1244 1245 public void endElement(String nsURI, String localname, String qname) 1246 throws SAXException 1247 { 1248 if (qname.equals("hacksheet")) { 1249 } 1250 else if (qname.equals("cell")) { 1251 _model.setCell(_crntCell); 1252 } 1253 else if (qname.equals("formula")) { 1254 _crntCell.setFormula(buf.toString()); 1255 buf.delete(0, buf.length()); 1256 } 1257 else 1258 throw new SAXException ("unknown tag \""+qname+"\""); 1259 } 1260 1261 1262 public void characters(char[] ch, int start, int ln) throws SAXException { 1263 for (int i = 0; i < ln; ++i) { 1264 buf.append(ch[start+i]); 1265 } 1266 } 1267 1268 1269 public XMLReader createParser() throws SAXException , ParserConfigurationException { 1270 SAXParserFactory spf = SAXParserFactory.newInstance(); 1271 spf.setValidating(false); 1272 1273 SAXParser saxParser = spf.newSAXParser(); 1274 XMLReader xmlrd = saxParser.getXMLReader(); 1275 xmlrd.setContentHandler (this); 1276 xmlrd.setErrorHandler (this); 1277 return xmlrd; 1278 } 1279 } 1280} 1281 1282 1286class RowHeader extends JComponent { 1287 static final long serialVersionUID = -1375303876648436931L; 1288 1289 private JTable _table; 1290 private TableCellRenderer _renderer; 1291 private JTableHeader _header; 1292 private CellRendererPane _rendererPane; 1293 private Font _headerFont; 1294 1295 public RowHeader(JTable table) { 1296 _table = table; 1297 _header = table.getTableHeader(); 1298 _renderer = _header.getDefaultRenderer(); 1299 _rendererPane = new CellRendererPane (); 1300 add(_rendererPane); 1301 1302 Component rendererComponent = 1303 _renderer.getTableCellRendererComponent(_table, "0", false, false, 0, -1); 1304 1305 _headerFont = rendererComponent.getFont(); 1306 1307 setFont(_headerFont); 1308 setBackground(rendererComponent.getBackground()); 1309 setForeground(rendererComponent.getForeground()); 1310 } 1312 1313 public TableCellRenderer getRenderer() { return _renderer; } 1314 public void setRenderer(TableCellRenderer renderer) { _renderer = renderer; } 1315 1316 public void setRowCount(int count) { 1317 resize(getPreferredSize()); 1318 } 1319 1320 public Dimension getPreferredSize() { 1321 Border border = (Border ) UIManager.getDefaults().get("TableHeader.cellBorder"); 1322 Insets insets = border.getBorderInsets(_header); 1323 FontMetrics metrics = getFontMetrics(_headerFont); 1324 Dimension dim = new Dimension ( metrics.stringWidth("99999") +insets.right +insets.left, 1325 _table.getRowHeight() * _table.getRowCount()); 1326 return dim; 1327 } 1328 1329 1330 protected void paintComponent(Graphics g) { 1331 1332 1335 Rectangle cellRect = new Rectangle (0,0,getWidth(),_table.getRowHeight(0)); 1336 int rowMargin = _header.getColumnModel().getColumnMargin() - 1; 1337 for (int i = 0; i < _table.getRowCount(); ++i) { 1338 int rowHeight = _table.getRowHeight(i); 1339 cellRect.height = rowHeight - rowMargin; 1340 paintCell(g, cellRect, i); 1341 cellRect.y += rowHeight; 1342 } 1343 } 1344 1345 private void paintCell(Graphics g, Rectangle cellRect, int rowIndex) { 1346 Component component = 1347 _renderer.getTableCellRendererComponent(_table,rowIndex,false,false,rowIndex,-1); 1348 1349 _rendererPane.paintComponent(g, component, this, cellRect.x, cellRect.y, 1350 cellRect.width, cellRect.height, true); 1351 } 1352} 1353 1354 | Popular Tags |