1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47:
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54:
55:
65: public class DefaultStyledDocument extends AbstractDocument implements
66: StyledDocument
67: {
68:
69:
74: public static class AttributeUndoableEdit extends AbstractUndoableEdit
75: {
76:
79: protected AttributeSet copy;
80:
81:
84: protected AttributeSet newAttributes;
85:
86:
90: protected boolean isReplacing;
91:
92:
95: protected Element element;
96:
97:
107: public AttributeUndoableEdit(Element el, AttributeSet newAtts,
108: boolean replacing)
109: {
110: element = el;
111: newAttributes = newAtts;
112: isReplacing = replacing;
113: copy = el.getAttributes().copyAttributes();
114: }
115:
116:
120: public void undo()
121: {
122: super.undo();
123: AttributeSet atts = element.getAttributes();
124: if (atts instanceof MutableAttributeSet)
125: {
126: MutableAttributeSet mutable = (MutableAttributeSet) atts;
127: mutable.removeAttributes(atts);
128: mutable.addAttributes(copy);
129: }
130: }
131:
132:
137: public void redo()
138: {
139: super.undo();
140: AttributeSet atts = element.getAttributes();
141: if (atts instanceof MutableAttributeSet)
142: {
143: MutableAttributeSet mutable = (MutableAttributeSet) atts;
144: if (isReplacing)
145: mutable.removeAttributes(atts);
146: mutable.addAttributes(newAttributes);
147: }
148: }
149: }
150:
151:
156: public static class ElementSpec
157: {
158:
161: public static final short StartTagType = 1;
162:
163:
166: public static final short EndTagType = 2;
167:
168:
172: public static final short ContentType = 3;
173:
174:
178: public static final short JoinPreviousDirection = 4;
179:
180:
184: public static final short JoinNextDirection = 5;
185:
186:
190: public static final short OriginateDirection = 6;
191:
192:
197: public static final short JoinFractureDirection = 7;
198:
199:
202: short type;
203:
204:
207: short direction;
208:
209:
212: int offset;
213:
214:
217: int length;
218:
219:
222: char[] content;
223:
224:
227: AttributeSet attributes;
228:
229:
238: public ElementSpec(AttributeSet a, short type)
239: {
240: this(a, type, 0);
241: }
242:
243:
255: public ElementSpec(AttributeSet a, short type, int len)
256: {
257: this(a, type, null, 0, len);
258: }
259:
260:
274: public ElementSpec(AttributeSet a, short type, char[] txt, int offs, int len)
275: {
276: attributes = a;
277: this.type = type;
278: offset = offs;
279: length = len;
280: content = txt;
281: direction = OriginateDirection;
282: }
283:
284:
290: public void setType(short type)
291: {
292: this.type = type;
293: }
294:
295:
300: public short getType()
301: {
302: return type;
303: }
304:
305:
311: public void setDirection(short dir)
312: {
313: direction = dir;
314: }
315:
316:
321: public short getDirection()
322: {
323: return direction;
324: }
325:
326:
331: public AttributeSet getAttributes()
332: {
333: return attributes;
334: }
335:
336:
341: public char[] getArray()
342: {
343: return content;
344: }
345:
346:
351: public int getOffset()
352: {
353: return offset;
354: }
355:
356:
361: public int getLength()
362: {
363: return length;
364: }
365:
366:
373: public String toString()
374: {
375: StringBuilder b = new StringBuilder();
376: switch (type)
377: {
378: case StartTagType:
379: b.append("StartTag");
380: break;
381: case EndTagType:
382: b.append("EndTag");
383: break;
384: case ContentType:
385: b.append("Content");
386: break;
387: default:
388: b.append("??");
389: break;
390: }
391:
392: b.append(':');
393:
394: switch (direction)
395: {
396: case JoinPreviousDirection:
397: b.append("JoinPrevious");
398: break;
399: case JoinNextDirection:
400: b.append("JoinNext");
401: break;
402: case OriginateDirection:
403: b.append("Originate");
404: break;
405: case JoinFractureDirection:
406: b.append("Fracture");
407: break;
408: default:
409: b.append("??");
410: break;
411: }
412:
413: b.append(':');
414: b.append(length);
415:
416: return b.toString();
417: }
418: }
419:
420:
425: public class ElementBuffer implements Serializable
426: {
427:
428: private static final long serialVersionUID = 1688745877691146623L;
429:
430:
431: private Element root;
432:
433:
434: private int offset;
435:
436:
437: private int endOffset;
438:
439:
440: private int length;
441:
442:
443: private int pos;
444:
445:
446: private Element lastFractured;
447:
448:
449: private boolean fracNotCreated;
450:
451:
455: private Stack elementStack;
456:
457:
460: DefaultDocumentEvent documentEvent;
461:
462:
469: public ElementBuffer(Element root)
470: {
471: this.root = root;
472: elementStack = new Stack();
473: }
474:
475:
480: public Element getRootElement()
481: {
482: return root;
483: }
484:
485:
496: public void remove(int offs, int len, DefaultDocumentEvent ev)
497: {
498: if (len == 0)
499: return;
500: offset = offs;
501: length = len;
502: pos = offset;
503: documentEvent = ev;
504: removeUpdate();
505: }
506:
507:
512: protected void removeUpdate()
513: {
514: int startParagraph = root.getElementIndex(offset);
515: int endParagraph = root.getElementIndex(offset + length);
516: Element[] empty = new Element[0];
517: int removeStart = -1;
518: int removeEnd = -1;
519: for (int i = startParagraph; i < endParagraph; i++)
520: {
521: BranchElement paragraph = (BranchElement) root.getElement(i);
522: int contentStart = paragraph.getElementIndex(offset);
523: int contentEnd = paragraph.getElementIndex(offset + length);
524: if (contentStart == paragraph.getStartOffset()
525: && contentEnd == paragraph.getEndOffset())
526: {
527:
528:
529:
530: if (removeStart == -1)
531: {
532: removeStart = i;
533: removeEnd = i;
534: }
535: else
536: removeEnd = i;
537: }
538: else
539: {
540:
541:
542: int removeLen = contentEnd - contentStart;
543: Element[] removed = new Element[removeLen];
544: for (int j = contentStart; j < contentEnd; j++)
545: removed[j] = paragraph.getElement(j);
546: Edit edit = getEditForParagraphAndIndex(paragraph, contentStart);
547: edit.addRemovedElements(removed);
548: }
549: }
550:
551:
552: if (removeStart != -1)
553: {
554: int removeLen = removeEnd - removeStart;
555: Element[] removed = new Element[removeLen];
556: for (int i = removeStart; i < removeEnd; i++)
557: removed[i] = root.getElement(i);
558: Edit edit = getEditForParagraphAndIndex((BranchElement) root,
559: removeStart);
560: edit.addRemovedElements(removed);
561: }
562: }
563:
564:
569: protected void changeUpdate()
570: {
571:
572: Element el = getCharacterElement(offset);
573: Element[] res = split(el, offset, 0, el.getElementIndex(offset));
574: BranchElement par = (BranchElement) el.getParentElement();
575: int index = par.getElementIndex(offset);
576: Edit edit = getEditForParagraphAndIndex(par, index);
577: if (res[1] != null)
578: {
579: Element[] removed;
580: Element[] added;
581: if (res[0] == null)
582: {
583: removed = new Element[0];
584: added = new Element[] { res[1] };
585: index++;
586: }
587: else
588: {
589: removed = new Element[] { el };
590: added = new Element[] { res[0], res[1] };
591: }
592: edit.addRemovedElements(removed);
593:
594: edit.addAddedElements(added);
595: }
596:
597: int endOffset = offset + length;
598: el = getCharacterElement(endOffset);
599: res = split(el, endOffset, 0, el.getElementIndex(endOffset));
600: par = (BranchElement) el.getParentElement();
601: if (res[0] != null)
602: {
603: Element[] removed;
604: Element[] added;
605: if (res[1] == null)
606: {
607: removed = new Element[0];
608: added = new Element[] { res[1] };
609: }
610: else
611: {
612: removed = new Element[] { el };
613: added = new Element[] { res[0], res[1] };
614: }
615: edit.addRemovedElements(removed);
616: edit.addAddedElements(added);
617: }
618: }
619:
620:
634: public void change(int offset, int length, DefaultDocumentEvent ev)
635: {
636: if (length == 0)
637: return;
638: this.offset = offset;
639: this.pos = offset;
640: this.length = length;
641: documentEvent = ev;
642: changeUpdate();
643: }
644:
645:
657: public Element clone(Element parent, Element clonee)
658: {
659: Element clone = clonee;
660:
661: if (clonee instanceof BranchElement)
662: {
663: BranchElement branchEl = (BranchElement) clonee;
664: BranchElement branchClone =
665: new BranchElement(parent, branchEl.getAttributes());
666:
667: int numChildren = branchClone.getElementCount();
668: Element[] cloneChildren = new Element[numChildren];
669: for (int i = 0; i < numChildren; ++i)
670: {
671: cloneChildren[i] = clone(branchClone,
672: branchClone.getElement(i));
673: }
674: branchClone.replace(0, 0, cloneChildren);
675: clone = branchClone;
676: }
677: else if (clonee instanceof LeafElement)
678: {
679: clone = new LeafElement(parent, clonee.getAttributes(),
680: clonee.getStartOffset(),
681: clonee.getEndOffset());
682: }
683: return clone;
684: }
685:
686:
701: public void insert(int offset, int length, ElementSpec[] data,
702: DefaultDocumentEvent ev)
703: {
704: if (length == 0)
705: return;
706:
707: this.offset = offset;
708: this.pos = offset;
709: this.endOffset = offset + length;
710: this.length = length;
711: documentEvent = ev;
712:
713: edits.removeAllElements();
714: elementStack.removeAllElements();
715: lastFractured = null;
716: fracNotCreated = false;
717: insertUpdate(data);
718:
719:
720: int size = edits.size();
721: for (int i = 0; i < size; i++)
722: {
723: Edit curr = (Edit) edits.get(i);
724: BranchElement e = (BranchElement) curr.e;
725: Element[] removed = curr.getRemovedElements();
726: Element[] added = curr.getAddedElements();
727:
728:
729: if (removed.length > 0 || added.length > 0)
730: {
731: if (curr.index + removed.length <= e.getElementCount())
732: {
733: e.replace(curr.index, removed.length, added);
734: ElementEdit ee = new ElementEdit(e, curr.index, removed, added);
735: ev.addEdit(ee);
736: }
737: else
738: {
739: System.err.println("WARNING: Tried to replace elements ");
740: System.err.print("beyond boundaries: elementCount: ");
741: System.err.println(e.getElementCount());
742: System.err.print("index: " + curr.index);
743: System.err.println(", removed.length: " + removed.length);
744: }
745: }
746: }
747: }
748:
749:
755: protected void insertUpdate(ElementSpec[] data)
756: {
757:
758: Element current = root;
759: int index;
760: while (!current.isLeaf())
761: {
762: index = current.getElementIndex(offset);
763: elementStack.push(current);
764: current = current.getElement(index);
765: }
766:
767: int i = 0;
768: int type = data[0].getType();
769: if (type == ElementSpec.ContentType)
770: {
771:
772:
773:
774: insertFirstContentTag(data);
775: pos += data[0].length;
776: i = 1;
777: }
778: else
779: {
780: createFracture(data);
781: i = 0;
782: }
783:
784:
785: for (; i < data.length; i++)
786: {
787: BranchElement paragraph = (BranchElement) elementStack.peek();
788: switch (data[i].getType())
789: {
790: case ElementSpec.StartTagType:
791: switch (data[i].getDirection())
792: {
793: case ElementSpec.JoinFractureDirection:
794:
795:
796: fracNotCreated = false;
797: insertFracture(data[i]);
798: if (fracNotCreated)
799: {
800: if (lastFractured != null)
801: elementStack.push(lastFractured.getParentElement());
802: else
803: elementStack.push(paragraph.getElement(0));
804: }
805: break;
806: case ElementSpec.JoinNextDirection:
807:
808:
809: int ix = paragraph.getElementIndex(pos) + 1;
810: elementStack.push(paragraph.getElement(ix));
811: break;
812: default:
813: Element br = null;
814: if (data.length > i + 1)
815: {
816:
817: int x = 0;
818: if (paragraph.getElementCount() > 0)
819: x = paragraph.getElementIndex(pos) + 1;
820: Edit e = getEditForParagraphAndIndex(paragraph, x);
821: br = (BranchElement) createBranchElement(paragraph,
822: data[i].getAttributes());
823: e.added.add(br);
824: elementStack.push(br);
825: }
826: else
827:
828: br = insertParagraph(paragraph, pos);
829: break;
830: }
831: break;
832: case ElementSpec.EndTagType:
833: elementStack.pop();
834: break;
835: case ElementSpec.ContentType:
836: insertContentTag(data[i]);
837: offset = pos;
838: break;
839: }
840: }
841: }
842:
843:
852: private Element insertParagraph(BranchElement par, int offset)
853: {
854: int index = par.getElementIndex(offset);
855: Element current = par.getElement(index);
856: Element[] res = split(current, offset, 0, 0);
857: Edit e = getEditForParagraphAndIndex(par, index + 1);
858: Element ret;
859: if (res[1] != null)
860: {
861: Element[] removed;
862: Element[] added;
863: if (res[0] == null)
864: {
865: removed = new Element[0];
866: if (res[1] instanceof BranchElement)
867: {
868: added = new Element[] { res[1] };
869: ret = res[1];
870: }
871: else
872: {
873: ret = createBranchElement(par, null);
874: added = new Element[] { ret, res[1] };
875: }
876: index++;
877: }
878: else
879: {
880: removed = new Element[] { current };
881: if (res[1] instanceof BranchElement)
882: {
883: ret = res[1];
884: added = new Element[] { res[0], res[1] };
885: }
886: else
887: {
888: ret = createBranchElement(par, null);
889: added = new Element[] { res[0], ret, res[1] };
890: }
891: }
892:
893: e.addAddedElements(added);
894: e.addRemovedElements(removed);
895: }
896: else
897: {
898: ret = createBranchElement(par, null);
899: e.addAddedElement(ret);
900: }
901: return ret;
902: }
903:
904:
910: private void insertFirstContentTag(ElementSpec[] data)
911: {
912: ElementSpec first = data[0];
913: BranchElement paragraph = (BranchElement) elementStack.peek();
914: int index = paragraph.getElementIndex(pos);
915: Element current = paragraph.getElement(index);
916: int newEndOffset = pos + first.length;
917: boolean onlyContent = data.length == 1;
918: Edit edit = getEditForParagraphAndIndex(paragraph, index);
919: switch (first.getDirection())
920: {
921: case ElementSpec.JoinPreviousDirection:
922: if (current.getEndOffset() != newEndOffset && !onlyContent)
923: {
924: Element newEl1 = createLeafElement(paragraph,
925: current.getAttributes(),
926: current.getStartOffset(),
927: newEndOffset);
928: edit.addAddedElement(newEl1);
929: edit.addRemovedElement(current);
930: offset = newEndOffset;
931: }
932: break;
933: case ElementSpec.JoinNextDirection:
934: if (pos != 0)
935: {
936: Element newEl1 = createLeafElement(paragraph,
937: current.getAttributes(),
938: current.getStartOffset(),
939: pos);
940: edit.addAddedElement(newEl1);
941: Element next = paragraph.getElement(index + 1);
942:
943: if (onlyContent)
944: newEl1 = createLeafElement(paragraph, next.getAttributes(),
945: pos, next.getEndOffset());
946: else
947: {
948: newEl1 = createLeafElement(paragraph, next.getAttributes(),
949: pos, newEndOffset);
950: pos = newEndOffset;
951: }
952: edit.addAddedElement(newEl1);
953: edit.addRemovedElement(current);
954: edit.addRemovedElement(next);
955: }
956: break;
957: default:
958: if (current.getStartOffset() != pos)
959: {
960: Element newEl = createLeafElement(paragraph,
961: current.getAttributes(),
962: current.getStartOffset(),
963: pos);
964: edit.addAddedElement(newEl);
965: }
966: edit.addRemovedElement(current);
967: Element newEl1 = createLeafElement(paragraph, first.getAttributes(),
968: pos, newEndOffset);
969: edit.addAddedElement(newEl1);
970: if (current.getEndOffset() != endOffset)
971: recreateLeaves(newEndOffset, paragraph, onlyContent);
972: else
973: offset = newEndOffset;
974: break;
975: }
976: }
977:
978:
984: private void insertContentTag(ElementSpec tag)
985: {
986: BranchElement paragraph = (BranchElement) elementStack.peek();
987: int len = tag.getLength();
988: int dir = tag.getDirection();
989: AttributeSet tagAtts = tag.getAttributes();
990:
991: if (dir == ElementSpec.JoinNextDirection)
992: {
993: int index = paragraph.getElementIndex(pos);
994: Element target = paragraph.getElement(index);
995: Edit edit = getEditForParagraphAndIndex(paragraph, index);
996:
997: if (paragraph.getStartOffset() > pos)
998: {
999: Element first = paragraph.getElement(0);
1000: Element newEl = createLeafElement(paragraph,
1001: first.getAttributes(), pos,
1002: first.getEndOffset());
1003: edit.addAddedElement(newEl);
1004: edit.addRemovedElement(first);
1005: }
1006: else if (paragraph.getElementCount() > (index + 1)
1007: && (pos == target.getStartOffset() && !target.equals(lastFractured)))
1008: {
1009: Element next = paragraph.getElement(index + 1);
1010: Element newEl = createLeafElement(paragraph,
1011: next.getAttributes(), pos,
1012: next.getEndOffset());
1013: edit.addAddedElement(newEl);
1014: edit.addRemovedElement(next);
1015: edit.addRemovedElement(target);
1016: }
1017: else
1018: {
1019: BranchElement parent = (BranchElement) paragraph.getParentElement();
1020: int i = parent.getElementIndex(pos);
1021: BranchElement next = (BranchElement) parent.getElement(i + 1);
1022: AttributeSet atts = tag.getAttributes();
1023:
1024: if (next != null)
1025: {
1026: Element nextLeaf = next.getElement(0);
1027: Edit e = getEditForParagraphAndIndex(next, 0);
1028: Element newEl2 = createLeafElement(next, atts, pos, nextLeaf.getEndOffset());
1029: e.addAddedElement(newEl2);
1030: e.addRemovedElement(nextLeaf);
1031: }
1032: }
1033: }
1034: else
1035: {
1036: int end = pos + len;
1037: Element leaf = createLeafElement(paragraph, tag.getAttributes(), pos, end);
1038:
1039:
1040: if (paragraph.getElementCount() > 0)
1041: {
1042: int index = paragraph.getElementIndex(pos);
1043: Element target = paragraph.getElement(index);
1044: boolean onlyContent = target.isLeaf();
1045:
1046: BranchElement toRec = paragraph;
1047: if (!onlyContent)
1048: toRec = (BranchElement) target;
1049:
1050:
1051: if (pos > target.getStartOffset())
1052: index++;
1053:
1054: Edit edit = getEditForParagraphAndIndex(paragraph, index);
1055: edit.addAddedElement(leaf);
1056: }
1057: else
1058: paragraph.replace(0, 0, new Element[] { leaf });
1059: }
1060:
1061: pos += len;
1062: }
1063:
1064:
1070: private void createFracture(ElementSpec[] data)
1071: {
1072: BranchElement paragraph = (BranchElement) elementStack.peek();
1073: int index = paragraph.getElementIndex(offset);
1074: Element child = paragraph.getElement(index);
1075: Edit edit = getEditForParagraphAndIndex(paragraph, index);
1076: AttributeSet atts = child.getAttributes();
1077:
1078: if (offset != 0)
1079: {
1080: Element newEl1 = createLeafElement(paragraph, atts,
1081: child.getStartOffset(), offset);
1082: edit.addAddedElement(newEl1);
1083: edit.addRemovedElement(child);
1084: }
1085: }
1086:
1087:
1095: private void recreateLeaves(int start, BranchElement paragraph, boolean onlyContent)
1096: {
1097: int index = paragraph.getElementIndex(start);
1098: Element child = paragraph.getElement(index);
1099: AttributeSet atts = child.getAttributes();
1100:
1101: if (!onlyContent)
1102: {
1103: BranchElement newBranch = (BranchElement) createBranchElement(paragraph,
1104: atts);
1105: Element newLeaf = createLeafElement(newBranch, atts, start,
1106: child.getEndOffset());
1107: newBranch.replace(0, 0, new Element[] { newLeaf });
1108:
1109: BranchElement parent = (BranchElement) paragraph.getParentElement();
1110: int parSize = parent.getElementCount();
1111: Edit edit = getEditForParagraphAndIndex(parent, parSize);
1112: edit.addAddedElement(newBranch);
1113:
1114: int paragraphSize = paragraph.getElementCount();
1115: Element[] removed = new Element[paragraphSize - (index + 1)];
1116: int s = 0;
1117: for (int j = index + 1; j < paragraphSize; j++)
1118: removed[s++] = paragraph.getElement(j);
1119:
1120: edit = getEditForParagraphAndIndex(paragraph, index);
1121: edit.addRemovedElements(removed);
1122: Element[] added = recreateAfterFracture(removed, newBranch, 0, child.getEndOffset());
1123: newBranch.replace(1, 0, added);
1124:
1125: lastFractured = newLeaf;
1126: pos = newBranch.getEndOffset();
1127: }
1128: else
1129: {
1130: Element newLeaf = createLeafElement(paragraph, atts, start,
1131: child.getEndOffset());
1132: Edit edit = getEditForParagraphAndIndex(paragraph, index);
1133: edit.addAddedElement(newLeaf);
1134: }
1135: }
1136:
1137:
1156: private Element[] split(Element el, int offset, int space, int editIndex)
1157: {
1158:
1159: if ((offset == el.getStartOffset() || offset == el.getEndOffset())
1160: && space == 0 && el.isLeaf())
1161: return new Element[2];
1162:
1163:
1164:
1165:
1166: Element[] res = new Element[2];
1167: if (el instanceof BranchElement)
1168: {
1169: int index = el.getElementIndex(offset);
1170: Element child = el.getElement(index);
1171: Element[] result = split(child, offset, space, editIndex);
1172: Element[] removed;
1173: Element[] added;
1174: Element[] newAdded;
1175:
1176: int count = el.getElementCount();
1177: if (result[1] != null)
1178: {
1179:
1180: if (result[0] == null)
1181: {
1182: removed = new Element[count - index - 1];
1183: newAdded = new Element[count - index - 1];
1184: added = new Element[] {};
1185:
1186: }
1187:
1188:
1189: else
1190: {
1191: removed = new Element[count - index];
1192: newAdded = new Element[count - index];
1193: added = new Element[] { result[0] };
1194: }
1195: newAdded[0] = result[1];
1196: for (int i = index; i < count; i++)
1197: {
1198: Element el2 = el.getElement(i);
1199: int ind = i - count + removed.length;
1200: removed[ind] = el2;
1201: if (ind != 0)
1202: newAdded[ind] = el2;
1203: }
1204:
1205: Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
1206: edit.addRemovedElements(removed);
1207: edit.addAddedElements(added);
1208:
1209: BranchElement newPar =
1210: (BranchElement) createBranchElement(el.getParentElement(),
1211: el.getAttributes());
1212: newPar.replace(0, 0, newAdded);
1213: res = new Element[] { null, newPar };
1214: }
1215: else
1216: {
1217: removed = new Element[count - index];
1218: for (int i = index; i < count; ++i)
1219: removed[i - index] = el.getElement(i);
1220:
1221: Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
1222: edit.addRemovedElements(removed);
1223:
1224: BranchElement newPar = (BranchElement) createBranchElement(el.getParentElement(),
1225: el.getAttributes());
1226: newPar.replace(0, 0, removed);
1227: res = new Element[] { null, newPar };
1228: }
1229: }
1230: else if (el instanceof LeafElement)
1231: {
1232: BranchElement par = (BranchElement) el.getParentElement();
1233: Element el1 = createLeafElement(par, el.getAttributes(),
1234: el.getStartOffset(), offset);
1235:
1236: Element el2 = createLeafElement(par, el.getAttributes(),
1237: offset + space,
1238: el.getEndOffset());
1239: res = new Element[] { el1, el2 };
1240: }
1241: return res;
1242: }
1243:
1244:
1250: private void insertFracture(ElementSpec tag)
1251: {
1252:
1253: BranchElement parent = (BranchElement) elementStack.peek();
1254: int parentIndex = parent.getElementIndex(pos);
1255: AttributeSet parentAtts = parent.getAttributes();
1256: Element toFracture = parent.getElement(parentIndex);
1257: int parSize = parent.getElementCount();
1258: Edit edit = getEditForParagraphAndIndex(parent, parentIndex);
1259: Element frac = toFracture;
1260: int leftIns = 0;
1261: int indexOfFrac = toFracture.getElementIndex(pos);
1262: int size = toFracture.getElementCount();
1263:
1264:
1265: frac = toFracture.getElement(indexOfFrac);
1266: while (!frac.isLeaf())
1267: frac = frac.getElement(frac.getElementIndex(pos));
1268:
1269: AttributeSet atts = frac.getAttributes();
1270: int fracStart = frac.getStartOffset();
1271: int fracEnd = frac.getEndOffset();
1272: if (pos >= fracStart && pos < fracEnd)
1273: {
1274:
1275:
1276: BranchElement rightBranch =
1277: (BranchElement) createBranchElement(parent, parentAtts);
1278:
1279:
1280:
1281: BranchElement leftBranch = null;
1282: Element[] added = null;
1283: if (edit.added.size() > 0 || edit.removed.size() > 0)
1284: {
1285: added = new Element[] { rightBranch };
1286:
1287:
1288: parentIndex++;
1289: }
1290: else
1291: {
1292: leftBranch =
1293: (BranchElement) createBranchElement(parent, parentAtts);
1294: added = new Element[] { leftBranch, rightBranch };
1295:
1296:
1297: if (fracStart != pos)
1298: {
1299: Element leftFracturedLeaf =
1300: createLeafElement(leftBranch, atts, fracStart, pos);
1301: leftBranch.replace(leftIns, 0,
1302: new Element[] { leftFracturedLeaf });
1303: }
1304: }
1305:
1306: if (!toFracture.isLeaf())
1307: {
1308:
1309: if (indexOfFrac > 0 && leftBranch != null)
1310: {
1311: Element[] add = new Element[indexOfFrac];
1312: for (int i = 0; i < indexOfFrac; i++)
1313: add[i] = toFracture.getElement(i);
1314: leftIns = add.length;
1315: leftBranch.replace(0, 0, add);
1316: }
1317:
1318: int count = size - indexOfFrac - 1;
1319: if (count > 0)
1320: {
1321: Element[] add = new Element[count];
1322: int j = 0;
1323: int i = indexOfFrac + 1;
1324: while (j < count)
1325: add[j++] = toFracture.getElement(i++);
1326: rightBranch.replace(0, 0, add);
1327: }
1328: }
1329:
1330:
1331:
1332: int rm = 0;
1333: int end = fracEnd;
1334: Element next = rightBranch.getElement(0);
1335: if (next != null && next.isLeaf()
1336: && next.getAttributes().isEqual(atts))
1337: {
1338: end = next.getEndOffset();
1339: rm = 1;
1340: }
1341:
1342: Element rightFracturedLeaf = createLeafElement(rightBranch, atts,
1343: pos, end);
1344: rightBranch.replace(0, rm, new Element[] { rightFracturedLeaf });
1345:
1346:
1347:
1348: int remove = parSize - parentIndex;
1349: Element[] removed = new Element[0];
1350: Element[] added2 = new Element[0];
1351: if (remove > 0)
1352: {
1353: removed = new Element[remove];
1354: int s = 0;
1355: for (int j = parentIndex; j < parSize; j++)
1356: removed[s++] = parent.getElement(j);
1357: edit.addRemovedElements(removed);
1358: added2 = recreateAfterFracture(removed, parent, 1,
1359: rightBranch.getEndOffset());
1360: }
1361:
1362: edit.addAddedElements(added);
1363: edit.addAddedElements(added2);
1364: elementStack.push(rightBranch);
1365: lastFractured = rightFracturedLeaf;
1366: }
1367: else
1368: fracNotCreated = true;
1369: }
1370:
1371:
1386: private Element[] recreateAfterFracture(Element[] recreate,
1387: BranchElement parent, int startFrom,
1388: int startOffset)
1389: {
1390: Element[] added = new Element[recreate.length - startFrom];
1391: int j = 0;
1392: for (int i = startFrom; i < recreate.length; i++)
1393: {
1394: Element curr = recreate[i];
1395: int len = curr.getEndOffset() - curr.getStartOffset();
1396: if (curr instanceof LeafElement)
1397: added[j] = createLeafElement(parent, curr.getAttributes(),
1398: startOffset, startOffset + len);
1399: else
1400: {
1401: BranchElement br =
1402: (BranchElement) createBranchElement(parent,
1403: curr.getAttributes());
1404: int bSize = curr.getElementCount();
1405: for (int k = 0; k < bSize; k++)
1406: {
1407: Element bCurr = curr.getElement(k);
1408: Element[] add = recreateAfterFracture(new Element[] { bCurr }, br, 0,
1409: startOffset);
1410: br.replace(0, 0, add);
1411:
1412: }
1413: added[j] = br;
1414: }
1415: startOffset += len;
1416: j++;
1417: }
1418:
1419: return added;
1420: }
1421: }
1422:
1423:
1435: Edit getEditForParagraphAndIndex(BranchElement para, int index)
1436: {
1437: Edit curr;
1438: int size = edits.size();
1439: for (int i = 0; i < size; i++)
1440: {
1441: curr = (Edit) edits.elementAt(i);
1442: if (curr.e.equals(para))
1443: return curr;
1444: }
1445: curr = new Edit(para, index, null, null);
1446: edits.add(curr);
1447:
1448: return curr;
1449: }
1450:
1456: class Edit
1457: {
1458:
1459: Element e;
1460:
1461:
1462: int index;
1463:
1464:
1465: Vector removed = new Vector();
1466:
1467:
1468: Vector added = new Vector();
1469:
1470:
1476: public Element[] getRemovedElements()
1477: {
1478: int size = removed.size();
1479: Element[] removedElements = new Element[size];
1480: for (int i = 0; i < size; i++)
1481: removedElements[i] = (Element) removed.elementAt(i);
1482: return removedElements;
1483: }
1484:
1485:
1491: public Element[] getAddedElements()
1492: {
1493: int size = added.size();
1494: Element[] addedElements = new Element[size];
1495: for (int i = 0; i < size; i++)
1496: addedElements[i] = (Element) added.elementAt(i);
1497: return addedElements;
1498: }
1499:
1500:
1507: private boolean contains(Vector v, Element e)
1508: {
1509: if (e == null)
1510: return false;
1511:
1512: int i = v.size();
1513: for (int j = 0; j < i; j++)
1514: {
1515: Element e1 = (Element) v.get(j);
1516: if ((e1 != null) && (e1.getAttributes().isEqual(e.getAttributes()))
1517: && (e1.getName().equals(e.getName()))
1518: && (e1.getStartOffset() == e.getStartOffset())
1519: && (e1.getEndOffset() == e.getEndOffset())
1520: && (e1.getParentElement().equals(e.getParentElement()))
1521: && (e1.getElementCount() == e.getElementCount()))
1522: return true;
1523: }
1524: return false;
1525: }
1526:
1527:
1533: public void addRemovedElement(Element e)
1534: {
1535: if (!contains(removed, e))
1536: removed.add(e);
1537: }
1538:
1539:
1545: public void addRemovedElements(Element[] e)
1546: {
1547: if (e == null || e.length == 0)
1548: return;
1549: for (int i = 0; i < e.length; i++)
1550: {
1551: if (!contains(removed, e[i]))
1552: removed.add(e[i]);
1553: }
1554: }
1555:
1556:
1562: public void addAddedElement(Element e)
1563: {
1564: if (!contains(added, e))
1565: added.add(e);
1566: }
1567:
1568:
1574: public void addAddedElements(Element[] e)
1575: {
1576: if (e == null || e.length == 0)
1577: return;
1578: for (int i = 0; i < e.length; i++)
1579: {
1580: if (!contains(added, e[i]))
1581: added.add(e[i]);
1582: }
1583: }
1584:
1585:
1599: public Edit(Element e, int i, Element[] removed, Element[] added)
1600: {
1601: this.e = e;
1602: this.index = i;
1603: addRemovedElements(removed);
1604: addAddedElements(added);
1605: }
1606: }
1607:
1608:
1612: protected class SectionElement extends BranchElement
1613: {
1614:
1617: public SectionElement()
1618: {
1619: super(null, null);
1620: }
1621:
1622:
1628: public String getName()
1629: {
1630: return SectionElementName;
1631: }
1632: }
1633:
1634:
1640: private class StyleChangeListener implements ChangeListener
1641: {
1642:
1643:
1650: public void stateChanged(ChangeEvent event)
1651: {
1652: Style style = (Style) event.getSource();
1653: styleChanged(style);
1654: }
1655: }
1656:
1657:
1658: private static final long serialVersionUID = 940485415728614849L;
1659:
1660:
1663: public static final int BUFFER_SIZE_DEFAULT = 4096;
1664:
1665:
1669: protected DefaultStyledDocument.ElementBuffer buffer;
1670:
1671:
1674: private StyleChangeListener styleChangeListener;
1675:
1676:
1679: Vector edits = new Vector();
1680:
1681:
1684: public DefaultStyledDocument()
1685: {
1686: this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext());
1687: }
1688:
1689:
1696: public DefaultStyledDocument(StyleContext context)
1697: {
1698: this(new GapContent(BUFFER_SIZE_DEFAULT), context);
1699: }
1700:
1701:
1710: public DefaultStyledDocument(AbstractDocument.Content content,
1711: StyleContext context)
1712: {
1713: super(content, context);
1714: buffer = new ElementBuffer(createDefaultRoot());
1715: setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE));
1716: }
1717:
1718:
1733: public Style addStyle(String nm, Style parent)
1734: {
1735: StyleContext context = (StyleContext) getAttributeContext();
1736: Style newStyle = context.addStyle(nm, parent);
1737:
1738:
1739: if (styleChangeListener == null)
1740: styleChangeListener = new StyleChangeListener();
1741: newStyle.addChangeListener(styleChangeListener);
1742:
1743: return newStyle;
1744: }
1745:
1746:
1751: protected AbstractDocument.AbstractElement createDefaultRoot()
1752: {
1753: Element[] tmp;
1754: SectionElement section = new SectionElement();
1755:
1756: BranchElement paragraph = new BranchElement(section, null);
1757: tmp = new Element[1];
1758: tmp[0] = paragraph;
1759: section.replace(0, 0, tmp);
1760:
1761: Element leaf = new LeafElement(paragraph, null, 0, 1);
1762: tmp = new Element[1];
1763: tmp[0] = leaf;
1764: paragraph.replace(0, 0, tmp);
1765:
1766: return section;
1767: }
1768:
1769:
1779: public Element getCharacterElement(int position)
1780: {
1781: Element element = getDefaultRootElement();
1782:
1783: while (!element.isLeaf())
1784: {
1785: int index = element.getElementIndex(position);
1786: element = element.getElement(index);
1787: }
1788:
1789: return element;
1790: }
1791:
1792:
1799: public Color getBackground(AttributeSet attributes)
1800: {
1801: StyleContext context = (StyleContext) getAttributeContext();
1802: return context.getBackground(attributes);
1803: }
1804:
1805:
1810: public Element getDefaultRootElement()
1811: {
1812: return buffer.getRootElement();
1813: }
1814:
1815:
1822: public Font getFont(AttributeSet attributes)
1823: {
1824: StyleContext context = (StyleContext) getAttributeContext();
1825: return context.getFont(attributes);
1826: }
1827:
1828:
1835: public Color getForeground(AttributeSet attributes)
1836: {
1837: StyleContext context = (StyleContext) getAttributeContext();
1838: return context.getForeground(attributes);
1839: }
1840:
1841:
1848: public Style getLogicalStyle(int position)
1849: {
1850: Element paragraph = getParagraphElement(position);
1851: AttributeSet attributes = paragraph.getAttributes();
1852: AttributeSet a = attributes.getResolveParent();
1853:
1854: if (a instanceof Style)
1855: return (Style) a;
1856: return null;
1857: }
1858:
1859:
1870: public Element getParagraphElement(int position)
1871: {
1872: Element e = getDefaultRootElement();
1873: while (!e.isLeaf())
1874: e = e.getElement(e.getElementIndex(position));
1875:
1876: if (e != null)
1877: return e.getParentElement();
1878: return e;
1879: }
1880:
1881:
1889: public Style getStyle(String nm)
1890: {
1891: StyleContext context = (StyleContext) getAttributeContext();
1892: return context.getStyle(nm);
1893: }
1894:
1895:
1901: public void removeStyle(String nm)
1902: {
1903: StyleContext context = (StyleContext) getAttributeContext();
1904: context.removeStyle(nm);
1905: }
1906:
1907:
1921: public void setCharacterAttributes(int offset, int length,
1922: AttributeSet attributes, boolean replace)
1923: {
1924:
1925: if (length == 0)
1926: return;
1927: try
1928: {
1929:
1930:
1931:
1932: writeLock();
1933: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
1934: length,
1935: DocumentEvent.EventType.CHANGE);
1936:
1937:
1938:
1939:
1940: buffer.change(offset, length, ev);
1941:
1942: Element root = getDefaultRootElement();
1943:
1944: int end = offset + length;
1945: Element curr;
1946: for (int pos = offset; pos < end;)
1947: {
1948:
1949: curr = getCharacterElement(pos);
1950: if (pos == curr.getEndOffset())
1951: break;
1952:
1953: MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();
1954: ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));
1955:
1956: if (replace)
1957: a.removeAttributes(a);
1958:
1959: a.addAttributes(attributes);
1960:
1961: pos = curr.getEndOffset();
1962: }
1963: fireChangedUpdate(ev);
1964: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
1965: }
1966: finally
1967: {
1968: writeUnlock();
1969: }
1970: }
1971:
1972:
1980: public void setLogicalStyle(int position, Style style)
1981: {
1982: Element el = getParagraphElement(position);
1983:
1984:
1985: if (el == null)
1986: return;
1987: try
1988: {
1989: writeLock();
1990: if (el instanceof AbstractElement)
1991: {
1992: AbstractElement ael = (AbstractElement) el;
1993: ael.setResolveParent(style);
1994: int start = el.getStartOffset();
1995: int end = el.getEndOffset();
1996: DefaultDocumentEvent ev = new DefaultDocumentEvent(start,
1997: end - start,
1998: DocumentEvent.EventType.CHANGE);
1999: fireChangedUpdate(ev);
2000: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2001: }
2002: else
2003: throw new AssertionError(
2004: "paragraph elements are expected to be"
2005: + "instances of AbstractDocument.AbstractElement");
2006: }
2007: finally
2008: {
2009: writeUnlock();
2010: }
2011: }
2012:
2013:
2026: public void setParagraphAttributes(int offset, int length,
2027: AttributeSet attributes, boolean replace)
2028: {
2029: try
2030: {
2031:
2032:
2033:
2034: writeLock();
2035:
2036:
2037: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2038: length,
2039: DocumentEvent.EventType.CHANGE);
2040:
2041:
2042:
2043:
2044: Element rootElement = getDefaultRootElement();
2045: int startElement = rootElement.getElementIndex(offset);
2046: int endElement = rootElement.getElementIndex(offset + length - 1);
2047: if (endElement < startElement)
2048: endElement = startElement;
2049:
2050: for (int i = startElement; i <= endElement; i++)
2051: {
2052: Element par = rootElement.getElement(i);
2053: MutableAttributeSet a = (MutableAttributeSet) par.getAttributes();
2054:
2055: ev.addEdit(new AttributeUndoableEdit(par, attributes, replace));
2056:
2057: if (replace)
2058: a.removeAttributes(a);
2059:
2060: a.addAttributes(attributes);
2061: }
2062: fireChangedUpdate(ev);
2063: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2064: }
2065: finally
2066: {
2067: writeUnlock();
2068: }
2069: }
2070:
2071:
2080: protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
2081: {
2082: super.insertUpdate(ev, attr);
2083:
2084: if (attr == null)
2085: attr = SimpleAttributeSet.EMPTY;
2086: int offset = ev.getOffset();
2087: int length = ev.getLength();
2088: int endOffset = offset + length;
2089: AttributeSet paragraphAttributes = getParagraphElement(endOffset).getAttributes();
2090: Segment txt = new Segment();
2091: try
2092: {
2093: getText(offset, length, txt);
2094: }
2095: catch (BadLocationException ex)
2096: {
2097: AssertionError ae = new AssertionError("Unexpected bad location");
2098: ae.initCause(ex);
2099: throw ae;
2100: }
2101:
2102: int len = 0;
2103: Vector specs = new Vector();
2104: ElementSpec finalStartTag = null;
2105: short finalStartDirection = ElementSpec.OriginateDirection;
2106: boolean prevCharWasNewline = false;
2107: Element prev = getCharacterElement(offset);
2108: Element next = getCharacterElement(endOffset);
2109: Element prevParagraph = getParagraphElement(offset);
2110: Element paragraph = getParagraphElement(endOffset);
2111:
2112: int segmentEnd = txt.offset + txt.count;
2113:
2114:
2115: if (offset > 0)
2116: {
2117: try
2118: {
2119: String s = getText(offset - 1, 1);
2120: if (s.equals("\n"))
2121: {
2122: finalStartDirection = handleInsertAfterNewline(specs, offset,
2123: endOffset,
2124: prevParagraph,
2125: paragraph,
2126: paragraphAttributes);
2127:
2128: prevCharWasNewline = true;
2129:
2130: for (int i = 0; i < specs.size(); i++)
2131: if (((ElementSpec) specs.get(i)).getType() == ElementSpec.StartTagType)
2132: finalStartTag = (ElementSpec) specs.get(i);
2133: }
2134: }
2135: catch (BadLocationException ble)
2136: {
2137:
2138: AssertionError ae = new AssertionError();
2139: ae.initCause(ble);
2140: throw ae;
2141: }
2142: }
2143:
2144: for (int i = txt.offset; i < segmentEnd; ++i)
2145: {
2146: len++;
2147: if (txt.array[i] == '\n')
2148: {
2149:
2150: specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
2151:
2152:
2153: specs.add(new ElementSpec(null, ElementSpec.EndTagType));
2154: finalStartTag = new ElementSpec(paragraphAttributes,
2155: ElementSpec.StartTagType);
2156: specs.add(finalStartTag);
2157: len = 0;
2158: }
2159: }
2160:
2161:
2162: if (len > 0)
2163: specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
2164:
2165:
2166:
2167:
2168: if (finalStartTag != null)
2169: {
2170: if (prevCharWasNewline)
2171: finalStartTag.setDirection(finalStartDirection);
2172: else if (prevParagraph.getEndOffset() != endOffset)
2173: finalStartTag.setDirection(ElementSpec.JoinFractureDirection);
2174: else
2175: {
2176:
2177:
2178: Element parent = prevParagraph.getParentElement();
2179: int index = parent.getElementIndex(offset);
2180: if (index + 1 < parent.getElementCount()
2181: && !parent.getElement(index + 1).isLeaf())
2182: finalStartTag.setDirection(ElementSpec.JoinNextDirection);
2183: }
2184: }
2185:
2186:
2187:
2188:
2189:
2190:
2191:
2192:
2193: ElementSpec last = (ElementSpec) specs.lastElement();
2194: if (last.getType() == ElementSpec.ContentType)
2195: {
2196: Element currentRun = prevParagraph.getElement(prevParagraph.getElementIndex(offset));
2197: if (currentRun.getEndOffset() == endOffset)
2198: {
2199: if (endOffset < getLength() && next.getAttributes().isEqual(attr)
2200: && last.getType() == ElementSpec.ContentType)
2201: last.setDirection(ElementSpec.JoinNextDirection);
2202: }
2203: else
2204: {
2205: if (finalStartTag != null
2206: && finalStartTag.getDirection() == ElementSpec.JoinFractureDirection
2207: && currentRun.getAttributes().isEqual(attr))
2208: {
2209: last.setDirection(ElementSpec.JoinNextDirection);
2210: }
2211: }
2212: }
2213:
2214:
2215:
2216: ElementSpec first = (ElementSpec) specs.firstElement();
2217: if (prev.getAttributes().isEqual(attr)
2218: && first.getType() == ElementSpec.ContentType)
2219: first.setDirection(ElementSpec.JoinPreviousDirection);
2220:
2221: ElementSpec[] elSpecs = (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]);
2222: buffer.insert(offset, length, elSpecs, ev);
2223: }
2224:
2225:
2232: short handleInsertAfterNewline(Vector specs, int offset, int endOffset,
2233: Element prevParagraph, Element paragraph,
2234: AttributeSet a)
2235: {
2236: if (prevParagraph.getParentElement() == paragraph.getParentElement())
2237: {
2238: specs.add(new ElementSpec(a, ElementSpec.EndTagType));
2239: specs.add(new ElementSpec(a, ElementSpec.StartTagType));
2240: if (paragraph.getStartOffset() != endOffset)
2241: return ElementSpec.JoinFractureDirection;
2242:
2243: Element parent = paragraph.getParentElement();
2244: if (parent.getElementCount() > (parent.getElementIndex(offset) + 1))
2245: return ElementSpec.JoinNextDirection;
2246: }
2247: return ElementSpec.OriginateDirection;
2248: }
2249:
2250:
2259: protected void removeUpdate(DefaultDocumentEvent ev)
2260: {
2261: super.removeUpdate(ev);
2262: buffer.remove(ev.getOffset(), ev.getLength(), ev);
2263: }
2264:
2265:
2270: public Enumeration getStyleNames()
2271: {
2272: StyleContext context = (StyleContext) getAttributeContext();
2273: return context.getStyleNames();
2274: }
2275:
2276:
2282: protected void styleChanged(Style style)
2283: {
2284:
2285: }
2286:
2287:
2295: protected void insert(int offset, ElementSpec[] data)
2296: throws BadLocationException
2297: {
2298: if (data == null || data.length == 0)
2299: return;
2300: try
2301: {
2302:
2303:
2304:
2305: writeLock();
2306:
2307:
2308: StringBuffer contentBuffer = new StringBuffer();
2309: for (int i = 0; i < data.length; i++)
2310: {
2311:
2312:
2313: ElementSpec spec = data[i];
2314: if (spec.getArray() != null && spec.getLength() > 0)
2315: contentBuffer.append(spec.getArray(), spec.getOffset(),
2316: spec.getLength());
2317: }
2318:
2319: int length = contentBuffer.length();
2320:
2321:
2322: if (length == 0)
2323: return;
2324:
2325: UndoableEdit edit = content.insertString(offset,
2326: contentBuffer.toString());
2327:
2328:
2329: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2330: length,
2331: DocumentEvent.EventType.INSERT);
2332: ev.addEdit(edit);
2333:
2334:
2335:
2336: buffer.insert(offset, length, data, ev);
2337: fireInsertUpdate(ev);
2338: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2339: }
2340: finally
2341: {
2342: writeUnlock();
2343: }
2344: }
2345:
2346:
2354: protected void create(ElementSpec[] data)
2355: {
2356: writeLock();
2357: try
2358: {
2359:
2360: int len = getLength();
2361: if (len > 0)
2362: remove(0, len);
2363:
2364:
2365: StringBuilder b = new StringBuilder();
2366: for (int i = 0; i < data.length; ++i)
2367: {
2368: ElementSpec el = data[i];
2369: if (el.getArray() != null && el.getLength() > 0)
2370: b.append(el.getArray(), el.getOffset(), el.getLength());
2371: }
2372: Content content = getContent();
2373: UndoableEdit cEdit = content.insertString(0, b.toString());
2374:
2375: DefaultDocumentEvent ev =
2376: new DefaultDocumentEvent(0, b.length(),
2377: DocumentEvent.EventType.INSERT);
2378: ev.addEdit(cEdit);
2379:
2380:
2381:
2382:
2383:
2384: BranchElement createRoot =
2385: (BranchElement) createBranchElement(null, null);
2386: Element dummyLeaf = createLeafElement(createRoot, null, 0, 1);
2387: createRoot.replace(0, 0, new Element[]{ dummyLeaf });
2388: ElementBuffer createBuffer = new ElementBuffer(createRoot);
2389: createBuffer.insert(0, b.length(), data, new DefaultDocumentEvent(0, b.length(), DocumentEvent.EventType.INSERT));
2390:
2391: Element newRoot = createRoot.getElement(0);
2392: BranchElement root = (BranchElement) getDefaultRootElement();
2393: Element[] added = new Element[newRoot.getElementCount()];
2394: for (int i = 0; i < added.length; ++i)
2395: {
2396: added[i] = newRoot.getElement(i);
2397: ((AbstractElement) added[i]).element_parent = root;
2398: }
2399: Element[] removed = new Element[root.getElementCount()];
2400: for (int i = 0; i < removed.length; ++i)
2401: removed[i] = root.getElement(i);
2402:
2403:
2404: root.replace(0, removed.length, added);
2405: ev.addEdit(new ElementEdit(root, 0, removed, added));
2406:
2407: fireInsertUpdate(ev);
2408: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2409: }
2410: catch (BadLocationException ex)
2411: {
2412: AssertionError err = new AssertionError("Unexpected bad location");
2413: err.initCause(ex);
2414: throw err;
2415: }
2416: finally
2417: {
2418: writeUnlock();
2419: }
2420: }
2421: }