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.Graphics;
024: import java.awt.Rectangle;
025: import java.awt.Shape;
026: import java.awt.geom.Rectangle2D;
027: import javax.swing.JComponent;
028: import javax.swing.text.Position.Bias;
029: import junit.framework.TestCase;
030:
031: public class ViewTest extends TestCase {
032: /**
033: * View class that simply overrides abstract methods of View class.
034: * No additional functionality is added.
035: */
036: public static class DisAbstractedView extends View {
037: /**
038: * Bounding shape. Used as the last parameter in
039: * modelToView, viewToModel.
040: */
041: static final Rectangle2D bounding = new Rectangle(2, 2);
042:
043: /**
044: * One of rectangles returned from modelToView.
045: */
046: static final Rectangle2D r1 = new Rectangle(0, 0, 1, 1);
047:
048: /**
049: * The second rectangle returned from modelToView.
050: */
051: static final Rectangle2D r2 = new Rectangle(1, 1, 1, 1);
052:
053: /**
054: *
055: * @param element
056: */
057: static final Rectangle2D r3;
058: static {
059: r3 = new Rectangle2D.Double();
060: Rectangle2D.union(r1, r2, r3);
061: }
062:
063: public DisAbstractedView(final Element element) {
064: super (element);
065: }
066:
067: @Override
068: public float getPreferredSpan(final int axis) {
069: return axis == X_AXIS ? 1.27f : 2.53f;
070: }
071:
072: @Override
073: public Shape modelToView(final int pos, final Shape shape,
074: final Bias bias) throws BadLocationException {
075: mtvBias = bias;
076: if (pos == 1) {
077: return r2;
078: }
079: return r1;
080: }
081:
082: @Override
083: public void paint(final Graphics g, final Shape shape) {
084: }
085:
086: @Override
087: public int viewToModel(final float x, final float y,
088: final Shape shape, final Bias[] biasReturn) {
089: // Save the parameters
090: viewToModelParams.x = x;
091: viewToModelParams.y = y;
092: viewToModelParams.shape = shape;
093: viewToModelParams.bias = biasReturn;
094: return 0;
095: }
096: }
097:
098: private static class ResizableView extends DisAbstractedView {
099: public ResizableView(final Element element) {
100: super (element);
101: }
102:
103: @Override
104: public int getResizeWeight(final int axis) {
105: return 1;
106: }
107: }
108:
109: /**
110: * Class to store parameters passed to viewToModel method. It is used
111: * to assert the parameters are the expected ones.
112: */
113: private static class ViewToModelParams {
114: public Bias[] bias;
115:
116: public Shape shape;
117:
118: public float x;
119:
120: public float y;
121: }
122:
123: boolean containerGetGraphicsCalled;
124:
125: // Used in testPreferenceChanged
126: boolean preferenceChangedCalledOnParent;
127:
128: View preferenceChangedChild;
129:
130: boolean revalidateCalled;
131:
132: boolean tooltipGetViewCalled;
133:
134: boolean tooltipGetViewIndexCalled;
135:
136: /**
137: * Document shared among tests.
138: */
139: private Document doc;
140:
141: /**
142: * Paragraph element shared among tests. This is the second line of
143: * text in the document.
144: */
145: private Element line;
146:
147: /**
148: * View under which tests are run.
149: */
150: private View view;
151:
152: /**
153: * Bias passes to modelToView method in the last call.
154: */
155: private static Bias mtvBias;
156:
157: /**
158: * Parameters passed to viewToModel method.
159: */
160: private static ViewToModelParams viewToModelParams;
161:
162: public void testBreakView() {
163: assertSame(view, view.breakView(View.X_AXIS, line
164: .getStartOffset() + 1, 4, 4));
165: }
166:
167: public void testCreateFragment() {
168: assertSame(view, view.createFragment(line.getStartOffset() + 1,
169: line.getEndOffset() - 1));
170: }
171:
172: public void testGetAlignment() {
173: assertEquals(0.5f, view.getAlignment(View.X_AXIS), 0.000001f);
174: assertEquals(0.5f, view.getAlignment(View.Y_AXIS), 0.000001f);
175: assertEquals(0.5f, view.getAlignment(-10), 0.000001f);
176: assertEquals(0.5f, view.getAlignment(10), 0.000001f);
177: }
178:
179: public void testGetAttributes() {
180: assertSame(line.getAttributes(), view.getAttributes());
181: }
182:
183: /**
184: * Tests <code>getBreakWeight</code> with default view setup.
185: */
186: public void testGetBreakWeight01() {
187: final float maxX = view.getMaximumSpan(View.X_AXIS); // = preferredSpan
188: final float maxY = view.getMaximumSpan(View.Y_AXIS);
189: assertEquals(maxX, view.getPreferredSpan(View.X_AXIS), 0.0001f);
190: // By default return Bad, but...
191: assertEquals(View.BadBreakWeight, view.getBreakWeight(
192: View.X_AXIS, 0.0f, maxX));
193: assertEquals(View.BadBreakWeight, view.getBreakWeight(
194: View.Y_AXIS, 0.0f, maxY));
195: // ...but Good when length where to break is greater than
196: // the length of the view
197: assertEquals(View.GoodBreakWeight, view.getBreakWeight(
198: View.X_AXIS, 0.0f, maxX + 0.01f));
199: assertEquals(View.GoodBreakWeight, view.getBreakWeight(
200: View.Y_AXIS, 0.0f, maxY + 0.01f));
201: }
202:
203: /**
204: * Tests <code>getBreakWeight</code> with resizable setup.
205: */
206: public void testGetBreakWeight02() {
207: view = new ResizableView(line);
208: final float maxX = view.getPreferredSpan(View.X_AXIS);
209: final float maxY = view.getPreferredSpan(View.Y_AXIS);
210: // By default return Bad, but...
211: assertEquals(View.BadBreakWeight, view.getBreakWeight(
212: View.X_AXIS, 0.0f, maxX));
213: assertEquals(View.BadBreakWeight, view.getBreakWeight(
214: View.Y_AXIS, 0.0f, maxY));
215: // ...but Good when length where to break is greater than
216: // the length of the view
217: assertEquals(View.GoodBreakWeight, view.getBreakWeight(
218: View.X_AXIS, 0.0f, maxX + 0.01f));
219: assertEquals(View.GoodBreakWeight, view.getBreakWeight(
220: View.Y_AXIS, 0.0f, maxY + 0.01f));
221: }
222:
223: public void testGetChildAllocation() {
224: // Always returns null whatever parameters are
225: assertNull(view.getChildAllocation(0, null));
226: assertNull(view.getChildAllocation(0, new Rectangle()));
227: assertNull(view.getChildAllocation(2, new Rectangle()));
228: }
229:
230: public void testGetContainer() {
231: assertNull(view.getContainer());
232: }
233:
234: public void testGetDocument() {
235: assertSame(doc, view.getDocument());
236: }
237:
238: public void testGetElement() {
239: assertSame(line, view.getElement());
240: }
241:
242: public void testGetEndOffset() throws BadLocationException {
243: assertEquals(12, view.getEndOffset());
244: doc.insertString(0, "line\n", null);
245: assertEquals(17, view.getEndOffset());
246: }
247:
248: public void testGetGraphics() {
249: view = new DisAbstractedView(doc.getDefaultRootElement()
250: .getElement(0)) {
251: @Override
252: public Container getContainer() {
253: return new JComponent() {
254: private static final long serialVersionUID = 1L;
255:
256: @Override
257: public Graphics getGraphics() {
258: containerGetGraphicsCalled = true;
259: return null;
260: }
261: };
262: }
263: };
264: assertFalse(containerGetGraphicsCalled);
265: assertNull(view.getGraphics());
266: assertTrue(containerGetGraphicsCalled);
267: }
268:
269: /**
270: * Tests <code>getMaximumSpan</code> with default view setup.
271: */
272: public void testGetMaximumSpan01() {
273: assertEquals(view.getPreferredSpan(View.X_AXIS), view
274: .getMaximumSpan(View.X_AXIS), 0.000001f);
275: assertEquals(view.getPreferredSpan(View.Y_AXIS), view
276: .getMaximumSpan(View.Y_AXIS), 0.000001f);
277: }
278:
279: /**
280: * Tests <code>getMaximumSpan</code> with resizable view.
281: */
282: public void testGetMaximumSpan02() {
283: view = new ResizableView(line);
284: assertEquals(Integer.MAX_VALUE, view
285: .getMaximumSpan(View.X_AXIS), 0.000001f);
286: assertEquals(Integer.MAX_VALUE, view
287: .getMaximumSpan(View.Y_AXIS), 0.000001f);
288: }
289:
290: /**
291: * Tests <code>getMinimumSpan</code> with default view setup.
292: */
293: public void testGetMinimumSpan01() {
294: assertEquals(view.getPreferredSpan(View.X_AXIS), view
295: .getMinimumSpan(View.X_AXIS), 0.000001f);
296: assertEquals(view.getPreferredSpan(View.Y_AXIS), view
297: .getMinimumSpan(View.Y_AXIS), 0.000001f);
298: }
299:
300: /**
301: * Tests <code>getMinimumSpan</code> with resizable view.
302: */
303: public void testGetMinimumSpan02() {
304: view = new ResizableView(line);
305: assertEquals(0.0f, view.getMinimumSpan(View.X_AXIS), 0.000001f);
306: assertEquals(0.0f, view.getMinimumSpan(View.Y_AXIS), 0.000001f);
307: }
308:
309: public void testGetParent() {
310: assertNull(view.getParent());
311: View parent = getLine1View(doc);
312: view.setParent(parent);
313: assertSame(parent, view.getParent());
314: }
315:
316: public void testGetResizeWeight() {
317: assertEquals(0, view.getResizeWeight(View.X_AXIS));
318: assertEquals(0, view.getResizeWeight(View.Y_AXIS));
319: }
320:
321: public void testGetStartOffset() throws BadLocationException {
322: assertEquals(6, view.getStartOffset());
323: doc.insertString(0, "line\n", null);
324: assertEquals(11, view.getStartOffset());
325: }
326:
327: public void testGetToolTipText() {
328: view = new DisAbstractedView(doc.getDefaultRootElement()
329: .getElement(0)) {
330: @Override
331: public View getView(final int index) {
332: tooltipGetViewCalled = true;
333: return super .getView(index);
334: }
335:
336: @Override
337: public int getViewIndex(final float x, final float y,
338: final Shape allocation) {
339: tooltipGetViewIndexCalled = true;
340: return super .getViewIndex(x, y, allocation);
341: }
342: };
343: assertNull(view.getToolTipText(0.0f, 0.0f, new Rectangle(2, 2)));
344: // getToolTipText calls getViewIndex to get child at this location
345: assertTrue(tooltipGetViewIndexCalled);
346: // As there's no children at all, getView didn't get called and null
347: // is return (which is asserted above)
348: assertFalse(tooltipGetViewCalled);
349: }
350:
351: public void testGetView() {
352: // Always returns null as there are no children
353: assertNull(view.getView(-1));
354: assertNull(view.getView(0));
355: assertNull(view.getView(10));
356: }
357:
358: public void testGetViewCount() {
359: assertEquals(0, view.getViewCount());
360: view.append(getLine1View(doc));
361: // View does not have children by default, nothing is changed
362: assertEquals(0, view.getViewCount());
363: }
364:
365: public void testGetViewFactory() {
366: assertNull(view.getViewFactory());
367: }
368:
369: /*
370: * Class under test for int getViewIndex(float, float, Shape)
371: */
372: public void testGetViewIndexfloatfloatShape() {
373: // As this view has no children, the method always returns -1
374: assertEquals(-1, view.getViewIndex(0.0f, 0.0f, null));
375: assertEquals(-1, view.getViewIndex(0.0f, 0.0f, new Rectangle(5,
376: 5)));
377: assertEquals(-1, view.getViewIndex(0.5f, 0.5f, new Rectangle(5,
378: 5)));
379: }
380:
381: /*
382: * Class under test for int getViewIndex(int, Position.Bias)
383: */
384: public void testGetViewIndexintBias() {
385: // The method should return -1
386: assertEquals(-1, view.getViewIndex(0, Bias.Forward));
387: assertEquals(-1, view.getViewIndex(0, Bias.Backward));
388: assertEquals(-1, view.getViewIndex(7, Bias.Forward));
389: assertEquals(-1, view.getViewIndex(7, Bias.Backward));
390: }
391:
392: public void testIsVisible() {
393: assertTrue(view.isVisible());
394: }
395:
396: /*
397: * Class under test for
398: * Shape modelToView(int, Position.Bias, int, Position.Bias, Shape)
399: */
400: public void testModelToViewintBiasintBiasShape()
401: throws BadLocationException {
402: Shape a = view.modelToView(1, Bias.Forward, 2, Bias.Forward,
403: DisAbstractedView.bounding);
404: assertEquals(DisAbstractedView.r3, a);
405: }
406:
407: /*
408: * Class under test for Shape modelToView(int, Shape)
409: */
410: @SuppressWarnings("deprecation")
411: public void testModelToViewintShape() throws BadLocationException {
412: Shape a = view.modelToView(0, DisAbstractedView.bounding);
413: assertSame(DisAbstractedView.r1, a);
414: assertEquals(Bias.Forward, mtvBias);
415: }
416:
417: public void testPreferenceChanged() {
418: View parent = new DisAbstractedView(doc.getDefaultRootElement()) {
419: @Override
420: public Container getContainer() {
421: return new JTextComponent() {
422: private static final long serialVersionUID = 1L;
423:
424: @Override
425: public void revalidate() {
426: revalidateCalled = true;
427: super .revalidate();
428: }
429: };
430: }
431:
432: @Override
433: public void preferenceChanged(final View child,
434: final boolean w, final boolean h) {
435: preferenceChangedCalledOnParent = true;
436: preferenceChangedChild = child;
437: // Assert the conditions are true
438: assertFalse(revalidateCalled);
439: assertNull(getParent());
440: // Call superclass
441: super .preferenceChanged(child, w, h);
442: // Component's revalidate method is still not called
443: assertFalse(revalidateCalled);
444: }
445: };
446: View child = getLine1View(doc);
447: // Assert we get no exceptions or errors
448: assertNull(view.getParent());
449: view.preferenceChanged(child, true, false);
450: assertFalse(preferenceChangedCalledOnParent);
451: // Set parent and test, that parent gets called
452: view.setParent(parent);
453: view.preferenceChanged(child, true, false);
454: assertTrue(preferenceChangedCalledOnParent);
455: // The view on which we called the method is the child for parent
456: assertSame(view, preferenceChangedChild);
457: }
458:
459: public void testSetParent() {
460: View parent = getLine1View(doc);
461: view.setParent(parent);
462: assertSame(parent, view.getParent());
463: view.setParent(null);
464: assertNull(view.getParent());
465: }
466:
467: public void testSetSize() {
468: // XXX View.setSize does nothing?
469: view.setSize(10f, 20f);
470: //assertEquals(10f, /*0.0*/view.getMaximumSpan(View.X_AXIS), 0.00001f);
471: //assertEquals(20f, /*0.0*/view.getMaximumSpan(View.Y_AXIS), 0.00001f);
472: }
473:
474: public void testView() {
475: View v = new DisAbstractedView(line);
476: assertSame(line, v.getElement());
477: assertSame(doc, v.getDocument());
478: v = new DisAbstractedView(null);
479: assertNull(v.getElement());
480: try {
481: assertNull(v.getDocument());
482: fail("This causes the exception 'cause element is used "
483: + "to get the document");
484: } catch (NullPointerException e) {
485: }
486: try {
487: assertEquals(0, v.getStartOffset());
488: fail("This causes the exception 'cause element is used "
489: + "to get the offset");
490: } catch (NullPointerException e) {
491: }
492: }
493:
494: /*
495: * Class under test for int viewToModel(float, float, Shape)
496: */
497: @SuppressWarnings("deprecation")
498: public void testViewToModelfloatfloatShape() {
499: Rectangle r = new Rectangle();
500: view.viewToModel(0.1f, 0.2f, r);
501: assertEquals(0.1f, viewToModelParams.x, 0.00001f);
502: assertEquals(0.2f, viewToModelParams.y, 0.00001f);
503: assertSame(r, viewToModelParams.shape);
504: assertEquals(1, viewToModelParams.bias.length);
505: assertEquals(Bias.Forward, viewToModelParams.bias[0]);
506: }
507:
508: /*
509: * @see TestCase#setUp()
510: */
511: @Override
512: protected void setUp() throws Exception {
513: super .setUp();
514: doc = new PlainDocument();
515: doc.insertString(0, "01234\nabcde", null);
516: line = doc.getDefaultRootElement().getElement(1);
517: view = new DisAbstractedView(line);
518: viewToModelParams = new ViewToModelParams();
519: mtvBias = null;
520: }
521:
522: /**
523: * Creates a new view for first line of text within the document.
524: * @return view for line 1
525: */
526: static final View getLine1View(final Document doc) {
527: return new DisAbstractedView(doc.getDefaultRootElement()
528: .getElement(0));
529: }
530: }
|