KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > text > html > BlockView


1 /*
2  * @(#)BlockView.java 1.36 04/03/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing.text.html;
8
9 import java.util.Enumeration JavaDoc;
10 import java.awt.*;
11 import javax.swing.SizeRequirements JavaDoc;
12 import javax.swing.border.*;
13 import javax.swing.event.DocumentEvent JavaDoc;
14 import javax.swing.text.*;
15
16 /**
17  * A view implementation to display a block (as a box)
18  * with CSS specifications.
19  *
20  * @author Timothy Prinzing
21  * @version 1.36 03/05/04
22  */

23 public class BlockView extends BoxView {
24
25     /**
26      * Creates a new view that represents an
27      * html box. This can be used for a number
28      * of elements.
29      *
30      * @param elem the element to create a view for
31      * @param axis either View.X_AXIS or View.Y_AXIS
32      */

33     public BlockView(Element elem, int axis) {
34     super(elem, axis);
35     }
36
37     /**
38      * Establishes the parent view for this view. This is
39      * guaranteed to be called before any other methods if the
40      * parent view is functioning properly.
41      * <p>
42      * This is implemented
43      * to forward to the superclass as well as call the
44      * {@link #setPropertiesFromAttributes()}
45      * method to set the paragraph properties from the css
46      * attributes. The call is made at this time to ensure
47      * the ability to resolve upward through the parents
48      * view attributes.
49      *
50      * @param parent the new parent, or null if the view is
51      * being removed from a parent it was previously added
52      * to
53      */

54     public void setParent(View parent) {
55     super.setParent(parent);
56         if (parent != null) {
57             setPropertiesFromAttributes();
58         }
59     }
60
61     /**
62      * Calculate the requirements of the block along the major
63      * axis (i.e. the axis along with it tiles). This is implemented
64      * to provide the superclass behavior and then adjust it if the
65      * CSS width or height attribute is specified and applicable to
66      * the axis.
67      */

68     protected SizeRequirements JavaDoc calculateMajorAxisRequirements(int axis, SizeRequirements JavaDoc r) {
69     if (r == null) {
70         r = new SizeRequirements JavaDoc();
71     }
72     if (! spanSetFromAttributes(axis, r, cssWidth, cssHeight)) {
73         r = super.calculateMajorAxisRequirements(axis, r);
74     }
75         else {
76             // Offset by the margins so that pref/min/max return the
77
// right value.
78
SizeRequirements JavaDoc parentR = super.calculateMajorAxisRequirements(
79                                       axis, null);
80             int margin = (axis == X_AXIS) ? getLeftInset() + getRightInset() :
81                                             getTopInset() + getBottomInset();
82             r.minimum -= margin;
83             r.preferred -= margin;
84             r.maximum -= margin;
85             constrainSize(axis, r, parentR);
86         }
87     return r;
88     }
89
90     /**
91      * Calculate the requirements of the block along the minor
92      * axis (i.e. the axis orthoginal to the axis along with it tiles).
93      * This is implemented
94      * to provide the superclass behavior and then adjust it if the
95      * CSS width or height attribute is specified and applicable to
96      * the axis.
97      */

98     protected SizeRequirements JavaDoc calculateMinorAxisRequirements(int axis, SizeRequirements JavaDoc r) {
99     if (r == null) {
100         r = new SizeRequirements JavaDoc();
101     }
102
103     if (! spanSetFromAttributes(axis, r, cssWidth, cssHeight)) {
104
105         /*
106          * The requirements were not directly specified by attributes, so
107          * compute the aggregate of the requirements of the children. The
108          * children that have a percentage value specified will be treated
109          * as completely stretchable since that child is not limited in any
110          * way.
111          */

112 /*
113         int min = 0;
114         long pref = 0;
115         int max = 0;
116         int n = getViewCount();
117         for (int i = 0; i < n; i++) {
118         View v = getView(i);
119         min = Math.max((int) v.getMinimumSpan(axis), min);
120         pref = Math.max((int) v.getPreferredSpan(axis), pref);
121         if (
122         max = Math.max((int) v.getMaximumSpan(axis), max);
123
124         }
125         r.preferred = (int) pref;
126         r.minimum = min;
127         r.maximum = max;
128         */

129         r = super.calculateMinorAxisRequirements(axis, r);
130     }
131         else {
132             // Offset by the margins so that pref/min/max return the
133
// right value.
134
SizeRequirements JavaDoc parentR = super.calculateMinorAxisRequirements(
135                                       axis, null);
136             int margin = (axis == X_AXIS) ? getLeftInset() + getRightInset() :
137                                             getTopInset() + getBottomInset();
138             r.minimum -= margin;
139             r.preferred -= margin;
140             r.maximum -= margin;
141             constrainSize(axis, r, parentR);
142         }
143
144     /*
145      * Set the alignment based upon the CSS properties if it is
146      * specified. For X_AXIS this would be text-align, for
147      * Y_AXIS this would be vertical-align.
148      */

149     if (axis == X_AXIS) {
150         Object JavaDoc o = getAttributes().getAttribute(CSS.Attribute.TEXT_ALIGN);
151         if (o != null) {
152         String JavaDoc align = o.toString();
153         if (align.equals("center")) {
154             r.alignment = 0.5f;
155         } else if (align.equals("right")) {
156             r.alignment = 1.0f;
157         } else {
158             r.alignment = 0.0f;
159         }
160         }
161     }
162     // Y_AXIS TBD
163
return r;
164     }
165
166     boolean isPercentage(int axis, AttributeSet a) {
167     if (axis == X_AXIS) {
168         if (cssWidth != null) {
169         return cssWidth.isPercentage();
170         }
171     } else {
172         if (cssHeight != null) {
173         return cssHeight.isPercentage();
174         }
175     }
176     return false;
177     }
178         
179     /**
180      * Adjust the given requirements to the CSS width or height if
181      * it is specified along the applicable axis. Return true if the
182      * size is exactly specified, false if the span is not specified
183      * in an attribute or the size specified is a percentage.
184      */

185     static boolean spanSetFromAttributes(int axis, SizeRequirements JavaDoc r,
186                                          CSS.LengthValue JavaDoc cssWidth,
187                                          CSS.LengthValue JavaDoc cssHeight) {
188     if (axis == X_AXIS) {
189         if ((cssWidth != null) && (! cssWidth.isPercentage())) {
190         r.minimum = r.preferred = r.maximum = (int) cssWidth.getValue();
191         return true;
192         }
193     } else {
194         if ((cssHeight != null) && (! cssHeight.isPercentage())) {
195         r.minimum = r.preferred = r.maximum = (int) cssHeight.getValue();
196         return true;
197         }
198     }
199     return false;
200     }
201
202     /**
203      * Perform layout for the minor axis of the box (i.e. the
204      * axis orthoginal to the axis that it represents). The results
205      * of the layout should be placed in the given arrays which represent
206      * the allocations to the children along the minor axis.
207      *
208      * @param targetSpan the total span given to the view, which
209      * whould be used to layout the childre.
210      * @param axis the axis being layed out
211      * @param offsets the offsets from the origin of the view for
212      * each of the child views; this is a return value and is
213      * filled in by the implementation of this method
214      * @param spans the span of each child view; this is a return
215      * value and is filled in by the implementation of this method
216      * @return the offset and span for each child view in the
217      * offsets and spans parameters
218      */

219     protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
220     int n = getViewCount();
221     Object JavaDoc key = (axis == X_AXIS) ? CSS.Attribute.WIDTH : CSS.Attribute.HEIGHT;
222     for (int i = 0; i < n; i++) {
223         View v = getView(i);
224         int min = (int) v.getMinimumSpan(axis);
225         int max;
226
227         // check for percentage span
228
AttributeSet a = v.getAttributes();
229         CSS.LengthValue JavaDoc lv = (CSS.LengthValue JavaDoc) a.getAttribute(key);
230         if ((lv != null) && lv.isPercentage()) {
231         // bound the span to the percentage specified
232
min = Math.max((int) lv.getValue(targetSpan), min);
233         max = min;
234         } else {
235                 max = (int)v.getMaximumSpan(axis);
236         }
237
238         // assign the offset and span for the child
239
if (max < targetSpan) {
240         // can't make the child this wide, align it
241
float align = v.getAlignment(axis);
242         offsets[i] = (int) ((targetSpan - max) * align);
243         spans[i] = max;
244         } else {
245         // make it the target width, or as small as it can get.
246
offsets[i] = 0;
247         spans[i] = Math.max(min, targetSpan);
248         }
249     }
250     }
251
252
253     /**
254      * Renders using the given rendering surface and area on that
255      * surface. This is implemented to delegate to the css box
256      * painter to paint the border and background prior to the
257      * interior.
258      *
259      * @param g the rendering surface to use
260      * @param allocation the allocated region to render into
261      * @see View#paint
262      */

263     public void paint(Graphics g, Shape allocation) {
264     Rectangle a = (Rectangle) allocation;
265     painter.paint(g, a.x, a.y, a.width, a.height, this);
266     super.paint(g, a);
267     }
268
269     /**
270      * Fetches the attributes to use when rendering. This is
271      * implemented to multiplex the attributes specified in the
272      * model with a StyleSheet.
273      */

274     public AttributeSet getAttributes() {
275     if (attr == null) {
276         StyleSheet JavaDoc sheet = getStyleSheet();
277         attr = sheet.getViewAttributes(this);
278     }
279     return attr;
280     }
281
282     /**
283      * Gets the resize weight.
284      *
285      * @param axis may be either X_AXIS or Y_AXIS
286      * @return the weight
287      * @exception IllegalArgumentException for an invalid axis
288      */

289     public int getResizeWeight(int axis) {
290     switch (axis) {
291     case View.X_AXIS:
292         return 1;
293     case View.Y_AXIS:
294         return 0;
295     default:
296         throw new IllegalArgumentException JavaDoc("Invalid axis: " + axis);
297     }
298     }
299
300     /**
301      * Gets the alignment.
302      *
303      * @param axis may be either X_AXIS or Y_AXIS
304      * @return the alignment
305      */

306     public float getAlignment(int axis) {
307     switch (axis) {
308     case View.X_AXIS:
309         return 0;
310     case View.Y_AXIS:
311         if (getViewCount() == 0) {
312         return 0;
313         }
314         float span = getPreferredSpan(View.Y_AXIS);
315         View v = getView(0);
316         float above = v.getPreferredSpan(View.Y_AXIS);
317         float a = (((int)span) != 0) ? (above * v.getAlignment(View.Y_AXIS)) / span: 0;
318         return a;
319     default:
320         throw new IllegalArgumentException JavaDoc("Invalid axis: " + axis);
321     }
322     }
323
324     public void changedUpdate(DocumentEvent JavaDoc changes, Shape a, ViewFactory f) {
325     super.changedUpdate(changes, a, f);
326     int pos = changes.getOffset();
327     if (pos <= getStartOffset() && (pos + changes.getLength()) >=
328         getEndOffset()) {
329         setPropertiesFromAttributes();
330     }
331     }
332
333     /**
334      * Determines the preferred span for this view along an
335      * axis.
336      *
337      * @param axis may be either <code>View.X_AXIS</code>
338      * or <code>View.Y_AXIS</code>
339      * @return the span the view would like to be rendered into >= 0;
340      * typically the view is told to render into the span
341      * that is returned, although there is no guarantee;
342      * the parent may choose to resize or break the view
343      * @exception IllegalArgumentException for an invalid axis type
344      */

345     public float getPreferredSpan(int axis) {
346     return super.getPreferredSpan(axis);
347     }
348
349     /**
350      * Determines the minimum span for this view along an
351      * axis.
352      *
353      * @param axis may be either <code>View.X_AXIS</code>
354      * or <code>View.Y_AXIS</code>
355      * @return the span the view would like to be rendered into >= 0;
356      * typically the view is told to render into the span
357      * that is returned, although there is no guarantee;
358      * the parent may choose to resize or break the view
359      * @exception IllegalArgumentException for an invalid axis type
360      */

361     public float getMinimumSpan(int axis) {
362     return super.getMinimumSpan(axis);
363     }
364
365     /**
366      * Determines the maximum span for this view along an
367      * axis.
368      *
369      * @param axis may be either <code>View.X_AXIS</code>
370      * or <code>View.Y_AXIS</code>
371      * @return the span the view would like to be rendered into >= 0;
372      * typically the view is told to render into the span
373      * that is returned, although there is no guarantee;
374      * the parent may choose to resize or break the view
375      * @exception IllegalArgumentException for an invalid axis type
376      */

377     public float getMaximumSpan(int axis) {
378     return super.getMaximumSpan(axis);
379     }
380
381     /**
382      * Update any cached values that come from attributes.
383      */

384     protected void setPropertiesFromAttributes() {
385
386     // update attributes
387
StyleSheet JavaDoc sheet = getStyleSheet();
388     attr = sheet.getViewAttributes(this);
389
390     // Reset the painter
391
painter = sheet.getBoxPainter(attr);
392     if (attr != null) {
393         setInsets((short) painter.getInset(TOP, this),
394               (short) painter.getInset(LEFT, this),
395               (short) painter.getInset(BOTTOM, this),
396               (short) painter.getInset(RIGHT, this));
397     }
398
399     // Get the width/height
400
cssWidth = (CSS.LengthValue JavaDoc) attr.getAttribute(CSS.Attribute.WIDTH);
401     cssHeight = (CSS.LengthValue JavaDoc) attr.getAttribute(CSS.Attribute.HEIGHT);
402     }
403
404     protected StyleSheet JavaDoc getStyleSheet() {
405     HTMLDocument JavaDoc doc = (HTMLDocument JavaDoc) getDocument();
406     return doc.getStyleSheet();
407     }
408
409     /**
410      * Constrains <code>want</code> to fit in the minimum size specified
411      * by <code>min</code>.
412      */

413     private void constrainSize(int axis, SizeRequirements JavaDoc want,
414                                SizeRequirements JavaDoc min) {
415         if (min.minimum > want.minimum) {
416             want.minimum = want.preferred = min.minimum;
417             want.maximum = Math.max(want.maximum, min.maximum);
418         }
419     }
420
421     private AttributeSet attr;
422     private StyleSheet.BoxPainter JavaDoc painter;
423
424     private CSS.LengthValue JavaDoc cssWidth;
425     private CSS.LengthValue JavaDoc cssHeight;
426
427 }
428
Popular Tags