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.Arrays;
026: import java.util.HashMap;
027: import java.util.HashSet;
028: import java.util.LinkedList;
029: import java.util.Map;
030: import java.util.Set;
031:
032: import org.apache.harmony.awt.FieldsAccessor;
033: import org.apache.harmony.awt.internal.nls.Messages;
034: import org.apache.harmony.awt.wtk.NativeWindow;
035:
036: public class BorderLayout implements LayoutManager2, Serializable {
037: private static final long serialVersionUID = -8658291919501921765L;
038:
039: public static final String BEFORE_LINE_BEGINS = "Before"; //$NON-NLS-1$
040: public static final String BEFORE_FIRST_LINE = "First"; //$NON-NLS-1$
041: public static final String AFTER_LINE_ENDS = "After"; //$NON-NLS-1$
042: public static final String AFTER_LAST_LINE = "Last"; //$NON-NLS-1$
043: public static final String LINE_START = "Before"; //$NON-NLS-1$
044: public static final String PAGE_START = "First"; //$NON-NLS-1$
045: public static final String LINE_END = "After"; //$NON-NLS-1$
046: public static final String PAGE_END = "Last"; //$NON-NLS-1$
047: public static final String CENTER = "Center"; //$NON-NLS-1$
048: public static final String NORTH = "North"; //$NON-NLS-1$
049: public static final String SOUTH = "South"; //$NON-NLS-1$
050: public static final String EAST = "East"; //$NON-NLS-1$
051: public static final String WEST = "West"; //$NON-NLS-1$
052:
053: private static final Set<String> supportedConstraints = new HashSet<String>();
054:
055: private static final int DEFAULT_GAP = 0;
056: private static final int MAX_COMPONENTS = 5;
057:
058: private static final int C = 0;
059: private static final int N = 1;
060: private static final int S = 2;
061: private static final int E = 3;
062: private static final int W = 4;
063:
064: private static final Dimension dummyDimension = new Dimension(0, 0);
065:
066: private final transient Toolkit toolkit;
067:
068: private final LinkedList<Component> components;
069: private final Map<Component, Object> components2Constraints;
070: private final Map<Object, Component> constraints2Components;
071:
072: private int hGap;
073: private int vGap;
074:
075: private boolean valid;
076: /* Cached data */
077: private final Component[] visibleComponents;
078: private final Dimension[] minCompSizes;
079: private final Dimension[] prefCompSizes;
080: private int vGapOverhead;
081: private int hGapOverhead;
082: private int visibleComponentsNumber;
083:
084: static {
085: supportedConstraints.add(LINE_START);
086: supportedConstraints.add(PAGE_START);
087: supportedConstraints.add(LINE_END);
088: supportedConstraints.add(PAGE_END);
089: supportedConstraints.add(CENTER);
090: supportedConstraints.add(NORTH);
091: supportedConstraints.add(SOUTH);
092: supportedConstraints.add(WEST);
093: supportedConstraints.add(EAST);
094: }
095:
096: public BorderLayout(int hgap, int vgap) {
097: toolkit = Toolkit.getDefaultToolkit();
098:
099: toolkit.lockAWT();
100: try {
101: components = new LinkedList<Component>();
102: components2Constraints = new HashMap<Component, Object>();
103: constraints2Components = new HashMap<Object, Component>();
104:
105: hGap = hgap;
106: vGap = vgap;
107:
108: valid = false;
109: visibleComponents = new Component[MAX_COMPONENTS];
110: minCompSizes = new Dimension[MAX_COMPONENTS];
111: prefCompSizes = new Dimension[MAX_COMPONENTS];
112: vGapOverhead = 0;
113: hGapOverhead = 0;
114: visibleComponentsNumber = 0;
115: } finally {
116: toolkit.unlockAWT();
117: }
118: }
119:
120: public BorderLayout() {
121: this (DEFAULT_GAP, DEFAULT_GAP);
122: toolkit.lockAWT();
123: try {
124: } finally {
125: toolkit.unlockAWT();
126: }
127: }
128:
129: /**
130: * @deprecated
131: */
132: @Deprecated
133: public void addLayoutComponent(String name, Component comp) {
134: toolkit.lockAWT();
135: try {
136: Object cons;
137: Component comp2Forget;
138:
139: if (name == null) {
140: cons = CENTER;
141: } else {
142: cons = name;
143: if (!supportedConstraints.contains(cons)) {
144: // awt.91=Unsupported constraints object: {0}
145: throw new IllegalArgumentException(Messages
146: .getString("awt.91", cons)); //$NON-NLS-1$
147: }
148: }
149:
150: if ((constraints2Components.get(cons) == comp)
151: && (components2Constraints.get(comp) == cons)) {
152: return;
153: }
154:
155: comp2Forget = constraints2Components.get(cons);
156: if (comp2Forget != null) {
157: forgetComponent(comp2Forget, cons);
158: }
159: if (components.contains(comp)) {
160: forgetComponent(comp, cons);
161: }
162:
163: components.addFirst(comp);
164: components2Constraints.put(comp, cons);
165: constraints2Components.put(cons, comp);
166: } finally {
167: toolkit.unlockAWT();
168: }
169: }
170:
171: public void addLayoutComponent(Component comp, Object constraints) {
172: toolkit.lockAWT();
173: try {
174: if (comp == null) {
175: throw new NullPointerException("Component is null");
176: }
177: if ((constraints == null)
178: || (constraints instanceof String)) {
179: addLayoutComponent((String) constraints, comp);
180: } else {
181: // awt.92=Constraints object must be String
182: throw new IllegalArgumentException(Messages
183: .getString("awt.92")); //$NON-NLS-1$
184: }
185: } finally {
186: toolkit.unlockAWT();
187: }
188: }
189:
190: public void removeLayoutComponent(Component comp) {
191: toolkit.lockAWT();
192: try {
193: Object cons = components2Constraints.get(comp);
194:
195: if (cons != null) {
196: forgetComponent(comp, cons);
197: }
198: } finally {
199: toolkit.unlockAWT();
200: }
201: }
202:
203: public Component getLayoutComponent(Object constraints) {
204: toolkit.lockAWT();
205: try {
206: if (!supportedConstraints.contains(constraints)) {
207: throw new IllegalArgumentException(
208: // awt.91=Unsupported constraints object: {0}
209: Messages.getString("awt.91", constraints)); //$NON-NLS-1$
210: }
211:
212: return constraints2Components.get(constraints);
213: } finally {
214: toolkit.unlockAWT();
215: }
216: }
217:
218: public Component getLayoutComponent(Container target,
219: Object constraints) {
220: boolean l2r = target.getComponentOrientation().isLeftToRight();
221: if (NORTH.equals(constraints)) {
222: return getComponent(PAGE_START, NORTH);
223: } else if (SOUTH.equals(constraints)) {
224: return getComponent(PAGE_END, SOUTH);
225: } else if (EAST.equals(constraints)) {
226: return getComponent(l2r ? LINE_END : LINE_START, EAST);
227: } else if (WEST.equals(constraints)) {
228: return getComponent(l2r ? LINE_START : LINE_END, WEST);
229: } else if (CENTER.equals(constraints)) {
230: return constraints2Components.get(CENTER);
231: }
232: // awt.93=cannot get component: invalid constraint: {0}
233: throw new IllegalArgumentException(Messages.getString("awt.93", //$NON-NLS-1$
234: constraints));
235: }
236:
237: private Component getComponent(Object relCons, Object absCons) {
238: Component comp = constraints2Components.get(relCons);
239: if (comp != null) {
240: return comp;
241: }
242: return constraints2Components.get(absCons);
243: }
244:
245: public Object getConstraints(Component comp) {
246: if (comp == null) {
247: return comp;
248: }
249:
250: return components2Constraints.get(comp);
251: }
252:
253: public void invalidateLayout(Container target) {
254: toolkit.lockAWT();
255: try {
256: valid = false;
257: } finally {
258: toolkit.unlockAWT();
259: }
260: }
261:
262: public Dimension maximumLayoutSize(Container target) {
263: toolkit.lockAWT();
264: try {
265: return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
266: } finally {
267: toolkit.unlockAWT();
268: }
269: }
270:
271: public Dimension minimumLayoutSize(Container target) {
272: toolkit.lockAWT();
273: try {
274: boolean wasValid = valid;
275: validate(target);
276: valid = wasValid;
277:
278: if (visibleComponentsNumber == 0) {
279: return target.addInsets(new Dimension(0, 0));
280: }
281:
282: return target.addInsets(calculateLayoutSize(minCompSizes));
283: } finally {
284: toolkit.unlockAWT();
285: }
286: }
287:
288: public Dimension preferredLayoutSize(Container target) {
289: toolkit.lockAWT();
290: try {
291: boolean wasValid = valid;
292: validate(target);
293: valid = wasValid;
294:
295: return target.addInsets(calculateLayoutSize(prefCompSizes));
296: } finally {
297: toolkit.unlockAWT();
298: }
299: }
300:
301: public void layoutContainer(Container target) {
302: toolkit.lockAWT();
303: try {
304: validate(target);
305:
306: if (visibleComponentsNumber != 0) {
307: Rectangle clientRect = target.getClient();
308:
309: if (clientRect.isEmpty()) {
310: resetBounds(clientRect);
311: } else {
312: setBounds(clientRect);
313: }
314: }
315: } finally {
316: toolkit.unlockAWT();
317: }
318: }
319:
320: public int getHgap() {
321: toolkit.lockAWT();
322: try {
323: return hGap;
324: } finally {
325: toolkit.unlockAWT();
326: }
327: }
328:
329: public void setHgap(int hgap) {
330: toolkit.lockAWT();
331: try {
332: hGap = hgap;
333: } finally {
334: toolkit.unlockAWT();
335: }
336: }
337:
338: public int getVgap() {
339: toolkit.lockAWT();
340: try {
341: return vGap;
342: } finally {
343: toolkit.unlockAWT();
344: }
345: }
346:
347: public void setVgap(int vgap) {
348: toolkit.lockAWT();
349: try {
350: vGap = vgap;
351: } finally {
352: toolkit.unlockAWT();
353: }
354: }
355:
356: @Override
357: public String toString() {
358: /* The format is based on 1.5 release behavior
359: * which can be revealed by the following code:
360: * System.out.println(new BorderLayout());
361: */
362:
363: toolkit.lockAWT();
364: try {
365: return getClass().getName()
366: + "[hgap=" + hGap + ",vgap=" + vGap + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
367: } finally {
368: toolkit.unlockAWT();
369: }
370: }
371:
372: public float getLayoutAlignmentX(Container parent) {
373: toolkit.lockAWT();
374: try {
375: return Component.CENTER_ALIGNMENT;
376: } finally {
377: toolkit.unlockAWT();
378: }
379: }
380:
381: public float getLayoutAlignmentY(Container parent) {
382: toolkit.lockAWT();
383: try {
384: return Component.CENTER_ALIGNMENT;
385: } finally {
386: toolkit.unlockAWT();
387: }
388: }
389:
390: private void validate(Container target) {
391: if (valid) {
392: return;
393: }
394: valid = true;
395:
396: validateArrays(target);
397: if (visibleComponentsNumber != 0) {
398: validateGaps();
399: }
400: }
401:
402: private void validateGaps() {
403: int h = -1;
404:
405: if (visibleComponents[N] != null) {
406: h++;
407: }
408: if (visibleComponents[S] != null) {
409: h++;
410: }
411: if ((visibleComponents[C] != null)
412: || (visibleComponents[W] != null)
413: || (visibleComponents[E] != null)) {
414: hGapOverhead = (visibleComponentsNumber - h - 2) * hGap;
415: h++;
416: } else {
417: hGapOverhead = 0;
418: }
419: vGapOverhead = h * vGap;
420: }
421:
422: private void validateArrays(Container target) {
423: Arrays.fill(minCompSizes, dummyDimension);
424: Arrays.fill(prefCompSizes, dummyDimension);
425: Arrays.fill(visibleComponents, null);
426: visibleComponentsNumber = 0;
427:
428: for (Component comp : components) {
429: int index = constraints2Index(components2Constraints
430: .get(comp), target.getComponentOrientation());
431:
432: if (comp.isVisible()) {
433: if (visibleComponents[index] == null) {
434: visibleComponents[index] = comp;
435: visibleComponentsNumber++;
436: minCompSizes[index] = comp.getMinimumSize();
437: prefCompSizes[index] = comp.getPreferredSize();
438: }
439: } else if (visibleComponents[index] == null) {
440: minCompSizes[index] = comp.getMinimumSize();
441: prefCompSizes[index] = comp.getPreferredSize();
442: }
443: }
444: }
445:
446: private int constraints2Index(Object cons,
447: ComponentOrientation orientation) {
448: if (cons.equals(CENTER)) {
449: return C;
450: } else if (cons.equals(NORTH)) {
451: return N;
452: } else if (cons.equals(SOUTH)) {
453: return S;
454: } else if (cons.equals(WEST)) {
455: return W;
456: } else if (cons.equals(EAST)) {
457: return E;
458: } else if (cons.equals(LINE_START)) {
459: return (!orientation.isLeftToRight() ? E : W);
460: } else if (cons.equals(LINE_END)) {
461: return (!orientation.isLeftToRight() ? W : E);
462: } else if (cons.equals(PAGE_START)) {
463: return N;
464: } else {//if (cons.equals(PAGE_END))
465: return S;
466: }
467: }
468:
469: private Dimension calculateLayoutSize(Dimension[] sizes) {
470: int w = Math.max(sizes[N].width, Math.max(sizes[S].width,
471: sizes[W].width + sizes[C].width + sizes[E].width
472: + hGapOverhead));
473: int h = sizes[N].height
474: + sizes[S].height
475: + Math.max(sizes[C].height, Math.max(sizes[W].height,
476: sizes[E].height)) + vGapOverhead;
477:
478: return new Dimension(w, h);
479: }
480:
481: private void setBounds(Rectangle clientRect) {
482: int centerX = clientRect.x;
483: int middleY = clientRect.y;
484:
485: if (visibleComponents[N] != null) {
486: visibleComponents[N].setSize(clientRect.width,
487: prefCompSizes[N].height);
488: visibleComponents[N].setBounds(clientRect.x, clientRect.y,
489: clientRect.width, prefCompSizes[N].height,
490: NativeWindow.BOUNDS_NOSIZE, true);
491: middleY += prefCompSizes[N].height + vGap;
492: }
493: int middleHeight = clientRect.height - prefCompSizes[N].height
494: - prefCompSizes[S].height - vGapOverhead;
495: middleHeight = Math.max(middleHeight, 0);
496: if (visibleComponents[W] != null) {
497: visibleComponents[W].setSize(prefCompSizes[W].width,
498: middleHeight);
499: visibleComponents[W].setBounds(clientRect.x, middleY,
500: prefCompSizes[W].width, middleHeight,
501: NativeWindow.BOUNDS_NOSIZE, true);
502: centerX += prefCompSizes[W].width + hGap;
503: }
504: int middleWidth = clientRect.width - prefCompSizes[W].width
505: - prefCompSizes[E].width - hGapOverhead;
506: middleWidth = Math.max(middleWidth, 0);
507: if (visibleComponents[C] != null) {
508: visibleComponents[C].setBounds(centerX, middleY,
509: middleWidth, middleHeight);
510: }
511: if (visibleComponents[S] != null) {
512: visibleComponents[S].setSize(clientRect.width,
513: prefCompSizes[S].height);
514: visibleComponents[S].setBounds(clientRect.x, clientRect.y
515: + clientRect.height - prefCompSizes[S].height,
516: clientRect.width, prefCompSizes[S].height,
517: NativeWindow.BOUNDS_NOSIZE, true);
518: }
519: if (visibleComponents[E] != null) {
520: visibleComponents[E].setSize(prefCompSizes[E].width,
521: middleHeight);
522: visibleComponents[E].setBounds(clientRect.x
523: + clientRect.width - prefCompSizes[E].width,
524: middleY, prefCompSizes[E].width, middleHeight,
525: NativeWindow.BOUNDS_NOSIZE, true);
526: }
527: }
528:
529: private void resetBounds(Rectangle clientRect) {
530: for (int i = 0; i < MAX_COMPONENTS; i++) {
531: Component comp = visibleComponents[i];
532:
533: if (comp != null) {
534: comp.setBounds(clientRect.x, clientRect.y, 0, 0);
535: }
536: }
537: }
538:
539: private void readObject(ObjectInputStream stream)
540: throws IOException, ClassNotFoundException {
541: stream.defaultReadObject();
542:
543: FieldsAccessor accessor = new FieldsAccessor(
544: BorderLayout.class, this );
545: accessor.set("toolkit", Toolkit.getDefaultToolkit()); //$NON-NLS-1$
546: }
547:
548: private void forgetComponent(Component comp, Object cons) {
549: components.remove(comp);
550: components2Constraints.remove(comp);
551: constraints2Components.remove(cons);
552: }
553:
554: }
|