Source Code Cross Referenced for AbstractDocument.java in  » Apache-Harmony-Java-SE » javax-package » javax » swing » text » 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 » Apache Harmony Java SE » javax package » javax.swing.text 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:        package javax.swing.text;
0018:
0019:        import java.awt.font.TextAttribute;
0020:        import java.io.IOException;
0021:        import java.io.ObjectInputStream;
0022:        import java.io.ObjectOutputStream;
0023:        import java.io.PrintStream;
0024:        import java.io.Serializable;
0025:        import java.text.Bidi;
0026:        import java.util.ArrayList;
0027:        import java.util.Arrays;
0028:        import java.util.Comparator;
0029:        import java.util.Dictionary;
0030:        import java.util.Enumeration;
0031:        import java.util.EventListener;
0032:        import java.util.HashMap;
0033:        import java.util.Hashtable;
0034:        import java.util.List;
0035:
0036:        import javax.swing.UIDefaults;
0037:        import javax.swing.UIManager;
0038:        import javax.swing.event.DocumentEvent;
0039:        import javax.swing.event.DocumentListener;
0040:        import javax.swing.event.EventListenerList;
0041:        import javax.swing.event.UndoableEditEvent;
0042:        import javax.swing.event.UndoableEditListener;
0043:        import javax.swing.event.DocumentEvent.ElementChange;
0044:        import javax.swing.event.DocumentEvent.EventType;
0045:        import javax.swing.tree.TreeNode;
0046:        import javax.swing.undo.AbstractUndoableEdit;
0047:        import javax.swing.undo.CompoundEdit;
0048:        import javax.swing.undo.UndoableEdit;
0049:
0050:        import org.apache.harmony.awt.text.PropertyNames;
0051:        import org.apache.harmony.awt.text.TextUtils;
0052:        import org.apache.harmony.x.swing.StringConstants;
0053:
0054:        import org.apache.harmony.x.swing.internal.nls.Messages;
0055:
0056:        public abstract class AbstractDocument implements  Document,
0057:                Serializable {
0058:
0059:            public abstract class AbstractElement implements  Element,
0060:                    MutableAttributeSet, Serializable, TreeNode {
0061:
0062:                private static final String INDENT_LEVEL = "  ";
0063:                private static final int MAX_LEAF_CONTENT_LENGTH = 40;
0064:
0065:                private transient AttributeSet attrs;
0066:
0067:                private final Element parent;
0068:
0069:                public AbstractElement(final Element parent,
0070:                        final AttributeSet attributes) {
0071:                    this .parent = parent;
0072:
0073:                    this .attrs = context.getEmptySet();
0074:
0075:                    if (attributes != null) {
0076:                        addAttributes(attributes);
0077:                    }
0078:                }
0079:
0080:                public abstract boolean getAllowsChildren();
0081:
0082:                public abstract boolean isLeaf();
0083:
0084:                public abstract Enumeration children();
0085:
0086:                public abstract Element getElement(final int index);
0087:
0088:                public abstract int getElementCount();
0089:
0090:                public abstract int getElementIndex(final int offset);
0091:
0092:                public abstract int getStartOffset();
0093:
0094:                public abstract int getEndOffset();
0095:
0096:                public void addAttribute(final Object key, final Object value) {
0097:                    checkWriteLock();
0098:
0099:                    attrs = context.addAttribute(attrs, key, value);
0100:                }
0101:
0102:                public void addAttributes(final AttributeSet attrSet) {
0103:                    checkWriteLock();
0104:
0105:                    attrs = context.addAttributes(attrs, attrSet);
0106:                }
0107:
0108:                public boolean containsAttribute(final Object key,
0109:                        final Object value) {
0110:                    return attrs.containsAttribute(key, value);
0111:                }
0112:
0113:                public boolean containsAttributes(final AttributeSet attrSet) {
0114:                    return attrs.containsAttributes(attrSet);
0115:                }
0116:
0117:                public AttributeSet copyAttributes() {
0118:                    return attrs.copyAttributes();
0119:                }
0120:
0121:                /**
0122:                 * Prints the element name and lists all attributes.
0123:                 */
0124:                public void dump(final PrintStream ps, final int indent) {
0125:                    final String name = getName();
0126:
0127:                    String indentation = "";
0128:                    for (int i = indent; i > 0; i--) {
0129:                        indentation += INDENT_LEVEL;
0130:                    }
0131:
0132:                    if (getAttributeCount() == 0) {
0133:                        ps.println(indentation + "<" + name + ">");
0134:                        indentation += INDENT_LEVEL;
0135:                    } else {
0136:                        ps.println(indentation + "<" + name);
0137:                        final String closing = indentation + ">";
0138:
0139:                        indentation += INDENT_LEVEL;
0140:
0141:                        Enumeration keys = getAttributeNames();
0142:                        while (keys.hasMoreElements()) {
0143:                            Object key = keys.nextElement();
0144:                            Object value = getAttribute(key);
0145:                            ps.println(indentation + key + "=" + value);
0146:                        }
0147:                        ps.println(closing);
0148:                    }
0149:
0150:                    if (isLeaf()) {
0151:                        try {
0152:                            String text = content.getString(getStartOffset(),
0153:                                    getEndOffset() - getStartOffset());
0154:                            if (text.length() > MAX_LEAF_CONTENT_LENGTH) {
0155:                                text = text.substring(0,
0156:                                        MAX_LEAF_CONTENT_LENGTH);
0157:                                text += "...";
0158:                            }
0159:                            ps.println(indentation + "[" + getStartOffset()
0160:                                    + "," + getEndOffset() + "][" + text + "]");
0161:                        } catch (final NullPointerException e) {
0162:                        } catch (final BadLocationException e) {
0163:                        }
0164:                    } else {
0165:                        Enumeration leaves = children();
0166:                        if (leaves == null) {
0167:                            return;
0168:                        }
0169:
0170:                        while (leaves.hasMoreElements()) {
0171:                            Object child = leaves.nextElement();
0172:                            if (child instanceof  AbstractElement) {
0173:                                ((AbstractElement) child).dump(ps, indent + 1);
0174:                            }
0175:                        }
0176:                    }
0177:                }
0178:
0179:                public Object getAttribute(final Object key) {
0180:                    Object value = attrs.getAttribute(key);
0181:                    AttributeSet resolver = getResolveParent();
0182:                    if (value == null && resolver != null) {
0183:                        value = resolver.getAttribute(key);
0184:                    }
0185:                    return value;
0186:                }
0187:
0188:                public int getAttributeCount() {
0189:                    return attrs.getAttributeCount();
0190:                }
0191:
0192:                public Enumeration<?> getAttributeNames() {
0193:                    return attrs.getAttributeNames();
0194:                }
0195:
0196:                public AttributeSet getAttributes() {
0197:                    return this ;
0198:                }
0199:
0200:                public TreeNode getChildAt(final int index) {
0201:                    return (TreeNode) getElement(index);
0202:                }
0203:
0204:                public int getChildCount() {
0205:                    return getElementCount();
0206:                }
0207:
0208:                public Document getDocument() {
0209:                    return AbstractDocument.this ;
0210:                }
0211:
0212:                public int getIndex(final TreeNode node) {
0213:                    if (getAllowsChildren()) {
0214:                        final int count = getChildCount();
0215:                        for (int i = 0; i < count; i++) {
0216:                            if (getChildAt(i) == node) {
0217:                                return i;
0218:                            }
0219:                        }
0220:                    }
0221:
0222:                    return -1;
0223:                }
0224:
0225:                public String getName() {
0226:                    return isDefined(ElementNameAttribute) ? (String) getAttribute(ElementNameAttribute)
0227:                            : null;
0228:                }
0229:
0230:                public TreeNode getParent() {
0231:                    final Element parentElement = getParentElement();
0232:                    return parentElement instanceof  TreeNode ? (TreeNode) parentElement
0233:                            : null;
0234:                }
0235:
0236:                public Element getParentElement() {
0237:                    return parent;
0238:                }
0239:
0240:                public AttributeSet getResolveParent() {
0241:                    AttributeSet resolver = attrs.getResolveParent();
0242:                    if (resolver == null && parent != null) {
0243:                        resolver = parent.getAttributes();
0244:                    }
0245:                    return resolver;
0246:                }
0247:
0248:                public boolean isDefined(final Object key) {
0249:                    return attrs.isDefined(key);
0250:                }
0251:
0252:                public boolean isEqual(final AttributeSet attrSet) {
0253:                    return attrs.isEqual(attrSet);
0254:                }
0255:
0256:                public void removeAttribute(final Object key) {
0257:                    checkWriteLock();
0258:
0259:                    attrs = context.removeAttribute(attrs, key);
0260:                }
0261:
0262:                public void removeAttributes(final AttributeSet attrSet) {
0263:                    checkWriteLock();
0264:
0265:                    attrs = context.removeAttributes(attrs, attrSet);
0266:                }
0267:
0268:                public void removeAttributes(final Enumeration<?> attrNames) {
0269:                    checkWriteLock();
0270:
0271:                    attrs = context.removeAttributes(attrs, attrNames);
0272:                }
0273:
0274:                public void setResolveParent(final AttributeSet resolveParent) {
0275:                    checkWriteLock();
0276:
0277:                    attrs = context.addAttribute(attrs,
0278:                            AttributeSet.ResolveAttribute, resolveParent);
0279:                }
0280:
0281:                final void checkWriteLock() {
0282:                    if (AbstractDocument.this .getCurrentWriter() != Thread
0283:                            .currentThread()) {
0284:
0285:                        throw new Error(Messages.getString("swing.err.0F")); //$NON-NLS-1$
0286:                    }
0287:                }
0288:
0289:                private void readObject(final ObjectInputStream ois)
0290:                        throws IOException, ClassNotFoundException {
0291:
0292:                    ois.defaultReadObject();
0293:
0294:                    MutableAttributeSet mas = new SimpleAttributeSet();
0295:                    StyleContext.readAttributeSet(ois, mas);
0296:
0297:                    attrs = context.getEmptySet();
0298:                    if (mas.getAttributeCount() > 0) {
0299:                        writeLock();
0300:                        addAttributes(mas);
0301:                        writeUnlock();
0302:                    }
0303:                }
0304:
0305:                private void writeObject(final ObjectOutputStream oos)
0306:                        throws IOException {
0307:
0308:                    oos.defaultWriteObject();
0309:                    StyleContext.writeAttributeSet(oos, attrs);
0310:                }
0311:
0312:            }
0313:
0314:            public static interface AttributeContext {
0315:
0316:                AttributeSet addAttribute(AttributeSet old, Object key,
0317:                        Object value);
0318:
0319:                AttributeSet addAttributes(AttributeSet old, AttributeSet toAdd);
0320:
0321:                AttributeSet getEmptySet();
0322:
0323:                void reclaim(AttributeSet attrs);
0324:
0325:                AttributeSet removeAttribute(AttributeSet old, Object key);
0326:
0327:                AttributeSet removeAttributes(AttributeSet old,
0328:                        AttributeSet toDelete);
0329:
0330:                AttributeSet removeAttributes(AttributeSet old,
0331:                        Enumeration<?> names);
0332:
0333:            }
0334:
0335:            @SuppressWarnings("serial")
0336:            public class BranchElement extends AbstractElement {
0337:                Element[] elements = new Element[0];
0338:
0339:                private final SearchElement searchElem = new SearchElement();
0340:                private final Comparator<Object> comparator = new ElementComparator();
0341:
0342:                public BranchElement(final Element parent,
0343:                        final AttributeSet attributes) {
0344:                    super (parent, attributes);
0345:                }
0346:
0347:                @Override
0348:                public Enumeration children() {
0349:                    if (elements == null || elements.length == 0) {
0350:                        return null;
0351:                    } else {
0352:                        return new Enumeration() {
0353:                            private int index = 0;
0354:
0355:                            public boolean hasMoreElements() {
0356:                                return index < elements.length;
0357:                            }
0358:
0359:                            public Object nextElement() {
0360:                                return elements[index++];
0361:                            }
0362:                        };
0363:                    }
0364:                }
0365:
0366:                @Override
0367:                public boolean getAllowsChildren() {
0368:                    return true;
0369:                }
0370:
0371:                @Override
0372:                public Element getElement(final int index) {
0373:                    if (0 <= index && index < elements.length) {
0374:                        return elements[index];
0375:                    } else {
0376:                        return null;
0377:                    }
0378:                }
0379:
0380:                @Override
0381:                public int getElementCount() {
0382:                    return elements.length;
0383:                }
0384:
0385:                @Override
0386:                public int getElementIndex(final int offset) {
0387:                    if (elements.length <= 1) {
0388:                        return 0;
0389:                    }
0390:
0391:                    searchElem.offset = offset;
0392:                    int result = Arrays.binarySearch(elements, searchElem,
0393:                            comparator);
0394:                    if (result < 0) {
0395:                        result = -result - 1;
0396:                    }
0397:                    if (result >= elements.length) {
0398:                        result = elements.length - 1;
0399:                    }
0400:
0401:                    return result;
0402:                }
0403:
0404:                @Override
0405:                public int getEndOffset() {
0406:                    if (elements.length == 0) {
0407:                        throw new NullPointerException();
0408:                    }
0409:                    return elements[elements.length - 1].getEndOffset();
0410:                }
0411:
0412:                @Override
0413:                public String getName() {
0414:                    final String inherited = super .getName();
0415:                    return inherited != null ? inherited : ParagraphElementName;
0416:                }
0417:
0418:                @Override
0419:                public int getStartOffset() {
0420:                    if (elements.length == 0) {
0421:                        throw new NullPointerException();
0422:                    }
0423:                    return elements[0].getStartOffset();
0424:                }
0425:
0426:                @Override
0427:                public boolean isLeaf() {
0428:                    return false;
0429:                }
0430:
0431:                public Element positionToElement(final int offset) {
0432:                    if (offset < getStartOffset()
0433:                            || offset > getEndOffset() - 1) {
0434:                        return null;
0435:                    }
0436:                    return elements[getElementIndex(offset)];
0437:                }
0438:
0439:                public void replace(final int index, final int length,
0440:                        final Element[] newElements) {
0441:                    Element[] newArray;
0442:
0443:                    if (index < 0 || length < 0
0444:                            || elements.length < index + length) {
0445:                        throw new ArrayIndexOutOfBoundsException();
0446:                    }
0447:
0448:                    newArray = new Element[elements.length - length
0449:                            + newElements.length];
0450:
0451:                    System.arraycopy(elements, 0, newArray, 0, index);
0452:                    System.arraycopy(newElements, 0, newArray, index,
0453:                            newElements.length);
0454:                    System.arraycopy(elements, index + length, newArray, index
0455:                            + newElements.length, elements.length
0456:                            - (index + length));
0457:
0458:                    elements = newArray;
0459:                }
0460:
0461:                @Override
0462:                public String toString() {
0463:                    return "BranchElement(" + getName() + ") "
0464:                            + getStartOffset() + "," + getEndOffset() + "\n";
0465:                }
0466:
0467:            }
0468:
0469:            public static interface Content {
0470:
0471:                Position createPosition(int offset) throws BadLocationException;
0472:
0473:                void getChars(int offset, int length, Segment text)
0474:                        throws BadLocationException;
0475:
0476:                String getString(int offset, int length)
0477:                        throws BadLocationException;
0478:
0479:                UndoableEdit insertString(int offset, String str)
0480:                        throws BadLocationException;
0481:
0482:                int length();
0483:
0484:                UndoableEdit remove(int offset, int length)
0485:                        throws BadLocationException;
0486:
0487:            }
0488:
0489:            @SuppressWarnings("serial")
0490:            public class DefaultDocumentEvent extends CompoundEdit implements 
0491:                    DocumentEvent {
0492:
0493:                private static final int THRESHOLD = 10;
0494:
0495:                private HashMap<Element, ElementChange> changes;
0496:                private int length;
0497:                private int offset;
0498:                private EventType type;
0499:
0500:                public DefaultDocumentEvent(final int offset, final int length,
0501:                        final DocumentEvent.EventType type) {
0502:                    this .offset = offset;
0503:                    this .length = length;
0504:                    this .type = type;
0505:                }
0506:
0507:                @Override
0508:                public boolean addEdit(final UndoableEdit anEdit) {
0509:                    boolean result = super .addEdit(anEdit);
0510:
0511:                    if (result && edits.size() > THRESHOLD) {
0512:                        if (changes == null) {
0513:                            changes = new HashMap<Element, ElementChange>();
0514:
0515:                            for (UndoableEdit edit : edits) {
0516:                                if (edit instanceof  ElementChange) {
0517:                                    ElementChange change = (ElementChange) edit;
0518:                                    changes.put(change.getElement(), change);
0519:                                }
0520:                            }
0521:                        } else {
0522:                            if (anEdit instanceof  ElementChange) {
0523:                                ElementChange change = (ElementChange) anEdit;
0524:                                changes.put(change.getElement(), change);
0525:                            }
0526:                        }
0527:                    }
0528:
0529:                    return result;
0530:                }
0531:
0532:                public ElementChange getChange(final Element element) {
0533:                    if (changes != null) {
0534:                        return changes.get(element);
0535:                    }
0536:
0537:                    for (UndoableEdit edit : edits) {
0538:                        if (edit instanceof  ElementChange) {
0539:                            ElementChange change = (ElementChange) edit;
0540:                            if (change.getElement() == element) {
0541:                                return change;
0542:                            }
0543:                        }
0544:                    }
0545:                    return null;
0546:                }
0547:
0548:                public Document getDocument() {
0549:                    return AbstractDocument.this ;
0550:                }
0551:
0552:                public int getLength() {
0553:                    return length;
0554:                }
0555:
0556:                public int getOffset() {
0557:                    return offset;
0558:                }
0559:
0560:                @Override
0561:                public String getPresentationName() {
0562:                    if (type == EventType.INSERT) {
0563:                        return getLocalizedString("AbstractDocument.additionText");
0564:                    } else if (type == EventType.REMOVE) {
0565:                        return getLocalizedString("AbstractDocument.deletionText");
0566:                    } else if (type == EventType.CHANGE) {
0567:                        return getLocalizedString("AbstractDocument.styleChangeText");
0568:                    }
0569:
0570:                    assert false : "Valid values are DocumentEvent.EventType.INSERT, "
0571:                            + "REMOVE, CHANGE";
0572:                    return null;
0573:                }
0574:
0575:                @Override
0576:                public String getRedoPresentationName() {
0577:                    return getLocalizedRedoName() + " " + getPresentationName();
0578:                }
0579:
0580:                public EventType getType() {
0581:                    return type;
0582:                }
0583:
0584:                @Override
0585:                public String getUndoPresentationName() {
0586:                    return getLocalizedUndoName() + " " + getPresentationName();
0587:                }
0588:
0589:                @Override
0590:                public boolean isSignificant() {
0591:                    return true;
0592:                }
0593:
0594:                @Override
0595:                public void redo() {
0596:                    writeLock();
0597:                    try {
0598:                        super .redo();
0599:
0600:                        fireEvent(false);
0601:                    } finally {
0602:                        writeUnlock();
0603:                    }
0604:                }
0605:
0606:                @Override
0607:                public String toString() {
0608:                    StringBuffer result = new StringBuffer();
0609:                    for (UndoableEdit edit : edits) {
0610:                        result.append(", ").append(edit.toString());
0611:                    }
0612:                    result.replace(0, 2, "[").append("]");
0613:                    return result.toString();
0614:                }
0615:
0616:                @Override
0617:                public void undo() {
0618:                    writeLock();
0619:                    try {
0620:                        super .undo();
0621:
0622:                        fireEvent(true);
0623:                    } finally {
0624:                        writeUnlock();
0625:                    }
0626:                }
0627:
0628:                private void fireEvent(final boolean undone) {
0629:                    final EventType eventType = type;
0630:                    if (type == EventType.CHANGE) {
0631:                        fireChangedUpdate(this );
0632:                    } else {
0633:                        if (type == EventType.INSERT && undone) {
0634:                            type = EventType.REMOVE;
0635:                            fireRemoveUpdate(this );
0636:                        } else {
0637:                            type = EventType.INSERT;
0638:                            fireInsertUpdate(this );
0639:                        }
0640:                        type = eventType;
0641:                    }
0642:                }
0643:
0644:                private String getLocalizedUndoName() {
0645:                    return UIManager.getString("AbstractDocument.undoText");
0646:                }
0647:
0648:                private String getLocalizedRedoName() {
0649:                    return UIManager.getString("AbstractDocument.redoText");
0650:                }
0651:            }
0652:
0653:            @SuppressWarnings("serial")
0654:            public static class ElementEdit extends AbstractUndoableEdit
0655:                    implements  ElementChange {
0656:
0657:                private Element[] added;
0658:                private Element element;
0659:                private int index;
0660:                private Element[] removed;
0661:
0662:                public ElementEdit(final Element element, final int index,
0663:                        final Element[] removed, final Element[] added) {
0664:                    this .element = element;
0665:                    this .index = index;
0666:                    this .removed = removed;
0667:                    this .added = added;
0668:                }
0669:
0670:                public Element[] getChildrenAdded() {
0671:                    return added;
0672:                }
0673:
0674:                public Element[] getChildrenRemoved() {
0675:                    return removed;
0676:                }
0677:
0678:                public Element getElement() {
0679:                    return element;
0680:                }
0681:
0682:                public int getIndex() {
0683:                    return index;
0684:                }
0685:
0686:                @Override
0687:                public void redo() {
0688:                    super .redo();
0689:                    Element[] temp = added;
0690:                    added = removed;
0691:                    removed = temp;
0692:                    ((BranchElement) element).replace(index, removed.length,
0693:                            added);
0694:                }
0695:
0696:                @Override
0697:                public void undo() {
0698:                    super .undo();
0699:                    ((BranchElement) element).replace(index, added.length,
0700:                            removed);
0701:                    Element[] temp = added;
0702:                    added = removed;
0703:                    removed = temp;
0704:                }
0705:
0706:            }
0707:
0708:            @SuppressWarnings("serial")
0709:            public class LeafElement extends AbstractElement {
0710:                private transient Position end;
0711:                private transient Position start;
0712:
0713:                public LeafElement(final Element parent,
0714:                        final AttributeSet attributes, final int startOffset,
0715:                        final int endOffset) {
0716:                    super (parent, attributes);
0717:
0718:                    int adjustedStartOffset = startOffset;
0719:                    int adjustedEndOffset = endOffset;
0720:
0721:                    if (adjustedStartOffset < 0) {
0722:                        adjustedStartOffset = 0;
0723:                    }
0724:
0725:                    if (adjustedEndOffset < adjustedStartOffset) {
0726:                        adjustedEndOffset = adjustedStartOffset;
0727:                    }
0728:
0729:                    initPositions(adjustedStartOffset, adjustedEndOffset);
0730:                }
0731:
0732:                @Override
0733:                public Enumeration children() {
0734:                    return null;
0735:                }
0736:
0737:                @Override
0738:                public boolean getAllowsChildren() {
0739:                    return false;
0740:                }
0741:
0742:                @Override
0743:                public Element getElement(final int offset) {
0744:                    return null;
0745:                }
0746:
0747:                @Override
0748:                public int getElementCount() {
0749:                    return 0;
0750:                }
0751:
0752:                @Override
0753:                public int getElementIndex(final int offset) {
0754:                    return -1;
0755:                }
0756:
0757:                @Override
0758:                public int getEndOffset() {
0759:                    return end.getOffset();
0760:                }
0761:
0762:                @Override
0763:                public String getName() {
0764:                    final String inherited = super .getName();
0765:                    return inherited != null ? inherited : ContentElementName;
0766:                }
0767:
0768:                @Override
0769:                public int getStartOffset() {
0770:                    return start.getOffset();
0771:                }
0772:
0773:                @Override
0774:                public boolean isLeaf() {
0775:                    return true;
0776:                }
0777:
0778:                @Override
0779:                public String toString() {
0780:                    return "LeafElement(" + getName() + ") " + getStartOffset()
0781:                            + "," + getEndOffset() + "\n";
0782:                }
0783:
0784:                private void initPositions(final int startOffset,
0785:                        final int endOffset) {
0786:                    try {
0787:                        start = createPosition(startOffset);
0788:                        end = createPosition(endOffset);
0789:                    } catch (final BadLocationException e) {
0790:                    }
0791:                }
0792:
0793:                private void readObject(final ObjectInputStream ois)
0794:                        throws IOException, ClassNotFoundException {
0795:
0796:                    ois.defaultReadObject();
0797:
0798:                    final int startOffset = ois.readInt();
0799:                    final int endOffset = ois.readInt();
0800:                    initPositions(startOffset, endOffset);
0801:                }
0802:
0803:                private void writeObject(final ObjectOutputStream oos)
0804:                        throws IOException {
0805:
0806:                    oos.defaultWriteObject();
0807:
0808:                    oos.writeInt(start.getOffset());
0809:                    oos.writeInt(end.getOffset());
0810:                }
0811:
0812:            }
0813:
0814:            @SuppressWarnings("serial")
0815:            private class BidiElement extends LeafElement {
0816:                public BidiElement(final AttributeSet attributes,
0817:                        final int startOffset, final int endOffset) {
0818:                    super (getBidiRootElement(), attributes, startOffset,
0819:                            endOffset);
0820:                }
0821:
0822:                @Override
0823:                public String getName() {
0824:                    return BidiElementName;
0825:                }
0826:            }
0827:
0828:            @SuppressWarnings("serial")
0829:            private class BidiRoot extends BranchElement {
0830:                public BidiRoot() {
0831:                    super (null, null);
0832:                }
0833:
0834:                @Override
0835:                public String getName() {
0836:                    return "bidi root";
0837:                }
0838:            }
0839:
0840:            private static class ReadWriteLock {
0841:                private boolean callingListeners;
0842:                private int writeAcquestCounter;
0843:                private int waitingWritersCounter;
0844:                private Thread activeWriter;
0845:                private final List<Thread> activeReaders = new ArrayList<Thread>();
0846:                private final Object lock = new Object();
0847:
0848:                public final Thread getCurrentWriter() {
0849:                    return activeWriter;
0850:                }
0851:
0852:                public final void readLock() {
0853:                    final Thread thread = Thread.currentThread();
0854:
0855:                    if (thread == activeWriter) {
0856:                        return;
0857:                    }
0858:
0859:                    synchronized (lock) {
0860:                        while ((activeWriter != null)
0861:                                || (waitingWritersCounter > 0)) {
0862:                            try {
0863:                                lock.wait();
0864:                            } catch (final InterruptedException e) {
0865:                                return;
0866:                            }
0867:                        }
0868:
0869:                        activeReaders.add(thread);
0870:                    }
0871:                }
0872:
0873:                public final void readUnlock() {
0874:                    final Thread thread = Thread.currentThread();
0875:
0876:                    if (thread == activeWriter) {
0877:                        return;
0878:                    }
0879:
0880:                    synchronized (lock) {
0881:                        if (!activeReaders.remove(thread)) {
0882:                            throw new Error(Messages.getString("swing.err.10")); //$NON-NLS-1$
0883:                        }
0884:
0885:                        lock.notifyAll();
0886:                    }
0887:                }
0888:
0889:                public final void setCallingListeners(final boolean flag) {
0890:                    callingListeners = flag;
0891:                }
0892:
0893:                public final void writeLock() {
0894:                    if (callingListeners) {
0895:                        throw new IllegalStateException(Messages
0896:                                .getString("swing.7E")); //$NON-NLS-1$
0897:                    }
0898:
0899:                    final Thread thread = Thread.currentThread();
0900:
0901:                    if (thread == activeWriter) {
0902:                        writeAcquestCounter++;
0903:                        return;
0904:                    }
0905:
0906:                    synchronized (lock) {
0907:                        if ((activeReaders.size() > 0)
0908:                                || (activeWriter != null)) {
0909:
0910:                            waitingWritersCounter++;
0911:
0912:                            while ((activeReaders.size() > 0)
0913:                                    || (activeWriter != null)) {
0914:                                try {
0915:                                    lock.wait();
0916:                                } catch (final InterruptedException e) {
0917:                                    waitingWritersCounter--;
0918:                                    return;
0919:                                }
0920:                            }
0921:
0922:                            waitingWritersCounter--;
0923:                        }
0924:
0925:                        writeAcquestCounter++;
0926:                        activeWriter = thread;
0927:                    }
0928:                }
0929:
0930:                public final void writeUnlock() {
0931:                    if (activeWriter != Thread.currentThread()) {
0932:                        throw new Error(Messages.getString("swing.err.11")); //$NON-NLS-1$            }
0933:                    }
0934:
0935:                    if (--writeAcquestCounter == 0) {
0936:                        synchronized (lock) {
0937:                            activeWriter = null;
0938:                            lock.notifyAll();
0939:                        }
0940:                    }
0941:                }
0942:            }
0943:
0944:            /**
0945:             * Object of this class serves as key when searching for element index.
0946:             * @see BranchElement#getElementIndex(int)
0947:             */
0948:            @SuppressWarnings("serial")
0949:            private static final class SearchElement implements  Serializable {
0950:                /**
0951:                 * Indicates the offset of interest.
0952:                 */
0953:                public transient int offset;
0954:
0955:                @Override
0956:                public String toString() {
0957:                    return "SearchElement(none) " + offset + ", " + offset
0958:                            + "\n";
0959:                }
0960:            }
0961:
0962:            /**
0963:             * The comparator to compare <code>Element</code>s when searching for
0964:             * element index.
0965:             * <p><em><strong>Note:</strong> This comparator imposes ordering that
0966:             * is inconsistent with equals.</em> Most of <code>Element</code>s
0967:             * does not override <code>equals</code>.
0968:             * @see BranchElement#getElementIndex(int)
0969:             */
0970:            @SuppressWarnings("serial")
0971:            private static final class ElementComparator implements 
0972:                    Comparator<Object>, Serializable {
0973:
0974:                /**
0975:                 * It is expected that the first argument is the <code>Element</code>
0976:                 * to compare with and the second argument is the key containing the
0977:                 * offset of interest.
0978:                 *
0979:                 * @param item element to compare with.
0980:                 *             Must be of type <code>Element</code>.
0981:                 * @param key the search key. Object of type <code>SearchElement</code>
0982:                 *            which contains the desired offset.
0983:                 * @return 0, -1 or +1
0984:                 */
0985:                public int compare(final Object item, final Object key) {
0986:                    Element e = (Element) item;
0987:                    int offset = ((SearchElement) key).offset;
0988:                    if (e.getStartOffset() <= offset
0989:                            && offset < e.getEndOffset()) {
0990:
0991:                        return 0;
0992:                    } else if (e.getEndOffset() <= offset) {
0993:                        return -1;
0994:                    } else {
0995:                        return +1;
0996:                    }
0997:                }
0998:            }
0999:
1000:            public static final String BidiElementName = "bidi level";
1001:            public static final String ContentElementName = "content";
1002:            public static final String ElementNameAttribute = "$ename";
1003:            public static final String ParagraphElementName = "paragraph";
1004:            public static final String SectionElementName = "section";
1005:
1006:            protected static final String BAD_LOCATION = "document location failure";
1007:
1008:            protected transient EventListenerList listenerList;
1009:
1010:            private transient BranchElement bidiRoot;
1011:            private transient Content content;
1012:            private transient AttributeContext context;
1013:            private transient Position docEnd;
1014:            private DocumentFilter docFilter;
1015:            private Dictionary<Object, Object> docProperties = new Hashtable<Object, Object>();
1016:            private transient Position docStart;
1017:            private transient DocumentFilter.FilterBypass filterBypasser;
1018:
1019:            private UIDefaults uiDefaults = null;
1020:
1021:            private transient ReadWriteLock lock;
1022:
1023:            protected AbstractDocument(final Content content) {
1024:                this (content, StyleContext.getDefaultStyleContext());
1025:            }
1026:
1027:            protected AbstractDocument(final Content content,
1028:                    final AttributeContext context) {
1029:
1030:                this .content = content;
1031:                this .context = context;
1032:
1033:                putProperty(StringConstants.BIDI_PROPERTY, Boolean.FALSE);
1034:
1035:                initTransientFields();
1036:
1037:                writeLock();
1038:                bidiRoot = new BidiRoot();
1039:                bidiRoot.replace(0, 0, new Element[] { new BidiElement(context
1040:                        .addAttribute(context.getEmptySet(),
1041:                                StyleConstants.BidiLevel, new Integer(0)),
1042:                        docStart.getOffset(), docEnd.getOffset()) });
1043:                writeUnlock();
1044:            }
1045:
1046:            public abstract Element getDefaultRootElement();
1047:
1048:            public abstract Element getParagraphElement(final int offset);
1049:
1050:            public void addDocumentListener(final DocumentListener listener) {
1051:                listenerList.add(DocumentListener.class, listener);
1052:            }
1053:
1054:            public void addUndoableEditListener(
1055:                    final UndoableEditListener listerner) {
1056:                listenerList.add(UndoableEditListener.class, listerner);
1057:            }
1058:
1059:            public synchronized Position createPosition(final int offset)
1060:                    throws BadLocationException {
1061:
1062:                return content.createPosition(offset);
1063:            }
1064:
1065:            /**
1066:             * Dumps the array returned by getRootElements.
1067:             */
1068:            public void dump(final PrintStream ps) {
1069:                Element[] roots = getRootElements();
1070:
1071:                for (Element root : roots) {
1072:                    if (root instanceof  AbstractElement) {
1073:                        ((AbstractElement) root).dump(ps, 0);
1074:                    }
1075:                }
1076:            }
1077:
1078:            public int getAsynchronousLoadPriority() {
1079:                Object value = getProperty(PropertyNames.LOAD_PRIORITY);
1080:                return value instanceof  Integer ? ((Integer) value).intValue()
1081:                        : -1;
1082:            }
1083:
1084:            public Element getBidiRootElement() {
1085:                return bidiRoot;
1086:            }
1087:
1088:            public DocumentFilter getDocumentFilter() {
1089:                return docFilter;
1090:            }
1091:
1092:            public DocumentListener[] getDocumentListeners() {
1093:                return listenerList.getListeners(DocumentListener.class);
1094:            }
1095:
1096:            public Dictionary<Object, Object> getDocumentProperties() {
1097:                return docProperties;
1098:            }
1099:
1100:            public final Position getEndPosition() {
1101:                return docEnd;
1102:            }
1103:
1104:            public int getLength() {
1105:                return content.length() - 1;
1106:            }
1107:
1108:            public <T extends EventListener> T[] getListeners(
1109:                    final Class<T> listenerType) {
1110:                return listenerList.getListeners(listenerType);
1111:            }
1112:
1113:            public final Object getProperty(final Object key) {
1114:                return getDocumentProperties().get(key);
1115:            }
1116:
1117:            public Element[] getRootElements() {
1118:                return new Element[] { getDefaultRootElement(),
1119:                        getBidiRootElement() };
1120:            }
1121:
1122:            public final Position getStartPosition() {
1123:                return docStart;
1124:            }
1125:
1126:            public String getText(final int offset, final int length)
1127:                    throws BadLocationException {
1128:
1129:                return content.getString(offset, length);
1130:            }
1131:
1132:            public void getText(final int offset, final int length,
1133:                    final Segment text) throws BadLocationException {
1134:
1135:                content.getChars(offset, length, text);
1136:            }
1137:
1138:            public UndoableEditListener[] getUndoableEditListeners() {
1139:                return listenerList.getListeners(UndoableEditListener.class);
1140:            }
1141:
1142:            public void insertString(final int offset, final String text,
1143:                    final AttributeSet attrs) throws BadLocationException {
1144:
1145:                if (org.apache.harmony.x.swing.Utilities.isEmptyString(text)) {
1146:                    return;
1147:                }
1148:
1149:                writeLock();
1150:                try {
1151:                    if (docFilter != null) {
1152:                        docFilter.insertString(filterBypasser, offset, text,
1153:                                attrs);
1154:                    } else {
1155:                        doInsert(offset, text, attrs);
1156:                    }
1157:                } finally {
1158:                    writeUnlock();
1159:                }
1160:            }
1161:
1162:            public final void putProperty(final Object key, final Object value) {
1163:                if (value == null) {
1164:                    getDocumentProperties().remove(key);
1165:                } else {
1166:                    getDocumentProperties().put(key, value);
1167:                }
1168:            }
1169:
1170:            public final void readLock() {
1171:                lock.readLock();
1172:            }
1173:
1174:            public final void readUnlock() {
1175:                lock.readUnlock();
1176:            }
1177:
1178:            public void remove(final int offset, final int length)
1179:                    throws BadLocationException {
1180:
1181:                writeLock();
1182:                try {
1183:                    if (docFilter != null) {
1184:                        docFilter.remove(filterBypasser, offset, length);
1185:                    } else {
1186:                        doRemove(offset, length);
1187:                    }
1188:                } finally {
1189:                    writeUnlock();
1190:                }
1191:            }
1192:
1193:            public void removeDocumentListener(final DocumentListener listener) {
1194:                listenerList.remove(DocumentListener.class, listener);
1195:            }
1196:
1197:            public void removeUndoableEditListener(
1198:                    final UndoableEditListener listener) {
1199:                listenerList.remove(UndoableEditListener.class, listener);
1200:            }
1201:
1202:            public void render(final Runnable r) {
1203:                readLock();
1204:                try {
1205:                    r.run();
1206:                } finally {
1207:                    readUnlock();
1208:                }
1209:            }
1210:
1211:            public void replace(final int offset, final int length,
1212:                    final String newText, final AttributeSet attrs)
1213:                    throws BadLocationException {
1214:
1215:                writeLock();
1216:
1217:                try {
1218:                    if (docFilter != null) {
1219:                        docFilter.replace(filterBypasser, offset, length,
1220:                                newText, attrs);
1221:                    } else {
1222:                        doReplace(offset, length, newText, attrs);
1223:                    }
1224:                } finally {
1225:                    writeUnlock();
1226:                }
1227:            }
1228:
1229:            public void setAsynchronousLoadPriority(final int priority) {
1230:                putProperty(PropertyNames.LOAD_PRIORITY, new Integer(priority));
1231:            }
1232:
1233:            public void setDocumentFilter(final DocumentFilter filter) {
1234:                this .docFilter = filter;
1235:            }
1236:
1237:            public void setDocumentProperties(
1238:                    final Dictionary<Object, Object> properties) {
1239:                this .docProperties = properties;
1240:            }
1241:
1242:            protected Element createBranchElement(final Element parent,
1243:                    final AttributeSet as) {
1244:                return new BranchElement(parent, as);
1245:            }
1246:
1247:            protected Element createLeafElement(final Element parent,
1248:                    final AttributeSet as, final int start, final int end) {
1249:                return new LeafElement(parent, as, start, end);
1250:            }
1251:
1252:            protected void fireChangedUpdate(final DocumentEvent event) {
1253:                lock.setCallingListeners(true);
1254:
1255:                try {
1256:                    DocumentListener[] listeners = getDocumentListeners();
1257:                    for (DocumentListener listener : listeners) {
1258:                        listener.changedUpdate(event);
1259:                    }
1260:                } finally {
1261:                    lock.setCallingListeners(false);
1262:                }
1263:            }
1264:
1265:            protected void fireInsertUpdate(final DocumentEvent event) {
1266:                lock.setCallingListeners(true);
1267:
1268:                try {
1269:                    DocumentListener[] listeners = getDocumentListeners();
1270:                    for (DocumentListener listener : listeners) {
1271:                        listener.insertUpdate(event);
1272:                    }
1273:                } finally {
1274:                    lock.setCallingListeners(false);
1275:                }
1276:            }
1277:
1278:            protected void fireRemoveUpdate(final DocumentEvent event) {
1279:                lock.setCallingListeners(true);
1280:
1281:                try {
1282:                    DocumentListener[] listeners = getDocumentListeners();
1283:                    for (DocumentListener listener : listeners) {
1284:                        listener.removeUpdate(event);
1285:                    }
1286:                } finally {
1287:                    lock.setCallingListeners(false);
1288:                }
1289:            }
1290:
1291:            protected void fireUndoableEditUpdate(final UndoableEditEvent event) {
1292:                lock.setCallingListeners(true);
1293:
1294:                try {
1295:                    UndoableEditListener[] listeners = getUndoableEditListeners();
1296:                    for (UndoableEditListener listener : listeners) {
1297:                        listener.undoableEditHappened(event);
1298:                    }
1299:                } finally {
1300:                    lock.setCallingListeners(false);
1301:                }
1302:            }
1303:
1304:            protected final AttributeContext getAttributeContext() {
1305:                return context;
1306:            }
1307:
1308:            protected final Content getContent() {
1309:                return content;
1310:            }
1311:
1312:            protected final Thread getCurrentWriter() {
1313:                return lock.getCurrentWriter();
1314:            }
1315:
1316:            protected void insertUpdate(final DefaultDocumentEvent event,
1317:                    final AttributeSet attrs) {
1318:                final int offset = event.getOffset();
1319:                final int length = event.getLength();
1320:
1321:                final Segment text = new Segment();
1322:
1323:                try {
1324:                    content.getChars(offset, length, text);
1325:                } catch (final BadLocationException e) {
1326:                }
1327:
1328:                if (!bidiUpdateProperty(offset, text)) {
1329:                    return;
1330:                }
1331:
1332:                final List<Element> added = new ArrayList<Element>();
1333:                Element par;
1334:                int nextOffset = offset;
1335:                do {
1336:                    par = getParagraphElement(nextOffset);
1337:                    bidiParseParagraph(added, par, text);
1338:
1339:                    nextOffset = par.getEndOffset();
1340:                } while (par.getEndOffset() < offset + length);
1341:
1342:                bidiUpdateStructure(event, added);
1343:            }
1344:
1345:            protected void postRemoveUpdate(final DefaultDocumentEvent event) {
1346:                if (!hasBidiInfo()) {
1347:                    return;
1348:                }
1349:
1350:                final List<Element> added = new ArrayList<Element>();
1351:
1352:                bidiParseParagraph(added,
1353:                        getParagraphElement(event.getOffset()), new Segment());
1354:
1355:                bidiUpdateStructure(event, added);
1356:            }
1357:
1358:            protected void removeUpdate(final DefaultDocumentEvent event) {
1359:            }
1360:
1361:            protected final void writeLock() {
1362:                lock.writeLock();
1363:            }
1364:
1365:            protected final void writeUnlock() {
1366:                lock.writeUnlock();
1367:            }
1368:
1369:            void doInsert(final int offset, final String text,
1370:                    final AttributeSet attrs) throws BadLocationException {
1371:
1372:                final DefaultDocumentEvent event = new DefaultDocumentEvent(
1373:                        offset, text.length(), EventType.INSERT);
1374:
1375:                final UndoableEdit contentEdit = content.insertString(offset,
1376:                        text);
1377:                if (contentEdit != null) {
1378:                    event.addEdit(contentEdit);
1379:                }
1380:
1381:                insertUpdate(event, attrs);
1382:
1383:                event.end();
1384:
1385:                fireInsertUpdate(event);
1386:                if (contentEdit != null) {
1387:                    fireUndoableEditUpdate(new UndoableEditEvent(this , event));
1388:                }
1389:            }
1390:
1391:            final void doRemove(final int offset, final int length)
1392:                    throws BadLocationException {
1393:
1394:                if (length == 0) {
1395:                    return;
1396:                }
1397:
1398:                if (offset < 0 || offset > getLength()) {
1399:                    throw new BadLocationException(Messages
1400:                            .getString("swing.7F"), offset); //$NON-NLS-1$
1401:                }
1402:
1403:                if (offset + length > getLength()) {
1404:                    throw new BadLocationException(Messages
1405:                            .getString("swing.80"), //$NON-NLS-1$
1406:                            offset + length);
1407:                }
1408:
1409:                final DefaultDocumentEvent event = new DefaultDocumentEvent(
1410:                        offset, length, EventType.REMOVE);
1411:
1412:                removeUpdate(event);
1413:
1414:                final UndoableEdit contentEdit = content.remove(offset, length);
1415:                if (contentEdit != null) {
1416:                    event.addEdit(contentEdit);
1417:                }
1418:
1419:                postRemoveUpdate(event);
1420:
1421:                event.end();
1422:
1423:                fireRemoveUpdate(event);
1424:                if (contentEdit != null) {
1425:                    fireUndoableEditUpdate(new UndoableEditEvent(this , event));
1426:                }
1427:            }
1428:
1429:            final void doReplace(final int offset, final int length,
1430:                    final String newText, final AttributeSet attrs)
1431:                    throws BadLocationException {
1432:
1433:                if (length > 0) {
1434:                    doRemove(offset, length);
1435:                }
1436:
1437:                if (!org.apache.harmony.x.swing.Utilities
1438:                        .isEmptyString(newText)) {
1439:                    doInsert(offset, newText, attrs);
1440:                }
1441:            }
1442:
1443:            final boolean isLeftToRight(final int offset) {
1444:                final Element e = bidiRoot.getElement(bidiRoot
1445:                        .getElementIndex(offset));
1446:                return TextUtils.isLTR(getBidiLevel(e));
1447:            }
1448:
1449:            private int bidiAdjustFirstElement(final List<Element> added,
1450:                    final Element par) {
1451:                int prevParIndex = bidiRoot.getElementIndex(par
1452:                        .getStartOffset() - 1);
1453:                final Element prevParBidi = bidiRoot.getElement(prevParIndex);
1454:                final Element firstAdded = added.get(0);
1455:
1456:                if (getBidiLevel(prevParBidi) == getBidiLevel(firstAdded)) {
1457:                    // Combine these two
1458:                    added.remove(0);
1459:                    added.add(0, new BidiElement(firstAdded.getAttributes(),
1460:                            prevParBidi.getStartOffset(), firstAdded
1461:                                    .getEndOffset()));
1462:                } else if (prevParBidi.getStartOffset() < firstAdded
1463:                        .getStartOffset()
1464:                        && prevParBidi.getEndOffset() > firstAdded
1465:                                .getStartOffset()) {
1466:                    // Divide prevParBidi
1467:                    added.add(0, new BidiElement(prevParBidi.getAttributes(),
1468:                            prevParBidi.getStartOffset(), firstAdded
1469:                                    .getStartOffset()));
1470:                } else if (prevParBidi.getStartOffset() != firstAdded
1471:                        .getStartOffset()) {
1472:                    // prevParBidi don't need to be deleted
1473:                    prevParIndex++;
1474:                }
1475:
1476:                return prevParIndex;
1477:            }
1478:
1479:            private int bidiAdjustLastElement(final List<Element> added) {
1480:                final Element lastAdded = added.get(added.size() - 1);
1481:                int nextParIndex = bidiRoot.getElementIndex(lastAdded
1482:                        .getEndOffset() + 1);
1483:                final Element nextParBidi = bidiRoot.getElement(nextParIndex);
1484:                if (nextParBidi == null) {
1485:                    return nextParIndex;
1486:                }
1487:
1488:                if (getBidiLevel(nextParBidi) == getBidiLevel(lastAdded)) {
1489:                    // Combine these two
1490:                    added.remove(added.size() - 1);
1491:                    added.add(new BidiElement(lastAdded.getAttributes(),
1492:                            lastAdded.getStartOffset(), nextParBidi
1493:                                    .getEndOffset()));
1494:                } else if (lastAdded.getEndOffset() > nextParBidi
1495:                        .getStartOffset()
1496:                        && lastAdded.getEndOffset() < nextParBidi
1497:                                .getEndOffset()) {
1498:                    // Divide nextParBidi
1499:                    added.add(new BidiElement(nextParBidi.getAttributes(),
1500:                            lastAdded.getEndOffset(), nextParBidi
1501:                                    .getEndOffset()));
1502:                } else if (nextParBidi.getEndOffset() != lastAdded
1503:                        .getEndOffset()) {
1504:                    // nextParBidi is left unchanged
1505:                    nextParIndex--;
1506:                }
1507:
1508:                return nextParIndex;
1509:            }
1510:
1511:            private void bidiParseParagraph(final List<Element> added,
1512:                    final Element par, final Segment text) {
1513:                final int parStart = par.getStartOffset();
1514:                final int parEnd = par.getEndOffset();
1515:                final int parLen = parEnd - parStart;
1516:
1517:                try {
1518:                    content.getChars(parStart, parLen, text);
1519:                } catch (final BadLocationException e) {
1520:                }
1521:
1522:                Bidi bidi = new Bidi(text.array, text.offset, null, 0,
1523:                        text.count, getDefaultDirection(par));
1524:
1525:                final int runCount = bidi.getRunCount();
1526:                for (int i = 0; i < runCount; i++) {
1527:                    int level = bidi.getRunLevel(i);
1528:
1529:                    if (i == 0 && added.size() > 0) {
1530:                        Element prevBidi = added.get(added.size() - 1);
1531:                        if (getBidiLevel(prevBidi) == level) {
1532:                            added.remove(added.size() - 1);
1533:                            added.add(new BidiElement(prevBidi.getAttributes(),
1534:                                    prevBidi.getStartOffset(), parStart
1535:                                            + bidi.getRunLimit(i)));
1536:                            continue;
1537:                        }
1538:                    }
1539:
1540:                    added.add(new BidiElement(context.addAttribute(context
1541:                            .getEmptySet(), StyleConstants.BidiLevel,
1542:                            new Integer(level)),
1543:                            parStart + bidi.getRunStart(i), parStart
1544:                                    + bidi.getRunLimit(i)));
1545:                }
1546:
1547:            }
1548:
1549:            private boolean bidiUpdateProperty(final int offset,
1550:                    final Segment text) {
1551:                final boolean hasBidiInfo = hasBidiInfo();
1552:
1553:                if (!hasBidiInfo
1554:                        && TextUtils.isLTR(getDefaultDirection(offset))
1555:                        && !Bidi.requiresBidi(text.array, text.offset,
1556:                                text.offset + text.count)) {
1557:
1558:                    return false;
1559:                }
1560:
1561:                final Bidi bidi = new Bidi(text.array, text.offset, null, 0,
1562:                        text.count, getDefaultDirection(offset));
1563:
1564:                if (hasBidiInfo && !bidi.isMixed()
1565:                        && isLeftToRight(offset) == bidi.isLeftToRight()) {
1566:
1567:                    return false;
1568:                }
1569:
1570:                if (!hasBidiInfo) {
1571:                    putProperty(StringConstants.BIDI_PROPERTY, Boolean.TRUE);
1572:                }
1573:                return true;
1574:            }
1575:
1576:            private void bidiUpdateStructure(final DefaultDocumentEvent event,
1577:                    final List<Element> added) {
1578:                Element par = getParagraphElement(event.getOffset());
1579:
1580:                int prevParIndex = bidiAdjustFirstElement(added, par);
1581:
1582:                int nextParIndex = bidiAdjustLastElement(added);
1583:                if (nextParIndex == -1) {
1584:                    nextParIndex = bidiRoot.getElementCount() - 1;
1585:                }
1586:
1587:                int removedLength = nextParIndex - prevParIndex + 1;
1588:                Element[] removed = new Element[removedLength];
1589:                System.arraycopy(bidiRoot.elements, prevParIndex, removed, 0,
1590:                        removedLength);
1591:
1592:                Element[] addedElements = added.toArray(new Element[added
1593:                        .size()]);
1594:                bidiRoot.replace(prevParIndex, removedLength, addedElements);
1595:
1596:                ElementEdit edit = new ElementEdit(bidiRoot, prevParIndex,
1597:                        removed, addedElements);
1598:                event.addEdit(edit);
1599:            }
1600:
1601:            private int getDefaultDirection(final Element par) {
1602:                Object runDirection = null;
1603:
1604:                if (par != null) {
1605:                    runDirection = par.getAttributes().getAttribute(
1606:                            TextAttribute.RUN_DIRECTION);
1607:
1608:                    if (runDirection != null) {
1609:                        return getDefaultDirection(runDirection);
1610:                    }
1611:                }
1612:
1613:                runDirection = getProperty(TextAttribute.RUN_DIRECTION);
1614:                if (runDirection != null) {
1615:                    return getDefaultDirection(runDirection);
1616:                } else {
1617:                    return Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
1618:                }
1619:            }
1620:
1621:            private int getDefaultDirection(final int offset) {
1622:                return getDefaultDirection(getParagraphElement(offset));
1623:            }
1624:
1625:            private boolean hasBidiInfo() {
1626:                final Object docProperty = getProperty(StringConstants.BIDI_PROPERTY);
1627:                return Boolean.TRUE.equals(docProperty);
1628:            }
1629:
1630:            private UIDefaults getUIDefaults() {
1631:                if (uiDefaults == null) {
1632:                    uiDefaults = new UIDefaults();
1633:                }
1634:
1635:                return uiDefaults;
1636:            }
1637:
1638:            private String getLocalizedString(final String key) {
1639:                Boolean isAWTDoc = (Boolean) getProperty(PropertyNames.AWT_DOCUMENT);
1640:                if (isAWTDoc != null && isAWTDoc.booleanValue()) {
1641:                    return getUIDefaults().getString(key);
1642:                } else {
1643:                    return UIManager.getString(key);
1644:                }
1645:            }
1646:
1647:            private void initTransientFields() {
1648:                try {
1649:                    docStart = content.createPosition(0);
1650:                    docEnd = content.createPosition(content.length());
1651:                } catch (final BadLocationException e) {
1652:                }
1653:
1654:                lock = new ReadWriteLock();
1655:
1656:                filterBypasser = new DocumentFilter.FilterBypass() {
1657:
1658:                    @Override
1659:                    public Document getDocument() {
1660:                        return AbstractDocument.this ;
1661:                    }
1662:
1663:                    @Override
1664:                    public void insertString(final int offset,
1665:                            final String text, final AttributeSet attrs)
1666:                            throws BadLocationException {
1667:
1668:                        doInsert(offset, text, attrs);
1669:                    }
1670:
1671:                    @Override
1672:                    public void remove(final int offset, final int length)
1673:                            throws BadLocationException {
1674:
1675:                        doRemove(offset, length);
1676:                    }
1677:
1678:                    @Override
1679:                    public void replace(final int offset, final int length,
1680:                            final String newText, final AttributeSet attrs)
1681:                            throws BadLocationException {
1682:
1683:                        doReplace(offset, length, newText, attrs);
1684:                    }
1685:
1686:                };
1687:
1688:                listenerList = new EventListenerList();
1689:            }
1690:
1691:            private void readObject(final ObjectInputStream ois)
1692:                    throws IOException, ClassNotFoundException {
1693:
1694:                ois.defaultReadObject();
1695:
1696:                context = (AttributeContext) ois.readObject();
1697:                content = (Content) ois.readObject();
1698:
1699:                initTransientFields();
1700:
1701:                bidiRoot = (BranchElement) ois.readObject();
1702:            }
1703:
1704:            private void writeObject(final ObjectOutputStream oos)
1705:                    throws IOException {
1706:                oos.defaultWriteObject();
1707:
1708:                oos.writeObject(context);
1709:                oos.writeObject(content);
1710:                oos.writeObject(bidiRoot);
1711:            }
1712:
1713:            private static int getBidiLevel(final Element e) {
1714:                return StyleConstants.getBidiLevel(e.getAttributes());
1715:            }
1716:
1717:            private static int getDefaultDirection(final Object runDirection) {
1718:                return TextAttribute.RUN_DIRECTION_LTR.equals(runDirection) ? Bidi.DIRECTION_LEFT_TO_RIGHT
1719:                        : Bidi.DIRECTION_RIGHT_TO_LEFT;
1720:            }
1721:
1722:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.