Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / javax / swing / text / AbstractDocument.java
bloba2c3fa65701fa19ab0b9667573aef1cf1d1e61ef
1 /* AbstractDocument.java --
2 Copyright (C) 2002, 2004, 2005 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)
9 any later version.
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
19 02111-1307 USA.
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
24 combination.
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.Dictionary;
44 import java.util.Enumeration;
45 import java.util.EventListener;
46 import java.util.Vector;
48 import javax.swing.event.DocumentEvent;
49 import javax.swing.event.DocumentListener;
50 import javax.swing.event.EventListenerList;
51 import javax.swing.event.UndoableEditEvent;
52 import javax.swing.event.UndoableEditListener;
53 import javax.swing.tree.TreeNode;
54 import javax.swing.undo.AbstractUndoableEdit;
55 import javax.swing.undo.CompoundEdit;
56 import javax.swing.undo.UndoableEdit;
58 public abstract class AbstractDocument
59 implements Document, Serializable
61 private static final long serialVersionUID = -116069779446114664L;
63 protected static final String BAD_LOCATION = "document location failure";
65 public static final String BidiElementName = "bidi level";
66 public static final String ContentElementName = "content";
67 public static final String ParagraphElementName = "paragraph";
68 public static final String SectionElementName = "section";
69 public static final String ElementNameAttribute = "$ename";
71 Content content;
72 AttributeContext context;
73 DocumentFilter documentFilter;
75 protected EventListenerList listenerList = new EventListenerList();
77 protected AbstractDocument(Content doc)
79 this(doc, StyleContext.getDefaultStyleContext());
82 protected AbstractDocument(Content doc, AttributeContext ctx)
84 content = doc;
85 context = ctx;
88 // These still need to be implemented by a derived class:
89 public abstract Element getParagraphElement(int pos);
91 public abstract Element getDefaultRootElement();
93 protected Element createBranchElement(Element parent,
94 AttributeSet attributes)
96 return new BranchElement(parent, attributes);
99 protected Element createLeafElement(Element parent, AttributeSet attributes,
100 int start, int end)
102 return new LeafElement(parent, attributes, start, end);
105 public Position createPosition(final int offset) throws BadLocationException
107 if (offset < 0 || offset > getLength())
108 throw new BadLocationException(getText(0, getLength()), offset);
110 return new Position()
112 public int getOffset()
114 return offset;
119 protected void fireChangedUpdate(DocumentEvent event)
121 DocumentListener[] listeners = getDocumentListeners();
123 for (int index = 0; index < listeners.length; ++index)
124 listeners[index].changedUpdate(event);
127 protected void fireInsertUpdate(DocumentEvent event)
129 DocumentListener[] listeners = getDocumentListeners();
131 for (int index = 0; index < listeners.length; ++index)
132 listeners[index].insertUpdate(event);
135 protected void fireRemoveUpdate(DocumentEvent event)
137 DocumentListener[] listeners = getDocumentListeners();
139 for (int index = 0; index < listeners.length; ++index)
140 listeners[index].removeUpdate(event);
143 protected void fireUndoableEditUpdate(UndoableEditEvent event)
145 UndoableEditListener[] listeners = getUndoableEditListeners();
147 for (int index = 0; index < listeners.length; ++index)
148 listeners[index].undoableEditHappened(event);
151 public int getAsynchronousLoadPriority()
153 return 0;
156 protected AttributeContext getAttributeContext()
158 return context;
161 public Element getBidiRootElement()
163 return null;
166 protected Content getContent()
168 return content;
171 protected Thread getCurrentWriter()
173 return null;
176 public Dictionary getDocumentProperties()
178 return null;
181 public Position getEndPosition()
183 return new Position()
185 public int getOffset()
187 return getLength();
192 public int getLength()
194 return content.length() - 1;
197 public EventListener[] getListeners(Class listenerType)
199 return listenerList.getListeners(listenerType);
202 public Object getProperty(Object key)
204 return null;
207 public Element[] getRootElements()
209 Element[] elements = new Element[1];
210 elements[0] = getDefaultRootElement();
211 return elements;
214 public Position getStartPosition()
216 return new Position()
218 public int getOffset()
220 return 0;
225 public String getText(int offset, int length) throws BadLocationException
227 return content.getString(offset, length);
230 public void getText(int offset, int length, Segment segment)
231 throws BadLocationException
233 content.getChars(offset, length, segment);
236 public void insertString(int offset, String text, AttributeSet attributes)
237 throws BadLocationException
239 // Just return when no text to insert was given.
240 if (text == null || text.length() == 0)
241 return;
243 DefaultDocumentEvent event =
244 new DefaultDocumentEvent(offset, text.length(),
245 DocumentEvent.EventType.INSERT);
246 content.insertString(offset, text);
247 insertUpdate(event, attributes);
248 fireInsertUpdate(event);
251 protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr)
255 protected void postRemoveUpdate(DefaultDocumentEvent chng)
259 public void putProperty(Object key, Object value)
263 public void readLock()
267 public void readUnlock()
271 public void remove(int offset, int length) throws BadLocationException
273 DefaultDocumentEvent event =
274 new DefaultDocumentEvent(offset, length,
275 DocumentEvent.EventType.REMOVE);
276 removeUpdate(event);
277 content.remove(offset, length);
278 postRemoveUpdate(event);
279 fireRemoveUpdate(event);
283 * Replaces some text in the document.
285 * @since 1.4
287 public void replace(int offset, int length, String text,
288 AttributeSet attributes)
289 throws BadLocationException
291 remove(offset, length);
292 insertString(offset, text, attributes);
296 * Adds a <code>DocumentListener</code> object to this document.
298 * @param listener the listener to add
300 public void addDocumentListener(DocumentListener listener)
302 listenerList.add(DocumentListener.class, listener);
306 * Removes a <code>DocumentListener</code> object from this document.
308 * @param listener the listener to remove
310 public void removeDocumentListener(DocumentListener listener)
312 listenerList.remove(DocumentListener.class, listener);
316 * Returns add added <code>DocumentListener</code> objects.
318 * @return an array of listeners
320 public DocumentListener[] getDocumentListeners()
322 return (DocumentListener[]) getListeners(DocumentListener.class);
326 * Adds a <code>UndoableEditListener</code> object to this document.
328 * @param listener the listener to add
330 public void addUndoableEditListener(UndoableEditListener listener)
332 listenerList.add(UndoableEditListener.class, listener);
336 * Removes a <code>UndoableEditListener</code> object from this document.
338 * @param listener the listener to remove
340 public void removeUndoableEditListener(UndoableEditListener listener)
342 listenerList.remove(UndoableEditListener.class, listener);
346 * Returns add added <code>UndoableEditListener</code> objects.
348 * @return an array of listeners
350 public UndoableEditListener[] getUndoableEditListeners()
352 return (UndoableEditListener[]) getListeners(UndoableEditListener.class);
355 protected void removeUpdate(DefaultDocumentEvent chng)
359 public void render(Runnable r)
363 public void setAsynchronousLoadPriority(int p)
367 public void setDocumentProperties(Dictionary x)
371 protected void writeLock()
375 protected void writeUnlock()
380 * @since 1.4
382 public DocumentFilter getDocumentFilter()
384 return documentFilter;
388 * @since 1.4
390 public void setDocumentFilter(DocumentFilter filter)
392 this.documentFilter = filter;
395 public void dump(PrintStream out)
397 ((AbstractElement) getDefaultRootElement()).dump(out, 0);
400 public interface AttributeContext
402 AttributeSet addAttribute(AttributeSet old, Object name, Object value);
404 AttributeSet addAttributes(AttributeSet old, AttributeSet attributes);
406 AttributeSet getEmptySet();
408 void reclaim(AttributeSet attributes);
410 AttributeSet removeAttribute(AttributeSet old, Object name);
412 AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes);
414 AttributeSet removeAttributes(AttributeSet old, Enumeration names);
417 public interface Content
419 Position createPosition(int offset) throws BadLocationException;
421 int length();
423 UndoableEdit insertString(int where, String str)
424 throws BadLocationException;
426 UndoableEdit remove(int where, int nitems) throws BadLocationException;
428 String getString(int where, int len) throws BadLocationException;
430 void getChars(int where, int len, Segment txt) throws BadLocationException;
433 public abstract class AbstractElement
434 implements Element, MutableAttributeSet, TreeNode, Serializable
436 private static final long serialVersionUID = 1265312733007397733L;
437 int count;
438 int offset;
440 AttributeSet attributes;
442 Element element_parent;
444 TreeNode tree_parent;
445 Vector tree_children;
447 public AbstractElement(Element p, AttributeSet s)
449 element_parent = p;
450 attributes = s;
453 // TreeNode implementation
455 public abstract Enumeration children();
457 public abstract boolean getAllowsChildren();
459 public TreeNode getChildAt(int index)
461 return (TreeNode) tree_children.get(index);
464 public int getChildCount()
466 return tree_children.size();
469 public int getIndex(TreeNode node)
471 return tree_children.indexOf(node);
474 public TreeNode getParent()
476 return tree_parent;
479 public abstract boolean isLeaf();
482 // MutableAttributeSet support
484 public void addAttribute(Object name, Object value)
486 attributes = getAttributeContext().addAttribute(attributes, name, value);
489 public void addAttributes(AttributeSet attrs)
491 attributes = getAttributeContext().addAttributes(attributes, attrs);
494 public void removeAttribute(Object name)
496 attributes = getAttributeContext().removeAttribute(attributes, name);
499 public void removeAttributes(AttributeSet attrs)
501 attributes = getAttributeContext().removeAttributes(attributes, attrs);
504 public void removeAttributes(Enumeration names)
506 attributes = getAttributeContext().removeAttributes(attributes, names);
509 public void setResolveParent(AttributeSet parent)
511 attributes = getAttributeContext().addAttribute(attributes, ResolveAttribute, parent);
515 // AttributeSet interface support
517 public boolean containsAttribute(Object name, Object value)
519 return attributes.containsAttribute(name, value);
522 public boolean containsAttributes(AttributeSet attrs)
524 return attributes.containsAttributes(attrs);
527 public AttributeSet copyAttributes()
529 return attributes.copyAttributes();
532 public Object getAttribute(Object key)
534 return attributes.getAttribute(key);
537 public int getAttributeCount()
539 return attributes.getAttributeCount();
542 public Enumeration getAttributeNames()
544 return attributes.getAttributeNames();
547 public AttributeSet getResolveParent()
549 return attributes.getResolveParent();
552 public boolean isDefined(Object attrName)
554 return attributes.isDefined(attrName);
557 public boolean isEqual(AttributeSet attrs)
559 return attributes.isEqual(attrs);
562 // Element interface support
564 public AttributeSet getAttributes()
566 return attributes;
569 public Document getDocument()
571 return AbstractDocument.this;
574 public abstract Element getElement(int index);
576 public String getName()
578 return (String) getAttribute(NameAttribute);
581 public Element getParentElement()
583 return element_parent;
586 public abstract int getEndOffset();
588 public abstract int getElementCount();
590 public abstract int getElementIndex(int offset);
592 public abstract int getStartOffset();
594 private void dumpElement(PrintStream stream, String indent, Element element)
596 System.out.println(indent + "<" + element.getName() +">");
598 if (element.isLeaf())
600 int start = element.getStartOffset();
601 int end = element.getEndOffset();
602 String text = "";
605 text = getContent().getString(start, end - start);
607 catch (BadLocationException e)
610 System.out.println(indent + " ["
611 + start + ","
612 + end + "]["
613 + text + "]");
615 else
617 for (int i = 0; i < element.getElementCount(); ++i)
618 dumpElement(stream, indent + " ", element.getElement(i));
622 public void dump(PrintStream stream, int indent)
624 String indentStr = "";
625 for (int i = 0; i < indent; ++i)
626 indentStr += " ";
627 dumpElement(stream, indentStr, this);
631 public class BranchElement extends AbstractElement
633 private static final long serialVersionUID = -8595176318868717313L;
635 private Element[] children = new Element[0];
637 public BranchElement(Element parent, AttributeSet attributes)
639 super(parent, attributes);
642 public Enumeration children()
644 if (children.length == 0)
645 return null;
647 Vector tmp = new Vector();
649 for (int index = 0; index < children.length; ++index)
650 tmp.add(children[index]);
652 return tmp.elements();
655 public boolean getAllowsChildren()
657 return true;
660 public Element getElement(int index)
662 if (index < 0 || index >= children.length)
663 return null;
665 return children[index];
668 public int getElementCount()
670 return children.length;
673 public int getElementIndex(int offset)
675 // XXX: There is surely a better algorithm
676 // as beginning from first element each time.
677 for (int index = 0; index < children.length; ++index)
679 Element elem = children[index];
681 if ((elem.getStartOffset() <= offset)
682 && (offset < elem.getEndOffset()))
683 return index;
686 return 0;
689 public int getEndOffset()
691 return children[children.length - 1].getEndOffset();
694 public String getName()
696 return ParagraphElementName;
699 public int getStartOffset()
701 return children[0].getStartOffset();
704 public boolean isLeaf()
706 return false;
709 public Element positionToElement(int position)
711 // XXX: There is surely a better algorithm
712 // as beginning from first element each time.
713 for (int index = 0; index < children.length; ++index)
715 Element elem = children[index];
717 if ((elem.getStartOffset() <= position)
718 && (position < elem.getEndOffset()))
719 return elem;
722 return null;
725 public void replace(int offset, int length, Element[] elements)
727 Element[] target = new Element[children.length - length
728 + elements.length];
729 System.arraycopy(children, 0, target, 0, offset);
730 System.arraycopy(elements, 0, target, offset, elements.length);
731 System.arraycopy(children, offset + length, target,
732 offset + elements.length,
733 children.length - offset - length);
734 children = target;
737 public String toString()
739 return ("BranchElement(" + getName() + ") "
740 + getStartOffset() + "," + getEndOffset() + "\n");
744 public class DefaultDocumentEvent extends CompoundEdit
745 implements DocumentEvent
747 private static final long serialVersionUID = -7406103236022413522L;
749 private int offset;
750 private int length;
751 private DocumentEvent.EventType type;
753 public DefaultDocumentEvent(int offset, int length,
754 DocumentEvent.EventType type)
756 this.offset = offset;
757 this.length = length;
758 this.type = type;
761 public Document getDocument()
763 return AbstractDocument.this;
766 public int getLength()
768 return length;
771 public int getOffset()
773 return offset;
776 public DocumentEvent.EventType getType()
778 return type;
781 public DocumentEvent.ElementChange getChange(Element elem)
783 return null;
787 public static class ElementEdit extends AbstractUndoableEdit
788 implements DocumentEvent.ElementChange
790 private static final long serialVersionUID = -1216620962142928304L;
792 private Element elem;
793 private int index;
794 private Element[] removed;
795 private Element[] added;
797 public ElementEdit(Element elem, int index,
798 Element[] removed, Element[] added)
800 this.elem = elem;
801 this.index = index;
802 this.removed = removed;
803 this.added = added;
806 public Element[] getChildrenAdded()
808 return added;
811 public Element[] getChildrenRemoved()
813 return removed;
816 public Element getElement()
818 return elem;
821 public int getIndex()
823 return index;
827 public class LeafElement extends AbstractElement
829 private static final long serialVersionUID = 5115368706941283802L;
830 private int start;
831 private int end;
833 public LeafElement(Element parent, AttributeSet attributes, int start,
834 int end)
836 super(parent, attributes);
837 this.start = start;
838 this.end = end;
841 public Enumeration children()
843 return null;
846 public boolean getAllowsChildren()
848 return false;
851 public Element getElement(int index)
853 return null;
856 public int getElementCount()
858 return 0;
861 public int getElementIndex(int offset)
863 return -1;
866 public int getEndOffset()
868 return end;
871 public String getName()
873 return ContentElementName;
876 public int getStartOffset()
878 return start;
881 public boolean isLeaf()
883 return true;
886 public String toString()
888 return ("LeafElement(" + getName() + ") "
889 + getStartOffset() + "," + getEndOffset() + "\n");