1 /* AbstractDocument.java --
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax
.swing
.text
;
41 import java
.io
.PrintStream
;
42 import java
.io
.Serializable
;
43 import java
.util
.Collections
;
44 import java
.util
.Dictionary
;
45 import java
.util
.Enumeration
;
46 import java
.util
.EventListener
;
47 import java
.util
.Vector
;
49 import javax
.swing
.event
.DocumentEvent
;
50 import javax
.swing
.event
.DocumentListener
;
51 import javax
.swing
.event
.EventListenerList
;
52 import javax
.swing
.event
.UndoableEditEvent
;
53 import javax
.swing
.event
.UndoableEditListener
;
54 import javax
.swing
.tree
.TreeNode
;
55 import javax
.swing
.undo
.AbstractUndoableEdit
;
56 import javax
.swing
.undo
.CompoundEdit
;
57 import javax
.swing
.undo
.UndoableEdit
;
59 public abstract class AbstractDocument
60 implements Document
, Serializable
62 private static final long serialVersionUID
= -116069779446114664L;
63 protected static final String BAD_LOCATION
= "document location failure";
64 public static final String BidiElementName
= "bidi level";
65 public static final String ContentElementName
= "content";
66 public static final String ParagraphElementName
= "paragraph";
67 public static final String SectionElementName
= "section";
68 public static final String ElementNameAttribute
= "$ename";
71 AttributeContext context
;
72 protected EventListenerList listenerList
= new EventListenerList();
74 protected AbstractDocument(Content doc
)
76 this(doc
, StyleContext
.getDefaultStyleContext());
79 protected AbstractDocument(Content doc
, AttributeContext ctx
)
85 // These still need to be implemented by a derived class:
86 public abstract Element
getParagraphElement(int pos
);
88 public abstract Element
getDefaultRootElement();
90 protected Element
createBranchElement(Element parent
,
91 AttributeSet attributes
)
93 return new BranchElement(parent
, attributes
);
96 protected Element
createLeafElement(Element parent
, AttributeSet attributes
,
99 return new LeafElement(parent
, attributes
, start
, end
);
102 public Position
createPosition(final int offset
) throws BadLocationException
104 if (offset
< 0 || offset
> getLength())
105 throw new BadLocationException(getText(0, getLength()), offset
);
107 return new Position()
109 public int getOffset()
116 protected void fireChangedUpdate(DocumentEvent event
)
118 DocumentListener
[] listeners
= getDocumentListeners();
120 for (int index
= 0; index
< listeners
.length
; ++index
)
121 listeners
[index
].changedUpdate(event
);
124 protected void fireInsertUpdate(DocumentEvent event
)
126 DocumentListener
[] listeners
= getDocumentListeners();
128 for (int index
= 0; index
< listeners
.length
; ++index
)
129 listeners
[index
].insertUpdate(event
);
132 protected void fireRemoveUpdate(DocumentEvent event
)
134 DocumentListener
[] listeners
= getDocumentListeners();
136 for (int index
= 0; index
< listeners
.length
; ++index
)
137 listeners
[index
].removeUpdate(event
);
140 protected void fireUndoableEditUpdate(UndoableEditEvent event
)
142 UndoableEditListener
[] listeners
= getUndoableEditListeners();
144 for (int index
= 0; index
< listeners
.length
; ++index
)
145 listeners
[index
].undoableEditHappened(event
);
148 public int getAsynchronousLoadPriority()
153 protected AttributeContext
getAttributeContext()
158 public Element
getBidiRootElement()
163 protected Content
getContent()
168 protected Thread
getCurrentWriter()
173 public Dictionary
getDocumentProperties()
178 public Position
getEndPosition()
180 return new Position()
182 public int getOffset()
189 public int getLength()
191 return content
.length() - 1;
194 public EventListener
[] getListeners(Class listenerType
)
196 return listenerList
.getListeners(listenerType
);
199 public Object
getProperty(Object key
)
204 public Element
[] getRootElements()
206 Element
[] elements
= new Element
[1];
207 elements
[0] = getDefaultRootElement();
211 public Position
getStartPosition()
213 return new Position()
215 public int getOffset()
222 public String
getText(int offset
, int length
) throws BadLocationException
224 return content
.getString(offset
, length
);
227 public void getText(int offset
, int length
, Segment segment
)
228 throws BadLocationException
230 content
.getChars(offset
, length
, segment
);
233 public void insertString(int offset
, String text
, AttributeSet attributes
)
234 throws BadLocationException
236 // Just return when no text to insert was given.
237 if (text
== null || text
.length() == 0)
240 DefaultDocumentEvent event
=
241 new DefaultDocumentEvent(offset
, text
.length(),
242 DocumentEvent
.EventType
.INSERT
);
243 content
.insertString(offset
, text
);
244 insertUpdate(event
, attributes
);
245 fireInsertUpdate(event
);
248 protected void insertUpdate(DefaultDocumentEvent chng
, AttributeSet attr
)
252 protected void postRemoveUpdate(DefaultDocumentEvent chng
)
256 public void putProperty(Object key
, Object value
)
260 public void readLock()
264 public void readUnlock()
268 public void remove(int offset
, int length
) throws BadLocationException
270 DefaultDocumentEvent event
=
271 new DefaultDocumentEvent(offset
, length
,
272 DocumentEvent
.EventType
.REMOVE
);
274 content
.remove(offset
, length
);
275 postRemoveUpdate(event
);
276 fireRemoveUpdate(event
);
280 * Replaces some text in the document.
284 public void replace(int offset
, int length
, String text
,
285 AttributeSet attributes
)
286 throws BadLocationException
288 remove(offset
, length
);
289 insertString(offset
, text
, attributes
);
293 * Adds a <code>DocumentListener</code> object to this document.
295 * @param listener the listener to add
297 public void addDocumentListener(DocumentListener listener
)
299 listenerList
.add(DocumentListener
.class, listener
);
303 * Removes a <code>DocumentListener</code> object from this document.
305 * @param listener the listener to remove
307 public void removeDocumentListener(DocumentListener listener
)
309 listenerList
.remove(DocumentListener
.class, listener
);
313 * Returns add added <code>DocumentListener</code> objects.
315 * @return an array of listeners
317 public DocumentListener
[] getDocumentListeners()
319 return (DocumentListener
[]) getListeners(DocumentListener
.class);
323 * Adds a <code>UndoableEditListener</code> object to this document.
325 * @param listener the listener to add
327 public void addUndoableEditListener(UndoableEditListener listener
)
329 listenerList
.add(UndoableEditListener
.class, listener
);
333 * Removes a <code>UndoableEditListener</code> object from this document.
335 * @param listener the listener to remove
337 public void removeUndoableEditListener(UndoableEditListener listener
)
339 listenerList
.remove(UndoableEditListener
.class, listener
);
343 * Returns add added <code>UndoableEditListener</code> objects.
345 * @return an array of listeners
347 public UndoableEditListener
[] getUndoableEditListeners()
349 return (UndoableEditListener
[]) getListeners(UndoableEditListener
.class);
352 protected void removeUpdate(DefaultDocumentEvent chng
)
356 public void render(Runnable r
)
360 public void setAsynchronousLoadPriority(int p
)
364 public void setDocumentProperties(Dictionary x
)
368 protected void writeLock()
372 protected void writeUnlock()
376 public interface AttributeContext
378 AttributeSet
addAttribute(AttributeSet old
, Object name
, Object value
);
380 AttributeSet
addAttributes(AttributeSet old
, AttributeSet attributes
);
382 AttributeSet
getEmptySet();
384 void reclaim(AttributeSet attributes
);
386 AttributeSet
removeAttribute(AttributeSet old
, Object name
);
388 AttributeSet
removeAttributes(AttributeSet old
, AttributeSet attributes
);
390 AttributeSet
removeAttributes(AttributeSet old
, Enumeration names
);
393 public interface Content
395 Position
createPosition(int offset
) throws BadLocationException
;
399 UndoableEdit
insertString(int where
, String str
)
400 throws BadLocationException
;
402 UndoableEdit
remove(int where
, int nitems
) throws BadLocationException
;
404 String
getString(int where
, int len
) throws BadLocationException
;
406 void getChars(int where
, int len
, Segment txt
) throws BadLocationException
;
409 public abstract class AbstractElement
410 implements Element
, MutableAttributeSet
, TreeNode
, Serializable
412 private static final long serialVersionUID
= 1265312733007397733L;
416 AttributeSet attributes
;
418 Element element_parent
;
419 Vector element_children
;
421 TreeNode tree_parent
;
422 Vector tree_children
;
424 public AbstractElement(Element p
, AttributeSet s
)
430 // TreeNode implementation
432 public abstract Enumeration
children();
434 public abstract boolean getAllowsChildren();
436 public TreeNode
getChildAt(int index
)
438 return (TreeNode
) tree_children
.get(index
);
441 public int getChildCount()
443 return tree_children
.size();
446 public int getIndex(TreeNode node
)
448 return tree_children
.indexOf(node
);
451 public TreeNode
getParent()
456 public abstract boolean isLeaf();
459 // MutableAttributeSet support
461 public void addAttribute(Object name
, Object value
)
463 attributes
= getAttributeContext().addAttribute(attributes
, name
, value
);
466 public void addAttributes(AttributeSet attrs
)
468 attributes
= getAttributeContext().addAttributes(attributes
, attrs
);
471 public void removeAttribute(Object name
)
473 attributes
= getAttributeContext().removeAttribute(attributes
, name
);
476 public void removeAttributes(AttributeSet attrs
)
478 attributes
= getAttributeContext().removeAttributes(attributes
, attrs
);
481 public void removeAttributes(Enumeration names
)
483 attributes
= getAttributeContext().removeAttributes(attributes
, names
);
486 public void setResolveParent(AttributeSet parent
)
488 attributes
= getAttributeContext().addAttribute(attributes
, ResolveAttribute
, parent
);
492 // AttributeSet interface support
494 public boolean containsAttribute(Object name
, Object value
)
496 return attributes
.containsAttribute(name
, value
);
499 public boolean containsAttributes(AttributeSet attrs
)
501 return attributes
.containsAttributes(attrs
);
504 public AttributeSet
copyAttributes()
506 return attributes
.copyAttributes();
509 public Object
getAttribute(Object key
)
511 return attributes
.getAttribute(key
);
514 public int getAttributeCount()
516 return attributes
.getAttributeCount();
519 public Enumeration
getAttributeNames()
521 return attributes
.getAttributeNames();
524 public AttributeSet
getResolveParent()
526 return attributes
.getResolveParent();
529 public boolean isDefined(Object attrName
)
531 return attributes
.isDefined(attrName
);
534 public boolean isEqual(AttributeSet attrs
)
536 return attributes
.isEqual(attrs
);
539 // Element interface support
541 public AttributeSet
getAttributes()
546 public Document
getDocument()
548 return AbstractDocument
.this;
551 public abstract Element
getElement(int index
);
553 public String
getName()
555 return (String
) getAttribute(NameAttribute
);
558 public Element
getParentElement()
560 return element_parent
;
563 public abstract int getEndOffset();
565 public abstract int getElementCount();
567 public abstract int getElementIndex(int offset
);
569 public abstract int getStartOffset();
571 private void dumpElement(PrintStream stream
, String indent
, Element element
)
573 System
.out
.println(indent
+ "<" + element
.getName() +">");
575 if (element
.isLeaf())
577 int start
= element
.getStartOffset();
578 int end
= element
.getEndOffset();
582 text
= getContent().getString(start
, end
- start
);
584 catch (BadLocationException e
)
587 System
.out
.println(indent
+ " ["
594 for (int i
= 0; i
< element
.getElementCount(); ++i
)
595 dumpElement(stream
, indent
+ " ", element
.getElement(i
));
599 public void dump(PrintStream stream
, int indent
)
601 String indentStr
= "";
602 for (int i
= 0; i
< indent
; ++i
)
604 dumpElement(stream
, indentStr
, this);
608 public class BranchElement
extends AbstractElement
610 private static final long serialVersionUID
= -8595176318868717313L;
612 private Vector children
= new Vector();
614 public BranchElement(Element parent
, AttributeSet attributes
)
616 super(parent
, attributes
);
619 public Enumeration
children()
621 return children
.elements();
624 public boolean getAllowsChildren()
629 public Element
getElement(int index
)
631 if (index
< 0 || index
>= children
.size())
634 return (Element
) children
.get(index
);
637 public int getElementCount()
639 return children
.size();
642 public int getElementIndex(int offset
)
644 if (children
.size() == 0)
647 Element element
= positionToElement(offset
);
652 return children
.indexOf(element
);
655 public int getEndOffset()
657 return ((Element
) children
.lastElement()).getEndOffset();
660 public String
getName()
662 return ParagraphElementName
;
665 public int getStartOffset()
667 return ((Element
) children
.firstElement()).getStartOffset();
670 public boolean isLeaf()
675 public Element
positionToElement(int position
)
677 // XXX: There is surely a better algorithm
678 // as beginning from first element each time.
679 for (int index
= 0; index
< children
.size(); ++index
)
681 Element elem
= (Element
) children
.get(index
);
683 if ((elem
.getStartOffset() <= position
)
684 && (position
< elem
.getEndOffset()))
691 public void replace(int offset
, int length
, Element
[] elems
)
693 for (int index
= 0; index
< length
; ++index
)
694 children
.removeElementAt(offset
);
696 for (int index
= 0; index
< elems
.length
; ++index
)
697 children
.add(offset
+ index
, elems
[index
]);
700 public String
toString()
702 return ("BranchElement(" + getName() + ") "
703 + getStartOffset() + "," + getEndOffset() + "\n");
707 public class DefaultDocumentEvent
extends CompoundEdit
708 implements DocumentEvent
710 private static final long serialVersionUID
= -7406103236022413522L;
714 private DocumentEvent
.EventType type
;
716 public DefaultDocumentEvent(int offset
, int length
,
717 DocumentEvent
.EventType type
)
719 this.offset
= offset
;
720 this.length
= length
;
724 public Document
getDocument()
726 return AbstractDocument
.this;
729 public int getLength()
734 public int getOffset()
739 public DocumentEvent
.EventType
getType()
744 public DocumentEvent
.ElementChange
getChange(Element elem
)
750 public static class ElementEdit
extends AbstractUndoableEdit
751 implements DocumentEvent
.ElementChange
753 private static final long serialVersionUID
= -1216620962142928304L;
755 private Element elem
;
757 private Element
[] removed
;
758 private Element
[] added
;
760 public ElementEdit(Element elem
, int index
,
761 Element
[] removed
, Element
[] added
)
765 this.removed
= removed
;
769 public Element
[] getChildrenAdded()
774 public Element
[] getChildrenRemoved()
779 public Element
getElement()
784 public int getIndex()
790 public class LeafElement
extends AbstractElement
792 private static final long serialVersionUID
= 5115368706941283802L;
796 public LeafElement(Element parent
, AttributeSet attributes
, int start
,
799 super(parent
, attributes
);
804 public Enumeration
children()
809 public boolean getAllowsChildren()
814 public Element
getElement(int index
)
819 public int getElementCount()
824 public int getElementIndex(int offset
)
829 public int getEndOffset()
834 public String
getName()
836 return ContentElementName
;
839 public int getStartOffset()
844 public boolean isLeaf()
849 public String
toString()
851 return ("LeafElement(" + getName() + ") "
852 + getStartOffset() + "," + getEndOffset() + "\n");