001 /* ParagraphView.java -- Renders a paragraph in HTML 002 Copyright (C) 2006 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package javax.swing.text.html; 040 041 import gnu.javax.swing.text.html.css.Length; 042 043 import java.awt.Graphics; 044 import java.awt.Rectangle; 045 import java.awt.Shape; 046 047 import javax.swing.SizeRequirements; 048 import javax.swing.text.AttributeSet; 049 import javax.swing.text.Document; 050 import javax.swing.text.Element; 051 import javax.swing.text.StyleConstants; 052 import javax.swing.text.View; 053 054 /** 055 * Renders a paragraph in HTML. This is a subclass of 056 * {@link javax.swing.text.ParagraphView} with some adjustments for 057 * understanding stylesheets. 058 * 059 * @author Roman Kennke (kennke@aicas.com) 060 */ 061 public class ParagraphView 062 extends javax.swing.text.ParagraphView 063 { 064 065 /** 066 * The attributes used by this view. 067 */ 068 private AttributeSet attributes; 069 070 /** 071 * The stylesheet's box painter. 072 */ 073 private StyleSheet.BoxPainter painter; 074 075 /** 076 * The width as specified in the stylesheet or null if not specified. 077 */ 078 private Length cssWidth; 079 080 /** 081 * The height as specified in the stylesheet or null if not specified. 082 */ 083 private Length cssHeight; 084 085 /** 086 * Creates a new ParagraphView for the specified element. 087 * 088 * @param element the element 089 */ 090 public ParagraphView(Element element) 091 { 092 super(element); 093 } 094 095 /** 096 * Sets the parent of this view. This is implemented to call the parent 097 * functionality and then trigger {@link #setPropertiesFromAttributes} in 098 * order to load the stylesheet attributes. 099 * 100 * @param parent the parent view to set 101 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 315 public float getMaximumSpan(int axis) 316 { 317 float span = 0; 318 if (isVisible()) 319 span = super.getMaximumSpan(axis); 320 return span; 321 } 322 }