FileDocCategorySizeDatePackage
FrameSetView.javaAPI DocJava SE 5 API9364Fri Aug 26 14:58:18 BST 2005javax.swing.text.html

FrameSetView

public class FrameSetView extends BoxView
Implements a FrameSetView, intended to support the HTML <FRAMESET> tag. Supports the ROWS and COLS attributes.
author
Sunita Mani Credit also to the hotjava browser engineers that worked on making the allocation of space algorithms conform to the HTML 4.0 standard and also be netscape compatible.
version
1.20 12/19/03

Fields Summary
String[]
children
int[]
percentChildren
int[]
absoluteChildren
int[]
relativeChildren
int
percentTotals
int
absoluteTotals
int
relativeTotals
Constructors Summary
public FrameSetView(Element elem, int axis)
Constructs a FrameSetView for the given element.

param
elem the element that this view is responsible for

	super(elem, axis);
	children = null;
    
Methods Summary
protected javax.swing.SizeRequirements[]getChildRequests(int targetSpan, int axis)


	int span[] = new int[children.length];

	spread(targetSpan, span);
	int n = getViewCount();
	SizeRequirements[] reqs = new SizeRequirements[n];
	for (int i = 0, sIndex = 0; i < n; i++) {
	    View v = getView(i);
	    if ((v instanceof FrameView) || (v instanceof FrameSetView)) {
		reqs[i] = new SizeRequirements((int) v.getMinimumSpan(axis),
					       span[sIndex], 
					       (int) v.getMaximumSpan(axis),
					       0.5f);
                sIndex++;
	    } else {
		int min = (int) v.getMinimumSpan(axis);
		int pref = (int) v.getPreferredSpan(axis);
		int max = (int) v.getMaximumSpan(axis);
		float a = v.getAlignment(axis);
		reqs[i] = new SizeRequirements(min, pref, max, a);
	    }
	}
	return reqs;
    
private voidinit()
Initializes a number of internal state variables that store information about space allocation for the frames contained within the frameset.

	if (getAxis() == View.Y_AXIS) {
	    children = parseRowColSpec(HTML.Attribute.ROWS);
	} else {
	    children = parseRowColSpec(HTML.Attribute.COLS);
	}
	percentChildren = new int[children.length];
	relativeChildren = new int[children.length];
	absoluteChildren = new int[children.length];

	for (int i = 0; i < children.length; i++) {
	    percentChildren[i] = -1;
	    relativeChildren[i] = -1;
	    absoluteChildren[i] = -1;

	    if (children[i].endsWith("*")) {
		if (children[i].length() > 1) {
		    relativeChildren[i] =
			Integer.parseInt(children[i].substring(
			    0, children[i].length()-1));
		    relativeTotals += relativeChildren[i];
		} else {
		    relativeChildren[i] = 1;
		    relativeTotals += 1;
		}
	    } else if (children[i].indexOf('%") != -1) {
		percentChildren[i] = parseDigits(children[i]);
		percentTotals += percentChildren[i];
	    } else {
		absoluteChildren[i] = Integer.parseInt(children[i]);
	    }
	}
	if (percentTotals > 100) {
	    for (int i = 0; i < percentChildren.length; i++) {
		if (percentChildren[i] > 0) {
		    percentChildren[i] = 
			(percentChildren[i] * 100) / percentTotals;
		}
	    }
	    percentTotals = 100;
	}
    
protected voidlayoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans)
Perform layout for the major axis of the box (i.e. the axis that it represents). The results of the layout should be placed in the given arrays which represent the allocations to the children along the major axis.

param
targetSpan the total span given to the view, which whould be used to layout the children
param
axis the axis being layed out
param
offsets the offsets from the origin of the view for each of the child views; this is a return value and is filled in by the implementation of this method
param
spans the span of each child view; this is a return value and is filled in by the implementation of this method
return
the offset and span for each child view in the offsets and spans parameters

	if (children == null) {
	    init();
	}
	SizeRequirements.calculateTiledPositions(targetSpan, null, 
						 getChildRequests(targetSpan,
								  axis),
						 offsets, spans);
    
private intparseDigits(java.lang.String mixedStr)

	int result = 0;
	for (int i = 0; i < mixedStr.length(); i++) {
	    char ch = mixedStr.charAt(i);
	    if (Character.isDigit(ch)) {
		result = (result * 10) + Character.digit(ch, 10);
	    }
	}
	return result;
    
private java.lang.String[]parseRowColSpec(javax.swing.text.html.HTML$Attribute key)
Parses the ROW or COL attributes and returns an array of strings that represent the space distribution.

	
	AttributeSet attributes = getElement().getAttributes();
	String spec = "*";
	if (attributes != null) {
	    if (attributes.getAttribute(key) != null) {
		spec = (String)attributes.getAttribute(key);
	    }
	}

	StringTokenizer tokenizer = new StringTokenizer(spec, ",");
	int nTokens = tokenizer.countTokens();
	int n = getViewCount();
        String[] items = new String[Math.max(nTokens, n)];
	int i = 0;
	for (; i < nTokens; i++) {
	    items[i] = tokenizer.nextToken().trim();
	    // As per the spec, 100% is the same as *
	    // hence the mapping.
	    //
	    if (items[i].equals("100%")) {
		items[i] = "*";
	    }
	}
        // extend spec if we have more children than specified
        // in ROWS or COLS attribute
        for (; i < items.length; i++) {
            items[i] = "*";
        }
	return items;
    
private voidspread(int targetSpan, int[] span)
This method is responsible for returning in span[] the span for each child view along the major axis. it computes this based on the information that extracted from the value of the ROW/COL attribute.


	if (targetSpan == 0) {
	    return;
	}

	int tempSpace = 0;
	int remainingSpace = targetSpan;
	
	// allocate the absolute's first, they have
	// precedence
	//
	for (int i = 0; i < span.length; i++) {
	    if (absoluteChildren[i] > 0) {
		span[i] = absoluteChildren[i];
		remainingSpace -= span[i];
	    }
	}
	
	// then deal with percents.
	//
	tempSpace = remainingSpace;
	for (int i = 0; i < span.length; i++) {
	    if (percentChildren[i] > 0 && tempSpace > 0) {
		span[i] = (percentChildren[i] * tempSpace) / 100;
		remainingSpace -= span[i];
	    } else if (percentChildren[i] > 0 && tempSpace <= 0) {
		span[i] = targetSpan / span.length;
		remainingSpace -= span[i];
	    }
	}

	// allocate remainingSpace to relative
	if (remainingSpace > 0 && relativeTotals > 0) {
	    for (int i = 0; i < span.length; i++) {
		if (relativeChildren[i] > 0) {
		    span[i] = (remainingSpace *
				relativeChildren[i]) / relativeTotals;
		}
	    }
	} else if (remainingSpace > 0) {
	    // There are no relative columns and the space has been
	    // under- or overallocated.  In this case, turn all the 
	    // percentage and pixel specified columns to percentage 
	    // columns based on the ratio of their pixel count to the
	    // total "virtual" size. (In the case of percentage columns,
	    // the pixel count would equal the specified percentage
	    // of the screen size.
      
	    // This action is in accordance with the HTML
	    // 4.0 spec (see section 8.3, the end of the discussion of
	    // the FRAMESET tag).  The precedence of percentage and pixel
	    // specified columns is unclear (spec seems to indicate that
	    // they share priority, however, unspecified what happens when
	    // overallocation occurs.)
	    
	    // addendum is that we behave similiar to netscape in that specified
	    // widths have precedance over percentage widths...
    
	    float vTotal = (float)(targetSpan - remainingSpace);
	    float[] tempPercents = new float[span.length];
	    remainingSpace = targetSpan;
	    for (int i = 0; i < span.length; i++) {
	    	// ok we know what our total space is, and we know how large each
	    	// column should be relative to each other... therefore we can use
	    	// that relative information to deduce their percentages of a whole
	    	// and then scale them appropriately for the correct size
	    	tempPercents[i] = ((float)span[i] / vTotal) * 100.00f;
	        span[i] = (int) ( ((float)targetSpan * tempPercents[i]) / 100.00f);
		remainingSpace -= span[i];
	    }

	       
	    // this is for just in case there is something left over.. if there is we just
	    // add it one pixel at a time to the frames in order.. We shouldn't really ever get
	    // here and if we do it shouldn't be with more than 1 pixel, maybe two.
	    int i = 0;
	    while (remainingSpace != 0) {
	    	if (remainingSpace < 0) {
	    	    span[i++]--;
	    	    remainingSpace++;
	    	}
	    	else {
	    	    span[i++]++;
	    	    remainingSpace--;
	    	}
	    	
	    	// just in case there are more pixels than frames...should never happen..
	    	if (i == span.length)i = 0;
	    }  
	}