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.Graphics;
023: import java.awt.Shape;
024: import java.io.StringReader;
025:
026: import javax.swing.BasicSwingTestCase;
027: import javax.swing.event.DocumentEvent;
028: import javax.swing.text.AttributeSet;
029: import javax.swing.text.BadLocationException;
030: import javax.swing.text.DefaultStyledDocument;
031: import javax.swing.text.Document;
032: import javax.swing.text.Element;
033: import javax.swing.text.GlyphView;
034: import javax.swing.text.SimpleAttributeSet;
035: import javax.swing.text.StyleConstants;
036: import javax.swing.text.StyledDocument;
037: import javax.swing.text.TabExpander;
038: import javax.swing.text.View;
039: import javax.swing.text.GlyphView.GlyphPainter;
040: import javax.swing.text.Position.Bias;
041:
042: public class InlineViewTest extends BasicSwingTestCase {
043: public static class FixedPainter extends GlyphPainter {
044: public static final int CHAR_WIDTH = 7;
045:
046: public float getSpan(GlyphView v, int startOffset,
047: int endOffset, TabExpander tabExpander, float x) {
048: return CHAR_WIDTH * (endOffset - startOffset);
049: }
050:
051: public int getBoundedPosition(GlyphView v, int startOffset,
052: float x, float len) {
053: int result = (int) len / CHAR_WIDTH + startOffset;
054: return result <= v.getEndOffset() ? result : v
055: .getEndOffset();
056: }
057:
058: public float getHeight(GlyphView v) {
059: return 0;
060: }
061:
062: public float getAscent(GlyphView v) {
063: return 0;
064: }
065:
066: public float getDescent(GlyphView v) {
067: return 0;
068: }
069:
070: public void paint(GlyphView v, Graphics g, Shape alloc,
071: int startOffset, int endOffset) {
072: }
073:
074: public Shape modelToView(GlyphView v, int offset, Bias bias,
075: Shape alloc) throws BadLocationException {
076: return null;
077: }
078:
079: public int viewToModel(GlyphView v, float x, float y,
080: Shape alloc, Bias[] biasReturn) {
081: return -1;
082: }
083: }
084:
085: private class Event implements DocumentEvent {
086: public int getOffset() {
087: return inline.getStartOffset() + 1;
088: }
089:
090: public int getLength() {
091: return inline.getEndOffset() - inline.getStartOffset() - 2;
092: }
093:
094: public Document getDocument() {
095: return doc;
096: }
097:
098: public EventType getType() {
099: return null;
100: }
101:
102: public ElementChange getChange(final Element elem) {
103: return null;
104: }
105: }
106:
107: private HTMLEditorKit kit;
108: private HTMLDocument doc;
109: private Element inline;
110: private InlineView view;
111: private AttributeSet attrs;
112:
113: private int startOffset;
114: private String text;
115: private int whitespace;
116:
117: protected void setUp() throws Exception {
118: super .setUp();
119: setIgnoreNotImplemented(true);
120: kit = new HTMLEditorKit();
121: doc = (HTMLDocument) kit.createDefaultDocument();
122: StringReader reader = new StringReader("<html><head></head>"
123: + "<body>" + "<p>Normal paragraph: <em>em inside</em>"
124: + " paragraph." + "</body></html>");
125: kit.read(reader, doc, 0);
126:
127: inline = doc.getCharacterElement(20);
128: assertNotNull(inline.getAttributes().getAttribute(HTML.Tag.EM));
129:
130: view = new InlineView(inline);
131: attrs = view.getAttributes();
132:
133: startOffset = inline.getStartOffset();
134: text = doc.getText(startOffset, inline.getEndOffset()
135: - startOffset);
136: whitespace = text.indexOf(' ');
137: }
138:
139: public void testInlineView() {
140: assertSame(inline, view.getElement());
141: assertNotSame(inline.getAttributes(), view.getAttributes());
142: }
143:
144: public void testInlineViewUponParagraph()
145: throws BadLocationException {
146: final Element paragraph = doc.getParagraphElement(20);
147: view = new InlineView(paragraph);
148: assertSame(paragraph, view.getElement());
149: assertNotSame(paragraph.getAttributes(), view.getAttributes());
150: }
151:
152: public void testInlineViewUponStyledDocument()
153: throws BadLocationException {
154: final StyledDocument styledDoc = new DefaultStyledDocument();
155: styledDoc.insertString(0, "a simple paragraph", null);
156: inline = styledDoc.getCharacterElement(1);
157: testExceptionalCase(new ClassCastCase() {
158: public void exceptionalAction() throws Exception {
159: new InlineView(inline);
160: }
161:
162: public String expectedExceptionMessage() {
163: return styledDoc.getClass().getName();
164: }
165: });
166: }
167:
168: public void testGetAttributes() {
169: assertEquals(2, attrs.getAttributeCount());
170: assertEquals("italic", attrs.getAttribute(
171: CSS.Attribute.FONT_STYLE).toString());
172: assertEquals(HTML.Tag.EM.toString(), attrs
173: .getAttribute(AttributeSet.NameAttribute));
174:
175: assertTrue(StyleConstants.isItalic(attrs));
176: }
177:
178: public void testGetAttributesUpdate() {
179: assertEquals(2, attrs.getAttributeCount());
180: assertEquals("italic", attrs.getAttribute(
181: CSS.Attribute.FONT_STYLE).toString());
182: assertEquals(HTML.Tag.EM.toString(), attrs
183: .getAttribute(AttributeSet.NameAttribute));
184: assertNull(attrs.getAttribute(CSS.Attribute.BACKGROUND_COLOR));
185:
186: doc.getStyleSheet().addRule("em { background-color: white }");
187: assertEquals(4, attrs.getAttributeCount());
188: assertEquals("white", attrs.getAttribute(
189: CSS.Attribute.BACKGROUND_COLOR).toString());
190: }
191:
192: public void testGetAttributesStyleSheet() {
193: final Marker ssMarker = new Marker();
194: view = new InlineView(inline) {
195: protected StyleSheet getStyleSheet() {
196: ssMarker.setOccurred();
197: return super .getStyleSheet();
198: };
199: };
200: assertTrue(ssMarker.isOccurred());
201: ssMarker.reset();
202: view.getAttributes();
203: assertFalse(ssMarker.isOccurred());
204: }
205:
206: public void testGetAttributesSame() {
207: assertSame(attrs, view.getAttributes());
208: }
209:
210: public void testGetBreakWeight() throws BadLocationException {
211: view.setGlyphPainter(new FixedPainter());
212: assertNull(attrs.getAttribute(CSS.Attribute.WHITE_SPACE));
213:
214: assertEquals(View.BadBreakWeight, view.getBreakWeight(
215: View.X_AXIS, startOffset,
216: FixedPainter.CHAR_WIDTH - 0.01f));
217: assertEquals(View.GoodBreakWeight, view.getBreakWeight(
218: View.X_AXIS, startOffset, FixedPainter.CHAR_WIDTH));
219:
220: assertEquals(View.GoodBreakWeight, view.getBreakWeight(
221: View.X_AXIS, startOffset, FixedPainter.CHAR_WIDTH
222: * whitespace));
223:
224: assertEquals(View.ExcellentBreakWeight, view.getBreakWeight(
225: View.X_AXIS, startOffset, FixedPainter.CHAR_WIDTH
226: * (whitespace + 1)));
227: }
228:
229: public void testGetBreakWeightNowrap() throws BadLocationException {
230: view.setGlyphPainter(new FixedPainter());
231:
232: assertNull(attrs.getAttribute(CSS.Attribute.WHITE_SPACE));
233: doc.getStyleSheet().addRule("em { white-space: nowrap }");
234: view.setPropertiesFromAttributes();
235: assertNotNull(attrs.getAttribute(CSS.Attribute.WHITE_SPACE));
236:
237: assertEquals(View.BadBreakWeight, view.getBreakWeight(
238: View.X_AXIS, startOffset,
239: FixedPainter.CHAR_WIDTH - 0.01f));
240: assertEquals(View.BadBreakWeight, view.getBreakWeight(
241: View.X_AXIS, startOffset, FixedPainter.CHAR_WIDTH));
242:
243: assertEquals(View.BadBreakWeight, view.getBreakWeight(
244: View.X_AXIS, startOffset, FixedPainter.CHAR_WIDTH
245: * whitespace));
246:
247: assertEquals(View.BadBreakWeight, view.getBreakWeight(
248: View.X_AXIS, startOffset, FixedPainter.CHAR_WIDTH
249: * (whitespace + 1)));
250: }
251:
252: public void testBreakView() throws BadLocationException {
253: view.setGlyphPainter(new FixedPainter());
254: assertNull(attrs.getAttribute(CSS.Attribute.WHITE_SPACE));
255:
256: View fragment = view.breakView(View.X_AXIS, startOffset, 0,
257: FixedPainter.CHAR_WIDTH - 0.01f);
258: assertTrue(fragment instanceof InlineView);
259: assertNotSame(view, fragment);
260: assertEquals(view.getStartOffset(), fragment.getStartOffset());
261: assertEquals(view.getEndOffset(), fragment.getEndOffset());
262:
263: fragment = view.breakView(View.X_AXIS, startOffset, 0,
264: FixedPainter.CHAR_WIDTH);
265: assertEquals(view.getStartOffset(), fragment.getStartOffset());
266: assertEquals(view.getStartOffset() + 1, fragment.getEndOffset());
267:
268: fragment = view.breakView(View.X_AXIS, startOffset, 0,
269: FixedPainter.CHAR_WIDTH * (whitespace + 1));
270: assertEquals(view.getStartOffset(), fragment.getStartOffset());
271: assertEquals(view.getStartOffset() + whitespace + 1, fragment
272: .getEndOffset());
273: }
274:
275: public void testBreakViewNowrap() {
276: view.setGlyphPainter(new FixedPainter());
277: doc.getStyleSheet().addRule("em { white-space: nowrap }");
278: view.setPropertiesFromAttributes();
279: assertNotNull(attrs.getAttribute(CSS.Attribute.WHITE_SPACE));
280:
281: View fragment = view.breakView(View.X_AXIS, startOffset, 0,
282: FixedPainter.CHAR_WIDTH - 0.01f);
283: assertTrue(fragment instanceof InlineView);
284: if (isHarmony()) {
285: // The view is not breakable
286: // if the value of 'white-space' is 'nowrap'
287: assertSame(view, fragment);
288: return;
289: }
290: assertNotSame(view, fragment);
291: assertEquals(view.getStartOffset(), fragment.getStartOffset());
292: assertEquals(view.getEndOffset(), fragment.getEndOffset());
293:
294: fragment = view.breakView(View.X_AXIS, startOffset, 0,
295: FixedPainter.CHAR_WIDTH);
296: assertEquals(view.getStartOffset(), fragment.getStartOffset());
297: assertEquals(view.getStartOffset() + 1, fragment.getEndOffset());
298:
299: fragment = view.breakView(View.X_AXIS, startOffset, 0,
300: FixedPainter.CHAR_WIDTH * (whitespace + 1));
301: assertEquals(view.getStartOffset(), fragment.getStartOffset());
302: assertEquals(view.getStartOffset() + whitespace + 1, fragment
303: .getEndOffset());
304: }
305:
306: public void testChangedUpdate() {
307: final Marker prefChanged = new Marker();
308: final Marker setProps = new Marker();
309: view = new InlineView(inline) {
310: public void preferenceChanged(View child, boolean width,
311: boolean height) {
312: prefChanged.setOccurred();
313: assertNull(child);
314: assertTrue(width);
315: assertTrue(height);
316: super .preferenceChanged(child, width, height);
317: }
318:
319: protected void setPropertiesFromAttributes() {
320: setProps.setOccurred();
321: super .setPropertiesFromAttributes();
322: }
323: };
324: assertFalse(prefChanged.isOccurred());
325: assertFalse(setProps.isOccurred());
326:
327: view.changedUpdate(new Event(), null, null);
328: assertTrue(prefChanged.isOccurred());
329: assertFalse(setProps.isOccurred());
330: }
331:
332: public void testChangedUpdateAttributes() {
333: final Marker viewAttrMarker = new Marker(true);
334: final StyleSheet ss = new StyleSheet() {
335: public AttributeSet getViewAttributes(final View v) {
336: viewAttrMarker.setOccurred();
337: return super .getViewAttributes(v);
338: }
339: };
340: view = new InlineView(inline) {
341: protected StyleSheet getStyleSheet() {
342: return ss;
343: }
344: };
345:
346: assertTrue(viewAttrMarker.isOccurred());
347: attrs = view.getAttributes();
348: view.changedUpdate(new Event(), null, null);
349: assertTrue(viewAttrMarker.isOccurred());
350: assertNotSame(attrs, view.getAttributes());
351: }
352:
353: public void testInsertUpdate() {
354: final Marker prefChanged = new Marker();
355: final Marker setProps = new Marker();
356: view = new InlineView(inline) {
357: public void preferenceChanged(View child, boolean width,
358: boolean height) {
359: prefChanged.setOccurred();
360: assertNull(child);
361: assertTrue(width);
362: assertFalse(height);
363: super .preferenceChanged(child, width, height);
364: }
365:
366: protected void setPropertiesFromAttributes() {
367: setProps.setOccurred();
368: super .setPropertiesFromAttributes();
369: }
370: };
371: assertFalse(prefChanged.isOccurred());
372: assertFalse(setProps.isOccurred());
373:
374: view.insertUpdate(new Event(), null, null);
375: assertTrue(prefChanged.isOccurred());
376: assertFalse(setProps.isOccurred());
377: }
378:
379: public void testRemoveUpdate() {
380: final Marker prefChanged = new Marker();
381: final Marker setProps = new Marker();
382: view = new InlineView(inline) {
383: public void preferenceChanged(View child, boolean width,
384: boolean height) {
385: prefChanged.setOccurred();
386: assertNull(child);
387: assertTrue(width);
388: assertFalse(height);
389: super .preferenceChanged(child, width, height);
390: }
391:
392: protected void setPropertiesFromAttributes() {
393: setProps.setOccurred();
394: super .setPropertiesFromAttributes();
395: }
396: };
397: assertFalse(prefChanged.isOccurred());
398: assertFalse(setProps.isOccurred());
399:
400: view.removeUpdate(new Event(), null, null);
401: assertTrue(prefChanged.isOccurred());
402: assertFalse(setProps.isOccurred());
403: }
404:
405: public void testSetPropertiesFromAttributes() {
406: assertTrue(view.getFont().isItalic());
407: assertFalse(view.isUnderline());
408: doc.getStyleSheet()
409: .addRule("em { text-decoration: underline }");
410: assertFalse(view.isUnderline());
411: view.setPropertiesFromAttributes();
412: assertTrue(view.isUnderline());
413: }
414:
415: public void testSetPropertiesFromAttributesBoxPainter() {
416: final Marker boxMarker = new Marker();
417: final Marker listMarker = new Marker();
418: final StyleSheet ss = new StyleSheet() {
419: public BoxPainter getBoxPainter(final AttributeSet attr) {
420: boxMarker.setOccurred();
421: return null;
422: }
423:
424: public ListPainter getListPainter(final AttributeSet attr) {
425: listMarker.setOccurred();
426: return null;
427: }
428: };
429: view = new InlineView(inline) {
430: protected StyleSheet getStyleSheet() {
431: return ss;
432: }
433: };
434: assertFalse(boxMarker.isOccurred());
435: assertFalse(listMarker.isOccurred());
436: view.setPropertiesFromAttributes();
437: assertFalse(boxMarker.isOccurred());
438: assertFalse(listMarker.isOccurred());
439: }
440:
441: public void testSetPropertiesFromAttributesAttributes() {
442: final Marker verticalAlign = new Marker();
443: final Marker textDecoration = new Marker();
444: final Marker whiteSpace = new Marker();
445: view = new InlineView(inline) {
446: private AttributeSet attributes;
447:
448: public AttributeSet getAttributes() {
449: if (attributes == null) {
450: attributes = new SimpleAttributeSet(super
451: .getAttributes()) {
452: public Object getAttribute(Object name) {
453: if (name == CSS.Attribute.VERTICAL_ALIGN) {
454: verticalAlign.setOccurred();
455: } else if (name == CSS.Attribute.TEXT_DECORATION) {
456: textDecoration.setOccurred();
457: } else if (name == CSS.Attribute.WHITE_SPACE) {
458: whiteSpace.setOccurred();
459: }
460: return super .getAttribute(name);
461: }
462: };
463: }
464: return attributes;
465: }
466: };
467: view.setPropertiesFromAttributes();
468: assertTrue(whiteSpace.isOccurred());
469: if (isHarmony()) {
470: assertFalse(verticalAlign.isOccurred());
471: assertFalse(textDecoration.isOccurred());
472: } else {
473: assertTrue(verticalAlign.isOccurred());
474: assertTrue(textDecoration.isOccurred());
475: }
476: }
477:
478: public void testGetStyleSheet() {
479: assertSame(doc.getStyleSheet(), view.getStyleSheet());
480: }
481:
482: }
|