1. /*
  2. * @(#)InlineView.java 1.22 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.text.html;
  8. import java.awt.Container;
  9. import java.awt.Shape;
  10. import java.awt.FontMetrics;
  11. import java.text.BreakIterator;
  12. import javax.swing.event.DocumentEvent;
  13. import javax.swing.text.*;
  14. /**
  15. * Displays the <dfn>inline element</dfn> styles
  16. * based upon css attributes.
  17. *
  18. * @author Timothy Prinzing
  19. * @version 1.22 01/23/03
  20. */
  21. public class InlineView extends LabelView {
  22. /**
  23. * Constructs a new view wrapped on an element.
  24. *
  25. * @param elem the element
  26. */
  27. public InlineView(Element elem) {
  28. super(elem);
  29. StyleSheet sheet = getStyleSheet();
  30. attr = sheet.getViewAttributes(this);
  31. }
  32. /**
  33. * Gives notification from the document that attributes were changed
  34. * in a location that this view is responsible for.
  35. *
  36. * @param e the change information from the associated document
  37. * @param a the current allocation of the view
  38. * @param f the factory to use to rebuild if the view has children
  39. * @see View#changedUpdate
  40. */
  41. public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
  42. super.changedUpdate(e, a, f);
  43. StyleSheet sheet = getStyleSheet();
  44. attr = sheet.getViewAttributes(this);
  45. preferenceChanged(null, true, true);
  46. }
  47. /**
  48. * Fetches the attributes to use when rendering. This is
  49. * implemented to multiplex the attributes specified in the
  50. * model with a StyleSheet.
  51. */
  52. public AttributeSet getAttributes() {
  53. return attr;
  54. }
  55. /**
  56. * Determines how attractive a break opportunity in
  57. * this view is. This can be used for determining which
  58. * view is the most attractive to call <code>breakView</code>
  59. * on in the process of formatting. A view that represents
  60. * text that has whitespace in it might be more attractive
  61. * than a view that has no whitespace, for example. The
  62. * higher the weight, the more attractive the break. A
  63. * value equal to or lower than <code>BadBreakWeight</code>
  64. * should not be considered for a break. A value greater
  65. * than or equal to <code>ForcedBreakWeight</code> should
  66. * be broken.
  67. * <p>
  68. * This is implemented to provide the default behavior
  69. * of returning <code>BadBreakWeight</code> unless the length
  70. * is greater than the length of the view in which case the
  71. * entire view represents the fragment. Unless a view has
  72. * been written to support breaking behavior, it is not
  73. * attractive to try and break the view. An example of
  74. * a view that does support breaking is <code>LabelView</code>.
  75. * An example of a view that uses break weight is
  76. * <code>ParagraphView</code>.
  77. *
  78. * @param axis may be either View.X_AXIS or View.Y_AXIS
  79. * @param pos the potential location of the start of the
  80. * broken view >= 0. This may be useful for calculating tab
  81. * positions.
  82. * @param len specifies the relative length from <em>pos</em>
  83. * where a potential break is desired >= 0.
  84. * @return the weight, which should be a value between
  85. * ForcedBreakWeight and BadBreakWeight.
  86. * @see LabelView
  87. * @see ParagraphView
  88. * @see javax.swing.text.View#BadBreakWeight
  89. * @see javax.swing.text.View#GoodBreakWeight
  90. * @see javax.swing.text.View#ExcellentBreakWeight
  91. * @see javax.swing.text.View#ForcedBreakWeight
  92. */
  93. public int getBreakWeight(int axis, float pos, float len) {
  94. if (nowrap) {
  95. return BadBreakWeight;
  96. }
  97. return super.getBreakWeight(axis, pos, len);
  98. }
  99. /**
  100. * Fetch the span of the longest word in the view.
  101. */
  102. float getLongestWordSpan() {
  103. // find the longest word
  104. float span = 0;
  105. try {
  106. Document doc = getDocument();
  107. int p0 = getStartOffset();
  108. int p1 = getEndOffset();
  109. if (p1 > p0) {
  110. Segment segment = new Segment();
  111. doc.getText(p0, p1 - p0, segment);
  112. int word0 = p0;
  113. int word1 = p0;
  114. Container c = getContainer();
  115. BreakIterator words;
  116. if (c != null) {
  117. words = BreakIterator.getWordInstance(c.getLocale());
  118. } else {
  119. words = BreakIterator.getWordInstance();
  120. }
  121. words.setText(segment);
  122. int start = words.first();
  123. for (int end = words.next(); end != BreakIterator.DONE;
  124. start = end, end = words.next()) {
  125. // update longest word boundary
  126. if ((end - start) > (word1 - word0)) {
  127. word0 = start;
  128. word1 = end;
  129. }
  130. }
  131. // calculate the minimum
  132. if ((word1 - word0) > 0) {
  133. FontMetrics metrics = getFontMetrics();
  134. int offs = segment.offset + word0 - segment.getBeginIndex();
  135. span = metrics.charsWidth(segment.array, offs, word1 - word0);
  136. }
  137. }
  138. } catch (BadLocationException ble) {
  139. // If the text can't be retrieved, it can't influence the size.
  140. }
  141. return span;
  142. }
  143. /**
  144. * Set the cached properties from the attributes.
  145. */
  146. protected void setPropertiesFromAttributes() {
  147. super.setPropertiesFromAttributes();
  148. AttributeSet a = getAttributes();
  149. Object decor = a.getAttribute(CSS.Attribute.TEXT_DECORATION);
  150. boolean u = (decor != null) ?
  151. (decor.toString().indexOf("underline") >= 0) : false;
  152. setUnderline(u);
  153. boolean s = (decor != null) ?
  154. (decor.toString().indexOf("line-through") >= 0) : false;
  155. setStrikeThrough(s);
  156. Object vAlign = a.getAttribute(CSS.Attribute.VERTICAL_ALIGN);
  157. s = (vAlign != null) ? (vAlign.toString().indexOf("sup") >= 0) : false;
  158. setSuperscript(s);
  159. s = (vAlign != null) ? (vAlign.toString().indexOf("sub") >= 0) : false;
  160. setSubscript(s);
  161. Object whitespace = a.getAttribute(CSS.Attribute.WHITE_SPACE);
  162. if ((whitespace != null) && whitespace.equals("nowrap")) {
  163. nowrap = true;
  164. } else {
  165. nowrap = false;
  166. }
  167. }
  168. protected StyleSheet getStyleSheet() {
  169. HTMLDocument doc = (HTMLDocument) getDocument();
  170. return doc.getStyleSheet();
  171. }
  172. private boolean nowrap;
  173. private AttributeSet attr;
  174. }