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.Font;
023: import java.awt.FontMetrics;
024: import java.awt.Toolkit;
025: import javax.swing.event.DocumentEvent;
026: import javax.swing.event.DocumentEvent.EventType;
027: import javax.swing.text.AbstractDocument.BranchElement;
028: import javax.swing.text.AbstractDocument.LeafElement;
029: import javax.swing.text.GlyphViewTest.EmptyPainter;
030: import junit.framework.TestCase;
031:
032: /**
033: * Tests breaking behavior of GlyphView.
034: *
035: */
036: public class GlyphView_BreakTest extends TestCase {
037: private GlyphView view;
038:
039: private StyledDocument doc;
040:
041: private Element root;
042:
043: private Element leaf;
044:
045: private Font font;
046:
047: private FontMetrics metrics;
048:
049: private float width;
050:
051: private static final String FULL_TEXT = "this text to check how view breaks";
052:
053: // 0123456789012345678901234567890123
054: private static final int startOffset = 5;
055:
056: private static final int endOffset = 28;
057:
058: private static final int length = endOffset - startOffset;
059:
060: private static final String LEAF_TEXT = FULL_TEXT.substring(
061: startOffset, endOffset);
062:
063: private static final int X_AXIS = View.X_AXIS;
064:
065: private static final int Y_AXIS = View.Y_AXIS;
066:
067: private static final int BAD = View.BadBreakWeight;
068:
069: private static final int GOOD = View.GoodBreakWeight;
070:
071: private static final int EXCELLENT = View.ExcellentBreakWeight;
072:
073: @SuppressWarnings("deprecation")
074: @Override
075: protected void setUp() throws Exception {
076: super .setUp();
077: doc = new DefaultStyledDocument();
078: root = doc.getDefaultRootElement();
079: doc.insertString(0, FULL_TEXT, null);
080: doc.setCharacterAttributes(startOffset, length,
081: SimpleAttributeSet.EMPTY, false);
082: leaf = root.getElement(0).getElement(1);
083: view = new GlyphView(leaf);
084: font = view.getFont();
085: metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
086: }
087:
088: /**
089: * Breaks the view along X at an invalid offset
090: * (not in the range of the view).
091: */
092: public void testBreakViewX_IncorrectOffset() {
093: View part;
094: // The text in view will be measured as if the view started at offset 0
095: width = metrics.stringWidth(FULL_TEXT.substring(0, 1));
096: part = view.breakView(X_AXIS, 0, 0.0f, width);
097: assertNotSame(view, part);
098: assertSame(view.getElement(), part.getElement());
099: assertEquals(0, part.getStartOffset());
100: assertEquals(1, part.getEndOffset());
101: assertEquals(5, view.getStartOffset()); // leaf.get{Start, End}Offset
102: assertEquals(28, view.getEndOffset());
103: part = view.breakView(X_AXIS, 0, 0.0f, width - 0.01f);
104: assertNotSame(view, part);
105: assertEquals(view.getStartOffset(), part.getStartOffset());
106: assertEquals(view.getEndOffset(), part.getEndOffset());
107: // Measuring will start at offset 1
108: width = metrics.stringWidth(FULL_TEXT.substring(1, 2));
109: part = view.breakView(X_AXIS, 1, 0.0f, width);
110: assertNotSame(view, part);
111: assertEquals(1, part.getStartOffset());
112: assertEquals(2, part.getEndOffset());
113: part = view.breakView(X_AXIS, 1, 0.0f, width - 0.01f);
114: assertNotSame(view, part);
115: assertEquals(view.getStartOffset(), part.getStartOffset());
116: assertEquals(view.getEndOffset(), part.getEndOffset());
117: width = metrics.stringWidth(FULL_TEXT.substring(0, 2));
118: part = view.breakView(X_AXIS, 0, 0.0f, width);
119: assertEquals(0, part.getStartOffset());
120: assertEquals(2, part.getEndOffset());
121: width = metrics.stringWidth(FULL_TEXT.substring(1, 3));
122: part = view.breakView(X_AXIS, 1, 0.0f, width - 0.01f);
123: assertEquals(1, part.getStartOffset());
124: assertEquals(2, part.getEndOffset());
125: width = metrics.stringWidth(FULL_TEXT.substring(0, 8));
126: part = view.breakView(X_AXIS, 0, 0.0f, width);
127: assertEquals(0, part.getStartOffset());
128: assertEquals(5, part.getEndOffset());
129: width = metrics.stringWidth(FULL_TEXT.substring(1, 9));
130: part = view.breakView(X_AXIS, 1, 0.0f, width - 0.01f);
131: assertEquals(1, part.getStartOffset());
132: assertEquals(5, part.getEndOffset());
133: }
134:
135: /**
136: * Breaks the view along X at a correct offset
137: * (in the range of the view).
138: */
139: public void testBreakViewX_CorrectOffset() {
140: View part;
141: width = metrics.stringWidth(LEAF_TEXT.substring(0, 1));
142: part = view.breakView(X_AXIS, startOffset, 0.0f, width);
143: assertNotSame(view, part);
144: assertSame(view.getElement(), part.getElement());
145: assertEquals(5, part.getStartOffset());
146: assertEquals(6, part.getEndOffset());
147: assertEquals(5, view.getStartOffset()); // leaf.get{Start, End}Offset
148: assertEquals(28, view.getEndOffset());
149: part = view.breakView(X_AXIS, startOffset, 0.0f, width - 0.01f);
150: assertEquals(5, part.getStartOffset());
151: assertEquals(28, part.getEndOffset());
152: // Measuring of text will start at startOffset + 1
153: width = metrics.stringWidth(LEAF_TEXT.substring(1, 2));
154: part = view.breakView(X_AXIS, startOffset + 1, 0.0f, width);
155: assertEquals(6, part.getStartOffset());
156: assertEquals(7, part.getEndOffset());
157: part = view.breakView(X_AXIS, startOffset + 1, 0.0f,
158: width - 0.01f);
159: assertEquals(5, part.getStartOffset());
160: assertEquals(28, part.getEndOffset());
161: width = metrics.stringWidth(LEAF_TEXT.substring(0, 2));
162: part = view.breakView(X_AXIS, startOffset, 0.0f, width);
163: assertEquals(5, part.getStartOffset());
164: assertEquals(7, part.getEndOffset());
165: width = metrics.stringWidth(LEAF_TEXT.substring(1, 3));
166: part = view.breakView(X_AXIS, startOffset + 1, 0.0f,
167: width - 0.01f);
168: assertEquals(6, part.getStartOffset());
169: assertEquals(7, part.getEndOffset());
170: width = metrics.stringWidth(LEAF_TEXT.substring(0, 8));
171: part = view.breakView(X_AXIS, startOffset, 0.0f, width);
172: assertEquals(5, part.getStartOffset());
173: assertEquals(13, part.getEndOffset());
174: width = metrics.stringWidth(LEAF_TEXT.substring(1, 9));
175: part = view.breakView(X_AXIS, startOffset + 1, 0.0f,
176: width - 0.01f);
177: assertEquals(6, part.getStartOffset());
178: assertEquals(13, part.getEndOffset());
179: }
180:
181: /**
182: * Shows the start and end offsets are updated when text is inserted
183: * before the start of the part this view represents.
184: */
185: public void testBreakViewX_ElementChangeBefore()
186: throws BadLocationException {
187: View part;
188: width = metrics.stringWidth(LEAF_TEXT.substring(0, 8));
189: part = view.breakView(X_AXIS, startOffset + 1, 0.0f,
190: width - 0.01f);
191: assertEquals(6, part.getStartOffset());
192: assertEquals(13, part.getEndOffset());
193: doc.insertString(5, "^^^", null);
194: assertEquals(9, part.getStartOffset());
195: assertEquals(16, part.getEndOffset());
196: DocumentEvent event = createEvent(5, 3, EventType.INSERT);
197: part.insertUpdate(event, null, null);
198: assertEquals(9, part.getStartOffset());
199: assertEquals(16, part.getEndOffset());
200: }
201:
202: /**
203: * Shows the start and end offsets are not updated when text is inserted
204: * in the middle of the part of the element this view represents.
205: */
206: public void testBreakViewX_ElementChangeMiddle()
207: throws BadLocationException {
208: View part;
209: width = metrics.stringWidth(LEAF_TEXT.substring(0, 8));
210: part = view.breakView(X_AXIS, startOffset + 1, 0.0f,
211: width - 0.01f);
212: assertEquals(6, part.getStartOffset());
213: assertEquals(13, part.getEndOffset());
214: doc.insertString(7, "^^^", null);
215: assertEquals(6, part.getStartOffset());
216: assertEquals(13, part.getEndOffset());
217: DocumentEvent event = createEvent(5, 3, EventType.INSERT);
218: part.insertUpdate(event, null, null);
219: assertEquals(6, part.getStartOffset());
220: assertEquals(13, part.getEndOffset());
221: }
222:
223: /**
224: * Breakes the view along Y.
225: */
226: public void testBreakViewY() {
227: View part;
228: final int offset = leaf.getStartOffset();
229: width = metrics.getHeight();
230: part = view.breakView(Y_AXIS, offset, 0.0f, width);
231: assertSame(view, part);
232: assertEquals(5, part.getStartOffset());
233: assertEquals(28, part.getEndOffset());
234: part = view.breakView(Y_AXIS, offset, 0.0f, width - 0.01f);
235: assertSame(view, part);
236: part = view.breakView(Y_AXIS, offset, 0.0f, width + 0.01f);
237: assertSame(view, part);
238: part = view.breakView(Y_AXIS, offset, 0.0f, width * 2);
239: assertSame(view, part);
240: }
241:
242: /**
243: * Tests <code>breakView</code> uses <code>createFragment</code> to
244: * produce the part.
245: */
246: public void testBreakViewCreate() throws Exception {
247: view = new GlyphView(root) {
248: @Override
249: public View createFragment(int startOffset, int endOffset) {
250: final Element part = ((AbstractDocument) doc).new LeafElement(
251: null, null, startOffset, endOffset);
252: return new LabelView(part);
253: };
254: };
255: final float width = metrics.stringWidth(FULL_TEXT.substring(0,
256: 2));
257: final View fragment = view.breakView(X_AXIS, 0, 0, width);
258: assertTrue(fragment instanceof LabelView);
259: assertFalse(view instanceof LabelView);
260: assertEquals(view.getStartOffset(), fragment.getStartOffset());
261: assertEquals(view.getStartOffset() + 2, fragment.getEndOffset());
262: assertTrue(fragment.getElement() instanceof LeafElement);
263: assertTrue(view.getElement() instanceof BranchElement);
264: }
265:
266: public void testCreateFragment() {
267: View fragment;
268: fragment = view.createFragment(1, 3);
269: assertEquals(1, fragment.getStartOffset());
270: assertEquals(3, fragment.getEndOffset());
271: assertSame(view.getElement(), fragment.getElement());
272: assertTrue(fragment instanceof GlyphView);
273: fragment = view.createFragment(5, 7);
274: assertEquals(5, fragment.getStartOffset());
275: assertEquals(7, fragment.getEndOffset());
276: assertSame(view.getElement(), fragment.getElement());
277: fragment = view.createFragment(startOffset, endOffset);
278: assertNotSame(view, fragment);
279: assertEquals(view.getStartOffset(), fragment.getStartOffset());
280: assertEquals(view.getEndOffset(), fragment.getEndOffset());
281: assertSame(view.getElement(), fragment.getElement());
282: fragment = view.createFragment(startOffset + length / 4,
283: endOffset - length / 4);
284: assertEquals(startOffset + length / 4, fragment
285: .getStartOffset());
286: assertEquals(endOffset - length / 4, fragment.getEndOffset());
287: assertSame(view.getElement(), fragment.getElement());
288: fragment = fragment.createFragment(
289: fragment.getStartOffset() + 2,
290: fragment.getEndOffset() - 1);
291: assertEquals(startOffset + length / 4 + 2, fragment
292: .getStartOffset());
293: assertEquals(endOffset - length / 4 - 1, fragment
294: .getEndOffset());
295: assertSame(view.getElement(), fragment.getElement());
296: }
297:
298: public void testGetBreakWeightX() {
299: width = metrics.stringWidth(LEAF_TEXT.substring(0, 1));
300: assertEquals(GOOD, view.getBreakWeight(X_AXIS, 0.0f, width));
301: assertEquals(BAD, view.getBreakWeight(X_AXIS, 0.0f,
302: width - 0.01f));
303: assertEquals(GOOD, view.getBreakWeight(X_AXIS, width, width));
304: assertEquals(BAD, view.getBreakWeight(X_AXIS, width,
305: width - 0.01f));
306: assertEquals(GOOD, view
307: .getBreakWeight(X_AXIS, width * 2, width));
308: assertEquals(BAD, view.getBreakWeight(X_AXIS, width * 2,
309: width - 0.01f));
310: assertEquals(GOOD, view
311: .getBreakWeight(X_AXIS, width * 3, width));
312: assertEquals(BAD, view.getBreakWeight(X_AXIS, width * 3,
313: width - 0.01f));
314: width = metrics.stringWidth(LEAF_TEXT.substring(0, 2));
315: assertEquals(GOOD, view.getBreakWeight(X_AXIS, 0.0f, width));
316: assertEquals(GOOD, view.getBreakWeight(X_AXIS, 0.0f,
317: width - 0.01f));
318: width = metrics.stringWidth(LEAF_TEXT.substring(0, 5));
319: assertEquals(EXCELLENT, view
320: .getBreakWeight(X_AXIS, 0.0f, width));
321: assertEquals(GOOD, view.getBreakWeight(X_AXIS, 0.0f,
322: width - 0.01f));
323: width = metrics.stringWidth(LEAF_TEXT.substring(0, 6));
324: assertEquals(EXCELLENT, view
325: .getBreakWeight(X_AXIS, 0.0f, width));
326: assertEquals(EXCELLENT, view.getBreakWeight(X_AXIS, 0.0f,
327: width - 0.01f));
328: }
329:
330: public void testGetBreakWeightY() {
331: width = metrics.getHeight();
332: assertEquals(BAD, view.getBreakWeight(Y_AXIS, 0.0f, width));
333: assertEquals(BAD, view.getBreakWeight(Y_AXIS, 0.0f,
334: width - 0.01f));
335: assertEquals(BAD, view.getBreakWeight(Y_AXIS, width, width));
336: assertEquals(BAD, view.getBreakWeight(Y_AXIS, width,
337: width - 0.01f));
338: assertEquals(GOOD, view.getBreakWeight(Y_AXIS, 0.0f,
339: width + 0.01f));
340: }
341:
342: public void testClone() {
343: view.setGlyphPainter(new EmptyPainter());
344: GlyphView clone = (GlyphView) view.clone();
345: assertEquals(view.getStartOffset(), clone.getStartOffset());
346: assertEquals(view.getEndOffset(), clone.getEndOffset());
347: assertSame(view.getElement(), clone.getElement());
348: assertSame(view.getGlyphPainter(), clone.getGlyphPainter());
349: }
350:
351: private DocumentEvent createEvent(final int offset,
352: final int length, final EventType type) {
353: return ((AbstractDocument) doc).new DefaultDocumentEvent(
354: offset, length, type);
355: }
356: }
|