1 /* ParagraphView.java -- Renders a paragraph in HTML 2 Copyright (C) 2006 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package javax.swing.text.html; 40 41 import gnu.javax.swing.text.html.css.Length; 42 43 import java.awt.Graphics; 44 import java.awt.Rectangle; 45 import java.awt.Shape; 46 47 import javax.swing.SizeRequirements; 48 import javax.swing.text.AttributeSet; 49 import javax.swing.text.Document; 50 import javax.swing.text.Element; 51 import javax.swing.text.StyleConstants; 52 import javax.swing.text.View; 53 54 /** 55 * Renders a paragraph in HTML. This is a subclass of 56 * {@link javax.swing.text.ParagraphView} with some adjustments for 57 * understanding stylesheets. 58 * 59 * @author Roman Kennke (kennke@aicas.com) 60 */ 61 public class ParagraphView 62 extends javax.swing.text.ParagraphView 63 { 64 65 /** 66 * The attributes used by this view. 67 */ 68 private AttributeSet attributes; 69 70 /** 71 * The stylesheet's box painter. 72 */ 73 private StyleSheet.BoxPainter painter; 74 75 /** 76 * The width as specified in the stylesheet or null if not specified. 77 */ 78 private Length cssWidth; 79 80 /** 81 * The height as specified in the stylesheet or null if not specified. 82 */ 83 private Length cssHeight; 84 85 /** 86 * Creates a new ParagraphView for the specified element. 87 * 88 * @param element the element 89 */ ParagraphView(Element element)90 public ParagraphView(Element element) 91 { 92 super(element); 93 } 94 95 /** 96 * Sets the parent of this view. This is implemented to call the parent 97 * functionality and then trigger {@link #setPropertiesFromAttributes} in 98 * order to load the stylesheet attributes. 99 * 100 * @param parent the parent view to set 101 */ setParent(View parent)102 public void setParent(View parent) 103 { 104 super.setParent(parent); 105 if (parent != null) 106 setPropertiesFromAttributes(); 107 } 108 109 /** 110 * Returns the attributes used by this view. This is implemented to multiplex 111 * the attributes of the model with the attributes of the stylesheet. 112 */ getAttributes()113 public AttributeSet getAttributes() 114 { 115 if (attributes == null) 116 { 117 attributes = getStyleSheet().getViewAttributes(this); 118 } 119 return attributes; 120 } 121 122 /** 123 * Loads the visual properties of the ParagraphView from the element's 124 * attributes and the stylesheet of the HTML document. 125 */ setPropertiesFromAttributes()126 protected void setPropertiesFromAttributes() 127 { 128 super.setPropertiesFromAttributes(); 129 130 // Fetch CSS attributes. 131 attributes = getAttributes(); 132 if (attributes != null) 133 { 134 super.setPropertiesFromAttributes(); 135 Object o = attributes.getAttribute(CSS.Attribute.TEXT_ALIGN); 136 if (o != null) 137 { 138 String align = o.toString(); 139 if (align.equals("left")) 140 setJustification(StyleConstants.ALIGN_LEFT); 141 else if (align.equals("right")) 142 setJustification(StyleConstants.ALIGN_RIGHT); 143 else if (align.equals("center")) 144 setJustification(StyleConstants.ALIGN_CENTER); 145 else if (align.equals("justify")) 146 setJustification(StyleConstants.ALIGN_JUSTIFIED); 147 } 148 149 // Fetch StyleSheet's box painter. 150 painter = getStyleSheet().getBoxPainter(attributes); 151 setInsets((short) painter.getInset(TOP, this), 152 (short) painter.getInset(LEFT, this), 153 (short) painter.getInset(BOTTOM, this), 154 (short) painter.getInset(RIGHT, this)); 155 156 StyleSheet ss = getStyleSheet(); 157 float emBase = ss.getEMBase(attributes); 158 float exBase = ss.getEXBase(attributes); 159 cssWidth = (Length) attributes.getAttribute(CSS.Attribute.WIDTH); 160 if (cssWidth != null) 161 cssWidth.setFontBases(emBase, exBase); 162 cssHeight = (Length) attributes.getAttribute(CSS.Attribute.WIDTH); 163 if (cssHeight != null) 164 cssHeight.setFontBases(emBase, exBase); 165 } 166 } 167 168 /** 169 * Returns the stylesheet used by this view. 170 * 171 * @return the stylesheet used by this view 172 */ getStyleSheet()173 protected StyleSheet getStyleSheet() 174 { 175 Document doc = getDocument(); 176 StyleSheet styleSheet = null; 177 if (doc instanceof HTMLDocument) 178 styleSheet = ((HTMLDocument) doc).getStyleSheet(); 179 return styleSheet; 180 } 181 182 /** 183 * Calculates the minor axis requirements of this view. This is implemented 184 * to return the super class'es requirements and modifies the minimumSpan 185 * slightly so that it is not smaller than the length of the longest word. 186 * 187 * @param axis the axis 188 * @param r the SizeRequirements object to be used as return parameter; 189 * if <code>null</code> a new one will be created 190 * 191 * @return the requirements along the minor layout axis 192 */ calculateMinorAxisRequirements(int axis, SizeRequirements r)193 protected SizeRequirements calculateMinorAxisRequirements(int axis, 194 SizeRequirements r) 195 { 196 r = super.calculateMinorAxisRequirements(axis, r); 197 if (! setCSSSpan(r, axis)) 198 { 199 int margin = axis == X_AXIS ? getLeftInset() + getRightInset() 200 : getTopInset() + getBottomInset(); 201 r.minimum -= margin; 202 r.preferred -= margin; 203 r.maximum -= margin; 204 } 205 return r; 206 } 207 208 /** 209 * Sets the span on the SizeRequirements object according to the 210 * according CSS span value, when it is set. 211 * 212 * @param r the size requirements 213 * @param axis the axis 214 * 215 * @return <code>true</code> when the CSS span has been set, 216 * <code>false</code> otherwise 217 */ setCSSSpan(SizeRequirements r, int axis)218 private boolean setCSSSpan(SizeRequirements r, int axis) 219 { 220 boolean ret = false; 221 if (axis == X_AXIS) 222 { 223 if (cssWidth != null && ! cssWidth.isPercentage()) 224 { 225 r.minimum = (int) cssWidth.getValue(); 226 r.preferred = (int) cssWidth.getValue(); 227 r.maximum = (int) cssWidth.getValue(); 228 ret = true; 229 } 230 } 231 else 232 { 233 if (cssHeight != null && ! cssWidth.isPercentage()) 234 { 235 r.minimum = (int) cssHeight.getValue(); 236 r.preferred = (int) cssHeight.getValue(); 237 r.maximum = (int) cssHeight.getValue(); 238 ret = true; 239 } 240 } 241 return ret; 242 } 243 244 /** 245 * Determines if this view is visible or not. If none of the children is 246 * visible and the only visible child is the break that ends the paragraph, 247 * this paragraph is not considered to be visible. 248 * 249 * @return the visibility of this paragraph 250 */ isVisible()251 public boolean isVisible() 252 { 253 // FIXME: Implement the above specified behaviour. 254 return super.isVisible(); 255 } 256 257 /** 258 * Paints this view. This paints the box using the stylesheet's 259 * box painter for this view and delegates to the super class paint() 260 * afterwards. 261 * 262 * @param g the graphics object 263 * @param a the current allocation of this view 264 */ paint(Graphics g, Shape a)265 public void paint(Graphics g, Shape a) 266 { 267 if (a != null) 268 { 269 Rectangle r = a instanceof Rectangle ? (Rectangle) a : a.getBounds(); 270 painter.paint(g, r.x, r.y, r.width, r.height, this); 271 } 272 super.paint(g, a); 273 } 274 275 /** 276 * Returns the preferred span of this view. If this view is not visible, 277 * we return <code>0</code>, otherwise the super class is called. 278 * 279 * @param axis the axis 280 * 281 * @return the preferred span of this view 282 */ getPreferredSpan(int axis)283 public float getPreferredSpan(int axis) 284 { 285 float span = 0; 286 if (isVisible()) 287 span = super.getPreferredSpan(axis); 288 return span; 289 } 290 291 /** 292 * Returns the minimum span of this view. If this view is not visible, 293 * we return <code>0</code>, otherwise the super class is called. 294 * 295 * @param axis the axis 296 * 297 * @return the minimum span of this view 298 */ getMinimumSpan(int axis)299 public float getMinimumSpan(int axis) 300 { 301 float span = 0; 302 if (isVisible()) 303 span = super.getMinimumSpan(axis); 304 return span; 305 } 306 307 /** 308 * Returns the maximum span of this view. If this view is not visible, 309 * we return <code>0</code>, otherwise the super class is called. 310 * 311 * @param axis the axis 312 * 313 * @return the maximum span of this view 314 */ getMaximumSpan(int axis)315 public float getMaximumSpan(int axis) 316 { 317 float span = 0; 318 if (isVisible()) 319 span = super.getMaximumSpan(axis); 320 return span; 321 } 322 } 323