1. /*
  2. * @(#)ParagraphView.java 1.28 03/12/19
  3. *
  4. * Copyright 2004 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.*;
  9. import javax.swing.SizeRequirements;
  10. import javax.swing.event.DocumentEvent;
  11. import javax.swing.text.Document;
  12. import javax.swing.text.Element;
  13. import javax.swing.text.AttributeSet;
  14. import javax.swing.text.StyleConstants;
  15. import javax.swing.text.View;
  16. import javax.swing.text.ViewFactory;
  17. import javax.swing.text.BadLocationException;
  18. import javax.swing.text.JTextComponent;
  19. /**
  20. * Displays the a paragraph, and uses css attributes for its
  21. * configuration.
  22. *
  23. * @author Timothy Prinzing
  24. * @version 1.28 12/19/03
  25. */
  26. public class ParagraphView extends javax.swing.text.ParagraphView {
  27. /**
  28. * Constructs a ParagraphView for the given element.
  29. *
  30. * @param elem the element that this view is responsible for
  31. */
  32. public ParagraphView(Element elem) {
  33. super(elem);
  34. }
  35. /**
  36. * Establishes the parent view for this view. This is
  37. * guaranteed to be called before any other methods if the
  38. * parent view is functioning properly.
  39. * <p>
  40. * This is implemented
  41. * to forward to the superclass as well as call the
  42. * <a href="#setPropertiesFromAttributes">setPropertiesFromAttributes</a>
  43. * method to set the paragraph properties from the css
  44. * attributes. The call is made at this time to ensure
  45. * the ability to resolve upward through the parents
  46. * view attributes.
  47. *
  48. * @param parent the new parent, or null if the view is
  49. * being removed from a parent it was previously added
  50. * to
  51. */
  52. public void setParent(View parent) {
  53. super.setParent(parent);
  54. if (parent != null) {
  55. setPropertiesFromAttributes();
  56. }
  57. }
  58. /**
  59. * Fetches the attributes to use when rendering. This is
  60. * implemented to multiplex the attributes specified in the
  61. * model with a StyleSheet.
  62. */
  63. public AttributeSet getAttributes() {
  64. if (attr == null) {
  65. StyleSheet sheet = getStyleSheet();
  66. attr = sheet.getViewAttributes(this);
  67. }
  68. return attr;
  69. }
  70. /**
  71. * Sets up the paragraph from css attributes instead of
  72. * the values found in StyleConstants (i.e. which are used
  73. * by the superclass). Since
  74. */
  75. protected void setPropertiesFromAttributes() {
  76. StyleSheet sheet = getStyleSheet();
  77. attr = sheet.getViewAttributes(this);
  78. painter = sheet.getBoxPainter(attr);
  79. if (attr != null) {
  80. super.setPropertiesFromAttributes();
  81. setInsets((short) painter.getInset(TOP, this),
  82. (short) painter.getInset(LEFT, this),
  83. (short) painter.getInset(BOTTOM, this),
  84. (short) painter.getInset(RIGHT, this));
  85. Object o = attr.getAttribute(CSS.Attribute.TEXT_ALIGN);
  86. if (o != null) {
  87. // set horizontal alignment
  88. String ta = o.toString();
  89. if (ta.equals("left")) {
  90. setJustification(StyleConstants.ALIGN_LEFT);
  91. } else if (ta.equals("center")) {
  92. setJustification(StyleConstants.ALIGN_CENTER);
  93. } else if (ta.equals("right")) {
  94. setJustification(StyleConstants.ALIGN_RIGHT);
  95. } else if (ta.equals("justify")) {
  96. setJustification(StyleConstants.ALIGN_JUSTIFIED);
  97. }
  98. }
  99. // Get the width/height
  100. cssWidth = (CSS.LengthValue)attr.getAttribute(
  101. CSS.Attribute.WIDTH);
  102. cssHeight = (CSS.LengthValue)attr.getAttribute(
  103. CSS.Attribute.HEIGHT);
  104. }
  105. }
  106. protected StyleSheet getStyleSheet() {
  107. HTMLDocument doc = (HTMLDocument) getDocument();
  108. return doc.getStyleSheet();
  109. }
  110. /**
  111. * Calculate the needs for the paragraph along the minor axis.
  112. * This implemented to use the requirements of the superclass,
  113. * modified slightly to set a minimum span allowed. Typical
  114. * html rendering doesn't let the view size shrink smaller than
  115. * the length of the longest word.
  116. */
  117. protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) {
  118. r = super.calculateMinorAxisRequirements(axis, r);
  119. if (!BlockView.spanSetFromAttributes(axis, r, cssWidth, cssHeight)) {
  120. // PENDING(prinz) Need to make this better so it doesn't require
  121. // InlineView and works with font changes within the word.
  122. // find the longest minimum span.
  123. float min = 0;
  124. int n = getLayoutViewCount();
  125. for (int i = 0; i < n; i++) {
  126. View v = getLayoutView(i);
  127. if (v instanceof InlineView) {
  128. float wordSpan = ((InlineView) v).getLongestWordSpan();
  129. min = Math.max(wordSpan, min);
  130. } else {
  131. min = Math.max(v.getMinimumSpan(axis), min);
  132. }
  133. }
  134. r.minimum = Math.max(r.minimum, (int) min);
  135. r.preferred = Math.max(r.minimum, r.preferred);
  136. r.maximum = Math.max(r.preferred, r.maximum);
  137. }
  138. else {
  139. // Offset by the margins so that pref/min/max return the
  140. // right value.
  141. int margin = (axis == X_AXIS) ? getLeftInset() + getRightInset() :
  142. getTopInset() + getBottomInset();
  143. r.minimum -= margin;
  144. r.preferred -= margin;
  145. r.maximum -= margin;
  146. }
  147. return r;
  148. }
  149. /**
  150. * Indicates whether or not this view should be
  151. * displayed. If none of the children wish to be
  152. * displayed and the only visible child is the
  153. * break that ends the paragraph, the paragraph
  154. * will not be considered visible. Otherwise,
  155. * it will be considered visible and return true.
  156. *
  157. * @return true if the paragraph should be displayed
  158. */
  159. public boolean isVisible() {
  160. int n = getLayoutViewCount() - 1;
  161. for (int i = 0; i < n; i++) {
  162. View v = getLayoutView(i);
  163. if (v.isVisible()) {
  164. return true;
  165. }
  166. }
  167. if (n > 0) {
  168. View v = getLayoutView(n);
  169. if ((v.getEndOffset() - v.getStartOffset()) == 1) {
  170. return false;
  171. }
  172. }
  173. // If it's the last paragraph and not editable, it shouldn't
  174. // be visible.
  175. if (getStartOffset() == getDocument().getLength()) {
  176. boolean editable = false;
  177. Component c = getContainer();
  178. if (c instanceof JTextComponent) {
  179. editable = ((JTextComponent)c).isEditable();
  180. }
  181. if (!editable) {
  182. return false;
  183. }
  184. }
  185. return true;
  186. }
  187. /**
  188. * Renders using the given rendering surface and area on that
  189. * surface. This is implemented to delgate to the superclass
  190. * after stashing the base coordinate for tab calculations.
  191. *
  192. * @param g the rendering surface to use
  193. * @param a the allocated region to render into
  194. * @see View#paint
  195. */
  196. public void paint(Graphics g, Shape a) {
  197. Rectangle r;
  198. if (a instanceof Rectangle) {
  199. r = (Rectangle) a;
  200. } else {
  201. r = a.getBounds();
  202. }
  203. painter.paint(g, r.x, r.y, r.width, r.height, this);
  204. super.paint(g, a);
  205. }
  206. /**
  207. * Determines the preferred span for this view. Returns
  208. * 0 if the view is not visible, otherwise it calls the
  209. * superclass method to get the preferred span.
  210. * axis.
  211. *
  212. * @param axis may be either View.X_AXIS or View.Y_AXIS
  213. * @return the span the view would like to be rendered into;
  214. * typically the view is told to render into the span
  215. * that is returned, although there is no guarantee;
  216. * the parent may choose to resize or break the view
  217. * @see javax.swing.text.ParagraphView#getPreferredSpan
  218. */
  219. public float getPreferredSpan(int axis) {
  220. if (!isVisible()) {
  221. return 0;
  222. }
  223. return super.getPreferredSpan(axis);
  224. }
  225. /**
  226. * Determines the minimum span for this view along an
  227. * axis. Returns 0 if the view is not visible, otherwise
  228. * it calls the superclass method to get the minimum span.
  229. *
  230. * @param axis may be either <code>View.X_AXIS</code> or
  231. * <code>View.Y_AXIS</code>
  232. * @return the minimum span the view can be rendered into
  233. * @see javax.swing.text.ParagraphView#getMinimumSpan
  234. */
  235. public float getMinimumSpan(int axis) {
  236. if (!isVisible()) {
  237. return 0;
  238. }
  239. return super.getMinimumSpan(axis);
  240. }
  241. /**
  242. * Determines the maximum span for this view along an
  243. * axis. Returns 0 if the view is not visible, otherwise
  244. * it calls the superclass method ot get the maximum span.
  245. *
  246. * @param axis may be either <code>View.X_AXIS</code> or
  247. * <code>View.Y_AXIS</code>
  248. * @return the maximum span the view can be rendered into
  249. * @see javax.swing.text.ParagraphView#getMaximumSpan
  250. */
  251. public float getMaximumSpan(int axis) {
  252. if (!isVisible()) {
  253. return 0;
  254. }
  255. return super.getMaximumSpan(axis);
  256. }
  257. private AttributeSet attr;
  258. private StyleSheet.BoxPainter painter;
  259. private CSS.LengthValue cssWidth;
  260. private CSS.LengthValue cssHeight;
  261. }