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: if (end != toRec.getEndOffset())
1058: {
1059: recreateLeaves(end, toRec, onlyContent);
1060:
1061: if (onlyContent)
1062: edit.addRemovedElement(target);
1063: }
1064: }
1065: else
1066: paragraph.replace(0, 0, new Element[] { leaf });
1067: }
1068:
1069: pos += len;
1070: }
1071:
1072:
1078: private void createFracture(ElementSpec[] data)
1079: {
1080: BranchElement paragraph = (BranchElement) elementStack.peek();
1081: int index = paragraph.getElementIndex(offset);
1082: Element child = paragraph.getElement(index);
1083: Edit edit = getEditForParagraphAndIndex(paragraph, index);
1084: AttributeSet atts = child.getAttributes();
1085:
1086: if (offset != 0)
1087: {
1088: Element newEl1 = createLeafElement(paragraph, atts,
1089: child.getStartOffset(), offset);
1090: edit.addAddedElement(newEl1);
1091: edit.addRemovedElement(child);
1092: }
1093: }
1094:
1095:
1103: private void recreateLeaves(int start, BranchElement paragraph, boolean onlyContent)
1104: {
1105: int index = paragraph.getElementIndex(start);
1106: Element child = paragraph.getElement(index);
1107: AttributeSet atts = child.getAttributes();
1108:
1109: if (!onlyContent)
1110: {
1111: BranchElement newBranch = (BranchElement) createBranchElement(paragraph,
1112: atts);
1113: Element newLeaf = createLeafElement(newBranch, atts, start,
1114: child.getEndOffset());
1115: newBranch.replace(0, 0, new Element[] { newLeaf });
1116:
1117: BranchElement parent = (BranchElement) paragraph.getParentElement();
1118: int parSize = parent.getElementCount();
1119: Edit edit = getEditForParagraphAndIndex(parent, parSize);
1120: edit.addAddedElement(newBranch);
1121:
1122: int paragraphSize = paragraph.getElementCount();
1123: Element[] removed = new Element[paragraphSize - (index + 1)];
1124: int s = 0;
1125: for (int j = index + 1; j < paragraphSize; j++)
1126: removed[s++] = paragraph.getElement(j);
1127:
1128: edit = getEditForParagraphAndIndex(paragraph, index);
1129: edit.addRemovedElements(removed);
1130: Element[] added = recreateAfterFracture(removed, newBranch, 0, child.getEndOffset());
1131: newBranch.replace(1, 0, added);
1132:
1133: lastFractured = newLeaf;
1134: pos = newBranch.getEndOffset();
1135: }
1136: else
1137: {
1138: Element newLeaf = createLeafElement(paragraph, atts, start,
1139: child.getEndOffset());
1140: Edit edit = getEditForParagraphAndIndex(paragraph, index);
1141: edit.addAddedElement(newLeaf);
1142: }
1143: }
1144:
1145:
1164: private Element[] split(Element el, int offset, int space, int editIndex)
1165: {
1166:
1167: if ((offset == el.getStartOffset() || offset == el.getEndOffset())
1168: && space == 0 && el.isLeaf())
1169: return new Element[2];
1170:
1171:
1172:
1173:
1174: Element[] res = new Element[2];
1175: if (el instanceof BranchElement)
1176: {
1177: int index = el.getElementIndex(offset);
1178: Element child = el.getElement(index);
1179: Element[] result = split(child, offset, space, editIndex);
1180: Element[] removed;
1181: Element[] added;
1182: Element[] newAdded;
1183:
1184: int count = el.getElementCount();
1185: if (result[1] != null)
1186: {
1187:
1188: if (result[0] == null)
1189: {
1190: removed = new Element[count - index - 1];
1191: newAdded = new Element[count - index - 1];
1192: added = new Element[] {};
1193:
1194: }
1195:
1196:
1197: else
1198: {
1199: removed = new Element[count - index];
1200: newAdded = new Element[count - index];
1201: added = new Element[] { result[0] };
1202: }
1203: newAdded[0] = result[1];
1204: for (int i = index; i < count; i++)
1205: {
1206: Element el2 = el.getElement(i);
1207: int ind = i - count + removed.length;
1208: removed[ind] = el2;
1209: if (ind != 0)
1210: newAdded[ind] = el2;
1211: }
1212:
1213: Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
1214: edit.addRemovedElements(removed);
1215: edit.addAddedElements(added);
1216:
1217: BranchElement newPar =
1218: (BranchElement) createBranchElement(el.getParentElement(),
1219: el.getAttributes());
1220: newPar.replace(0, 0, newAdded);
1221: res = new Element[] { null, newPar };
1222: }
1223: else
1224: {
1225: removed = new Element[count - index];
1226: for (int i = index; i < count; ++i)
1227: removed[i - index] = el.getElement(i);
1228:
1229: Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
1230: edit.addRemovedElements(removed);
1231:
1232: BranchElement newPar = (BranchElement) createBranchElement(el.getParentElement(),
1233: el.getAttributes());
1234: newPar.replace(0, 0, removed);
1235: res = new Element[] { null, newPar };
1236: }
1237: }
1238: else if (el instanceof LeafElement)
1239: {
1240: BranchElement par = (BranchElement) el.getParentElement();
1241: Element el1 = createLeafElement(par, el.getAttributes(),
1242: el.getStartOffset(), offset);
1243:
1244: Element el2 = createLeafElement(par, el.getAttributes(),
1245: offset + space,
1246: el.getEndOffset());
1247: res = new Element[] { el1, el2 };
1248: }
1249: return res;
1250: }
1251:
1252:
1258: private void insertFracture(ElementSpec tag)
1259: {
1260:
1261: BranchElement parent = (BranchElement) elementStack.peek();
1262: int parentIndex = parent.getElementIndex(pos);
1263: AttributeSet parentAtts = parent.getAttributes();
1264: Element toFracture = parent.getElement(parentIndex);
1265: int parSize = parent.getElementCount();
1266: Edit edit = getEditForParagraphAndIndex(parent, parentIndex);
1267: Element frac = toFracture;
1268: int leftIns = 0;
1269: int indexOfFrac = toFracture.getElementIndex(pos);
1270: int size = toFracture.getElementCount();
1271:
1272:
1273: frac = toFracture.getElement(indexOfFrac);
1274: while (!frac.isLeaf())
1275: frac = frac.getElement(frac.getElementIndex(pos));
1276:
1277: AttributeSet atts = frac.getAttributes();
1278: int fracStart = frac.getStartOffset();
1279: int fracEnd = frac.getEndOffset();
1280: if (pos >= fracStart && pos < fracEnd)
1281: {
1282:
1283:
1284: BranchElement rightBranch =
1285: (BranchElement) createBranchElement(parent, parentAtts);
1286:
1287:
1288:
1289: BranchElement leftBranch = null;
1290: Element[] added = null;
1291: if (edit.added.size() > 0 || edit.removed.size() > 0)
1292: {
1293: added = new Element[] { rightBranch };
1294:
1295:
1296: parentIndex++;
1297: }
1298: else
1299: {
1300: leftBranch =
1301: (BranchElement) createBranchElement(parent, parentAtts);
1302: added = new Element[] { leftBranch, rightBranch };
1303:
1304:
1305: if (fracStart != pos)
1306: {
1307: Element leftFracturedLeaf =
1308: createLeafElement(leftBranch, atts, fracStart, pos);
1309: leftBranch.replace(leftIns, 0,
1310: new Element[] { leftFracturedLeaf });
1311: }
1312: }
1313:
1314: if (!toFracture.isLeaf())
1315: {
1316:
1317: if (indexOfFrac > 0 && leftBranch != null)
1318: {
1319: Element[] add = new Element[indexOfFrac];
1320: for (int i = 0; i < indexOfFrac; i++)
1321: add[i] = toFracture.getElement(i);
1322: leftIns = add.length;
1323: leftBranch.replace(0, 0, add);
1324: }
1325:
1326: int count = size - indexOfFrac - 1;
1327: if (count > 0)
1328: {
1329: Element[] add = new Element[count];
1330: int j = 0;
1331: int i = indexOfFrac + 1;
1332: while (j < count)
1333: add[j++] = toFracture.getElement(i++);
1334: rightBranch.replace(0, 0, add);
1335: }
1336: }
1337:
1338:
1339:
1340: int rm = 0;
1341: int end = fracEnd;
1342: Element next = rightBranch.getElement(0);
1343: if (next != null && next.isLeaf()
1344: && next.getAttributes().isEqual(atts))
1345: {
1346: end = next.getEndOffset();
1347: rm = 1;
1348: }
1349:
1350: Element rightFracturedLeaf = createLeafElement(rightBranch, atts,
1351: pos, end);
1352: rightBranch.replace(0, rm, new Element[] { rightFracturedLeaf });
1353:
1354:
1355:
1356: int remove = parSize - parentIndex;
1357: Element[] removed = new Element[0];
1358: Element[] added2 = new Element[0];
1359: if (remove > 0)
1360: {
1361: removed = new Element[remove];
1362: int s = 0;
1363: for (int j = parentIndex; j < parSize; j++)
1364: removed[s++] = parent.getElement(j);
1365: edit.addRemovedElements(removed);
1366: added2 = recreateAfterFracture(removed, parent, 1,
1367: rightBranch.getEndOffset());
1368: }
1369:
1370: edit.addAddedElements(added);
1371: edit.addAddedElements(added2);
1372: elementStack.push(rightBranch);
1373: lastFractured = rightFracturedLeaf;
1374: }
1375: else
1376: fracNotCreated = true;
1377: }
1378:
1379:
1394: private Element[] recreateAfterFracture(Element[] recreate,
1395: BranchElement parent, int startFrom,
1396: int startOffset)
1397: {
1398: Element[] added = new Element[recreate.length - startFrom];
1399: int j = 0;
1400: for (int i = startFrom; i < recreate.length; i++)
1401: {
1402: Element curr = recreate[i];
1403: int len = curr.getEndOffset() - curr.getStartOffset();
1404: if (curr instanceof LeafElement)
1405: added[j] = createLeafElement(parent, curr.getAttributes(),
1406: startOffset, startOffset + len);
1407: else
1408: {
1409: BranchElement br =
1410: (BranchElement) createBranchElement(parent,
1411: curr.getAttributes());
1412: int bSize = curr.getElementCount();
1413: for (int k = 0; k < bSize; k++)
1414: {
1415: Element bCurr = curr.getElement(k);
1416: Element[] add = recreateAfterFracture(new Element[] { bCurr }, br, 0,
1417: startOffset);
1418: br.replace(0, 0, add);
1419:
1420: }
1421: added[j] = br;
1422: }
1423: startOffset += len;
1424: j++;
1425: }
1426:
1427: return added;
1428: }
1429: }
1430:
1431:
1443: Edit getEditForParagraphAndIndex(BranchElement para, int index)
1444: {
1445: Edit curr;
1446: int size = edits.size();
1447: for (int i = 0; i < size; i++)
1448: {
1449: curr = (Edit) edits.elementAt(i);
1450: if (curr.e.equals(para))
1451: return curr;
1452: }
1453: curr = new Edit(para, index, null, null);
1454: edits.add(curr);
1455:
1456: return curr;
1457: }
1458:
1464: class Edit
1465: {
1466:
1467: Element e;
1468:
1469:
1470: int index;
1471:
1472:
1473: Vector removed = new Vector();
1474:
1475:
1476: Vector added = new Vector();
1477:
1478:
1484: public Element[] getRemovedElements()
1485: {
1486: int size = removed.size();
1487: Element[] removedElements = new Element[size];
1488: for (int i = 0; i < size; i++)
1489: removedElements[i] = (Element) removed.elementAt(i);
1490: return removedElements;
1491: }
1492:
1493:
1499: public Element[] getAddedElements()
1500: {
1501: int size = added.size();
1502: Element[] addedElements = new Element[size];
1503: for (int i = 0; i < size; i++)
1504: addedElements[i] = (Element) added.elementAt(i);
1505: return addedElements;
1506: }
1507:
1508:
1515: private boolean contains(Vector v, Element e)
1516: {
1517: if (e == null)
1518: return false;
1519:
1520: int i = v.size();
1521: for (int j = 0; j < i; j++)
1522: {
1523: Element e1 = (Element) v.get(j);
1524: if ((e1 != null) && (e1.getAttributes().isEqual(e.getAttributes()))
1525: && (e1.getName().equals(e.getName()))
1526: && (e1.getStartOffset() == e.getStartOffset())
1527: && (e1.getEndOffset() == e.getEndOffset())
1528: && (e1.getParentElement().equals(e.getParentElement()))
1529: && (e1.getElementCount() == e.getElementCount()))
1530: return true;
1531: }
1532: return false;
1533: }
1534:
1535:
1541: public void addRemovedElement(Element e)
1542: {
1543: if (!contains(removed, e))
1544: removed.add(e);
1545: }
1546:
1547:
1553: public void addRemovedElements(Element[] e)
1554: {
1555: if (e == null || e.length == 0)
1556: return;
1557: for (int i = 0; i < e.length; i++)
1558: {
1559: if (!contains(removed, e[i]))
1560: removed.add(e[i]);
1561: }
1562: }
1563:
1564:
1570: public void addAddedElement(Element e)
1571: {
1572: if (!contains(added, e))
1573: added.add(e);
1574: }
1575:
1576:
1582: public void addAddedElements(Element[] e)
1583: {
1584: if (e == null || e.length == 0)
1585: return;
1586: for (int i = 0; i < e.length; i++)
1587: {
1588: if (!contains(added, e[i]))
1589: added.add(e[i]);
1590: }
1591: }
1592:
1593:
1607: public Edit(Element e, int i, Element[] removed, Element[] added)
1608: {
1609: this.e = e;
1610: this.index = i;
1611: addRemovedElements(removed);
1612: addAddedElements(added);
1613: }
1614: }
1615:
1616:
1620: protected class SectionElement extends BranchElement
1621: {
1622:
1625: public SectionElement()
1626: {
1627: super(null, null);
1628: }
1629:
1630:
1636: public String getName()
1637: {
1638: return SectionElementName;
1639: }
1640: }
1641:
1642:
1648: private class StyleChangeListener implements ChangeListener
1649: {
1650:
1651:
1658: public void stateChanged(ChangeEvent event)
1659: {
1660: Style style = (Style) event.getSource();
1661: styleChanged(style);
1662: }
1663: }
1664:
1665:
1666: private static final long serialVersionUID = 940485415728614849L;
1667:
1668:
1671: public static final int BUFFER_SIZE_DEFAULT = 4096;
1672:
1673:
1677: protected DefaultStyledDocument.ElementBuffer buffer;
1678:
1679:
1682: private StyleChangeListener styleChangeListener;
1683:
1684:
1687: Vector edits = new Vector();
1688:
1689:
1692: public DefaultStyledDocument()
1693: {
1694: this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext());
1695: }
1696:
1697:
1704: public DefaultStyledDocument(StyleContext context)
1705: {
1706: this(new GapContent(BUFFER_SIZE_DEFAULT), context);
1707: }
1708:
1709:
1718: public DefaultStyledDocument(AbstractDocument.Content content,
1719: StyleContext context)
1720: {
1721: super(content, context);
1722: buffer = new ElementBuffer(createDefaultRoot());
1723: setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE));
1724: }
1725:
1726:
1741: public Style addStyle(String nm, Style parent)
1742: {
1743: StyleContext context = (StyleContext) getAttributeContext();
1744: Style newStyle = context.addStyle(nm, parent);
1745:
1746:
1747: if (styleChangeListener == null)
1748: styleChangeListener = new StyleChangeListener();
1749: newStyle.addChangeListener(styleChangeListener);
1750:
1751: return newStyle;
1752: }
1753:
1754:
1759: protected AbstractDocument.AbstractElement createDefaultRoot()
1760: {
1761: Element[] tmp;
1762: SectionElement section = new SectionElement();
1763:
1764: BranchElement paragraph = new BranchElement(section, null);
1765: tmp = new Element[1];
1766: tmp[0] = paragraph;
1767: section.replace(0, 0, tmp);
1768:
1769: Element leaf = new LeafElement(paragraph, null, 0, 1);
1770: tmp = new Element[1];
1771: tmp[0] = leaf;
1772: paragraph.replace(0, 0, tmp);
1773:
1774: return section;
1775: }
1776:
1777:
1787: public Element getCharacterElement(int position)
1788: {
1789: Element element = getDefaultRootElement();
1790:
1791: while (!element.isLeaf())
1792: {
1793: int index = element.getElementIndex(position);
1794: element = element.getElement(index);
1795: }
1796:
1797: return element;
1798: }
1799:
1800:
1807: public Color getBackground(AttributeSet attributes)
1808: {
1809: StyleContext context = (StyleContext) getAttributeContext();
1810: return context.getBackground(attributes);
1811: }
1812:
1813:
1818: public Element getDefaultRootElement()
1819: {
1820: return buffer.getRootElement();
1821: }
1822:
1823:
1830: public Font getFont(AttributeSet attributes)
1831: {
1832: StyleContext context = (StyleContext) getAttributeContext();
1833: return context.getFont(attributes);
1834: }
1835:
1836:
1843: public Color getForeground(AttributeSet attributes)
1844: {
1845: StyleContext context = (StyleContext) getAttributeContext();
1846: return context.getForeground(attributes);
1847: }
1848:
1849:
1856: public Style getLogicalStyle(int position)
1857: {
1858: Element paragraph = getParagraphElement(position);
1859: AttributeSet attributes = paragraph.getAttributes();
1860: AttributeSet a = attributes.getResolveParent();
1861:
1862: if (a instanceof Style)
1863: return (Style) a;
1864: return null;
1865: }
1866:
1867:
1878: public Element getParagraphElement(int position)
1879: {
1880: Element e = getDefaultRootElement();
1881: while (!e.isLeaf())
1882: e = e.getElement(e.getElementIndex(position));
1883:
1884: if (e != null)
1885: return e.getParentElement();
1886: return e;
1887: }
1888:
1889:
1897: public Style getStyle(String nm)
1898: {
1899: StyleContext context = (StyleContext) getAttributeContext();
1900: return context.getStyle(nm);
1901: }
1902:
1903:
1909: public void removeStyle(String nm)
1910: {
1911: StyleContext context = (StyleContext) getAttributeContext();
1912: context.removeStyle(nm);
1913: }
1914:
1915:
1929: public void setCharacterAttributes(int offset, int length,
1930: AttributeSet attributes, boolean replace)
1931: {
1932:
1933: if (length == 0)
1934: return;
1935: try
1936: {
1937:
1938:
1939:
1940: writeLock();
1941: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
1942: length,
1943: DocumentEvent.EventType.CHANGE);
1944:
1945:
1946:
1947:
1948: buffer.change(offset, length, ev);
1949:
1950: Element root = getDefaultRootElement();
1951:
1952: int end = offset + length;
1953: Element curr;
1954: for (int pos = offset; pos < end;)
1955: {
1956:
1957: curr = getCharacterElement(pos);
1958: if (pos == curr.getEndOffset())
1959: break;
1960:
1961: MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();
1962: ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));
1963:
1964: if (replace)
1965: a.removeAttributes(a);
1966:
1967: a.addAttributes(attributes);
1968:
1969: pos = curr.getEndOffset();
1970: }
1971: fireChangedUpdate(ev);
1972: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
1973: }
1974: finally
1975: {
1976: writeUnlock();
1977: }
1978: }
1979:
1980:
1988: public void setLogicalStyle(int position, Style style)
1989: {
1990: Element el = getParagraphElement(position);
1991:
1992:
1993: if (el == null)
1994: return;
1995: try
1996: {
1997: writeLock();
1998: if (el instanceof AbstractElement)
1999: {
2000: AbstractElement ael = (AbstractElement) el;
2001: ael.setResolveParent(style);
2002: int start = el.getStartOffset();
2003: int end = el.getEndOffset();
2004: DefaultDocumentEvent ev = new DefaultDocumentEvent(start,
2005: end - start,
2006: DocumentEvent.EventType.CHANGE);
2007: fireChangedUpdate(ev);
2008: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2009: }
2010: else
2011: throw new AssertionError(
2012: "paragraph elements are expected to be"
2013: + "instances of AbstractDocument.AbstractElement");
2014: }
2015: finally
2016: {
2017: writeUnlock();
2018: }
2019: }
2020:
2021:
2034: public void setParagraphAttributes(int offset, int length,
2035: AttributeSet attributes, boolean replace)
2036: {
2037: try
2038: {
2039:
2040:
2041:
2042: writeLock();
2043:
2044:
2045: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2046: length,
2047: DocumentEvent.EventType.CHANGE);
2048:
2049:
2050:
2051:
2052: Element rootElement = getDefaultRootElement();
2053: int startElement = rootElement.getElementIndex(offset);
2054: int endElement = rootElement.getElementIndex(offset + length - 1);
2055: if (endElement < startElement)
2056: endElement = startElement;
2057:
2058: for (int i = startElement; i <= endElement; i++)
2059: {
2060: Element par = rootElement.getElement(i);
2061: MutableAttributeSet a = (MutableAttributeSet) par.getAttributes();
2062:
2063: ev.addEdit(new AttributeUndoableEdit(par, attributes, replace));
2064:
2065: if (replace)
2066: a.removeAttributes(a);
2067:
2068: a.addAttributes(attributes);
2069: }
2070: fireChangedUpdate(ev);
2071: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2072: }
2073: finally
2074: {
2075: writeUnlock();
2076: }
2077: }
2078:
2079:
2088: protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
2089: {
2090: super.insertUpdate(ev, attr);
2091:
2092: if (attr == null)
2093: attr = SimpleAttributeSet.EMPTY;
2094: int offset = ev.getOffset();
2095: int length = ev.getLength();
2096: int endOffset = offset + length;
2097: AttributeSet paragraphAttributes = getParagraphElement(endOffset).getAttributes();
2098: Segment txt = new Segment();
2099: try
2100: {
2101: getText(offset, length, txt);
2102: }
2103: catch (BadLocationException ex)
2104: {
2105: AssertionError ae = new AssertionError("Unexpected bad location");
2106: ae.initCause(ex);
2107: throw ae;
2108: }
2109:
2110: int len = 0;
2111: Vector specs = new Vector();
2112: ElementSpec finalStartTag = null;
2113: short finalStartDirection = ElementSpec.OriginateDirection;
2114: boolean prevCharWasNewline = false;
2115: Element prev = getCharacterElement(offset);
2116: Element next = getCharacterElement(endOffset);
2117: Element prevParagraph = getParagraphElement(offset);
2118: Element paragraph = getParagraphElement(endOffset);
2119:
2120: int segmentEnd = txt.offset + txt.count;
2121:
2122:
2123: if (offset > 0)
2124: {
2125: try
2126: {
2127: String s = getText(offset - 1, 1);
2128: if (s.equals("\n"))
2129: {
2130: finalStartDirection = handleInsertAfterNewline(specs, offset,
2131: endOffset,
2132: prevParagraph,
2133: paragraph,
2134: paragraphAttributes);
2135:
2136: prevCharWasNewline = true;
2137:
2138: for (int i = 0; i < specs.size(); i++)
2139: if (((ElementSpec) specs.get(i)).getType() == ElementSpec.StartTagType)
2140: finalStartTag = (ElementSpec) specs.get(i);
2141: }
2142: }
2143: catch (BadLocationException ble)
2144: {
2145:
2146: AssertionError ae = new AssertionError();
2147: ae.initCause(ble);
2148: throw ae;
2149: }
2150: }
2151:
2152: for (int i = txt.offset; i < segmentEnd; ++i)
2153: {
2154: len++;
2155: if (txt.array[i] == '\n')
2156: {
2157:
2158: specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
2159:
2160:
2161: specs.add(new ElementSpec(null, ElementSpec.EndTagType));
2162: finalStartTag = new ElementSpec(paragraphAttributes,
2163: ElementSpec.StartTagType);
2164: specs.add(finalStartTag);
2165: len = 0;
2166: }
2167: }
2168:
2169:
2170: if (len > 0)
2171: specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
2172:
2173:
2174:
2175:
2176: if (finalStartTag != null)
2177: {
2178: if (prevCharWasNewline)
2179: finalStartTag.setDirection(finalStartDirection);
2180: else if (prevParagraph.getEndOffset() != endOffset)
2181: finalStartTag.setDirection(ElementSpec.JoinFractureDirection);
2182: else
2183: {
2184:
2185:
2186: Element parent = prevParagraph.getParentElement();
2187: int index = parent.getElementIndex(offset);
2188: if (index + 1 < parent.getElementCount()
2189: && !parent.getElement(index + 1).isLeaf())
2190: finalStartTag.setDirection(ElementSpec.JoinNextDirection);
2191: }
2192: }
2193:
2194:
2195:
2196:
2197:
2198:
2199:
2200:
2201: ElementSpec last = (ElementSpec) specs.lastElement();
2202: if (last.getType() == ElementSpec.ContentType)
2203: {
2204: Element currentRun = prevParagraph.getElement(prevParagraph.getElementIndex(offset));
2205: if (currentRun.getEndOffset() == endOffset)
2206: {
2207: if (endOffset < getLength() && next.getAttributes().isEqual(attr)
2208: && last.getType() == ElementSpec.ContentType)
2209: last.setDirection(ElementSpec.JoinNextDirection);
2210: }
2211: else
2212: {
2213: if (finalStartTag != null
2214: && finalStartTag.getDirection() == ElementSpec.JoinFractureDirection
2215: && currentRun.getAttributes().isEqual(attr))
2216: {
2217: last.setDirection(ElementSpec.JoinNextDirection);
2218: }
2219: }
2220: }
2221:
2222:
2223:
2224: ElementSpec first = (ElementSpec) specs.firstElement();
2225: if (prev.getAttributes().isEqual(attr)
2226: && first.getType() == ElementSpec.ContentType)
2227: first.setDirection(ElementSpec.JoinPreviousDirection);
2228:
2229: ElementSpec[] elSpecs = (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]);
2230: buffer.insert(offset, length, elSpecs, ev);
2231: }
2232:
2233:
2240: short handleInsertAfterNewline(Vector specs, int offset, int endOffset,
2241: Element prevParagraph, Element paragraph,
2242: AttributeSet a)
2243: {
2244: if (prevParagraph.getParentElement() == paragraph.getParentElement())
2245: {
2246: specs.add(new ElementSpec(a, ElementSpec.EndTagType));
2247: specs.add(new ElementSpec(a, ElementSpec.StartTagType));
2248: if (paragraph.getStartOffset() != endOffset)
2249: return ElementSpec.JoinFractureDirection;
2250:
2251: Element parent = paragraph.getParentElement();
2252: if (parent.getElementCount() > (parent.getElementIndex(offset) + 1))
2253: return ElementSpec.JoinNextDirection;
2254: }
2255: return ElementSpec.OriginateDirection;
2256: }
2257:
2258:
2267: protected void removeUpdate(DefaultDocumentEvent ev)
2268: {
2269: super.removeUpdate(ev);
2270: buffer.remove(ev.getOffset(), ev.getLength(), ev);
2271: }
2272:
2273:
2278: public Enumeration getStyleNames()
2279: {
2280: StyleContext context = (StyleContext) getAttributeContext();
2281: return context.getStyleNames();
2282: }
2283:
2284:
2290: protected void styleChanged(Style style)
2291: {
2292:
2293: }
2294:
2295:
2303: protected void insert(int offset, ElementSpec[] data)
2304: throws BadLocationException
2305: {
2306: if (data == null || data.length == 0)
2307: return;
2308: try
2309: {
2310:
2311:
2312:
2313: writeLock();
2314:
2315:
2316: StringBuffer contentBuffer = new StringBuffer();
2317: for (int i = 0; i < data.length; i++)
2318: {
2319:
2320:
2321: ElementSpec spec = data[i];
2322: if (spec.getArray() != null && spec.getLength() > 0)
2323: contentBuffer.append(spec.getArray(), spec.getOffset(),
2324: spec.getLength());
2325: }
2326:
2327: int length = contentBuffer.length();
2328:
2329:
2330: if (length == 0)
2331: return;
2332:
2333: UndoableEdit edit = content.insertString(offset,
2334: contentBuffer.toString());
2335:
2336:
2337: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2338: length,
2339: DocumentEvent.EventType.INSERT);
2340: ev.addEdit(edit);
2341:
2342:
2343:
2344: buffer.insert(offset, length, data, ev);
2345: fireInsertUpdate(ev);
2346: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2347: }
2348: finally
2349: {
2350: writeUnlock();
2351: }
2352: }
2353:
2354:
2362: protected void create(ElementSpec[] data)
2363: {
2364: writeLock();
2365: try
2366: {
2367:
2368: int len = getLength();
2369: if (len > 0)
2370: remove(0, len);
2371:
2372:
2373: StringBuilder b = new StringBuilder();
2374: for (int i = 0; i < data.length; ++i)
2375: {
2376: ElementSpec el = data[i];
2377: if (el.getArray() != null && el.getLength() > 0)
2378: b.append(el.getArray(), el.getOffset(), el.getLength());
2379: }
2380: Content content = getContent();
2381: UndoableEdit cEdit = content.insertString(0, b.toString());
2382:
2383: DefaultDocumentEvent ev =
2384: new DefaultDocumentEvent(0, b.length(),
2385: DocumentEvent.EventType.INSERT);
2386: ev.addEdit(cEdit);
2387:
2388:
2389:
2390:
2391:
2392: BranchElement createRoot =
2393: (BranchElement) createBranchElement(null, null);
2394: Element dummyLeaf = createLeafElement(createRoot, null, 0, 1);
2395: createRoot.replace(0, 0, new Element[]{ dummyLeaf });
2396: ElementBuffer createBuffer = new ElementBuffer(createRoot);
2397: createBuffer.insert(0, b.length(), data, new DefaultDocumentEvent(0, b.length(), DocumentEvent.EventType.INSERT));
2398:
2399: Element newRoot = createRoot.getElement(0);
2400: BranchElement root = (BranchElement) getDefaultRootElement();
2401: Element[] added = new Element[newRoot.getElementCount()];
2402: for (int i = 0; i < added.length; ++i)
2403: {
2404: added[i] = newRoot.getElement(i);
2405: ((AbstractElement) added[i]).element_parent = root;
2406: }
2407: Element[] removed = new Element[root.getElementCount()];
2408: for (int i = 0; i < removed.length; ++i)
2409: removed[i] = root.getElement(i);
2410:
2411:
2412: root.replace(0, removed.length, added);
2413: ev.addEdit(new ElementEdit(root, 0, removed, added));
2414:
2415: fireInsertUpdate(ev);
2416: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2417: }
2418: catch (BadLocationException ex)
2419: {
2420: AssertionError err = new AssertionError("Unexpected bad location");
2421: err.initCause(ex);
2422: throw err;
2423: }
2424: finally
2425: {
2426: writeUnlock();
2427: }
2428: }
2429: }