Source Code Cross Referenced for ConsoleBuffer.java in  » Scripting » oscript-2.10.4 » ti » swing » console » 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 » Scripting » oscript 2.10.4 » ti.swing.console 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*=============================================================================
002:         *     Copyright Texas Instruments, Inc., 2002.  All Rights Reserved.
003:         * 
004:         *  This program is free software; you can redistribute it and/or modify
005:         *  it under the terms of the GNU General Public License as published by
006:         *  the Free Software Foundation; either version 2 of the License, or
007:         *  (at your option) any later version.
008:         * 
009:         *  This program is distributed in the hope that it will be useful,
010:         *  but WITHOUT ANY WARRANTY; without even the implied warranty of
011:         *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012:         *  GNU General Public License for more details.
013:         * 
014:         *  You should have received a copy of the GNU General Public License
015:         *  along with this program; if not, write to the Free Software
016:         *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
017:         */
018:
019:        package ti.swing.console;
020:
021:        import ti.exceptions.ProgrammingErrorException;
022:
023:        import java.awt.Graphics;
024:        import java.awt.Image;
025:        import java.awt.Point;
026:        import java.awt.Rectangle;
027:        import java.util.Iterator;
028:        import java.util.LinkedList;
029:        import java.util.TreeSet;
030:        import java.util.Comparator;
031:        import java.util.Vector;
032:
033:        /**
034:         * The console-buffer is the actual "core" of the console, leaving all the
035:         * details of being a swing component (resizing, scrollbar, etc.) to the
036:         * public class {@link Console}.  All synchronization happens here, for 
037:         * modifying the state of the buffer, and rendering the buffer.
038:         * <p>
039:         * This really could be an inner-class, as it is "owned" by the console that
040:         * creates it, but that one file would be too big.
041:         * 
042:         * @author Rob Clark
043:         * @version 0.0
044:         */
045:        class ConsoleBuffer implements  InputHandler,
046:                java.awt.image.ImageObserver, java.io.Serializable {
047:            /**
048:             * Number of rows.
049:             */
050:            private int nrows;
051:
052:            /**
053:             * Number of colums.
054:             */
055:            private int ncols;
056:
057:            /**
058:             * The set of rows is a circular buffer, and <code>lastRow</code> is the
059:             * index of the last row in the "unwrapped" buffer.
060:             */
061:            private int lastRow = 0;
062:            private Row[] rows;
063:
064:            /**
065:             * Because the buffer might be locked by the time a repaint event is
066:             * handled, but the paintBuffer() method can't just do nothing (or the
067:             * console will flicker), when the console is locked we just repaint
068:             * the last thing we painted to screen.  While the console is locked,
069:             * the offscreen isn't touched, so this is safe.  But, since the
070:             * <code>lastRow</code> might have changed, we need to snapshot it
071:             * every time the offscreen is refreshed.
072:             * <p>
073:             * A repaint() is triggered whenever the buffer is unlock()'d, so
074:             * just redrawing the last thing is a safe thing to do.
075:             */
076:            private int lastRowAtRefresh = 0;
077:
078:            private Console console;
079:
080:            private static final String EOL = System.getProperty(
081:                    "line.separator", "\n");
082:
083:            /**
084:             * Class Constructor.
085:             */
086:            ConsoleBuffer(Console console, int nrows, int ncols) {
087:                this .console = console;
088:
089:                this .nrows = nrows;
090:                this .ncols = ncols;
091:
092:                rows = new Row[nrows];
093:                for (int i = 0; i < nrows; i++)
094:                    rows[i] = new Row(0);
095:            }
096:
097:            /**
098:             * Get the number of rows in the buffer.
099:             * 
100:             * @return number of rows
101:             */
102:            int getRowCount() {
103:                return nrows;
104:            }
105:
106:            /**
107:             * Get the number of columns in the buffer.
108:             * 
109:             * @return number of columns
110:             */
111:            int getColumnCount() {
112:                return ncols;
113:            }
114:
115:            /**
116:             * Set the number of rows in the buffer.
117:             * 
118:             * @param nrows        number of rows
119:             */
120:            void setRowCount(int nrows) {
121:                throw new ProgrammingErrorException("unimplemented");
122:            }
123:
124:            /**
125:             * Set the number of columns in the buffer.
126:             * 
127:             * @param ncols        number of columns
128:             */
129:            synchronized void setColumnCount(int ncols) {
130:                ncols = Math.max(1, ncols);
131:
132:                if (this .ncols != ncols) {
133:                    this .ncols = ncols;
134:
135:                    if (offScreen != null)
136:                        offScreen.flush();
137:
138:                    offScreen = null;
139:
140:                    for (int i = 0; i < nrows; i++)
141:                        rows[i].markDirty();
142:                }
143:            }
144:
145:            /**
146:             * Convert the specified row/column coordinate to an offset into the 
147:             * character stream.
148:             * 
149:             * @param row          row coordinate
150:             * @param col          column coordinate
151:             * @return offset into document stream
152:             */
153:            int toOffset(int row, int col) {
154:                int actualRow = (lastRow + 1 + row) % nrows;
155:
156:                if ((actualRow < 0) || (actualRow >= rows.length))
157:                    return -1;
158:
159:                int actualCol = Math.min(col, rows[actualRow].getLength());
160:
161:                return rows[actualRow].getOffset() + actualCol;
162:            }
163:
164:            /**
165:             * Convert the specified offset into a row/column coordinate.  The
166:             * x value of the returned point is the column, and the y value is
167:             * the row.
168:             * 
169:             * @param offset       the offset into document stream
170:             * @return the row/col coordinate
171:             */
172:            Point toPoint(int offset) {
173:                // deal with offset >= end of character stream:
174:                if (offset >= (rows[lastRow].getOffset() + rows[lastRow]
175:                        .getLength()))
176:                    return new Point(rows[lastRow].getLength(), nrows - 1);
177:
178:                // start search from bottom of document, because this is used to
179:                // determine cursor position, and the cursor is usually (always?)
180:                // near the end of the document:
181:
182:                for (int i = 0; i < nrows; i++) {
183:                    int idx = (lastRow - i + nrows) % nrows;
184:
185:                    int rowOffset = rows[idx].getOffset();
186:                    int rowLength = rows[idx].getLength();
187:
188:                    if ((offset >= rowOffset)
189:                            && (offset < (rowOffset + rowLength))) {
190:                        int row = nrows - i - 1;
191:                        int col = offset - rowOffset;
192:
193:                        return new Point(col, row);
194:                    }
195:                }
196:
197:                // offset must have scrolled off the top:
198:                return new Point(0, 0);
199:            }
200:
201:            /**
202:             * Append characters to the end of the character stream.
203:             * 
204:             * @param cbuf         the character buffer
205:             * @param off          the offset into cbuf to first character to append
206:             * @param len          the number of characters to append
207:             */
208:            public synchronized void append(char[] cbuf, int off, int len) {
209:                if ((off + len) > cbuf.length)
210:                    throw new ProgrammingErrorException("bad args");
211:
212:                int consumed = 0;
213:
214:                while (consumed < len) {
215:                    boolean lf = false;
216:                    boolean wrap = false;
217:
218:                    int n = ncols - rows[lastRow].getLength(); // max chars to fit in row
219:
220:                    // n could be negative if ncols is changed
221:                    n = Math.max(0, Math.min(n, len - consumed));
222:
223:                    for (int i = 0; i < n; i++) {
224:                        if (cbuf[off + consumed + i] == Console.LF) {
225:                            n = i;
226:                            lf = true;
227:                            break;
228:                        }
229:                    }
230:
231:                    rows[lastRow].append(cbuf, off + consumed, n);
232:                    consumed += n;
233:
234:                    if (rows[lastRow].getLength() >= ncols)
235:                        wrap = true;
236:
237:                    if (lf || wrap) {
238:                        // if LF, consume '\n' char
239:                        if (lf)
240:                            consumed++;
241:
242:                        int offset = (rows[lastRow].getOffset() + rows[lastRow]
243:                                .getLength());
244:
245:                        lastRow = (lastRow + 1) % nrows;
246:                        rows[lastRow] = new Row(offset);
247:
248:                        // remove regions where (region.end < rows[firstRow].getOffset())
249:                        int firstRow = (lastRow + 1) % nrows;
250:                        int firstOffset = rows[firstRow].getOffset();
251:
252:                        Vector regionsToRemove = null; // we can't remove while iterating
253:                        Iterator itr = pointSet.iterator();
254:                        while (itr.hasNext()) {
255:                            RegionPoint rp = (RegionPoint) (itr.next());
256:
257:                            if (rp.getOffset() >= firstOffset)
258:                                break;
259:
260:                            if (rp instanceof  EndRegionPoint) {
261:                                if (regionsToRemove == null)
262:                                    regionsToRemove = new Vector();
263:                                regionsToRemove.addElement(rp.getRegion());
264:                            }
265:                        }
266:
267:                        if (regionsToRemove != null)
268:                            for (int i = 0; i < regionsToRemove.size(); i++)
269:                                removeRegionImpl((Region) (regionsToRemove
270:                                        .elementAt(i)));
271:                    }
272:                }
273:
274:                refresh();
275:            }
276:
277:            /**
278:             * Delete characters from end of character stream.
279:             * 
280:             * @param num          the number of characters to delete
281:             */
282:            public synchronized void zap(int num) {
283:                // used to avoid infinite loop in case of zap'ing too many chars:
284:                int watchdog = nrows;
285:
286:                while ((num > 0) && (watchdog > 0)) {
287:                    int n = Math.min(num, rows[lastRow].getLength());
288:
289:                    rows[lastRow].zap(n);
290:
291:                    if (rows[lastRow].getLength() == 0)
292:                        lastRow = (lastRow + nrows - 1) % nrows;
293:
294:                    num -= n;
295:
296:                    watchdog--;
297:                }
298:
299:                refresh();
300:            }
301:
302:            /**
303:             * Get the current offset of the last character in the character stream.
304:             * 
305:             * @return an offset
306:             */
307:            public synchronized int getOffset() {
308:                return rows[lastRow].getOffset() + rows[lastRow].getLength();
309:            }
310:
311:            /**
312:             * Get the data within the specified region.  If the requested region has
313:             * scrolled past the top of the buffer, the returned data may be truncated.
314:             * 
315:             * @param offset       the begining of the range
316:             * @param len          the length of the range in characters
317:             * @return the data
318:             */
319:            public synchronized char[] getData(int offset, int len) {
320:                // offset and len may be invalid, so fix that first:   ///////
321:                {
322:                    int beg = rows[((2 * lastRow) + 1) % nrows].getOffset();
323:                    int end = getOffset();
324:                    offset = Math.max(offset, beg);
325:                    len = Math.min(len, end - beg);
326:                }
327:                //////////////////////////////////////////////////////////////
328:
329:                int end = offset + len;
330:
331:                StringBuffer sb = new StringBuffer(len);
332:
333:                for (int i = 0; i < nrows; i++) {
334:                    int idx = (lastRow + i + 1) % nrows;
335:
336:                    int rowOffset = rows[idx].getOffset();
337:                    int rowLength = rows[idx].getLength();
338:                    int rowEnd = rowOffset + rowLength;
339:
340:                    if ((offset < rowEnd) && (end > rowOffset)) {
341:                        String str = rows[idx].getData();
342:
343:                        int a = Math.max(offset, rowOffset);
344:                        int b = Math.min(end, rowEnd);
345:
346:                        sb.append(str.toCharArray(), a - rowOffset, b - a);
347:
348:                        if (end > rowEnd)
349:                            sb.append(EOL);
350:                    }
351:                }
352:
353:                return sb.toString().toCharArray();
354:            }
355:
356:            /**
357:             * Close method 
358:             */
359:            public void close() {
360:                /* no-op */
361:            }
362:
363:            /*=======================================================================*/
364:            // sorted list of points is walked thru as we refresh()
365:            private TreeSet pointSet = new TreeSet(new RegionPointComparator());
366:
367:            private static class RegionPointComparator implements  Comparator,
368:                    java.io.Serializable {
369:                public int compare(Object o1, Object o2) {
370:                    return ((RegionPoint) o1).compareTo((RegionPoint) o2);
371:                }
372:            }
373:
374:            /**
375:             * Add a region mapped over a section of character stream.  If the section
376:             * of the character stream over which the region is mapped has scrolled off
377:             * the top of the fixed size row buffer, the region will be automatically
378:             * removed.
379:             * 
380:             * @param r            region to add
381:             * @see #removeRegion
382:             */
383:            public synchronized void addRegion(Region r) {
384:                if (r.getStart() < r.getEnd()) {
385:                    pointSet.add(new StartRegionPoint(r));
386:                    pointSet.add(new EndRegionPoint(r));
387:                    markDirty(r.getStart(), r.getEnd());
388:                    refresh();
389:                }
390:            }
391:
392:            /**
393:             * Remove a region.
394:             * 
395:             * @param r            region to remove
396:             * @see #addRegion
397:             */
398:            public synchronized void removeRegion(Region r) {
399:                if (r.getStart() < r.getEnd()) {
400:                    removeRegionImpl(r);
401:                    markDirty(r.getStart(), r.getEnd());
402:                    refresh();
403:                }
404:            }
405:
406:            private final void removeRegionImpl(Region r) // remove region, but does not trigger 
407:            { // a refresh(), or markDirty()
408:                pointSet.remove(new StartRegionPoint(r));
409:                pointSet.remove(new EndRegionPoint(r));
410:            }
411:
412:            /**
413:             * Given a <code>start</code> and <code>end</code> offsets, mark the rows
414:             * that contain parts of the specified region as needing to be rerendered.
415:             */
416:            private final void markDirty(int start, int end) {
417:                // the common case is that the region being added/removed is at or near
418:                // the end of the buffer, so work backwards from the end of the buffer,
419:                // and bail out once we are past the start of the specified region
420:                for (int i = 0; i < nrows; i++) {
421:                    int idx = (lastRow + nrows - i) % nrows;
422:                    int rowStart = rows[idx].getOffset();
423:                    int rowEnd = rowStart + rows[idx].getLength();
424:
425:                    if ((start <= rowEnd) && (end >= rowStart))
426:                        rows[idx].markDirty();
427:
428:                    if (rowStart <= start)
429:                        break;
430:                }
431:            }
432:
433:            /**
434:             * Get an object on which to synchronize access to the buffer
435:             * 
436:             * @return an object suitable for synchronizing buffer access
437:             * @see #getRegions
438:             */
439:            public Object getBufferLock() {
440:                return this ;
441:            }
442:
443:            /**
444:             * Get an iterator of the regions containing the specified range.  Access
445:             * to the iterator must be synchronized on the buffer-lock, to prevent 
446:             * concurrent modification problems.  For example:
447:             * <pre>
448:             *   synchronized( ih.getBufferLock() )
449:             *   {
450:             *     for( Iterator itr=ih.getRegions( off, len ); itr.hasNext(); )
451:             *     {
452:             *       ...
453:             *     }
454:             *   }
455:             * </pre>
456:             * 
457:             * @param offset       the begining of the range
458:             * @param len          the length of the range in characters
459:             * @return an iterator of {@link Region}
460:             * @see #getBufferLock
461:             */
462:            public Iterator getRegions(int offset, int len) {
463:                return new RegionIterator(pointSet.iterator(), offset, len);
464:            }
465:
466:            private static class RegionIterator implements  Iterator {
467:                private Iterator itr;
468:                private int start;
469:                private int end;
470:                private Object next;
471:
472:                RegionIterator(Iterator itr, int offset, int len) {
473:                    this .itr = itr;
474:                    this .start = offset;
475:                    this .end = offset + len;
476:                    update();
477:                }
478:
479:                public boolean hasNext() {
480:                    return next != null;
481:                }
482:
483:                public Object next() {
484:                    if (next == null)
485:                        throw new java.util.NoSuchElementException();
486:                    Object obj = next;
487:                    update();
488:                    return obj;
489:                }
490:
491:                public void remove() {
492:                    throw new UnsupportedOperationException("remove");
493:                }
494:
495:                private void update() {
496:                    next = null;
497:                    while (itr.hasNext()) {
498:                        RegionPoint rp = (RegionPoint) (itr.next());
499:
500:                        // since there is both a StartRegionPoint and EndRegionPoint for
501:                        // each region, but we only want to see each Region once in the
502:                        // output, ignore the EndRegionPoint-s
503:                        if (rp instanceof  StartRegionPoint) {
504:                            Region r = rp.getRegion();
505:
506:                            if ((r.getStart() <= end) && (r.getEnd() >= start)) {
507:                                next = r;
508:                                break;
509:                            }
510:                        }
511:                    }
512:                }
513:            }
514:
515:            /*=======================================================================*/
516:            private int lockCnt = 0;
517:
518:            /**
519:             * Lock the console from repaints.  This can be used to batch multiple
520:             * updates ({@link #append}, {@link #zap}, {@link #addRegion}, 
521:             * {@link #removeRegion}) and only trigger a single repaint at the end.
522:             * 
523:             * @see #unlock
524:             */
525:            public synchronized void lock() {
526:                lockCnt++;
527:            }
528:
529:            /**
530:             * Unlock the console, rerendering if needed.
531:             * 
532:             * @see #lock
533:             */
534:            public synchronized void unlock() {
535:                if (--lockCnt == 0)
536:                    refresh();
537:            }
538:
539:            /**
540:             * Is the console locked from rerendering?
541:             * 
542:             * @return <code>true</code> if rerendering shouldn't happen yet
543:             */
544:            final boolean locked() {
545:                return lockCnt > 0;
546:            }
547:
548:            /*=======================================================================*/
549:            private transient Image offScreen = null;
550:
551:            /**
552:             * If not locked, trigger a repaint.
553:             */
554:            private final void refresh() {
555:                if (!locked()) {
556:                    javax.swing.SwingUtilities.invokeLater(new Runnable() {
557:                        public void run() {
558:                            console.repaint();
559:                        }
560:                    });
561:                }
562:            }
563:
564:            /**
565:             * The actual rerender of the offscreen buffer is done here... this should
566:             * only be called directly from paintBuffer(), and only if the buffer is
567:             * not locked().  Other code should call {@link #refresh}.
568:             */
569:            private void refreshOffscreenBuffer() {
570:                ConsoleGraphics g = new ConsoleGraphics(offScreen.getGraphics());
571:
572:                g.setFont(console.getFont());
573:
574:                int fontHeight = console.getRowHeight();
575:                int fontWidth = console.getColumnWidth();
576:
577:                Iterator itr = pointSet.iterator();
578:                RegionPoint p = null;
579:                int pOffset = 0;
580:
581:                for (int i = 0; i < nrows; i++) {
582:                    int rowNum = (lastRow + 1 + i) % nrows;
583:                    Row row = rows[rowNum];
584:                    String str = row.getData();
585:
586:                    int x = 0;
587:                    int y = rowNum * fontHeight;
588:
589:                    int offsetIntoRow = 0;
590:                    int rowOffset = row.getOffset();
591:                    int rowLength = row.getLength();
592:
593:                    // loop to handle all "segments" within a row:
594:                    while (offsetIntoRow < rowLength) {
595:                        if (p == null) {
596:                            if (itr.hasNext()) {
597:                                p = (RegionPoint) (itr.next());
598:                                pOffset = p.getOffset();
599:                            } else {
600:                                pOffset = Integer.MAX_VALUE;
601:                            }
602:                        }
603:
604:                        if (pOffset <= (rowOffset + offsetIntoRow)) {
605:                            p.handle(g);
606:                            p = null;
607:                            continue;
608:                        }
609:
610:                        // number of chars to draw:
611:                        int n = Math.min(rowLength, pOffset - rowOffset)
612:                                - offsetIntoRow;
613:
614:                        if (row.needsRedraw())
615:                            g.drawString(str.substring(offsetIntoRow,
616:                                    offsetIntoRow + n), x, y);
617:
618:                        offsetIntoRow += n;
619:                        x += fontWidth * n;
620:                    }
621:
622:                    // handle special case of region ending at last char in row:
623:                    if ((p != null) && (pOffset == (rowOffset + offsetIntoRow))) {
624:                        p.handle(g);
625:                        p = null;
626:                    }
627:
628:                    if (row.needsRedraw()) {
629:                        g.clearRect(x, y,
630:                                (fontWidth * (ncols - offsetIntoRow)),
631:                                fontHeight);
632:
633:                        row.markClean();
634:                    }
635:                }
636:
637:                if (p != null)
638:                    p.handle(g);
639:
640:                while (itr.hasNext())
641:                    ((RegionPoint) (itr.next())).handle(g);
642:            }
643:
644:            /**
645:             * Render the buffer into the provided graphics, starting at the origin.
646:             */
647:            synchronized void paintBuffer(Graphics g) {
648:                int fontHeight = console.getRowHeight();
649:                int fontWidth = console.getColumnWidth();
650:                int width = (fontWidth * ncols);
651:                int height = (fontHeight * nrows);
652:
653:                if (offScreen == null)
654:                    if ((width > 0) && (height > 0))
655:                        offScreen = console.createImage(width, height);
656:
657:                /* blit the offScreen in two parts, because it is a circular buffer... the 
658:                 * top half of the on-screen image starts potentially somewhere other than 
659:                 * the top of the off-screen, so we have to swap the two halves.
660:                 */
661:                if (offScreen != null) {
662:                    Rectangle clipRect = g.getClipBounds();
663:
664:                    if (!locked()) {
665:                        int firstRow = (lastRow + 1) % nrows;
666:                        int y1 = clipRect.y;
667:                        int y2 = y1 + clipRect.height;
668:
669:                        for (int i = 0; i < nrows; i++) {
670:                            int rowNum = (firstRow + i) % nrows;
671:                            int y = i * fontHeight;
672:                            rows[rowNum].setVisible((y1 <= (y + fontHeight))
673:                                    && (y <= y2));
674:                        }
675:
676:                        refreshOffscreenBuffer();
677:                        lastRowAtRefresh = lastRow;
678:                    }
679:
680:                    // top vs. bottom refer to on-screen:
681:                    int trow = (lastRowAtRefresh + 1) % nrows;
682:                    int th = (nrows - trow) * fontHeight; // height of top section
683:                    int bh = trow * fontHeight; // height of bottom section
684:
685:                    g.clearRect(clipRect.x, clipRect.y, clipRect.width,
686:                            clipRect.height);
687:
688:                    Image img;
689:                    //      if( console.isEnabled() )
690:                    img = offScreen;
691:                    //      else   // XXX for some reason the GrayFilter is causing a NPE deep within drawImage()
692:                    //        img = javax.swing.GrayFilter.createDisabledImage(offScreen);
693:
694:                    // draw top half:
695:                    g.drawImage(img, 0, 0, 0 + width, 0 + th, 0, bh, 0 + width,
696:                            bh + th, this );
697:
698:                    // draw bottom half:
699:                    g.drawImage(img, 0, th, 0 + width, th + bh, 0, 0,
700:                            0 + width, 0 + bh, this );
701:                }
702:            }
703:
704:            // called when image changes... we just ignore it..
705:            public boolean imageUpdate(Image img, int infoflags, int x, int y,
706:                    int width, int height) {
707:                return false;
708:            }
709:        }
710:
711:        /**
712:         * Kinda weird to extend number, but thats what NumericalSortingVisitor
713:         * wants... represents the start of end of a region.  FWIW, two regions
714:         * are equal (in the .equals() sense) iff the offsets are the same, and
715:         * the regions are the same.
716:         */
717:        abstract class RegionPoint {
718:            protected int offset;
719:            protected Region r;
720:            protected double adj; // a hack to make EndRegionPoint go before StartRegionPoint
721:
722:            protected RegionPoint(int offset, Region r, double adj) {
723:                this .offset = offset;
724:                this .r = r;
725:                this .adj = adj;
726:            }
727:
728:            public int hashCode() {
729:                return getOffset();
730:            }
731:
732:            public boolean equals(Object obj) {
733:                return ((obj instanceof  RegionPoint)
734:                        && (((RegionPoint) obj).offset == offset) && ((RegionPoint) obj).r
735:                        .equals(r));
736:            }
737:
738:            public int compareTo(RegionPoint rp) {
739:                // scale up difference to prevent truncation when cast to int...
740:                // (remember adj could be 0.1)
741:                int rc = (int) ((doubleValue() - rp.doubleValue()) * 10.0);
742:
743:                // if offset is the same, defer to the region's count, which
744:                // is a unique sequence number for each region.  This ensures
745:                // that there are never two points that are equal (unless, of
746:                // course, they are end points of the same region, in which
747:                // case rc != 0 because the region length >= 1)
748:                if (rc == 0)
749:                    rc = r.getCount() - rp.r.getCount();
750:
751:                return rc;
752:            }
753:
754:            public Region getRegion() {
755:                return r;
756:            }
757:
758:            public int getOffset() {
759:                return offset;
760:            }
761:
762:            public final double doubleValue() {
763:                return (double) getOffset() + adj;
764:            }
765:
766:            public abstract void handle(ConsoleGraphics g);
767:
768:            public String toString() {
769:                return "[" + getClass().getName() + ": region=" + getRegion()
770:                        + ", offset=" + getOffset() + "]";
771:            }
772:        }
773:
774:        class StartRegionPoint extends RegionPoint {
775:            StartRegionPoint(Region r) {
776:                super (r.getStart(), r, 0.1);
777:            }
778:
779:            public void handle(ConsoleGraphics g) {
780:                r.enter(g);
781:            }
782:        }
783:
784:        class EndRegionPoint extends RegionPoint {
785:            EndRegionPoint(Region r) {
786:                super (r.getEnd(), r, 0.0);
787:            }
788:
789:            public void handle(ConsoleGraphics g) {
790:                r.leave(g);
791:            }
792:        }
793:
794:        /*
795:         *   Local Variables:
796:         *   tab-width: 2
797:         *   indent-tabs-mode: nil
798:         *   mode: java
799:         *   c-indentation-style: java
800:         *   c-basic-offset: 2
801:         *   eval: (c-set-offset 'substatement-open '0)
802:         *   eval: (c-set-offset 'case-label '+)
803:         *   eval: (c-set-offset 'inclass '+)
804:         *   eval: (c-set-offset 'inline-open '0)
805:         *   End:
806:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.