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