aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/text/AbstractDocument.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/text/AbstractDocument.java')
-rw-r--r--libjava/classpath/javax/swing/text/AbstractDocument.java912
1 files changed, 912 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/text/AbstractDocument.java b/libjava/classpath/javax/swing/text/AbstractDocument.java
new file mode 100644
index 0000000..c3a3d70
--- /dev/null
+++ b/libjava/classpath/javax/swing/text/AbstractDocument.java
@@ -0,0 +1,912 @@
+/* AbstractDocument.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.EventListenerList;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.event.UndoableEditListener;
+import javax.swing.tree.TreeNode;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CompoundEdit;
+import javax.swing.undo.UndoableEdit;
+
+public abstract class AbstractDocument
+ implements Document, Serializable
+{
+ private static final long serialVersionUID = -116069779446114664L;
+
+ protected static final String BAD_LOCATION = "document location failure";
+
+ public static final String BidiElementName = "bidi level";
+ public static final String ContentElementName = "content";
+ public static final String ParagraphElementName = "paragraph";
+ public static final String SectionElementName = "section";
+ public static final String ElementNameAttribute = "$ename";
+
+ Content content;
+ AttributeContext context;
+ DocumentFilter documentFilter;
+
+ /** The documents properties. */
+ Dictionary properties;
+
+ protected EventListenerList listenerList = new EventListenerList();
+
+ protected AbstractDocument(Content doc)
+ {
+ this(doc, StyleContext.getDefaultStyleContext());
+ }
+
+ protected AbstractDocument(Content doc, AttributeContext ctx)
+ {
+ content = doc;
+ context = ctx;
+ }
+
+ // These still need to be implemented by a derived class:
+ public abstract Element getParagraphElement(int pos);
+
+ public abstract Element getDefaultRootElement();
+
+ protected Element createBranchElement(Element parent,
+ AttributeSet attributes)
+ {
+ return new BranchElement(parent, attributes);
+ }
+
+ protected Element createLeafElement(Element parent, AttributeSet attributes,
+ int start, int end)
+ {
+ return new LeafElement(parent, attributes, start, end);
+ }
+
+ public Position createPosition(final int offset) throws BadLocationException
+ {
+ if (offset < 0 || offset > getLength())
+ throw new BadLocationException(getText(0, getLength()), offset);
+
+ return new Position()
+ {
+ public int getOffset()
+ {
+ return offset;
+ }
+ };
+ }
+
+ protected void fireChangedUpdate(DocumentEvent event)
+ {
+ DocumentListener[] listeners = getDocumentListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].changedUpdate(event);
+ }
+
+ protected void fireInsertUpdate(DocumentEvent event)
+ {
+ DocumentListener[] listeners = getDocumentListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].insertUpdate(event);
+ }
+
+ protected void fireRemoveUpdate(DocumentEvent event)
+ {
+ DocumentListener[] listeners = getDocumentListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].removeUpdate(event);
+ }
+
+ protected void fireUndoableEditUpdate(UndoableEditEvent event)
+ {
+ UndoableEditListener[] listeners = getUndoableEditListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].undoableEditHappened(event);
+ }
+
+ public int getAsynchronousLoadPriority()
+ {
+ return 0;
+ }
+
+ protected AttributeContext getAttributeContext()
+ {
+ return context;
+ }
+
+ public Element getBidiRootElement()
+ {
+ return null;
+ }
+
+ protected Content getContent()
+ {
+ return content;
+ }
+
+ protected Thread getCurrentWriter()
+ {
+ return null;
+ }
+
+ public Dictionary getDocumentProperties()
+ {
+ // FIXME: make me thread-safe
+ if (properties == null)
+ properties = new Hashtable();
+
+ return properties;
+ }
+
+ public Position getEndPosition()
+ {
+ return new Position()
+ {
+ public int getOffset()
+ {
+ return getLength();
+ }
+ };
+ }
+
+ public int getLength()
+ {
+ return content.length() - 1;
+ }
+
+ public EventListener[] getListeners(Class listenerType)
+ {
+ return listenerList.getListeners(listenerType);
+ }
+
+ public Object getProperty(Object key)
+ {
+ // FIXME: make me thread-safe
+ Object value = null;
+ if (properties != null)
+ value = properties.get(key);
+
+ return value;
+ }
+
+ public Element[] getRootElements()
+ {
+ Element[] elements = new Element[1];
+ elements[0] = getDefaultRootElement();
+ return elements;
+ }
+
+ public Position getStartPosition()
+ {
+ return new Position()
+ {
+ public int getOffset()
+ {
+ return 0;
+ }
+ };
+ }
+
+ public String getText(int offset, int length) throws BadLocationException
+ {
+ return content.getString(offset, length);
+ }
+
+ public void getText(int offset, int length, Segment segment)
+ throws BadLocationException
+ {
+ content.getChars(offset, length, segment);
+ }
+
+ public void insertString(int offset, String text, AttributeSet attributes)
+ throws BadLocationException
+ {
+ // Just return when no text to insert was given.
+ if (text == null || text.length() == 0)
+ return;
+
+ DefaultDocumentEvent event =
+ new DefaultDocumentEvent(offset, text.length(),
+ DocumentEvent.EventType.INSERT);
+ content.insertString(offset, text);
+ insertUpdate(event, attributes);
+ fireInsertUpdate(event);
+ }
+
+ protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr)
+ {
+ }
+
+ protected void postRemoveUpdate(DefaultDocumentEvent chng)
+ {
+ }
+
+ public void putProperty(Object key, Object value)
+ {
+ // FIXME: make me thread-safe
+ if (properties == null)
+ properties = new Hashtable();
+
+ properties.put(key, value);
+ }
+
+ public void readLock()
+ {
+ }
+
+ public void readUnlock()
+ {
+ }
+
+ public void remove(int offset, int length) throws BadLocationException
+ {
+ DefaultDocumentEvent event =
+ new DefaultDocumentEvent(offset, length,
+ DocumentEvent.EventType.REMOVE);
+ removeUpdate(event);
+ content.remove(offset, length);
+ postRemoveUpdate(event);
+ fireRemoveUpdate(event);
+ }
+
+ /**
+ * Replaces some text in the document.
+ *
+ * @since 1.4
+ */
+ public void replace(int offset, int length, String text,
+ AttributeSet attributes)
+ throws BadLocationException
+ {
+ remove(offset, length);
+ insertString(offset, text, attributes);
+ }
+
+ /**
+ * Adds a <code>DocumentListener</code> object to this document.
+ *
+ * @param listener the listener to add
+ */
+ public void addDocumentListener(DocumentListener listener)
+ {
+ listenerList.add(DocumentListener.class, listener);
+ }
+
+ /**
+ * Removes a <code>DocumentListener</code> object from this document.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeDocumentListener(DocumentListener listener)
+ {
+ listenerList.remove(DocumentListener.class, listener);
+ }
+
+ /**
+ * Returns add added <code>DocumentListener</code> objects.
+ *
+ * @return an array of listeners
+ */
+ public DocumentListener[] getDocumentListeners()
+ {
+ return (DocumentListener[]) getListeners(DocumentListener.class);
+ }
+
+ /**
+ * Adds a <code>UndoableEditListener</code> object to this document.
+ *
+ * @param listener the listener to add
+ */
+ public void addUndoableEditListener(UndoableEditListener listener)
+ {
+ listenerList.add(UndoableEditListener.class, listener);
+ }
+
+ /**
+ * Removes a <code>UndoableEditListener</code> object from this document.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeUndoableEditListener(UndoableEditListener listener)
+ {
+ listenerList.remove(UndoableEditListener.class, listener);
+ }
+
+ /**
+ * Returns add added <code>UndoableEditListener</code> objects.
+ *
+ * @return an array of listeners
+ */
+ public UndoableEditListener[] getUndoableEditListeners()
+ {
+ return (UndoableEditListener[]) getListeners(UndoableEditListener.class);
+ }
+
+ protected void removeUpdate(DefaultDocumentEvent chng)
+ {
+ }
+
+ public void render(Runnable r)
+ {
+ }
+
+ public void setAsynchronousLoadPriority(int p)
+ {
+ }
+
+ public void setDocumentProperties(Dictionary x)
+ {
+ // FIXME: make me thread-safe
+ properties = x;
+ }
+
+ protected void writeLock()
+ {
+ }
+
+ protected void writeUnlock()
+ {
+ }
+
+ /**
+ * @since 1.4
+ */
+ public DocumentFilter getDocumentFilter()
+ {
+ return documentFilter;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void setDocumentFilter(DocumentFilter filter)
+ {
+ this.documentFilter = filter;
+ }
+
+ public void dump(PrintStream out)
+ {
+ ((AbstractElement) getDefaultRootElement()).dump(out, 0);
+ }
+
+ public interface AttributeContext
+ {
+ AttributeSet addAttribute(AttributeSet old, Object name, Object value);
+
+ AttributeSet addAttributes(AttributeSet old, AttributeSet attributes);
+
+ AttributeSet getEmptySet();
+
+ void reclaim(AttributeSet attributes);
+
+ AttributeSet removeAttribute(AttributeSet old, Object name);
+
+ AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes);
+
+ AttributeSet removeAttributes(AttributeSet old, Enumeration names);
+ }
+
+ public interface Content
+ {
+ Position createPosition(int offset) throws BadLocationException;
+
+ int length();
+
+ UndoableEdit insertString(int where, String str)
+ throws BadLocationException;
+
+ UndoableEdit remove(int where, int nitems) throws BadLocationException;
+
+ String getString(int where, int len) throws BadLocationException;
+
+ void getChars(int where, int len, Segment txt) throws BadLocationException;
+ }
+
+ public abstract class AbstractElement
+ implements Element, MutableAttributeSet, TreeNode, Serializable
+ {
+ private static final long serialVersionUID = 1265312733007397733L;
+ int count;
+ int offset;
+
+ AttributeSet attributes;
+
+ Element element_parent;
+
+ TreeNode tree_parent;
+ Vector tree_children;
+
+ public AbstractElement(Element p, AttributeSet s)
+ {
+ element_parent = p;
+ attributes = s;
+ }
+
+ // TreeNode implementation
+
+ public abstract Enumeration children();
+
+ public abstract boolean getAllowsChildren();
+
+ public TreeNode getChildAt(int index)
+ {
+ return (TreeNode) tree_children.get(index);
+ }
+
+ public int getChildCount()
+ {
+ return tree_children.size();
+ }
+
+ public int getIndex(TreeNode node)
+ {
+ return tree_children.indexOf(node);
+ }
+
+ public TreeNode getParent()
+ {
+ return tree_parent;
+ }
+
+ public abstract boolean isLeaf();
+
+
+ // MutableAttributeSet support
+
+ public void addAttribute(Object name, Object value)
+ {
+ attributes = getAttributeContext().addAttribute(attributes, name, value);
+ }
+
+ public void addAttributes(AttributeSet attrs)
+ {
+ attributes = getAttributeContext().addAttributes(attributes, attrs);
+ }
+
+ public void removeAttribute(Object name)
+ {
+ attributes = getAttributeContext().removeAttribute(attributes, name);
+ }
+
+ public void removeAttributes(AttributeSet attrs)
+ {
+ attributes = getAttributeContext().removeAttributes(attributes, attrs);
+ }
+
+ public void removeAttributes(Enumeration names)
+ {
+ attributes = getAttributeContext().removeAttributes(attributes, names);
+ }
+
+ public void setResolveParent(AttributeSet parent)
+ {
+ attributes = getAttributeContext().addAttribute(attributes, ResolveAttribute, parent);
+ }
+
+
+ // AttributeSet interface support
+
+ public boolean containsAttribute(Object name, Object value)
+ {
+ return attributes.containsAttribute(name, value);
+ }
+
+ public boolean containsAttributes(AttributeSet attrs)
+ {
+ return attributes.containsAttributes(attrs);
+ }
+
+ public AttributeSet copyAttributes()
+ {
+ return attributes.copyAttributes();
+ }
+
+ public Object getAttribute(Object key)
+ {
+ return attributes.getAttribute(key);
+ }
+
+ public int getAttributeCount()
+ {
+ return attributes.getAttributeCount();
+ }
+
+ public Enumeration getAttributeNames()
+ {
+ return attributes.getAttributeNames();
+ }
+
+ public AttributeSet getResolveParent()
+ {
+ return attributes.getResolveParent();
+ }
+
+ public boolean isDefined(Object attrName)
+ {
+ return attributes.isDefined(attrName);
+ }
+
+ public boolean isEqual(AttributeSet attrs)
+ {
+ return attributes.isEqual(attrs);
+ }
+
+ // Element interface support
+
+ public AttributeSet getAttributes()
+ {
+ return attributes;
+ }
+
+ public Document getDocument()
+ {
+ return AbstractDocument.this;
+ }
+
+ public abstract Element getElement(int index);
+
+ public String getName()
+ {
+ return (String) getAttribute(NameAttribute);
+ }
+
+ public Element getParentElement()
+ {
+ return element_parent;
+ }
+
+ public abstract int getEndOffset();
+
+ public abstract int getElementCount();
+
+ public abstract int getElementIndex(int offset);
+
+ public abstract int getStartOffset();
+
+ private void dumpElement(PrintStream stream, String indent, Element element)
+ {
+ System.out.println(indent + "<" + element.getName() +">");
+
+ if (element.isLeaf())
+ {
+ int start = element.getStartOffset();
+ int end = element.getEndOffset();
+ String text = "";
+ try
+ {
+ text = getContent().getString(start, end - start);
+ }
+ catch (BadLocationException e)
+ {
+ }
+ System.out.println(indent + " ["
+ + start + ","
+ + end + "]["
+ + text + "]");
+ }
+ else
+ {
+ for (int i = 0; i < element.getElementCount(); ++i)
+ dumpElement(stream, indent + " ", element.getElement(i));
+ }
+ }
+
+ public void dump(PrintStream stream, int indent)
+ {
+ String indentStr = "";
+ for (int i = 0; i < indent; ++i)
+ indentStr += " ";
+ dumpElement(stream, indentStr, this);
+ }
+ }
+
+ public class BranchElement extends AbstractElement
+ {
+ private static final long serialVersionUID = -8595176318868717313L;
+
+ private Element[] children = new Element[0];
+
+ public BranchElement(Element parent, AttributeSet attributes)
+ {
+ super(parent, attributes);
+ }
+
+ public Enumeration children()
+ {
+ if (children.length == 0)
+ return null;
+
+ Vector tmp = new Vector();
+
+ for (int index = 0; index < children.length; ++index)
+ tmp.add(children[index]);
+
+ return tmp.elements();
+ }
+
+ public boolean getAllowsChildren()
+ {
+ return true;
+ }
+
+ public Element getElement(int index)
+ {
+ if (index < 0 || index >= children.length)
+ return null;
+
+ return children[index];
+ }
+
+ public int getElementCount()
+ {
+ return children.length;
+ }
+
+ public int getElementIndex(int offset)
+ {
+ // XXX: There is surely a better algorithm
+ // as beginning from first element each time.
+ for (int index = 0; index < children.length; ++index)
+ {
+ Element elem = children[index];
+
+ if ((elem.getStartOffset() <= offset)
+ && (offset < elem.getEndOffset()))
+ return index;
+ }
+
+ return 0;
+ }
+
+ public int getEndOffset()
+ {
+ return children[children.length - 1].getEndOffset();
+ }
+
+ public String getName()
+ {
+ return ParagraphElementName;
+ }
+
+ public int getStartOffset()
+ {
+ return children[0].getStartOffset();
+ }
+
+ public boolean isLeaf()
+ {
+ return false;
+ }
+
+ public Element positionToElement(int position)
+ {
+ // XXX: There is surely a better algorithm
+ // as beginning from first element each time.
+ for (int index = 0; index < children.length; ++index)
+ {
+ Element elem = children[index];
+
+ if ((elem.getStartOffset() <= position)
+ && (position < elem.getEndOffset()))
+ return elem;
+ }
+
+ return null;
+ }
+
+ public void replace(int offset, int length, Element[] elements)
+ {
+ Element[] target = new Element[children.length - length
+ + elements.length];
+ System.arraycopy(children, 0, target, 0, offset);
+ System.arraycopy(elements, 0, target, offset, elements.length);
+ System.arraycopy(children, offset + length, target,
+ offset + elements.length,
+ children.length - offset - length);
+ children = target;
+ }
+
+ public String toString()
+ {
+ return ("BranchElement(" + getName() + ") "
+ + getStartOffset() + "," + getEndOffset() + "\n");
+ }
+ }
+
+ public class DefaultDocumentEvent extends CompoundEdit
+ implements DocumentEvent
+ {
+ private static final long serialVersionUID = -7406103236022413522L;
+
+ private int offset;
+ private int length;
+ private DocumentEvent.EventType type;
+
+ public DefaultDocumentEvent(int offset, int length,
+ DocumentEvent.EventType type)
+ {
+ this.offset = offset;
+ this.length = length;
+ this.type = type;
+ }
+
+ public Document getDocument()
+ {
+ return AbstractDocument.this;
+ }
+
+ public int getLength()
+ {
+ return length;
+ }
+
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ public DocumentEvent.EventType getType()
+ {
+ return type;
+ }
+
+ public DocumentEvent.ElementChange getChange(Element elem)
+ {
+ return null;
+ }
+ }
+
+ public static class ElementEdit extends AbstractUndoableEdit
+ implements DocumentEvent.ElementChange
+ {
+ private static final long serialVersionUID = -1216620962142928304L;
+
+ private Element elem;
+ private int index;
+ private Element[] removed;
+ private Element[] added;
+
+ public ElementEdit(Element elem, int index,
+ Element[] removed, Element[] added)
+ {
+ this.elem = elem;
+ this.index = index;
+ this.removed = removed;
+ this.added = added;
+ }
+
+ public Element[] getChildrenAdded()
+ {
+ return added;
+ }
+
+ public Element[] getChildrenRemoved()
+ {
+ return removed;
+ }
+
+ public Element getElement()
+ {
+ return elem;
+ }
+
+ public int getIndex()
+ {
+ return index;
+ }
+ }
+
+ public class LeafElement extends AbstractElement
+ {
+ private static final long serialVersionUID = 5115368706941283802L;
+ int start;
+ int end;
+
+ public LeafElement(Element parent, AttributeSet attributes, int start,
+ int end)
+ {
+ super(parent, attributes);
+ this.start = start;
+ this.end = end;
+ }
+
+ public Enumeration children()
+ {
+ return null;
+ }
+
+ public boolean getAllowsChildren()
+ {
+ return false;
+ }
+
+ public Element getElement(int index)
+ {
+ return null;
+ }
+
+ public int getElementCount()
+ {
+ return 0;
+ }
+
+ public int getElementIndex(int offset)
+ {
+ return -1;
+ }
+
+ public int getEndOffset()
+ {
+ return end;
+ }
+
+ public String getName()
+ {
+ return ContentElementName;
+ }
+
+ public int getStartOffset()
+ {
+ return start;
+ }
+
+ public boolean isLeaf()
+ {
+ return true;
+ }
+
+ public String toString()
+ {
+ return ("LeafElement(" + getName() + ") "
+ + getStartOffset() + "," + getEndOffset() + "\n");
+ }
+ }
+}