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 Alexander T. Simbirtsev
019: * @version $Revision$
020: */package org.apache.harmony.x.swing;
021:
022: import javax.swing.SizeRequirements;
023:
024: /**
025: * Helper object which wraps functionality of javax.swing.SizeRequirements
026: * so that it can be easily used by javax.swing.text.BoxView.
027: *
028: */
029: public final class SizeRequirementsHelper {
030: /**
031: * @see javax.swing.SizeRequirements#getTiledSizeRequirements(SizeRequirements[])
032: *
033: * @param sr SizeRequirements where results to be copied. If sr is null, new object is created
034: *
035: * @return SizeRequirements sr or newly created object
036: */
037: public static SizeRequirements getTiledSizeRequirements(
038: final SizeRequirements[] children, final SizeRequirements sr) {
039:
040: SizeRequirements result = (sr != null) ? sr
041: : new SizeRequirements();
042: result.minimum = 0;
043: result.preferred = 0;
044: result.maximum = 0;
045: result.alignment = 0.5f;
046:
047: for (int iChild = 0; iChild < children.length; iChild++) {
048: result.minimum = Utilities.safeIntSum(
049: children[iChild].minimum, result.minimum);
050: result.preferred = Utilities.safeIntSum(
051: children[iChild].preferred, result.preferred);
052: result.maximum = Utilities.safeIntSum(
053: children[iChild].maximum, result.maximum);
054: }
055:
056: return result;
057: }
058:
059: /**
060: * @see javax.swing.SizeRequirements#getAlignedSizeRequirements(SizeRequirements[])
061: *
062: * @param sr SizeRequirements where results to be copied. If sr is null, new object is created
063: * @param alignByPreferred boolean value representing which size (preferred or minimal) should be used for alignment calculation
064: *
065: * @return SizeRequirements sr or newly created object
066: */
067: public static SizeRequirements getAlignedSizeRequirements(
068: final SizeRequirements[] children,
069: final SizeRequirements sr, final boolean alignByPreferred) {
070:
071: int minRight = 0;
072: int minLeft = 0;
073: int prefRight = 0;
074: int prefLeft = 0;
075: int maxRight = 0;
076: int maxLeft = 0;
077:
078: for (int iChild = 0; iChild < children.length; iChild++) {
079: int alignedMin = (int) (children[iChild].alignment * children[iChild].minimum);
080: minLeft = Math.max(minLeft, alignedMin);
081: minRight = Math.max(minRight, children[iChild].minimum
082: - alignedMin);
083:
084: int alignedPref = (int) (children[iChild].alignment * children[iChild].preferred);
085: prefLeft = Math.max(prefLeft, alignedPref);
086: prefRight = Math.max(prefRight, children[iChild].preferred
087: - alignedPref);
088:
089: int alignedMax = (int) (children[iChild].alignment * children[iChild].maximum);
090: maxLeft = Math.max(maxLeft, alignedMax);
091: maxRight = Math.max(maxRight, children[iChild].maximum
092: - alignedMax);
093: }
094:
095: SizeRequirements result = (sr != null) ? sr
096: : new SizeRequirements();
097: result.minimum = Utilities.safeIntSum(minRight, minLeft);
098: result.preferred = Utilities.safeIntSum(prefRight, prefLeft);
099: result.maximum = Utilities.safeIntSum(maxRight, maxLeft);
100: if (alignByPreferred) {
101: result.alignment = (result.preferred != 0) ? (float) prefLeft
102: / result.preferred
103: : 0;
104: } else {
105: result.alignment = (result.minimum != 0) ? (float) minLeft
106: / result.minimum : 0;
107: }
108:
109: return result;
110: }
111:
112: /**
113: * @see javax.swing.SizeRequirements#calculateTiledPositions(int, SizeRequirements, SizeRequirements[], int[], int[], boolean)
114: */
115: public static void calculateTiledPositions(final int allocated,
116: final SizeRequirements total,
117: final SizeRequirements[] children, final int[] offsets,
118: final int[] spans, final boolean normal) {
119:
120: calculateTiledSpans(allocated, total, children, spans);
121:
122: if (normal) {
123: int curOffset = 0;
124: for (int iChild = 0; iChild < children.length; iChild++) {
125: offsets[iChild] = curOffset;
126: curOffset += spans[iChild];
127: }
128: } else {
129: int curOffset = allocated;
130: for (int iChild = 0; iChild < children.length; iChild++) {
131: curOffset -= spans[iChild];
132: offsets[iChild] = curOffset;
133: }
134: }
135: }
136:
137: /**
138: * @see javax.swing.SizeRequirements#calculateAlignedPositions(int, SizeRequirements, SizeRequirements[], int[], int[], boolean)
139: */
140: public static void calculateAlignedPositions(final int allocated,
141: final SizeRequirements total,
142: final SizeRequirements[] children, final int[] offsets,
143: final int[] spans, final boolean normal) {
144:
145: final int alignedAllocated = (int) (allocated * total.alignment);
146: for (int iChild = 0; iChild < children.length; iChild++) {
147: spans[iChild] = children[iChild].maximum;
148: offsets[iChild] = alignedAllocated
149: - (int) (children[iChild].maximum * children[iChild].alignment);
150:
151: if (offsets[iChild] < 0) {
152: spans[iChild] = spans[iChild] + offsets[iChild];
153: offsets[iChild] = 0;
154: }
155: if (offsets[iChild] + spans[iChild] > allocated) {
156: spans[iChild] = allocated - offsets[iChild];
157: }
158: }
159: if (!normal) {
160: for (int iChild = 0; iChild < children.length; iChild++) {
161: offsets[iChild] = allocated - offsets[iChild]
162: - spans[iChild];
163: }
164: }
165: }
166:
167: /**
168: * @see javax.swing.SizeRequirements#calculateAlignedPositions(int, SizeRequirements, SizeRequirements[], int[], int[])
169: */
170: public static void calculateAlignedPositions(final int allocated,
171: final SizeRequirements total,
172: final SizeRequirements[] children, final int[] offsets,
173: final int[] spans) {
174:
175: int baseLineOffset = (int) (allocated * total.alignment);
176: int childMinRequirement;
177:
178: for (int iChild = 0; iChild < children.length; iChild++) {
179: childMinRequirement = children[iChild].minimum;
180:
181: if (children[iChild].alignment == 0) {
182: offsets[iChild] = baseLineOffset;
183: if (allocated - baseLineOffset > childMinRequirement) {
184: spans[iChild] = Math.min(children[iChild].maximum,
185: allocated - baseLineOffset);
186: } else {
187: spans[iChild] = childMinRequirement;
188: }
189: continue;
190: }
191:
192: if (children[iChild].alignment == 1) {
193: if (baseLineOffset < childMinRequirement) {
194: spans[iChild] = childMinRequirement;
195: } else {
196: spans[iChild] = Math.min(children[iChild].maximum,
197: baseLineOffset);
198: }
199: offsets[iChild] = baseLineOffset - spans[iChild];
200: continue;
201: }
202:
203: int upperSpan = (int) (baseLineOffset / children[iChild].alignment);
204: int bottomSpan = (int) ((allocated - baseLineOffset) / (1 - children[iChild].alignment));
205:
206: spans[iChild] = childMinRequirement;
207: if (childMinRequirement <= upperSpan
208: && childMinRequirement <= bottomSpan) {
209: spans[iChild] = Math.min(children[iChild].maximum, Math
210: .min(upperSpan, bottomSpan));
211: }
212: offsets[iChild] = baseLineOffset
213: - (int) (spans[iChild] * children[iChild].alignment);
214: }
215: }
216:
217: private static void calculateTiledSpans(final int allocated,
218: final SizeRequirements total,
219: final SizeRequirements[] children, final int[] spans) {
220:
221: if (total.preferred <= allocated) {
222: if (total.maximum <= allocated) {
223: for (int iChild = 0; iChild < children.length; iChild++) {
224: spans[iChild] = children[iChild].maximum;
225: }
226: } else {
227: int allocatedDelta = allocated - total.preferred;
228: long maxDelta = 0;
229: for (int iChild = 0; iChild < children.length; iChild++) {
230: maxDelta += children[iChild].maximum
231: - children[iChild].preferred;
232: }
233: for (int iChild = 0; iChild < children.length; iChild++) {
234: spans[iChild] = children[iChild].preferred
235: + safeIntRatio(
236: allocatedDelta,
237: children[iChild].maximum
238: - children[iChild].preferred,
239: maxDelta);
240: }
241: }
242: } else {
243: if (total.minimum < allocated) {
244: int allocatedDelta = allocated - total.minimum;
245: long prefDelta = 0;
246: for (int iChild = 0; iChild < children.length; iChild++) {
247: prefDelta += children[iChild].preferred
248: - children[iChild].minimum;
249: }
250: for (int iChild = 0; iChild < children.length; iChild++) {
251: spans[iChild] = children[iChild].minimum
252: + safeIntRatio(allocatedDelta,
253: children[iChild].preferred
254: - children[iChild].minimum,
255: prefDelta);
256: }
257: } else {
258: for (int iChild = 0; iChild < children.length; iChild++) {
259: spans[iChild] = children[iChild].minimum;
260: }
261: }
262: }
263: }
264:
265: /**
266: * Returns ratio of two integers multiplied by the third one.
267: * Avoid "division by zero" problem if the divider is 0.
268: * This function prevents wrong results when arguments are close
269: * to Integer.MAX_VALUE
270: *
271: * @param item1 the first multiplier
272: * @param item2 the second multiplier
273: * @param item3 divisor
274: * @return the ratio of (item1 * item2 / item3)
275: */
276: private static int safeIntRatio(final long item1, final long item2,
277: final long item3) {
278: return (item3 != 0) ? (int) ((item1 * item2) / item3) : 0;
279: }
280: }
|