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.html;
021:
022: import java.awt.Insets;
023: import java.io.StringReader;
024:
025: import javax.swing.BasicSwingTestCase;
026: import javax.swing.SizeRequirements;
027: import javax.swing.event.DocumentEvent;
028: import javax.swing.text.AttributeSet;
029: import javax.swing.text.Document;
030: import javax.swing.text.Element;
031: import javax.swing.text.GlyphView;
032: import javax.swing.text.PlainView;
033: import javax.swing.text.Style;
034: import javax.swing.text.StyleConstants;
035: import javax.swing.text.View;
036: import javax.swing.text.ViewFactory;
037: import javax.swing.text.GlyphView.GlyphPainter;
038: import javax.swing.text.ViewTestHelpers.ChildrenFactory;
039: import javax.swing.text.html.InlineViewTest.FixedPainter;
040:
041: public class BlockViewTest extends BasicSwingTestCase {
042: private class Event implements DocumentEvent {
043: public int getOffset() {
044: return block.getStartOffset();
045: }
046:
047: public int getLength() {
048: return block.getEndOffset() - block.getStartOffset();
049: }
050:
051: public Document getDocument() {
052: return doc;
053: }
054:
055: public EventType getType() {
056: return EventType.CHANGE;
057: }
058:
059: public ElementChange getChange(Element elem) {
060: return null;
061: }
062: }
063:
064: public static class InlineViewFactory implements ViewFactory {
065: public static final GlyphPainter painter = new FixedPainter();
066:
067: public View create(Element element) {
068: GlyphView result = new InlineView(element);
069: result.setGlyphPainter(painter);
070: return result;
071: }
072: }
073:
074: private class BlockViewImpl extends BlockView {
075: public BlockViewImpl(final Element element, final int axis) {
076: super (element, axis);
077: loadChildren();
078: }
079:
080: public ViewFactory getViewFactory() {
081: return factory;
082: }
083:
084: public void loadChildren() {
085: loadChildren(getViewFactory());
086: }
087:
088: public void layoutMinorAxis(final int targetSpan,
089: final int axis, final int[] offsets, final int[] spans) {
090: super .layoutMinorAxis(targetSpan, axis, offsets, spans);
091: }
092: }
093:
094: private static final int Y_AXIS = View.Y_AXIS;
095: private static final int X_AXIS = View.X_AXIS;
096:
097: private HTMLEditorKit kit;
098: private HTMLDocument doc;
099: private Element block;
100: private BlockView view;
101: private ViewFactory factory;
102: private AttributeSet attrs;
103:
104: protected void setUp() throws Exception {
105: super .setUp();
106: setIgnoreNotImplemented(true);
107: kit = new HTMLEditorKit();
108: doc = (HTMLDocument) kit.createDefaultDocument();
109: StringReader reader = new StringReader("<html><head></head>"
110: + "<body>" + "<p>Normal <em>em inside</em> paragraph."
111: + "</body></html>");
112: kit.read(reader, doc, 0);
113:
114: block = doc.getParagraphElement(10);
115: assertEquals(HTML.Tag.P.toString(), block.getName());
116:
117: factory = new InlineViewFactory();
118: view = new BlockViewImpl(block, Y_AXIS);
119: attrs = view.getAttributes();
120: doc.getStyleSheet().getStyleSheets()[0]
121: .addRule("p { margin-top: 15pt }");
122: }
123:
124: public void testBlockView() {
125: assertSame(block, view.getElement());
126: assertNotSame(block.getAttributes(), view.getAttributes());
127: assertEquals(block.getElementCount(), view.getViewCount());
128: }
129:
130: public void testGetMinimumSpan() {
131: assertEquals(view.getPreferredSpan(X_AXIS), view
132: .getMinimumSpan(X_AXIS), 0);
133: assertEquals(view.getPreferredSpan(Y_AXIS), view
134: .getMinimumSpan(Y_AXIS), 0);
135: }
136:
137: public void testGetPreferredSpan() {
138: assertEquals(getMaxChildSpan(X_AXIS), view
139: .getPreferredSpan(X_AXIS), 0);
140: assertEquals(0, (int) view.getPreferredSpan(Y_AXIS));
141: }
142:
143: public void testGetMaximumSpan() {
144: assertEquals(Integer.MAX_VALUE, view.getMaximumSpan(X_AXIS), 0);
145: assertEquals(0, (int) view.getMaximumSpan(Y_AXIS));
146: }
147:
148: public void testGetAlignment() {
149: factory = new ChildrenFactory();
150: ((ChildrenFactory) factory).makeFlexible();
151:
152: view = new BlockViewImpl(block, Y_AXIS);
153: assertEquals(0, view.getAlignment(X_AXIS), 0);
154: assertEquals(0, view.getAlignment(Y_AXIS), 0);
155: }
156:
157: public void testGetAlignmentFlexible() {
158: factory = new ChildrenFactory();
159: ((ChildrenFactory) factory).makeFlexible();
160: view = new BlockViewImpl(block, Y_AXIS);
161:
162: assertEquals(0, view.getAlignment(X_AXIS), 0);
163: assertEquals(0, view.getAlignment(Y_AXIS), 0);
164:
165: SizeRequirements r = view.calculateMajorAxisRequirements(
166: Y_AXIS, null);
167: assertEquals(0.5f, r.alignment, 0);
168:
169: r = view.calculateMajorAxisRequirements(X_AXIS, r);
170: assertEquals(0.5f, r.alignment, 0);
171: }
172:
173: public void testGetAttributes() {
174: assertEquals(2, attrs.getAttributeCount());
175: assertEquals("15pt", attrs.getAttribute(
176: CSS.Attribute.MARGIN_TOP).toString());
177: assertEquals(HTML.Tag.P.toString(), attrs
178: .getAttribute(AttributeSet.NameAttribute));
179:
180: assertEquals(15, StyleConstants.getSpaceAbove(attrs), 0f);
181: }
182:
183: public void testGetAttributesUpdate() {
184: assertEquals(2, attrs.getAttributeCount());
185: assertEquals("15pt", attrs.getAttribute(
186: CSS.Attribute.MARGIN_TOP).toString());
187: assertEquals(HTML.Tag.P.toString(), attrs
188: .getAttribute(AttributeSet.NameAttribute));
189: assertNull(attrs.getAttribute(CSS.Attribute.BACKGROUND_COLOR));
190:
191: doc.getStyleSheet().addRule("p { background-color: red }");
192: assertEquals(4, attrs.getAttributeCount());
193: assertEquals("red", attrs.getAttribute(
194: CSS.Attribute.BACKGROUND_COLOR).toString());
195: }
196:
197: public void testGetAttributesStyleSheet() {
198: final Marker ssMarker = new Marker();
199: view = new BlockView(block, Y_AXIS) {
200: protected StyleSheet getStyleSheet() {
201: ssMarker.setOccurred();
202: return super .getStyleSheet();
203: };
204: };
205: assertFalse(ssMarker.isOccurred());
206: view.getAttributes();
207: assertTrue(ssMarker.isOccurred());
208: }
209:
210: public void testGetAttributesSame() {
211: assertSame(attrs, view.getAttributes());
212: }
213:
214: public void testGetResizeWeight() {
215: assertEquals(1, view.getResizeWeight(X_AXIS));
216: assertEquals(0, view.getResizeWeight(Y_AXIS));
217: }
218:
219: public void testGetResizeWeightFlexible() {
220: factory = new ChildrenFactory();
221: ((ChildrenFactory) factory).makeFlexible();
222: view = new BlockViewImpl(block, Y_AXIS);
223:
224: assertEquals(1, view.getResizeWeight(X_AXIS));
225: assertEquals(isHarmony() ? 1 : 0, view.getResizeWeight(Y_AXIS));
226:
227: SizeRequirements r = view.calculateMajorAxisRequirements(
228: Y_AXIS, null);
229: assertEquals(44, r.minimum);
230: assertEquals(400, r.maximum);
231: assertEquals(44, (int) view.getMinimumSpan(Y_AXIS));
232: assertEquals(400, (int) view.getMaximumSpan(Y_AXIS));
233: }
234:
235: public void testChangedUpdate() {
236: final Marker propMarker = new Marker();
237: final Marker prefMarker = new Marker();
238: view = new BlockViewImpl(block, Y_AXIS) {
239: private int count;
240: private boolean flag;
241:
242: protected void setPropertiesFromAttributes() {
243: propMarker.setOccurred();
244: super .setPropertiesFromAttributes();
245: }
246:
247: public void preferenceChanged(View child, boolean width,
248: boolean height) {
249: prefMarker.setOccurred();
250: assertSame(getView(count), child);
251: if (isHarmony() || flag) {
252: count++;
253: }
254: flag = !flag;
255: prefMarker.setAuxiliary(new Integer(count));
256:
257: assertNotNull(child);
258: assertTrue(width);
259: assertTrue(height);
260: super .preferenceChanged(child, width, height);
261: }
262: };
263:
264: assertFalse(propMarker.isOccurred());
265: assertFalse(prefMarker.isOccurred());
266:
267: view.changedUpdate(new Event(), null, null);
268:
269: assertTrue(propMarker.isOccurred());
270: assertTrue(prefMarker.isOccurred());
271: assertEquals(view.getViewCount(), ((Integer) prefMarker
272: .getAuxiliary()).intValue());
273: }
274:
275: public void testChangedUpdateAttributes() {
276: final Marker viewAttrMarker = new Marker(true);
277: final StyleSheet ss = new StyleSheet() {
278: public AttributeSet getViewAttributes(final View v) {
279: viewAttrMarker.setOccurred();
280: return super .getViewAttributes(v);
281: }
282: };
283: view = new BlockView(block, View.Y_AXIS) {
284: protected StyleSheet getStyleSheet() {
285: return ss;
286: }
287: };
288:
289: attrs = view.getAttributes();
290: assertTrue(viewAttrMarker.isOccurred());
291: view.changedUpdate(new Event(), null, null);
292: assertTrue(viewAttrMarker.isOccurred());
293: assertNotSame(attrs, view.getAttributes());
294: }
295:
296: public void testSetParent() {
297: final Marker propertiesMarker = new Marker(true);
298: view = new BlockView(block, Y_AXIS) {
299: protected void setPropertiesFromAttributes() {
300: propertiesMarker.setOccurred();
301: super .setPropertiesFromAttributes();
302: }
303: };
304: assertFalse(propertiesMarker.isOccurred());
305: view.setParent(null);
306: assertFalse(propertiesMarker.isOccurred());
307:
308: view.setParent(new PlainView(doc.getDefaultRootElement()));
309: assertTrue(propertiesMarker.isOccurred());
310:
311: view.setParent(null);
312: assertFalse(propertiesMarker.isOccurred());
313: }
314:
315: public void testCalculateMajorAxisRequirements() {
316: SizeRequirements r = view.calculateMajorAxisRequirements(
317: Y_AXIS, null);
318: assertEquals(r.preferred, r.minimum);
319: assertEquals(0, r.preferred);
320: assertEquals(0, r.maximum);
321:
322: doc.getStyleSheet().addRule("p {width: 305pt}");
323: view.setPropertiesFromAttributes();
324: SizeRequirements sr = view.calculateMajorAxisRequirements(
325: Y_AXIS, r);
326: assertSame(r, sr);
327: assertEquals(0, r.minimum);
328: assertEquals(0, r.preferred);
329: assertEquals(0, r.maximum);
330:
331: doc.getStyleSheet().addRule("p {height: 40pt}");
332: view.setPropertiesFromAttributes();
333: view.calculateMajorAxisRequirements(Y_AXIS, r);
334: assertEquals(25, r.minimum);
335: assertEquals(25, r.preferred);
336: assertEquals(25, r.maximum);
337: }
338:
339: public void testCalculateMajorAxisRequirementsFlexible() {
340: factory = new ChildrenFactory();
341: ((ChildrenFactory) factory).makeFlexible();
342:
343: view = new BlockViewImpl(block, Y_AXIS);
344:
345: int minSpan = 0;
346: for (int i = 0; i < view.getViewCount(); i++) {
347: minSpan += (int) view.getView(i).getMinimumSpan(Y_AXIS);
348: }
349: assertEquals(44, minSpan);
350:
351: int prefSpan = 0;
352: for (int i = 0; i < view.getViewCount(); i++) {
353: prefSpan += (int) view.getView(i).getPreferredSpan(Y_AXIS);
354: }
355: assertEquals(112, prefSpan);
356:
357: int maxSpan = 0;
358: for (int i = 0; i < view.getViewCount(); i++) {
359: maxSpan += (int) view.getView(i).getMaximumSpan(Y_AXIS);
360: }
361: assertEquals(400, maxSpan);
362:
363: doc.getStyleSheet().addRule("p {height: 45pt}");
364: view.setPropertiesFromAttributes();
365: SizeRequirements r = view.calculateMajorAxisRequirements(
366: Y_AXIS, null);
367: assertEquals(44, r.minimum); // 45 - 15 def. margin = 30 < 44
368: assertEquals(isHarmony() ? 112 : 44, r.preferred);
369: assertEquals(400, r.maximum);
370:
371: doc.getStyleSheet().addRule("p {height: 60pt}");
372: view.setPropertiesFromAttributes();
373: view.calculateMajorAxisRequirements(Y_AXIS, r);
374: assertEquals(45, r.minimum); // 60 - 15 def. margin = 45 > 44
375: assertEquals(45, r.preferred);
376: assertEquals(45, r.maximum);
377: }
378:
379: public void testCalculateMinorAxisRequirements() {
380: SizeRequirements r = view.calculateMinorAxisRequirements(
381: X_AXIS, null);
382: assertEquals(r.preferred, r.minimum);
383: assertEquals((int) getMaxChildSpan(X_AXIS), r.preferred);
384: assertEquals(Integer.MAX_VALUE, r.maximum);
385:
386: doc.getStyleSheet().addRule("p {height: 40pt}");
387: view.setPropertiesFromAttributes();
388: SizeRequirements sr = view.calculateMinorAxisRequirements(
389: X_AXIS, r);
390: assertSame(r, sr);
391: assertEquals(r.preferred, r.minimum);
392: assertEquals((int) getMaxChildSpan(X_AXIS), r.preferred);
393: assertEquals(Integer.MAX_VALUE, r.maximum);
394:
395: doc.getStyleSheet().addRule("p {width: 305pt}");
396: view.setPropertiesFromAttributes();
397: view.calculateMinorAxisRequirements(X_AXIS, r);
398: assertEquals(r.preferred, r.minimum);
399: assertEquals(305, r.preferred);
400: assertEquals(305, r.maximum);
401: }
402:
403: public void testCalculateMinorAxisRequirementsFlexible() {
404: factory = new ChildrenFactory();
405: ((ChildrenFactory) factory).makeFlexible();
406:
407: view = new BlockViewImpl(block, Y_AXIS);
408:
409: int minSpan = 0;
410: for (int i = 0; i < view.getViewCount(); i++) {
411: minSpan = Math.max(minSpan, (int) view.getView(i)
412: .getMinimumSpan(X_AXIS));
413: }
414: assertEquals(50, minSpan);
415:
416: int prefSpan = 0;
417: for (int i = 0; i < view.getViewCount(); i++) {
418: prefSpan = Math.max(prefSpan, (int) view.getView(i)
419: .getPreferredSpan(X_AXIS));
420: }
421: assertEquals(100, prefSpan);
422:
423: doc.getStyleSheet().addRule("p {width: 46pt}");
424: view.setPropertiesFromAttributes();
425: SizeRequirements r = view.calculateMinorAxisRequirements(
426: X_AXIS, null);
427: assertEquals(50, r.minimum);
428: assertEquals(isHarmony() ? 100 : 50, r.preferred);
429: assertEquals(Integer.MAX_VALUE, r.maximum);
430:
431: doc.getStyleSheet().addRule("p {width: 146pt}");
432: view.setPropertiesFromAttributes();
433: view.calculateMinorAxisRequirements(X_AXIS, r);
434: assertEquals(146, r.minimum);
435: assertEquals(146, r.preferred);
436: assertEquals(146, r.maximum);
437: }
438:
439: public void testCalculateMinorAxisRequirementsOrthogonal() {
440: view = new BlockViewImpl(block, X_AXIS);
441: SizeRequirements r = view.calculateMinorAxisRequirements(
442: Y_AXIS, null);
443: assertEquals(r.preferred, r.minimum);
444: assertEquals(0, r.preferred);
445: assertEquals(Integer.MAX_VALUE, r.maximum);
446:
447: doc.getStyleSheet().addRule("p {width: 305pt}");
448: view.setPropertiesFromAttributes();
449: SizeRequirements sr = view.calculateMinorAxisRequirements(
450: Y_AXIS, r);
451: assertSame(r, sr);
452: assertEquals(r.preferred, r.minimum);
453: assertEquals(0, r.preferred);
454: assertEquals(Integer.MAX_VALUE, r.maximum);
455:
456: doc.getStyleSheet().addRule("p {height: 40pt}");
457: view.setPropertiesFromAttributes();
458: view.calculateMinorAxisRequirements(Y_AXIS, r);
459: assertEquals(r.preferred, r.minimum);
460: assertEquals(25, r.preferred); // 40 - 15 (def. top margin) = 25
461: assertEquals(25, r.maximum);
462: }
463:
464: public void testLayoutMinorAxis() {
465: final Marker marker = new Marker();
466: view = new BlockViewImpl(block, Y_AXIS) {
467: protected void baselineLayout(int targetSpan, int axis,
468: int[] offsets, int[] spans) {
469: marker.setOccurred();
470: super .baselineLayout(targetSpan, axis, offsets, spans);
471: }
472: };
473:
474: final int[] offsets = new int[view.getViewCount()];
475: final int[] spans = new int[view.getViewCount()];
476: final int target = 305;
477: ((BlockViewImpl) view).layoutMinorAxis(target, X_AXIS, offsets,
478: spans);
479: assertFalse(marker.isOccurred());
480: for (int i = 0; i < view.getViewCount(); i++) {
481: View child = view.getView(i);
482: assertEquals(0.0, view.getAlignment(X_AXIS), 0);
483: assertEquals((int) child.getPreferredSpan(X_AXIS), spans[i]);
484: assertEquals((target - spans[i]) / 2, offsets[i]);
485: }
486: }
487:
488: public void testLayoutMinorAxisFlexible() {
489: factory = new ChildrenFactory();
490: ((ChildrenFactory) factory).makeFlexible();
491:
492: view = new BlockViewImpl(block, Y_AXIS);
493:
494: final int[] offsets = new int[view.getViewCount()];
495: final int[] spans = new int[view.getViewCount()];
496: final int target = 305;
497: ((BlockViewImpl) view).layoutMinorAxis(target, X_AXIS, offsets,
498: spans);
499: for (int i = 0; i < view.getViewCount(); i++) {
500: View child = view.getView(i);
501: SizeRequirements sr = new SizeRequirements((int) child
502: .getMinimumSpan(X_AXIS), (int) child
503: .getPreferredSpan(X_AXIS), (int) child
504: .getMaximumSpan(X_AXIS), child.getAlignment(X_AXIS));
505: assertEquals(getChildSpan(target, sr), spans[i]);
506: assertEquals(getChildOffset(target, spans[i], sr),
507: offsets[i]);
508: }
509: }
510:
511: public void testLayoutMinorAxisFlexibleWide() {
512: factory = new ChildrenFactory();
513: ((ChildrenFactory) factory).makeFlexible();
514:
515: view = new BlockViewImpl(block, Y_AXIS);
516:
517: final int[] offsets = new int[view.getViewCount()];
518: final int[] spans = new int[view.getViewCount()];
519: final int target = 451;
520: ((BlockViewImpl) view).layoutMinorAxis(target, X_AXIS, offsets,
521: spans);
522: for (int i = 0; i < view.getViewCount(); i++) {
523: View child = view.getView(i);
524: SizeRequirements sr = new SizeRequirements((int) child
525: .getMinimumSpan(X_AXIS), (int) child
526: .getPreferredSpan(X_AXIS), (int) child
527: .getMaximumSpan(X_AXIS), child.getAlignment(X_AXIS));
528: assertEquals(getChildSpan(target, sr), spans[i]);
529: assertEquals(getChildOffset(target, spans[i], sr),
530: offsets[i]);
531: }
532: }
533:
534: public void testGetStyleSheet() {
535: assertSame(doc.getStyleSheet(), view.getStyleSheet());
536: }
537:
538: public void testSetPropertiesFromAttributes() {
539: final StyleSheet ss = doc.getStyleSheet();
540: final Style pStyle = ss.getRule("p");
541: assertEquals(2, pStyle.getAttributeCount());
542: assertEquals("15pt", pStyle.getAttribute(
543: CSS.Attribute.MARGIN_TOP).toString());
544:
545: final Marker insetMarker = new Marker(true);
546: final Insets insets = new Insets(0, 0, 0, 0);
547: view = new BlockViewImpl(block, Y_AXIS) {
548: protected void setParagraphInsets(AttributeSet attrs) {
549: fail("Unexpected call setParagraphInsets(AttributeSet)");
550: super .setParagraphInsets(attrs);
551: }
552:
553: protected void setInsets(short top, short left,
554: short bottom, short right) {
555: super .setInsets(top, left, bottom, right);
556: insetMarker.setOccurred();
557: insets.top = top;
558: insets.left = left;
559: insets.bottom = bottom;
560: insets.right = right;
561: }
562: };
563: view.setPropertiesFromAttributes();
564: assertTrue(insetMarker.isOccurred());
565: assertEquals(15, insets.top);
566: assertEquals(0, insets.left);
567: assertEquals(0, insets.bottom);
568: assertEquals(0, insets.right);
569:
570: ss.addRule("p { padding-right: 31px; margin-bottom: 3pt }");
571: view.setPropertiesFromAttributes();
572: assertEquals(15, insets.top);
573: assertEquals(0, insets.left);
574: assertEquals(3, insets.bottom);
575: assertEquals(40, insets.right);
576: }
577:
578: public void testSetPropertiesFromAttributesBoxPainter() {
579: final Marker boxMarker = new Marker();
580: final Marker listMarker = new Marker();
581: final StyleSheet ss = new StyleSheet() {
582: public BoxPainter getBoxPainter(final AttributeSet attr) {
583: boxMarker.setOccurred();
584: return super .getBoxPainter(attr);
585: }
586:
587: public ListPainter getListPainter(final AttributeSet attr) {
588: listMarker.setOccurred();
589: return null;
590: }
591: };
592: view = new BlockView(block, Y_AXIS) {
593: protected StyleSheet getStyleSheet() {
594: return ss;
595: }
596: };
597: assertFalse(boxMarker.isOccurred());
598: assertFalse(listMarker.isOccurred());
599: view.setPropertiesFromAttributes();
600: assertTrue(boxMarker.isOccurred());
601: assertFalse(listMarker.isOccurred());
602: }
603:
604: private int getChildSpan(final int targetSpan,
605: final SizeRequirements sr) {
606: return Math.max(sr.minimum, Math.min(targetSpan, sr.maximum));
607: }
608:
609: private int getChildOffset(final int targetSpan,
610: final int childSpan, final SizeRequirements sr) {
611: return (int) ((targetSpan - childSpan) * sr.alignment);
612: }
613:
614: private float getMaxChildSpan(final int axis) {
615: float result = 0;
616: for (int i = 0; i < view.getViewCount(); i++) {
617: result = Math.max(result, view.getView(i).getPreferredSpan(
618: axis));
619: }
620: return result;
621: }
622: }
|