Source Code Cross Referenced for Cell.java in  » Development » jga-Generic-Algorithms » net » sf » jga » swing » spreadsheet » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » jga Generic Algorithms » net.sf.jga.swing.spreadsheet 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // ============================================================================
002:        // $Id: Cell.java,v 1.12 2006/01/08 00:52:25 davidahall Exp $
003:        // Copyright (c) 2004-2005  David A. Hall
004:        // ============================================================================
005:        // The contents of this file are subject to the Common Development and
006:        // Distribution License (CDDL), Version 1.0 (the License); you may not use this 
007:        // file except in compliance with the License.  You should have received a copy
008:        // of the the License along with this file: if not, a copy of the License is 
009:        // available from Sun Microsystems, Inc.
010:        //
011:        // http://www.sun.com/cddl/cddl.html
012:        //
013:        // From time to time, the license steward (initially Sun Microsystems, Inc.) may
014:        // publish revised and/or new versions of the License.  You may not use,  
015:        // distribute, or otherwise make this file available under subsequent versions 
016:        // of the License.
017:        // 
018:        // Alternatively, the contents of this file may be used under the terms of the 
019:        // GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
020:        // case the provisions of the LGPL are applicable instead of those above. If you 
021:        // wish to allow use of your version of this file only under the terms of the 
022:        // LGPL, and not to allow others to use your version of this file under the 
023:        // terms of the CDDL, indicate your decision by deleting the provisions above 
024:        // and replace them with the notice and other provisions required by the LGPL. 
025:        // If you do not delete the provisions above, a recipient may use your version 
026:        // of this file under the terms of either the CDDL or the LGPL.
027:        // 
028:        // This library is distributed in the hope that it will be useful,
029:        // but WITHOUT ANY WARRANTY; without even the implied warranty of
030:        // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
031:        // ============================================================================
032:
033:        package net.sf.jga.swing.spreadsheet;
034:
035:        import java.awt.Component;
036:        import java.awt.Point;
037:        import java.util.HashSet;
038:        import java.util.Iterator;
039:        import java.util.Observable;
040:        import java.util.Observer;
041:        import java.util.Set;
042:        import java.util.logging.Level;
043:        import java.util.logging.Logger;
044:        import javax.swing.DefaultCellEditor;
045:        import javax.swing.JTable;
046:        import javax.swing.JTextField;
047:        import javax.swing.table.TableCellEditor;
048:        import javax.swing.table.TableCellRenderer;
049:        import net.sf.jga.fn.AdaptorVisitor;
050:        import net.sf.jga.fn.BinaryFunctor;
051:        import net.sf.jga.fn.EvaluationException;
052:        import net.sf.jga.fn.Generator;
053:        import net.sf.jga.fn.UnaryFunctor;
054:        import net.sf.jga.fn.Visitable;
055:        import net.sf.jga.fn.adaptor.ApplyBinary;
056:        import net.sf.jga.fn.adaptor.ApplyGenerator;
057:        import net.sf.jga.fn.adaptor.ApplyUnary;
058:        import net.sf.jga.fn.adaptor.Bind1st;
059:        import net.sf.jga.fn.adaptor.Bind2nd;
060:        import net.sf.jga.fn.adaptor.Bind;
061:        import net.sf.jga.fn.adaptor.ChainBinary;
062:        import net.sf.jga.fn.adaptor.ChainUnary;
063:        import net.sf.jga.fn.adaptor.ComposeBinary;
064:        import net.sf.jga.fn.adaptor.ComposeUnary;
065:        import net.sf.jga.fn.adaptor.ConditionalBinary;
066:        import net.sf.jga.fn.adaptor.ConditionalGenerator;
067:        import net.sf.jga.fn.adaptor.ConditionalUnary;
068:        import net.sf.jga.fn.adaptor.Constant;
069:        import net.sf.jga.fn.adaptor.Distribute;
070:        import net.sf.jga.fn.adaptor.Generate1st;
071:        import net.sf.jga.fn.adaptor.Generate2nd;
072:        import net.sf.jga.fn.adaptor.Generate;
073:        import net.sf.jga.fn.adaptor.GenerateBinary;
074:        import net.sf.jga.fn.adaptor.GenerateUnary;
075:        import net.sf.jga.parser.FunctorParser;
076:        import net.sf.jga.parser.ParseException;
077:        import net.sf.jga.swing.GenericTableCellRenderer;
078:        import net.sf.jga.util.Formattable;
079:
080:        /**
081:         * A single cell in spreadsheet.  Encapsulates information about the generator
082:         * that provides the value of the cell, the cell's formatting information, and
083:         * the editor and/or renderer used to display/update the cell's contents.
084:         * <p>
085:         * Copyright &copy; 2004-2005  David A. Hall
086:         * @author <a href="mailto:davidahall@users.sf.net">David A. Hall</a>
087:         */
088:
089:        // Problem: this class can't be generic, as the type T can be changed if the
090:        // user changes the formula to return a different type.  An alternative is to
091:        // allow this type to remain generic, and when the user enters a new formula,
092:        // a new instance if generated.  In this case, we'd need the new cell to be
093:        // able to adopt the listener list of the old cell, and the listener list in
094:        // the base class (Observable) is private.
095:        // TODO: implement the strictTyping flag of the enclosing spreadsheet. When
096:        // strictly typed, a cell may reject a value/formula if it is not of the type
097:        // already set (the first value/formula assigned to an undefined cell will
098:        // never be rejected if it is not of the default type, however)
099:        public class Cell extends Observable implements  Observer {
100:
101:            private Spreadsheet _parent;
102:
103:            //     // the type that the cell holds: typechecking has to be implemented
104:            //     // in this class, as the table can represent a heterogenous collection
105:            //     // of cells
106:            //     private Class _type;
107:
108:            // The name of the cell
109:            private String _name;
110:
111:            // caches the value held by the cell
112:            private Object _value;
113:
114:            // the functor that returns the value of the cell: in the simple case,
115:            // it'll be a Constant<T>, but it can be an arbitrarily complex functor
116:            private Generator _generator;
117:
118:            // the formula that describes the value of the cell: this string is
119:            // parsed to create the Generator
120:            private String _formula;
121:
122:            // The address of this cell (for the time being, rows & columns won't be
123:            // inserted (we'll need to update the address of a cell or provide a map)
124:            private Point _addr;
125:
126:            // Flag that controls editablilty: we can make cells read-only
127:            private boolean _editable;
128:
129:            // Component used to render cells in the paint method 
130:            private TableCellRenderer _renderer;
131:
132:            // Component used to edit cell values
133:            private TableCellEditor _editor;
134:
135:            // The last exception caught by the cell
136:            private Throwable _exception;
137:
138:            // The string shown on the UI when a cell encounters an error
139:            private String _errMsg;
140:
141:            // Implies that a dependency value is not of the expected type
142:            static public final String CLASS_CAST_ERR = "### CLASS ###";
143:
144:            // Implies that a formula encounters an error when evaluated 
145:            static public final String EVALUATION_ERR = "### EVAL ###";
146:
147:            // Implies that a cell's formula depends directly or indirectly on itself
148:            static public final String CIRCULAR_REF_ERR = "### CIRC ###";
149:
150:            // Implies that a cell's formula encounted an unexpected null value when evaluated
151:            static public final String NULL_POINTER_ERR = "### NULL ###";
152:
153:            // Implies that a cell reference cannot be resolved
154:            static public final String REFERENCE_ERR = "### REF ###";
155:
156:            // Implies that a cell has been referenced before it is initialized
157:            static public final String UNDEFINED_ERR = "### UNDEF ###";
158:
159:            // Implies that a cell's formula cannot be parsed: nothing past the point in the
160:            // string representation of the formula where the parser exception was thrown has
161:            // been analyzed.
162:            static public final String PARSER_ERR = "### PARSE ###";
163:
164:            // The set of cells on which this cell depends.
165:            private Set<Cell> _dependencies = new HashSet<Cell>();
166:
167:            // TODO: move this into spreadsheet model (cell should only know about Generators:
168:            // it would be up to the model to parse string formulas and set the cell's
169:            // generator or error state)
170:
171:            /**
172:             * Builds a possibly editable cell at the given address, using the formula to build
173:             * a generator to retrieve the value.  
174:             */
175:            Cell(Spreadsheet parent, Point addr, String formula,
176:                    boolean editable) {
177:                if (formula == null || formula.trim().length() <= 0)
178:                    throw new IllegalArgumentException(
179:                            "Formula must be supplied");
180:
181:                // TODO: delete this temporary hack
182:                //         _type = Object.class;
183:
184:                _parent = parent;
185:                _addr = addr;
186:                _editable = editable;
187:                setFormula(formula);
188:
189:                //         if (isValid())
190:                //             _type = getParser().getReturnType();
191:
192:                _renderer = new Renderer(); //GenericTableCellRenderer();
193:            }
194:
195:            /**
196:             * Builds a read-only cell at the given address, using the generator to retrieve the
197:             * value. 
198:             */
199:            <T> Cell(Spreadsheet parent, Class<T> type, Point addr,
200:                    Generator<T> value) {
201:                _parent = parent;
202:                //         _type = type;
203:                _addr = addr;
204:                _editable = false;
205:                _renderer = new Renderer(); // GenericTableCellRenderer();
206:
207:                setFormulaImpl(value);
208:            }
209:
210:            Cell(Spreadsheet parent, int row, int col) {
211:                _parent = parent;
212:                _addr = new Point(row, col);
213:                _editable = true;
214:                _errMsg = UNDEFINED_ERR;
215:                //         _type = parent.getDefaultType();
216:                _value = parent.getDefaultCellValue();
217:            }
218:
219:            Spreadsheet getParent() {
220:                return _parent;
221:            }
222:
223:            private Spreadsheet.Parser getParser() {
224:                return _parent._parser;
225:            }
226:
227:            public String getName() {
228:                return _name;
229:            }
230:
231:            void setName(String name) {
232:                _name = name;
233:            }
234:
235:            /**
236:             * Returns the type of values held by the cell.
237:             */
238:            //     public Class getType() { return _type; }
239:            public Class getType() {
240:                return _value == null ? Object.class : _value.getClass();
241:            }
242:
243:            /**
244:             * Returns the formula that describes the cell's contents.
245:             */
246:            String getFormula() {
247:                return _formula;
248:            }
249:
250:            /**
251:             * Returns true if the cell is editable, false if it is read-only.
252:             */
253:            public boolean isEditable() {
254:                return _editable;
255:            }
256:
257:            /**
258:             * Sets the cell as editable (or not).
259:             */
260:            public void setEditable(boolean b) {
261:                _editable = b;
262:            }
263:
264:            /**
265:             * Returns the address of the cell.
266:             */
267:            public Point getAddress() {
268:                return _addr;
269:            }
270:
271:            /**
272:             * Returns the renderer used to paint the cell
273:             */
274:            public TableCellRenderer getRenderer() {
275:                return _renderer;
276:            }
277:
278:            /**
279:             * Sets the component used to paint the cell
280:             */
281:            public void setRenderer(TableCellRenderer renderer) {
282:                _renderer = renderer;
283:            }
284:
285:            /**
286:             * Returns the component used to edit the cell
287:             */
288:            public TableCellEditor getEditor() {
289:                if (_editor == null)
290:                    _editor = new Editor();
291:
292:                return _editor;
293:            }
294:
295:            /**
296:             * Sets the component used to edit the cell
297:             */
298:            public void setEditor(TableCellEditor editor) {
299:                _editor = editor;
300:            }
301:
302:            /**
303:             * Returns true if the cell's value can be retrieved without error
304:             */
305:            public boolean isValid() {
306:                return _errMsg == null;
307:            }
308:
309:            // TODO: fix this: it's bad to use _errMsg in this way, as the first thing
310:            // that setFormula does is clear this information.  (It might be OK, but if
311:            // so, its more of an accident than anything)
312:
313:            /**
314:             * Returns true if the cell's value is undefined
315:             */
316:            public boolean isUndefined() {
317:                return _errMsg == UNDEFINED_ERR;
318:            }
319:
320:            /**
321:             * Returns the textual description of the last error associated with cell.
322:             * The string will be used by the UI.  If the cell's value can be retrieved
323:             * without error, then this field will be null.
324:             */
325:            public String getErrorMsg() {
326:                return _errMsg;
327:            }
328:
329:            /**
330:             * Puts the cell into the error display mode: the invalid formula is preserved
331:             * as a string, and the error message is set
332:             */
333:            private void setError(Throwable t, String formula, String msg) {
334:                Logger.global.log(Level.FINE, formula, t);
335:                _exception = t;
336:                _parent.setStatus(t.getMessage());
337:
338:                //         _type = String.class;
339:                _formula = formula;
340:                _errMsg = msg;
341:
342:                _value = t;
343:                notifyObservers();
344:            }
345:
346:            /**
347:             * Puts the cell into the standard mode.
348:             */
349:            private void clearError() {
350:                _exception = null;
351:                _errMsg = null;
352:            }
353:
354:            /**
355:             * Returns the value of the cell.  If an exception is caught while
356:             * evaluating the cell, then this will return null and the getErrorMsg()
357:             * method will return a description of the problem.
358:             */
359:            public Object getValue() {
360:                return _value;
361:            }
362:
363:            /**
364:             * Evaluates the cell's formula and caches the result.  This can cause the cell to enter
365:             * an error state, if the forumula throws one of several exceptions.
366:             */
367:            private void setValue() {
368:                try {
369:                    _value = _generator.gen();
370:                    clearError();
371:                } catch (CircularReferenceException x) {
372:                    setError(x, _formula, CIRCULAR_REF_ERR);
373:                } catch (InvalidReferenceException x) {
374:                    recover(x, _formula, REFERENCE_ERR);
375:                } catch (NullPointerException x) {
376:                    setError(x, _formula, NULL_POINTER_ERR);
377:                } catch (ClassCastException x) {
378:                    recover(x, _formula, CLASS_CAST_ERR);
379:                } catch (EvaluationException x) {
380:                    recover(x, _formula, EVALUATION_ERR);
381:                } catch (IllegalArgumentException x) {
382:                    recover(x, _formula, EVALUATION_ERR);
383:                } catch (Exception x) {
384:                    setError(x, _formula, EVALUATION_ERR);
385:                }
386:            }
387:
388:            /**
389:             * Clears the contents of the cell, setting to the default type and value.
390:             */
391:
392:            public void clear() {
393:                doClear(null, _parent.getDefaultCellValue());
394:            }
395:
396:            /**
397:             * Clears the contents of the cell, and sets its state to an invalid state to
398:             * force all dependant cells to reparse.
399:             */
400:
401:            void unlink() {
402:                doClear(REFERENCE_ERR, new InvalidReferenceException("Cell("
403:                        + _addr.x + "," + _addr.y + ")"));
404:            }
405:
406:            private void doClear(String msg, Object value) {
407:                unregister();
408:
409:                _editable = true;
410:                //         _type = parent.getDefaultType();
411:                _value = value;
412:                _generator = null;
413:                _formula = null;
414:                _errMsg = msg;
415:
416:                notifyObservers();
417:            }
418:
419:            /**
420:             * Sets the contents of the cell to the given value.  
421:             */
422:            public final void setValue(Object value) {
423:                if (value instanceof  Generator)
424:                    setFormula((Generator) value);
425:
426:                // If the value we receive is the current exception, then we're at the end
427:                // of an editing process that went bad.  The Editor has set the cell's state
428:                // to reflect the error, and we don't want to undo that here.
429:                else if (value != _exception)
430:                    setFormula(new Constant(value));
431:            }
432:
433:            /**
434:             * Sets the contents of the cell to the given formula.
435:             */
436:            public final void setFormula(String formula)
437:                    throws CircularReferenceException {
438:                if (formula == null || "".equals(formula)) {
439:                    clear();
440:                    return;
441:                }
442:
443:                if (formula.startsWith("="))
444:                    formula = formula.substring(1);
445:
446:                try {
447:                    Generator gen = getParser().parseGenerator(this , formula);
448:                    //             _type = getParser().getReturnType();
449:                    setFormula(gen);
450:                    _formula = formula;
451:                } catch (ParseException x) {
452:                    setError(x, formula, PARSER_ERR);
453:                } catch (ClassCastException x) {
454:                    recover(x, formula, CLASS_CAST_ERR);
455:                } catch (NullPointerException x) {
456:                    setError(x, formula, NULL_POINTER_ERR);
457:                }
458:            }
459:
460:            // TODO: define a version of setFormula that the spreadsheet to use: it must do
461:            // all of this and also set the _formula member to something meaningful
462:
463:            /**
464:             * Sets the contents of the cell to the given formula, notifying all observers of
465:             * the change.
466:             */
467:            public final void setFormula(Generator formula) {
468:                clearError();
469:                unregister();
470:                setFormulaImpl(formula);
471:                notifyObservers();
472:            }
473:
474:            /**
475:             * Checks the given formula to prevent circular dependencies, and sets the contents of the
476:             * cell to the given formula.  A circular reference causes the cell to enter an error state,
477:             * and its old value will be retained.
478:             */
479:            private void setFormulaImpl(Generator formula) {
480:                try {
481:                    _generator = register(formula);
482:                    setValue();
483:                } catch (CircularReferenceException x) {
484:                    setError(x, formula.toString(), CIRCULAR_REF_ERR);
485:                }
486:            }
487:
488:            /**
489:             * Attempts one recovery from the given exception.  The formula stored in the cell
490:             * is reparsed, to allow recovery in cases where there is a type mismatch between the
491:             * old formula functor and new values in input cells.
492:             */
493:            synchronized private void recover(Exception x, String formula,
494:                    String msg) {
495:                if (_inRecovery) {
496:                    setError(x, formula, msg);
497:                } else {
498:                    _inRecovery = true;
499:                    setFormula(_formula);
500:                    if (!isValid() && _errMsg.equals(PARSER_ERR)) {
501:                        setError(x, formula, msg);
502:                    }
503:
504:                    _inRecovery = false;
505:                }
506:            }
507:
508:            // guards against re-entering the recover method
509:            private boolean _inRecovery = false;
510:
511:            /**
512:             * Sets the format of the cell, if formatting is supported by the cell's
513:             * renderer.  If formatting is not supported, invoking this method will
514:             * have no effect.
515:             */
516:            public <T> void setFormat(UnaryFunctor<T, String> formatter) {
517:                if (_renderer instanceof  Formattable)
518:                    ((Formattable) _renderer).setFormat(formatter);
519:            }
520:
521:            /**
522:             * Returns a reference to the cell's formula.  
523:             */
524:            public Generator getReference() {
525:                return new CellReference(this );
526:            }
527:
528:            /**
529:             * Returns true if this cell references the given cell, either directly or
530:             * indirectly.  Also returns true if this cell <i>is</i> the given cell.
531:             */
532:            public boolean references(Cell c) {
533:                if (getAddress().equals(c.getAddress())) {
534:                    return true;
535:                }
536:
537:                for (Cell c1 : _dependencies) {
538:                    if (c1 == c) {
539:                        return true;
540:                    }
541:                    if (c1.references(c)) {
542:                        return true;
543:                    }
544:                }
545:
546:                return false;
547:            }
548:
549:            /**
550:             * returns an iterator over all cells on which this cell directly depends
551:             */
552:            public final Iterator<Cell> dependsOn() {
553:                return _dependencies.iterator();
554:            }
555:
556:            public String toString() {
557:                StringBuffer buf = new StringBuffer(256);
558:                buf.append("Cell(").append(_addr.x).append(",").append(_addr.y)
559:                        .append(") ");
560:                if (_name != null) {
561:                    buf.append('"').append(_name).append('"').append(' ');
562:                }
563:                buf.append("[");
564:                if (_exception != null)
565:                    buf.append(_exception.getMessage());
566:                else if (_formula != null)
567:                    buf.append(_formula);
568:                else
569:                    buf.append(_value);
570:
571:                return buf.append("]").toString();
572:            }
573:
574:            // - - - - - - - - - - - -
575:            // Observer Interface
576:            // - - - - - - - - - - - -
577:
578:            public void update(Observable observable, Object object) {
579:                setValue();
580:                notifyObservers();
581:            }
582:
583:            /**
584:             * Triggers cells (and other observers) that this cell's contents have been
585:             * changed.
586:             */
587:            public void notifyObservers() {
588:                setChanged();
589:                notifyObservers(_value);
590:                clearChanged();
591:            }
592:
593:            // - - - - - - - - - - - -
594:            // Registration details
595:            // - - - - - - - - - - - -
596:
597:            // Examines the current value generator, adding this as an observer to
598:            // any cells on which this depends
599:            private <T> Generator<T> register(Generator<T> formula)
600:                    throws CircularReferenceException {
601:                formula.accept(new RegistrationVisitor());
602:                return formula;
603:            }
604:
605:            // Examines the current value generator, removing this as an observer to
606:            // any cells on which this depends.
607:            private void unregister() {
608:                if (_generator != null)
609:                    _generator.accept(new UnregistrationVisitor());
610:
611:                _dependencies.clear();
612:            }
613:
614:            private class RegistrationVisitor extends AdaptorVisitor implements 
615:                    CellReference.Visitor {
616:                public void visit(CellReference host) {
617:                    Cell hostCell = host.getCell();
618:
619:                    // check for circular references
620:                    if (hostCell.references(Cell.this ))
621:                        throw new CircularReferenceException();
622:
623:                    host.register(Cell.this );
624:                    _dependencies.add(hostCell);
625:                }
626:            }
627:
628:            private class UnregistrationVisitor extends AdaptorVisitor
629:                    implements  CellReference.Visitor {
630:                public void visit(CellReference host) {
631:                    host.unregister(Cell.this );
632:                }
633:            }
634:
635:            // - - - - - - - - - - -
636:            // Editor class
637:            // - - - - - - - - - - -
638:
639:            static class Editor extends DefaultCellEditor {
640:
641:                static final long serialVersionUID = -9010644547311806213L;
642:
643:                private Spreadsheet _sheet;
644:                private Cell _cell;
645:
646:                public Editor() {
647:                    super (new JTextField());
648:                }
649:
650:                public Object getCellEditorValue() {
651:                    // The superclass' editorComponent is the textField we passed at construction
652:                    // the super class returns the text fields contents.  we'll parse it and pass
653:                    // the result
654:                    String formula = (String) super .getCellEditorValue();
655:                    if (formula.startsWith("="))
656:                        formula = formula.substring(1);
657:
658:                    try {
659:                        return _sheet._parser.parseGenerator(_cell, formula);
660:                    } catch (ParseException x) {
661:                        _cell.setError(x, formula, PARSER_ERR);
662:                        return x;
663:                    }
664:                }
665:
666:                public Component getTableCellEditorComponent(JTable table,
667:                        Object value, boolean isSelected, int row, int col) {
668:                    _sheet = (Spreadsheet) table;
669:                    _cell = _sheet.getCellAt(row, col);
670:                    return super .getTableCellEditorComponent(table,
671:                            _cell._formula, isSelected, row, col);
672:                }
673:            }
674:
675:            // - - - - - - - - - - -
676:            // Renderer class
677:            // - - - - - - - - - - -
678:
679:            static class Renderer extends GenericTableCellRenderer {
680:
681:                public Component getTableCellRendererComponent(JTable table,
682:                        Object value, boolean isSelected, boolean hasFocus,
683:                        int row, int column) {
684:                    Spreadsheet sheet = (Spreadsheet) table;
685:                    Cell cell = sheet.getCellIfPresent(row, column);
686:                    boolean editable = (cell != null) ? cell.isEditable()
687:                            : sheet.isEditableByDefault();
688:                    return super .getTableCellRendererComponent(table, value,
689:                            isSelected && editable, hasFocus && editable, row,
690:                            column);
691:                }
692:            }
693:        }
694:
695:        // - - - - - - - - - - -
696:        // Cell Reference class
697:        // - - - - - - - - - - -
698:
699:        class CellReference extends Generator {
700:
701:            static final long serialVersionUID = -2552950462394369940L;
702:
703:            private Cell _cell;
704:
705:            public CellReference(Cell cell) {
706:                _cell = cell;
707:            }
708:
709:            public Object gen() {
710:                Object obj = _cell.getValue();
711:                if (obj instanceof  RuntimeException)
712:                    throw (RuntimeException) obj;
713:
714:                return obj;
715:            }
716:
717:            public Cell getCell() {
718:                return _cell;
719:            }
720:
721:            public void register(Observer obs) {
722:                _cell.addObserver(obs);
723:            }
724:
725:            public void unregister(Observer obs) {
726:                _cell.deleteObserver(obs);
727:            }
728:
729:            public String toString() {
730:                return "CellReference(" + _cell + ")";
731:            }
732:
733:            public void accept(net.sf.jga.fn.Visitor v) {
734:                if (v instanceof  CellReference.Visitor)
735:                    ((CellReference.Visitor) v).visit(this );
736:                else
737:                    v.visit(this );
738:            }
739:
740:            public interface Visitor extends net.sf.jga.fn.Visitor {
741:                public void visit(CellReference host);
742:            }
743:        }
744:
745:        class CircularReferenceException extends RuntimeException {
746:            static final long serialVersionUID = -8670923266092229864L;
747:
748:            public String getMessage() {
749:                return "Circular Reference";
750:            }
751:        }
752:
753:        class InvalidReferenceException extends RuntimeException {
754:            public InvalidReferenceException(String msg) {
755:                super(msg);
756:            }
757:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.