001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Vadim L. Bogdanov
019: * @version $Revision$
020: */package javax.swing.text.html;
021:
022: import javax.swing.text.BoxView;
023: import javax.swing.text.Element;
024: import javax.swing.text.View;
025:
026: class FrameSetTagView extends BoxView {
027:
028: public FrameSetTagView(final Element elem) {
029: super (elem, calculateMajorAxis(elem));
030: }
031:
032: protected void layoutMajorAxis(final int targetSpan,
033: final int axis, final int[] offsets, final int[] spans) {
034: if (!hasNoFramesView()) {
035: layoutAxisImpl(targetSpan, axis, offsets, spans);
036: return;
037: }
038:
039: View noFramesView = getView(getViewCount() - 1);
040: int noFramesSpan = (int) noFramesView.getMinimumSpan(axis);
041: int newTargetSpan = targetSpan - noFramesSpan;
042:
043: layoutAxisImpl(newTargetSpan, axis, offsets, spans);
044:
045: offsets[getViewCount() - 1] = newTargetSpan;
046: spans[getViewCount() - 1] = noFramesSpan;
047: }
048:
049: protected void layoutMinorAxis(final int targetSpan,
050: final int axis, final int[] offsets, final int[] spans) {
051: layoutAxisImpl(targetSpan, axis, offsets, spans);
052:
053: if (hasNoFramesView()) {
054: offsets[getViewCount() - 1] = 0;
055: spans[getViewCount() - 1] = targetSpan;
056: }
057: }
058:
059: private void layoutAxisImpl(final int targetSpan, final int axis,
060: final int[] offsets, final int[] spans) {
061: Object attr;
062: if (axis == X_AXIS) {
063: attr = HTML.Attribute.COLS;
064: } else {
065: attr = HTML.Attribute.ROWS;
066: }
067:
068: String[] strLengths = parseLengths((String) getAttributes()
069: .getAttribute(attr));
070: int lineLength = strLengths.length;
071:
072: int[] lengths = calculateLengths(strLengths, targetSpan);
073:
074: int x = 0;
075: int y = 0;
076: int curOffset = 0;
077: int viewsToLayout = hasNoFramesView() ? getViewCount() - 1
078: : getViewCount();
079: for (int i = 0; i < viewsToLayout; i++) {
080: offsets[i] = curOffset;
081: spans[i] = lengths[x];
082:
083: if (axis == X_AXIS) {
084: curOffset += spans[i];
085: x++;
086: if (x >= lineLength) {
087: x = 0;
088: y++;
089: curOffset = 0;
090: }
091: } else {
092: y++;
093: if (y >= offsets.length / lineLength) {
094: x++;
095: y = 0;
096: curOffset += spans[i];
097: }
098: }
099: }
100: }
101:
102: private int[] calculateLengths(final String[] strLengths,
103: final int targetLength) {
104: int[] lengths = new int[strLengths.length];
105:
106: int remainingLength = targetLength;
107: int starsCount = 0;
108: for (int i = 0; i < lengths.length; i++) {
109: String strLen = strLengths[i];
110: if (strLen.endsWith("%")) {
111: lengths[i] = targetLength * cutTailAndParseInt(strLen)
112: / 100;
113: } else if (strLen.endsWith("*")) {
114: // we'll just count '*' during this pass
115: lengths[i] = 0;
116: starsCount += cutTailAndParseInt(strLen);
117: } else {
118: lengths[i] = Integer.parseInt(strLen);
119: }
120: remainingLength -= lengths[i];
121: }
122:
123: // allocate space for '*' frames
124: int starsLength = Math.max(remainingLength, 0);
125: if (starsCount > 0) {
126: for (int i = 0; i < lengths.length; i++) {
127: String strLen = strLengths[i];
128: if (strLen.endsWith("*")) {
129: lengths[i] = starsLength
130: * cutTailAndParseInt(strLen) / starsCount;
131: remainingLength -= lengths[i];
132: }
133: }
134: }
135:
136: normalizeLengths(lengths, targetLength, targetLength
137: - remainingLength);
138: return lengths;
139: }
140:
141: private int cutTailAndParseInt(final String str) {
142: if ("*".equals(str)) {
143: return 1;
144: }
145: return Integer.parseInt(str.substring(0, str.length() - 1));
146: }
147:
148: private void normalizeLengths(final int[] lengths,
149: final int targetLength, final int allocatedLength) {
150: if (targetLength == allocatedLength || allocatedLength == 0) {
151: return;
152: } else if (Math.abs(targetLength - allocatedLength) < lengths.length) {
153: lengths[lengths.length - 1] += targetLength
154: - allocatedLength;
155: return;
156: }
157:
158: int usedLength = 0;
159: for (int i = 0; i < lengths.length; i++) {
160: lengths[i] = lengths[i] * targetLength / allocatedLength;
161: usedLength += lengths[i];
162: }
163:
164: lengths[lengths.length - 1] += targetLength - usedLength;
165: }
166:
167: private static String[] parseLengths(final String lengths) {
168: if (lengths == null) {
169: return new String[] { "100%" };
170: }
171:
172: return lengths.split(", *");
173: }
174:
175: private static int calculateMajorAxis(final Element elem) {
176: return elem.getAttributes().isDefined(HTML.Attribute.ROWS) ? Y_AXIS
177: : X_AXIS;
178: }
179:
180: private boolean hasNoFramesView() {
181: if (getViewCount() == 0) {
182: return false;
183: }
184: return getView(getViewCount() - 1) instanceof NoFramesTagView;
185: }
186: }
|