1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49:
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56:
57:
67: public class DefaultStyledDocument extends AbstractDocument implements
68: StyledDocument
69: {
70:
71:
76: public static class AttributeUndoableEdit extends AbstractUndoableEdit
77: {
78:
81: protected AttributeSet copy;
82:
83:
86: protected AttributeSet newAttributes;
87:
88:
92: protected boolean isReplacing;
93:
94:
97: protected Element element;
98:
99:
109: public AttributeUndoableEdit(Element el, AttributeSet newAtts,
110: boolean replacing)
111: {
112: element = el;
113: newAttributes = newAtts;
114: isReplacing = replacing;
115: copy = el.getAttributes().copyAttributes();
116: }
117:
118:
122: public void undo()
123: {
124: super.undo();
125: AttributeSet atts = element.getAttributes();
126: if (atts instanceof MutableAttributeSet)
127: {
128: MutableAttributeSet mutable = (MutableAttributeSet) atts;
129: mutable.removeAttributes(atts);
130: mutable.addAttributes(copy);
131: }
132: }
133:
134:
139: public void redo()
140: {
141: super.undo();
142: AttributeSet atts = element.getAttributes();
143: if (atts instanceof MutableAttributeSet)
144: {
145: MutableAttributeSet mutable = (MutableAttributeSet) atts;
146: if (isReplacing)
147: mutable.removeAttributes(atts);
148: mutable.addAttributes(newAttributes);
149: }
150: }
151: }
152:
153:
158: public static class ElementSpec
159: {
160:
163: public static final short StartTagType = 1;
164:
165:
168: public static final short EndTagType = 2;
169:
170:
174: public static final short ContentType = 3;
175:
176:
180: public static final short JoinPreviousDirection = 4;
181:
182:
186: public static final short JoinNextDirection = 5;
187:
188:
192: public static final short OriginateDirection = 6;
193:
194:
199: public static final short JoinFractureDirection = 7;
200:
201:
204: short type;
205:
206:
209: short direction;
210:
211:
214: int offset;
215:
216:
219: int length;
220:
221:
224: char[] content;
225:
226:
229: AttributeSet attributes;
230:
231:
240: public ElementSpec(AttributeSet a, short type)
241: {
242: this(a, type, 0);
243: }
244:
245:
257: public ElementSpec(AttributeSet a, short type, int len)
258: {
259: this(a, type, null, 0, len);
260: }
261:
262:
276: public ElementSpec(AttributeSet a, short type, char[] txt, int offs, int len)
277: {
278: attributes = a;
279: this.type = type;
280: offset = offs;
281: length = len;
282: content = txt;
283: direction = OriginateDirection;
284: }
285:
286:
292: public void setType(short type)
293: {
294: this.type = type;
295: }
296:
297:
302: public short getType()
303: {
304: return type;
305: }
306:
307:
313: public void setDirection(short dir)
314: {
315: direction = dir;
316: }
317:
318:
323: public short getDirection()
324: {
325: return direction;
326: }
327:
328:
333: public AttributeSet getAttributes()
334: {
335: return attributes;
336: }
337:
338:
343: public char[] getArray()
344: {
345: return content;
346: }
347:
348:
353: public int getOffset()
354: {
355: return offset;
356: }
357:
358:
363: public int getLength()
364: {
365: return length;
366: }
367:
368:
375: public String toString()
376: {
377: StringBuilder b = new StringBuilder();
378: switch (type)
379: {
380: case StartTagType:
381: b.append("StartTag");
382: break;
383: case EndTagType:
384: b.append("EndTag");
385: break;
386: case ContentType:
387: b.append("Content");
388: break;
389: default:
390: b.append("??");
391: break;
392: }
393:
394: b.append(':');
395:
396: switch (direction)
397: {
398: case JoinPreviousDirection:
399: b.append("JoinPrevious");
400: break;
401: case JoinNextDirection:
402: b.append("JoinNext");
403: break;
404: case OriginateDirection:
405: b.append("Originate");
406: break;
407: case JoinFractureDirection:
408: b.append("Fracture");
409: break;
410: default:
411: b.append("??");
412: break;
413: }
414:
415: b.append(':');
416: b.append(length);
417:
418: return b.toString();
419: }
420: }
421:
422:
427: public class ElementBuffer implements Serializable
428: {
429:
435: class Edit
436: {
437:
438: Element e;
439:
440:
441: int index;
442:
443:
444: ArrayList removed = new ArrayList();
445:
446:
447: ArrayList added = new ArrayList();
448:
449:
452: boolean isFracture;
453:
454:
460: Edit(Element el, int i)
461: {
462: this(el, i, false);
463: }
464:
465:
472: Edit(Element el, int i, boolean frac)
473: {
474: e = el;
475: index = i;
476: isFracture = frac;
477: }
478:
479: }
480:
481:
482: private static final long serialVersionUID = 1688745877691146623L;
483:
484:
485: private Element root;
486:
487:
488: private int offset;
489:
490:
491: private int endOffset;
492:
493:
494: private int length;
495:
496:
497: private int pos;
498:
499:
502: private Element fracturedParent;
503:
504:
507: private Element fracturedChild;
508:
509:
512: private boolean createdFracture;
513:
514:
518: private Stack elementStack;
519:
520: private Edit[] insertPath;
521:
522: private boolean recreateLeafs;
523:
524:
527: private ArrayList edits;
528:
529: private boolean offsetLastIndex;
530: private boolean offsetLastIndexReplace;
531:
532:
539: public ElementBuffer(Element root)
540: {
541: this.root = root;
542: }
543:
544:
549: public Element getRootElement()
550: {
551: return root;
552: }
553:
554:
565: public void remove(int offs, int len, DefaultDocumentEvent ev)
566: {
567: prepareEdit(offs, len);
568: removeUpdate();
569: finishEdit(ev);
570: }
571:
572:
577: protected void removeUpdate()
578: {
579: removeElements(root, offset, endOffset);
580: }
581:
582: private boolean removeElements(Element elem, int rmOffs0, int rmOffs1)
583: {
584: boolean ret = false;
585: if (! elem.isLeaf())
586: {
587:
588: int index0 = elem.getElementIndex(rmOffs0);
589: int index1 = elem.getElementIndex(rmOffs1);
590: elementStack.push(new Edit(elem, index0));
591: Edit ec = (Edit) elementStack.peek();
592:
593:
594:
595: if (index0 == index1)
596: {
597: Element child0 = elem.getElement(index0);
598: if(rmOffs0 <= child0.getStartOffset()
599: && rmOffs1 >= child0.getEndOffset())
600: {
601:
602: ec.removed.add(child0);
603: }
604: else if (removeElements(child0, rmOffs0, rmOffs1))
605: {
606: ec.removed.add(child0);
607: }
608: }
609: else
610: {
611:
612:
613:
614: Element child0 = elem.getElement(index0);
615: Element child1 = elem.getElement(index1);
616: boolean containsOffs1 = (rmOffs1 < elem.getEndOffset());
617: if (containsOffs1 && canJoin(child0, child1))
618: {
619:
620: for (int i = index0; i <= index1; i++)
621: {
622: ec.removed.add(elem.getElement(i));
623: }
624: Element e = join(elem, child0, child1, rmOffs0, rmOffs1);
625: ec.added.add(e);
626: }
627: else
628: {
629:
630: int rmIndex0 = index0 + 1;
631: int rmIndex1 = index1 - 1;
632: if (child0.getStartOffset() == rmOffs0
633: || (index0 == 0 && child0.getStartOffset() > rmOffs0
634: && child0.getEndOffset() <= rmOffs1))
635: {
636:
637: child0 = null;
638: rmIndex0 = index0;
639: }
640: if (! containsOffs1)
641: {
642: child1 = null;
643: rmIndex1++;
644: }
645: else if (child1.getStartOffset() == rmOffs1)
646: {
647:
648: child1 = null;
649: }
650: if (rmIndex0 <= rmIndex1)
651: {
652: ec.index = rmIndex0;
653: }
654: for (int i = rmIndex0; i <= rmIndex1; i++)
655: {
656: ec.removed.add(elem.getElement(i));
657: }
658: if (child0 != null)
659: {
660: if(removeElements(child0, rmOffs0, rmOffs1))
661: {
662: ec.removed.add(0, child0);
663: ec.index = index0;
664: }
665: }
666: if (child1 != null)
667: {
668: if(removeElements(child1, rmOffs0, rmOffs1))
669: {
670: ec.removed.add(child1);
671: }
672: }
673: }
674: }
675:
676:
677: pop();
678:
679:
680: if(elem.getElementCount() == (ec.removed.size() - ec.added.size()))
681: ret = true;
682: }
683: return ret;
684: }
685:
686:
694: void create(int len, ElementSpec[] data, DefaultDocumentEvent ev)
695: {
696: prepareEdit(offset, len);
697: Element el = root;
698: int index = el.getElementIndex(0);
699: while (! el.isLeaf())
700: {
701: Element child = el.getElement(index);
702: Edit edit = new Edit(el, index, false);
703: elementStack.push(edit);
704: el = child;
705: index = el.getElementIndex(0);
706: }
707: Edit ed = (Edit) elementStack.peek();
708: Element child = ed.e.getElement(ed.index);
709: ed.added.add(createLeafElement(ed.e, child.getAttributes(), getLength(),
710: child.getEndOffset()));
711: ed.removed.add(child);
712: while (elementStack.size() > 1)
713: pop();
714: int n = data.length;
715:
716:
717: AttributeSet newAtts = null;
718: if (n > 0 && data[0].getType() == ElementSpec.StartTagType)
719: newAtts = data[0].getAttributes();
720: if (newAtts == null)
721: newAtts = SimpleAttributeSet.EMPTY;
722: MutableAttributeSet mAtts = (MutableAttributeSet) root.getAttributes();
723: ev.addEdit(new AttributeUndoableEdit(root, newAtts, true));
724: mAtts.removeAttributes(mAtts);
725: mAtts.addAttributes(newAtts);
726:
727:
728: for (int i = 1; i < n; i++)
729: insertElement(data[i]);
730:
731:
732: while (elementStack.size() > 0)
733: pop();
734:
735: finishEdit(ev);
736: }
737:
738: private boolean canJoin(Element e0, Element e1)
739: {
740: boolean ret = false;
741: if ((e0 != null) && (e1 != null))
742: {
743:
744: boolean isLeaf0 = e0.isLeaf();
745: boolean isLeaf1 = e1.isLeaf();
746: if(isLeaf0 == isLeaf1)
747: {
748: if (isLeaf0)
749: {
750:
751:
752: ret = e0.getAttributes().isEqual(e1.getAttributes());
753: }
754: else
755: {
756:
757:
758:
759: String name0 = e0.getName();
760: String name1 = e1.getName();
761: if (name0 != null)
762: ret = name0.equals(name1);
763: else if (name1 != null)
764: ret = name1.equals(name0);
765: else
766: ret = true;
767: }
768: }
769: }
770: return ret;
771: }
772:
773: private Element join(Element p, Element left, Element right, int rmOffs0,
774: int rmOffs1)
775: {
776: Element joined = null;
777: if (left.isLeaf() && right.isLeaf())
778: {
779: joined = createLeafElement(p, left.getAttributes(),
780: left.getStartOffset(),
781: right.getEndOffset());
782: }
783: else if ((! left.isLeaf()) && (! right.isLeaf()))
784: {
785:
786:
787:
788:
789: joined = createBranchElement(p, left.getAttributes());
790: int ljIndex = left.getElementIndex(rmOffs0);
791: int rjIndex = right.getElementIndex(rmOffs1);
792: Element lj = left.getElement(ljIndex);
793: if (lj.getStartOffset() >= rmOffs0)
794: {
795: lj = null;
796: }
797: Element rj = right.getElement(rjIndex);
798: if (rj.getStartOffset() == rmOffs1)
799: {
800: rj = null;
801: }
802: ArrayList children = new ArrayList();
803:
804: for (int i = 0; i < ljIndex; i++)
805: {
806: children.add(clone(joined, left.getElement(i)));
807: }
808:
809:
810: if (canJoin(lj, rj))
811: {
812: Element e = join(joined, lj, rj, rmOffs0, rmOffs1);
813: children.add(e);
814: }
815: else
816: {
817: if (lj != null)
818: {
819: children.add(cloneAsNecessary(joined, lj, rmOffs0, rmOffs1));
820: }
821: if (rj != null)
822: {
823: children.add(cloneAsNecessary(joined, rj, rmOffs0, rmOffs1));
824: }
825: }
826:
827:
828: int n = right.getElementCount();
829: for (int i = (rj == null) ? rjIndex : rjIndex + 1; i < n; i++)
830: {
831: children.add(clone(joined, right.getElement(i)));
832: }
833:
834:
835: Element[] c = new Element[children.size()];
836: c = (Element[]) children.toArray(c);
837: ((BranchElement) joined).replace(0, 0, c);
838: }
839: else
840: {
841: assert false : "Must not happen";
842: }
843: return joined;
844: }
845:
846:
851: protected void changeUpdate()
852: {
853: boolean didEnd = split(offset, length);
854: if (! didEnd)
855: {
856:
857: while (elementStack.size() != 0)
858: {
859: pop();
860: }
861: split(offset + length, 0);
862: }
863: while (elementStack.size() != 0)
864: {
865: pop();
866: }
867: }
868:
869:
883: public void change(int offset, int length, DefaultDocumentEvent ev)
884: {
885: prepareEdit(offset, length);
886: changeUpdate();
887: finishEdit(ev);
888: }
889:
890:
902: public Element clone(Element parent, Element clonee)
903: {
904: Element clone = clonee;
905:
906: if (clonee instanceof BranchElement)
907: {
908: BranchElement branchEl = (BranchElement) clonee;
909: BranchElement branchClone =
910: new BranchElement(parent, branchEl.getAttributes());
911:
912: int numChildren = branchClone.getElementCount();
913: Element[] cloneChildren = new Element[numChildren];
914: for (int i = 0; i < numChildren; ++i)
915: {
916: cloneChildren[i] = clone(branchClone,
917: branchClone.getElement(i));
918: }
919: branchClone.replace(0, 0, cloneChildren);
920: clone = branchClone;
921: }
922: else if (clonee instanceof LeafElement)
923: {
924: clone = new LeafElement(parent, clonee.getAttributes(),
925: clonee.getStartOffset(),
926: clonee.getEndOffset());
927: }
928: return clone;
929: }
930:
931: private Element cloneAsNecessary(Element parent, Element clonee,
932: int rmOffs0, int rmOffs1)
933: {
934: Element cloned;
935: if (clonee.isLeaf())
936: {
937: cloned = createLeafElement(parent, clonee.getAttributes(),
938: clonee.getStartOffset(),
939: clonee.getEndOffset());
940: }
941: else
942: {
943: Element e = createBranchElement(parent, clonee.getAttributes());
944: int n = clonee.getElementCount();
945: ArrayList childrenList = new ArrayList(n);
946: for (int i = 0; i < n; i++)
947: {
948: Element elem = clonee.getElement(i);
949: if (elem.getStartOffset() < rmOffs0
950: || elem.getEndOffset() > rmOffs1)
951: {
952: childrenList.add(cloneAsNecessary(e, elem, rmOffs0,
953: rmOffs1));
954: }
955: }
956: Element[] children = new Element[childrenList.size()];
957: children = (Element[]) childrenList.toArray(children);
958: ((BranchElement) e).replace(0, 0, children);
959: cloned = e;
960: }
961: return cloned;
962: }
963:
964:
979: public void insert(int offset, int length, ElementSpec[] data,
980: DefaultDocumentEvent ev)
981: {
982: if (length > 0)
983: {
984: prepareEdit(offset, length);
985: insertUpdate(data);
986: finishEdit(ev);
987: }
988: }
989:
990:
996: private void prepareEdit(int offset, int length)
997: {
998: this.offset = offset;
999: this.pos = offset;
1000: this.endOffset = offset + length;
1001: this.length = length;
1002:
1003: if (edits == null)
1004: edits = new ArrayList();
1005: else
1006: edits.clear();
1007:
1008: if (elementStack == null)
1009: elementStack = new Stack();
1010: else
1011: elementStack.clear();
1012:
1013: fracturedParent = null;
1014: fracturedChild = null;
1015: offsetLastIndex = false;
1016: offsetLastIndexReplace = false;
1017: }
1018:
1019:
1025: private void finishEdit(DefaultDocumentEvent ev)
1026: {
1027:
1028:
1029: for (Iterator i = edits.iterator(); i.hasNext();)
1030: {
1031: Edit edits = (Edit) i.next();
1032: Element[] removed = new Element[edits.removed.size()];
1033: removed = (Element[]) edits.removed.toArray(removed);
1034: Element[] added = new Element[edits.added.size()];
1035: added = (Element[]) edits.added.toArray(added);
1036: int index = edits.index;
1037: BranchElement parent = (BranchElement) edits.e;
1038: parent.replace(index, removed.length, added);
1039: ElementEdit ee = new ElementEdit(parent, index, removed, added);
1040: ev.addEdit(ee);
1041: }
1042: edits.clear();
1043: elementStack.clear();
1044: }
1045:
1046:
1051: protected void insertUpdate(ElementSpec[] data)
1052: {
1053:
1054: Element current = root;
1055: int index = current.getElementIndex(offset);
1056: while (! current.isLeaf())
1057: {
1058: Element child = current.getElement(index);
1059: int editIndex = child.isLeaf() ? index : index + 1;
1060: Edit edit = new Edit(current, editIndex);
1061: elementStack.push(edit);
1062: current = child;
1063: index = current.getElementIndex(offset);
1064: }
1065:
1066:
1067: insertPath = new Edit[elementStack.size()];
1068: insertPath = (Edit[]) elementStack.toArray(insertPath);
1069:
1070:
1071: createdFracture = false;
1072:
1073:
1074: int i = 0;
1075: recreateLeafs = false;
1076: int type = data[0].getType();
1077: if (type == ElementSpec.ContentType)
1078: {
1079:
1080:
1081:
1082: insertFirstContentTag(data);
1083: pos += data[0].length;
1084: i = 1;
1085: }
1086: else
1087: {
1088: createFracture(data);
1089: i = 0;
1090: }
1091:
1092:
1093: for (; i < data.length; i++)
1094: {
1095: insertElement(data[i]);
1096: }
1097:
1098:
1099: if (! createdFracture)
1100: fracture(-1);
1101:
1102:
1103: while (elementStack.size() != 0)
1104: pop();
1105:
1106:
1107: if (offsetLastIndex && offsetLastIndexReplace)
1108: insertPath[insertPath.length - 1].index++;
1109:
1110:
1111: for (int p = insertPath.length - 1; p >= 0; p--)
1112: {
1113: Edit edit = insertPath[p];
1114: if (edit.e == fracturedParent)
1115: edit.added.add(fracturedChild);
1116: if ((edit.added.size() > 0 || edit.removed.size() > 0)
1117: && ! edits.contains(edit))
1118: edits.add(edit);
1119: }
1120:
1121:
1122:
1123: if (offset == 0 && fracturedParent != null
1124: && data[0].getType() == ElementSpec.EndTagType)
1125: {
1126: int p;
1127: for (p = 0;
1128: p < data.length && data[p].getType() == ElementSpec.EndTagType;
1129: p++)
1130: ;
1131:
1132: Edit edit = insertPath[insertPath.length - p - 1];
1133: edit.index--;
1134: edit.removed.add(0, edit.e.getElement(edit.index));
1135: }
1136: }
1137:
1138: private void pop()
1139: {
1140: Edit edit = (Edit) elementStack.peek();
1141: elementStack.pop();
1142: if ((edit.added.size() > 0) || (edit.removed.size() > 0))
1143: {
1144: edits.add(edit);
1145: }
1146: else if (! elementStack.isEmpty())
1147: {
1148: Element e = edit.e;
1149: if (e.getElementCount() == 0)
1150: {
1151:
1152:
1153: edit = (Edit) elementStack.peek();
1154: edit.added.remove(e);
1155: }
1156: }
1157: }
1158:
1159: private void insertElement(ElementSpec spec)
1160: {
1161: Edit edit = (Edit) elementStack.peek();
1162: switch (spec.getType())
1163: {
1164: case ElementSpec.StartTagType:
1165: switch (spec.getDirection())
1166: {
1167: case ElementSpec.JoinFractureDirection:
1168:
1169:
1170: if (! createdFracture)
1171: {
1172: fracture(elementStack.size() - 1);
1173: }
1174: if (! edit.isFracture)
1175: {
1176:
1177:
1178: Edit newEdit = new Edit(fracturedChild, 0, true);
1179: elementStack.push(newEdit);
1180: }
1181: else
1182: {
1183:
1184: Element el = edit.e.getElement(0);
1185: Edit newEdit = new Edit(el, 0, true);
1186: elementStack.push(newEdit);
1187: }
1188: break;
1189: case ElementSpec.JoinNextDirection:
1190:
1191:
1192: Element parent = edit.e.getElement(edit.index);
1193: if (parent.isLeaf())
1194: {
1195: if (edit.index + 1 < edit.e.getElementCount())
1196: parent = edit.e.getElement(edit.index + 1);
1197: else
1198: assert false;
1199: }
1200: elementStack.push(new Edit(parent, 0, true));
1201: break;
1202: default:
1203: Element branch = createBranchElement(edit.e,
1204: spec.getAttributes());
1205: edit.added.add(branch);
1206: elementStack.push(new Edit(branch, 0));
1207: break;
1208: }
1209: break;
1210: case ElementSpec.EndTagType:
1211: pop();
1212: break;
1213: case ElementSpec.ContentType:
1214: insertContentTag(spec, edit);
1215: break;
1216: }
1217: }
1218:
1219:
1225: private void insertFirstContentTag(ElementSpec[] data)
1226: {
1227: ElementSpec first = data[0];
1228: Edit edit = (Edit) elementStack.peek();
1229: Element current = edit.e.getElement(edit.index);
1230: int firstEndOffset = offset + first.length;
1231: boolean onlyContent = data.length == 1;
1232: switch (first.getDirection())
1233: {
1234: case ElementSpec.JoinPreviousDirection:
1235: if (current.getEndOffset() != firstEndOffset && ! onlyContent)
1236: {
1237: Element newEl1 = createLeafElement(edit.e,
1238: current.getAttributes(),
1239: current.getStartOffset(),
1240: firstEndOffset);
1241: edit.added.add(newEl1);
1242: edit.removed.add(current);
1243: if (current.getEndOffset() != endOffset)
1244: recreateLeafs = true;
1245: else
1246: offsetLastIndex = true;
1247: }
1248: else
1249: {
1250: offsetLastIndex = true;
1251: offsetLastIndexReplace = true;
1252: }
1253: break;
1254: case ElementSpec.JoinNextDirection:
1255: if (offset != 0)
1256: {
1257: Element newEl1 = createLeafElement(edit.e,
1258: current.getAttributes(),
1259: current.getStartOffset(),
1260: offset);
1261: edit.added.add(newEl1);
1262: Element next = edit.e.getElement(edit.index + 1);
1263: if (onlyContent)
1264: newEl1 = createLeafElement(edit.e, next.getAttributes(),
1265: offset, next.getEndOffset());
1266: else
1267: {
1268: newEl1 = createLeafElement(edit.e, next.getAttributes(),
1269: offset, firstEndOffset);
1270: }
1271: edit.added.add(newEl1);
1272: edit.removed.add(current);
1273: edit.removed.add(next);
1274: }
1275: break;
1276: default:
1277: if (current.getStartOffset() != offset)
1278: {
1279: Element newEl = createLeafElement(edit.e,
1280: current.getAttributes(),
1281: current.getStartOffset(),
1282: offset);
1283: edit.added.add(newEl);
1284: }
1285: edit.removed.add(current);
1286: Element newEl1 = createLeafElement(edit.e, first.getAttributes(),
1287: offset, firstEndOffset);
1288: edit.added.add(newEl1);
1289: if (current.getEndOffset() != endOffset)
1290: recreateLeafs = true;
1291: else
1292: offsetLastIndex = true;
1293: break;
1294: }
1295: }
1296:
1297:
1303: private void insertContentTag(ElementSpec tag, Edit edit)
1304: {
1305: int len = tag.getLength();
1306: int dir = tag.getDirection();
1307: if (dir == ElementSpec.JoinNextDirection)
1308: {
1309: if (! edit.isFracture)
1310: {
1311: Element first = null;
1312: if (insertPath != null)
1313: {
1314: for (int p = insertPath.length - 1; p >= 0; p--)
1315: {
1316: if (insertPath[p] == edit)
1317: {
1318: if (p != insertPath.length - 1)
1319: first = edit.e.getElement(edit.index);
1320: break;
1321: }
1322: }
1323: }
1324: if (first == null)
1325: first = edit.e.getElement(edit.index + 1);
1326: Element leaf = createLeafElement(edit.e, first.getAttributes(),
1327: pos, first.getEndOffset());
1328: edit.added.add(leaf);
1329: edit.removed.add(first);
1330: }
1331: else
1332: {
1333: Element first = edit.e.getElement(0);
1334: Element leaf = createLeafElement(edit.e, first.getAttributes(),
1335: pos, first.getEndOffset());
1336: edit.added.add(leaf);
1337: edit.removed.add(first);
1338: }
1339: }
1340: else
1341: {
1342: Element leaf = createLeafElement(edit.e, tag.getAttributes(), pos,
1343: pos + len);
1344: edit.added.add(leaf);
1345: }
1346:
1347: pos += len;
1348:
1349: }
1350:
1351:
1358: private void createFracture(ElementSpec[] data)
1359: {
1360: Edit edit = (Edit) elementStack.peek();
1361: Element child = edit.e.getElement(edit.index);
1362: if (offset != 0)
1363: {
1364: Element newChild = createLeafElement(edit.e, child.getAttributes(),
1365: child.getStartOffset(), offset);
1366: edit.added.add(newChild);
1367: }
1368: edit.removed.add(child);
1369: if (child.getEndOffset() != endOffset)
1370: recreateLeafs = true;
1371: else
1372: offsetLastIndex = true;
1373: }
1374:
1375: private void fracture(int depth)
1376: {
1377: int len = insertPath.length;
1378: int lastIndex = -1;
1379: boolean recreate = recreateLeafs;
1380: Edit lastEdit = insertPath[len - 1];
1381: boolean childChanged = lastEdit.index + 1 < lastEdit.e.getElementCount();
1382: int deepestChangedIndex = recreate ? len : - 1;
1383: int lastChangedIndex = len - 1;
1384: createdFracture = true;
1385: for (int i = len - 2; i >= 0; i--)
1386: {
1387: Edit edit = insertPath[i];
1388: if (edit.added.size() > 0 || i == depth)
1389: {
1390: lastIndex = i;
1391: if (! recreate && childChanged)
1392: {
1393: recreate = true;
1394: if (deepestChangedIndex == -1)
1395: deepestChangedIndex = lastChangedIndex + 1;
1396: }
1397: }
1398: if (! childChanged && edit.index < edit.e.getElementCount())
1399: {
1400: childChanged = true;
1401: lastChangedIndex = i;
1402: }
1403: }
1404: if (recreate)
1405: {
1406: if (lastIndex == -1)
1407: lastIndex = len - 1;
1408: recreate(lastIndex, deepestChangedIndex);
1409: }
1410: }
1411:
1412: private void recreate(int startIndex, int endIndex)
1413: {
1414:
1415: Edit edit = insertPath[startIndex];
1416: Element child;
1417: Element newChild;
1418: int changeLength = insertPath.length;
1419:
1420: if (startIndex + 1 == changeLength)
1421: child = edit.e.getElement(edit.index);
1422: else
1423: child = edit.e.getElement(edit.index - 1);
1424:
1425: if(child.isLeaf())
1426: {
1427: newChild = createLeafElement(edit.e, child.getAttributes(),
1428: Math.max(endOffset, child.getStartOffset()),
1429: child.getEndOffset());
1430: }
1431: else
1432: {
1433: newChild = createBranchElement(edit.e, child.getAttributes());
1434: }
1435: fracturedParent = edit.e;
1436: fracturedChild = newChild;
1437:
1438:
1439: Element parent = newChild;
1440: while (++startIndex < endIndex)
1441: {
1442: boolean isEnd = (startIndex + 1) == endIndex;
1443: boolean isEndLeaf = (startIndex + 1) == changeLength;
1444:
1445:
1446:
1447:
1448: edit = insertPath[startIndex];
1449:
1450:
1451:
1452: if(isEnd)
1453: {
1454: if(offsetLastIndex || ! isEndLeaf)
1455: child = null;
1456: else
1457: child = edit.e.getElement(edit.index);
1458: }
1459: else
1460: {
1461: child = edit.e.getElement(edit.index - 1);
1462: }
1463:
1464:
1465: if(child != null)
1466: {
1467: if(child.isLeaf())
1468: {
1469: newChild = createLeafElement(parent, child.getAttributes(),
1470: Math.max(endOffset, child.getStartOffset()),
1471: child.getEndOffset());
1472: }
1473: else
1474: {
1475: newChild = createBranchElement(parent,
1476: child.getAttributes());
1477: }
1478: }
1479: else
1480: newChild = null;
1481:
1482:
1483: int childrenToMove = edit.e.getElementCount() - edit.index;
1484: Element[] children;
1485: int moveStartIndex;
1486: int childStartIndex = 1;
1487:
1488: if (newChild == null)
1489: {
1490:
1491: if (isEndLeaf)
1492: {
1493: childrenToMove--;
1494: moveStartIndex = edit.index + 1;
1495: }
1496: else
1497: {
1498: moveStartIndex = edit.index;
1499: }
1500: childStartIndex = 0;
1501: children = new Element[childrenToMove];
1502: }
1503: else
1504: {
1505: if (! isEnd)
1506: {
1507:
1508: childrenToMove++;
1509: moveStartIndex = edit.index;
1510: }
1511: else
1512: {
1513:
1514: moveStartIndex = edit.index + 1;
1515: }
1516: children = new Element[childrenToMove];
1517: children[0] = newChild;
1518: }
1519:
1520: for (int c = childStartIndex; c < childrenToMove; c++)
1521: {
1522: Element toMove = edit.e.getElement(moveStartIndex++);
1523: children[c] = recreateFracturedElement(parent, toMove);
1524: edit.removed.add(toMove);
1525: }
1526: ((BranchElement) parent).replace(0, 0, children);
1527: parent = newChild;
1528: }
1529:
1530: }
1531:
1532: private Element recreateFracturedElement(Element parent, Element toCopy)
1533: {
1534: Element recreated;
1535: if(toCopy.isLeaf())
1536: {
1537: recreated = createLeafElement(parent, toCopy.getAttributes(),
1538: Math.max(toCopy.getStartOffset(), endOffset),
1539: toCopy.getEndOffset());
1540: }
1541: else
1542: {
1543: Element newParent = createBranchElement(parent,
1544: toCopy.getAttributes());
1545: int childCount = toCopy.getElementCount();
1546: Element[] newChildren = new Element[childCount];
1547: for (int i = 0; i < childCount; i++)
1548: {
1549: newChildren[i] = recreateFracturedElement(newParent,
1550: toCopy.getElement(i));
1551: }
1552: ((BranchElement) newParent).replace(0, 0, newChildren);
1553: recreated = newParent;
1554: }
1555: return recreated;
1556: }
1557:
1558: private boolean split(int offs, int len)
1559: {
1560: boolean splitEnd = false;
1561:
1562: Element e = root;
1563: int index = e.getElementIndex(offs);
1564: while (! e.isLeaf())
1565: {
1566: elementStack.push(new Edit(e, index));
1567: e = e.getElement(index);
1568: index = e.getElementIndex(offs);
1569: }
1570:
1571: Edit ec = (Edit) elementStack.peek();
1572: Element child = ec.e.getElement(ec.index);
1573:
1574:
1575:
1576: if (child.getStartOffset() < offs && offs < child.getEndOffset())
1577: {
1578:
1579:
1580: int index0 = ec.index;
1581: int index1 = index0;
1582: if (((offs + len) < ec.e.getEndOffset()) && (len != 0))
1583: {
1584:
1585: index1 = ec.e.getElementIndex(offs+len);
1586: if (index1 == index0)
1587: {
1588:
1589: ec.removed.add(child);
1590: e = createLeafElement(ec.e, child.getAttributes(),
1591: child.getStartOffset(), offs);
1592: ec.added.add(e);
1593: e = createLeafElement(ec.e, child.getAttributes(),
1594: offs, offs + len);
1595: ec.added.add(e);
1596: e = createLeafElement(ec.e, child.getAttributes(),
1597: offs + len, child.getEndOffset());
1598: ec.added.add(e);
1599: return true;
1600: }
1601: else
1602: {
1603: child = ec.e.getElement(index1);
1604: if ((offs + len) == child.getStartOffset())
1605: {
1606:
1607: index1 = index0;
1608: }
1609: }
1610: splitEnd = true;
1611: }
1612:
1613:
1614: pos = offs;
1615: child = ec.e.getElement(index0);
1616: ec.removed.add(child);
1617: e = createLeafElement(ec.e, child.getAttributes(),
1618: child.getStartOffset(), pos);
1619: ec.added.add(e);
1620: e = createLeafElement(ec.e, child.getAttributes(),
1621: pos, child.getEndOffset());
1622: ec.added.add(e);
1623:
1624:
1625: for (int i = index0 + 1; i < index1; i++)
1626: {
1627: child = ec.e.getElement(i);
1628: ec.removed.add(child);
1629: ec.added.add(child);
1630: }
1631:
1632: if (index1 != index0)
1633: {
1634: child = ec.e.getElement(index1);
1635: pos = offs + len;
1636: ec.removed.add(child);
1637: e = createLeafElement(ec.e, child.getAttributes(),
1638: child.getStartOffset(), pos);
1639: ec.added.add(e);
1640: e = createLeafElement(ec.e, child.getAttributes(),
1641: pos, child.getEndOffset());
1642:
1643: ec.added.add(e);
1644: }
1645: }
1646: return splitEnd;
1647:
1648: }
1649:
1650: }
1651:
1652:
1653:
1657: protected class SectionElement extends BranchElement
1658: {
1659:
1662: public SectionElement()
1663: {
1664: super(null, null);
1665: }
1666:
1667:
1673: public String getName()
1674: {
1675: return SectionElementName;
1676: }
1677: }
1678:
1679:
1685: private class StyleChangeListener implements ChangeListener
1686: {
1687:
1688:
1695: public void stateChanged(ChangeEvent event)
1696: {
1697: Style style = (Style) event.getSource();
1698: styleChanged(style);
1699: }
1700: }
1701:
1702:
1703: private static final long serialVersionUID = 940485415728614849L;
1704:
1705:
1708: public static final int BUFFER_SIZE_DEFAULT = 4096;
1709:
1710:
1714: protected DefaultStyledDocument.ElementBuffer buffer;
1715:
1716:
1719: private StyleChangeListener styleChangeListener;
1720:
1721:
1724: public DefaultStyledDocument()
1725: {
1726: this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext());
1727: }
1728:
1729:
1736: public DefaultStyledDocument(StyleContext context)
1737: {
1738: this(new GapContent(BUFFER_SIZE_DEFAULT), context);
1739: }
1740:
1741:
1750: public DefaultStyledDocument(AbstractDocument.Content content,
1751: StyleContext context)
1752: {
1753: super(content, context);
1754: buffer = new ElementBuffer(createDefaultRoot());
1755: setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE));
1756: }
1757:
1758:
1773: public Style addStyle(String nm, Style parent)
1774: {
1775: StyleContext context = (StyleContext) getAttributeContext();
1776: Style newStyle = context.addStyle(nm, parent);
1777:
1778:
1779: if (styleChangeListener == null)
1780: styleChangeListener = new StyleChangeListener();
1781: newStyle.addChangeListener(styleChangeListener);
1782:
1783: return newStyle;
1784: }
1785:
1786:
1791: protected AbstractDocument.AbstractElement createDefaultRoot()
1792: {
1793: Element[] tmp;
1794: SectionElement section = new SectionElement();
1795:
1796: BranchElement paragraph = new BranchElement(section, null);
1797: tmp = new Element[1];
1798: tmp[0] = paragraph;
1799: section.replace(0, 0, tmp);
1800:
1801: Element leaf = new LeafElement(paragraph, null, 0, 1);
1802: tmp = new Element[1];
1803: tmp[0] = leaf;
1804: paragraph.replace(0, 0, tmp);
1805:
1806: return section;
1807: }
1808:
1809:
1819: public Element getCharacterElement(int position)
1820: {
1821: Element element = getDefaultRootElement();
1822:
1823: while (!element.isLeaf())
1824: {
1825: int index = element.getElementIndex(position);
1826: element = element.getElement(index);
1827: }
1828:
1829: return element;
1830: }
1831:
1832:
1839: public Color getBackground(AttributeSet attributes)
1840: {
1841: StyleContext context = (StyleContext) getAttributeContext();
1842: return context.getBackground(attributes);
1843: }
1844:
1845:
1850: public Element getDefaultRootElement()
1851: {
1852: return buffer.getRootElement();
1853: }
1854:
1855:
1862: public Font getFont(AttributeSet attributes)
1863: {
1864: StyleContext context = (StyleContext) getAttributeContext();
1865: return context.getFont(attributes);
1866: }
1867:
1868:
1875: public Color getForeground(AttributeSet attributes)
1876: {
1877: StyleContext context = (StyleContext) getAttributeContext();
1878: return context.getForeground(attributes);
1879: }
1880:
1881:
1888: public Style getLogicalStyle(int position)
1889: {
1890: Element paragraph = getParagraphElement(position);
1891: AttributeSet attributes = paragraph.getAttributes();
1892: AttributeSet a = attributes.getResolveParent();
1893:
1894: if (a instanceof Style)
1895: return (Style) a;
1896: return null;
1897: }
1898:
1899:
1910: public Element getParagraphElement(int position)
1911: {
1912: Element e = getDefaultRootElement();
1913: while (!e.isLeaf())
1914: e = e.getElement(e.getElementIndex(position));
1915:
1916: if (e != null)
1917: return e.getParentElement();
1918: return e;
1919: }
1920:
1921:
1929: public Style getStyle(String nm)
1930: {
1931: StyleContext context = (StyleContext) getAttributeContext();
1932: return context.getStyle(nm);
1933: }
1934:
1935:
1941: public void removeStyle(String nm)
1942: {
1943: StyleContext context = (StyleContext) getAttributeContext();
1944: context.removeStyle(nm);
1945: }
1946:
1947:
1961: public void setCharacterAttributes(int offset, int length,
1962: AttributeSet attributes, boolean replace)
1963: {
1964:
1965: if (length == 0)
1966: return;
1967: try
1968: {
1969:
1970:
1971:
1972: writeLock();
1973: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
1974: length,
1975: DocumentEvent.EventType.CHANGE);
1976:
1977:
1978:
1979:
1980: buffer.change(offset, length, ev);
1981:
1982:
1983: int end = offset + length;
1984: Element curr;
1985: for (int pos = offset; pos < end;)
1986: {
1987:
1988: curr = getCharacterElement(pos);
1989: if (pos == curr.getEndOffset())
1990: break;
1991:
1992: MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();
1993: ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));
1994:
1995: if (replace)
1996: a.removeAttributes(a);
1997:
1998: a.addAttributes(attributes);
1999:
2000: pos = curr.getEndOffset();
2001: }
2002: fireChangedUpdate(ev);
2003: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2004: }
2005: finally
2006: {
2007: writeUnlock();
2008: }
2009: }
2010:
2011:
2019: public void setLogicalStyle(int position, Style style)
2020: {
2021: Element el = getParagraphElement(position);
2022:
2023:
2024: if (el == null)
2025: return;
2026: try
2027: {
2028: writeLock();
2029: if (el instanceof AbstractElement)
2030: {
2031: AbstractElement ael = (AbstractElement) el;
2032: ael.setResolveParent(style);
2033: int start = el.getStartOffset();
2034: int end = el.getEndOffset();
2035: DefaultDocumentEvent ev = new DefaultDocumentEvent(start,
2036: end - start,
2037: DocumentEvent.EventType.CHANGE);
2038: fireChangedUpdate(ev);
2039: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2040: }
2041: else
2042: throw new AssertionError(
2043: "paragraph elements are expected to be"
2044: + "instances of AbstractDocument.AbstractElement");
2045: }
2046: finally
2047: {
2048: writeUnlock();
2049: }
2050: }
2051:
2052:
2065: public void setParagraphAttributes(int offset, int length,
2066: AttributeSet attributes, boolean replace)
2067: {
2068: try
2069: {
2070:
2071:
2072:
2073: writeLock();
2074:
2075:
2076: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2077: length,
2078: DocumentEvent.EventType.CHANGE);
2079:
2080:
2081:
2082:
2083: Element rootElement = getDefaultRootElement();
2084: int startElement = rootElement.getElementIndex(offset);
2085: int endElement = rootElement.getElementIndex(offset + length - 1);
2086: if (endElement < startElement)
2087: endElement = startElement;
2088:
2089: for (int i = startElement; i <= endElement; i++)
2090: {
2091: Element par = rootElement.getElement(i);
2092: MutableAttributeSet a = (MutableAttributeSet) par.getAttributes();
2093:
2094: ev.addEdit(new AttributeUndoableEdit(par, attributes, replace));
2095:
2096: if (replace)
2097: a.removeAttributes(a);
2098:
2099: a.addAttributes(attributes);
2100: }
2101: fireChangedUpdate(ev);
2102: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2103: }
2104: finally
2105: {
2106: writeUnlock();
2107: }
2108: }
2109:
2110:
2119: protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
2120: {
2121: int offs = ev.getOffset();
2122: int len = ev.getLength();
2123: int endOffs = offs + len;
2124: if (attr == null)
2125: attr = SimpleAttributeSet.EMPTY;
2126:
2127:
2128: Element paragraph = getParagraphElement(endOffs);
2129: AttributeSet pAttr = paragraph.getAttributes();
2130:
2131: Element paragraph2 = getParagraphElement(offs);
2132: int contIndex = paragraph2.getElementIndex(offs);
2133: Element content = paragraph2.getElement(contIndex);
2134: AttributeSet cAttr = content.getAttributes();
2135:
2136: boolean insertAtBoundary = content.getEndOffset() == endOffs;
2137: try
2138: {
2139: Segment s = new Segment();
2140: ArrayList buf = new ArrayList();
2141: ElementSpec lastStartTag = null;
2142: boolean insertAfterNewline = false;
2143: short lastStartDir = ElementSpec.OriginateDirection;
2144:
2145:
2146: if (offs > 0)
2147: {
2148: getText(offs - 1, 1, s);
2149: if (s.array[s.offset] == '\n')
2150: {
2151: insertAfterNewline = true;
2152: lastStartDir = insertAfterNewline(paragraph, paragraph2,
2153: pAttr, buf, offs,
2154: endOffs);
2155:
2156: for (int i = buf.size() - 1; i >= 0 && lastStartTag == null;
2157: i--)
2158: {
2159: ElementSpec tag = (ElementSpec) buf.get(i);
2160: if (tag.getType() == ElementSpec.StartTagType)
2161: {
2162: lastStartTag = tag;
2163: }
2164: }
2165: }
2166:
2167: }
2168:
2169:
2170:
2171: if (! insertAfterNewline)
2172: pAttr = paragraph2.getAttributes();
2173:
2174:
2175: getText(offs, len, s);
2176: int end = s.offset + s.count;
2177: int last = s.offset;
2178: for (int i = s.offset; i < end; i++)
2179: {
2180: if (s.array[i] == '\n')
2181: {
2182: int breakOffs = i + 1;
2183: buf.add(new ElementSpec(attr, ElementSpec.ContentType,
2184: breakOffs - last));
2185: buf.add(new ElementSpec(null, ElementSpec.EndTagType));
2186: lastStartTag = new ElementSpec(pAttr,
2187: ElementSpec.StartTagType);
2188: buf.add(lastStartTag);
2189: last = breakOffs;
2190: }
2191: }
2192:
2193:
2194: if (last < end)
2195: {
2196: buf.add(new ElementSpec(attr, ElementSpec.ContentType,
2197: end - last));
2198: }
2199:
2200:
2201: ElementSpec first = (ElementSpec) buf.get(0);
2202: int doclen = getLength();
2203:
2204:
2205:
2206: if (first.getType() == ElementSpec.ContentType && cAttr.isEqual(attr))
2207: first.setDirection(ElementSpec.JoinPreviousDirection);
2208:
2209:
2210: if (lastStartTag != null)
2211: {
2212: if (insertAfterNewline)
2213: lastStartTag.setDirection(lastStartDir);
2214: else if (paragraph2.getEndOffset() != endOffs)
2215: lastStartTag.setDirection(ElementSpec.JoinFractureDirection);
2216: else
2217: {
2218: Element par = paragraph2.getParentElement();
2219: int par2Index = par.getElementIndex(offs);
2220: if (par2Index + 1 < par.getElementCount()
2221: && ! par.getElement(par2Index + 1).isLeaf())
2222: lastStartTag.setDirection(ElementSpec.JoinNextDirection);
2223: }
2224: }
2225:
2226:
2227: if (insertAtBoundary && endOffs < doclen)
2228: {
2229: ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
2230: if (lastTag.getType() == ElementSpec.ContentType
2231: && ((lastStartTag == null
2232: && (paragraph == paragraph2 || insertAfterNewline))
2233: || (lastStartTag != null
2234: && lastStartTag.getDirection() != ElementSpec.OriginateDirection)))
2235: {
2236: int nextIndex = paragraph.getElementIndex(endOffs);
2237: Element nextRun = paragraph.getElement(nextIndex);
2238: if (nextRun.isLeaf() && attr.isEqual(nextRun.getAttributes()))
2239: lastTag.setDirection(ElementSpec.JoinNextDirection);
2240: }
2241: }
2242:
2243: else if (! insertAtBoundary && lastStartTag != null
2244: && lastStartTag.getDirection() == ElementSpec.JoinFractureDirection)
2245: {
2246: ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
2247: if (lastTag.getType() == ElementSpec.ContentType
2248: && lastTag.getDirection() != ElementSpec.JoinPreviousDirection
2249: && attr.isEqual(cAttr))
2250: {
2251: lastTag.setDirection(ElementSpec.JoinNextDirection);
2252: }
2253: }
2254:
2255: ElementSpec[] specs = new ElementSpec[buf.size()];
2256: specs = (ElementSpec[]) buf.toArray(specs);
2257: buffer.insert(offs, len, specs, ev);
2258: }
2259: catch (BadLocationException ex)
2260: {
2261:
2262: ex.printStackTrace();
2263: }
2264: super.insertUpdate(ev, attr);
2265: }
2266:
2267: private short insertAfterNewline(Element par1, Element par2,
2268: AttributeSet attr, ArrayList buf,
2269: int offs, int endOffs)
2270: {
2271: short dir = 0;
2272: if (par1.getParentElement() == par2.getParentElement())
2273: {
2274: ElementSpec tag = new ElementSpec(attr, ElementSpec.EndTagType);
2275: buf.add(tag);
2276: tag = new ElementSpec(attr, ElementSpec.StartTagType);
2277: buf.add(tag);
2278: if (par2.getEndOffset() != endOffs)
2279: dir = ElementSpec.JoinFractureDirection;
2280: else
2281: {
2282: Element par = par2.getParentElement();
2283: if (par.getElementIndex(offs) + 1 < par.getElementCount())
2284: dir = ElementSpec.JoinNextDirection;
2285: }
2286: }
2287: else
2288: {
2289:
2290:
2291: ArrayList parentsLeft = new ArrayList();
2292: ArrayList parentsRight = new ArrayList();
2293: Element e = par2;
2294: while (e != null)
2295: {
2296: parentsLeft.add(e);
2297: e = e.getParentElement();
2298: }
2299: e = par1;
2300: int leftIndex = -1;
2301: while (e != null && (leftIndex = parentsLeft.indexOf(e)) == 1)
2302: {
2303: parentsRight.add(e);
2304: e = e.getParentElement();
2305: }
2306:
2307: if (e != null)
2308:
2309: {
2310:
2311:
2312: for (int c = 0; c < leftIndex; c++)
2313: {
2314: buf.add(new ElementSpec(null, ElementSpec.EndTagType));
2315: }
2316:
2317: for (int c = parentsRight.size() - 1; c >= 0; c--)
2318: {
2319: Element el = (Element) parentsRight.get(c);
2320: ElementSpec tag = new ElementSpec(el.getAttributes(),
2321: ElementSpec.StartTagType);
2322: if (c > 0)
2323: tag.setDirection(ElementSpec.JoinNextDirection);
2324: buf.add(tag);
2325: }
2326: if (parentsRight.size() > 0)
2327: dir = ElementSpec.JoinNextDirection;
2328: else
2329: dir = ElementSpec.JoinFractureDirection;
2330: }
2331: else
2332: assert false;
2333: }
2334: return dir;
2335: }
2336:
2337:
2344: short handleInsertAfterNewline(Vector specs, int offset, int endOffset,
2345: Element prevParagraph, Element paragraph,
2346: AttributeSet a)
2347: {
2348: if (prevParagraph.getParentElement() == paragraph.getParentElement())
2349: {
2350: specs.add(new ElementSpec(a, ElementSpec.EndTagType));
2351: specs.add(new ElementSpec(a, ElementSpec.StartTagType));
2352: if (paragraph.getStartOffset() != endOffset)
2353: return ElementSpec.JoinFractureDirection;
2354:
2355: Element parent = paragraph.getParentElement();
2356: if (parent.getElementCount() > (parent.getElementIndex(offset) + 1))
2357: return ElementSpec.JoinNextDirection;
2358: }
2359: return ElementSpec.OriginateDirection;
2360: }
2361:
2362:
2371: protected void removeUpdate(DefaultDocumentEvent ev)
2372: {
2373: super.removeUpdate(ev);
2374: buffer.remove(ev.getOffset(), ev.getLength(), ev);
2375: }
2376:
2377:
2382: public Enumeration<?> getStyleNames()
2383: {
2384: StyleContext context = (StyleContext) getAttributeContext();
2385: return context.getStyleNames();
2386: }
2387:
2388:
2394: protected void styleChanged(Style style)
2395: {
2396:
2397: }
2398:
2399:
2407: protected void insert(int offset, ElementSpec[] data)
2408: throws BadLocationException
2409: {
2410: if (data == null || data.length == 0)
2411: return;
2412: try
2413: {
2414:
2415:
2416:
2417: writeLock();
2418:
2419:
2420: StringBuffer contentBuffer = new StringBuffer();
2421: for (int i = 0; i < data.length; i++)
2422: {
2423:
2424:
2425: ElementSpec spec = data[i];
2426: if (spec.getArray() != null && spec.getLength() > 0)
2427: contentBuffer.append(spec.getArray(), spec.getOffset(),
2428: spec.getLength());
2429: }
2430:
2431: int length = contentBuffer.length();
2432:
2433:
2434: if (length == 0)
2435: return;
2436:
2437: Content c = getContent();
2438: UndoableEdit edit = c.insertString(offset,
2439: contentBuffer.toString());
2440:
2441:
2442: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2443: length,
2444: DocumentEvent.EventType.INSERT);
2445:
2446: ev.addEdit(edit);
2447:
2448:
2449:
2450: buffer.insert(offset, length, data, ev);
2451:
2452: super.insertUpdate(ev, null);
2453:
2454: ev.end();
2455: fireInsertUpdate(ev);
2456: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2457: }
2458: finally
2459: {
2460: writeUnlock();
2461: }
2462: }
2463:
2464:
2472: protected void create(ElementSpec[] data)
2473: {
2474: try
2475: {
2476:
2477:
2478: int len = getLength();
2479: if (len > 0)
2480: remove(0, len);
2481:
2482: writeLock();
2483:
2484:
2485: StringBuilder b = new StringBuilder();
2486: for (int i = 0; i < data.length; ++i)
2487: {
2488: ElementSpec el = data[i];
2489: if (el.getArray() != null && el.getLength() > 0)
2490: b.append(el.getArray(), el.getOffset(), el.getLength());
2491: }
2492: Content content = getContent();
2493: UndoableEdit cEdit = content.insertString(0, b.toString());
2494:
2495: len = b.length();
2496: DefaultDocumentEvent ev =
2497: new DefaultDocumentEvent(0, b.length(),
2498: DocumentEvent.EventType.INSERT);
2499: ev.addEdit(cEdit);
2500:
2501: buffer.create(len, data, ev);
2502:
2503:
2504: super.insertUpdate(ev, null);
2505:
2506: ev.end();
2507: fireInsertUpdate(ev);
2508: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2509: }
2510: catch (BadLocationException ex)
2511: {
2512: AssertionError err = new AssertionError("Unexpected bad location");
2513: err.initCause(ex);
2514: throw err;
2515: }
2516: finally
2517: {
2518: writeUnlock();
2519: }
2520: }
2521: }