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 Michael Danilov
019: * @version $Revision$
020: */package java.awt;
021:
022: import java.io.IOException;
023: import java.io.ObjectInputStream;
024: import java.io.Serializable;
025: import java.util.*;
026:
027: import org.apache.harmony.awt.FieldsAccessor;
028:
029: public class FlowLayout implements LayoutManager, Serializable {
030: private static final long serialVersionUID = -7262534875583282631L;
031:
032: public static final int LEFT = 0;
033: public static final int CENTER = 1;
034: public static final int RIGHT = 2;
035: public static final int LEADING = 3;
036: public static final int TRAILING = 4;
037:
038: private static final int DEFAULT_GAP = 5;
039:
040: private final transient Toolkit toolkit = Toolkit
041: .getDefaultToolkit();
042:
043: private int hGap;
044: private int vGap;
045: private int alignment;
046:
047: private transient Component[] components;
048:
049: public FlowLayout(int align) {
050: this (align, DEFAULT_GAP, DEFAULT_GAP);
051: toolkit.lockAWT();
052: try {
053: } finally {
054: toolkit.unlockAWT();
055: }
056: }
057:
058: public FlowLayout() {
059: this (CENTER, DEFAULT_GAP, DEFAULT_GAP);
060: toolkit.lockAWT();
061: try {
062: } finally {
063: toolkit.unlockAWT();
064: }
065: }
066:
067: public FlowLayout(int align, int hgap, int vgap) {
068: toolkit.lockAWT();
069: try {
070: hGap = hgap;
071: vGap = vgap;
072: alignment = align;
073: } finally {
074: toolkit.unlockAWT();
075: }
076: }
077:
078: @Override
079: public String toString() {
080: /* The format is based on 1.5 release behavior
081: * which can be revealed by the following code:
082: * System.out.println(new FlowLayout());
083: */
084:
085: toolkit.lockAWT();
086: try {
087: String alignStr;
088: switch (alignment) {
089: case LEFT:
090: alignStr = "left"; //$NON-NLS-1$
091: break;
092: case RIGHT:
093: alignStr = "right"; //$NON-NLS-1$
094: break;
095: case CENTER:
096: alignStr = "center"; //$NON-NLS-1$
097: break;
098: case TRAILING:
099: alignStr = "trailing"; //$NON-NLS-1$
100: break;
101: case LEADING:
102: default:
103: alignStr = "leading"; //$NON-NLS-1$
104: }
105: return (getClass().getName()
106: + "[hgap=" + hGap + ",vgap=" + vGap + //$NON-NLS-1$ //$NON-NLS-2$
107: ",align=" + alignStr + "]"); //$NON-NLS-1$ //$NON-NLS-2$
108: } finally {
109: toolkit.unlockAWT();
110: }
111: }
112:
113: public void addLayoutComponent(String name, Component comp) {
114: // do nothing here according to spec
115: }
116:
117: public int getAlignment() {
118: toolkit.lockAWT();
119: try {
120: return alignment;
121: } finally {
122: toolkit.unlockAWT();
123: }
124: }
125:
126: public int getHgap() {
127: toolkit.lockAWT();
128: try {
129: return hGap;
130: } finally {
131: toolkit.unlockAWT();
132: }
133: }
134:
135: public int getVgap() {
136: toolkit.lockAWT();
137: try {
138: return vGap;
139: } finally {
140: toolkit.unlockAWT();
141: }
142: }
143:
144: public void layoutContainer(Container target) {
145: toolkit.lockAWT();
146: try {
147: components = target.getComponents();
148: if (getComponentsNumber() == 0) {
149: return;
150: }
151: doLayoutContainer(target);
152: } finally {
153: toolkit.unlockAWT();
154: }
155: }
156:
157: private void doLayoutContainer(Container target) {
158: Rectangle clientRect = target.getClient();
159: Insets insets = target.getInsets();
160: boolean l2r = target.getComponentOrientation().isLeftToRight();
161: ArrayList<Component> rowComponents = new ArrayList<Component>();
162: int initW = 2 * hGap;
163: int w = initW;
164: int y = insets.top + vGap;
165: int maxH = 0;
166: boolean first = true;
167:
168: for (Component component : getComponentsZOrder(target)) {
169: if ((component == null) || !component.isVisible()) {
170: continue;
171: }
172:
173: Dimension cd = component.getPreferredSize();
174:
175: if (!first && ((w + cd.width) > clientRect.width)) {
176: layoutRow(rowComponents, clientRect.width - (w - hGap),
177: insets.left, y, maxH, l2r);
178: rowComponents.clear();
179:
180: w = initW;
181: y += maxH + vGap;
182: maxH = 0;
183: }
184: first = false;
185: rowComponents.add(component);
186: w += cd.width + hGap;
187: maxH = Math.max(maxH, cd.height);
188: }
189: layoutRow(rowComponents, clientRect.width - (w - hGap),
190: insets.left, y, maxH, l2r);
191: }
192:
193: public Dimension minimumLayoutSize(Container target) {
194: toolkit.lockAWT();
195: try {
196: components = target.getComponents();
197: if (getComponentsNumber() == 0) {
198: // not (0,0) for compatibility!
199: return target.addInsets(new Dimension(10, 10));
200: }
201:
202: return target.addInsets(layoutSize(false));
203: } finally {
204: toolkit.unlockAWT();
205: }
206: }
207:
208: public Dimension preferredLayoutSize(Container target) {
209: toolkit.lockAWT();
210: try {
211: components = target.getComponents();
212:
213: if (getComponentsNumber() == 0) {
214: // not (0,0) for compatibility!
215: return target.addInsets(new Dimension(10, 10));
216: }
217:
218: return target.addInsets(layoutSize(true));
219: } finally {
220: toolkit.unlockAWT();
221: }
222: }
223:
224: public void removeLayoutComponent(Component comp) {
225: // do nothing here according to spec
226: }
227:
228: public void setAlignment(int align) {
229: toolkit.lockAWT();
230: try {
231: alignment = align;
232: } finally {
233: toolkit.unlockAWT();
234: }
235: }
236:
237: public void setHgap(int hgap) {
238: toolkit.lockAWT();
239: try {
240: hGap = hgap;
241: } finally {
242: toolkit.unlockAWT();
243: }
244: }
245:
246: public void setVgap(int vgap) {
247: toolkit.lockAWT();
248: try {
249: vGap = vgap;
250: } finally {
251: toolkit.unlockAWT();
252: }
253: }
254:
255: private void layoutRow(ArrayList<Component> rowComponents,
256: int freeW, int x, int y, int maxH, boolean l2r) {
257: x += hGap;
258: switch (alignment) {
259: case LEFT:
260: break;
261: case RIGHT:
262: x += freeW;
263: break;
264: case CENTER:
265: x += freeW / 2;
266: break;
267: case TRAILING:
268: x += !l2r ? 0 : freeW;
269: break;
270: case LEADING:
271: default: // any invalid alignment is treated as LEADING
272: x += l2r ? 0 : freeW;
273: break;
274: }
275:
276: int lastInd = rowComponents.size() - 1;
277: for (int i = 0; i <= lastInd; i++) {
278: Component c = rowComponents.get(l2r ? i : lastInd - i);
279: Dimension d = c.getPreferredSize();
280: c
281: .setBounds(x, y + (maxH - d.height) / 2, d.width,
282: d.height);
283: x += d.width + hGap;
284: }
285: }
286:
287: private int getComponentsNumber() {
288: int componentsNumber = 0;
289: int i = 0;
290: while (i < components.length) {
291: if (components[i].isVisible()) {
292: componentsNumber++;
293: }
294: i++;
295: }
296:
297: return componentsNumber;
298: }
299:
300: private Dimension layoutSize(boolean preferred) {
301: int w = hGap;
302: int maxH = 0;
303:
304: for (Component component : components) {
305: if (component.isVisible()) {
306: Dimension cd = preferred ? component.getPreferredSize()
307: : component.getMinimumSize();
308: maxH = Math.max(maxH, cd.height);
309: w += cd.width + hGap;
310: }
311: }
312:
313: return new Dimension(w, maxH + 2 * vGap);
314: }
315:
316: private ArrayList<Component> getComponentsZOrder(Container target) {
317: int capacity = target.getComponentCount();
318: ArrayList<Component> zComponents = new ArrayList<Component>(
319: capacity);
320:
321: for (int i = 0; i < capacity; i++) {
322: zComponents.add(null);
323: }
324:
325: for (Component component : components) {
326: if (component.getParent() == target) {
327: zComponents.set(target.getComponentZOrder(component),
328: component);
329: }
330: }
331:
332: return zComponents;
333: }
334:
335: private void readObject(ObjectInputStream stream)
336: throws IOException, ClassNotFoundException {
337:
338: stream.defaultReadObject();
339:
340: FieldsAccessor accessor = new FieldsAccessor(FlowLayout.class,
341: this );
342: accessor.set("toolkit", Toolkit.getDefaultToolkit()); //$NON-NLS-1$
343: }
344: }
|