diff options
Diffstat (limited to 'libjava/classpath/javax/swing/text/AbstractDocument.java')
-rw-r--r-- | libjava/classpath/javax/swing/text/AbstractDocument.java | 912 |
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"); + } + } +} |