KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)FrameSetView.java 1.20 03/12/19
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.awt.*;
10 import java.util.*;
11 import javax.swing.*;
12 import javax.swing.text.*;
13 import javax.swing.event.*;
14
15 /**
16  * Implements a FrameSetView, intended to support the HTML
17  * <FRAMESET> tag. Supports the ROWS and COLS attributes.
18  *
19  * @author Sunita Mani
20  *
21  * Credit also to the hotjava browser engineers that
22  * worked on making the allocation of space algorithms
23  * conform to the HTML 4.0 standard and also be netscape
24  * compatible.
25  *
26  * @version 1.20 12/19/03
27  */

28
29 class FrameSetView extends javax.swing.text.BoxView JavaDoc {
30
31     String JavaDoc[] children;
32     int[] percentChildren;
33     int[] absoluteChildren;
34     int[] relativeChildren;
35     int percentTotals;
36     int absoluteTotals;
37     int relativeTotals;
38
39     /**
40      * Constructs a FrameSetView for the given element.
41      *
42      * @param elem the element that this view is responsible for
43      */

44     public FrameSetView(Element elem, int axis) {
45     super(elem, axis);
46     children = null;
47     }
48
49     /**
50      * Parses the ROW or COL attributes and returns
51      * an array of strings that represent the space
52      * distribution.
53      *
54      */

55     private String JavaDoc[] parseRowColSpec(HTML.Attribute JavaDoc key) {
56     
57     AttributeSet attributes = getElement().getAttributes();
58     String JavaDoc spec = "*";
59     if (attributes != null) {
60         if (attributes.getAttribute(key) != null) {
61         spec = (String JavaDoc)attributes.getAttribute(key);
62         }
63     }
64
65     StringTokenizer tokenizer = new StringTokenizer(spec, ",");
66     int nTokens = tokenizer.countTokens();
67     int n = getViewCount();
68         String JavaDoc[] items = new String JavaDoc[Math.max(nTokens, n)];
69     int i = 0;
70     for (; i < nTokens; i++) {
71         items[i] = tokenizer.nextToken().trim();
72         // As per the spec, 100% is the same as *
73
// hence the mapping.
74
//
75
if (items[i].equals("100%")) {
76         items[i] = "*";
77         }
78     }
79         // extend spec if we have more children than specified
80
// in ROWS or COLS attribute
81
for (; i < items.length; i++) {
82             items[i] = "*";
83         }
84     return items;
85     }
86
87
88     /**
89      * Initializes a number of internal state variables
90      * that store information about space allocation
91      * for the frames contained within the frameset.
92      */

93     private void init() {
94     if (getAxis() == View.Y_AXIS) {
95         children = parseRowColSpec(HTML.Attribute.ROWS);
96     } else {
97         children = parseRowColSpec(HTML.Attribute.COLS);
98     }
99     percentChildren = new int[children.length];
100     relativeChildren = new int[children.length];
101     absoluteChildren = new int[children.length];
102
103     for (int i = 0; i < children.length; i++) {
104         percentChildren[i] = -1;
105         relativeChildren[i] = -1;
106         absoluteChildren[i] = -1;
107
108         if (children[i].endsWith("*")) {
109         if (children[i].length() > 1) {
110             relativeChildren[i] =
111             Integer.parseInt(children[i].substring(
112                 0, children[i].length()-1));
113             relativeTotals += relativeChildren[i];
114         } else {
115             relativeChildren[i] = 1;
116             relativeTotals += 1;
117         }
118         } else if (children[i].indexOf('%') != -1) {
119         percentChildren[i] = parseDigits(children[i]);
120         percentTotals += percentChildren[i];
121         } else {
122         absoluteChildren[i] = Integer.parseInt(children[i]);
123         }
124     }
125     if (percentTotals > 100) {
126         for (int i = 0; i < percentChildren.length; i++) {
127         if (percentChildren[i] > 0) {
128             percentChildren[i] =
129             (percentChildren[i] * 100) / percentTotals;
130         }
131         }
132         percentTotals = 100;
133     }
134     }
135
136     /**
137      * Perform layout for the major axis of the box (i.e. the
138      * axis that it represents). The results of the layout should
139      * be placed in the given arrays which represent the allocations
140      * to the children along the major axis.
141      *
142      * @param targetSpan the total span given to the view, which
143      * whould be used to layout the children
144      * @param axis the axis being layed out
145      * @param offsets the offsets from the origin of the view for
146      * each of the child views; this is a return value and is
147      * filled in by the implementation of this method
148      * @param spans the span of each child view; this is a return
149      * value and is filled in by the implementation of this method
150      * @return the offset and span for each child view in the
151      * offsets and spans parameters
152      */

153     protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
154                    int[] spans) {
155     if (children == null) {
156         init();
157     }
158     SizeRequirements.calculateTiledPositions(targetSpan, null,
159                          getChildRequests(targetSpan,
160                                   axis),
161                          offsets, spans);
162     }
163
164     protected SizeRequirements[] getChildRequests(int targetSpan, int axis) {
165
166     int span[] = new int[children.length];
167
168     spread(targetSpan, span);
169     int n = getViewCount();
170     SizeRequirements[] reqs = new SizeRequirements[n];
171     for (int i = 0, sIndex = 0; i < n; i++) {
172         View v = getView(i);
173         if ((v instanceof FrameView JavaDoc) || (v instanceof FrameSetView JavaDoc)) {
174         reqs[i] = new SizeRequirements((int) v.getMinimumSpan(axis),
175                            span[sIndex],
176                            (int) v.getMaximumSpan(axis),
177                            0.5f);
178                 sIndex++;
179         } else {
180         int min = (int) v.getMinimumSpan(axis);
181         int pref = (int) v.getPreferredSpan(axis);
182         int max = (int) v.getMaximumSpan(axis);
183         float a = v.getAlignment(axis);
184         reqs[i] = new SizeRequirements(min, pref, max, a);
185         }
186     }
187     return reqs;
188     }
189
190
191     /**
192      * This method is responsible for returning in span[] the
193      * span for each child view along the major axis. it
194      * computes this based on the information that extracted
195      * from the value of the ROW/COL attribute.
196      */

197     private void spread(int targetSpan, int span[]) {
198
199     if (targetSpan == 0) {
200         return;
201     }
202
203     int tempSpace = 0;
204     int remainingSpace = targetSpan;
205     
206     // allocate the absolute's first, they have
207
// precedence
208
//
209
for (int i = 0; i < span.length; i++) {
210         if (absoluteChildren[i] > 0) {
211         span[i] = absoluteChildren[i];
212         remainingSpace -= span[i];
213         }
214     }
215     
216     // then deal with percents.
217
//
218
tempSpace = remainingSpace;
219     for (int i = 0; i < span.length; i++) {
220         if (percentChildren[i] > 0 && tempSpace > 0) {
221         span[i] = (percentChildren[i] * tempSpace) / 100;
222         remainingSpace -= span[i];
223         } else if (percentChildren[i] > 0 && tempSpace <= 0) {
224         span[i] = targetSpan / span.length;
225         remainingSpace -= span[i];
226         }
227     }
228
229     // allocate remainingSpace to relative
230
if (remainingSpace > 0 && relativeTotals > 0) {
231         for (int i = 0; i < span.length; i++) {
232         if (relativeChildren[i] > 0) {
233             span[i] = (remainingSpace *
234                 relativeChildren[i]) / relativeTotals;
235         }
236         }
237     } else if (remainingSpace > 0) {
238         // There are no relative columns and the space has been
239
// under- or overallocated. In this case, turn all the
240
// percentage and pixel specified columns to percentage
241
// columns based on the ratio of their pixel count to the
242
// total "virtual" size. (In the case of percentage columns,
243
// the pixel count would equal the specified percentage
244
// of the screen size.
245

246         // This action is in accordance with the HTML
247
// 4.0 spec (see section 8.3, the end of the discussion of
248
// the FRAMESET tag). The precedence of percentage and pixel
249
// specified columns is unclear (spec seems to indicate that
250
// they share priority, however, unspecified what happens when
251
// overallocation occurs.)
252

253         // addendum is that we behave similiar to netscape in that specified
254
// widths have precedance over percentage widths...
255

256         float vTotal = (float)(targetSpan - remainingSpace);
257         float[] tempPercents = new float[span.length];
258         remainingSpace = targetSpan;
259         for (int i = 0; i < span.length; i++) {
260             // ok we know what our total space is, and we know how large each
261
// column should be relative to each other... therefore we can use
262
// that relative information to deduce their percentages of a whole
263
// and then scale them appropriately for the correct size
264
tempPercents[i] = ((float)span[i] / vTotal) * 100.00f;
265             span[i] = (int) ( ((float)targetSpan * tempPercents[i]) / 100.00f);
266         remainingSpace -= span[i];
267         }
268
269            
270         // this is for just in case there is something left over.. if there is we just
271
// add it one pixel at a time to the frames in order.. We shouldn't really ever get
272
// here and if we do it shouldn't be with more than 1 pixel, maybe two.
273
int i = 0;
274         while (remainingSpace != 0) {
275             if (remainingSpace < 0) {
276                 span[i++]--;
277                 remainingSpace++;
278             }
279             else {
280                 span[i++]++;
281                 remainingSpace--;
282             }
283             
284             // just in case there are more pixels than frames...should never happen..
285
if (i == span.length)i = 0;
286         }
287     }
288     }
289
290     /*
291      * Users have been known to type things like "%25" and "25 %". Deal
292      * with it.
293      */

294     private int parseDigits(String JavaDoc mixedStr) {
295     int result = 0;
296     for (int i = 0; i < mixedStr.length(); i++) {
297         char ch = mixedStr.charAt(i);
298         if (Character.isDigit(ch)) {
299         result = (result * 10) + Character.digit(ch, 10);
300         }
301     }
302     return result;
303     }
304
305 }
306
307
Popular Tags