📄 abstractdocument.java
字号:
/* 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 modifyit under the terms of the GNU General Public License as published bythe 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, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Classpath; see the file COPYING. If not, write to theFree Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA02110-1301 USA.Linking this library statically or dynamically with other modules ismaking a combined work based on this library. Thus, the terms andconditions of the GNU General Public License cover the wholecombination.As a special exception, the copyright holders of this library give youpermission to link this library with independent modules to produce anexecutable, regardless of the license terms of these independentmodules, and to copy and distribute the resulting executable underterms of your choice, provided that you also meet, for each linkedindependent module, the terms and conditions of the license of thatmodule. An independent module is a module which is not derived fromor based on this library. If you modify this library, you may extendthis exception to your version of the library, but you are notobligated to do so. If you do not wish to do so, delete thisexception 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;/** * An abstract base implementation for the {@link Document} interface. * This class provides some common functionality for all <code>Element</code>s, * most notably it implements a locking mechanism to make document modification * thread-safe. * * @author original author unknown * @author Roman Kennke (roman@kennke.org) */public abstract class AbstractDocument implements Document, Serializable{ /** The serialization UID (compatible with JDK1.5). */ private static final long serialVersionUID = 6842927725919637215L; /** * Standard error message to indicate a bad location. */ protected static final String BAD_LOCATION = "document location failure"; /** * Standard name for unidirectional <code>Element</code>s. */ public static final String BidiElementName = "bidi level"; /** * Standard name for content <code>Element</code>s. These are usually * {@link LeafElement}s. */ public static final String ContentElementName = "content"; /** * Standard name for paragraph <code>Element</code>s. These are usually * {@link BranchElement}s. */ public static final String ParagraphElementName = "paragraph"; /** * Standard name for section <code>Element</code>s. These are usually * {@link DefaultStyledDocument.SectionElement}s. */ public static final String SectionElementName = "section"; /** * Attribute key for storing the element name. */ public static final String ElementNameAttribute = "$ename"; /** * The actual content model of this <code>Document</code>. */ Content content; /** * The AttributeContext for this <code>Document</code>. */ AttributeContext context; /** * The currently installed <code>DocumentFilter</code>. */ DocumentFilter documentFilter; /** * The documents properties. */ Dictionary properties; /** * Manages event listeners for this <code>Document</code>. */ protected EventListenerList listenerList = new EventListenerList(); /** * Stores the current writer thread. Used for locking. */ private Thread currentWriter = null; /** * The number of readers. Used for locking. */ private int numReaders = 0; /** * Tells if there are one or more writers waiting. */ private int numWritersWaiting = 0; /** * A condition variable that readers and writers wait on. */ Object documentCV = new Object(); /** * Creates a new <code>AbstractDocument</code> with the specified * {@link Content} model. * * @param doc the <code>Content</code> model to be used in this * <code>Document<code> * * @see GapContent * @see StringContent */ protected AbstractDocument(Content doc) { this(doc, StyleContext.getDefaultStyleContext()); } /** * Creates a new <code>AbstractDocument</code> with the specified * {@link Content} model and {@link AttributeContext}. * * @param doc the <code>Content</code> model to be used in this * <code>Document<code> * @param ctx the <code>AttributeContext</code> to use * * @see GapContent * @see StringContent */ protected AbstractDocument(Content doc, AttributeContext ctx) { content = doc; context = ctx; } /** * Returns the paragraph {@link Element} that holds the specified position. * * @param pos the position for which to get the paragraph element * * @return the paragraph {@link Element} that holds the specified position */ public abstract Element getParagraphElement(int pos); /** * Returns the default root {@link Element} of this <code>Document</code>. * Usual <code>Document</code>s only have one root element and return this. * However, there may be <code>Document</code> implementations that * support multiple root elements, they have to return a default root element * here. * * @return the default root {@link Element} of this <code>Document</code> */ public abstract Element getDefaultRootElement(); /** * Creates and returns a branch element with the specified * <code>parent</code> and <code>attributes</code>. Note that the new * <code>Element</code> is linked to the parent <code>Element</code> * through {@link Element#getParentElement}, but it is not yet added * to the parent <code>Element</code> as child. * * @param parent the parent <code>Element</code> for the new branch element * @param attributes the text attributes to be installed in the new element * * @return the new branch <code>Element</code> * * @see BranchElement */ protected Element createBranchElement(Element parent, AttributeSet attributes) { return new BranchElement(parent, attributes); } /** * Creates and returns a leaf element with the specified * <code>parent</code> and <code>attributes</code>. Note that the new * <code>Element</code> is linked to the parent <code>Element</code> * through {@link Element#getParentElement}, but it is not yet added * to the parent <code>Element</code> as child. * * @param parent the parent <code>Element</code> for the new branch element * @param attributes the text attributes to be installed in the new element * * @return the new branch <code>Element</code> * * @see LeafElement */ protected Element createLeafElement(Element parent, AttributeSet attributes, int start, int end) { return new LeafElement(parent, attributes, start, end); } /** * Creates a {@link Position} that keeps track of the location at the * specified <code>offset</code>. * * @param offset the location in the document to keep track by the new * <code>Position</code> * * @return the newly created <code>Position</code> * * @throws BadLocationException if <code>offset</code> is not a valid * location in the documents content model */ public Position createPosition(final int offset) throws BadLocationException { return content.createPosition(offset); } /** * Notifies all registered listeners when the document model changes. * * @param event the <code>DocumentEvent</code> to be fired */ protected void fireChangedUpdate(DocumentEvent event) { DocumentListener[] listeners = getDocumentListeners(); for (int index = 0; index < listeners.length; ++index) listeners[index].changedUpdate(event); } /** * Notifies all registered listeners when content is inserted in the document * model. * * @param event the <code>DocumentEvent</code> to be fired */ protected void fireInsertUpdate(DocumentEvent event) { DocumentListener[] listeners = getDocumentListeners(); for (int index = 0; index < listeners.length; ++index) listeners[index].insertUpdate(event); } /** * Notifies all registered listeners when content is removed from the * document model. * * @param event the <code>DocumentEvent</code> to be fired */ protected void fireRemoveUpdate(DocumentEvent event) { DocumentListener[] listeners = getDocumentListeners(); for (int index = 0; index < listeners.length; ++index) listeners[index].removeUpdate(event); } /** * Notifies all registered listeners when an <code>UndoableEdit</code> has * been performed on this <code>Document</code>. * * @param event the <code>UndoableEditEvent</code> to be fired */ protected void fireUndoableEditUpdate(UndoableEditEvent event) { UndoableEditListener[] listeners = getUndoableEditListeners(); for (int index = 0; index < listeners.length; ++index) listeners[index].undoableEditHappened(event); } /** * Returns the asynchronous loading priority. Returns <code>-1</code> if this * document should not be loaded asynchronously. * * @return the asynchronous loading priority */ public int getAsynchronousLoadPriority() { return 0; } /** * Returns the {@link AttributeContext} used in this <code>Document</code>. * * @return the {@link AttributeContext} used in this <code>Document</code> */ protected AttributeContext getAttributeContext() { return context; } /** * Returns the root element for bidirectional content. * * @return the root element for bidirectional content */ public Element getBidiRootElement() { return null; } /** * Returns the {@link Content} model for this <code>Document</code> * * @return the {@link Content} model for this <code>Document</code> * * @see GapContent * @see StringContent */ protected final Content getContent() { return content; } /** * Returns the thread that currently modifies this <code>Document</code> * if there is one, otherwise <code>null</code>. This can be used to * distinguish between a method call that is part of an ongoing modification * or if it is a separate modification for which a new lock must be aquired. * * @return the thread that currently modifies this <code>Document</code> * if there is one, otherwise <code>null</code> */ protected Thread getCurrentWriter() { return currentWriter; } /** * Returns the properties of this <code>Document</code>. * * @return the properties of this <code>Document</code> */ public Dictionary getDocumentProperties() { // FIXME: make me thread-safe if (properties == null) properties = new Hashtable(); return properties; } /** * Returns a {@link Position} which will always mark the end of the * <code>Document</code>. * * @return a {@link Position} which will always mark the end of the * <code>Document</code> */ public Position getEndPosition() { // FIXME: Properly implement this by calling Content.createPosition(). return new Position() { public int getOffset() { return getLength(); } }; } /** * Returns the length of this <code>Document</code>'s content. * * @return the length of this <code>Document</code>'s content */ public int getLength() { // We return Content.getLength() -1 here because there is always an // implicit \n at the end of the Content which does count in Content // but not in Document. return content.length() - 1; } /** * Returns all registered listeners of a given listener type. * * @param listenerType the type of the listeners to be queried * * @return all registered listeners of the specified type */ public EventListener[] getListeners(Class listenerType) { return listenerList.getListeners(listenerType); } /** * Returns a property from this <code>Document</code>'s property list.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -