blob: 52f6264967484ed8f03ebac0b4d96347dcd32791 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.rt.ui.swing.ext;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import org.eclipse.scout.rt.ui.swing.SwingLayoutUtility;
import org.eclipse.scout.rt.ui.swing.form.fields.AbstractLayoutManager2;
/**
* <pre>
* Fixed version of BorderLayout
* Sun's BorderLayout does not respect maximumSize of contained components.
* It just returns new Dimension(MAX,MAX)
* 1) this class corrects this behaviour and respects container item's min, preferred and max sizes
* 2) this class fixes issues when dimensions use Integer.MAX_VALUE
* 3) fixes out-of-component layout when container is smaller than preferred size
* </pre>
*/
public class BorderLayoutEx extends BorderLayout {
private static final long serialVersionUID = 1L;
public BorderLayoutEx() {
super();
}
public BorderLayoutEx(int hgap, int vgap) {
super(hgap, vgap);
}
protected Dimension getLayoutSize(Container parent, int sizeflag) {
int hgap = getHgap();
int vgap = getVgap();
Dimension dim = new Dimension(0, 0);
boolean ltr = parent.getComponentOrientation().isLeftToRight();
Component c = null;
if ((c = getChild(EAST, ltr)) != null) {
Dimension d = SwingLayoutUtility.getSize(c, sizeflag);
if (sizeflag == AbstractLayoutManager2.MAX_SIZE) {
doMaxSizeRangeCheck(d);
}
dim.width += d.width + hgap;
dim.height = Math.max(d.height, dim.height);
}
if ((c = getChild(WEST, ltr)) != null) {
Dimension d = SwingLayoutUtility.getSize(c, sizeflag);
if (sizeflag == AbstractLayoutManager2.MAX_SIZE) {
doMaxSizeRangeCheck(d);
}
dim.width += d.width + hgap;
dim.height = Math.max(d.height, dim.height);
}
if ((c = getChild(CENTER, ltr)) != null) {
Dimension d = SwingLayoutUtility.getSize(c, sizeflag);
if (sizeflag == AbstractLayoutManager2.MAX_SIZE) {
doMaxSizeRangeCheck(d);
}
dim.width += d.width;
dim.height = Math.max(d.height, dim.height);
}
if ((c = getChild(NORTH, ltr)) != null) {
Dimension d = SwingLayoutUtility.getSize(c, sizeflag);
if (sizeflag == AbstractLayoutManager2.MAX_SIZE) {
doMaxSizeRangeCheck(d);
}
dim.width = Math.max(d.width, dim.width);
dim.height += d.height + vgap;
}
if ((c = getChild(SOUTH, ltr)) != null) {
Dimension d = SwingLayoutUtility.getSize(c, sizeflag);
if (sizeflag == AbstractLayoutManager2.MAX_SIZE) {
doMaxSizeRangeCheck(d);
}
dim.width = Math.max(d.width, dim.width);
dim.height += d.height + vgap;
}
if (dim.width > 0 && dim.height > 0) {
Insets insets = parent.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
}
return dim;
}
@Override
public Dimension minimumLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
return new Dimension(getLayoutSize(parent, AbstractLayoutManager2.MIN_SIZE));
}
}
@Override
public Dimension preferredLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
return new Dimension(getLayoutSize(parent, AbstractLayoutManager2.PREF_SIZE));
}
}
@Override
public Dimension maximumLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
return new Dimension(getLayoutSize(parent, AbstractLayoutManager2.MAX_SIZE));
}
}
protected void doMaxSizeRangeCheck(Dimension d) {
if (d.width > 1000000) {
d.width = 1000000;
}
if (d.height > 1000000) {
d.height = 1000000;
}
}
@Override
public void layoutContainer(Container parent) {
synchronized (parent.getTreeLock()) {
/*
* necessary as workaround for awt bug: when component does not change
* size, its reported minimumSize, preferredSize and maximumSize are
* cached instead of beeing calculated using layout manager
*/
for (Component c : parent.getComponents()) {
c.setBounds(0, 0, 0, 0);
}
//
Insets insets = parent.getInsets();
int top = insets.top;
int bottom = parent.getHeight() - insets.bottom;
int left = insets.left;
int right = parent.getWidth() - insets.right;
int hgap = getHgap();
int vgap = getVgap();
boolean ltr = parent.getComponentOrientation().isLeftToRight();
Component c = null;
if ((c = getChild(NORTH, ltr)) != null) {
c.setSize(right - left, c.getHeight());
Dimension d = c.getPreferredSize();
int ch = Math.max(0, Math.min(bottom - top, d.height));
c.setBounds(left, top, right - left, ch);
top += ch + vgap;
}
if ((c = getChild(SOUTH, ltr)) != null) {
c.setSize(right - left, c.getHeight());
Dimension d = c.getPreferredSize();
int ch = Math.max(0, Math.min(bottom - top, d.height));
c.setBounds(left, bottom - ch, right - left, ch);
bottom -= ch + vgap;
}
if ((c = getChild(WEST, ltr)) != null) {
c.setSize(c.getWidth(), bottom - top);
Dimension d = c.getPreferredSize();
int cw = Math.max(0, Math.min(right - left, d.width));
c.setBounds(left, top, cw, bottom - top);
left += cw + hgap;
}
if ((c = getChild(EAST, ltr)) != null) {
c.setSize(c.getWidth(), bottom - top);
Dimension d = c.getPreferredSize();
int cw = Math.max(0, Math.min(right - left, d.width));
c.setBounds(right - cw, top, cw, bottom - top);
right -= cw + hgap;
}
if ((c = getChild(CENTER, ltr)) != null) {
int cw = Math.max(0, right - left);
int ch = Math.max(0, bottom - top);
c.setBounds(left, top, cw, ch);
}
}
}
private Component getChild(String key, boolean ltr) {
Component result = null;
if (key == NORTH) {
Component firstLine = getLayoutComponent(PAGE_START);
Component north = getLayoutComponent(NORTH);
result = (firstLine != null) ? firstLine : north;
}
else if (key == SOUTH) {
Component lastLine = getLayoutComponent(PAGE_END);
Component south = getLayoutComponent(SOUTH);
result = (lastLine != null) ? lastLine : south;
}
else if (key == WEST) {
Component firstItem = getLayoutComponent(LINE_START);
Component lastItem = getLayoutComponent(LINE_END);
Component west = getLayoutComponent(WEST);
result = ltr ? firstItem : lastItem;
if (result == null) {
result = west;
}
}
else if (key == EAST) {
Component firstItem = getLayoutComponent(LINE_START);
Component lastItem = getLayoutComponent(LINE_END);
Component east = getLayoutComponent(EAST);
result = ltr ? lastItem : firstItem;
if (result == null) {
result = east;
}
}
else if (key == CENTER) {
Component center = getLayoutComponent(CENTER);
result = center;
}
if (result != null && !result.isVisible()) {
result = null;
}
return result;
}
}