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 }