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: if (elementStack.isEmpty())
1162: return;
1163:
1164: Edit edit = (Edit) elementStack.peek();
1165: switch (spec.getType())
1166: {
1167: case ElementSpec.StartTagType:
1168: switch (spec.getDirection())
1169: {
1170: case ElementSpec.JoinFractureDirection:
1171:
1172:
1173: if (! createdFracture)
1174: {
1175: fracture(elementStack.size() - 1);
1176: }
1177: if (! edit.isFracture)
1178: {
1179:
1180:
1181: Edit newEdit = new Edit(fracturedChild, 0, true);
1182: elementStack.push(newEdit);
1183: }
1184: else
1185: {
1186:
1187: Element el = edit.e.getElement(0);
1188: Edit newEdit = new Edit(el, 0, true);
1189: elementStack.push(newEdit);
1190: }
1191: break;
1192: case ElementSpec.JoinNextDirection:
1193:
1194:
1195: Element parent = edit.e.getElement(edit.index);
1196: if (parent.isLeaf())
1197: {
1198: if (edit.index + 1 < edit.e.getElementCount())
1199: parent = edit.e.getElement(edit.index + 1);
1200: else
1201: assert false;
1202: }
1203: elementStack.push(new Edit(parent, 0, true));
1204: break;
1205: default:
1206: Element branch = createBranchElement(edit.e,
1207: spec.getAttributes());
1208: edit.added.add(branch);
1209: elementStack.push(new Edit(branch, 0));
1210: break;
1211: }
1212: break;
1213: case ElementSpec.EndTagType:
1214: pop();
1215: break;
1216: case ElementSpec.ContentType:
1217: insertContentTag(spec, edit);
1218: break;
1219: }
1220: }
1221:
1222:
1228: private void insertFirstContentTag(ElementSpec[] data)
1229: {
1230: ElementSpec first = data[0];
1231: Edit edit = (Edit) elementStack.peek();
1232: Element current = edit.e.getElement(edit.index);
1233: int firstEndOffset = offset + first.length;
1234: boolean onlyContent = data.length == 1;
1235: switch (first.getDirection())
1236: {
1237: case ElementSpec.JoinPreviousDirection:
1238: if (current.getEndOffset() != firstEndOffset && ! onlyContent)
1239: {
1240: Element newEl1 = createLeafElement(edit.e,
1241: current.getAttributes(),
1242: current.getStartOffset(),
1243: firstEndOffset);
1244: edit.added.add(newEl1);
1245: edit.removed.add(current);
1246: if (current.getEndOffset() != endOffset)
1247: recreateLeafs = true;
1248: else
1249: offsetLastIndex = true;
1250: }
1251: else
1252: {
1253: offsetLastIndex = true;
1254: offsetLastIndexReplace = true;
1255: }
1256: break;
1257: case ElementSpec.JoinNextDirection:
1258: if (offset != 0)
1259: {
1260: Element newEl1 = createLeafElement(edit.e,
1261: current.getAttributes(),
1262: current.getStartOffset(),
1263: offset);
1264: edit.added.add(newEl1);
1265: Element next = edit.e.getElement(edit.index + 1);
1266: if (onlyContent)
1267: newEl1 = createLeafElement(edit.e, next.getAttributes(),
1268: offset, next.getEndOffset());
1269: else
1270: {
1271: newEl1 = createLeafElement(edit.e, next.getAttributes(),
1272: offset, firstEndOffset);
1273: }
1274: edit.added.add(newEl1);
1275: edit.removed.add(current);
1276: edit.removed.add(next);
1277: }
1278: break;
1279: default:
1280: if (current.getStartOffset() != offset)
1281: {
1282: Element newEl = createLeafElement(edit.e,
1283: current.getAttributes(),
1284: current.getStartOffset(),
1285: offset);
1286: edit.added.add(newEl);
1287: }
1288: edit.removed.add(current);
1289: Element newEl1 = createLeafElement(edit.e, first.getAttributes(),
1290: offset, firstEndOffset);
1291: edit.added.add(newEl1);
1292: if (current.getEndOffset() != endOffset)
1293: recreateLeafs = true;
1294: else
1295: offsetLastIndex = true;
1296: break;
1297: }
1298: }
1299:
1300:
1306: private void insertContentTag(ElementSpec tag, Edit edit)
1307: {
1308: int len = tag.getLength();
1309: int dir = tag.getDirection();
1310: if (dir == ElementSpec.JoinNextDirection)
1311: {
1312: if (! edit.isFracture)
1313: {
1314: Element first = null;
1315: if (insertPath != null)
1316: {
1317: for (int p = insertPath.length - 1; p >= 0; p--)
1318: {
1319: if (insertPath[p] == edit)
1320: {
1321: if (p != insertPath.length - 1)
1322: first = edit.e.getElement(edit.index);
1323: break;
1324: }
1325: }
1326: }
1327: if (first == null)
1328: first = edit.e.getElement(edit.index + 1);
1329: Element leaf = createLeafElement(edit.e, first.getAttributes(),
1330: pos, first.getEndOffset());
1331: edit.added.add(leaf);
1332: edit.removed.add(first);
1333: }
1334: else
1335: {
1336: Element first = edit.e.getElement(0);
1337: Element leaf = createLeafElement(edit.e, first.getAttributes(),
1338: pos, first.getEndOffset());
1339: edit.added.add(leaf);
1340: edit.removed.add(first);
1341: }
1342: }
1343: else
1344: {
1345: Element leaf = createLeafElement(edit.e, tag.getAttributes(), pos,
1346: pos + len);
1347: edit.added.add(leaf);
1348: }
1349:
1350: pos += len;
1351:
1352: }
1353:
1354:
1361: private void createFracture(ElementSpec[] data)
1362: {
1363: Edit edit = (Edit) elementStack.peek();
1364: Element child = edit.e.getElement(edit.index);
1365: if (offset != 0)
1366: {
1367: Element newChild = createLeafElement(edit.e, child.getAttributes(),
1368: child.getStartOffset(), offset);
1369: edit.added.add(newChild);
1370: }
1371: edit.removed.add(child);
1372: if (child.getEndOffset() != endOffset)
1373: recreateLeafs = true;
1374: else
1375: offsetLastIndex = true;
1376: }
1377:
1378: private void fracture(int depth)
1379: {
1380: int len = insertPath.length;
1381: int lastIndex = -1;
1382: boolean recreate = recreateLeafs;
1383: Edit lastEdit = insertPath[len - 1];
1384: boolean childChanged = lastEdit.index + 1 < lastEdit.e.getElementCount();
1385: int deepestChangedIndex = recreate ? len : - 1;
1386: int lastChangedIndex = len - 1;
1387: createdFracture = true;
1388: for (int i = len - 2; i >= 0; i--)
1389: {
1390: Edit edit = insertPath[i];
1391: if (edit.added.size() > 0 || i == depth)
1392: {
1393: lastIndex = i;
1394: if (! recreate && childChanged)
1395: {
1396: recreate = true;
1397: if (deepestChangedIndex == -1)
1398: deepestChangedIndex = lastChangedIndex + 1;
1399: }
1400: }
1401: if (! childChanged && edit.index < edit.e.getElementCount())
1402: {
1403: childChanged = true;
1404: lastChangedIndex = i;
1405: }
1406: }
1407: if (recreate)
1408: {
1409: if (lastIndex == -1)
1410: lastIndex = len - 1;
1411: recreate(lastIndex, deepestChangedIndex);
1412: }
1413: }
1414:
1415: private void recreate(int startIndex, int endIndex)
1416: {
1417:
1418: Edit edit = insertPath[startIndex];
1419: Element child;
1420: Element newChild;
1421: int changeLength = insertPath.length;
1422:
1423: if (startIndex + 1 == changeLength)
1424: child = edit.e.getElement(edit.index);
1425: else
1426: child = edit.e.getElement(edit.index - 1);
1427:
1428: if(child.isLeaf())
1429: {
1430: newChild = createLeafElement(edit.e, child.getAttributes(),
1431: Math.max(endOffset, child.getStartOffset()),
1432: child.getEndOffset());
1433: }
1434: else
1435: {
1436: newChild = createBranchElement(edit.e, child.getAttributes());
1437: }
1438: fracturedParent = edit.e;
1439: fracturedChild = newChild;
1440:
1441:
1442: Element parent = newChild;
1443: while (++startIndex < endIndex)
1444: {
1445: boolean isEnd = (startIndex + 1) == endIndex;
1446: boolean isEndLeaf = (startIndex + 1) == changeLength;
1447:
1448:
1449:
1450:
1451: edit = insertPath[startIndex];
1452:
1453:
1454:
1455: if(isEnd)
1456: {
1457: if(offsetLastIndex || ! isEndLeaf)
1458: child = null;
1459: else
1460: child = edit.e.getElement(edit.index);
1461: }
1462: else
1463: {
1464: child = edit.e.getElement(edit.index - 1);
1465: }
1466:
1467:
1468: if(child != null)
1469: {
1470: if(child.isLeaf())
1471: {
1472: newChild = createLeafElement(parent, child.getAttributes(),
1473: Math.max(endOffset, child.getStartOffset()),
1474: child.getEndOffset());
1475: }
1476: else
1477: {
1478: newChild = createBranchElement(parent,
1479: child.getAttributes());
1480: }
1481: }
1482: else
1483: newChild = null;
1484:
1485:
1486: int childrenToMove = edit.e.getElementCount() - edit.index;
1487: Element[] children;
1488: int moveStartIndex;
1489: int childStartIndex = 1;
1490:
1491: if (newChild == null)
1492: {
1493:
1494: if (isEndLeaf)
1495: {
1496: childrenToMove--;
1497: moveStartIndex = edit.index + 1;
1498: }
1499: else
1500: {
1501: moveStartIndex = edit.index;
1502: }
1503: childStartIndex = 0;
1504: children = new Element[childrenToMove];
1505: }
1506: else
1507: {
1508: if (! isEnd)
1509: {
1510:
1511: childrenToMove++;
1512: moveStartIndex = edit.index;
1513: }
1514: else
1515: {
1516:
1517: moveStartIndex = edit.index + 1;
1518: }
1519: children = new Element[childrenToMove];
1520: children[0] = newChild;
1521: }
1522:
1523: for (int c = childStartIndex; c < childrenToMove; c++)
1524: {
1525: Element toMove = edit.e.getElement(moveStartIndex++);
1526: children[c] = recreateFracturedElement(parent, toMove);
1527: edit.removed.add(toMove);
1528: }
1529: ((BranchElement) parent).replace(0, 0, children);
1530: parent = newChild;
1531: }
1532:
1533: }
1534:
1535: private Element recreateFracturedElement(Element parent, Element toCopy)
1536: {
1537: Element recreated;
1538: if(toCopy.isLeaf())
1539: {
1540: recreated = createLeafElement(parent, toCopy.getAttributes(),
1541: Math.max(toCopy.getStartOffset(), endOffset),
1542: toCopy.getEndOffset());
1543: }
1544: else
1545: {
1546: Element newParent = createBranchElement(parent,
1547: toCopy.getAttributes());
1548: int childCount = toCopy.getElementCount();
1549: Element[] newChildren = new Element[childCount];
1550: for (int i = 0; i < childCount; i++)
1551: {
1552: newChildren[i] = recreateFracturedElement(newParent,
1553: toCopy.getElement(i));
1554: }
1555: ((BranchElement) newParent).replace(0, 0, newChildren);
1556: recreated = newParent;
1557: }
1558: return recreated;
1559: }
1560:
1561: private boolean split(int offs, int len)
1562: {
1563: boolean splitEnd = false;
1564:
1565: Element e = root;
1566: int index = e.getElementIndex(offs);
1567: while (! e.isLeaf())
1568: {
1569: elementStack.push(new Edit(e, index));
1570: e = e.getElement(index);
1571: index = e.getElementIndex(offs);
1572: }
1573:
1574: Edit ec = (Edit) elementStack.peek();
1575: Element child = ec.e.getElement(ec.index);
1576:
1577:
1578:
1579: if (child.getStartOffset() < offs && offs < child.getEndOffset())
1580: {
1581:
1582:
1583: int index0 = ec.index;
1584: int index1 = index0;
1585: if (((offs + len) < ec.e.getEndOffset()) && (len != 0))
1586: {
1587:
1588: index1 = ec.e.getElementIndex(offs+len);
1589: if (index1 == index0)
1590: {
1591:
1592: ec.removed.add(child);
1593: e = createLeafElement(ec.e, child.getAttributes(),
1594: child.getStartOffset(), offs);
1595: ec.added.add(e);
1596: e = createLeafElement(ec.e, child.getAttributes(),
1597: offs, offs + len);
1598: ec.added.add(e);
1599: e = createLeafElement(ec.e, child.getAttributes(),
1600: offs + len, child.getEndOffset());
1601: ec.added.add(e);
1602: return true;
1603: }
1604: else
1605: {
1606: child = ec.e.getElement(index1);
1607: if ((offs + len) == child.getStartOffset())
1608: {
1609:
1610: index1 = index0;
1611: }
1612: }
1613: splitEnd = true;
1614: }
1615:
1616:
1617: pos = offs;
1618: child = ec.e.getElement(index0);
1619: ec.removed.add(child);
1620: e = createLeafElement(ec.e, child.getAttributes(),
1621: child.getStartOffset(), pos);
1622: ec.added.add(e);
1623: e = createLeafElement(ec.e, child.getAttributes(),
1624: pos, child.getEndOffset());
1625: ec.added.add(e);
1626:
1627:
1628: for (int i = index0 + 1; i < index1; i++)
1629: {
1630: child = ec.e.getElement(i);
1631: ec.removed.add(child);
1632: ec.added.add(child);
1633: }
1634:
1635: if (index1 != index0)
1636: {
1637: child = ec.e.getElement(index1);
1638: pos = offs + len;
1639: ec.removed.add(child);
1640: e = createLeafElement(ec.e, child.getAttributes(),
1641: child.getStartOffset(), pos);
1642: ec.added.add(e);
1643: e = createLeafElement(ec.e, child.getAttributes(),
1644: pos, child.getEndOffset());
1645:
1646: ec.added.add(e);
1647: }
1648: }
1649: return splitEnd;
1650:
1651: }
1652:
1653: }
1654:
1655:
1656:
1660: protected class SectionElement extends BranchElement
1661: {
1662:
1665: public SectionElement()
1666: {
1667: super(null, null);
1668: }
1669:
1670:
1676: public String getName()
1677: {
1678: return SectionElementName;
1679: }
1680: }
1681:
1682:
1688: private class StyleChangeListener implements ChangeListener
1689: {
1690:
1691:
1698: public void stateChanged(ChangeEvent event)
1699: {
1700: Style style = (Style) event.getSource();
1701: styleChanged(style);
1702: }
1703: }
1704:
1705:
1706: private static final long serialVersionUID = 940485415728614849L;
1707:
1708:
1711: public static final int BUFFER_SIZE_DEFAULT = 4096;
1712:
1713:
1717: protected DefaultStyledDocument.ElementBuffer buffer;
1718:
1719:
1722: private StyleChangeListener styleChangeListener;
1723:
1724:
1727: public DefaultStyledDocument()
1728: {
1729: this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext());
1730: }
1731:
1732:
1739: public DefaultStyledDocument(StyleContext context)
1740: {
1741: this(new GapContent(BUFFER_SIZE_DEFAULT), context);
1742: }
1743:
1744:
1753: public DefaultStyledDocument(AbstractDocument.Content content,
1754: StyleContext context)
1755: {
1756: super(content, context);
1757: buffer = new ElementBuffer(createDefaultRoot());
1758: setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE));
1759: }
1760:
1761:
1776: public Style addStyle(String nm, Style parent)
1777: {
1778: StyleContext context = (StyleContext) getAttributeContext();
1779: Style newStyle = context.addStyle(nm, parent);
1780:
1781:
1782: if (styleChangeListener == null)
1783: styleChangeListener = new StyleChangeListener();
1784: newStyle.addChangeListener(styleChangeListener);
1785:
1786: return newStyle;
1787: }
1788:
1789:
1794: protected AbstractDocument.AbstractElement createDefaultRoot()
1795: {
1796: Element[] tmp;
1797: SectionElement section = new SectionElement();
1798:
1799: BranchElement paragraph = new BranchElement(section, null);
1800: tmp = new Element[1];
1801: tmp[0] = paragraph;
1802: section.replace(0, 0, tmp);
1803:
1804: Element leaf = new LeafElement(paragraph, null, 0, 1);
1805: tmp = new Element[1];
1806: tmp[0] = leaf;
1807: paragraph.replace(0, 0, tmp);
1808:
1809: return section;
1810: }
1811:
1812:
1822: public Element getCharacterElement(int position)
1823: {
1824: Element element = getDefaultRootElement();
1825:
1826: while (!element.isLeaf())
1827: {
1828: int index = element.getElementIndex(position);
1829: element = element.getElement(index);
1830: }
1831:
1832: return element;
1833: }
1834:
1835:
1842: public Color getBackground(AttributeSet attributes)
1843: {
1844: StyleContext context = (StyleContext) getAttributeContext();
1845: return context.getBackground(attributes);
1846: }
1847:
1848:
1853: public Element getDefaultRootElement()
1854: {
1855: return buffer.getRootElement();
1856: }
1857:
1858:
1865: public Font getFont(AttributeSet attributes)
1866: {
1867: StyleContext context = (StyleContext) getAttributeContext();
1868: return context.getFont(attributes);
1869: }
1870:
1871:
1878: public Color getForeground(AttributeSet attributes)
1879: {
1880: StyleContext context = (StyleContext) getAttributeContext();
1881: return context.getForeground(attributes);
1882: }
1883:
1884:
1891: public Style getLogicalStyle(int position)
1892: {
1893: Element paragraph = getParagraphElement(position);
1894: AttributeSet attributes = paragraph.getAttributes();
1895: AttributeSet a = attributes.getResolveParent();
1896:
1897: if (a instanceof Style)
1898: return (Style) a;
1899: return null;
1900: }
1901:
1902:
1913: public Element getParagraphElement(int position)
1914: {
1915: Element e = getDefaultRootElement();
1916: while (!e.isLeaf())
1917: e = e.getElement(e.getElementIndex(position));
1918:
1919: if (e != null)
1920: return e.getParentElement();
1921: return e;
1922: }
1923:
1924:
1932: public Style getStyle(String nm)
1933: {
1934: StyleContext context = (StyleContext) getAttributeContext();
1935: return context.getStyle(nm);
1936: }
1937:
1938:
1944: public void removeStyle(String nm)
1945: {
1946: StyleContext context = (StyleContext) getAttributeContext();
1947: context.removeStyle(nm);
1948: }
1949:
1950:
1964: public void setCharacterAttributes(int offset, int length,
1965: AttributeSet attributes, boolean replace)
1966: {
1967:
1968: if (length == 0)
1969: return;
1970: try
1971: {
1972:
1973:
1974:
1975: writeLock();
1976: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
1977: length,
1978: DocumentEvent.EventType.CHANGE);
1979:
1980:
1981:
1982:
1983: buffer.change(offset, length, ev);
1984:
1985:
1986: int end = offset + length;
1987: Element curr;
1988: for (int pos = offset; pos < end;)
1989: {
1990:
1991: curr = getCharacterElement(pos);
1992: if (pos == curr.getEndOffset())
1993: break;
1994:
1995: MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();
1996: ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));
1997:
1998: if (replace)
1999: a.removeAttributes(a);
2000:
2001: a.addAttributes(attributes);
2002:
2003: pos = curr.getEndOffset();
2004: }
2005: fireChangedUpdate(ev);
2006: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2007: }
2008: finally
2009: {
2010: writeUnlock();
2011: }
2012: }
2013:
2014:
2022: public void setLogicalStyle(int position, Style style)
2023: {
2024: Element el = getParagraphElement(position);
2025:
2026:
2027: if (el == null)
2028: return;
2029: try
2030: {
2031: writeLock();
2032: if (el instanceof AbstractElement)
2033: {
2034: AbstractElement ael = (AbstractElement) el;
2035: ael.setResolveParent(style);
2036: int start = el.getStartOffset();
2037: int end = el.getEndOffset();
2038: DefaultDocumentEvent ev = new DefaultDocumentEvent(start,
2039: end - start,
2040: DocumentEvent.EventType.CHANGE);
2041: fireChangedUpdate(ev);
2042: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2043: }
2044: else
2045: throw new AssertionError(
2046: "paragraph elements are expected to be"
2047: + "instances of AbstractDocument.AbstractElement");
2048: }
2049: finally
2050: {
2051: writeUnlock();
2052: }
2053: }
2054:
2055:
2068: public void setParagraphAttributes(int offset, int length,
2069: AttributeSet attributes, boolean replace)
2070: {
2071: try
2072: {
2073:
2074:
2075:
2076: writeLock();
2077:
2078:
2079: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2080: length,
2081: DocumentEvent.EventType.CHANGE);
2082:
2083:
2084:
2085:
2086: Element rootElement = getDefaultRootElement();
2087: int startElement = rootElement.getElementIndex(offset);
2088: int endElement = rootElement.getElementIndex(offset + length - 1);
2089: if (endElement < startElement)
2090: endElement = startElement;
2091:
2092: for (int i = startElement; i <= endElement; i++)
2093: {
2094: Element par = rootElement.getElement(i);
2095: MutableAttributeSet a = (MutableAttributeSet) par.getAttributes();
2096:
2097: ev.addEdit(new AttributeUndoableEdit(par, attributes, replace));
2098:
2099: if (replace)
2100: a.removeAttributes(a);
2101:
2102: a.addAttributes(attributes);
2103: }
2104: fireChangedUpdate(ev);
2105: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2106: }
2107: finally
2108: {
2109: writeUnlock();
2110: }
2111: }
2112:
2113:
2122: protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
2123: {
2124: int offs = ev.getOffset();
2125: int len = ev.getLength();
2126: int endOffs = offs + len;
2127: if (attr == null)
2128: attr = SimpleAttributeSet.EMPTY;
2129:
2130:
2131: Element paragraph = getParagraphElement(endOffs);
2132: AttributeSet pAttr = paragraph.getAttributes();
2133:
2134: Element paragraph2 = getParagraphElement(offs);
2135: int contIndex = paragraph2.getElementIndex(offs);
2136: Element content = paragraph2.getElement(contIndex);
2137: AttributeSet cAttr = content.getAttributes();
2138:
2139: boolean insertAtBoundary = content.getEndOffset() == endOffs;
2140: try
2141: {
2142: Segment s = new Segment();
2143: ArrayList buf = new ArrayList();
2144: ElementSpec lastStartTag = null;
2145: boolean insertAfterNewline = false;
2146: short lastStartDir = ElementSpec.OriginateDirection;
2147:
2148:
2149: if (offs > 0)
2150: {
2151: getText(offs - 1, 1, s);
2152: if (s.array[s.offset] == '\n')
2153: {
2154: insertAfterNewline = true;
2155: lastStartDir = insertAfterNewline(paragraph, paragraph2,
2156: pAttr, buf, offs,
2157: endOffs);
2158:
2159: for (int i = buf.size() - 1; i >= 0 && lastStartTag == null;
2160: i--)
2161: {
2162: ElementSpec tag = (ElementSpec) buf.get(i);
2163: if (tag.getType() == ElementSpec.StartTagType)
2164: {
2165: lastStartTag = tag;
2166: }
2167: }
2168: }
2169:
2170: }
2171:
2172:
2173:
2174: if (! insertAfterNewline)
2175: pAttr = paragraph2.getAttributes();
2176:
2177:
2178: getText(offs, len, s);
2179: int end = s.offset + s.count;
2180: int last = s.offset;
2181: for (int i = s.offset; i < end; i++)
2182: {
2183: if (s.array[i] == '\n')
2184: {
2185: int breakOffs = i + 1;
2186: buf.add(new ElementSpec(attr, ElementSpec.ContentType,
2187: breakOffs - last));
2188: buf.add(new ElementSpec(null, ElementSpec.EndTagType));
2189: lastStartTag = new ElementSpec(pAttr,
2190: ElementSpec.StartTagType);
2191: buf.add(lastStartTag);
2192: last = breakOffs;
2193: }
2194: }
2195:
2196:
2197: if (last < end)
2198: {
2199: buf.add(new ElementSpec(attr, ElementSpec.ContentType,
2200: end - last));
2201: }
2202:
2203:
2204: ElementSpec first = (ElementSpec) buf.get(0);
2205: int doclen = getLength();
2206:
2207:
2208:
2209: if (first.getType() == ElementSpec.ContentType && cAttr.isEqual(attr))
2210: first.setDirection(ElementSpec.JoinPreviousDirection);
2211:
2212:
2213: if (lastStartTag != null)
2214: {
2215: if (insertAfterNewline)
2216: lastStartTag.setDirection(lastStartDir);
2217: else if (paragraph2.getEndOffset() != endOffs)
2218: lastStartTag.setDirection(ElementSpec.JoinFractureDirection);
2219: else
2220: {
2221: Element par = paragraph2.getParentElement();
2222: int par2Index = par.getElementIndex(offs);
2223: if (par2Index + 1 < par.getElementCount()
2224: && ! par.getElement(par2Index + 1).isLeaf())
2225: lastStartTag.setDirection(ElementSpec.JoinNextDirection);
2226: }
2227: }
2228:
2229:
2230: if (insertAtBoundary && endOffs < doclen)
2231: {
2232: ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
2233: if (lastTag.getType() == ElementSpec.ContentType
2234: && ((lastStartTag == null
2235: && (paragraph == paragraph2 || insertAfterNewline))
2236: || (lastStartTag != null
2237: && lastStartTag.getDirection() != ElementSpec.OriginateDirection)))
2238: {
2239: int nextIndex = paragraph.getElementIndex(endOffs);
2240: Element nextRun = paragraph.getElement(nextIndex);
2241: if (nextRun.isLeaf() && attr.isEqual(nextRun.getAttributes()))
2242: lastTag.setDirection(ElementSpec.JoinNextDirection);
2243: }
2244: }
2245:
2246: else if (! insertAtBoundary && lastStartTag != null
2247: && lastStartTag.getDirection() == ElementSpec.JoinFractureDirection)
2248: {
2249: ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
2250: if (lastTag.getType() == ElementSpec.ContentType
2251: && lastTag.getDirection() != ElementSpec.JoinPreviousDirection
2252: && attr.isEqual(cAttr))
2253: {
2254: lastTag.setDirection(ElementSpec.JoinNextDirection);
2255: }
2256: }
2257:
2258: ElementSpec[] specs = new ElementSpec[buf.size()];
2259: specs = (ElementSpec[]) buf.toArray(specs);
2260: buffer.insert(offs, len, specs, ev);
2261: }
2262: catch (BadLocationException ex)
2263: {
2264:
2265: ex.printStackTrace();
2266: }
2267: super.insertUpdate(ev, attr);
2268: }
2269:
2270: private short insertAfterNewline(Element par1, Element par2,
2271: AttributeSet attr, ArrayList buf,
2272: int offs, int endOffs)
2273: {
2274: short dir = 0;
2275: if (par1.getParentElement() == par2.getParentElement())
2276: {
2277: ElementSpec tag = new ElementSpec(attr, ElementSpec.EndTagType);
2278: buf.add(tag);
2279: tag = new ElementSpec(attr, ElementSpec.StartTagType);
2280: buf.add(tag);
2281: if (par2.getEndOffset() != endOffs)
2282: dir = ElementSpec.JoinFractureDirection;
2283: else
2284: {
2285: Element par = par2.getParentElement();
2286: if (par.getElementIndex(offs) + 1 < par.getElementCount())
2287: dir = ElementSpec.JoinNextDirection;
2288: }
2289: }
2290: else
2291: {
2292:
2293:
2294: ArrayList parentsLeft = new ArrayList();
2295: ArrayList parentsRight = new ArrayList();
2296: Element e = par2;
2297: while (e != null)
2298: {
2299: parentsLeft.add(e);
2300: e = e.getParentElement();
2301: }
2302: e = par1;
2303: int leftIndex = -1;
2304: while (e != null && (leftIndex = parentsLeft.indexOf(e)) == 1)
2305: {
2306: parentsRight.add(e);
2307: e = e.getParentElement();
2308: }
2309:
2310: if (e != null)
2311:
2312: {
2313:
2314:
2315: for (int c = 0; c < leftIndex; c++)
2316: {
2317: buf.add(new ElementSpec(null, ElementSpec.EndTagType));
2318: }
2319:
2320: for (int c = parentsRight.size() - 1; c >= 0; c--)
2321: {
2322: Element el = (Element) parentsRight.get(c);
2323: ElementSpec tag = new ElementSpec(el.getAttributes(),
2324: ElementSpec.StartTagType);
2325: if (c > 0)
2326: tag.setDirection(ElementSpec.JoinNextDirection);
2327: buf.add(tag);
2328: }
2329: if (parentsRight.size() > 0)
2330: dir = ElementSpec.JoinNextDirection;
2331: else
2332: dir = ElementSpec.JoinFractureDirection;
2333: }
2334: else
2335: assert false;
2336: }
2337: return dir;
2338: }
2339:
2340:
2347: short handleInsertAfterNewline(Vector specs, int offset, int endOffset,
2348: Element prevParagraph, Element paragraph,
2349: AttributeSet a)
2350: {
2351: if (prevParagraph.getParentElement() == paragraph.getParentElement())
2352: {
2353: specs.add(new ElementSpec(a, ElementSpec.EndTagType));
2354: specs.add(new ElementSpec(a, ElementSpec.StartTagType));
2355: if (paragraph.getStartOffset() != endOffset)
2356: return ElementSpec.JoinFractureDirection;
2357:
2358: Element parent = paragraph.getParentElement();
2359: if (parent.getElementCount() > (parent.getElementIndex(offset) + 1))
2360: return ElementSpec.JoinNextDirection;
2361: }
2362: return ElementSpec.OriginateDirection;
2363: }
2364:
2365:
2374: protected void removeUpdate(DefaultDocumentEvent ev)
2375: {
2376: super.removeUpdate(ev);
2377: buffer.remove(ev.getOffset(), ev.getLength(), ev);
2378: }
2379:
2380:
2385: public Enumeration<?> getStyleNames()
2386: {
2387: StyleContext context = (StyleContext) getAttributeContext();
2388: return context.getStyleNames();
2389: }
2390:
2391:
2397: protected void styleChanged(Style style)
2398: {
2399:
2400: }
2401:
2402:
2410: protected void insert(int offset, ElementSpec[] data)
2411: throws BadLocationException
2412: {
2413: if (data == null || data.length == 0)
2414: return;
2415: try
2416: {
2417:
2418:
2419:
2420: writeLock();
2421:
2422:
2423: StringBuffer contentBuffer = new StringBuffer();
2424: for (int i = 0; i < data.length; i++)
2425: {
2426:
2427:
2428: ElementSpec spec = data[i];
2429: if (spec.getArray() != null && spec.getLength() > 0)
2430: contentBuffer.append(spec.getArray(), spec.getOffset(),
2431: spec.getLength());
2432: }
2433:
2434: int length = contentBuffer.length();
2435:
2436:
2437: if (length == 0)
2438: return;
2439:
2440: Content c = getContent();
2441: UndoableEdit edit = c.insertString(offset,
2442: contentBuffer.toString());
2443:
2444:
2445: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2446: length,
2447: DocumentEvent.EventType.INSERT);
2448:
2449: ev.addEdit(edit);
2450:
2451:
2452:
2453: buffer.insert(offset, length, data, ev);
2454:
2455: super.insertUpdate(ev, null);
2456:
2457: ev.end();
2458: fireInsertUpdate(ev);
2459: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2460: }
2461: finally
2462: {
2463: writeUnlock();
2464: }
2465: }
2466:
2467:
2475: protected void create(ElementSpec[] data)
2476: {
2477: try
2478: {
2479:
2480:
2481: int len = getLength();
2482: if (len > 0)
2483: remove(0, len);
2484:
2485: writeLock();
2486:
2487:
2488: StringBuilder b = new StringBuilder();
2489: for (int i = 0; i < data.length; ++i)
2490: {
2491: ElementSpec el = data[i];
2492: if (el.getArray() != null && el.getLength() > 0)
2493: b.append(el.getArray(), el.getOffset(), el.getLength());
2494: }
2495: Content content = getContent();
2496: UndoableEdit cEdit = content.insertString(0, b.toString());
2497:
2498: len = b.length();
2499: DefaultDocumentEvent ev =
2500: new DefaultDocumentEvent(0, b.length(),
2501: DocumentEvent.EventType.INSERT);
2502: ev.addEdit(cEdit);
2503:
2504: buffer.create(len, data, ev);
2505:
2506:
2507: super.insertUpdate(ev, null);
2508:
2509: ev.end();
2510: fireInsertUpdate(ev);
2511: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2512: }
2513: catch (BadLocationException ex)
2514: {
2515: AssertionError err = new AssertionError("Unexpected bad location");
2516: err.initCause(ex);
2517: throw err;
2518: }
2519: finally
2520: {
2521: writeUnlock();
2522: }
2523: }
2524: }