/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.util.gui; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; /** * BorderLayout that lays out North and South between East and West (normal BorderLayout puts North and South surrounding East and West). */ public class VerticalBorderLayout extends BorderLayout { /** * Get the component that corresponds to the given constraint location * * @param key The desired absolute position, either NORTH, SOUTH, EAST, or WEST. * @param ltr Is the component line direction left-to-right? */ private Component getChild(String key, boolean ltr) { Component result = null; if (key == NORTH) { result = (getLayoutComponent(PAGE_START) != null) ? getLayoutComponent(PAGE_START) : getLayoutComponent(NORTH); } else if (key == SOUTH) { result = (getLayoutComponent(PAGE_END) != null) ? getLayoutComponent(PAGE_END) : getLayoutComponent(SOUTH); } else if (key == WEST) { result = ltr ? getLayoutComponent(LINE_START) : getLayoutComponent(LINE_END); if (result == null) { result = getLayoutComponent(WEST); } } else if (key == EAST) { result = ltr ? getLayoutComponent(LINE_END) : getLayoutComponent(LINE_START); if (result == null) { result = getLayoutComponent(EAST); } } else if (key == CENTER) { result = getLayoutComponent(CENTER); } if (result != null && !result.isVisible()) { result = null; } return result; } /** * Determines the minimum size of the <code>target</code> container using this layout manager. * <p> * This method is called when a container calls its <code>getMinimumSize</code> method. Most applications do not call this method directly. * * @param target the container in which to do the layout. * @return the minimum dimensions needed to lay out the subcomponents of the specified container. * @see java.awt.Container * @see java.awt.BorderLayout#preferredLayoutSize * @see java.awt.Container#getMinimumSize() */ @Override public Dimension minimumLayoutSize(Container target) { synchronized (target.getTreeLock()) { Dimension dim = new Dimension(0, 0); boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c = getChild(NORTH, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.height += d.height + getHgap(); dim.width = Math.max(d.width, dim.width); } if ((c = getChild(SOUTH, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.height += d.height + getHgap(); dim.width = Math.max(d.width, dim.width); } if ((c = getChild(CENTER, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.height += d.height; dim.width = Math.max(d.width, dim.width); } if ((c = getChild(EAST, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.height = Math.max(d.height, dim.height); dim.width += d.width + getVgap(); } if ((c = getChild(WEST, ltr)) != null) { Dimension d = c.getMinimumSize(); dim.height = Math.max(d.height, dim.height); dim.width += d.width + getVgap(); } Insets insets = target.getInsets(); dim.height += insets.left + insets.right; dim.width += insets.top + insets.bottom; return dim; } } /** * Determines the preferred size of the <code>target</code> container using this layout manager, based on the components in the container. * <p> * Most applications do not call this method directly. This method is called when a container calls its <code>getPreferredSize</code> method. * * @param target the container in which to do the layout. * @return the preferred dimensions to lay out the subcomponents of the specified container. * @see java.awt.Container * @see java.awt.BorderLayout#minimumLayoutSize * @see java.awt.Container#getPreferredSize() */ @Override public Dimension preferredLayoutSize(Container target) { synchronized (target.getTreeLock()) { Dimension dim = new Dimension(0, 0); boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c = getChild(NORTH, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.height += d.height + getHgap(); dim.width = Math.max(d.width, dim.width); } if ((c = getChild(SOUTH, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.height += d.height + getHgap(); dim.width = Math.max(d.width, dim.width); } if ((c = getChild(CENTER, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.height += d.height; dim.width = Math.max(d.width, dim.width); } if ((c = getChild(EAST, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.height = Math.max(d.height, dim.height); dim.width += d.width + getVgap(); } if ((c = getChild(WEST, ltr)) != null) { Dimension d = c.getPreferredSize(); dim.height = Math.max(d.height, dim.height); dim.width += d.width + getVgap(); } Insets insets = target.getInsets(); dim.height += insets.left + insets.right; dim.width += insets.top + insets.bottom; return dim; } } /** * Returns the maximum dimensions for this layout given the components in the specified target container. * * @param target the component which needs to be laid out * @see Container * @see #minimumLayoutSize * @see #preferredLayoutSize */ @Override public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } /** * Lays out the container argument using this border layout. * <p> * This method actually reshapes the components in the specified container in order to satisfy the constraints of this <code>BorderLayout</code> object. * The <code>NORTH</code> and <code>SOUTH</code> components, if any, are placed at the top and bottom of the container, respectively. The * <code>WEST</code> and <code>EAST</code> components are then placed on the left and right, respectively. Finally, the <code>CENTER</code> object is * placed in any remaining space in the middle. * <p> * Most applications do not call this method directly. This method is called when a container calls its <code>doLayout</code> method. * * @param target the container in which to do the layout. * @see java.awt.Container * @see java.awt.Container#doLayout() */ @Override public void layoutContainer(Container target) { synchronized (target.getTreeLock()) { Insets insets = target.getInsets(); int top = insets.top; int bottom = target.getHeight() - insets.bottom; int left = insets.left; int right = target.getWidth() - insets.right; boolean ltr = target.getComponentOrientation().isLeftToRight(); Component c = null; if ((c = getChild(EAST, ltr)) != null) { c.setSize(c.getWidth(), bottom - top); Dimension d = c.getPreferredSize(); c.setBounds(right - d.width, top, d.width, bottom - top); right -= d.width + getHgap(); } if ((c = getChild(WEST, ltr)) != null) { c.setSize(c.getWidth(), bottom - top); Dimension d = c.getPreferredSize(); c.setBounds(left, top, d.width, bottom - top); left += d.width + getHgap(); } if ((c = getChild(NORTH, ltr)) != null) { c.setSize(right - left, c.getHeight()); Dimension d = c.getPreferredSize(); c.setBounds(left, top, right - left, d.height); top += d.height + getVgap(); } if ((c = getChild(SOUTH, ltr)) != null) { c.setSize(right - left, c.getHeight()); Dimension d = c.getPreferredSize(); c.setBounds(left, bottom - d.height, right - left, d.height); bottom -= d.height + getVgap(); } if ((c = getChild(CENTER, ltr)) != null) { c.setBounds(left, top, right - left, bottom - top); } } } }