001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Alexey A. Ivanov
019: * @version $Revision$
020: */package javax.swing.text;
021:
022: import java.util.List;
023: import javax.swing.event.DocumentEvent;
024: import javax.swing.event.DocumentListener;
025: import javax.swing.event.DocumentEvent.EventType;
026: import javax.swing.text.AbstractDocument.DefaultDocumentEvent;
027: import javax.swing.text.DefaultStyledDocument.AttributeUndoableEdit;
028: import javax.swing.text.DefaultStyledDocument.ElementBuffer;
029: import javax.swing.text.DefaultStyledDocument.ElementSpec;
030: import junit.framework.TestCase;
031:
032: /**
033: * Tests DefaultStyledDocument.ElementBuffer class. Here tested the methods
034: * that update document structure: insert, remove, change, and their protected
035: * counterparts.
036: * <p>
037: * The contents of the DefaultDocumentEvent is checked.
038: * Also AttributeUndoableEdit is tested here a little bit.
039: *
040: */
041: public class DefaultStyledDocument_ElementBuffer_UpdateTest extends
042: TestCase {
043: private DefaultStyledDocument doc;
044:
045: private Element root;
046:
047: private ElementBuffer buf;
048:
049: private DefaultDocumentEvent event;
050:
051: @Override
052: protected void setUp() throws Exception {
053: super .setUp();
054: doc = new DefaultStyledDocument();
055: doc.insertString(0, "01234\nabcde", null);
056: root = doc.getDefaultRootElement();
057: }
058:
059: /*
060: * DefaultStyledDocument.ElementBuffer.changeUpdate()
061: *
062: * Checks when DefaultDocumentEvent is filled with edits, and which
063: * types of edits are performed during changing of character attributes.
064: */
065: public void testChangeUpdateChar() {
066: buf = doc.new ElementBuffer(root) {
067: private static final long serialVersionUID = 1L;
068:
069: @Override
070: protected void changeUpdate() {
071: final List<?> edits = getEdits(event);
072: assertEquals(0, edits.size());
073: super .changeUpdate();
074: assertEquals(0, edits.size());
075: assertTrue(event.isInProgress());
076: }
077:
078: @Override
079: public void change(int offset, int length,
080: DefaultDocumentEvent e) {
081: event = e;
082: final List<?> edits = getEdits(event);
083: assertSame(EventType.CHANGE, event.getType());
084: assertEquals(0, edits.size());
085: super .change(offset, length, event);
086: assertEquals(1, edits.size());
087: }
088: };
089: doc.buffer = buf;
090: MutableAttributeSet attrs = new SimpleAttributeSet();
091: StyleConstants.setBold(attrs, true);
092: doc.setCharacterAttributes(2, 2, attrs, false);
093: List<?> edits = getEdits(event);
094: assertEquals(2, edits.size());
095: assertChange(edits.get(0), root.getElement(0), 0, new int[] {
096: 0, 2, 2, 4, 4, 6 }, new int[] { 0, 6 });
097: AttributeUndoableEdit attrEdit = (AttributeUndoableEdit) edits
098: .get(1);
099: assertFalse(attrEdit.isReplacing);
100: assertEquals(SimpleAttributeSet.EMPTY, attrEdit.copy);
101: assertEquals(attrs, attrEdit.newAttributes);
102: assertSame(root.getElement(0).getElement(1), attrEdit.element);
103: final Element leaf = root.getElement(0).getElement(1);
104: assertEquals(attrs, leaf.getAttributes());
105: doc.writeLock();
106: try {
107: attrEdit.undo();
108: } finally {
109: doc.writeUnlock();
110: }
111: assertEquals(SimpleAttributeSet.EMPTY, leaf.getAttributes());
112: }
113:
114: /*
115: * DefaultStyledDocument.ElementBuffer.changeUpdate()
116: *
117: * Checks when DefaultDocumentEvent is filled with edits, and which
118: * types of edits are performed during changing of character attributes.
119: */
120: public void testChangeUpdateCharDirect() {
121: buf = doc.new ElementBuffer(root) {
122: private static final long serialVersionUID = 1L;
123:
124: @Override
125: protected void changeUpdate() {
126: final List<?> edits = getEdits(event);
127: assertEquals(0, edits.size());
128: super .changeUpdate();
129: assertEquals(0, edits.size());
130: assertTrue(event.isInProgress());
131: }
132:
133: @Override
134: public void change(int offset, int length,
135: DefaultDocumentEvent e) {
136: event = e;
137: final List<?> edits = getEdits(event);
138: assertSame(EventType.CHANGE, event.getType());
139: assertEquals(0, edits.size());
140: super .change(offset, length, event);
141: assertEquals(1, edits.size());
142: }
143: };
144: doc.buffer = buf;
145: MutableAttributeSet attrs = new SimpleAttributeSet();
146: StyleConstants.setBold(attrs, true);
147: event = doc.new DefaultDocumentEvent(2, 2, EventType.CHANGE);
148: doc.writeLock();
149: try {
150: buf.change(2, 2, event);
151: } finally {
152: doc.writeUnlock();
153: }
154: // The call to buf.change is almost like a call
155: // doc.setCharacterAttributes(2, 2, SimpleAttributeSet.EMPTY, false);
156: // but the latter will also safe attribute changes into
157: // AttributeUndoableEdit despite there actually were no changes
158: // in attributes.
159: List<?> edits = getEdits(event);
160: assertEquals(1, edits.size());
161: assertChange(edits.get(0), root.getElement(0), 0, new int[] {
162: 0, 2, 2, 4, 4, 6 }, new int[] { 0, 6 });
163: final Element leaf = root.getElement(0).getElement(1);
164: assertEquals(SimpleAttributeSet.EMPTY, leaf.getAttributes());
165: }
166:
167: /*
168: * DefaultStyledDocument.ElementBuffer.changeUpdate()
169: *
170: * Checks when DefaultDocumentEvent is filled with edits, and which
171: * types of edits are performed during changing of paragraph attributes.
172: */
173: public void testChangeUpdatePar() {
174: buf = doc.new ElementBuffer(root) {
175: private static final long serialVersionUID = 1L;
176:
177: @Override
178: protected void changeUpdate() {
179: fail("ElementBuffer.changeUpdate is not expected");
180: }
181:
182: @Override
183: public void change(int offset, int length,
184: DefaultDocumentEvent e) {
185: fail("ElementBuffer.change is not expected");
186: }
187: };
188: doc.buffer = buf;
189: MutableAttributeSet attrs = new SimpleAttributeSet();
190: StyleConstants.setBold(attrs, true);
191: doc.addDocumentListener(new DocumentListener() {
192: public void changedUpdate(DocumentEvent e) {
193: event = (DefaultDocumentEvent) e;
194: }
195:
196: public void insertUpdate(DocumentEvent e) {
197: fail("DocumentListener.insertUpdate is not expected");
198: }
199:
200: public void removeUpdate(DocumentEvent e) {
201: fail("DocumentListener.removeUpdate is not expected");
202: }
203: });
204: doc.setParagraphAttributes(2, 2, attrs, false);
205: List<?> edits = getEdits(event);
206: assertEquals(1, edits.size());
207: AttributeUndoableEdit attrEdit = (AttributeUndoableEdit) edits
208: .get(0);
209: assertFalse(attrEdit.isReplacing);
210: assertEquals(1, attrEdit.copy.getAttributeCount());
211: assertTrue(attrEdit.copy
212: .isDefined(AttributeSet.ResolveAttribute));
213: assertEquals(attrs, attrEdit.newAttributes);
214: assertSame(root.getElement(0), attrEdit.element);
215: }
216:
217: /*
218: * DefaultStyledDocument.ElementBuffer.insertUpdate(ElementSpec[])
219: */
220: public void testInsertUpdate() throws BadLocationException {
221: buf = doc.new ElementBuffer(root) {
222: private static final long serialVersionUID = 1L;
223:
224: @Override
225: protected void insertUpdate(ElementSpec[] spec) {
226: final List<?> edits = getEdits(event);
227: assertEquals(0, edits.size());
228: super .insertUpdate(spec);
229: assertEquals(0, edits.size());
230: assertTrue(event.isInProgress());
231: }
232:
233: @Override
234: public void insert(int offset, int length,
235: ElementSpec[] spec, DefaultDocumentEvent event) {
236: final List<?> edits = getEdits(event);
237: assertEquals(0, edits.size());
238: super .insert(offset, length, spec, event);
239: assertEquals(3, edits.size());
240: }
241: };
242: doc.buffer = buf;
243: // The specs are:
244: // Content:JoinPrevious:1,
245: // EndTag:Originate:0,
246: // StartTag:Fracture:0,
247: // Content:JoinNext:4
248: // It is the same as:
249: // doc.insertString(doc.getLength(), "\nthird", null);
250: //
251: // Document contains: "01234\nabcde\n"
252: // Offsets 012345 678901 2
253: // 0 1
254: // Paragraphs 000000 111111
255: // After the text is inserted:
256: // "01234\nabcde\nthird\n"
257: // Offsets: 012345 678901 234567 8
258: // 0 1
259: // Paragraphs 000000 111111 222222
260: //
261: // doc.dump(System.out);
262: //<section>
263: // <paragraph
264: // resolver=NamedStyle:default {name=default,}
265: // >
266: // <content>
267: // [0,6][01234
268: //]
269: // <paragraph
270: // resolver=NamedStyle:default {name=default,}
271: // >
272: // <content>
273: // [6,12][abcde
274: //]
275: // <paragraph
276: // resolver=NamedStyle:default {name=default,}
277: // >
278: // <content>
279: // [12,18][third
280: //]
281: ElementSpec[] specs = {
282: new ElementSpec(SimpleAttributeSet.EMPTY,
283: ElementSpec.ContentType, 1),
284: new ElementSpec(null, ElementSpec.EndTagType, 0),
285: new ElementSpec(root.getElement(1).getAttributes(),
286: ElementSpec.StartTagType, 0),
287: new ElementSpec(SimpleAttributeSet.EMPTY,
288: ElementSpec.ContentType, 5) };
289: specs[0].setDirection(ElementSpec.JoinPreviousDirection);
290: specs[2].setDirection(ElementSpec.JoinFractureDirection);
291: specs[3].setDirection(ElementSpec.JoinNextDirection);
292: event = doc.new DefaultDocumentEvent(doc.getLength(), 6,
293: EventType.INSERT);
294: int off = doc.getLength();
295: // Insert the text into the content, so that ElementBuffer
296: // could use proper offsets (or BadLocationException may be thrown).
297: doc.getContent().insertString(off, "\nthird");
298: doc.writeLock();
299: try {
300: buf.insert(off, 6, specs, event);
301: } finally {
302: doc.writeUnlock();
303: }
304: List<?> edits = getEdits(event);
305: assertEquals(3, edits.size());
306: assertChange(edits.get(0), root.getElement(1), 0, new int[] {
307: 6, 12 }, new int[] { 6, 18 });
308: assertChange(edits.get(1), root.getElement(2), 0, new int[] {
309: 12, 18 }, new int[] { 17, 18 });
310: assertChange(edits.get(2), root, 2, new int[] { 12, 18 },
311: new int[] {});
312: }
313:
314: /*
315: * DefaultStyledDocument.ElementBuffer.removeUpdate()
316: *
317: * Remove a portion so that no structural changes are needed.
318: */
319: public void testRemoveUpdateNoStrucChange() {
320: buf = doc.new ElementBuffer(root) {
321: private static final long serialVersionUID = 1L;
322:
323: @Override
324: protected void removeUpdate() {
325: final List<?> edits = getEdits(event);
326: assertEquals(0, edits.size());
327: super .removeUpdate();
328: assertEquals(0, edits.size());
329: assertTrue(event.isInProgress());
330: }
331:
332: @Override
333: public void remove(int offset, int length,
334: DefaultDocumentEvent e) {
335: event = e;
336: final List<?> edits = getEdits(event);
337: assertSame(EventType.REMOVE, event.getType());
338: assertEquals(0, edits.size());
339: super .remove(offset, length, event);
340: assertEquals(0, edits.size());
341: }
342: };
343: doc.buffer = buf;
344: event = doc.new DefaultDocumentEvent(2, 2, EventType.REMOVE);
345: doc.writeLock();
346: try {
347: buf.remove(2, 2, event);
348: } finally {
349: doc.writeUnlock();
350: }
351: List<?> edits = getEdits(event);
352: assertEquals(0, edits.size());
353: }
354:
355: /*
356: * DefaultStyledDocument.ElementBuffer.removeUpdate()
357: *
358: * Remove a portion so that the document structure is changed.
359: */
360: public void testRemoveUpdateStrucChange() {
361: buf = doc.new ElementBuffer(root) {
362: private static final long serialVersionUID = 1L;
363:
364: @Override
365: protected void removeUpdate() {
366: final List<?> edits = getEdits(event);
367: assertEquals(0, edits.size());
368: super .removeUpdate();
369: assertEquals(0, edits.size());
370: assertTrue(event.isInProgress());
371: }
372:
373: @Override
374: public void remove(int offset, int length,
375: DefaultDocumentEvent e) {
376: event = e;
377: final List<?> edits = getEdits(event);
378: assertSame(EventType.REMOVE, event.getType());
379: assertEquals(0, edits.size());
380: super .remove(offset, length, event);
381: assertEquals(1, edits.size());
382: }
383: };
384: doc.buffer = buf;
385: event = doc.new DefaultDocumentEvent(2, 2, EventType.REMOVE);
386: doc.writeLock();
387: try {
388: buf.remove(4, 3, event);
389: } finally {
390: doc.writeUnlock();
391: }
392: List<?> edits = getEdits(event);
393: assertEquals(1, edits.size());
394: assertChange(edits.get(0), root, 0, new int[] { 0, 12 },
395: new int[] { 0, 6, 6, 12 });
396: }
397:
398: private static void assertChange(final Object change,
399: final Element element, final int index,
400: final int[] addedOffsets, final int[] removedOffsets) {
401: DefStyledDoc_Helpers.assertChange(change, element, index,
402: removedOffsets, addedOffsets);
403: }
404:
405: private static List<?> getEdits(final DefaultDocumentEvent event) {
406: return DefStyledDoc_Helpers.getEdits(event);
407: }
408: }
|