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.awt.Container;
023: import java.awt.Rectangle;
024: import java.awt.Shape;
025: import java.util.ArrayList;
026: import java.util.List;
027: import javax.swing.BasicSwingTestCase;
028: import javax.swing.JTextArea;
029: import javax.swing.event.DocumentEvent;
030: import javax.swing.event.DocumentListener;
031: import javax.swing.text.ViewTest.DisAbstractedView;
032:
033: public class ViewRTest extends BasicSwingTestCase implements
034: DocumentListener {
035: private static class Factory implements ViewFactory {
036: public View create(Element element) {
037: final String name = element.getName();
038: if (AbstractDocument.SectionElementName.equals(name)) {
039: return new BoxView(element, View.Y_AXIS) {
040: @Override
041: protected void forwardUpdateToView(View view,
042: DocumentEvent event, Shape shape,
043: ViewFactory factory) {
044: viewsForwardedTo.add(view);
045: super .forwardUpdateToView(view, event, shape,
046: factory);
047: }
048: };
049: }
050: if (AbstractDocument.ParagraphElementName.equals(name)) {
051: return new ParagraphView(element);
052: }
053: if (AbstractDocument.ContentElementName.equals(name)) {
054: return new LabelView(element);
055: }
056: throw new Error("Unexpected element name: " + name);
057: }
058: }
059:
060: private Document doc;
061:
062: private Element root;
063:
064: private View view;
065:
066: private DocumentEvent event;
067:
068: private static final ViewFactory factory = new Factory();
069:
070: private static final Shape shape = new Rectangle(5, 7, 452, 217);
071:
072: private static final List<View> viewsForwardedTo = new ArrayList<View>();
073:
074: @Override
075: protected void setUp() throws Exception {
076: super .setUp();
077: doc = new DefaultStyledDocument();
078: root = doc.getDefaultRootElement();
079: }
080:
081: /**
082: * Tests the case where a mutation occured on element boundaries, so that
083: * both paragraphs changed but the section where these paragraphs lie
084: * is not changed.
085: * In this case the update must be forwarded to these both paragraphs.
086: * <p>
087: * In more detail, the document structure for this test is like this:
088: * <pre>
089: * section
090: * |
091: * +--paragraph
092: * | +--content [0, 5; plain]
093: * | +--content [5, 12; italic\n]
094: * |
095: * +--paragraph
096: * +--content [12, 13; \n] // represents implied new line char
097: * </pre>
098: * Then an unattributed text, which doesn't contain the new line char,
099: * is inserted at <code>doc.getLength()</code>.
100: * This insert causes the element structure to be rebuild, however
101: * no changes occur to the section element.
102: * <p>Thus <code>change</code> parameter to
103: * <code>forwardUpdate</code> will be <code>null</code>.
104: */
105: public void testInsertUpdate01() throws BadLocationException {
106: MutableAttributeSet italic = new SimpleAttributeSet();
107: StyleConstants.setItalic(italic, true);
108: // Init the document structure
109: doc.insertString(doc.getLength(), "plain", null);
110: doc.insertString(doc.getLength(), "italic\n", italic);
111: // Init the view hierarchy
112: view = factory.create(root);
113: ((CompositeView) view).loadChildren(factory);
114: doc.addDocumentListener(this );
115: // Perform the change tested against
116: doc.insertString(doc.getLength(), "second", null);
117: // Both paragraph elements will be modified,
118: // but the section will not
119: assertNotNull(event.getChange(root.getElement(0)));
120: assertNotNull(event.getChange(root.getElement(1)));
121: assertNull(event.getChange(root));
122: viewsForwardedTo.clear();
123: assertEquals(2, view.getViewCount());
124: view.insertUpdate(event, shape, factory);
125: assertEquals(2, view.getViewCount());
126: assertEquals(2, viewsForwardedTo.size());
127: assertSame(view.getView(0), viewsForwardedTo.get(0));
128: assertSame(view.getView(1), viewsForwardedTo.get(1));
129: viewsForwardedTo.clear();
130: }
131:
132: /**
133: * Tests the case where a mutation occured on element boundaries, so that
134: * both the existing paragraph needs to rebuild its elements and a new
135: * paragraph is created. Because of the latter, the section is modified
136: * too.
137: * In this case the view must create a new child to represent the new
138: * paragrap as well as notify the previous paragraph so that it updates
139: * itself.
140: * <p>
141: * In more detail, the document structure for this test is like this:
142: * <pre>
143: * section
144: * |
145: * +--paragraph
146: * | +--content [0, 5; plain]
147: * | +--content [5, 12; italic\n]
148: * |
149: * +--paragraph
150: * +--content [12, 19; second ]
151: * +--content [19, 31; italic again]
152: * +--content [31, 32; \n] // represents implied new line char
153: * </pre>
154: * Then an unattributed text, which contains the new line char,
155: * is inserted at <code>doc.getLength()</code>.
156: * This insert causes the element structure to be rebuild:
157: * <ol>
158: * <li>The second paragraph re-creates its last element.
159: * This element is mapped to the inserted text.</li>
160: * <li>The new paragraph is created, which will contain the
161: * implied new line char.<li>
162: * </ol>
163: * <p>Thus <code>change</code> parameter to
164: * <code>forwardUpdate</code> will be not <code>null</code>.
165: */
166: public void testInsertUpdate02() throws BadLocationException {
167: MutableAttributeSet italic = new SimpleAttributeSet();
168: StyleConstants.setItalic(italic, true);
169: // Init the document structure
170: doc.insertString(doc.getLength(), "plain", null);
171: doc.insertString(doc.getLength(), "italic\n", italic);
172: doc.insertString(doc.getLength(), "second ", null);
173: doc.insertString(doc.getLength(), "italic again", italic);
174: // Init the view hierarchy
175: view = factory.create(root);
176: ((CompositeView) view).loadChildren(factory);
177: doc.addDocumentListener(this );
178: // Perform the change tested against
179: doc.insertString(doc.getLength(), " & plain again\n", null);
180: // Both paragraph elements will be modified,
181: // but the section will not
182: assertNotNull(event.getChange(root.getElement(1)));
183: assertNull(event.getChange(root.getElement(2)));
184: assertNotNull(event.getChange(root));
185: viewsForwardedTo.clear();
186: assertEquals(2, view.getViewCount());
187: view.insertUpdate(event, shape, factory);
188: assertEquals(3, view.getViewCount());
189: assertEquals(1, viewsForwardedTo.size());
190: assertSame(view.getView(1), viewsForwardedTo.get(0));
191: viewsForwardedTo.clear();
192: }
193:
194: public void testUpdateLayout() throws Exception {
195: doc = new PlainDocument();
196: root = doc.getDefaultRootElement();
197: doc.insertString(0, "1\n\n\n\n", null);
198: doc.addDocumentListener(this );
199: doc.insertString(3, "\n2", null);
200: final Marker marker = new Marker();
201: final JTextArea area = new JTextArea(doc) {
202: private static final long serialVersionUID = 1L;
203:
204: @Override
205: public void repaint() {
206: marker.setOccurred();
207: }
208: };
209: view = new DisAbstractedView(root) {
210: @Override
211: public Container getContainer() {
212: return area;
213: }
214: };
215: assertEquals(0, view.getViewCount());
216: assertNull(view.getParent());
217: marker.reset();
218: assertNotNull(event.getChange(root));
219: view.updateLayout(event.getChange(root), event, shape);
220: assertTrue(marker.isOccurred());
221: marker.reset();
222: view.updateLayout(null, event, shape);
223: assertFalse(marker.isOccurred());
224: }
225:
226: public void insertUpdate(DocumentEvent e) {
227: event = e;
228: }
229:
230: public void removeUpdate(DocumentEvent e) {
231: }
232:
233: public void changedUpdate(DocumentEvent e) {
234: }
235: }
|