defaultstyleddocument.java

来自「linux下建立JAVA虚拟机的源码KAFFE」· Java 代码 · 共 2,006 行 · 第 1/5 页

JAVA
2,006
字号
          b.append("Originate");          break;        case JoinFractureDirection:          b.append("Fracture");          break;        default:          b.append("??");          break;        }      b.append(':');      b.append(length);      return b.toString();    }  }  /**   * Performs all <em>structural</code> changes to the <code>Element</code>   * hierarchy.  This class was implemented with much help from the document:   * http://java.sun.com/products/jfc/tsc/articles/text/element_buffer/index.html.   */  public class ElementBuffer implements Serializable  {    /** The serialization UID (compatible with JDK1.5). */    private static final long serialVersionUID = 1688745877691146623L;    /** The root element of the hierarchy. */    private Element root;    /** Holds the offset for structural changes. */    private int offset;    /** Holds the end offset for structural changes. */    private int endOffset;    /** Holds the length of structural changes. */    private int length;    /** Holds the position of the change. */    private int pos;    /** Holds the element that was last fractured. */    private Element lastFractured;        /** True if a fracture was not created during a insertFracture call. */    private boolean fracNotCreated;    /**     * The current position in the element tree. This is used for bulk inserts     * using ElementSpecs.     */    private Stack elementStack;    /**     * The ElementChange that describes the latest changes.     */    DefaultDocumentEvent documentEvent;    /**     * Creates a new <code>ElementBuffer</code> for the specified     * <code>root</code> element.     *      * @param root     *          the root element for this <code>ElementBuffer</code>     */    public ElementBuffer(Element root)    {      this.root = root;      elementStack = new Stack();    }    /**     * Returns the root element of this <code>ElementBuffer</code>.     *      * @return the root element of this <code>ElementBuffer</code>     */    public Element getRootElement()    {      return root;    }    /**     * Removes the content. This method sets some internal parameters and     * delegates the work to {@link #removeUpdate}.     *      * @param offs     *          the offset from which content is remove     * @param len     *          the length of the removed content     * @param ev     *          the document event that records the changes     */    public void remove(int offs, int len, DefaultDocumentEvent ev)    {      if (len == 0)        return;      offset = offs;      length = len;      pos = offset;      documentEvent = ev;      removeUpdate();    }    /**     * Updates the element structure of the document in response to removal of     * content. It removes the affected {@link Element}s from the document     * structure.     */    protected void removeUpdate()    {      int startParagraph = root.getElementIndex(offset);      int endParagraph = root.getElementIndex(offset + length);      Element[] empty = new Element[0];      int removeStart = -1;      int removeEnd = -1;      for (int i = startParagraph; i < endParagraph; i++)        {          BranchElement paragraph = (BranchElement) root.getElement(i);          int contentStart = paragraph.getElementIndex(offset);          int contentEnd = paragraph.getElementIndex(offset + length);          if (contentStart == paragraph.getStartOffset()              && contentEnd == paragraph.getEndOffset())            {              // In this case we only need to remove the whole paragraph. We              // do this in one go after this loop and only record the indices              // here.              if (removeStart == -1)                {                  removeStart = i;                  removeEnd = i;                }              else                removeEnd = i;            }          else            {              // In this case we remove a couple of child elements from this              // paragraph.              int removeLen = contentEnd - contentStart;              Element[] removed = new Element[removeLen];              for (int j = contentStart; j < contentEnd; j++)                removed[j] = paragraph.getElement(j);              Edit edit = getEditForParagraphAndIndex(paragraph, contentStart);              edit.addRemovedElements(removed);            }        }      // Now we remove paragraphs from the root that have been tagged for      // removal.      if (removeStart != -1)        {          int removeLen = removeEnd - removeStart;          Element[] removed = new Element[removeLen];          for (int i = removeStart; i < removeEnd; i++)            removed[i] = root.getElement(i);          Edit edit = getEditForParagraphAndIndex((BranchElement) root,                                                  removeStart);          edit.addRemovedElements(removed);        }    }    /**     * Performs the actual work for {@link #change}. The elements at the     * interval boundaries are split up (if necessary) so that the interval     * boundaries are located at element boundaries.     */    protected void changeUpdate()    {      // Split up the element at the start offset if necessary.      Element el = getCharacterElement(offset);      Element[] res = split(el, offset, 0, el.getElementIndex(offset));      BranchElement par = (BranchElement) el.getParentElement();      int index = par.getElementIndex(offset);      Edit edit = getEditForParagraphAndIndex(par, index);      if (res[1] != null)        {          Element[] removed;          Element[] added;          if (res[0] == null)            {              removed = new Element[0];              added = new Element[] { res[1] };              index++;            }          else            {              removed = new Element[] { el };              added = new Element[] { res[0], res[1] };            }          edit.addRemovedElements(removed);          edit.addAddedElements(added);        }      int endOffset = offset + length;      el = getCharacterElement(endOffset);      res = split(el, endOffset, 0, el.getElementIndex(endOffset));      par = (BranchElement) el.getParentElement();      if (res[0] != null)        {          Element[] removed;          Element[] added;          if (res[1] == null)            {              removed = new Element[0];              added = new Element[] { res[1] };            }          else            {              removed = new Element[] { el };              added = new Element[] { res[0], res[1] };            }          edit.addRemovedElements(removed);          edit.addAddedElements(added);        }    }    /**     * Modifies the element structure so that the specified interval starts and     * ends at an element boundary. Content and paragraph elements are split and     * created as necessary. This also updates the     * <code>DefaultDocumentEvent</code> to reflect the structural changes.     * The bulk work is delegated to {@link #changeUpdate()}.     *      * @param offset     *          the start index of the interval to be changed     * @param length     *          the length of the interval to be changed     * @param ev     *          the <code>DefaultDocumentEvent</code> describing the change     */    public void change(int offset, int length, DefaultDocumentEvent ev)    {      if (length == 0)        return;      this.offset = offset;      this.pos = offset;      this.length = length;      documentEvent = ev;      changeUpdate();    }    /**     * Creates and returns a deep clone of the specified <code>clonee</code>     * with the specified parent as new parent.     *     * This method can only clone direct instances of {@link BranchElement}     * or {@link LeafElement}.     *     * @param parent the new parent     * @param clonee the element to be cloned     *     * @return the cloned element with the new parent     */    public Element clone(Element parent, Element clonee)    {      Element clone = clonee;      // We can only handle AbstractElements here.      if (clonee instanceof BranchElement)        {          BranchElement branchEl = (BranchElement) clonee;          BranchElement branchClone =            new BranchElement(parent, branchEl.getAttributes());          // Also clone all of the children.          int numChildren = branchClone.getElementCount();          Element[] cloneChildren = new Element[numChildren];          for (int i = 0; i < numChildren; ++i)            {              cloneChildren[i] = clone(branchClone,                                       branchClone.getElement(i));            }          branchClone.replace(0, 0, cloneChildren);          clone = branchClone;        }      else if (clonee instanceof LeafElement)        {          clone = new LeafElement(parent, clonee.getAttributes(),                                  clonee.getStartOffset(),                                  clonee.getEndOffset());        }      return clone;    }    /**     * Inserts new <code>Element</code> in the document at the specified     * position. Most of the work is done by {@link #insertUpdate}, after some     * fields have been prepared for it.     *      * @param offset     *          the location in the document at which the content is inserted     * @param length     *          the length of the inserted content     * @param data     *          the element specifications for the content to be inserted     * @param ev     *          the document event that is updated to reflect the structural     *          changes     */    public void insert(int offset, int length, ElementSpec[] data,                       DefaultDocumentEvent ev)    {      if (length == 0)        return;            this.offset = offset;      this.pos = offset;      this.endOffset = offset + length;      this.length = length;      documentEvent = ev;            edits.removeAllElements();      elementStack.removeAllElements();      lastFractured = null;      fracNotCreated = false;      insertUpdate(data);      // This for loop applies all the changes that were made and updates the      // DocumentEvent.      int size = edits.size();      for (int i = 0; i < size; i++)        {          Edit curr = (Edit) edits.get(i);          BranchElement e = (BranchElement) curr.e;          Element[] removed = curr.getRemovedElements();          Element[] added = curr.getAddedElements();          // FIXME: We probably shouldn't create the empty Element[] in the          // first place.          if (removed.length > 0 || added.length > 0)            {              if (curr.index + removed.length <= e.getElementCount())                {                  e.replace(curr.index, removed.length, added);                  ElementEdit ee = new ElementEdit(e, curr.index, removed, added);                  ev.addEdit(ee);                }              else                {                  System.err.println("WARNING: Tried to replace elements ");                  System.err.print("beyond boundaries: elementCount: ");                  System.err.println(e.getElementCount());                  System.err.print("index: " + curr.index);                  System.err.println(", removed.length: " + removed.length);                }            }        }    }    /**     * Inserts new content     *      * @param data     *          the element specifications for the elements to be inserted     */    protected void insertUpdate(ElementSpec[] data)    {      // Push the root and the paragraph at offset onto the element stack.      Element current = root;      int index;      while (!current.isLeaf())        {          index = current.getElementIndex(offset);          elementStack.push(current);          current = current.getElement(index);        }            int i = 0;      int type = data[0].getType();      if (type == ElementSpec.ContentType)        {          // If the first tag is content we must treat it separately to allow          // for joining properly to previous Elements and to ensure that          // no extra LeafElements are erroneously inserted.          insertFirstContentTag(data);          pos += data[0].length;          i = 1;        }      else        {          createFracture(data);          i = 0;        }            // Handle each ElementSpec individually.      for (; i < data.length; i++)        {          BranchElement paragraph = (BranchElement) elementStack.peek();          switch (data[i].getType())            {            case ElementSpec.StartTagType:              switch (data[i].getDirection())                {                case ElementSpec.JoinFractureDirection:                  // Fracture the tree and ensure the appropriate element                  // is on top of the stack.                  fracNotCreated = false;                  insertFracture(data[i]);                  if (fracNotCreated)                    {                      if (lastFractured != null)                        elementStack.push(lastFractured.getParentElement());                      else                        elementStack.push(paragraph.getElement(0));                    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?