Source Code Cross Referenced for OutputDocument.java in  » IDE-Netbeans » core » org » netbeans » core » output2 » 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 » IDE Netbeans » core » org.netbeans.core.output2 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:
042:        package org.netbeans.core.output2;
043:
044:        import java.util.logging.Level;
045:        import java.util.logging.Logger;
046:        import org.openide.util.Mutex;
047:        import javax.swing.*;
048:        import javax.swing.event.*;
049:        import javax.swing.text.*;
050:        import java.awt.event.ActionEvent;
051:        import java.awt.event.ActionListener;
052:        import java.util.ArrayList;
053:        import java.util.Iterator;
054:        import java.util.List;
055:        import org.netbeans.core.output2.ui.AbstractOutputPane;
056:        import org.openide.util.Exceptions;
057:
058:        /** An implementation of Document directly over a memory mapped file such that
059:         * no (or nearly no) memory copies are required to fetch data to display.
060:         *
061:         * @author  Tim Boudreau, Jesse Glick
062:         */
063:        public class OutputDocument implements  Document, Element,
064:                ChangeListener, ActionListener, Runnable {
065:            private List<DocumentListener> dlisteners = new ArrayList<DocumentListener>();
066:            private volatile Timer timer = null;
067:
068:            private OutWriter writer;
069:
070:            private StringBuffer inBuffer;
071:            private boolean lastInput;
072:            private AbstractOutputPane pane;
073:
074:            /** Creates a new instance of OutputDocument */
075:            OutputDocument(OutWriter writer) {
076:                if (Controller.LOG) {
077:                    Controller.log("Creating a Document for " + writer);
078:                }
079:                this .writer = writer;
080:                getLines().addChangeListener(this );
081:                inBuffer = new StringBuffer();
082:            }
083:
084:            //#119985
085:            public int getOutputLength() {
086:                return getLines().getCharCount();
087:            }
088:
089:            //#114290
090:            public void setPane(AbstractOutputPane pane) {
091:                this .pane = pane;
092:            }
093:
094:            /**
095:             * Destroy this OutputDocument and its backing storage.  The document should not be visible
096:             * in the UI when this method is called.
097:             */
098:            public void dispose() {
099:                if (Controller.LOG)
100:                    Controller
101:                            .log("Disposing document and backing storage for "
102:                                    + getLines().readLock());
103:                disposeQuietly();
104:                writer.dispose();
105:                writer = null;
106:            }
107:
108:            /**
109:             * Destory this OutputDocument, but not its backing storage.  The document should not be
110:             * visible in the UI when this method is called.
111:             */
112:            public void disposeQuietly() {
113:                if (timer != null) {
114:                    timer.stop();
115:                    timer = null;
116:                }
117:                dlisteners.clear();
118:                lastEvent = null;
119:                getLines().removeChangeListener(this );
120:            }
121:
122:            public synchronized void addDocumentListener(
123:                    DocumentListener documentListener) {
124:                dlisteners.add(documentListener);
125:                lastEvent = null;
126:            }
127:
128:            public void addUndoableEditListener(UndoableEditListener l) {
129:                //do nothing
130:            }
131:
132:            public Position createPosition(int offset)
133:                    throws BadLocationException {
134:                if (offset < 0
135:                        || offset > getLines().getCharCount()
136:                                + inBuffer.length()) {
137:                    throw new BadLocationException("Bad position", offset); //NOI18N
138:                }
139:                //TODO
140:                return new ODPosition(offset);
141:            }
142:
143:            public Element getDefaultRootElement() {
144:                return this ;
145:            }
146:
147:            public Position getEndPosition() {
148:                return new ODEndPosition();
149:            }
150:
151:            public int getLength() {
152:                return getLines().getCharCount() + inBuffer.length();
153:            }
154:
155:            public Object getProperty(Object obj) {
156:                return null;
157:            }
158:
159:            public Element[] getRootElements() {
160:                return new Element[] { this  };
161:            }
162:
163:            public Position getStartPosition() {
164:                return new ODStartPosition();
165:            }
166:
167:            public String getText(int offset, int length)
168:                    throws BadLocationException {
169:                if (offset < 0
170:                        || offset > getLines().getCharCount()
171:                                + inBuffer.length() || length < 0) {
172:                    throw new BadLocationException("Bad: " + offset + "," + //NOI18N
173:                            length, offset);
174:                }
175:                if (length == 0) {
176:                    return ""; //NOI18N
177:                }
178:                String result;
179:                synchronized (getLines().readLock()) {
180:                    int linesOffset = Math.min(getLines().getCharCount(),
181:                            offset);
182:                    int linesEnd = Math.min(getLines().getCharCount(), offset
183:                            + length);
184:                    result = getLines().getText(linesOffset, linesEnd);
185:                    if (offset + length > getLines().getCharCount()) {
186:                        int inEnd = offset + length - getLines().getCharCount();
187:                        result = result + inBuffer.substring(0, inEnd);
188:                    }
189:                }
190:                return result;
191:            }
192:
193:            private char[] reusableSubrange = new char[256];
194:
195:            public void getText(int offset, int length, Segment txt)
196:                    throws BadLocationException {
197:                if (length < 0) {
198:                    //document is empty
199:                    txt.array = new char[0];
200:                    txt.offset = 0;
201:                    txt.count = 0;
202:                    return;
203:                }
204:
205:                if (offset < 0) {
206:                    throw new BadLocationException("Negative offset", offset); //NOI18N
207:                }
208:                if (getLines().getLineCount() == 0) {
209:                    txt.array = new char[] { '\n' };
210:                    txt.offset = 0;
211:                    txt.count = 1;
212:                    return;
213:                }
214:                if (length > reusableSubrange.length) {
215:                    reusableSubrange = new char[length];
216:                }
217:                try {
218:                    synchronized (getLines().readLock()) {
219:                        int charCount = getLines().getCharCount();
220:                        int linesOffset = Math.min(charCount, offset);
221:                        int linesEnd = Math.min(charCount, offset + length);
222:                        char[] chars = getLines().getText(linesOffset,
223:                                linesEnd, reusableSubrange);
224:                        if (offset + length >= charCount) {
225:                            int inEnd = offset - charCount + length;
226:                            int inStart = Math.max(0, offset - charCount);
227:                            // calling Math.min to prevent nasty AOOBE wich seem to come out of nowhere..
228:                            inBuffer.getChars(Math.min(inStart, inBuffer
229:                                    .length()), Math.min(inEnd, inBuffer
230:                                    .length()), chars, linesEnd - linesOffset);
231:                        }
232:                        txt.array = chars;
233:                        txt.offset = 0;
234:                        txt.count = Math.min(length, chars.length);
235:                    }
236:                } catch (OutOfMemoryError error) {
237:                    //#50189 - try to salvage what we can
238:                    OutWriter.lowDiskSpace = true;
239:                    //mkleint: is not necessary low disk space, can also mean too many mapped buffers were requirested too fast..
240:                    //Sets the error flag and releases the storage
241:                    writer.dispose();
242:                    Logger.getAnonymousLogger().log(Level.WARNING,
243:                            "OOME while reading output.  Cleaning up.", //NOI18N
244:                            error);
245:                }
246:            }
247:
248:            public void insertString(int offset, String str,
249:                    AttributeSet attributeSet) throws BadLocationException {
250:                final int off = Math.max(offset, getLength()
251:                        - inBuffer.length());
252:                final int len = str.length();
253:                inBuffer.insert(off - (getLength() - inBuffer.length()), str);
254:                DocumentEvent ev = new DocumentEvent() {
255:                    public int getOffset() {
256:                        return off;
257:                    }
258:
259:                    public int getLength() {
260:                        return len;
261:                    }
262:
263:                    public Document getDocument() {
264:                        return OutputDocument.this ;
265:                    }
266:
267:                    public EventType getType() {
268:                        return EventType.INSERT;
269:                    }
270:
271:                    public ElementChange getChange(Element arg0) {
272:                        return null;
273:                    }
274:                };
275:                fireDocumentEvent(ev);
276:            }
277:
278:            public String sendLine() {
279:                final int off = getLength() - inBuffer.length();
280:                final int len = inBuffer.length();
281:                String toReturn = inBuffer.toString();
282:                inBuffer = new StringBuffer();
283:                DocumentEvent ev = new DocumentEvent() {
284:                    public int getOffset() {
285:                        return off;
286:                    }
287:
288:                    public int getLength() {
289:                        return len;
290:                    }
291:
292:                    public Document getDocument() {
293:                        return OutputDocument.this ;
294:                    }
295:
296:                    public EventType getType() {
297:                        return EventType.REMOVE;
298:                    }
299:
300:                    public ElementChange getChange(Element arg0) {
301:                        return null;
302:                    }
303:                };
304:                fireDocumentEvent(ev);
305:                return toReturn;
306:            }
307:
308:            public void putProperty(Object obj, Object obj1) {
309:                //do nothing
310:            }
311:
312:            public void remove(int offset, int length)
313:                    throws BadLocationException {
314:                int startOff = getLength() - inBuffer.length();
315:                final int off = Math.max(startOff, offset);
316:                final int len = Math.min(length, inBuffer.length());
317:                if (off - startOff + len <= getLength()) {
318:                    inBuffer.delete(off - startOff, off - startOff + len);
319:                    DocumentEvent ev = new DocumentEvent() {
320:                        public int getOffset() {
321:                            return off - len;
322:                        }
323:
324:                        public int getLength() {
325:                            return len;
326:                        }
327:
328:                        public Document getDocument() {
329:                            return OutputDocument.this ;
330:                        }
331:
332:                        public EventType getType() {
333:                            return EventType.REMOVE;
334:                        }
335:
336:                        public ElementChange getChange(Element arg0) {
337:                            return null;
338:                        }
339:                    };
340:                    fireDocumentEvent(ev);
341:                }
342:            }
343:
344:            public synchronized void removeDocumentListener(
345:                    DocumentListener documentListener) {
346:                dlisteners.remove(documentListener);
347:                lastEvent = null;
348:                if (dlisteners.isEmpty() && timer != null) {
349:                    timer.stop();
350:                    timer = null;
351:                }
352:            }
353:
354:            public Lines getLines() {
355:                //Unit test will check for null to determine if dispose succeeded
356:                return writer != null ? writer.getLines() : null;
357:            }
358:
359:            public int getLineStart(int line) {
360:                return getLines().getLineCount() > 0 ? getLines().getLineStart(
361:                        line) : 0;
362:            }
363:
364:            public int getLineEnd(int lineIndex) {
365:                if (getLines().getLineCount() == 0) {
366:                    return 0;
367:                }
368:                int endOffset;
369:                if (lineIndex >= getLines().getLineCount() - 1) {
370:                    endOffset = getLines().getCharCount() + inBuffer.length();
371:                } else {
372:                    endOffset = getLines().getLineStart(lineIndex + 1);
373:                }
374:                return endOffset;
375:            }
376:
377:            public void removeUndoableEditListener(
378:                    UndoableEditListener undoableEditListener) {
379:                //do nothing
380:            }
381:
382:            public void render(Runnable runnable) {
383:                getElementCount(); //Force a refresh of lastPostedLine
384:                runnable.run();
385:            }
386:
387:            public AttributeSet getAttributes() {
388:                return SimpleAttributeSet.EMPTY;
389:            }
390:
391:            public Document getDocument() {
392:                return this ;
393:            }
394:
395:            public Element getElement(int index) {
396:                //Thanks to Mila Metelka for pointing out that Swing documents always
397:                //are expected to have a trailing empty element
398:                if (getLines().getLineCount() == 0) {
399:                    return new EmptyElement(OutputDocument.this );
400:                }
401:                synchronized (getLines().readLock()) {
402:                    if (index > lastPostedLine) {
403:                        lastPostedLine = index;
404:                    }
405:                }
406:                return new ODElement(index);
407:            }
408:
409:            public int getElementCount() {
410:                int result;
411:                synchronized (getLines().readLock()) {
412:                    result = getLines().getLineCount();
413:                    lastPostedLine = result;
414:                }
415:                if (result == 0) {
416:                    result = 1;
417:                }
418:                return result;
419:            }
420:
421:            public int getElementIndex(int offset) {
422:                return getLines().getLineAt(offset);
423:            }
424:
425:            public int getEndOffset() {
426:                return getLength();
427:            }
428:
429:            public String getName() {
430:                return "foo"; //XXX
431:            }
432:
433:            public Element getParentElement() {
434:                return null;
435:            }
436:
437:            public int getStartOffset() {
438:                return 0;
439:            }
440:
441:            public boolean isLeaf() {
442:                return getLines().getLineCount() == 0;
443:            }
444:
445:            private volatile DO lastEvent = null;
446:            private int lastPostedLine = -1;
447:            private int lastPostedLength = -1;
448:            private int lastFiredLine = -1;
449:            private int lastFiredlength = -1;
450:
451:            public void stateChanged(ChangeEvent changeEvent) {
452:                if (Controller.VERBOSE)
453:                    Controller
454:                            .log(changeEvent != null ? "Document got change event from writer"
455:                                    : "Document timer polling");
456:                if (dlisteners.isEmpty()) {
457:                    if (Controller.VERBOSE)
458:                        Controller.log("listeners empty, not firing");
459:                    return;
460:                }
461:                if (getLines().checkDirty(true)) {
462:                    if (lastEvent != null && !lastEvent.isConsumed()) {
463:                        if (Controller.VERBOSE)
464:                            Controller
465:                                    .log("Last event not consumed, not firing");
466:                        return;
467:                    }
468:                    boolean noPostedLine = lastPostedLine == -1;
469:
470:                    int lineCount = getLines().getLineCount();
471:                    int size = getLines().getCharCount() + inBuffer.length();
472:                    lastPostedLine = lineCount;
473:                    lastPostedLength = size;
474:
475:                    if (Controller.VERBOSE)
476:                        Controller
477:                                .log("Document may fire event - last fired getLine="
478:                                        + lastFiredLine
479:                                        + " getLine count now "
480:                                        + lineCount);
481:                    if ((lastFiredLine != lastPostedLine || lastPostedLength != lastFiredlength)
482:                            || noPostedLine) {
483:                        lastEvent = new DO(
484:                                Math
485:                                        .max(
486:                                                0,
487:                                                lastFiredLine == lastPostedLine ? lastFiredLine - 1
488:                                                        : lastFiredLine),
489:                                noPostedLine);
490:                        //                evts.add (lastEvent);
491:                        Mutex.EVENT.readAccess(new Runnable() {
492:                            public void run() {
493:                                if (Controller.VERBOSE)
494:                                    Controller
495:                                            .log("Firing document event on EQ with start index "
496:                                                    + lastEvent.start);
497:                                fireDocumentEvent(lastEvent);
498:                            }
499:                        });
500:                        lastFiredLine = lastPostedLine;
501:                        lastFiredlength = lastPostedLength;
502:                    } else {
503:                        if (Controller.VERBOSE)
504:                            Controller.log("Line count is still " + lineCount
505:                                    + " - not firing");
506:                    }
507:                } else {
508:                    if (Controller.VERBOSE)
509:                        Controller
510:                                .log("Writer says it is not dirty, firing no change");
511:                }
512:                updateTimerState();
513:            }
514:
515:            private boolean updatingTimerState = false;
516:
517:            private synchronized void updateTimerState() {
518:                if (updatingTimerState) {
519:                    return;
520:                }
521:                updatingTimerState = true;
522:                long newTime = System.currentTimeMillis();
523:                if (timer == null && getLines().isGrowing()) {
524:                    if (Controller.LOG)
525:                        Controller.log("Starting timer");
526:                    //Run the timer fast and furious at first, slowing down after
527:                    //the initial output has been captured
528:                    timer = new javax.swing.Timer(50, this );
529:                    timer.setRepeats(true);
530:                    timer.start();
531:                } else if (!getLines().isGrowing()) {
532:                    if (timer != null) {
533:                        timer.stop();
534:                    }
535:                    if (getLines().checkDirty(false) && timer != null) {
536:                        //There's still some output we haven't displayed - 
537:                        //fire a change one last time.
538:                        Mutex.EVENT.readAccess(this );
539:                    }
540:                    //            logInfo();
541:                    timer = null;
542:                } else if (lastFireTime != 0 && timer != null) {
543:                    if (newTime - lastFireTime > 15000) {
544:                        //Probably we're done, but someone forgot to close the stream.
545:                        //Slow down the timer to a dull roar.
546:                        timer.setDelay(10000);
547:                    }
548:                }
549:                if (timer != null && timer.getDelay() < 350) {
550:                    timer.setDelay(timer.getDelay() + 20);
551:                    if (Controller.VERBOSE)
552:                        Controller.log("Decreased timer interval to "
553:                                + timer.getDelay());
554:                }
555:                lastFireTime = newTime;
556:                updatingTimerState = false;
557:            }
558:
559:            public void run() {
560:                stateChanged(null);
561:            }
562:
563:            private long lastFireTime = 0;
564:
565:            public void actionPerformed(ActionEvent actionEvent) {
566:                if (!getLines().isGrowing()) {
567:                    updateTimerState();
568:                }
569:                stateChanged(null);
570:            }
571:
572:            private void fireDocumentEvent(DocumentEvent de) {
573:                for (DocumentListener dl : new ArrayList<DocumentListener>(
574:                        dlisteners)) {
575:                    //#114290
576:                    if (!(de instanceof  DO)) {
577:                        if (pane != null) {
578:                            pane.doUpdateCaret();
579:                        }
580:                    }
581:                    if (de.getType() == DocumentEvent.EventType.REMOVE) {
582:                        dl.removeUpdate(de);
583:                    } else if (de.getType() == DocumentEvent.EventType.CHANGE) {
584:                        dl.changedUpdate(de);
585:                    } else {
586:                        dl.insertUpdate(de);
587:                    }
588:                    //#114290
589:                    if (!(de instanceof  DO)) {
590:                        if (pane != null) {
591:                            pane.dontUpdateCaret();
592:                        }
593:                    }
594:                }
595:            }
596:
597:            static final class ODPosition implements  Position {
598:                private int offset;
599:
600:                ODPosition(int offset) {
601:                    this .offset = offset;
602:                }
603:
604:                public int getOffset() {
605:                    return offset;
606:                }
607:
608:                public int hashCode() {
609:                    return offset * 11;
610:                }
611:
612:                public boolean equals(Object o) {
613:                    return (o instanceof  ODPosition)
614:                            && ((ODPosition) o).getOffset() == offset;
615:                }
616:            }
617:
618:            final class ODEndPosition implements  Position {
619:                public int getOffset() {
620:                    return getLines().getCharCount() + inBuffer.length();
621:                }
622:
623:                private Document doc() {
624:                    return OutputDocument.this ;
625:                }
626:
627:                public boolean equals(Object o) {
628:                    return (o instanceof  ODEndPosition)
629:                            && ((ODEndPosition) o).doc() == doc();
630:                }
631:
632:                public int hashCode() {
633:                    return -2390481;
634:                }
635:            }
636:
637:            final class ODStartPosition implements  Position {
638:                public int getOffset() {
639:                    return 0;
640:                }
641:
642:                private Document doc() {
643:                    return OutputDocument.this ;
644:                }
645:
646:                public boolean equals(Object o) {
647:                    return (o instanceof  ODStartPosition)
648:                            && ((ODStartPosition) o).doc() == doc();
649:                }
650:
651:                public int hashCode() {
652:                    return 2190481;
653:                }
654:            }
655:
656:            final class ODElement implements  Element {
657:                private int lineIndex;
658:                private int startOffset = -1;
659:                private int endOffset = -1;
660:
661:                ODElement(int lineIndex) {
662:                    this .lineIndex = lineIndex;
663:                }
664:
665:                public int hashCode() {
666:                    return lineIndex;
667:                }
668:
669:                public boolean equals(Object o) {
670:                    return (o instanceof  ODElement)
671:                            && ((ODElement) o).lineIndex == lineIndex
672:                            && ((ODElement) o).getDocument() == getDocument();
673:                }
674:
675:                public AttributeSet getAttributes() {
676:                    return SimpleAttributeSet.EMPTY;
677:                }
678:
679:                public Document getDocument() {
680:                    return OutputDocument.this ;
681:                }
682:
683:                public Element getElement(int param) {
684:                    return null;
685:                }
686:
687:                public int getElementCount() {
688:                    return 0;
689:                }
690:
691:                public int getElementIndex(int param) {
692:                    return -1;
693:                }
694:
695:                public int getEndOffset() {
696:                    calc();
697:                    return endOffset;
698:                }
699:
700:                public String getName() {
701:                    return null;
702:                }
703:
704:                public Element getParentElement() {
705:                    return OutputDocument.this ;
706:                }
707:
708:                public int getStartOffset() {
709:                    calc();
710:                    return startOffset;
711:                }
712:
713:                void calc() {
714:                    synchronized (getLines().readLock()) {
715:                        if (startOffset == -1) {
716:                            startOffset = getLines().getLineCount() > 0 ? getLines()
717:                                    .getLineStart(lineIndex)
718:                                    : 0;
719:                            if (lineIndex >= getLines().getLineCount() - 1) {
720:                                endOffset = getLines().getCharCount()
721:                                        + inBuffer.length();
722:                            } else {
723:                                endOffset = getLines().getLineStart(
724:                                        lineIndex + 1);
725:                            }
726:                            assert endOffset >= getStartOffset() : "Illogical getLine #"
727:                                    + lineIndex
728:                                    + " with lines "
729:                                    + getLines()
730:                                    + " or writer has been reset";
731:                        } else if (lineIndex >= getLines().getLineCount() - 1) {
732:                            //always recalculate the last line...
733:                            endOffset = getLines().getCharCount()
734:                                    + inBuffer.length();
735:                        }
736:                    }
737:                }
738:
739:                public boolean isLeaf() {
740:                    return true;
741:                }
742:
743:                public String toString() {
744:                    try {
745:                        return OutputDocument.this .getText(getStartOffset(),
746:                                getEndOffset() - getStartOffset());
747:                    } catch (BadLocationException ble) {
748:                        Exceptions.printStackTrace(ble);
749:                        return "";
750:                    }
751:                }
752:            }
753:
754:            /**
755:             * Bug in javax.swing.text.PlainView - even if the element count is 0,
756:             * it tries to fetch the 0th element.
757:             */
758:            private static class EmptyElement implements  Element {
759:                private final OutputDocument doc;
760:
761:                EmptyElement(OutputDocument doc) {
762:                    this .doc = doc;
763:                }
764:
765:                public javax.swing.text.AttributeSet getAttributes() {
766:                    return SimpleAttributeSet.EMPTY;
767:                }
768:
769:                public javax.swing.text.Document getDocument() {
770:                    return doc;
771:                }
772:
773:                public javax.swing.text.Element getElement(int param) {
774:                    return null;
775:                }
776:
777:                public int getElementCount() {
778:                    return 0;
779:                }
780:
781:                public int getElementIndex(int param) {
782:                    return 0;
783:                }
784:
785:                public int getEndOffset() {
786:                    return 0;
787:                }
788:
789:                public String getName() {
790:                    return "empty";
791:                }
792:
793:                public javax.swing.text.Element getParentElement() {
794:                    return doc;
795:                }
796:
797:                public int getStartOffset() {
798:                    return 0;
799:                }
800:
801:                public boolean isLeaf() {
802:                    return true;
803:                }
804:            }
805:
806:            public class DO implements  DocumentEvent,
807:                    DocumentEvent.ElementChange {
808:                private int start;
809:                private int offset = -1;
810:                private int length = -1;
811:                private int lineCount = -1;
812:                private boolean consumed = false;
813:                private boolean initial = false;
814:                private int first = -1;
815:
816:                DO(int start, boolean initial) {
817:                    this .start = start;
818:                    this .initial = initial;
819:                    if (start < 0) {
820:                        throw new IllegalArgumentException("Illogical start: "
821:                                + start);
822:                    }
823:                }
824:
825:                private void calc() {
826:                    //#60414 related assertion. The exceptions in the bug can only happen
827:                    // when this method is called from 2 threads? but that should not be happening
828:                    assert SwingUtilities.isEventDispatchThread() : "Should be accessed from AWT only or we have a synchronization problem"; //NOI18N
829:                    if (!consumed) {
830:                        //                synchronized (writer) {
831:                        consumed = true;
832:                        if (Controller.VERBOSE)
833:                            Controller.log("EVENT CONSUMED: " + start);
834:                        int charsWritten = getLines().getCharCount()
835:                                + inBuffer.length();
836:                        if (initial) {
837:                            first = 0;
838:                            offset = 0;
839:                            lineCount = getLines().getLineCount();
840:                            length = charsWritten;
841:                        } else {
842:                            first = start;
843:                            //                        if (first == getLines().getLineCount()) {
844:                            //                            throw new IllegalStateException ("Out of bounds");
845:                            //                        }
846:
847:                            offset = getLines().getLineStart(first);
848:                            lineCount = getLines().getLineCount() - first;
849:                            length = charsWritten - offset;
850:                        }
851:                        //                }
852:                    }
853:                }
854:
855:                public boolean isConsumed() {
856:                    return consumed;
857:                }
858:
859:                public String toString() {
860:                    boolean wasConsumed = isConsumed();
861:                    calc();
862:                    return "Event: start=" + start + " first=" + first
863:                            + " linecount=" + lineCount + " offset=" + offset
864:                            + " length=" + length + " consumed=" + wasConsumed;
865:                }
866:
867:                public DocumentEvent.ElementChange getChange(Element element) {
868:                    if (element == OutputDocument.this ) {
869:                        return this ;
870:                    } else {
871:                        return null;
872:                    }
873:                }
874:
875:                public Document getDocument() {
876:                    return OutputDocument.this ;
877:                }
878:
879:                public int getLength() {
880:                    calc();
881:                    return length;
882:                }
883:
884:                public int getOffset() {
885:                    calc();
886:                    return offset;
887:                }
888:
889:                public DocumentEvent.EventType getType() {
890:                    return start == 0 ? DocumentEvent.EventType.CHANGE
891:                            : DocumentEvent.EventType.INSERT;
892:                }
893:
894:                public Element[] getChildrenAdded() {
895:                    calc();
896:                    Element[] e = new Element[lineCount];
897:                    if (e.length == 0) {
898:                        return new Element[] { new EmptyElement(
899:                                OutputDocument.this ) };
900:                    } else {
901:                        for (int i = 0; i < lineCount; i++) {
902:                            e[i] = new ODElement(first + i);
903:                            if (first + i >= getLines().getLineCount()) {
904:                                throw new IllegalStateException("UGH!!!");
905:                            }
906:                        }
907:                    }
908:                    return e;
909:                }
910:
911:                public Element[] getChildrenRemoved() {
912:                    if (start == 0) {
913:                        return new Element[] { new EmptyElement(
914:                                OutputDocument.this ) };
915:                    } else {
916:                        return new Element[0];
917:                    }
918:                }
919:
920:                public Element getElement() {
921:                    return OutputDocument.this ;
922:                }
923:
924:                public int getIndex() {
925:                    calc();
926:                    return start;
927:                }
928:            }
929:
930:            public String toString() {
931:                return "OD@" + System.identityHashCode(this ) + " for "
932:                        + getLines().readLock();
933:            }
934:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.