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 javax.swing;
021:
022: import java.awt.Component;
023: import java.awt.Container;
024: import java.awt.Dimension;
025: import java.awt.Insets;
026: import java.awt.Rectangle;
027:
028: import org.apache.harmony.x.swing.Utilities;
029:
030: /**
031: * This class helps BoxLayout and OverlayLayout to layout their components
032: * and calculate all target's necessary parameters. It incapsulates all necessary
033: * for calculations data.
034: *
035: */
036: final class LayoutParameters {
037:
038: public float alignmentX = 0.0f;
039: public float alignmentY = 0.0f;
040: public final Dimension minimumSize = new Dimension();
041: public final Dimension preferredSize = new Dimension();
042: public final Dimension maximumSize = new Dimension();
043:
044: public final static int MIXED_ALIGNMENT = 0;
045: public final static int HORIZONTAL_ALIGNMENT = 1;
046: public final static int VERTICAL_ALIGNMENT = 2;
047:
048: private SizeRequirements[] horRequirements = null;
049: private SizeRequirements[] vertRequirements = null;
050: private final SizeRequirements totalRequirements = new SizeRequirements();
051: private int[] offsetsX = null;
052: private int[] spansX = null;
053: private int[] offsetsY = null;
054: private int[] spansY = null;
055:
056: private boolean isValid = false;
057: private final Container target;
058: private int alignment;
059:
060: /**
061: *
062: * @param target - container being laid out with this parameters
063: * @param alignment - alignment of the target. It can be one of the following values:
064: * <code>MIXED_ALIGNMENT</code> - value for OverlayLayout
065: * <code>HORIZONTAL_ALIGNMENT</code> - value for BoxLayout with horizontal alignment
066: * <code>VERTICAL_ALIGNMENT</code> - value for BoxLayout with vertical alignment
067: */
068: public LayoutParameters(final Container target, final int alignment) {
069: this .target = target;
070: this .alignment = alignment;
071: }
072:
073: /**
074: * This method layouts target:
075: * calculates sizes an positions for all subcomponents
076: *
077: */
078: public void layoutTarget() {
079: calculateLayoutParameters();
080:
081: int numChildren = target.getComponentCount();
082: if (offsetsX == null || offsetsX.length != numChildren) {
083: offsetsX = new int[numChildren];
084: spansX = new int[numChildren];
085: offsetsY = new int[numChildren];
086: spansY = new int[numChildren];
087: }
088: final Insets insets = target.getInsets();
089: Rectangle innerSize = Utilities.subtractInsets(target
090: .getBounds(), insets);
091: totalRequirements.alignment = alignmentX;
092: if (alignment == HORIZONTAL_ALIGNMENT) {
093: SizeRequirements.calculateTiledPositions(innerSize.width,
094: totalRequirements, horRequirements, offsetsX,
095: spansX);
096: } else {
097: SizeRequirements.calculateAlignedPositions(innerSize.width,
098: totalRequirements, horRequirements, offsetsX,
099: spansX);
100: }
101: totalRequirements.alignment = alignmentY;
102: if (alignment == VERTICAL_ALIGNMENT) {
103: SizeRequirements.calculateTiledPositions(innerSize.height,
104: totalRequirements, vertRequirements, offsetsY,
105: spansY);
106: } else {
107: SizeRequirements.calculateAlignedPositions(
108: innerSize.height, totalRequirements,
109: vertRequirements, offsetsY, spansY);
110: }
111:
112: final boolean isLTR = target.getComponentOrientation()
113: .isLeftToRight();
114: final int offsetX = isLTR ? insets.left : target.getWidth()
115: - insets.right;
116: final int offsetY = insets.top;
117: for (int iChild = 0; iChild < numChildren; iChild++) {
118: final Component component = target.getComponent(iChild);
119: final int spanX = spansX[iChild] > 0 ? spansX[iChild] : 0;
120: final int spanY = spansY[iChild] > 0 ? spansY[iChild] : 0;
121: final int x = isLTR ? offsetsX[iChild] : -offsetsX[iChild]
122: - spanX;
123: component.setBounds(offsetX + x,
124: offsetY + offsetsY[iChild], spanX, spanY);
125: }
126: }
127:
128: /**
129: * fills arrays with target's subcomponents data
130: * required in futher calculations
131: */
132: private synchronized void fillRequirementArrays() {
133: int numChildren = target.getComponentCount();
134: if (horRequirements == null
135: || horRequirements.length != numChildren) {
136: horRequirements = new SizeRequirements[numChildren];
137: vertRequirements = new SizeRequirements[numChildren];
138: for (int iChild = 0; iChild < numChildren; iChild++) {
139: horRequirements[iChild] = new SizeRequirements();
140: vertRequirements[iChild] = new SizeRequirements();
141: }
142: }
143:
144: for (int iChild = 0; iChild < numChildren; iChild++) {
145: Component component = target.getComponent(iChild);
146: if (component.isVisible()) {
147: Dimension minSize = component.getMinimumSize();
148: Dimension prefSize = component.getPreferredSize();
149: Dimension maxSize = component.getMaximumSize();
150: horRequirements[iChild].set(minSize.width,
151: prefSize.width, maxSize.width, component
152: .getAlignmentX());
153: vertRequirements[iChild].set(minSize.height,
154: prefSize.height, maxSize.height, component
155: .getAlignmentY());
156: } else {
157: horRequirements[iChild].reset();
158: vertRequirements[iChild].reset();
159: }
160: }
161: }
162:
163: /**
164: * Calculates layout parameters:
165: * maximum, preferred and minimum sizes for container
166: */
167: public synchronized void calculateLayoutParameters() {
168: if (isValid) {
169: return;
170: }
171: fillRequirementArrays();
172:
173: Insets insets = target.getInsets();
174: int horzInsets = insets.left + insets.right;
175: int vertInsets = insets.top + insets.bottom;
176:
177: SizeRequirements resultedRequirements = null;
178: if (alignment == HORIZONTAL_ALIGNMENT) {
179: resultedRequirements = SizeRequirements
180: .getTiledSizeRequirements(horRequirements);
181: } else {
182: resultedRequirements = SizeRequirements
183: .getAlignedSizeRequirements(horRequirements);
184: }
185: alignmentX = resultedRequirements.alignment;
186: minimumSize.width = Utilities.safeIntSum(
187: resultedRequirements.minimum, horzInsets);
188: preferredSize.width = Utilities.safeIntSum(
189: resultedRequirements.preferred, horzInsets);
190: maximumSize.width = Utilities.safeIntSum(
191: resultedRequirements.maximum, horzInsets);
192:
193: if (alignment == VERTICAL_ALIGNMENT) {
194: resultedRequirements = SizeRequirements
195: .getTiledSizeRequirements(vertRequirements);
196: } else {
197: resultedRequirements = SizeRequirements
198: .getAlignedSizeRequirements(vertRequirements);
199: }
200: alignmentY = resultedRequirements.alignment;
201: minimumSize.height = Utilities.safeIntSum(
202: resultedRequirements.minimum, vertInsets);
203: preferredSize.height = Utilities.safeIntSum(
204: resultedRequirements.preferred, vertInsets);
205: maximumSize.height = Utilities.safeIntSum(
206: resultedRequirements.maximum, vertInsets);
207:
208: isValid = true;
209: }
210:
211: /**
212: * This method is to be invoked to notify LayoutParameters object, that target was changed somehow
213: * and all cached data became unreliable
214: */
215: public void invalidate() {
216: isValid = false;
217: }
218:
219: public int getAlignment() {
220: return alignment;
221: }
222:
223: public void setAlignment(final int alignment) {
224: if (this.alignment == alignment) {
225: return;
226: }
227: this.alignment = alignment;
228: invalidate();
229: }
230: }
|