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 + -
显示快捷键?