diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | javax/swing/text/DefaultStyledDocument.java | 1216 |
2 files changed, 655 insertions, 582 deletions
@@ -1,10 +1,29 @@ +2006-01-26 Lillian Angel <langel@redhat.com> + + * javax/swing/text/DefaultStyledDocument.java + (ElementBuffer): Added fields. + (remove): Initialized pos. + (change): Likewise. + (insert): Likewise. + (insertUpdate): Incremented pos. Fixed check, createFracture should + be called on first tag if it is not ContentType. + (insertFirstContentTag): Reworked to use proper offsets and + set offset accordingly. This might need more work in the future. + (insertContentTag): Likewise. Fixed to use pos, instead of + offset. + (createFracture): Fixed to recreate other leaves. Still needs + more work. + (insertFracture): Reimplemented. + (recreateAfterFracture): New method. + (getParagraphElement): Reimplemented, more efficent. + 2006-01-26 Christian Thalinger <twisti@complang.tuwien.ac.at> * native/jni/java-lang/java_lang_VMDouble.c (doubleToLongBits) (doubleToRawLongBits, longBitsToDouble): Swap the byte ordering for little-endian arms without VFP. -2006-01-27 Raif S. Naffah <raif@swiftdsl.com.au> +2006-01-26 Raif S. Naffah <raif@swiftdsl.com.au> PR classpath/25981 * gnu/javax/crypto/jce/GnuCrypto.java (run): Added KeyGenerator entries. diff --git a/javax/swing/text/DefaultStyledDocument.java b/javax/swing/text/DefaultStyledDocument.java index 873a87a35..795941654 100644 --- a/javax/swing/text/DefaultStyledDocument.java +++ b/javax/swing/text/DefaultStyledDocument.java @@ -53,28 +53,25 @@ import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.UndoableEdit; /** - * The default implementation of {@link StyledDocument}. - * - * The document is modeled as an {@link Element} tree, which has - * a {@link SectionElement} as single root, which has one or more - * {@link AbstractDocument.BranchElement}s as paragraph nodes - * and each paragraph node having one or more + * The default implementation of {@link StyledDocument}. The document is + * modeled as an {@link Element} tree, which has a {@link SectionElement} as + * single root, which has one or more {@link AbstractDocument.BranchElement}s + * as paragraph nodes and each paragraph node having one or more * {@link AbstractDocument.LeafElement}s as content nodes. - * + * * @author Michael Koch (konqueror@gmx.de) * @author Roman Kennke (roman@kennke.org) */ -public class DefaultStyledDocument extends AbstractDocument - implements StyledDocument +public class DefaultStyledDocument extends AbstractDocument implements + StyledDocument { - + /** * An {@link UndoableEdit} that can undo attribute changes to an element. - * + * * @author Roman Kennke (kennke@aicas.com) */ - public static class AttributeUndoableEdit - extends AbstractUndoableEdit + public static class AttributeUndoableEdit extends AbstractUndoableEdit { /** * A copy of the old attributes. @@ -99,11 +96,13 @@ public class DefaultStyledDocument extends AbstractDocument /** * Creates a new <code>AttributeUndoableEdit</code>. - * - * @param el the element that changes attributes - * @param newAtts the new attributes - * @param replacing if the new attributes replace the old or only append to - * them + * + * @param el + * the element that changes attributes + * @param newAtts + * the new attributes + * @param replacing + * if the new attributes replace the old or only append to them */ public AttributeUndoableEdit(Element el, AttributeSet newAtts, boolean replacing) @@ -150,21 +149,19 @@ public class DefaultStyledDocument extends AbstractDocument } /** - * Carries specification information for new {@link Element}s that should - * be created in {@link ElementBuffer}. This allows the parsing process - * to be decoupled from the <code>Element</code> creation process. + * Carries specification information for new {@link Element}s that should be + * created in {@link ElementBuffer}. This allows the parsing process to be + * decoupled from the <code>Element</code> creation process. */ public static class ElementSpec { /** - * This indicates a start tag. This is a possible value for - * {@link #getType}. + * This indicates a start tag. This is a possible value for {@link #getType}. */ public static final short StartTagType = 1; /** - * This indicates an end tag. This is a possible value for - * {@link #getType}. + * This indicates an end tag. This is a possible value for {@link #getType}. */ public static final short EndTagType = 2; @@ -176,22 +173,19 @@ public class DefaultStyledDocument extends AbstractDocument /** * This indicates that the data associated with this spec should be joined - * with what precedes it. This is a possible value for - * {@link #getDirection}. + * with what precedes it. This is a possible value for {@link #getDirection}. */ public static final short JoinPreviousDirection = 4; /** * This indicates that the data associated with this spec should be joined - * with what follows it. This is a possible value for - * {@link #getDirection}. + * with what follows it. This is a possible value for {@link #getDirection}. */ public static final short JoinNextDirection = 5; /** - * This indicates that the data associated with this spec should be used - * to create a new element. This is a possible value for - * {@link #getDirection}. + * This indicates that the data associated with this spec should be used to + * create a new element. This is a possible value for {@link #getDirection}. */ public static final short OriginateDirection = 6; @@ -235,9 +229,11 @@ public class DefaultStyledDocument extends AbstractDocument /** * Creates a new <code>ElementSpec</code> with no content, length or * offset. This is most useful for start and end tags. - * - * @param a the attributes for the element to be created - * @param type the type of the tag + * + * @param a + * the attributes for the element to be created + * @param type + * the type of the tag */ public ElementSpec(AttributeSet a, short type) { @@ -248,27 +244,34 @@ public class DefaultStyledDocument extends AbstractDocument * Creates a new <code>ElementSpec</code> that specifies the length but * not the offset of an element. Such <code>ElementSpec</code>s are * processed sequentially from a known starting point. - * - * @param a the attributes for the element to be created - * @param type the type of the tag - * @param len the length of the element + * + * @param a + * the attributes for the element to be created + * @param type + * the type of the tag + * @param len + * the length of the element */ public ElementSpec(AttributeSet a, short type, int len) { this(a, type, null, 0, len); } - + /** * Creates a new <code>ElementSpec</code> with document content. - * - * @param a the attributes for the element to be created - * @param type the type of the tag - * @param txt the actual content - * @param offs the offset into the <code>txt</code> array - * @param len the length of the element + * + * @param a + * the attributes for the element to be created + * @param type + * the type of the tag + * @param txt + * the actual content + * @param offs + * the offset into the <code>txt</code> array + * @param len + * the length of the element */ - public ElementSpec(AttributeSet a, short type, char[] txt, int offs, - int len) + public ElementSpec(AttributeSet a, short type, char[] txt, int offs, int len) { attributes = a; this.type = type; @@ -280,8 +283,9 @@ public class DefaultStyledDocument extends AbstractDocument /** * Sets the type of the element. - * - * @param type the type of the element to be set + * + * @param type + * the type of the element to be set */ public void setType(short type) { @@ -290,7 +294,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the type of the element. - * + * * @return the type of the element */ public short getType() @@ -300,8 +304,9 @@ public class DefaultStyledDocument extends AbstractDocument /** * Sets the direction of the element. - * - * @param dir the direction of the element to be set + * + * @param dir + * the direction of the element to be set */ public void setDirection(short dir) { @@ -310,7 +315,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the direction of the element. - * + * * @return the direction of the element */ public short getDirection() @@ -320,7 +325,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the attributes of the element. - * + * * @return the attributes of the element */ public AttributeSet getAttributes() @@ -330,7 +335,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the actual content of the element. - * + * * @return the actual content of the element */ public char[] getArray() @@ -340,7 +345,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the offset of the content. - * + * * @return the offset of the content */ public int getOffset() @@ -350,7 +355,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the length of the content. - * + * * @return the length of the content */ public int getLength() @@ -362,7 +367,7 @@ public class DefaultStyledDocument extends AbstractDocument * Returns a String representation of this <code>ElementSpec</code> * describing the type, direction and length of this * <code>ElementSpec</code>. - * + * * @return a String representation of this <code>ElementSpec</code> */ public String toString() @@ -410,8 +415,8 @@ public class DefaultStyledDocument extends AbstractDocument 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: @@ -433,10 +438,13 @@ public class DefaultStyledDocument extends AbstractDocument /** Holds the length of structural changes. */ private int length; - - /** Holds the element that was created by insertFirstContentTag. */ - private Element firstCreated; - + + /** Holds the position of the change. */ + private int pos; + + /** Holds the element that was last fractured. */ + private Element lastFractured; + /** * The current position in the element tree. This is used for bulk inserts * using ElementSpecs. @@ -488,6 +496,7 @@ public class DefaultStyledDocument extends AbstractDocument return; offset = offs; length = len; + pos = offset; documentEvent = ev; removeUpdate(); } @@ -625,6 +634,7 @@ public class DefaultStyledDocument extends AbstractDocument if (length == 0) return; this.offset = offset; + this.pos = offset; this.length = length; documentEvent = ev; changeUpdate(); @@ -651,6 +661,7 @@ public class DefaultStyledDocument extends AbstractDocument if (length == 0) return; this.offset = offset; + this.pos = offset; this.endOffset = offset + length; this.length = length; documentEvent = ev; @@ -680,7 +691,7 @@ public class DefaultStyledDocument extends AbstractDocument addEdit(e, curr.index, removed, added); } } - + /** * Inserts new content * @@ -698,9 +709,13 @@ public class DefaultStyledDocument extends AbstractDocument // no extra LeafElements are erroneously inserted. i = 1; insertFirstContentTag(data); + pos += data[0].length; + } + else + { + i = 0; + createFracture(data); } - else if (type == ElementSpec.StartTagType) - createFracture(data); // Handle each ElementSpec individually. for (; i < data.length; i++) @@ -722,15 +737,13 @@ public class DefaultStyledDocument extends AbstractDocument int index = paragraph.getElementIndex(offset); elementStack.push(paragraph.getElement(index)); break; - case ElementSpec.OriginateDirection: + default: // Create a new paragraph and push it onto the stack. Element current = (Element) elementStack.peek(); Element newParagraph = insertParagraph((BranchElement) current, offset); elementStack.push(newParagraph); break; - default: - break; } break; case ElementSpec.EndTagType: @@ -742,11 +755,72 @@ public class DefaultStyledDocument extends AbstractDocument } } } - + + /** + * Inserts a new paragraph. + * + * @param par - the parent + * @param offset - the offset + * @return the new paragraph + */ + private Element insertParagraph(BranchElement par, int offset) + { + Element current = par.getElement(par.getElementIndex(offset)); + Element[] res = split(current, offset, 0); + int index = par.getElementIndex(offset); + Element ret; + if (res[1] != null) + { + Element[] removed; + Element[] added; + if (res[0] == null) + { + removed = new Element[0]; + if (res[1] instanceof BranchElement) + { + added = new Element[] { res[1] }; + ret = res[1]; + } + else + { + ret = createBranchElement(par, null); + added = new Element[] { ret, res[1] }; + } + index++; + } + else + { + removed = new Element[] { current }; + if (res[1] instanceof BranchElement) + { + ret = res[1]; + added = new Element[] { res[0], res[1] }; + } + else + { + ret = createBranchElement(par, null); + added = new Element[] { res[0], ret, res[1] }; + } + } + Edit e = getEditForParagraphAndIndex(par, index); + e.addAddedElements(added); + e.addRemovedElements(removed); + } + else + { + ret = createBranchElement(par, null); + Element[] added = new Element[] { ret }; + Edit e = getEditForParagraphAndIndex(par, index); + e.addAddedElements(added); + } + return ret; + } + /** * Inserts the first tag into the document. * - * @param data - the data to be inserted. + * @param data - + * the data to be inserted. */ private void insertFirstContentTag(ElementSpec[] data) { @@ -755,239 +829,204 @@ public class DefaultStyledDocument extends AbstractDocument int index = paragraph.getElementIndex(offset); Element current = paragraph.getElement(index); int newEndOffset = offset + first.length; - Edit edit = getEditForParagraphAndIndex(paragraph, index); boolean onlyContent = data.length == 1; - + Edit edit = getEditForParagraphAndIndex(paragraph, index); + switch (first.getDirection()) { case ElementSpec.JoinPreviousDirection: - int end = newEndOffset; - if (onlyContent) - end = current.getEndOffset(); - - if (current.getEndOffset() != end) + if (current.getEndOffset() != newEndOffset && !onlyContent) { Element newEl1 = createLeafElement(paragraph, current.getAttributes(), current.getStartOffset(), - end); - firstCreated = newEl1; - edit.addRemovedElement(current); + newEndOffset); + edit.addAddedElement(newEl1); + edit.addRemovedElement(current); + + if (current.getEndOffset() != endOffset) + { + // recreate all other leaves + Element newEl2 = createLeafElement(paragraph, + current.getAttributes(), + newEndOffset, + current.getEndOffset()); + edit.addAddedElement(newEl2); + } } + offset = newEndOffset; break; case ElementSpec.JoinNextDirection: if (offset != 0) { - Element next = paragraph.getElement(index + 1); - Element[] removed = new Element[] { current, next }; Element newEl1 = createLeafElement(paragraph, current.getAttributes(), current.getStartOffset(), offset); - firstCreated = newEl1; - Element[] added = new Element[2]; - added[0] = newEl1; - - end = newEndOffset; + edit.addAddedElement(newEl1); + + Element next = paragraph.getElement(index + 1); + if (onlyContent) - end = next.getEndOffset(); - - added[1] = createLeafElement(paragraph, next.getAttributes(), - offset, end); - edit.addRemovedElements(removed); - edit.addAddedElements(added); + newEl1 = createLeafElement(paragraph, next.getAttributes(), + offset, next.getEndOffset()); + else + newEl1 = createLeafElement(paragraph, next.getAttributes(), + offset, newEndOffset); + edit.addAddedElement(newEl1); + edit.addRemovedElement(current); + edit.addRemovedElement(next); } break; - case ElementSpec.OriginateDirection: + default: if (current.getStartOffset() != offset) { - Element newEl1 = createLeafElement(paragraph, - current.getAttributes(), - current.getStartOffset(), - offset); - firstCreated = newEl1; - edit.addAddedElement(newEl1); + Element newEl = createLeafElement(paragraph, + current.getAttributes(), + current.getStartOffset(), + offset); + edit.addAddedElement(newEl); } - Element newEl2 = createLeafElement(paragraph, first.getAttributes(), - offset, newEndOffset); - edit.addAddedElement(newEl2); edit.addRemovedElement(current); - - if (current.getEndOffset() != newEndOffset && onlyContent) - { - // This means all the leaves that were there previously need - // to be recreated after all the new Elements are inserted. - Element newCurrent = createLeafElement(paragraph, - current.getAttributes(), - newEndOffset, - current.getEndOffset()); - edit.addAddedElement(newCurrent); - } - else if (!onlyContent) + Element newEl1 = createLeafElement(paragraph, first.getAttributes(), + offset, newEndOffset); + edit.addAddedElement(newEl1); + if (current.getEndOffset() != endOffset) { - int size = paragraph.getElementCount(); - for (int i = index + 1; i < size; i++) - edit.addRemovedElement(paragraph.getElement(i)); + // recreate all other leaves + Element newEl2 = createLeafElement(paragraph, + current.getAttributes(), + newEndOffset, + current.getEndOffset()); + edit.addAddedElement(newEl2); } - break; - default: + else + offset = newEndOffset; break; } - offset = newEndOffset; } /** * Inserts a content element into the document structure. * - * @param tag the element spec + * @param tag - + * the element spec */ private void insertContentTag(ElementSpec tag) { int len = tag.getLength(); int dir = tag.getDirection(); AttributeSet tagAtts = tag.getAttributes(); + BranchElement paragraph = (BranchElement) elementStack.peek(); + int index = paragraph.getElementIndex(pos); + Element target = paragraph.getElement(index); + Edit edit = getEditForParagraphAndIndex(paragraph, index); if (dir == ElementSpec.JoinNextDirection) { - BranchElement paragraph = (BranchElement) elementStack.peek(); - int index = paragraph.getElementIndex(offset); - Element target = paragraph.getElement(index); - Edit edit = getEditForParagraphAndIndex(paragraph, index); - - if (paragraph.getStartOffset() > offset) + if (paragraph.getStartOffset() > pos) { Element first = paragraph.getElement(0); Element newEl = createLeafElement(paragraph, - first.getAttributes(), offset, + first.getAttributes(), pos, first.getEndOffset()); edit.addAddedElement(newEl); edit.addRemovedElement(first); } - else if (paragraph.getElementCount() > (index + 1)) + else if (paragraph.getElementCount() > (index + 1) + && (pos == target.getStartOffset() && !target.equals(lastFractured))) { Element next = paragraph.getElement(index + 1); - if (offset == target.getStartOffset()) { Element newEl = createLeafElement(paragraph, - next.getAttributes(), - offset, next.getEndOffset()); + next.getAttributes(), pos, + next.getEndOffset()); edit.addAddedElement(newEl); edit.addRemovedElement(next); edit.addRemovedElement(target); } - else - { - Element newEl1 = createLeafElement(paragraph, - target.getAttributes(), - target.getStartOffset(), - offset); - Element newEl2 = createLeafElement(paragraph, - next.getAttributes(), - offset, - next.getEndOffset()); - edit.addRemovedElement(target); - edit.addRemovedElement(next); - edit.addAddedElement(newEl1); - edit.addAddedElement(newEl2); - } - } - } - else if (dir == ElementSpec.OriginateDirection) - { - BranchElement paragraph = (BranchElement) elementStack.peek(); - int index = paragraph.getElementIndex(offset); - Element current = paragraph.getElement(index); - - Element[] added; - Element[] removed = new Element[] { current }; - Element[] splitRes = split(current, offset, len); - - if (splitRes[0] == null) - { - added = new Element[2]; - added[0] = new LeafElement(paragraph, tagAtts, offset, - endOffset); - added[1] = splitRes[1]; - removed = new Element[0]; - index++; - } - else if (current.getStartOffset() == offset && current.getEndOffset() == endOffset) - { - added = new Element[1]; - added[0] = new LeafElement(paragraph, tagAtts, offset, - endOffset); - } - else if (current.getStartOffset() == offset) - { - // This is if the new insertion happens immediately before - // the <code>current</code> Element. In this case there are 2 - // resulting Elements. - added = new Element[2]; - added[0] = new LeafElement(paragraph, tagAtts, offset, - endOffset); - added[1] = splitRes[1]; - } - else if (current.getEndOffset() == endOffset) - { - // This is if the new insertion happens right at the end of - // the <code>current</code> Element. In this case there are - // 2 resulting Elements. - added = new Element[2]; - added[0] = splitRes[0]; - added[1] = new LeafElement(paragraph, tagAtts, offset, - endOffset); - } - else - { - // This is if the new insertion is in the middle of the - // <code>current</code> Element. In this case - // there will be 3 resulting Elements. - added = new Element[3]; - added[0] = splitRes[0]; - added[1] = new LeafElement(paragraph, tagAtts, offset, - endOffset); - added[2] = splitRes[1]; } - Edit edit = getEditForParagraphAndIndex(paragraph, index); - edit.addRemovedElements(removed); - edit.addAddedElements(added); } - offset += len; + pos += len; } - + /** * This method fractures the child at offset. - * @param data the ElementSpecs used for the entire insertion + * + * @param data + * the ElementSpecs used for the entire insertion */ private void createFracture(ElementSpec[] data) { - BranchElement paragraph = (BranchElement)elementStack.peek(); + BranchElement paragraph = (BranchElement) elementStack.peek(); int index = paragraph.getElementIndex(offset); Element child = paragraph.getElement(index); Edit edit = getEditForParagraphAndIndex(paragraph, index); + AttributeSet atts = data[0].getAttributes(); + if (offset != 0) { - Element newEl1 = createLeafElement(paragraph, child.getAttributes(), child.getStartOffset(), offset); + // FIXME: sometimes creating too many els + Element newEl1 = createLeafElement(paragraph, atts, + child.getStartOffset(), offset); edit.addAddedElement(newEl1); + + // add rest of leaf to next branch, if it exists. + BranchElement parent = (BranchElement) paragraph.getParentElement(); + int parIndex = parent.getElementIndex(offset); + BranchElement next = (BranchElement) parent.getElement(parIndex + 1); + if (next == null) + { + BranchElement newB = (BranchElement) createBranchElement(parent, + atts); + Element newEl2 = createLeafElement(newB, atts, offset, + child.getEndOffset()); + newB.replace(0, 0, new Element[] { newEl2 }); + Edit e = getEditForParagraphAndIndex(newB, 0); + e.addAddedElement(newB); + elementStack.push(newB); + } + else + { + // FIXME: need to tag those elements to ignore, those created by the fracture + // don't join with those elements. + int end = child.getEndOffset(); + + Edit e = getEditForParagraphAndIndex(next, parIndex); + + // check if can join with next leaf + Element nextLeaf = next.getElement(0); + if (nextLeaf != null && nextLeaf.isLeaf() + && nextLeaf.getAttributes().isEqual(atts)) + { + end = nextLeaf.getEndOffset(); + e.addRemovedElement(nextLeaf); + } + + Element newEl2 = createLeafElement(next, atts, offset, end); + e.addAddedElement(newEl2); + } } edit.addRemovedElement(child); } - + /** - * Splits an element if <code>offset</code> is not already at its boundary. - * - * @param el the Element to possibly split - * @param offset the offset at which to possibly split - * @param space the amount of space to create between the splitted parts - * - * @return An array of elements which represent the split result. This - * array has two elements, the two parts of the split. The first - * element might be null, which means that the element which should - * be splitted can remain in place. The second element might also - * be null, which means that the offset is already at an element + * Splits an element if <code>offset</code> is not already at its + * boundary. + * + * @param el + * the Element to possibly split + * @param offset + * the offset at which to possibly split + * @param space + * the amount of space to create between the splitted parts + * @return An array of elements which represent the split result. This array + * has two elements, the two parts of the split. The first element + * might be null, which means that the element which should be + * splitted can remain in place. The second element might also be + * null, which means that the offset is already at an element * boundary and the element doesn't need to be splitted. - * */ private Element[] split(Element el, int offset, int space) { @@ -1016,14 +1055,14 @@ public class DefaultStyledDocument extends AbstractDocument { removed = new Element[count - index - 1]; newAdded = new Element[count - index - 1]; - added = new Element[]{}; + added = new Element[] {}; } // This is the case when we may not keep the first element. else { removed = new Element[count - index]; newAdded = new Element[count - index]; - added = new Element[]{result[0]}; + added = new Element[] { result[0] }; } newAdded[0] = result[1]; for (int i = index; i < count; i++) @@ -1035,16 +1074,15 @@ public class DefaultStyledDocument extends AbstractDocument newAdded[ind] = el2; } - Edit edit = getEditForParagraphAndIndex((BranchElement)el, index); + Edit edit = getEditForParagraphAndIndex((BranchElement) el, index); edit.addRemovedElements(removed); edit.addAddedElements(added); - - BranchElement newPar = - (BranchElement) new BranchElement(el.getParentElement(), - el.getAttributes()); - + + BranchElement newPar = (BranchElement) new BranchElement(el.getParentElement(), + el.getAttributes()); + newPar.replace(0, 0, newAdded); - res = new Element[]{ null, newPar }; + res = new Element[] { null, newPar }; } else { @@ -1052,165 +1090,175 @@ public class DefaultStyledDocument extends AbstractDocument for (int i = index; i < count; ++i) removed[i - index] = el.getElement(i); added = new Element[0]; - - Edit edit = getEditForParagraphAndIndex((BranchElement)el, index); + + Edit edit = getEditForParagraphAndIndex((BranchElement) el, index); edit.addRemovedElements(removed); edit.addAddedElements(added); - - BranchElement newPar = - (BranchElement) new BranchElement(el.getParentElement(), - el.getAttributes()); + + BranchElement newPar = (BranchElement) new BranchElement(el.getParentElement(), + el.getAttributes()); newPar.replace(0, 0, removed); - res = new Element[]{ null, newPar }; + res = new Element[] { null, newPar }; } } else if (el instanceof LeafElement) { BranchElement par = (BranchElement) el.getParentElement(); - Element el1 = new LeafElement(par, el.getAttributes(), + Element el1 = createLeafElement(par, el.getAttributes(), el.getStartOffset(), offset); - - Element el2 = new LeafElement(par, el.getAttributes(), - offset + space, el.getEndOffset()); - res = new Element[]{ el1, el2 }; + + Element el2 = createLeafElement(par, el.getAttributes(), offset + + space, + el.getEndOffset()); + res = new Element[] { el1, el2 }; } return res; } - + /** - * Inserts a new paragraph. + * Inserts a fracture into the document structure. * - * @param par - paragraph to insert new paragraph at. - * @param offset - offset to insert at. - * @return new paragraph + * @param tag - + * the element spec. */ - private Element insertParagraph(BranchElement par, int offset) + private void insertFracture(ElementSpec tag) { - Element current = par.getElement(par.getElementIndex(offset)); - Element[] res = split(current, offset, 0); - int index = par.getElementIndex(offset); - Element ret; - if (res[1] != null) + // insert the fracture at offset. + BranchElement parent = (BranchElement) elementStack.peek(); + int parentIndex = parent.getElementIndex(offset); + AttributeSet parentAtts = parent.getAttributes(); + Element toFracture = parent.getElement(parentIndex); + int parSize = parent.getElementCount(); + + // recreate left-side of branch and all its children before offset + // add the fractured leaves to the right branch + BranchElement leftBranch = new BranchElement(parent, parentAtts); + BranchElement rightBranch = new BranchElement(parent, parentAtts); + + Element frac = toFracture; + int leftIns = 0; + int indexOfFrac = toFracture.getElementIndex(offset); + int size = toFracture.getElementCount(); + if (!toFracture.isLeaf()) { - Element[] removed; - Element[] added; - if (res[0] == null) + // add all non-fracture elements to the branches + if (indexOfFrac > 0) { - removed = new Element[0]; - if (res[1] instanceof BranchElement) - { - added = new Element[]{ res[1] }; - ret = res[1]; - } - else - { - ret = createBranchElement(par, null); - added = new Element[]{ ret, res[1] }; - } - index++; + Element[] add = new Element[indexOfFrac]; + for (int i = 0; i < indexOfFrac; i++) + add[i] = toFracture.getElement(i); + leftIns = add.length; + leftBranch.replace(0, 0, add); } - else + + int count = size - indexOfFrac - 1; + if (count > 0) { - removed = new Element[]{ current }; - if (res[1] instanceof BranchElement) - { - ret = res[1]; - added = new Element[]{ res[0], res[1] }; - } - else - { - ret = createBranchElement(par, null); - added = new Element[]{ res[0], ret, res[1] }; - } + Element[] add = new Element[count]; + int j = 0; + int i = indexOfFrac + 1; + while (j < count) + add[j++] = toFracture.getElement(i++); + rightBranch.replace(0, 0, add); } - Edit edit = getEditForParagraphAndIndex(par, index); - edit.addRemovedElements(removed); - edit.addAddedElements(added); + + // gets the leaf that falls along the fracture + frac = toFracture.getElement(indexOfFrac); + while (!frac.isLeaf()) + frac = frac.getElement(frac.getElementIndex(offset)); } - else + + int fracStart = frac.getStartOffset(); + int fracEnd = frac.getEndOffset(); + if (fracStart < offset && offset < fracEnd) { - ret = createBranchElement(par, null); - Edit edit = getEditForParagraphAndIndex(par, index); - edit.addAddedElement(ret); + // fracture the leaf and split among 2 branches + AttributeSet atts = frac.getAttributes(); + // replaces old leaf. + Element leftFracturedLeaf = createLeafElement(leftBranch, atts, + fracStart, offset); + leftBranch.replace(leftIns, 0, new Element[] { leftFracturedLeaf }); + + // Check if we can join the right frac leaf with the next leaf + int rm = 0; + int end = fracEnd; + Element next = rightBranch.getElement(0); + if (next != null && next.isLeaf() + && next.getAttributes().isEqual(atts)) + { + end = next.getEndOffset(); + rm = 1; + } + + Element rightFracturedLeaf = createLeafElement(rightBranch, atts, + offset, end); + rightBranch.replace(0, rm, new Element[] { rightFracturedLeaf }); + + // recreate those elements after parentIndex and add/remove all + // new/old elements to parent + int remove = parSize - parentIndex; + Element[] removed = new Element[remove]; + int s = 0; + for (int j = parentIndex; j < parSize; j++) + removed[s++] = parent.getElement(j); + + Element[] added = new Element[] { leftBranch, rightBranch }; + Edit edit = getEditForParagraphAndIndex(parent, parentIndex); + edit.addAddedElements(added); + edit.addRemovedElements(removed); + recreateAfterFracture(removed, parent, 1, rightBranch.getEndOffset()); + elementStack.push(rightBranch); + lastFractured = rightFracturedLeaf; } - return ret; } - + /** - * Inserts a fracture into the document structure. + * Recreates all the elements from the parent to the element on the top of + * the stack, starting from startFrom with the starting offset of + * startOffset. * - * @param tag - the element spec. + * @param recreate - + * the elements to recreate + * @param parent - + * the element to add the new elements to + * @param startFrom - + * where to start recreating from + * @param startOffset - + * the offset of the first element */ - private void insertFracture(ElementSpec tag) - { - // The steps we must take to properly fracture are: - // 1. Recreate the LeafElement at offset to have the correct end offset. - // 2. Create a new LeafElement with the remainder of the LeafElement in - // #1 ==> this is whatever was in that LeafElement to the right of the - // inserted newline. - // 3. Find the paragraph at offset and remove all its children that - // occur at and after offset. These will be moved to the newly created - // paragraph. - // 4. Move the LeafElement created in #2 and all the LeafElements removed - // in #3 to the newly created paragraph. - // 5. Add the new paragraph to the parent. - BranchElement parent = (BranchElement) elementStack.peek(); - int parentIndex = parent.getElementIndex(offset); - - BranchElement previous = (BranchElement) parent.getElement(parentIndex); - int previousIndex = previous.getElementIndex(offset); - Element previousLeaf = previous.getElement(previousIndex); - AttributeSet prevLeafAtts = previous.getAttributes(); - int numReplaced = previous.getElementCount() - previousIndex; - - BranchElement newBranch = - (BranchElement) createBranchElement(parent, prevLeafAtts); - - int start = previousLeaf.getStartOffset(); - Element newPreviousLeaf = null; - if (firstCreated != null && (start != firstCreated.getStartOffset() - && offset != firstCreated.getEndOffset())) - { - newPreviousLeaf = createLeafElement(previous, prevLeafAtts, - start, offset); - Edit edit2 = getEditForParagraphAndIndex(previous, previousIndex); - edit2.addRemovedElement(previousLeaf); - edit2.addAddedElement(newPreviousLeaf); - } - - // FIXME: This is a workaround... figure out how to determine newEndOffset - int newEndOffset = Math.min(previousLeaf.getEndOffset(), getLength()); - if (offset == newEndOffset) - newEndOffset = previousLeaf.getEndOffset(); - - if (endOffset > offset) - { - Element newTempLeaf = createLeafElement(newBranch, prevLeafAtts, - newEndOffset, newEndOffset + 1); - newBranch.replace(0, 0, new Element[] { newTempLeaf }); - } - else + private void recreateAfterFracture(Element[] recreate, + BranchElement parent, int startFrom, + int startOffset) + { + Element[] added = new Element[recreate.length - startFrom]; + int j = 0; + for (int i = startFrom; i < recreate.length; i++) { - Element firstLeafInNewBranch = createLeafElement(newBranch, - prevLeafAtts, - offset, newEndOffset); - Edit edit = getEditForParagraphAndIndex(newBranch, 0); - Element newLeaves = firstLeafInNewBranch; - if (newLeaves.getStartOffset() >= endOffset) - edit.addAddedElement(newLeaves); - for (int i = 1; i < numReplaced; i++) + Element curr = recreate[i]; + int len = curr.getEndOffset() - curr.getStartOffset(); + if (curr instanceof LeafElement) + added[j] = createLeafElement(parent, curr.getAttributes(), + startOffset, startOffset + len); + else { - newLeaves = previous.getElement(previousIndex + i); - if (newLeaves.getStartOffset() >= endOffset) - edit.addAddedElement(newLeaves); + BranchElement br = new BranchElement(parent, curr.getAttributes()); + int bSize = curr.getElementCount(); + for (int k = 0; k < bSize; k++) + { + Element bCurr = curr.getElement(k); + recreateAfterFracture(new Element[] { bCurr }, br, 0, + startOffset); + } + added[j] = br; } + startOffset += len; + j++; } - - Edit edit3 = getEditForParagraphAndIndex(parent, parentIndex + 1); - edit3.addAddedElement(newBranch); - elementStack.push(newBranch); + + Edit edit = getEditForParagraphAndIndex(parent, parent.getElementCount()); + edit.addAddedElements(added); } - + /** * Adds an ElementChange for a given element modification to the document * event. If there already is an ElementChange registered for this element, @@ -1248,7 +1296,6 @@ public class DefaultStyledDocument extends AbstractDocument i = ec.getIndex(); } else - // FIXME: Not implemented. throw new AssertionError("Not yet implemented case."); } else if (added != null) @@ -1275,7 +1322,6 @@ public class DefaultStyledDocument extends AbstractDocument i = ec.getIndex(); } else - // FIXME: Not implemented. throw new AssertionError("Not yet implemented case."); } else if (removed != null) @@ -1486,7 +1532,7 @@ public class DefaultStyledDocument extends AbstractDocument * name. */ protected class SectionElement extends BranchElement - { + { /** * Creates a new SectionElement. */ @@ -1498,7 +1544,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the name of the element. This method always returns * "section". - * + * * @return the name of the element */ public String getName() @@ -1510,18 +1556,18 @@ public class DefaultStyledDocument extends AbstractDocument /** * Receives notification when any of the document's style changes and calls * {@link DefaultStyledDocument#styleChanged(Style)}. - * + * * @author Roman Kennke (kennke@aicas.com) */ - private class StyleChangeListener - implements ChangeListener + private class StyleChangeListener implements ChangeListener { /** * Receives notification when any of the document's style changes and calls * {@link DefaultStyledDocument#styleChanged(Style)}. - * - * @param event the change event + * + * @param event + * the change event */ public void stateChanged(ChangeEvent event) { @@ -1548,7 +1594,7 @@ public class DefaultStyledDocument extends AbstractDocument * Listens for changes on this document's styles and notifies styleChanged(). */ private StyleChangeListener styleChangeListener; - + /** Vector that contains all the edits. */ Vector edits = new Vector(); @@ -1561,10 +1607,11 @@ public class DefaultStyledDocument extends AbstractDocument } /** - * Creates a new <code>DefaultStyledDocument</code> that uses the - * specified {@link StyleContext}. - * - * @param context the <code>StyleContext</code> to use + * Creates a new <code>DefaultStyledDocument</code> that uses the specified + * {@link StyleContext}. + * + * @param context + * the <code>StyleContext</code> to use */ public DefaultStyledDocument(StyleContext context) { @@ -1572,14 +1619,16 @@ public class DefaultStyledDocument extends AbstractDocument } /** - * Creates a new <code>DefaultStyledDocument</code> that uses the - * specified {@link StyleContext} and {@link Content} buffer. - * - * @param content the <code>Content</code> buffer to use - * @param context the <code>StyleContext</code> to use + * Creates a new <code>DefaultStyledDocument</code> that uses the specified + * {@link StyleContext} and {@link Content} buffer. + * + * @param content + * the <code>Content</code> buffer to use + * @param context + * the <code>StyleContext</code> to use */ public DefaultStyledDocument(AbstractDocument.Content content, - StyleContext context) + StyleContext context) { super(content, context); buffer = new ElementBuffer(createDefaultRoot()); @@ -1587,10 +1636,9 @@ public class DefaultStyledDocument extends AbstractDocument } /** - * Adds a style into the style hierarchy. Unspecified style attributes - * can be resolved in the <code>parent</code> style, if one is specified. - * - * While it is legal to add nameless styles (<code>nm == null</code), + * Adds a style into the style hierarchy. Unspecified style attributes can be + * resolved in the <code>parent</code> style, if one is specified. While it + * is legal to add nameless styles (<code>nm == null</code), * you must be aware that the client application is then responsible * for managing the style hierarchy, since unnamed styles cannot be * looked up by their name. @@ -1617,7 +1665,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Create the default root element for this kind of <code>Document</code>. - * + * * @return the default root element for this kind of <code>Document</code> */ protected AbstractDocument.AbstractElement createDefaultRoot() @@ -1639,14 +1687,14 @@ public class DefaultStyledDocument extends AbstractDocument } /** - * Returns the <code>Element</code> that corresponds to the character - * at the specified position. - * - * @param position the position of which we query the corresponding - * <code>Element</code> - * - * @return the <code>Element</code> that corresponds to the character - * at the specified position + * Returns the <code>Element</code> that corresponds to the character at the + * specified position. + * + * @param position + * the position of which we query the corresponding + * <code>Element</code> + * @return the <code>Element</code> that corresponds to the character at the + * specified position */ public Element getCharacterElement(int position) { @@ -1657,15 +1705,15 @@ public class DefaultStyledDocument extends AbstractDocument int index = element.getElementIndex(position); element = element.getElement(index); } - + return element; } /** * Extracts a background color from a set of attributes. - * - * @param attributes the attributes from which to get a background color - * + * + * @param attributes + * the attributes from which to get a background color * @return the background color that correspond to the attributes */ public Color getBackground(AttributeSet attributes) @@ -1676,7 +1724,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the default root element. - * + * * @return the default root element */ public Element getDefaultRootElement() @@ -1686,9 +1734,9 @@ public class DefaultStyledDocument extends AbstractDocument /** * Extracts a font from a set of attributes. - * - * @param attributes the attributes from which to get a font - * + * + * @param attributes + * the attributes from which to get a font * @return the font that correspond to the attributes */ public Font getFont(AttributeSet attributes) @@ -1696,12 +1744,12 @@ public class DefaultStyledDocument extends AbstractDocument StyleContext context = (StyleContext) getAttributeContext(); return context.getFont(attributes); } - + /** * Extracts a foreground color from a set of attributes. - * - * @param attributes the attributes from which to get a foreground color - * + * + * @param attributes + * the attributes from which to get a foreground color * @return the foreground color that correspond to the attributes */ public Color getForeground(AttributeSet attributes) @@ -1712,9 +1760,9 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns the logical <code>Style</code> for the specified position. - * - * @param position the position from which to query to logical style - * + * + * @param position + * the position from which to query to logical style * @return the logical <code>Style</code> for the specified position */ public Style getLogicalStyle(int position) @@ -1729,37 +1777,32 @@ public class DefaultStyledDocument extends AbstractDocument } /** - * Returns the paragraph element for the specified position. - * If the position is outside the bounds of the document's root element, - * then the closest element is returned. That is the last paragraph if + * Returns the paragraph element for the specified position. If the position + * is outside the bounds of the document's root element, then the closest + * element is returned. That is the last paragraph if * <code>position >= endIndex</code> or the first paragraph if * <code>position < startIndex</code>. - * - * @param position the position for which to query the paragraph element - * + * + * @param position + * the position for which to query the paragraph element * @return the paragraph element for the specified position */ public Element getParagraphElement(int position) { - BranchElement root = (BranchElement) getDefaultRootElement(); - int start = root.getStartOffset(); - int end = root.getEndOffset(); - if (position >= end) - position = end - 1; - else if (position < start) - position = start; - - Element par = root.positionToElement(position); - - assert par != null : "The paragraph element must not be null"; - return par; + Element e = getDefaultRootElement(); + while (!e.isLeaf()) + e = e.getElement(e.getElementIndex(position)); + + if (e != null) + return e.getParentElement(); + return e; } /** * Looks up and returns a named <code>Style</code>. - * - * @param nm the name of the <code>Style</code> - * + * + * @param nm + * the name of the <code>Style</code> * @return the found <code>Style</code> of <code>null</code> if no such * <code>Style</code> exists */ @@ -1771,8 +1814,9 @@ public class DefaultStyledDocument extends AbstractDocument /** * Removes a named <code>Style</code> from the style hierarchy. - * - * @param nm the name of the <code>Style</code> to be removed + * + * @param nm + * the name of the <code>Style</code> to be removed */ public void removeStyle(String nm) { @@ -1783,31 +1827,33 @@ public class DefaultStyledDocument extends AbstractDocument /** * Sets text attributes for the fragment specified by <code>offset</code> * and <code>length</code>. - * - * @param offset the start offset of the fragment - * @param length the length of the fragment - * @param attributes the text attributes to set - * @param replace if <code>true</code>, the attributes of the current - * selection are overridden, otherwise they are merged + * + * @param offset + * the start offset of the fragment + * @param length + * the length of the fragment + * @param attributes + * the text attributes to set + * @param replace + * if <code>true</code>, the attributes of the current selection + * are overridden, otherwise they are merged */ public void setCharacterAttributes(int offset, int length, - AttributeSet attributes, - boolean replace) + AttributeSet attributes, boolean replace) { // Exit early if length is 0, so no DocumentEvent is created or fired. if (length == 0) return; try { - // Must obtain a write lock for this method. writeLock() and + // Must obtain a write lock for this method. writeLock() and // writeUnlock() should always be in try/finally block to make // sure that locking happens in a balanced manner. writeLock(); - DefaultDocumentEvent ev = - new DefaultDocumentEvent( - offset, - length, - DocumentEvent.EventType.CHANGE); + DefaultDocumentEvent ev = new DefaultDocumentEvent( + offset, + length, + DocumentEvent.EventType.CHANGE); // Modify the element structure so that the interval begins at an // element @@ -1818,13 +1864,13 @@ public class DefaultStyledDocument extends AbstractDocument // Visit all paragraph elements within the specified interval int end = offset + length; Element curr; - for (int pos = offset; pos < end; ) + for (int pos = offset; pos < end;) { // Get the CharacterElement at offset pos. curr = getCharacterElement(pos); if (pos == curr.getEndOffset()) break; - + MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes(); ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace)); // If replace is true, remove all the old attributes. @@ -1843,12 +1889,14 @@ public class DefaultStyledDocument extends AbstractDocument writeUnlock(); } } - + /** * Sets the logical style for the paragraph at the specified position. - * - * @param position the position at which the logical style is added - * @param style the style to set for the current paragraph + * + * @param position + * the position at which the logical style is added + * @param style + * the style to set for the current paragraph */ public void setLogicalStyle(int position, Style style) { @@ -1858,59 +1906,61 @@ public class DefaultStyledDocument extends AbstractDocument if (el == null) return; try - { - writeLock(); - if (el instanceof AbstractElement) - { - AbstractElement ael = (AbstractElement) el; - ael.setResolveParent(style); - int start = el.getStartOffset(); - int end = el.getEndOffset(); - DefaultDocumentEvent ev = - new DefaultDocumentEvent (start, - end - start, - DocumentEvent.EventType.CHANGE); - fireChangedUpdate(ev); - fireUndoableEditUpdate(new UndoableEditEvent(this, ev)); - } - else - throw new - AssertionError("paragraph elements are expected to be" - + "instances of AbstractDocument.AbstractElement"); - } + { + writeLock(); + if (el instanceof AbstractElement) + { + AbstractElement ael = (AbstractElement) el; + ael.setResolveParent(style); + int start = el.getStartOffset(); + int end = el.getEndOffset(); + DefaultDocumentEvent ev = new DefaultDocumentEvent( + start, + end - start, + DocumentEvent.EventType.CHANGE); + fireChangedUpdate(ev); + fireUndoableEditUpdate(new UndoableEditEvent(this, ev)); + } + else + throw new AssertionError( + "paragraph elements are expected to be" + + "instances of AbstractDocument.AbstractElement"); + } finally - { - writeUnlock(); - } + { + writeUnlock(); + } } /** * Sets text attributes for the paragraph at the specified fragment. - * - * @param offset the beginning of the fragment - * @param length the length of the fragment - * @param attributes the text attributes to set - * @param replace if <code>true</code>, the attributes of the current - * selection are overridden, otherwise they are merged + * + * @param offset + * the beginning of the fragment + * @param length + * the length of the fragment + * @param attributes + * the text attributes to set + * @param replace + * if <code>true</code>, the attributes of the current selection + * are overridden, otherwise they are merged */ public void setParagraphAttributes(int offset, int length, - AttributeSet attributes, - boolean replace) + AttributeSet attributes, boolean replace) { try { - // Must obtain a write lock for this method. writeLock() and + // Must obtain a write lock for this method. writeLock() and // writeUnlock() should always be in try/finally blocks to make // sure that locking occurs in a balanced manner. writeLock(); - + // Create a DocumentEvent to use for changedUpdate(). - DefaultDocumentEvent ev = - new DefaultDocumentEvent ( - offset, - length, - DocumentEvent.EventType.CHANGE); - + DefaultDocumentEvent ev = new DefaultDocumentEvent( + offset, + length, + DocumentEvent.EventType.CHANGE); + // Have to iterate through all the _paragraph_ elements that are // contained or partially contained in the interval // (offset, offset + length). @@ -1919,7 +1969,7 @@ public class DefaultStyledDocument extends AbstractDocument int endElement = rootElement.getElementIndex(offset + length - 1); if (endElement < startElement) endElement = startElement; - + for (int i = startElement; i <= endElement; i++) { Element par = rootElement.getElement(i); @@ -1942,11 +1992,13 @@ public class DefaultStyledDocument extends AbstractDocument } /** - * Called in response to content insert actions. This is used to - * update the element structure. - * - * @param ev the <code>DocumentEvent</code> describing the change - * @param attr the attributes for the change + * Called in response to content insert actions. This is used to update the + * element structure. + * + * @param ev + * the <code>DocumentEvent</code> describing the change + * @param attr + * the attributes for the change */ protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr) { @@ -1957,8 +2009,7 @@ public class DefaultStyledDocument extends AbstractDocument int offset = ev.getOffset(); int length = ev.getLength(); int endOffset = offset + length; - AttributeSet paragraphAttributes = - getParagraphElement(endOffset).getAttributes(); + AttributeSet paragraphAttributes = getParagraphElement(endOffset).getAttributes(); Segment txt = new Segment(); try { @@ -1977,77 +2028,75 @@ public class DefaultStyledDocument extends AbstractDocument short finalStartDirection = ElementSpec.OriginateDirection; boolean prevCharWasNewline = false; Element prev = getCharacterElement(offset); - Element next = getCharacterElement(endOffset); + Element next = getCharacterElement(endOffset); Element prevParagraph = getParagraphElement(offset); Element paragraph = getParagraphElement(endOffset); - + int segmentEnd = txt.offset + txt.count; - + // Check to see if we're inserting immediately after a newline. if (offset > 0) { try - { - String s = getText(offset - 1, 1); - if (s.equals("\n")) - { - finalStartDirection = - handleInsertAfterNewline(specs, offset, endOffset, - prevParagraph, - paragraph, - paragraphAttributes); - - prevCharWasNewline = true; - // Find the final start tag from the ones just created. - for (int i = 0; i < specs.size(); i++) - if (((ElementSpec) specs.get(i)).getType() - == ElementSpec.StartTagType) - finalStartTag = (ElementSpec)specs.get(i); - } - } + { + String s = getText(offset - 1, 1); + if (s.equals("\n")) + { + finalStartDirection = handleInsertAfterNewline(specs, offset, + endOffset, + prevParagraph, + paragraph, + paragraphAttributes); + + prevCharWasNewline = true; + // Find the final start tag from the ones just created. + for (int i = 0; i < specs.size(); i++) + if (((ElementSpec) specs.get(i)).getType() == ElementSpec.StartTagType) + finalStartTag = (ElementSpec) specs.get(i); + } + } catch (BadLocationException ble) - { - // This shouldn't happen. - AssertionError ae = new AssertionError(); - ae.initCause(ble); - throw ae; - } + { + // This shouldn't happen. + AssertionError ae = new AssertionError(); + ae.initCause(ble); + throw ae; + } } - for (int i = txt.offset; i < segmentEnd; ++i) { len++; if (txt.array[i] == '\n') { // Add the ElementSpec for the content. - specs.add(new ElementSpec(attr, ElementSpec.ContentType, len)); + specs.add(new ElementSpec(attr, ElementSpec.ContentType, len)); // Add ElementSpecs for the newline. specs.add(new ElementSpec(null, ElementSpec.EndTagType)); finalStartTag = new ElementSpec(paragraphAttributes, - ElementSpec.StartTagType); + ElementSpec.StartTagType); specs.add(finalStartTag); len = 0; } } // Create last element if last character hasn't been a newline. - if (len > 0) + if (len > 0) specs.add(new ElementSpec(attr, ElementSpec.ContentType, len)); - // Set the direction of the last spec of type StartTagType. - // If we are inserting after a newline then this value comes from + // Set the direction of the last spec of type StartTagType. + // If we are inserting after a newline then this value comes from // handleInsertAfterNewline. if (finalStartTag != null) - { + { if (prevCharWasNewline) finalStartTag.setDirection(finalStartDirection); else if (prevParagraph.getEndOffset() != endOffset) finalStartTag.setDirection(ElementSpec.JoinFractureDirection); else { - // If there is an element AFTER this one, then set the + // If there is an element AFTER this one, then set the // direction to JoinNextDirection. Element parent = prevParagraph.getParentElement(); int index = parent.getElementIndex(offset); @@ -2056,19 +2105,18 @@ public class DefaultStyledDocument extends AbstractDocument finalStartTag.setDirection(ElementSpec.JoinNextDirection); } } - + // If we are at the last index, then check if we could probably be // joined with the next element. // This means: - // - we must be a ContentTag - // - if there is a next Element, we must have the same attributes - // - if there is no next Element, but one will be created, - // we must have the same attributes as the higher-level run. + // - we must be a ContentTag + // - if there is a next Element, we must have the same attributes + // - if there is no next Element, but one will be created, + // we must have the same attributes as the higher-level run. ElementSpec last = (ElementSpec) specs.lastElement(); if (last.getType() == ElementSpec.ContentType) { - Element currentRun = - prevParagraph.getElement(prevParagraph.getElementIndex(offset)); + Element currentRun = prevParagraph.getElement(prevParagraph.getElementIndex(offset)); if (currentRun.getEndOffset() == endOffset) { if (endOffset < getLength() && next.getAttributes().isEqual(attr) @@ -2078,36 +2126,36 @@ public class DefaultStyledDocument extends AbstractDocument else { if (finalStartTag != null - && finalStartTag.getDirection() == - ElementSpec.JoinFractureDirection + && finalStartTag.getDirection() == ElementSpec.JoinFractureDirection && currentRun.getAttributes().isEqual(attr)) { last.setDirection(ElementSpec.JoinNextDirection); } } } - + // If we are at the first new element, then check if it could be // joined with the previous element. ElementSpec first = (ElementSpec) specs.firstElement(); if (prev.getAttributes().isEqual(attr) && first.getType() == ElementSpec.ContentType) first.setDirection(ElementSpec.JoinPreviousDirection); - - ElementSpec[] elSpecs = - (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]); + + ElementSpec[] elSpecs = (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]); buffer.insert(offset, length, elSpecs, ev); } /** - * A helper method to set up the ElementSpec buffer for the special - * case of an insertion occurring immediately after a newline. - * @param specs the ElementSpec buffer to initialize. + * A helper method to set up the ElementSpec buffer for the special case of an + * insertion occurring immediately after a newline. + * + * @param specs + * the ElementSpec buffer to initialize. */ short handleInsertAfterNewline(Vector specs, int offset, int endOffset, - Element prevParagraph, Element paragraph, - AttributeSet a) + Element prevParagraph, Element paragraph, + AttributeSet a) { if (prevParagraph.getParentElement() == paragraph.getParentElement()) { @@ -2117,23 +2165,25 @@ public class DefaultStyledDocument extends AbstractDocument return ElementSpec.JoinFractureDirection; // If there is an Element after this one, use JoinNextDirection. Element parent = paragraph.getParentElement(); - if (parent.getElementCount() > parent.getElementIndex(offset) + 1) + if (parent.getElementCount() > (parent.getElementIndex(offset) + 1)) return ElementSpec.JoinNextDirection; } else { - // TODO: What to do here? + // FIXME: What to do here? + System.out.println("handleInsertAfterNewline: else reached -> Not implemented."); } return ElementSpec.OriginateDirection; } - + /** * Updates the document structure in response to text removal. This is - * forwarded to the {@link ElementBuffer} of this document. Any changes to - * the document structure are added to the specified document event and - * sent to registered listeners. - * - * @param ev the document event that records the changes to the document + * forwarded to the {@link ElementBuffer} of this document. Any changes to the + * document structure are added to the specified document event and sent to + * registered listeners. + * + * @param ev + * the document event that records the changes to the document */ protected void removeUpdate(DefaultDocumentEvent ev) { @@ -2143,7 +2193,7 @@ public class DefaultStyledDocument extends AbstractDocument /** * Returns an enumeration of all style names. - * + * * @return an enumeration of all style names */ public Enumeration getStyleNames() @@ -2154,32 +2204,35 @@ public class DefaultStyledDocument extends AbstractDocument /** * Called when any of this document's styles changes. - * - * @param style the style that changed + * + * @param style + * the style that changed */ protected void styleChanged(Style style) { // Nothing to do here. This is intended to be overridden by subclasses. } - + /** * Inserts a bulk of structured content at once. - * - * @param offset the offset at which the content should be inserted - * @param data the actual content spec to be inserted + * + * @param offset + * the offset at which the content should be inserted + * @param data + * the actual content spec to be inserted */ protected void insert(int offset, ElementSpec[] data) - throws BadLocationException + throws BadLocationException { if (data == null || data.length == 0) return; try { // writeLock() and writeUnlock() should always be in a try/finally - // block so that locking balance is guaranteed even if some + // block so that locking balance is guaranteed even if some // exception is thrown. writeLock(); - + // First we collect the content to be inserted. StringBuffer contentBuffer = new StringBuffer(); for (int i = 0; i < data.length; i++) @@ -2197,15 +2250,15 @@ public class DefaultStyledDocument extends AbstractDocument // If there was no content inserted then exit early. if (length == 0) return; - + UndoableEdit edit = content.insertString(offset, contentBuffer.toString()); // Create the DocumentEvent with the ElementEdit added - DefaultDocumentEvent ev = - new DefaultDocumentEvent(offset, - length, - DocumentEvent.EventType.INSERT); + DefaultDocumentEvent ev = new DefaultDocumentEvent( + offset, + length, + DocumentEvent.EventType.INSERT); ev.addEdit(edit); // Finally we must update the document structure and fire the insert @@ -2223,9 +2276,10 @@ public class DefaultStyledDocument extends AbstractDocument /** * Initializes the <code>DefaultStyledDocument</code> with the specified * data. - * - * @param data the specification of the content with which the document is - * initialized + * + * @param data + * the specification of the content with which the document is + * initialized */ protected void create(ElementSpec[] data) { |