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