Java/Swing JFC/Customized Layout
Содержание
- 1 A layout manager that displays a single component in the center of its container.
- 2 A layout manager that spaces components over six columns in seven different formats.
- 3 Applet GUI demo of TreeLayout layout manager
- 4 A simple layoutmanager to overlay all components of a parent.
- 5 Basically two (or more) columns of different, but constant, widths
- 6 Center Layout
- 7 ColumnLayout
- 8 Compents are laid out in a circle.
- 9 Customized layout manager
- 10 Custom Layout Demo
- 11 Custom layout: EdgeLayout
- 12 DividerLayout is layout that divides two components with the column of actions
- 13 Flex Layout
- 14 GraphPaperLayout
- 15 Place components at exact locations (x, y, width, height) and then determine how they behave when the window containing them (their parent) is resized
- 16 Relative Layout Manager for Java J2SE
- 17 Specialised layout manager for a grid of components.
- 18 Special simple layout used in TabbedContainer
- 19 Square Layout
- 20 Stack Layout, uses an orientation to determine if the contents should be arranged horizontally or vertically.
- 21 Table Layout
- 22 Table Layout implements LayoutManager2
- 23 Table layout manager
- 24 Tile Layout
- 25 Wrapper Layout
- 26 X Y Layout
A layout manager that displays a single component in the center of its container.
<source lang="java">
/*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * ----------------- * CenterLayout.java * ----------------- * (C) Copyright 2000-2005, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * * $Id: CenterLayout.java,v 1.6 2005/11/16 15:58:40 taqua Exp $ * * Changes (from 5-Nov-2001) * ------------------------- * 05-Nov-2001 : Changed package to com.jrefinery.layout.* (DG); * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG); * */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.io.Serializable; /**
* A layout manager that displays a single component in the center of its * container. * * @author David Gilbert */
public class CenterLayout implements LayoutManager, Serializable {
/** For serialization. */ private static final long serialVersionUID = 469319532333015042L; /** * Creates a new layout manager. */ public CenterLayout() { } /** * Returns the preferred size. * * @param parent * the parent. * * @return the preferred size. */ public Dimension preferredLayoutSize(final Container parent) { synchronized (parent.getTreeLock()) { final Insets insets = parent.getInsets(); if (parent.getComponentCount() > 0) { final Component component = parent.getComponent(0); final Dimension d = component.getPreferredSize(); return new Dimension((int) d.getWidth() + insets.left + insets.right, (int) d.getHeight() + insets.top + insets.bottom); } else { return new Dimension(insets.left + insets.right, insets.top + insets.bottom); } } } /** * Returns the minimum size. * * @param parent * the parent. * * @return the minimum size. */ public Dimension minimumLayoutSize(final Container parent) { synchronized (parent.getTreeLock()) { final Insets insets = parent.getInsets(); if (parent.getComponentCount() > 0) { final Component component = parent.getComponent(0); final Dimension d = component.getMinimumSize(); return new Dimension(d.width + insets.left + insets.right, d.height + insets.top + insets.bottom); } else { return new Dimension(insets.left + insets.right, insets.top + insets.bottom); } } } /** * Lays out the components. * * @param parent * the parent. */ public void layoutContainer(final Container parent) { synchronized (parent.getTreeLock()) { if (parent.getComponentCount() > 0) { final Insets insets = parent.getInsets(); final Dimension parentSize = parent.getSize(); final Component component = parent.getComponent(0); final Dimension componentSize = component.getPreferredSize(); final int xx = insets.left + (Math.max((parentSize.width - insets.left - insets.right - componentSize.width) / 2, 0)); final int yy = insets.top + (Math.max( (parentSize.height - insets.top - insets.bottom - componentSize.height) / 2, 0)); component.setBounds(xx, yy, componentSize.width, componentSize.height); } } } /** * Not used. * * @param comp * the component. */ public void addLayoutComponent(final Component comp) { // not used. } /** * Not used. * * @param comp * the component. */ public void removeLayoutComponent(final Component comp) { // not used } /** * Not used. * * @param name * the component name. * @param comp * the component. */ public void addLayoutComponent(final String name, final Component comp) { // not used } /** * Not used. * * @param name * the component name. * @param comp * the component. */ public void removeLayoutComponent(final String name, final Component comp) { // not used }
}
</source>
A layout manager that spaces components over six columns in seven different formats.
<source lang="java">
/*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * ----------------- * FormatLayout.java * ----------------- * (C) Copyright 2000-2005, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * * $Id: FormatLayout.java,v 1.4 2005/10/18 13:16:50 mungady Exp $ * * Changes (from 26-Oct-2001) * -------------------------- * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG); * 26-Jun-2002 : Removed redundant code (DG); * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG); * */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.io.Serializable; /**
* A layout manager that spaces components over six columns in seven different * formats. * * @author David Gilbert */
public class FormatLayout implements LayoutManager, Serializable {
/** For serialization. */ private static final long serialVersionUID = 2866692886323930722L; /** A useful constant representing layout format 1. */ public static final int C = 1; /** A useful constant representing layout format 2. */ public static final int LC = 2; /** A useful constant representing layout format 3. */ public static final int LCB = 3; /** A useful constant representing layout format 4. */ public static final int LCLC = 4; /** A useful constant representing layout format 5. */ public static final int LCLCB = 5; /** A useful constant representing layout format 6. */ public static final int LCBLC = 6; /** A useful constant representing layout format 7. */ public static final int LCBLCB = 7; /** The layout format for each row. */ private int[] rowFormats; /** The gap between the rows. */ private int rowGap; /** * The gaps between the columns (gap[0] is the gap following column zero). */ private int[] columnGaps; /** Working array for recording the height of each row. */ private int[] rowHeights; /** The total height of the layout. */ private int totalHeight; /** Working array for recording the width of each column. */ private int[] columnWidths; /** The total width of the layout. */ private int totalWidth; /** Combined width of columns 1 and 2. */ private int columns1and2Width; /** Combined width of columns 4 and 5. */ private int columns4and5Width; /** Combined width of columns 1 to 4. */ private int columns1to4Width; /** Combined width of columns 1 to 5. */ private int columns1to5Width; /** Combined width of columns 0 to 5. */ private int columns0to5Width; /** * Constructs a new layout manager that can be used to create input forms. * The layout manager works by arranging components in rows using six * columns (some components will use more than one column).*
* Any component can be added, but I think of them in terms of Labels, * Components, and Buttons. * The formats available are: C, LC, LCB, LCLC, LCLCB, LCBLC or LCBLCB. *
C | *1 component in this row (spread across all six columns). | *
LC | *2 components, a label in the 1st column, and a component using the * remaining 5 columns). | *
LCB | *3 components, a label in the 1st column, a component spread across * the next 4, and a button in the last column. | *
LCLC | *4 components, a label in column 1, a component in 2-3, a label in * 4 and a component in 5-6. | *
LCLCB | *5 components, a label in column 1, a component in 2-3, a label * in 4, a component in 5 and a button in 6. | *
LCBLC | *5 components, a label in column 1, a component in 2, a button in 3, * a label in 4, a component in 5-6. | *
LCBLCB | *6 components, one in each column. | *
* <P>
* Columns 1 and 4 expand to accommodate the widest label, and 3 and 6 to
* accommodate the widest button.
* <P>
* Each row will contain the number of components indicated by the format.
* Be sure to specify enough row formats to cover all the components you
* add to the layout.
*
* @param rowCount the number of rows.
* @param rowFormats the row formats.
*/
public FormatLayout(final int rowCount, final int[] rowFormats) {
this.rowFormats = rowFormats;
this.rowGap = 2;
this.columnGaps = new int[5];
this.columnGaps[0] = 10;
this.columnGaps[1] = 5;
this.columnGaps[2] = 5;
this.columnGaps[3] = 10;
this.columnGaps[4] = 5;
// working structures...
this.rowHeights = new int[rowCount];
this.columnWidths = new int[6];
}
/**
* Returns the preferred size of the component using this layout manager.
*
* @param parent the parent.
*
* @return the preferred size of the component.
*/
public Dimension preferredLayoutSize(final Container parent) {
Component c0, c1, c2, c3, c4, c5;
synchronized (parent.getTreeLock()) {
final Insets insets = parent.getInsets();
int componentIndex = 0;
final int rowCount = this.rowHeights.length;
for (int i = 0; i < this.columnWidths.length; i++) {
this.columnWidths[i] = 0;
}
this.columns1and2Width = 0;
this.columns4and5Width = 0;
this.columns1to4Width = 0;
this.columns1to5Width = 0;
this.columns0to5Width = 0;
this.totalHeight = 0;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
final int format
= this.rowFormats[rowIndex % this.rowFormats.length];
switch (format) {
case FormatLayout.C:
c0 = parent.getComponent(componentIndex);
updateC(rowIndex, c0.getPreferredSize());
componentIndex = componentIndex + 1;
break;
case FormatLayout.LC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
updateLC(rowIndex, c0.getPreferredSize(),
c1.getPreferredSize());
componentIndex = componentIndex + 2;
break;
case FormatLayout.LCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
updateLCB(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize());
componentIndex = componentIndex + 3;
break;
case FormatLayout.LCLC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
updateLCLC(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize(),
c3.getPreferredSize());
componentIndex = componentIndex + 4;
break;
case FormatLayout.LCBLC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
updateLCBLC(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize(),
c3.getPreferredSize(),
c4.getPreferredSize());
componentIndex = componentIndex + 5;
break;
case FormatLayout.LCLCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
updateLCLCB(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize(),
c3.getPreferredSize(),
c4.getPreferredSize());
componentIndex = componentIndex + 5;
break;
case FormatLayout.LCBLCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
c5 = parent.getComponent(componentIndex + 5);
updateLCBLCB(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize(),
c3.getPreferredSize(),
c4.getPreferredSize(),
c5.getPreferredSize());
componentIndex = componentIndex + 6;
break;
}
}
complete();
return new Dimension(this.totalWidth + insets.left + insets.right,
this.totalHeight + (rowCount - 1) * this.rowGap
+ insets.top + insets.bottom);
}
}
/**
* Returns the minimum size of the component using this layout manager.
*
* @param parent the parent.
*
* @return the minimum size of the component
*/
public Dimension minimumLayoutSize(final Container parent) {
Component c0, c1, c2, c3, c4, c5;
synchronized (parent.getTreeLock()) {
final Insets insets = parent.getInsets();
int componentIndex = 0;
final int rowCount = this.rowHeights.length;
for (int i = 0; i < this.columnWidths.length; i++) {
this.columnWidths[i] = 0;
}
this.columns1and2Width = 0;
this.columns4and5Width = 0;
this.columns1to4Width = 0;
this.columns1to5Width = 0;
this.columns0to5Width = 0;
final int totalHeight = 0;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
final int format
= this.rowFormats[rowIndex % this.rowFormats.length];
switch (format) {
case FormatLayout.C:
c0 = parent.getComponent(componentIndex);
this.columns0to5Width = Math.max(
this.columns0to5Width, c0.getMinimumSize().width
);
componentIndex = componentIndex + 1;
break;
case FormatLayout.LC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
updateLC(rowIndex,
c0.getMinimumSize(),
c1.getMinimumSize());
componentIndex = componentIndex + 2;
break;
case FormatLayout.LCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
updateLCB(rowIndex,
c0.getMinimumSize(),
c1.getMinimumSize(),
c2.getMinimumSize());
componentIndex = componentIndex + 3;
break;
case FormatLayout.LCLC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
updateLCLC(rowIndex,
c0.getMinimumSize(),
c1.getMinimumSize(),
c2.getMinimumSize(),
c3.getMinimumSize());
componentIndex = componentIndex + 3;
break;
case FormatLayout.LCBLC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
updateLCBLC(rowIndex,
c0.getMinimumSize(),
c1.getMinimumSize(),
c2.getMinimumSize(),
c3.getMinimumSize(),
c4.getMinimumSize());
componentIndex = componentIndex + 4;
break;
case FormatLayout.LCLCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
updateLCLCB(rowIndex,
c0.getMinimumSize(),
c1.getMinimumSize(),
c2.getMinimumSize(),
c3.getMinimumSize(),
c4.getMinimumSize());
componentIndex = componentIndex + 4;
break;
case FormatLayout.LCBLCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
c5 = parent.getComponent(componentIndex + 5);
updateLCBLCB(rowIndex,
c0.getMinimumSize(),
c1.getMinimumSize(),
c2.getMinimumSize(),
c3.getMinimumSize(),
c4.getMinimumSize(),
c5.getMinimumSize());
componentIndex = componentIndex + 5;
break;
}
}
complete();
return new Dimension(this.totalWidth + insets.left + insets.right,
totalHeight + (rowCount - 1) * this.rowGap
+ insets.top + insets.bottom);
}
}
/**
* Performs the layout of the container.
*
* @param parent the parent.
*/
public void layoutContainer(final Container parent) {
Component c0, c1, c2, c3, c4, c5;
synchronized (parent.getTreeLock()) {
final Insets insets = parent.getInsets();
int componentIndex = 0;
final int rowCount = this.rowHeights.length;
for (int i = 0; i < this.columnWidths.length; i++) {
this.columnWidths[i] = 0;
}
this.columns1and2Width = 0;
this.columns4and5Width = 0;
this.columns1to4Width = 0;
this.columns1to5Width = 0;
this.columns0to5Width
= parent.getBounds().width - insets.left - insets.right;
this.totalHeight = 0;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
final int format
= this.rowFormats[rowIndex % this.rowFormats.length];
switch (format) {
case FormatLayout.C:
c0 = parent.getComponent(componentIndex);
updateC(rowIndex, c0.getPreferredSize());
componentIndex = componentIndex + 1;
break;
case FormatLayout.LC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
updateLC(rowIndex, c0.getPreferredSize(),
c1.getPreferredSize());
componentIndex = componentIndex + 2;
break;
case FormatLayout.LCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
updateLCB(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize());
componentIndex = componentIndex + 3;
break;
case FormatLayout.LCLC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
updateLCLC(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize(),
c3.getPreferredSize());
componentIndex = componentIndex + 4;
break;
case FormatLayout.LCBLC:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
updateLCBLC(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize(),
c3.getPreferredSize(),
c4.getPreferredSize());
componentIndex = componentIndex + 5;
break;
case FormatLayout.LCLCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
updateLCLCB(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize(),
c3.getPreferredSize(),
c4.getPreferredSize());
componentIndex = componentIndex + 5;
break;
case FormatLayout.LCBLCB:
c0 = parent.getComponent(componentIndex);
c1 = parent.getComponent(componentIndex + 1);
c2 = parent.getComponent(componentIndex + 2);
c3 = parent.getComponent(componentIndex + 3);
c4 = parent.getComponent(componentIndex + 4);
c5 = parent.getComponent(componentIndex + 5);
updateLCBLCB(rowIndex,
c0.getPreferredSize(),
c1.getPreferredSize(),
c2.getPreferredSize(),
c3.getPreferredSize(),
c4.getPreferredSize(),
c5.getPreferredSize());
componentIndex = componentIndex + 6;
break;
}
}
complete();
componentIndex = 0;
int rowY = insets.top;
final int[] rowX = new int[6];
rowX[0] = insets.left;
rowX[1] = rowX[0] + this.columnWidths[0] + this.columnGaps[0];
rowX[2] = rowX[1] + this.columnWidths[1] + this.columnGaps[1];
rowX[3] = rowX[2] + this.columnWidths[2] + this.columnGaps[2];
rowX[4] = rowX[3] + this.columnWidths[3] + this.columnGaps[3];
rowX[5] = rowX[4] + this.columnWidths[4] + this.columnGaps[4];
final int w1to2 = this.columnWidths[1] + this.columnGaps[1]
+ this.columnWidths[2];
final int w4to5 = this.columnWidths[4] + this.columnGaps[4]
+ this.columnWidths[5];
final int w1to4 = w1to2 + this.columnGaps[2] + this.columnWidths[3]
+ this.columnGaps[3] + this.columnWidths[4];
final int w1to5 = w1to4 + this.columnGaps[4] + this.columnWidths[5];
final int w0to5 = w1to5 + this.columnWidths[0] + this.columnGaps[0];
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
final int format
= this.rowFormats[rowIndex % this.rowFormats.length];
switch (format) {
case FormatLayout.C:
c0 = parent.getComponent(componentIndex);
c0.setBounds(rowX[0], rowY, w0to5,
c0.getPreferredSize().height);
componentIndex = componentIndex + 1;
break;
case FormatLayout.LC:
c0 = parent.getComponent(componentIndex);
c0.setBounds(
rowX[0],
rowY + (this.rowHeights[rowIndex]
- c0.getPreferredSize().height) / 2,
this.columnWidths[0], c0.getPreferredSize().height
);
c1 = parent.getComponent(componentIndex + 1);
c1.setBounds(
rowX[1],
rowY + (this.rowHeights[rowIndex]
- c1.getPreferredSize().height) / 2,
w1to5, c1.getPreferredSize().height
);
componentIndex = componentIndex + 2;
break;
case FormatLayout.LCB:
c0 = parent.getComponent(componentIndex);
c0.setBounds(
rowX[0],
rowY + (this.rowHeights[rowIndex]
- c0.getPreferredSize().height) / 2,
this.columnWidths[0], c0.getPreferredSize().height
);
c1 = parent.getComponent(componentIndex + 1);
c1.setBounds(
rowX[1],
rowY + (this.rowHeights[rowIndex]
- c1.getPreferredSize().height) / 2,
w1to4, c1.getPreferredSize().height
);
c2 = parent.getComponent(componentIndex + 2);
c2.setBounds(
rowX[5],
rowY + (this.rowHeights[rowIndex]
- c2.getPreferredSize().height) / 2,
this.columnWidths[5], c2.getPreferredSize().height
);
componentIndex = componentIndex + 3;
break;
case FormatLayout.LCLC:
c0 = parent.getComponent(componentIndex);
c0.setBounds(
rowX[0],
rowY + (this.rowHeights[rowIndex]
- c0.getPreferredSize().height) / 2,
this.columnWidths[0], c0.getPreferredSize().height
);
c1 = parent.getComponent(componentIndex + 1);
c1.setBounds(
rowX[1],
rowY + (this.rowHeights[rowIndex]
- c1.getPreferredSize().height) / 2,
w1to2, c1.getPreferredSize().height
);
c2 = parent.getComponent(componentIndex + 2);
c2.setBounds(
rowX[3],
rowY + (this.rowHeights[rowIndex]
- c2.getPreferredSize().height) / 2,
this.columnWidths[3], c2.getPreferredSize().height
);
c3 = parent.getComponent(componentIndex + 3);
c3.setBounds(
rowX[4],
rowY + (this.rowHeights[rowIndex]
- c3.getPreferredSize().height) / 2,
w4to5, c3.getPreferredSize().height
);
componentIndex = componentIndex + 4;
break;
case FormatLayout.LCBLC:
c0 = parent.getComponent(componentIndex);
c0.setBounds(
rowX[0],
rowY + (this.rowHeights[rowIndex]
- c0.getPreferredSize().height) / 2,
this.columnWidths[0], c0.getPreferredSize().height
);
c1 = parent.getComponent(componentIndex + 1);
c1.setBounds(
rowX[1],
rowY + (this.rowHeights[rowIndex]
- c1.getPreferredSize().height) / 2,
this.columnWidths[1], c1.getPreferredSize().height
);
c2 = parent.getComponent(componentIndex + 2);
c2.setBounds(
rowX[2],
rowY + (this.rowHeights[rowIndex]
- c2.getPreferredSize().height) / 2,
this.columnWidths[2], c2.getPreferredSize().height
);
c3 = parent.getComponent(componentIndex + 3);
c3.setBounds(
rowX[3],
rowY + (this.rowHeights[rowIndex]
- c3.getPreferredSize().height) / 2,
this.columnWidths[3], c3.getPreferredSize().height
);
c4 = parent.getComponent(componentIndex + 4);
c4.setBounds(
rowX[4],
rowY + (this.rowHeights[rowIndex]
- c4.getPreferredSize().height) / 2,
w4to5, c4.getPreferredSize().height
);
componentIndex = componentIndex + 5;
break;
case FormatLayout.LCLCB:
c0 = parent.getComponent(componentIndex);
c0.setBounds(
rowX[0],
rowY + (this.rowHeights[rowIndex]
- c0.getPreferredSize().height) / 2,
this.columnWidths[0], c0.getPreferredSize().height
);
c1 = parent.getComponent(componentIndex + 1);
c1.setBounds(
rowX[1],
rowY + (this.rowHeights[rowIndex]
- c1.getPreferredSize().height) / 2,
w1to2, c1.getPreferredSize().height
);
c2 = parent.getComponent(componentIndex + 2);
c2.setBounds(
rowX[3],
rowY + (this.rowHeights[rowIndex]
- c2.getPreferredSize().height) / 2,
this.columnWidths[3], c2.getPreferredSize().height
);
c3 = parent.getComponent(componentIndex + 3);
c3.setBounds(
rowX[4],
rowY + (this.rowHeights[rowIndex]
- c3.getPreferredSize().height) / 2,
this.columnWidths[4], c3.getPreferredSize().height
);
c4 = parent.getComponent(componentIndex + 4);
c4.setBounds(
rowX[5],
rowY + (this.rowHeights[rowIndex]
- c4.getPreferredSize().height) / 2,
this.columnWidths[5], c4.getPreferredSize().height
);
componentIndex = componentIndex + 5;
break;
case FormatLayout.LCBLCB:
c0 = parent.getComponent(componentIndex);
c0.setBounds(
rowX[0],
rowY + (this.rowHeights[rowIndex]
- c0.getPreferredSize().height) / 2,
this.columnWidths[0], c0.getPreferredSize().height
);
c1 = parent.getComponent(componentIndex + 1);
c1.setBounds(
rowX[1],
rowY + (this.rowHeights[rowIndex]
- c1.getPreferredSize().height) / 2,
this.columnWidths[1], c1.getPreferredSize().height
);
c2 = parent.getComponent(componentIndex + 2);
c2.setBounds(
rowX[2],
rowY + (this.rowHeights[rowIndex]
- c2.getPreferredSize().height) / 2,
this.columnWidths[2], c2.getPreferredSize().height
);
c3 = parent.getComponent(componentIndex + 3);
c3.setBounds(
rowX[3],
rowY + (this.rowHeights[rowIndex]
- c3.getPreferredSize().height) / 2,
this.columnWidths[3], c3.getPreferredSize().height
);
c4 = parent.getComponent(componentIndex + 4);
c4.setBounds(
rowX[4],
rowY + (this.rowHeights[rowIndex]
- c4.getPreferredSize().height) / 2,
this.columnWidths[4], c4.getPreferredSize().height
);
c5 = parent.getComponent(componentIndex + 5);
c5.setBounds(
rowX[5],
rowY + (this.rowHeights[rowIndex]
- c5.getPreferredSize().height) / 2,
this.columnWidths[5], c5.getPreferredSize().height
);
componentIndex = componentIndex + 6;
break;
}
rowY = rowY + this.rowHeights[rowIndex] + this.rowGap;
}
}
}
/**
* Processes a row in "C" format.
*
* @param rowIndex the row index.
* @param d0 dimension 0.
*/
protected void updateC(final int rowIndex, final Dimension d0) {
this.rowHeights[rowIndex] = d0.height;
this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
this.columns0to5Width = Math.max(this.columns0to5Width, d0.width);
}
/**
* Processes a row in "LC" format.
*
* @param rowIndex the row index.
* @param d0 dimension 0.
* @param d1 dimension 1.
*/
protected void updateLC(final int rowIndex, final Dimension d0,
final Dimension d1) {
this.rowHeights[rowIndex] = Math.max(d0.height, d1.height);
this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
this.columns1to5Width = Math.max(this.columns1to5Width, d1.width);
}
/**
* Processes a row in "LCB" format.
*
* @param rowIndex the row index.
* @param d0 dimension 0.
* @param d1 dimension 1.
* @param d2 dimension 2.
*/
protected void updateLCB(final int rowIndex,
final Dimension d0, final Dimension d1,
final Dimension d2) {
this.rowHeights[rowIndex]
= Math.max(d0.height, Math.max(d1.height, d2.height));
this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
this.columns1to4Width = Math.max(this.columns1to4Width, d1.width);
this.columnWidths[5] = Math.max(this.columnWidths[5], d2.width);
}
/**
* Processes a row in "LCLC" format.
*
* @param rowIndex the row index.
* @param d0 dimension 0.
* @param d1 dimension 1.
* @param d2 dimension 2.
* @param d3 dimension 3.
*/
protected void updateLCLC(final int rowIndex, final Dimension d0,
final Dimension d1, final Dimension d2,
final Dimension d3) {
this.rowHeights[rowIndex] = Math.max(Math.max(d0.height, d1.height),
Math.max(d2.height, d3.height));
this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
this.columns1and2Width = Math.max(this.columns1and2Width, d1.width);
this.columnWidths[3] = Math.max(this.columnWidths[3], d2.width);
this.columns4and5Width = Math.max(this.columns4and5Width, d3.width);
}
/**
* Processes a row in "LCBLC" format.
*
* @param rowIndex the row index.
* @param d0 dimension 0.
* @param d1 dimension 1.
* @param d2 dimension 2.
* @param d3 dimension 3.
* @param d4 dimension 4.
*/
protected void updateLCBLC(final int rowIndex, final Dimension d0,
final Dimension d1, final Dimension d2,
final Dimension d3, final Dimension d4) {
this.rowHeights[rowIndex] = (Math.max(
d0.height,
Math.max(Math.max(d1.height, d2.height),
Math.max(d3.height, d4.height)))
);
this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
this.columnWidths[1] = Math.max(this.columnWidths[1], d1.width);
this.columnWidths[2] = Math.max(this.columnWidths[2], d2.width);
this.columnWidths[3] = Math.max(this.columnWidths[3], d3.width);
this.columns4and5Width = Math.max(this.columns4and5Width, d4.width);
}
/**
* Processes a row in "LCLCB" format.
*
* @param rowIndex the row index.
* @param d0 dimension 0.
* @param d1 dimension 1.
* @param d2 dimension 2.
* @param d3 dimension 3.
* @param d4 dimension 4.
*/
protected void updateLCLCB(final int rowIndex, final Dimension d0,
final Dimension d1, final Dimension d2,
final Dimension d3, final Dimension d4) {
this.rowHeights[rowIndex] = (Math.max(d0.height,
Math.max(Math.max(d1.height, d2.height),
Math.max(d3.height, d4.height))));
this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
this.columns1and2Width = Math.max(this.columns1and2Width, d1.width);
this.columnWidths[3] = Math.max(this.columnWidths[3], d2.width);
this.columnWidths[4] = Math.max(this.columnWidths[4], d3.width);
this.columnWidths[5] = Math.max(this.columnWidths[5], d4.width);
}
/**
* Processes a row in "LCBLCB" format.
*
* @param rowIndex the row index.
* @param d0 dimension 0.
* @param d1 dimension 1.
* @param d2 dimension 2.
* @param d3 dimension 3.
* @param d4 dimension 4.
* @param d5 dimension 5.
*/
protected void updateLCBLCB(final int rowIndex,
final Dimension d0, final Dimension d1,
final Dimension d2,
final Dimension d3, final Dimension d4,
final Dimension d5) {
this.rowHeights[rowIndex] = Math.max(
Math.max(d0.height, d1.height),
Math.max(Math.max(d2.height, d3.height),
Math.max(d4.height, d5.height))
);
this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
this.columnWidths[1] = Math.max(this.columnWidths[1], d1.width);
this.columnWidths[2] = Math.max(this.columnWidths[2], d2.width);
this.columnWidths[3] = Math.max(this.columnWidths[3], d3.width);
this.columnWidths[4] = Math.max(this.columnWidths[4], d4.width);
this.columnWidths[5] = Math.max(this.columnWidths[5], d5.width);
}
/**
* Finishes of the processing.
*/
public void complete() {
this.columnWidths[1] = Math.max(
this.columnWidths[1],
this.columns1and2Width - this.columnGaps[1] - this.columnWidths[2]
);
this.columnWidths[4] = Math.max(
this.columnWidths[4],
Math.max(
this.columns4and5Width - this.columnGaps[4]
- this.columnWidths[5],
Math.max(
this.columns1to4Width - this.columnGaps[1]
- this.columnGaps[2] - this.columnGaps[3]
- this.columnWidths[1] - this.columnWidths[2]
- this.columnWidths[3],
this.columns1to5Width - this.columnGaps[1]
- this.columnGaps[2] - this.columnGaps[3]
- this.columnWidths[1] - this.columnWidths[2]
- this.columnWidths[3] - this.columnGaps[4]
)
)
);
int leftWidth = this.columnWidths[0] + this.columnGaps[0]
+ this.columnWidths[1] + this.columnGaps[1]
+ this.columnWidths[2];
int rightWidth = this.columnWidths[3] + this.columnGaps[3]
+ this.columnWidths[4] + this.columnGaps[4]
+ this.columnWidths[5];
if (splitLayout()) {
if (leftWidth > rightWidth) {
final int mismatch = leftWidth - rightWidth;
this.columnWidths[4] = this.columnWidths[4] + mismatch;
rightWidth = rightWidth + mismatch;
}
else {
final int mismatch = rightWidth - leftWidth;
this.columnWidths[1] = this.columnWidths[1] + mismatch;
leftWidth = leftWidth + mismatch;
}
}
this.totalWidth = leftWidth + this.columnGaps[2] + rightWidth;
if (this.columns0to5Width > this.totalWidth) {
final int spaceToAdd = (this.columns0to5Width - this.totalWidth);
if (splitLayout()) {
final int halfSpaceToAdd = spaceToAdd / 2;
this.columnWidths[1] = this.columnWidths[1] + halfSpaceToAdd;
this.columnWidths[4] = this.columnWidths[4] + spaceToAdd
- halfSpaceToAdd;
this.totalWidth = this.totalWidth + spaceToAdd;
}
else {
this.columnWidths[1] = this.columnWidths[1] + spaceToAdd;
this.totalWidth = this.totalWidth + spaceToAdd;
}
}
}
/**
* Returns true if this layout involves a split into two sections.
*
* @return true
if this layout involves a split into two
* sections.
*/
private boolean splitLayout() {
for (int i = 0; i < this.rowFormats.length; i++) {
if (this.rowFormats[i] > FormatLayout.LCB) {
return true;
}
}
return false;
}
/**
* Not used.
*
* @param comp the component.
*/
public void addLayoutComponent(final Component comp) {
// not used
}
/**
* Not used.
*
* @param comp the component.
*/
public void removeLayoutComponent(final Component comp) {
// not used
}
/**
* Not used.
*
* @param name the component name.
* @param comp the component.
*/
public void addLayoutComponent(final String name, final Component comp) {
// not used
}
/**
* Not used.
*
* @param name the component name.
* @param comp the component.
*/
public void removeLayoutComponent(final String name, final Component comp) {
// not used
}
}
</source>
Applet GUI demo of TreeLayout layout manager
<source lang="java">
import java.applet.Applet; import java.awt.Button; import java.awt.Canvas; import java.awt.Color; import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.Insets; import java.awt.Label; import java.awt.LayoutManager; import java.awt.List; import java.awt.Rectangle; import java.awt.TextField; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; /**
* Applet GUI demo of Gamelan TreeLayout layout manager. Constructs a tree and, * for each entry, makes a button that jumps to it. * * The input language is a file like this: R Java Resources # root L - Resources * at Sun # label B http://www.sun.ru/foo/bar Interesting Stuff # URLbutton B * http://javasoft.ru/b/c More Stuff # URLbutton * * The result is (supposedly) a beautiful(?) tree. Each L is a top-level label, * and each B is in the tree below it. * * Could be made much fancier with getParameter("FontName"), "FontSize", * adjusting width with fontMetrics, etc. Works adequately for now. */
public class TreeLinkTest extends Applet {
TreeLayout tl; public void init() { tl = new TreeLayout(); setLayout(tl); Button root = new Button("This is the root"); add("Root", root); tl.setRoot(root); Component x = new Label("A random label"); add("label", x); tl.setParent(x, root); Component y; y = new TextField("Add any component"); add("comp", y); tl.setParent(y, root); x = new List(); ((List) x).add("List entry"); ((List) x).add("Similarly useless list entry"); add("list", x); tl.setParent(x, root); x = new Button("Extremely long and unnecessary button title"); add("button", x); tl.setParent(x, y); x = new MyCanvas(getImage(getDocumentBase(), "icons/tools.gif")); add("image", x); tl.setParent(x, y); } public void paint(Graphics g) { super.paint(g); tl.paintLines(g, getBackground()); } class MyCanvas extends Canvas { Image img; MyCanvas(Image img) { this.img = img; } public Dimension getPreferredSize() { return new Dimension(64, 64); } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { g.drawImage(img, 0, getSize().height / 2 - 16, 32, 32, this); } }
} /**
* Simple layout manager that arranges its children in a tree. The tree always * expands to fill the available area, and the internal components are resized * to fit the area proportional to their preferred size and the actual available * size. * * This layout manager requires several method calls beyond the normal layout * manager. Please notice the following: * Components must be added using the * add(String, Component) method. The strings don"t have to be unique, but must * be present. * Each instance must have exactly one root object, which must be * add()ed, then setRoot()ed. * Each component after the root must first * be added and then must be connected into the tree using setParent(child, * parent). * If you want lines between parents and children, you must * call paintLines() from your applet"s paint() method. * * @author name unknown, xxx@blackdown.org */
class TreeLayout implements LayoutManager {
TreeNode root; Hashtable nodes; public TreeLayout() { nodes = new Hashtable(); } public void addLayoutComponent(String name, Component comp) { TreeNode tn = new TreeNode(comp); nodes.put(comp, tn); } public void removeLayoutComponent(Component comp) { nodes.remove(comp); } /** * You must make this call, otherwise none of the components will * be layed out. */ public void setRoot(Component c) { root = (TreeNode) nodes.get(c); } /** * Sets the tree parent of a child. The components must have been * previously added. If either component has not previously been added, this * injunction is silently ignored. Cycles are not checked. */ public void setParent(Component child, Component parent) { TreeNode p = (TreeNode) nodes.get(parent); TreeNode c = (TreeNode) nodes.get(child); if ((p != null) && (c != null)) p.addChild(c); } public Dimension minimumLayoutSize(Container target) { Dimension d = root.getMinimumSize(); Insets insets = target.getInsets(); d.width += insets.left + insets.right; d.height += insets.top + insets.bottom; return d; } public Dimension preferredLayoutSize(Container target) { Dimension d = root.getPreferredSize(); Insets insets = target.getInsets(); d.width += insets.left + insets.right; d.height += insets.top + insets.bottom; return d; } public void layoutContainer(Container target) { Insets insets = target.getInsets(); Dimension d = target.getSize(); Dimension root_pref = root.getPreferredSize(); double xscale = ((double) (d.width - insets.left - insets.right) / (double) (root_pref.width)); double yscale = ((double) (d.height - insets.top - insets.bottom) / (double) (root_pref.height)); root.doLayout(xscale, yscale, insets.left, insets.top); } /** * This piece of hackery is needed since one cant really draw things from a * layout manager. Call this if you want to draw lines between components. */ public void paintLines(Graphics g, Color bg) { Color dk = bg.darker(); Color br = bg.brighter(); root.paintLines(g, dk, br); }
} class TreeNode {
Component comp; Vector children; Dimension prefSz, minSz; TreeNode(Component comp) { super(); this.rup = comp; children = new Vector(); } Dimension getMinimumSize() { if (!comp.isVisible()) return new Dimension(0, 0); if (minSz == null) { Dimension d = comp.getMinimumSize(); minSz = new Dimension(d.width, d.height); if (children.size() > 0) { for (Enumeration e = children.elements(); e.hasMoreElements();) { TreeNode t = (TreeNode) (e.nextElement()); if (t.rup.isVisible()) { d = t.getMinimumSize(); minSz.height += d.height; minSz.width = Math.max(d.width, minSz.width); } } } } return minSz; } Dimension getPreferredSize() { if (!comp.isVisible()) return new Dimension(0, 0); if (prefSz == null) { Dimension d = comp.getPreferredSize(); prefSz = new Dimension(d.width, d.height); if (children.size() > 0) { int wmax = 0; for (Enumeration e = children.elements(); e.hasMoreElements();) { TreeNode t = (TreeNode) (e.nextElement()); if (t.rup.isVisible()) { d = t.getPreferredSize(); prefSz.height += d.height; if (wmax < d.width) { wmax = d.width; } } } prefSz.width += wmax; } } return prefSz; } void addChild(TreeNode t) { children.addElement(t); prefSz = null; minSz = null; } void removeChild(TreeNode t) { children.removeElement(t); prefSz = null; minSz = null; } void paintLines(Graphics g, Color dk, Color br) { if (comp.isVisible()) { Rectangle b = comp.getBounds(); int x1off = b.x + b.width / 2; int x2off = b.x + b.width; int y1off = b.y; for (Enumeration e = children.elements(); e.hasMoreElements();) { TreeNode tn = (TreeNode) (e.nextElement()); if (tn.rup.isVisible()) { Rectangle bn = tn.rup.getBounds(); int y2off = bn.y + bn.height / 2; g.setColor(dk); g.drawLine(x1off, y1off, x1off, y2off); g.drawLine(x1off, y2off - 1, x2off, y2off - 1); g.setColor(br); g.drawLine(x1off + 1, y1off, x1off + 1, y2off); g.drawLine(x1off, y2off, x2off, y2off); tn.paintLines(g, dk, br); } } } } void doLayout(double xscale, double yscale, int x, int y) { // x and y are the offsets into the // Container where we start doing the // goodies for this Node if (comp.isVisible()) { Dimension pref = comp.getPreferredSize(); int ht = (int) Math.round(yscale * pref.height); int wd = (int) Math.round(xscale * pref.width); ht = (pref.height < ht) ? pref.height : ht; wd = (pref.width < wd) ? pref.width : wd; comp.setBounds(x, y, wd, ht); y += ht; x += wd; for (Enumeration e = children.elements(); e.hasMoreElements();) { TreeNode tn = (TreeNode) (e.nextElement()); if (tn.rup.isVisible()) { pref = tn.getPreferredSize(); tn.doLayout(xscale, yscale, x, y); y += (int) Math.round(yscale * pref.height); } } } }
}
</source>
A simple layoutmanager to overlay all components of a parent.
<source lang="java">
/*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * ------------------------------ * OverlayLayout.java * ------------------------------ * (C)opyright 2003, by Thomas Morgner and Contributors. * * Original Author: Thomas Morgner; * Contributor(s): -; * * $Id: OverlayLayout.java,v 1.5 2005/10/18 13:18:34 mungady Exp $ * * Changes * ------------------------- * 09-12-2003 : Initial version * */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Rectangle; /**
* A simple layoutmanager to overlay all components of a parent. * <p/> * This layout manager acts similiar to the card layout, but all * childs of the parent band have the same size and all childs can * be visible at the same time. * * @author Thomas Morgner */
public final class OverlayLayout implements LayoutManager {
/** * A flag that defines, whether invisible components should be ignored when * computing the layout. */ private boolean ignoreInvisible; /** * Creates a new instance. * * @param ignoreInvisible whether to ignore invisible components when computing the layout. */ public OverlayLayout(final boolean ignoreInvisible) { this.ignoreInvisible = ignoreInvisible; } /** * DefaultConstructor. */ public OverlayLayout() { } /** * If the layout manager uses a per-component string, * adds the componentcomp
to the layout, * associating it * with the string specified byname
. * * @param name the string to be associated with the component * @param comp the component to be added */ public void addLayoutComponent(final String name, final Component comp) { } /** * Removes the specified component from the layout. * * @param comp the component to be removed */ public void removeLayoutComponent(final Component comp) { } /** * Lays out the specified container. * * @param parent the container to be laid out */ public void layoutContainer(final Container parent) { synchronized (parent.getTreeLock()) { final Insets ins = parent.getInsets(); final Rectangle bounds = parent.getBounds(); final int width = bounds.width - ins.left - ins.right; final int height = bounds.height - ins.top - ins.bottom; final Component[] comps = parent.getComponents(); for (int i = 0; i < comps.length; i++) { final Component c = comps[i]; if ((comps[i].isVisible() == false) && this.ignoreInvisible) { continue; } c.setBounds(ins.left, ins.top, width, height); } } } /** * Calculates the minimum size dimensions for the specified * container, given the components it contains. * * @param parent the component to be laid out * @return the minimum size computed for the parent. * @see #preferredLayoutSize */ public Dimension minimumLayoutSize(final Container parent) { synchronized (parent.getTreeLock()) { final Insets ins = parent.getInsets(); final Component[] comps = parent.getComponents(); int height = 0; int width = 0; for (int i = 0; i < comps.length; i++) { if ((comps[i].isVisible() == false) && this.ignoreInvisible) { continue; } final Dimension pref = comps[i].getMinimumSize(); if (pref.height > height) { height = pref.height; } if (pref.width > width) { width = pref.width; } } return new Dimension(width + ins.left + ins.right, height + ins.top + ins.bottom); } } /** * Calculates the preferred size dimensions for the specified * container, given the components it contains. * * @param parent the container to be laid out * @return the preferred size computed for the parent. * @see #minimumLayoutSize */ public Dimension preferredLayoutSize(final Container parent) { synchronized (parent.getTreeLock()) { final Insets ins = parent.getInsets(); final Component[] comps = parent.getComponents(); int height = 0; int width = 0; for (int i = 0; i < comps.length; i++) { if ((comps[i].isVisible() == false) && this.ignoreInvisible) { continue; } final Dimension pref = comps[i].getPreferredSize(); if (pref.height > height) { height = pref.height; } if (pref.width > width) { width = pref.width; } } return new Dimension(width + ins.left + ins.right, height + ins.top + ins.bottom); } }
}
</source>
Basically two (or more) columns of different, but constant, widths
<source lang="java">
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002. * All rights reserved. Software written by Ian F. Darwin and others. * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS"" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s, * pioneering role in inventing and promulgating (and standardizing) the Java * language and environment is gratefully acknowledged. * * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for * inventing predecessor languages C and C++ is also gratefully acknowledged. */
import java.awt.*; /**
* A simple layout manager, for "Entry" areas ith e.g., a list of labels and * their corresponding JTextFields. These typically look like: **
* * Login: _______________ * Password: _______________ * *
* * Basically two (or more) columns of different, but constant, widths. Note: * all columns must be the same height! . * <P> * Construct instances by passing an array of the column width percentages (as * doubles, fractions from 0.1 to 0.9, so 40%,60% would be {0.4, 0.6}). The * length of this array uniquely determines the number of columns. Columns are * forced to be the relevant widths. Note: As with GridLayout, the * number of items added must be an even multiple of the number of * columns. If not, exceptions may be thrown! * * @author Ian F. Darwin, http://www.darwinsys.ru/ * @version $Id: EntryLayout.java,v 1.11 2004/06/01 02:51:37 ian Exp $ */
public class EntryLayout implements LayoutManager {
/** The array of widths, as decimal fractions (0.4 == 40%, etc.). */ protected final double[] widthPercentages; /** The number of columns. */ protected final int COLUMNS; /** The default padding */ protected final static int HPAD = 5, VPAD = 5; /** The actual padding */ protected final int hpad, vpad; /** True if the list of widths was valid. */ protected boolean validWidths = false; /** * Construct an EntryLayout with widths and padding specified. * * @param relWidths * Array of doubles specifying relative column widths. * @param h * Horizontal padding between items * @param v * Vertical padding between items */ public EntryLayout(double[] relWidths, int h, int v) { COLUMNS = relWidths.length; widthPercentages = new double[COLUMNS]; for (int i = 0; i < relWidths.length; i++) { if (relWidths[i] >= 1.0) throw new IllegalArgumentException( "EntryLayout: widths must be fractions < 1"); widthPercentages[i] = relWidths[i]; } validWidths = true; hpad = h; vpad = v; } /** * Construct an EntryLayout with widths and with default padding amounts. * * @param relWidths * Array of doubles specifying column widths. */ public EntryLayout(double[] relWidths) { this(relWidths, HPAD, VPAD); } /** * Adds the specified component with the specified constraint to the layout; * required by LayoutManager but not used. */ public void addLayoutComponent(String name, Component comp) { // nothing to do } /** * Removes the specified component from the layout; required by * LayoutManager, but does nothing. */ public void removeLayoutComponent(Component comp) { // nothing to do } /** * Calculates the preferred size dimensions for the specified panel given * the components in the specified parent container. */ public Dimension preferredLayoutSize(Container parent) { // System.out.println("preferredLayoutSize"); return computeLayoutSize(parent, hpad, vpad); } /** * Find the minimum Dimension for the specified container given the * components therein. */ public Dimension minimumLayoutSize(Container parent) { // System.out.println("minimumLayoutSize"); return computeLayoutSize(parent, 0, 0); } /** The width of each column, as found by computLayoutSize(). */ int[] widths; /** The height of each row, as found by computLayoutSize(). */ int[] heights; /** * Compute the size of the whole mess. Serves as the guts of * preferredLayoutSize() and minimumLayoutSize(). * * @param parent * The container in which to do the layout. * @param hp * The horizontal padding (may be zero) * @param vp * The Vertical Padding (may be zero). */ protected Dimension computeLayoutSize(Container parent, int hp, int vp) { if (!validWidths) return null; Component[] components = parent.getComponents(); Dimension contSize = parent.getSize(); int preferredWidth = 0, preferredHeight = 0; widths = new int[COLUMNS]; heights = new int[components.length / COLUMNS]; // System.out.println("Grid: " + widths.length + ", " + heights.length); int i; // Pass One: Compute largest widths and heights. for (i = 0; i < components.length; i++) { int row = i / widthPercentages.length; int col = i % widthPercentages.length; Component c = components[i]; Dimension d = c.getPreferredSize(); widths[col] = Math.max(widths[col], d.width); heights[row] = Math.max(heights[row], d.height); } // Pass two: agregate them. for (i = 0; i < widths.length; i++) preferredWidth += widths[i] + hp; for (i = 0; i < heights.length; i++) preferredHeight += heights[i] + vp; // Finally, pass the sums back as the actual size. return new Dimension(preferredWidth, preferredHeight); } /** * Lays out the container in the specified panel. This is a row-column type * layout; find x, y, width and height of each Component. * * @param parent * The Container whose children we are laying out. */ public void layoutContainer(Container parent) { if (!validWidths) return; Component[] components = parent.getComponents(); Dimension contSize = parent.getSize(); int x = 0; for (int i = 0; i < components.length; i++) { int row = i / COLUMNS; int col = i % COLUMNS; Component c = components[i]; Dimension d = c.getPreferredSize(); int colWidth = (int) (contSize.width * widthPercentages[col]); if (col == 0) { x = hpad; } else { x += hpad * (col - 1) + (int) (contSize.width * widthPercentages[col - 1]); } int y = vpad * (row) + (row * heights[row]) + (heights[row] - d.height); Rectangle r = new Rectangle(x, y, colWidth, d.height); c.setBounds(r); } }
}
</source>
Center Layout
<source lang="java">
/*
GNU LESSER GENERAL PUBLIC LICENSE Copyright (C) 2006 The Lobo Project This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Contact info: lobochief@users.sourceforge.net
- /
/*
* Created on Mar 19, 2005 */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager; /**
* @author J. H. S. */
public class CenterLayout implements LayoutManager {
public void addLayoutComponent(String arg0, Component arg1) { } public void removeLayoutComponent(Component arg0) { } public Dimension preferredLayoutSize(Container arg0) { java.awt.Insets insets = arg0.getInsets(); int count = arg0.getComponentCount(); if(count > 0) { Dimension d = arg0.getComponent(0).getPreferredSize(); return new Dimension(d.width + insets.left + insets.right, d.height + insets.top + insets.bottom); } else { return new Dimension(insets.left + insets.right, insets.top + insets.bottom); } } /* (non-Javadoc) * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container) */ public Dimension minimumLayoutSize(Container arg0) { java.awt.Insets insets = arg0.getInsets(); int count = arg0.getComponentCount(); if(count > 0) { Dimension d = arg0.getComponent(0).getMinimumSize(); return new Dimension(d.width + insets.left + insets.right, d.height + insets.top + insets.bottom); } else { return new Dimension(insets.left + insets.right, insets.top + insets.bottom); } } /* (non-Javadoc) * @see java.awt.LayoutManager#layoutContainer(java.awt.Container) */ public void layoutContainer(Container container) { int count = container.getComponentCount(); if(count > 0) { Component child = container.getComponent(0); java.awt.Insets insets = container.getInsets(); int availWidth = container.getWidth() - insets.left - insets.right; int availHeight = container.getHeight() - insets.top - insets.bottom; Dimension preferredSize = child.getPreferredSize(); double preferredWidth = preferredSize.getWidth(); double preferredHeight = preferredSize.getHeight(); int width; int height; int x; int y; if(preferredWidth < availWidth) { x = (int) Math.round(insets.left + (availWidth - preferredWidth) / 2); width = (int) Math.round(preferredWidth); } else { x = insets.left; width = availWidth; } if(preferredHeight < availHeight) { y = (int) Math.round(insets.top + (availHeight - preferredHeight) / 2); height = (int) Math.round(preferredHeight); } else { y = insets.top; height = availHeight; } child.setBounds(x, y, width, height); } } private static CenterLayout instance = new CenterLayout(); public static CenterLayout getInstance() { return instance; }
}
</source>
ColumnLayout
<source lang="java">
/*
* Copyright (c) 2000 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 2nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book (recommended), * visit http://www.davidflanagan.ru/javaexamples2. */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.Insets; import java.awt.LayoutManager2; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; /**
* This LayoutManager arranges the components into a column. Components are * always given their preferred size. * * When you create a ColumnLayout, you may specify four values: margin_height -- * how much space to leave on top and bottom margin_width -- how much space to * leave on left and right spacing -- how much vertical space to leave between * items alignment -- the horizontal position of the components: * ColumnLayout.LEFT -- left-justify the components ColumnLayout.CENTER -- * horizontally center the components ColumnLayout.RIGHT -- right-justify the * components * * You never call the methods of a ColumnLayout object. Just create one and make * it the layout manager for your container by passing it to the addLayout() * method of the Container object. */
public class ColumnLayout implements LayoutManager2 {
protected int margin_height; protected int margin_width; protected int spacing; protected int alignment; // Constants for the alignment argument to the constructor. public static final int LEFT = 0; public static final int CENTER = 1; public static final int RIGHT = 2; /** The constructor. See comment above for meanings of these arguments */ public ColumnLayout(int margin_height, int margin_width, int spacing, int alignment) { this.margin_height = margin_height; this.margin_width = margin_width; this.spacing = spacing; this.alignment = alignment; } /** * A default constructor that creates a ColumnLayout using 5-pixel margin * width and height, 5-pixel spacing, and left alignment */ public ColumnLayout() { this(5, 5, 5, LEFT); } /** * The method that actually performs the layout. Called by the Container */ public void layoutContainer(Container parent) { Insets insets = parent.getInsets(); Dimension parent_size = parent.getSize(); Component kid; int nkids = parent.getComponentCount(); int x0 = insets.left + margin_width; // The base X position int x; int y = insets.top + margin_height; // Start at the top of the column for (int i = 0; i < nkids; i++) { // Loop through the kids kid = parent.getComponent(i); // Get the kid if (!kid.isVisible()) continue; // Skip hidden ones Dimension pref = kid.getPreferredSize(); // How big is it? switch (alignment) { // Compute X coordinate default: case LEFT: x = x0; break; case CENTER: x = (parent_size.width - pref.width) / 2; break; case RIGHT: x = parent_size.width - insets.right - margin_width - pref.width; break; } // Set the size and position of this kid kid.setBounds(x, y, pref.width, pref.height); y += pref.height + spacing; // Get Y position of the next one } } /** The Container calls this to find out how big the layout should to be */ public Dimension preferredLayoutSize(Container parent) { return layoutSize(parent, 1); } /** The Container calls this to find out how big the layout must be */ public Dimension minimumLayoutSize(Container parent) { return layoutSize(parent, 2); } /** The Container calls this to find out how big the layout can be */ public Dimension maximumLayoutSize(Container parent) { return layoutSize(parent, 3); } // Compute min, max, or preferred size of all the visible children protected Dimension layoutSize(Container parent, int sizetype) { int nkids = parent.getComponentCount(); Dimension size = new Dimension(0, 0); Insets insets = parent.getInsets(); int num_visible_kids = 0; // Compute maximum width and total height of all visible kids for (int i = 0; i < nkids; i++) { Component kid = parent.getComponent(i); Dimension d; if (!kid.isVisible()) continue; num_visible_kids++; if (sizetype == 1) d = kid.getPreferredSize(); else if (sizetype == 2) d = kid.getMinimumSize(); else d = kid.getMaximumSize(); if (d.width > size.width) size.width = d.width; size.height += d.height; } // Now add in margins and stuff size.width += insets.left + insets.right + 2 * margin_width; size.height += insets.top + insets.bottom + 2 * margin_height; if (num_visible_kids > 1) size.height += (num_visible_kids - 1) * spacing; return size; } // Other LayoutManager(2) methods that are unused by this class public void addLayoutComponent(String constraint, Component comp) { } public void addLayoutComponent(Component comp, Object constraint) { } public void removeLayoutComponent(Component comp) { } public void invalidateLayout(Container parent) { } public float getLayoutAlignmentX(Container parent) { return 0.5f; } public float getLayoutAlignmentY(Container parent) { return 0.5f; }
} class ColumnLayoutPane extends JPanel {
public ColumnLayoutPane() { // Get rid of the default layout manager. // We"ll arrange the components ourselves. this.setLayout(new ColumnLayout(5, 5, 10, ColumnLayout.RIGHT)); // Create some buttons and set their sizes and positions explicitly for (int i = 0; i < 6; i++) { int pointsize = 8 + i * 2; JButton b = new JButton("Point size " + pointsize); b.setFont(new Font("helvetica", Font.BOLD, pointsize)); this.add(b); } } public static void main(String[] a) { JFrame f = new JFrame(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setContentPane(new ColumnLayoutPane()); f.pack(); f.setVisible(true); }
}
</source>
Compents are laid out in a circle.
<source lang="java">
/*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * ----------------- * RadialLayout.java * ----------------- * (C) Copyright 2003, 2004, by Bryan Scott (for Australian Antarctic Division). * * Original Author: Bryan Scott (for Australian Antarctic Division); * Contributor(s): David Gilbert (for Object Refinery Limited); * * * Changes: * -------- * 30-Jun-2003 : Version 1 (BS); * 24-Jul-2003 : Completed missing Javadocs (DG); * */
import java.awt.Checkbox; import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Frame; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Panel; import java.io.Serializable; /**
* RadialLayout is a component layout manager. Compents are laid out in a * circle. If only one component is contained in the layout it is positioned * centrally, otherwise components are evenly spaced around the centre with * the first component placed to the North. *<P> * This code was developed to display CTD rosette firing control * * WARNING: Not thoughly tested, use at own risk. * * @author Bryan Scott (for Australian Antarctic Division) */
public class RadialLayout implements LayoutManager, Serializable {
/** For serialization. */ private static final long serialVersionUID = -7582156799248315534L; /** The minimum width. */ private int minWidth = 0; /** The minimum height. */ private int minHeight = 0; /** The maximum component width. */ private int maxCompWidth = 0; /** The maximum component height. */ private int maxCompHeight = 0; /** The preferred width. */ private int preferredWidth = 0; /** The preferred height. */ private int preferredHeight = 0; /** Size unknown flag. */ private boolean sizeUnknown = true; /** * Constructs this layout manager with default properties. */ public RadialLayout() { super(); } /** * Not used. * * @param comp the component. */ public void addLayoutComponent(final Component comp) { // not used } /** * Not used. * * @param comp the component. */ public void removeLayoutComponent(final Component comp) { // not used } /** * Not used. * * @param name the component name. * @param comp the component. */ public void addLayoutComponent(final String name, final Component comp) { // not used } /** * Not used. * * @param name the component name. * @param comp the component. */ public void removeLayoutComponent(final String name, final Component comp) { // not used } /** * Sets the sizes attribute of the RadialLayout object. * * @param parent the parent. * * @see LayoutManager */ private void setSizes(final Container parent) { final int nComps = parent.getComponentCount(); //Reset preferred/minimum width and height. this.preferredWidth = 0; this.preferredHeight = 0; this.minWidth = 0; this.minHeight = 0; for (int i = 0; i < nComps; i++) { final Component c = parent.getComponent(i); if (c.isVisible()) { final Dimension d = c.getPreferredSize(); if (this.maxCompWidth < d.width) { this.maxCompWidth = d.width; } if (this.maxCompHeight < d.height) { this.maxCompHeight = d.height; } this.preferredWidth += d.width; this.preferredHeight += d.height; } } this.preferredWidth = this.preferredWidth / 2; this.preferredHeight = this.preferredHeight / 2; this.minWidth = this.preferredWidth; this.minHeight = this.preferredHeight; } /** * Returns the preferred size. * * @param parent the parent. * * @return The preferred size. * @see LayoutManager */ public Dimension preferredLayoutSize(final Container parent) { final Dimension dim = new Dimension(0, 0); setSizes(parent); //Always add the container"s insets! final Insets insets = parent.getInsets(); dim.width = this.preferredWidth + insets.left + insets.right; dim.height = this.preferredHeight + insets.top + insets.bottom; this.sizeUnknown = false; return dim; } /** * Returns the minimum size. * * @param parent the parent. * * @return The minimum size. * @see LayoutManager */ public Dimension minimumLayoutSize(final Container parent) { final Dimension dim = new Dimension(0, 0); //Always add the container"s insets! final Insets insets = parent.getInsets(); dim.width = this.minWidth + insets.left + insets.right; dim.height = this.minHeight + insets.top + insets.bottom; this.sizeUnknown = false; return dim; } /** * This is called when the panel is first displayed, and every time its size * changes. * Note: You CAN"T assume preferredLayoutSize or minimumLayoutSize will be * called -- in the case of applets, at least, they probably won"t be. * * @param parent the parent. * @see LayoutManager */ public void layoutContainer(final Container parent) { final Insets insets = parent.getInsets(); final int maxWidth = parent.getSize().width - (insets.left + insets.right); final int maxHeight = parent.getSize().height - (insets.top + insets.bottom); final int nComps = parent.getComponentCount(); int x = 0; int y = 0; // Go through the components" sizes, if neither preferredLayoutSize nor // minimumLayoutSize has been called. if (this.sizeUnknown) { setSizes(parent); } if (nComps < 2) { final Component c = parent.getComponent(0); if (c.isVisible()) { final Dimension d = c.getPreferredSize(); c.setBounds(x, y, d.width, d.height); } } else { double radialCurrent = Math.toRadians(90); final double radialIncrement = 2 * Math.PI / nComps; final int midX = maxWidth / 2; final int midY = maxHeight / 2; final int a = midX - this.maxCompWidth; final int b = midY - this.maxCompHeight; for (int i = 0; i < nComps; i++) { final Component c = parent.getComponent(i); if (c.isVisible()) { final Dimension d = c.getPreferredSize(); x = (int) (midX - (a * Math.cos(radialCurrent)) - (d.getWidth() / 2) + insets.left); y = (int) (midY - (b * Math.sin(radialCurrent)) - (d.getHeight() / 2) + insets.top); // Set the component"s size and position. c.setBounds(x, y, d.width, d.height); } radialCurrent += radialIncrement; } } } /** * Returns the class name. * * @return The class name. */ public String toString() { return getClass().getName(); } /** * Run a demonstration. * * @param args ignored. * * @throws Exception when an error occurs. */ public static void main(final String[] args) throws Exception { final Frame frame = new Frame(); final Panel panel = new Panel(); panel.setLayout(new RadialLayout()); panel.add(new Checkbox("One")); panel.add(new Checkbox("Two")); panel.add(new Checkbox("Three")); panel.add(new Checkbox("Four")); panel.add(new Checkbox("Five")); panel.add(new Checkbox("One")); panel.add(new Checkbox("Two")); panel.add(new Checkbox("Three")); panel.add(new Checkbox("Four")); panel.add(new Checkbox("Five")); frame.add(panel); frame.setSize(300, 500); frame.setVisible(true); }
}
</source>
Customized layout manager
<source lang="java">
import java.awt.Button; import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; public class CircleLayoutTest extends JFrame {
public CircleLayoutTest() { setTitle("CircleLayoutTest"); setSize(300, 300); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); getContentPane().setLayout(new CircleLayout()); getContentPane().add(new Button("3")); getContentPane().add(new Button("4")); getContentPane().add(new Button("5")); getContentPane().add(new Button("6")); getContentPane().add(new Button("7")); getContentPane().add(new Button("8")); getContentPane().add(new Button("9")); getContentPane().add(new Button("10")); getContentPane().add(new Button("11")); getContentPane().add(new Button("12")); getContentPane().add(new Button("1")); getContentPane().add(new Button("2")); } public static void main(String[] args) { JFrame f = new CircleLayoutTest(); f.show(); }
} class CircleLayout implements LayoutManager {
private int minWidth = 0; private int minHeight = 0; private int preferredWidth = 0, preferredHeight = 0; private boolean sizesSet = false; private int maxComponentWidth = 0; private int maxComponentHeight = 0; public void addLayoutComponent(String name, Component comp) { } public void removeLayoutComponent(Component comp) { } public void setSizes(Container parent) { if (sizesSet) return; int comCount = parent.getComponentCount(); for (int i = 0; i < comCount; i++) { Component c = parent.getComponent(i); if (c.isVisible()) { Dimension size = c.getPreferredSize(); maxComponentWidth = Math.max(maxComponentWidth, size.width); maxComponentHeight = Math.max(maxComponentWidth, size.height); preferredHeight += size.height; } } preferredHeight += maxComponentHeight; preferredWidth = 2 * maxComponentWidth; minHeight = preferredHeight; minWidth = preferredWidth; sizesSet = true; } public Dimension preferredLayoutSize(Container parent) { Dimension dim = new Dimension(0, 0); setSizes(parent); Insets insets = parent.getInsets(); dim.width = preferredWidth + insets.left + insets.right; dim.height = preferredHeight + insets.top + insets.bottom; return dim; } public Dimension minimumLayoutSize(Container parent) { return preferredLayoutSize(parent); } public void layoutContainer(Container parent) { Insets insets = parent.getInsets(); int containerWidth = parent.getSize().width - insets.left - insets.right; int containerHeight = parent.getSize().height - insets.top - insets.bottom; int xradius = (containerWidth - maxComponentWidth) / 2; int yradius = (containerHeight - maxComponentHeight) / 2; setSizes(parent); int centerX = insets.left + containerWidth / 2; int centerY = insets.top + containerHeight / 2; int comCount = parent.getComponentCount(); for (int i = 0; i < comCount; i++) { Component c = parent.getComponent(i); if (c.isVisible()) { Dimension size = c.getPreferredSize(); double angle = 2 * Math.PI * i / comCount; int x = centerX + (int) (Math.cos(angle) * xradius); int y = centerY + (int) (Math.sin(angle) * yradius); c.setBounds(x - size.width / 2, y - size.height / 2, size.width, size.height); } } }
}
</source>
Custom Layout Demo
<source lang="java">
/* From http://java.sun.ru/docs/books/tutorial/index.html */ /*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */
/*
* CustomLayoutDemo.java is a 1.4 application that requires one other file: * DiagonalLayout.java */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import javax.swing.JButton; import javax.swing.JFrame; public class CustomLayoutDemo {
public static void addComponentsToPane(Container pane) { pane.setLayout(new DiagonalLayout()); pane.add(new JButton("Button 1")); pane.add(new JButton("Button 2")); pane.add(new JButton("Button 3")); pane.add(new JButton("Button 4")); pane.add(new JButton("Button 5")); } /** * Create the GUI and show it. For thread safety, this method should be * invoked from the event-dispatching thread. */ private static void createAndShowGUI() { //Make sure we have nice window decorations. JFrame.setDefaultLookAndFeelDecorated(true); //Create and set up the window. JFrame frame = new JFrame("CustomLayoutDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Set up the content pane. addComponentsToPane(frame.getContentPane()); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { //Schedule a job for the event-dispatching thread: //creating and showing this application"s GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); }
} /*
* 1.2+ version. Used by CustomLayoutDemo.java. */
class DiagonalLayout implements LayoutManager {
private int vgap; private int minWidth = 0, minHeight = 0; private int preferredWidth = 0, preferredHeight = 0; private boolean sizeUnknown = true; public DiagonalLayout() { this(5); } public DiagonalLayout(int v) { vgap = v; } /* Required by LayoutManager. */ public void addLayoutComponent(String name, Component comp) { } /* Required by LayoutManager. */ public void removeLayoutComponent(Component comp) { } private void setSizes(Container parent) { int nComps = parent.getComponentCount(); Dimension d = null; //Reset preferred/minimum width and height. preferredWidth = 0; preferredHeight = 0; minWidth = 0; minHeight = 0; for (int i = 0; i < nComps; i++) { Component c = parent.getComponent(i); if (c.isVisible()) { d = c.getPreferredSize(); if (i > 0) { preferredWidth += d.width / 2; preferredHeight += vgap; } else { preferredWidth = d.width; } preferredHeight += d.height; minWidth = Math.max(c.getMinimumSize().width, minWidth); minHeight = preferredHeight; } } } /* Required by LayoutManager. */ public Dimension preferredLayoutSize(Container parent) { Dimension dim = new Dimension(0, 0); int nComps = parent.getComponentCount(); setSizes(parent); //Always add the container"s insets! Insets insets = parent.getInsets(); dim.width = preferredWidth + insets.left + insets.right; dim.height = preferredHeight + insets.top + insets.bottom; sizeUnknown = false; return dim; } /* Required by LayoutManager. */ public Dimension minimumLayoutSize(Container parent) { Dimension dim = new Dimension(0, 0); int nComps = parent.getComponentCount(); //Always add the container"s insets! Insets insets = parent.getInsets(); dim.width = minWidth + insets.left + insets.right; dim.height = minHeight + insets.top + insets.bottom; sizeUnknown = false; return dim; } /* Required by LayoutManager. */ /* * This is called when the panel is first displayed, and every time its size * changes. Note: You CAN"T assume preferredLayoutSize or minimumLayoutSize * will be called -- in the case of applets, at least, they probably won"t * be. */ public void layoutContainer(Container parent) { Insets insets = parent.getInsets(); int maxWidth = parent.getWidth() - (insets.left + insets.right); int maxHeight = parent.getHeight() - (insets.top + insets.bottom); int nComps = parent.getComponentCount(); int previousWidth = 0, previousHeight = 0; int x = 0, y = insets.top; int rowh = 0, start = 0; int xFudge = 0, yFudge = 0; boolean oneColumn = false; // Go through the components" sizes, if neither // preferredLayoutSize nor minimumLayoutSize has // been called. if (sizeUnknown) { setSizes(parent); } if (maxWidth <= minWidth) { oneColumn = true; } if (maxWidth != preferredWidth) { xFudge = (maxWidth - preferredWidth) / (nComps - 1); } if (maxHeight > preferredHeight) { yFudge = (maxHeight - preferredHeight) / (nComps - 1); } for (int i = 0; i < nComps; i++) { Component c = parent.getComponent(i); if (c.isVisible()) { Dimension d = c.getPreferredSize(); // increase x and y, if appropriate if (i > 0) { if (!oneColumn) { x += previousWidth / 2 + xFudge; } y += previousHeight + vgap + yFudge; } // If x is too large, if ((!oneColumn) && (x + d.width) > (parent.getWidth() - insets.right)) { // reduce x to a reasonable number. x = parent.getWidth() - insets.bottom - d.width; } // If y is too large, if ((y + d.height) > (parent.getHeight() - insets.bottom)) { // do nothing. // Another choice would be to do what we do to x. } // Set the component"s size and position. c.setBounds(x, y, d.width, d.height); previousWidth = d.width; previousHeight = d.height; } } } public String toString() { String str = ""; return getClass().getName() + "[vgap=" + vgap + str + "]"; }
}
</source>
Custom layout: EdgeLayout
<source lang="java">
/* Code from Desktop Java Live Source URL: http://www.sourcebeat.ru/downloads/
- /
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager2; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class EdgeLayoutExample {
public static JPanel createPanel() { JPanel outerPanel = new JPanel(); outerPanel.setLayout(new EdgeLayout()); outerPanel.add(new JButton("West1"), EdgeLayout.WEST); outerPanel.add(new JButton("North1"), EdgeLayout.NORTH); outerPanel.add(new JButton("West2"), EdgeLayout.WEST); outerPanel.add(new JButton("North2"), EdgeLayout.NORTH); outerPanel.add(new JButton("East1"), EdgeLayout.EAST); outerPanel.add(new JButton("South1"), EdgeLayout.SOUTH); outerPanel.add(new JButton("West3"), EdgeLayout.WEST); outerPanel.add(new JButton("West4"), EdgeLayout.WEST); outerPanel.add(new JButton("South2"), EdgeLayout.SOUTH); outerPanel.add(new JButton("South3"), EdgeLayout.SOUTH); outerPanel.add(new JButton("Center1"), EdgeLayout.CENTER); return outerPanel; } public static void main(String[] a){ JFrame f = new JFrame(); f.setDefaultCloseOperation(1); f.add(createPanel()); f.pack(); f.setVisible(true); }
}
class EdgeLayout implements LayoutManager2, java.io.Serializable {
private List components = new ArrayList(); private HashMap constraints = new HashMap(); public static final String CENTER = "center"; public static final String NORTH = "north"; public static final String SOUTH = "south"; public static final String EAST = "east"; public static final String WEST = "west"; public void addLayoutComponent(Component comp, Object constraints) { synchronized (comp.getTreeLock()) { if (constraints instanceof String && comp != null) { this.ruponents.add(comp); this.constraints.put(comp, constraints); } else { throw new IllegalArgumentException("Invalid component constraints."); } } } public Dimension maximumLayoutSize(Container target) { //Return a very large size since this layout manager will fill all available space. return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } public float getLayoutAlignmentX(Container target) { //Centered on the X return (float) 0.5; } public float getLayoutAlignmentY(Container target) { //Centered on the Y return (float) 0.5; } public void invalidateLayout(Container target) { //There is no caching in EdgeLayout to there is nothing to invalidate } public void addLayoutComponent(String name, Component comp) { throw new IllegalArgumentException("EdgeLayout only supports addition with contraints."); } public void removeLayoutComponent(Component comp) { synchronized (comp.getTreeLock()) { this.ruponents.remove(comp); this.constraints.remove(comp); } } public Dimension preferredLayoutSize(Container parent) { synchronized (parent.getTreeLock()) { int width = 0; int height = 0; //Add the preferred widths of all EAST/WEST components //Add the preferred height of all NORTH/SOUTH components for (int i = 0; i < this.ruponents.size(); i++) { Component c = (Component) this.ruponents.get(i); if (this.constraints.get(c).equals(WEST) || this.constraints.get(c).equals(EAST)) { width += c.getPreferredSize().getWidth(); } else { height += c.getPreferredSize().getHeight(); } } width += parent.getInsets().right + parent.getInsets().left; height += parent.getInsets().top + parent.getInsets().bottom; return new Dimension(width, height); } } public Dimension minimumLayoutSize(Container parent) { synchronized (parent.getTreeLock()) { int width = 0; int height = 0; //Add the minimum widths of all EAST/WEST components //Add the minimum height of all NORTH/SOUTH components for (int i = 0; i < this.ruponents.size(); i++) { Component c = (Component) this.ruponents.get(i); if (this.constraints.get(c).equals(WEST) || this.constraints.get(c).equals(EAST)) { width += c.getMinimumSize().getWidth(); } else { height += c.getMinimumSize().getHeight(); } } width += parent.getInsets().right + parent.getInsets().left; height += parent.getInsets().top + parent.getInsets().bottom; return new Dimension(width, height); } } public void layoutContainer(Container parent) { synchronized (parent.getTreeLock()) { Insets insets = parent.getInsets(); int top = insets.top; int left = insets.left; Dimension minimumSize = minimumLayoutSize(parent); int height = minimumSize.height; int width = minimumSize.width; int availableHeight = parent.getHeight() - insets.bottom - insets.top; int availableWidth = parent.getWidth() - insets.left - insets.right; if (height < availableHeight) { height = availableHeight; } if (width < availableWidth) { width = availableWidth; } int bottom = availableHeight; int right = availableWidth; Dimension preferredSize = preferredLayoutSize(parent); int preferredWidthAvailable = width - preferredSize.width; int preferredHeightAvailable = height - preferredSize.height;
Component centerComp = null; for (int i = 0; i < this.ruponents.size(); i++) { Component c = (Component) this.ruponents.get(i); String constraint = (String) this.constraints.get(c); if (constraint.equals(CENTER)) { centerComp = c; } else { int compHeight; int compWidth; int xOrigin; int yOrigin;
if (constraint.equals(NORTH) || constraint.equals(SOUTH)) { compWidth = width; if (preferredHeightAvailable > 0) { int preferredHeightNeeded = c.getPreferredSize().height - c.getMinimumSize().height; if (preferredHeightAvailable > preferredHeightNeeded) { compHeight = c.getPreferredSize().height; preferredHeightAvailable -= preferredHeightNeeded; } else { compHeight = c.getMinimumSize().height + preferredHeightAvailable; preferredHeightAvailable = 0; } } else { compHeight = c.getMinimumSize().height; } height = height - compHeight; xOrigin = left; if (constraint.equals(NORTH)) { yOrigin = top; top += compHeight; } else { yOrigin = bottom - compHeight; bottom = yOrigin; } } else { compHeight = height; if (preferredWidthAvailable > 0) { int preferredWidthNeeded = c.getPreferredSize().width - c.getMinimumSize().width; if (preferredWidthAvailable > preferredWidthNeeded) { compWidth = c.getPreferredSize().width; preferredWidthAvailable -= preferredWidthNeeded; } else { compWidth = c.getMinimumSize().width + preferredWidthAvailable; preferredWidthAvailable = 0; } } else { compWidth = c.getMinimumSize().width; } width = width - compWidth; yOrigin = top; if (constraint.equals(WEST)) { xOrigin = left; left += compWidth; } else { xOrigin = right - compWidth; right = xOrigin; } } c.setSize(compWidth, compHeight); c.setBounds(xOrigin, yOrigin, compWidth, compHeight); } if (centerComp != null) { c.setSize(width, height); c.setBounds(left, top, width, height); } } } }
}
</source>
DividerLayout is layout that divides two components with the column of actions
<source lang="java">
/*
* $Id: DividerLayout.java,v 1.1.1.1 2005/04/07 18:36:20 pocho Exp $ */
// Revised from javautils swing; import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager2; import java.awt.Rectangle; /**
* <p>
* DividerLayout
is layout that divides two components with the
* column of actions. It is especially usefull for components that contains
* two lists of elements and buttons for transfering elements between these
* two lists.
*
* * Components are indicated as {@link #WEST}, {@link #EAST} and {@link #CENTER}. *
* * @version $Name: $ - $Revision: 1.1.1.1 $ - $Date: 2005/04/07 18:36:20 $ * TODO Test */
public class DividerLayout implements LayoutManager2 {
/** * Indicates west component */ public final static String WEST = "WEST"; /** * indicates east component */ public final static String EAST = "EAST"; /** * indicates center component */ public final static String CENTER = "CENTER"; /** * west component */ protected Component westComponent; /** * center component */ protected Component centerComponent; /** * east component */ protected Component eastComponent; /** * Adds a component to specified position. */ public void addLayoutComponent(Component comp, Object constraints) { if (WEST.equalsIgnoreCase((String) constraints)) { westComponent = comp; } else if (CENTER.equalsIgnoreCase((String) constraints)) { centerComponent = comp; } else if (EAST.equalsIgnoreCase((String) constraints)) { eastComponent = comp; } } /** * @see java.awt.LayoutManager2#maximumLayoutSize(java.awt.Container) */ public Dimension maximumLayoutSize(Container target) { Dimension size; int width = 0; int height = 0; if ((westComponent != null) && (westComponent.isVisible())) { size = westComponent.getMaximumSize(); width = Math.max(width, size.width); height = Math.max(height, size.height); } if ((eastComponent != null) && (eastComponent.isVisible())) { size = eastComponent.getMaximumSize(); width = Math.max(width, size.width); height = Math.max(height, size.height); } width *= 2; if ((centerComponent != null) && (centerComponent.isVisible())) { size = centerComponent.getPreferredSize(); width += size.width; height = Math.max(height, size.height); } return new Dimension(width, height); } /** * @see java.awt.LayoutManager2#getLayoutAlignmentX(java.awt.Container) */ public float getLayoutAlignmentX(Container target) { return 0.0f; } /** * @see java.awt.LayoutManager2#getLayoutAlignmentY(java.awt.Container) */ public float getLayoutAlignmentY(Container target) { return 0.0f; } /** * @see java.awt.LayoutManager2#invalidateLayout(java.awt.Container) */ public void invalidateLayout(Container target) {} /** * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.ruponent) */ public void addLayoutComponent(String name, Component comp) { addLayoutComponent(comp, name); } /** * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.ruponent) */ public void removeLayoutComponent(Component comp) { if (comp == westComponent) { westComponent = null; } else if (comp == centerComponent) { centerComponent = null; } else if (comp == eastComponent) { centerComponent = null; } } /** * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container) */ public Dimension preferredLayoutSize(Container parent) { Dimension size; int width = 0; int height = 0; if ((westComponent != null) && (westComponent.isVisible())) { size = westComponent.getPreferredSize(); width = Math.max(width, size.width); height = Math.max(height, size.height); } if ((eastComponent != null) && (eastComponent.isVisible())) { size = eastComponent.getPreferredSize(); width = Math.max(width, size.width); height = Math.max(height, size.height); } width *= 2; if ((centerComponent != null) && (centerComponent.isVisible())) { size = centerComponent.getPreferredSize(); width += size.width; height = Math.max(height, size.height); } return new Dimension(width, height); }
/** * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container) */ public Dimension minimumLayoutSize(Container parent) { Dimension size; int width = 0; int height = 0; if ((westComponent != null) && (westComponent.isVisible())) { size = westComponent.getMinimumSize(); width = Math.max(width, size.width); height = Math.max(height, size.height); } if ((eastComponent != null) && (eastComponent.isVisible())) { size = eastComponent.getMinimumSize(); width = Math.max(width, size.width); height = Math.max(height, size.height); } width *= 2; if ((centerComponent != null) && (centerComponent.isVisible())) { size = centerComponent.getPreferredSize(); width += size.width; height += Math.max(height, size.height); } return new Dimension(width, height); } /** * @see java.awt.LayoutManager#layoutContainer(java.awt.Container) */ public void layoutContainer(Container container) { Insets insets = container.getInsets(); Dimension westSize = new Dimension(0, 0); Dimension centerSize = new Dimension(0, 0); Dimension eastSize = new Dimension(0, 0); Rectangle centerBounds = new Rectangle(0, 0, 0, 0); Dimension containerSize = container.getSize(); int centerX = containerSize.width / 2; int centerY = containerSize.height / 2; if ((centerComponent != null) && (centerComponent.isVisible())) { centerSize = centerComponent.getPreferredSize(); centerSize.width = Math.min(centerSize.width, containerSize.width - insets.left - insets.right); centerSize.height = Math.min(centerSize.height, containerSize.height - insets.top - insets.bottom); centerComponent.setBounds(centerX - (centerSize.width / 2), centerY - (centerSize.height / 2), centerSize.width, centerSize.height); centerBounds = centerComponent.getBounds(); } if ((westComponent != null) && (westComponent.isVisible())) { westSize = westComponent.getPreferredSize(); } if ((eastComponent != null) && (eastComponent.isVisible())) { eastSize = eastComponent.getPreferredSize(); } /* int maxWidth = Math.min(westSize.width, eastSize.width); maxWidth = Math.min(maxWidth, (containerSize.width - centerBounds.width - insets.left - insets.right) / 2);*/ int maxWidth = (containerSize.width - centerBounds.width - insets.left - insets.right) / 2; /* int maxHeight = Math.min(westSize.height, eastSize.height); maxHeight = Math.max(maxHeight, containerSize.height - insets.top - insets.bottom);*/ int maxHeight=containerSize.height - insets.top - insets.bottom; if (westComponent != null) { westComponent.setBounds(centerBounds.x - maxWidth, centerY - (maxHeight / 2), maxWidth, maxHeight); } if (eastComponent != null) { eastComponent.setBounds(centerBounds.x + centerBounds.width, centerY - (maxHeight / 2), maxWidth, maxHeight); } }
}
</source>
Flex Layout
<source lang="java">
// FlexLayout // Copyright (C) by Andrea Carboni. // This file may be distributed under the terms of the LGPL license.
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.util.StringTokenizer; /** This class implements a combination of the GridBag and Border layouts. The
* container is subdivided into rows and columns (basically a grid). Each cell * can be empty or can contain a component and a component can occupy one or more * cells. If a component is smaller than its cell, it can be aligned both horizontally * and vertically. The width of a column is the width of its largest component. The * height of a row is the height of its tallest component. Furthermore, a row or a * column can be expandable, that is its width/height changes depending on the container"s * size.* Example:
* General design issues:
* First, decide the grid size. Consider that some components (like panels) usually * spread over more cells so it is a good idea to make the grid a little bigger.
* Second, decide which row/column expand (this is done by the setColProp/setRowProp * methods).
* Third, add components to container (layout) giving proper constraints.
* FlexLayout flexL = new FlexLayout(2, 3, 4, 4); //--- (1) * flexL.setColProp(1, FlexLayout.EXPAND); //--- (2) * flexL.setRowProp(2, FlexLayout.EXPAND); //--- (3) * setLayout(flexL); //--- (4) * * add("0,0", new Label("Name")); //--- (5) * add("0,1", new Label("Surname")); //--- (6) * add("1,0,x", textField); //--- (7) * add("1,1,x", textField); //--- (8) * add("0,2,x,x,2", panel); //--- (9) *
* Description:* The complete command string is:
* line 1: creates a FlexLayout of 2 columns and 3 rows. The two 4 represent the gap * between each column and each row. To modify this gap use setXgap and setYgap.
* line 2 & 3: column 1 and row 2 are set to expandable (the default is USEPREFERRED) * remember that row and column id starts from index 0.
* line 4: the layout is added to the container.
* line 5 & 6: add two labels in position (0,0) and (0,1) * line 7 & 8: add two textfields in position (1,0) and (1,1). The x means that the * width will be expanded to occupy all column size. Because column 1 is set to expandable, * when the container is resized the textfields are resized too.
* line 9: adds a panel in position (0,2). Then panel is expanded both horizontally and * vertically and spreads over 2 cells in x direction.
* "x,y,xa,ya,xs,ys" where: * x,y specify the component position (are the column-row indexes) * xa specifies the x align of the component and can be: * l - for left * c - for center * r - for right * x - exands the component"s width * (default is l) * ya specifies the y align of the component and can be: * t - for top * c - for center * b - for bottom * x - exands the component"s height * (default is c) * xs and ys specify the number or columns/rows occupied by the component (default is 1) *
* Notes:
* - if a component occupies more than 1 cell in x direction, its preferred width is NOT * taken into account (same for y).
* - if a column / row is empty, its size is set to a default value. This value can be * changed using setXNullgap/setYNullgap methods. *
* Have fun!!! * * @author Andrea Carboni */
public class FlexLayout implements LayoutManager {
private int xgap; private int ygap; private int width; private int height; private int xnullgap = 24; private int ynullgap = 24; private FlexCell cells[][]; //--- flags for rows and columns --- public static final int USEPREFERRED = 0; //--- default --- public static final int EXPAND = 1; private int xflags[]; private int yflags[]; private int xpref[]; private int ypref[]; //--------------------------------------------------------------------------- public FlexLayout(int width, int height) { this(width, height, 4, 4); } //--------------------------------------------------------------------------- public FlexLayout(int width, int height, int xgap, int ygap) { if (width <1 || height <1) throw new IllegalArgumentException("width & height must be >0"); this.width = width; this.height = height; this.xgap = xgap; this.ygap = ygap; cells = new FlexCell[width][height]; xflags = new int[width]; yflags = new int[height]; xpref = new int[width]; ypref = new int[height]; } //--------------------------------------------------------------------------- public void setColProp(int index, int flag) { xflags[index] = flag; } //--------------------------------------------------------------------------- public void setRowProp(int index, int flag) { yflags[index] = flag; } //--------------------------------------------------------------------------- public void setNullGaps(int xgap, int ygap) { xnullgap = xgap; ynullgap = ygap; } //--------------------------------------------------------------------------- public void setXgap(int xgap) { this.xgap = xgap; } public void setYgap(int ygap) { this.ygap = ygap; } public int getXgap() { return xgap; } public int getYgap() { return ygap; } public int getXNullgap() { return xnullgap; } public int getYNullgap() { return ynullgap; } public int getWidth() { return width; } public int getHeight() { return height; } //--------------------------------------------------------------------------- //--- //--- LayoutManager Interface //--- //--------------------------------------------------------------------------- public void addLayoutComponent(String name, Component comp) { StringTokenizer strTk = new StringTokenizer(name,","); int x = 1; int y = 1; int xalign = FlexCell.LEFT; int yalign = FlexCell.CENTERY; int xext = 1; int yext = 1; if (strTk.hasMoreTokens()) x = Integer.parseInt(strTk.nextToken()); if (strTk.hasMoreTokens()) y = Integer.parseInt(strTk.nextToken()); if (strTk.hasMoreTokens()) { String align = strTk.nextToken().toLowerCase(); if (align.equals("l")) xalign = FlexCell.LEFT; if (align.equals("c")) xalign = FlexCell.CENTERX; if (align.equals("r")) xalign = FlexCell.RIGHT; if (align.equals("x")) xalign = FlexCell.EXPANDX; } if (strTk.hasMoreTokens()) { String align = strTk.nextToken().toLowerCase(); if (align.equals("t")) yalign = FlexCell.TOP; if (align.equals("c")) yalign = FlexCell.CENTERY; if (align.equals("b")) yalign = FlexCell.BOTTOM; if (align.equals("x")) yalign = FlexCell.EXPANDY; } if (strTk.hasMoreTokens()) xext = Integer.parseInt(strTk.nextToken()); if (strTk.hasMoreTokens()) yext = Integer.parseInt(strTk.nextToken()); cells[x][y] = new FlexCell(xalign, yalign, xext, yext, comp); } //--------------------------------------------------------------------------- public void removeLayoutComponent(Component comp) { for(int x=0; x<width; x++) for(int y=0; y<height; y++) if (cells[x][y].ruponent == comp) { cells[x][y] = null; return; } } //--------------------------------------------------------------------------- public Dimension preferredLayoutSize(Container parent) { synchronized (parent.getTreeLock()) { calcMaxWidthArray(); calcMaxHeightArray(); int maxW = 0; int maxH = 0; for(int x=0; x<width; x++) maxW += xpref[x]; for(int y=0; y<height; y++) maxH += ypref[y]; Insets insets = parent.getInsets(); return new Dimension(insets.left + insets.right + maxW + (width-1)*xgap, insets.top + insets.bottom + maxH + (height-1)*ygap); } } //--------------------------------------------------------------------------- public Dimension minimumLayoutSize(Container parent) { return preferredLayoutSize(parent); } //--------------------------------------------------------------------------- public void layoutContainer(Container parent) { synchronized (parent.getTreeLock()) { FlexCell cell; //--- maximun preferred Width & Height calculus for each column --- calcMaxWidthArray(); calcMaxHeightArray(); //--------------------------------------------------------------------- //--- Layout Calculus //--------------------------------------------------------------------- Insets i = parent.getInsets(); int maxWidth = parent.getSize().width - i.left - i.right - (width-1)*xgap; int maxHeight = parent.getSize().height- i.top - i.bottom- (height-1)*ygap; //--- total space occupied by fixed columns (and rows) --- int fixedWidth = 0; int fixedHeight = 0; //--- number of variable columns (and rows) --- int varXCount = 0; int varYCount = 0; //--- width of a variable column (or row) --- int varWidth = 0; int varHeight = 0; //--------------------------------------------------------------------- //--- Handle Columns //--------------------------------------------------------------------- //--- calc totale space occupied by fixed columns --- for(int x=0; x<width; x++) { if (xflags[x] == USEPREFERRED) fixedWidth += xpref[x]; else varXCount++; } //--- calc width of a generic variable column --- if (varXCount != 0) { varWidth = (maxWidth - fixedWidth) / varXCount; if (varWidth < 0) varWidth = 0; } //--- calc width for expandable columns --- for(int x=0; x<width; x++) if (xflags[x] == EXPAND) xpref[x] = varWidth; //--------------------------------------------------------------------- //--- Handle Rows //--------------------------------------------------------------------- //--- calc totale space occupied by fixed rows --- for(int y=0; y<height; y++) { if (yflags[y] == USEPREFERRED) fixedHeight += ypref[y]; else varYCount++; } //--- calc height of a generic variable row --- if (varYCount != 0) { varHeight = (maxHeight - fixedHeight) / varYCount; if (varHeight < 0) varHeight = 0; } //--- calc width for expandable rows --- for(int y=0; y<height; y++) if (yflags[y] == EXPAND) ypref[y] = varHeight; //--------------------------------------------------------------------- //--- Do Layout //--------------------------------------------------------------------- int currentX = i.left; int currentY = i.top; int compX, compY, compW, compH; int cellW, cellH; int xc, yc; for(int y=0; y<height; y++) { currentX = i.left; for(int x=0; x<width; x++) { //--- calculate current cell width and height --- cellW = 0; cellH = 0; cell = cells[x][y]; if (cell != null) { for(xc = x; xc< x + cell.xext; xc++) cellW += xpref[xc]; for(yc = y; yc< y + cell.yext; yc++) cellH += ypref[yc]; Dimension compSize = cell.ruponent.getPreferredSize(); //------------------------------------------------------------ //--- calculate compX & compW depending on align //------------------------------------------------------------ switch(cell.xalign) { case FlexCell.LEFT: compX = currentX; compW = compSize.width; break; case FlexCell.CENTERX: compX = currentX + (cellW - compSize.width)/2; compW = compSize.width; break; case FlexCell.RIGHT: compX = currentX + cellW - compSize.width; compW = compSize.width; break; case FlexCell.EXPANDX: compX = currentX; compW = cellW; break; default: System.out.println("FlexLayout: invalid X align type"); compX = currentX; compW = cellW; break; } //------------------------------------------------------------ //--- calculate compY & compH depending on align //------------------------------------------------------------ switch(cell.yalign) { case FlexCell.TOP: compY = currentY; compH = compSize.height; break; case FlexCell.CENTERY: compY = currentY + (cellH - compSize.height)/2; compH = compSize.height; break; case FlexCell.BOTTOM: compY = currentY + cellH - compSize.height; compH = compSize.height; break; case FlexCell.EXPANDY: compY = currentY; compH = cellH; break; default: System.out.println("FlexLayout: invalid Y align type"); compY = currentY; compH = cellH; break; } //--- resize component --- cell.ruponent.setBounds(compX, compY, compW + (cell.xext-1)*xgap, compH + (cell.yext-1)*ygap); } currentX += xpref[x] + xgap; } currentY += ypref[y] + ygap; } } } //--------------------------------------------------------------------------- private void calcMaxWidthArray() { //--- maximun preferred Width calculus for each column --- FlexCell cell; int maxPrefW, curPrefW; for(int x=0; x<width; x++) { maxPrefW = 0; for(int y=0; y<height; y++) { cell = cells[x][y]; if (cell != null && cell.xext == 1) { curPrefW = cell.ruponent.getPreferredSize().width; if (curPrefW > maxPrefW) maxPrefW = curPrefW; } } if (maxPrefW == 0) maxPrefW = xnullgap; xpref[x] = maxPrefW; } } //--------------------------------------------------------------------------- private void calcMaxHeightArray() { //--- maximun preferred Height calculus for each row --- FlexCell cell; int maxPrefH, curPrefH; for(int y=0; y<height; y++) { maxPrefH = 0; for(int x=0; x<width; x++) { cell = cells[x][y]; if (cell != null && cell.yext == 1) { curPrefH = cell.ruponent.getPreferredSize().height; if (curPrefH > maxPrefH) maxPrefH = curPrefH; } } if (maxPrefH == 0) maxPrefH = ynullgap; ypref[y] = maxPrefH; } }
} class FlexCell {
//--- X align constants --- public static final int LEFT = 0; public static final int CENTERX = 1; public static final int RIGHT = 2; public static final int EXPANDX = 3; //--- Y align constants --- public static final int TOP = 0; public static final int CENTERY = 1; public static final int BOTTOM = 2; public static final int EXPANDY = 3; public int xalign, xext; public int yalign, yext; public Component component; //--------------------------------------------------------------------------- public FlexCell(int xalign, int yalign, int xext, int yext, Component c) { this.xalign = xalign; this.yalign = yalign; this.xext = xext; this.yext = yext; component = c; }
}
</source>
GraphPaperLayout
<source lang="java">
/* From http://java.sun.ru/docs/books/tutorial/index.html */ /*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */
import java.awt.BorderLayout; import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.LayoutManager2; import java.awt.Rectangle; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Hashtable; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class GraphPaperTest extends JPanel {
public GraphPaperTest() { setLayout(new GraphPaperLayout(new Dimension(5, 5))); // Add a 1x1 Rect at (0,0) add(new JButton("1"), new Rectangle(0, 0, 1, 1)); // Add a 2x1 Rect at (2,0) add(new JButton("2"), new Rectangle(2, 0, 2, 1)); // Add a 1x2 Rect at (1,1) add(new JButton("3"), new Rectangle(1, 1, 1, 2)); // Add a 2x2 Rect at (3,2) add(new JButton("4"), new Rectangle(3, 2, 2, 2)); // Add a 1x1 Rect at (0,4) add(new JButton("5"), new Rectangle(0, 4, 1, 1)); // Add a 1x2 Rect at (2,3) add(new JButton("6"), new Rectangle(2, 3, 1, 2)); } public static void main(String[] args) { JFrame f = new JFrame("GraphPaperTest"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.getContentPane().add(new GraphPaperTest(), BorderLayout.CENTER); f.pack(); f.setVisible(true); }
} /**
* The GraphPaperLayout
class is a layout manager that lays out a
* container"s components in a rectangular grid, similar to GridLayout. Unlike
* GridLayout, however, components can take up multiple rows and/or columns. The
* layout manager acts as a sheet of graph paper. When a component is added to
* the layout manager, the location and relative size of the component are
* simply supplied by the constraints as a Rectangle.
*
*
*
* import java.awt.*;
* import java.applet.Applet;
*
* public class ButtonGrid extends Applet {
* public void init() {
* setLayout(new GraphPaperLayout(new Dimension(5, 5)));
* // Add a 1x1 Rect at (0,0)
* add(new Button("1"), new Rectangle(0, 0, 1, 1));
* // Add a 2x1 Rect at (2,0)
* add(new Button("2"), new Rectangle(2, 0, 2, 1));
* // Add a 1x2 Rect at (1,1)
* add(new Button("3"), new Rectangle(1, 1, 1, 2));
* // Add a 2x2 Rect at (3,2)
* add(new Button("4"), new Rectangle(3, 2, 2, 2));
* // Add a 1x1 Rect at (0,4)
* add(new Button("5"), new Rectangle(0, 4, 1, 1));
* // Add a 1x2 Rect at (2,3)
* add(new Button("6"), new Rectangle(2, 3, 1, 2));
* }
* }
*
* * @author Michael Martak */
class GraphPaperLayout implements LayoutManager2 {
int hgap; //horizontal gap int vgap; //vertical gap Dimension gridSize; //grid size in logical units (n x m) Hashtable compTable; //constraints (Rectangles) /** * Creates a graph paper layout with a default of a 1 x 1 graph, with no * vertical or horizontal padding. */ public GraphPaperLayout() { this(new Dimension(1, 1)); } /** * Creates a graph paper layout with the given grid size, with no vertical * or horizontal padding. */ public GraphPaperLayout(Dimension gridSize) { this(gridSize, 0, 0); } /** * Creates a graph paper layout with the given grid size and padding. * * @param gridSize * size of the graph paper in logical units (n x m) * @param hgap * horizontal padding * @param vgap * vertical padding */ public GraphPaperLayout(Dimension gridSize, int hgap, int vgap) { if ((gridSize.width <= 0) || (gridSize.height <= 0)) { throw new IllegalArgumentException( "dimensions must be greater than zero"); } this.gridSize = new Dimension(gridSize); this.hgap = hgap; this.vgap = vgap; compTable = new Hashtable(); } /** * @return the size of the graph paper in logical units (n x m) */ public Dimension getGridSize() { return new Dimension(gridSize); } /** * Set the size of the graph paper in logical units (n x m) */ public void setGridSize(Dimension d) { setGridSize(d.width, d.height); } /** * Set the size of the graph paper in logical units (n x m) */ public void setGridSize(int width, int height) { gridSize = new Dimension(width, height); } public void setConstraints(Component comp, Rectangle constraints) { compTable.put(comp, new Rectangle(constraints)); } /** * Adds the specified component with the specified name to the layout. This * does nothing in GraphPaperLayout, since constraints are required. */ public void addLayoutComponent(String name, Component comp) { } /** * Removes the specified component from the layout. * * @param comp * the component to be removed */ public void removeLayoutComponent(Component comp) { compTable.remove(comp); } /** * Calculates the preferred size dimensions for the specified panel given * the components in the specified parent container. * * @param parent * the component to be laid out * * @see #minimumLayoutSize */ public Dimension preferredLayoutSize(Container parent) { return getLayoutSize(parent, true); } /** * Calculates the minimum size dimensions for the specified panel given the * components in the specified parent container. * * @param parent * the component to be laid out * @see #preferredLayoutSize */ public Dimension minimumLayoutSize(Container parent) { return getLayoutSize(parent, false); } /** * Algorithm for calculating layout size (minimum or preferred). * <p> * The width of a graph paper layout is the largest cell width (calculated * ingetLargestCellSize()
times the number of columns, plus * the horizontal padding times the number of columns plus one, plus the * left and right insets of the target container. * <p> * The height of a graph paper layout is the largest cell height (calculated * ingetLargestCellSize()
times the number of rows, plus the * vertical padding times the number of rows plus one, plus the top and * bottom insets of the target container. * * @param parent * the container in which to do the layout. * @param isPreferred * true for calculating preferred size, false for calculating * minimum size. * @return the dimensions to lay out the subcomponents of the specified * container. * @see java.awt.GraphPaperLayout#getLargestCellSize */ protected Dimension getLayoutSize(Container parent, boolean isPreferred) { Dimension largestSize = getLargestCellSize(parent, isPreferred); Insets insets = parent.getInsets(); largestSize.width = (largestSize.width * gridSize.width) + (hgap * (gridSize.width + 1)) + insets.left + insets.right; largestSize.height = (largestSize.height * gridSize.height) + (vgap * (gridSize.height + 1)) + insets.top + insets.bottom; return largestSize; } /** * Algorithm for calculating the largest minimum or preferred cell size. * <p> * Largest cell size is calculated by getting the applicable size of each * component and keeping the maximum value, dividing the component"s width * by the number of columns it is specified to occupy and dividing the * component"s height by the number of rows it is specified to occupy. * * @param parent * the container in which to do the layout. * @param isPreferred * true for calculating preferred size, false for calculating * minimum size. * @return the largest cell size required. */ protected Dimension getLargestCellSize(Container parent, boolean isPreferred) { int ncomponents = parent.getComponentCount(); Dimension maxCellSize = new Dimension(0, 0); for (int i = 0; i < ncomponents; i++) { Component c = parent.getComponent(i); Rectangle rect = (Rectangle) compTable.get(c); if (c != null && rect != null) { Dimension componentSize; if (isPreferred) { componentSize = c.getPreferredSize(); } else { componentSize = c.getMinimumSize(); } // Note: rect dimensions are already asserted to be > 0 when the // component is added with constraints maxCellSize.width = Math.max(maxCellSize.width, componentSize.width / rect.width); maxCellSize.height = Math.max(maxCellSize.height, componentSize.height / rect.height); } } return maxCellSize; } /** * Lays out the container in the specified container. * * @param parent * the component which needs to be laid out */ public void layoutContainer(Container parent) { synchronized (parent.getTreeLock()) { Insets insets = parent.getInsets(); int ncomponents = parent.getComponentCount(); if (ncomponents == 0) { return; } // Total parent dimensions Dimension size = parent.getSize(); int totalW = size.width - (insets.left + insets.right); int totalH = size.height - (insets.top + insets.bottom); // Cell dimensions, including padding int totalCellW = totalW / gridSize.width; int totalCellH = totalH / gridSize.height; // Cell dimensions, without padding int cellW = (totalW - ((gridSize.width + 1) * hgap)) / gridSize.width; int cellH = (totalH - ((gridSize.height + 1) * vgap)) / gridSize.height; for (int i = 0; i < ncomponents; i++) { Component c = parent.getComponent(i); Rectangle rect = (Rectangle) compTable.get(c); if (rect != null) { int x = insets.left + (totalCellW * rect.x) + hgap; int y = insets.top + (totalCellH * rect.y) + vgap; int w = (cellW * rect.width) - hgap; int h = (cellH * rect.height) - vgap; c.setBounds(x, y, w, h); } } } } // LayoutManager2 ///////////////////////////////////////////////////////// /** * Adds the specified component to the layout, using the specified * constraint object. * * @param comp * the component to be added * @param constraints * where/how the component is added to the layout. */ public void addLayoutComponent(Component comp, Object constraints) { if (constraints instanceof Rectangle) { Rectangle rect = (Rectangle) constraints; if (rect.width <= 0 || rect.height <= 0) { throw new IllegalArgumentException( "cannot add to layout: rectangle must have positive width and height"); } if (rect.x < 0 || rect.y < 0) { throw new IllegalArgumentException( "cannot add to layout: rectangle x and y must be >= 0"); } setConstraints(comp, rect); } else if (constraints != null) { throw new IllegalArgumentException( "cannot add to layout: constraint must be a Rectangle"); } } /** * Returns the maximum size of this component. * * @see java.awt.ruponent#getMinimumSize() * @see java.awt.ruponent#getPreferredSize() * @see LayoutManager */ public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } /** * Returns the alignment along the x axis. This specifies how the component * would like to be aligned relative to other components. The value should * be a number between 0 and 1 where 0 represents alignment along the * origin, 1 is aligned the furthest away from the origin, 0.5 is centered, * etc. */ public float getLayoutAlignmentX(Container target) { return 0.5f; } /** * Returns the alignment along the y axis. This specifies how the component * would like to be aligned relative to other components. The value should * be a number between 0 and 1 where 0 represents alignment along the * origin, 1 is aligned the furthest away from the origin, 0.5 is centered, * etc. */ public float getLayoutAlignmentY(Container target) { return 0.5f; } /** * Invalidates the layout, indicating that if the layout manager has cached * information it should be discarded. */ public void invalidateLayout(Container target) { // Do nothing }
}
</source>
Place components at exact locations (x, y, width, height) and then determine how they behave when the window containing them (their parent) is resized
<source lang="java">
import java.awt.*; import java.util.*; /*
* @(#)FunLayout.java 1.0 96/10/12 Eric Swildens Copyright (c) 1996 * * Permission to use, copy, modify, and distribute this software * for any purpose is hereby granted provided that this copyright * notice appears in all copies. * * NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF * THE SOFTWARE ARE GIVEN, EITHER EXPRESS OR IMPLIED, INCLUDING BUT * NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. */
public class FunLayout implements LayoutManager { // Using this layout manager, you can place components at exact // locations (x, y, width, height) and then determine how they // behave when the window containing them (their parent) is resized. // // sample use: // // fun1.html: // // <title>fun1 example</title> // <applet code="fun1.class" width=400 height=300> </applet> // // fun1.java: // // import java.applet.Applet; // import java.awt.*; // // public class fun1 extends Applet // { // public void init() // { // FunLayout layout = new FunLayout(); // setLayout(layout); // // setBackground(Color.lightGray); // // Button rightButton1 = new Button("Button1"); // rightButton1.reshape(300, 5, 90, 20); // add(rightButton1); // layout.movesRight(rightButton1); // // Button rightButton2 = new Button("Button 2"); // rightButton2.reshape(200, 5, 90, 20); // add(rightButton2); // layout.movesRight(rightButton2); // // Panel midPanel = new Panel(); // midPanel.reshape(5, 40, 390, 200); // midPanel.setBackground(Color.blue); // layout.widthChanges(midPanel); // layout.heightChanges(midPanel); // add(midPanel); // // Panel statusBar = new Panel(); // statusBar.reshape(5, 245, 390, 20); // statusBar.setBackground(Color.black); // layout.movesDown(statusBar); // layout.widthChanges(statusBar); // add(statusBar); // } // } // // The above code creates an applet containing 2 buttons, a center panel // and a status panel. The two buttons are placed next to each other // in the upper right. When the window is sized wider, the buttons // will move to the right to stick near the edge of the window. // // The midPanel is placed in the center and when the window is sized // larger (in both dimensions), the panel will grow wider and taller. // // The statusBar is placed on the bottom and sticks to the bottom of // the panel when it is sized larger or smaller in height (it moves // down if the window it is contained in is sized to a larger height). // It will grow wider if the window it is contained in is sized wider. // // The advantage of the FunLayout is that you place components where you // want them to appear (best when using an interface builder) and still // have control over what happens during sizing. // // This is the default layout mechanism many interface systems use, such // as Netscape"s IFC. In fact, if you use this layout manager, you will // find porting your code to Netscape"s IFC much easier, as the layout // container here is very similar to Netscape"s IFC layout mechanism. // // There are only 4 methods which determine how components are resized // // layout.movesRight(comp); // layout.movesDown(comp); // layout.widthChanges(comp); // layout.heightChanges(comp); // // When you determine which to choose, you should ask "What should the // component do when the window is sized larger?" // // If you don"t call any of the above methods for a component, it will // simply stay at its current location. // // It"s more Fun than a Bag of layouts :-) // private Hashtable _moves; private Hashtable _negSized; private Dimension _prevContainerSize; private final static int MOVES_RIGHT = 2; private final static int MOVES_DOWN = 4; private final static int HEIGHT_CHANGES = 8; private final static int WIDTH_CHANGES = 16; public FunLayout()
{ _moves = new Hashtable(); _negSized = new Hashtable(); }
private int _getMove(Component comp)
{ if (!_moves.containsKey(comp)) return 0; return ((Integer)_moves.get(comp)).intValue(); }
// // private methods // private void _setMove(Component comp, int move)
{ if (_moves.containsKey(comp)) { move |= ((Integer)_moves.get(comp)).intValue(); _moves.remove(comp); } _moves.put(comp, new Integer(move)); }
// // LayoutManager implementation // public void addLayoutComponent(String name, Component c)
{ }
/**
* When the window containing the given component is stretched to a * larger height, the given component will grow taller (and shorter * when the window is shortened). * @param comp the target Component */
public void heightChanges(Component comp)
{ if ((_getMove(comp) & MOVES_DOWN) > 0) System.out.println(getClass() + ":layout conflict for " + comp); _setMove(comp, HEIGHT_CHANGES); }
public void layoutContainer(Container con)
{ int i, count, deltax, deltay, move; Dimension conSize; Rectangle rect; Component comp; conSize = con.getSize(); if (_prevContainerSize == null) { _prevContainerSize = conSize; return; } deltax = conSize.width - _prevContainerSize.width; deltay = conSize.height - _prevContainerSize.height; _prevContainerSize = conSize; count = con.countComponents(); for (i = 0; i < count; i++) { comp = con.getComponent(i); if (!comp.isVisible()) continue; move = _getMove(comp); if (move == 0) continue; rect = comp.getBounds(); if (_negSized.containsKey(comp)) { // the component is really at a negative size rect = (Rectangle)_negSized.get(comp); _negSized.remove(comp); } if ((move & MOVES_RIGHT) > 0) rect.x += deltax; else if ((move & WIDTH_CHANGES) > 0) rect.width += deltax; if ((move & MOVES_DOWN) > 0) rect.y += deltay; else if ((move & HEIGHT_CHANGES) > 0) rect.height += deltay; // if a components size becomes negative, we track it since the AWT // does not allow components to have a size < (0, 0) if (rect.width < 0 || rect.height < 0) _negSized.put(comp, rect); comp.setBounds(rect.x, rect.y, rect.width, rect.height); } }
public Dimension minimumLayoutSize(Container target)
{ return new Dimension(10, 10); }
/**
* When the window containing the given component is stretched to a * larger height, the given component will move down (and up * when the window is shortened). * @param comp the target Component */
public void movesDown(Component comp)
{ if ((_getMove(comp) & HEIGHT_CHANGES) > 0) System.out.println(getClass() + ":layout conflict for " + comp); _setMove(comp, MOVES_DOWN); }
// // public methods // /**
* When the window containing the given component is widened, the * component will move right (and left when the window is shrunk). * @param comp the target Component */
public void movesRight(Component comp)
{ if ((_getMove(comp) & WIDTH_CHANGES) > 0) System.out.println(getClass() + ":layout conflict for " + comp); _setMove(comp, MOVES_RIGHT); }
public Dimension preferredLayoutSize(Container con)
{ Component comp; Rectangle rect; int i, count; Dimension d; d = new Dimension(0, 0); count = con.countComponents(); for (i = 0; i < count; i++) { comp = con.getComponent(i); if (!comp.isVisible()) continue; rect = comp.getBounds(); if (d.width < rect.x + rect.width) d.width = rect.x + rect.width; if (d.height < rect.y + rect.height) d.height = rect.y + rect.height; } return d; }
public void removeLayoutComponent(Component c)
{ if (_negSized.containsKey(c)) _negSized.remove(c); }
/**
* When the window containing the given component is widened, the * component will grow wider (and smaller when the window is shrunk). * @param comp the target Component */
public void widthChanges(Component comp)
{ if ((_getMove(comp) & MOVES_RIGHT) > 0) System.out.println(getClass() + ":layout conflict for " + comp); _setMove(comp, WIDTH_CHANGES); }
}
</source>
Relative Layout Manager for Java J2SE
<source lang="java">
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002. * All rights reserved. Software written by Ian F. Darwin and others. * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS"" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s, * pioneering role in inventing and promulgating (and standardizing) the Java * language and environment is gratefully acknowledged. * * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for * inventing predecessor languages C and C++ is also gratefully acknowledged. */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Point; import java.util.StringTokenizer; import java.util.Vector; /**
* <p> * RelativeLayout, a Relative Layout Manager for Java J2SE. Mainly for porting * tired old code that uses x,y locations. You really can"t just assign x,y * locations to components in Java Java J2SE - it breaks badly when the user * resizes (and you can not mandate that the user can"t resize you -- * see any book on UI design for that little discussion -- and can * also look bad due to resolution independance. Symantec Cafe 1.x, for example, * used to spit out unfortunate (and unmaintainable) code like this: **
* setLayout(null); * setSize(331, 241); * label1 = new Label("Info Applet", Label.CENTER); * add(label1); * label1.setBounds(91, 19, 107, 15); *
** *
* Bleaarrgghh!!! To make it work properly at all resolutions and * survive user-initiated resize actions, change it to * *
* * setLayout(new RelativeLayout(331,241,false); * label1=new Label("Info Applet", Label.CENTER); * add("91,19", label1); * *
* * Note that it"s actually less work to get it right. Symantec, * Microsoft, and others, please take note!*
* * @author Ian Darwin, http://www.darwinsys.ru/ */
public class RelativeLayout implements LayoutManager {
/** requested absolute width of canvas */ protected int reqWid; /** requested absolute height of canvas */ protected int reqHgt; /** actual size width when laid out */ protected int curWid; /** actual size height when laid out */ protected int curHgt; /** to track Components added by named add form. */ protected Vector curComps = new Vector(); /** * Constructs an RelativeLayout, given original hard-coded size of panel. */ public RelativeLayout(int wid, int ht) { this.reqWid = wid; this.reqHgt = ht; } /** * Called by AWT when the user uses the form add(name, Component). Adds the * specified component with the specified name to the layout. * * @param name * String with location for component c Note: the * "name" must contain x, y location, ie.,
* add("" + 320 + "," + 100, new Button("Quit"));
* or
* add("320,100", new Button("Quit").
* This adds the Button at x=320, y=100 when the Panel is at its * original full size. * @param c * Component to be added. */ public void addLayoutComponent(String name, Component c) { int x, y; StringTokenizer st = new StringTokenizer(name, ","); x = Integer.parseInt(st.nextToken()); y = Integer.parseInt(st.nextToken()); // System.out.println("Adding: Name " + name +"; obj " + c // + "; x " + x + "; y " + y); Tracker t = new Tracker(x, y, c); curComps.addElement(t); } /** * Called by AWT to lay out the components in the target Container at its * current size. * * @param target * Container whose components are to be laid out. */ public void layoutContainer(Container target) { Dimension targSize = target.getSize(); Insets ins = target.getInsets(); // System.out.println("layoutContainer: size " + targSize); curWid = targSize.width; curHgt = targSize.height; float widRatio = (float) curWid / (float) reqWid; float hgtRatio = (float) curHgt / (float) reqHgt; for (int i = 0; i < curComps.size(); i++) { int px, py, pw, ph; Tracker t = (Tracker) curComps.elementAt(i); Component tc = t.getComponent(); Dimension d = tc.getPreferredSize(); px = ins.right + (int) (t.getRequestedLoc().x * widRatio); py = ins.top + (int) (t.getRequestedLoc().y * hgtRatio); pw = d.width; ph = d.height; // System.out.println("layoutContainer["+i+"]: move " + // tc + " to " + px + ", " + py); tc.setBounds(px, py, pw, ph); } } /** * Called from AWT to calculate the minimum size dimensions for the target * panel given the components in it. But we use our own list of named * insertions, not the list of Components that the container keeps. * * @param target * Container to calculate for */ public Dimension minimumLayoutSize(Container target) { int minw = 0, minh = 0; for (int i = 0; i < curComps.size(); i++) { Tracker t = (Tracker) curComps.elementAt(i); Component tc = t.getComponent(); Dimension d = tc.getMinimumSize(); Point rl = t.getRequestedLoc(); minw = Math.max(minw, rl.x + d.width); minh = Math.max(minh, rl.y + d.height); // System.out.println("minLay, minw = " + minw // + "; minh = " + minh); } return new Dimension(minw, minw); } /** * Called by AWT to compute the preferred size for the target panel given * our list of the components that it contains. * * @param target * Container to calculate for */ public Dimension preferredLayoutSize(Container target) { int prefw = 0, prefh = 0; for (int i = 0; i < curComps.size(); i++) { Tracker t = (Tracker) curComps.elementAt(i); Component tc = t.getComponent(); Dimension d = tc.getMinimumSize(); Point rl = t.getRequestedLoc(); prefw = Math.max(prefw, rl.x + d.width); prefh = Math.max(prefh, rl.y + d.height); // System.out.println("prefLay, prefw = " + // prefw + "; prefh = " + prefh); } return new Dimension(prefw, prefh); } /** * Called by AWT to remove a given component from the layout. * * @param c * Component to be removed */ public void removeLayoutComponent(Component c) { curComps.removeElement(c); } /** * Tracker is a class used only by RelativeLayout, to track the original * "requested" (hard-coded) x,y locations of each Component. */ class Tracker { int absx, absy; Component theComp; /** Construct a tracker item given its location and Component. */ Tracker(int x, int y, Component c) { this.absx = x; this.absy = y; this.theComp = c; } /** Extract the location as a Point. */ public Point getRequestedLoc() { return new Point(absx, absy); } /** Extract the Component from this Tracker. */ public Component getComponent() { return theComp; } }
}
</source>
Specialised layout manager for a grid of components.
<source lang="java">
/*
* JCommon : a free general purpose class library for the Java(tm) platform * * * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jcommon/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * -------------- * LCBLayout.java * -------------- * (C) Copyright 2000-2005, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * * $Id: LCBLayout.java,v 1.5 2005/11/16 15:58:40 taqua Exp $ * * Changes (from 26-Oct-2001) * -------------------------- * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG); * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG); */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.io.Serializable; /**
* Specialised layout manager for a grid of components. * * @author David Gilbert */
public class LCBLayout implements LayoutManager, Serializable {
/** For serialization. */ private static final long serialVersionUID = -2531780832406163833L; /** A constant for the number of columns in the layout. */ private static final int COLUMNS = 3; /** Tracks the column widths. */ private int[] colWidth; /** Tracks the row heights. */ private int[] rowHeight; /** The gap between each label and component. */ private int labelGap; /** The gap between each component and button. */ private int buttonGap; /** The gap between rows. */ private int vGap; /** * Creates a new LCBLayout with the specified maximum number of rows. * * @param maxrows the maximum number of rows. */ public LCBLayout(final int maxrows) { this.labelGap = 10; this.buttonGap = 6; this.vGap = 2; this.colWidth = new int[COLUMNS]; this.rowHeight = new int[maxrows]; } /** * Returns the preferred size using this layout manager. * * @param parent the parent. * * @return the preferred size using this layout manager. */ public Dimension preferredLayoutSize(final Container parent) { synchronized (parent.getTreeLock()) { final Insets insets = parent.getInsets(); final int ncomponents = parent.getComponentCount(); final int nrows = ncomponents / COLUMNS; for (int c = 0; c < COLUMNS; c++) { for (int r = 0; r < nrows; r++) { final Component component = parent.getComponent(r * COLUMNS + c); final Dimension d = component.getPreferredSize(); if (this.colWidth[c] < d.width) { this.colWidth[c] = d.width; } if (this.rowHeight[r] < d.height) { this.rowHeight[r] = d.height; } } } int totalHeight = this.vGap * (nrows - 1); for (int r = 0; r < nrows; r++) { totalHeight = totalHeight + this.rowHeight[r]; } final int totalWidth = this.colWidth[0] + this.labelGap + this.colWidth[1] + this.buttonGap + this.colWidth[2]; return new Dimension( insets.left + insets.right + totalWidth + this.labelGap + this.buttonGap, insets.top + insets.bottom + totalHeight + this.vGap ); } } /** * Returns the minimum size using this layout manager. * * @param parent the parent. * * @return the minimum size using this layout manager. */ public Dimension minimumLayoutSize(final Container parent) { synchronized (parent.getTreeLock()) { final Insets insets = parent.getInsets(); final int ncomponents = parent.getComponentCount(); final int nrows = ncomponents / COLUMNS; for (int c = 0; c < COLUMNS; c++) { for (int r = 0; r < nrows; r++) { final Component component = parent.getComponent(r * COLUMNS + c); final Dimension d = component.getMinimumSize(); if (this.colWidth[c] < d.width) { this.colWidth[c] = d.width; } if (this.rowHeight[r] < d.height) { this.rowHeight[r] = d.height; } } } int totalHeight = this.vGap * (nrows - 1); for (int r = 0; r < nrows; r++) { totalHeight = totalHeight + this.rowHeight[r]; } final int totalWidth = this.colWidth[0] + this.labelGap + this.colWidth[1] + this.buttonGap + this.colWidth[2]; return new Dimension( insets.left + insets.right + totalWidth + this.labelGap + this.buttonGap, insets.top + insets.bottom + totalHeight + this.vGap ); } } /** * Lays out the components. * * @param parent the parent. */ public void layoutContainer(final Container parent) { synchronized (parent.getTreeLock()) { final Insets insets = parent.getInsets(); final int ncomponents = parent.getComponentCount(); final int nrows = ncomponents / COLUMNS; for (int c = 0; c < COLUMNS; c++) { for (int r = 0; r < nrows; r++) { final Component component = parent.getComponent(r * COLUMNS + c); final Dimension d = component.getPreferredSize(); if (this.colWidth[c] < d.width) { this.colWidth[c] = d.width; } if (this.rowHeight[r] < d.height) { this.rowHeight[r] = d.height; } } } int totalHeight = this.vGap * (nrows - 1); for (int r = 0; r < nrows; r++) { totalHeight = totalHeight + this.rowHeight[r]; } final int totalWidth = this.colWidth[0] + this.colWidth[1] + this.colWidth[2]; // adjust the width of the second column to use up all of parent final int available = parent.getWidth() - insets.left - insets.right - this.labelGap - this.buttonGap; this.colWidth[1] = this.colWidth[1] + (available - totalWidth); // *** DO THE LAYOUT *** int x = insets.left; for (int c = 0; c < COLUMNS; c++) { int y = insets.top; for (int r = 0; r < nrows; r++) { final int i = r * COLUMNS + c; if (i < ncomponents) { final Component component = parent.getComponent(i); final Dimension d = component.getPreferredSize(); final int h = d.height; final int adjust = (this.rowHeight[r] - h) / 2; parent.getComponent(i).setBounds(x, y + adjust, this.colWidth[c], h); } y = y + this.rowHeight[r] + this.vGap; } x = x + this.colWidth[c]; if (c == 0) { x = x + this.labelGap; } if (c == 1) { x = x + this.buttonGap; } } } } /** * Not used. * * @param comp the component. */ public void addLayoutComponent(final Component comp) { // not used } /** * Not used. * * @param comp the component. */ public void removeLayoutComponent(final Component comp) { // not used } /** * Not used. * * @param name the component name. * @param comp the component. */ public void addLayoutComponent(final String name, final Component comp) { // not used } /** * Not used. * * @param name the component name. * @param comp the component. */ public void removeLayoutComponent(final String name, final Component comp) { // not used }
}
</source>
Special simple layout used in TabbedContainer
<source lang="java">
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common * Development and Distribution License("CDDL") (collectively, the * "License"). You may not use this file except in compliance with the * License. You can obtain a copy of the License at * http://www.netbeans.org/cddl-gplv2.html * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the * specific language governing permissions and limitations under the * License. When distributing the software, include this License Header * Notice in each file and include the License file at * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the * License Header, with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * Contributor(s): * * The Original Software is NetBeans. The Initial Developer of the Original * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun * Microsystems, Inc. All Rights Reserved. * * If you wish your version of this file to be governed by only the CDDL * or only the GPL Version 2, indicate your decision by adding * "[Contributor] elects to include this software in this distribution * under the [CDDL or GPL Version 2] license." If you do not indicate a * single choice of license, a recipient has the option to distribute * your version of this file under either the CDDL, the GPL Version 2 or * to extend the choice of license to its licensees as provided above. * However, if you add GPL Version 2 code and therefore, elected the GPL * Version 2 license, then the option applies only if the new code is * made subject to such option by the copyright holder. */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import java.lang.ref.WeakReference; import javax.swing.JComponent; /**
* Special simple layout used in TabbedContainer. Shows component in the * "stack", it means that only one component is visible at any time, others are * always hidden "below" the visible one. Use method showComponent to select * visible component. * * @author Dafe Simonek */
class StackLayout implements LayoutManager {
// #100486 - hold visibleComp weakly, because removeLayoutComponent may not // be called and then visibleComp is not freed. See StackLayoutTest for details. /** * Holds currently visible component or null if no comp is visible */ private WeakReference<Component> visibleComp = null; /** * Set the currently displayed component. If passed null for the component, * all contained components will be made invisible (sliding windows do this) * @param c Component to show * @param parent Parent container */ public void showComponent(Component c, Container parent) { Component comp = getVisibleComponent(); if (comp != c) { if (!parent.isAncestorOf(c) && c != null) { parent.add(c); } synchronized (parent.getTreeLock()) { if (comp != null) { comp.setVisible(false); } visibleComp = new WeakReference<Component>(c); if (c != null) { c.setVisible(true); } // trigger re-layout if (c instanceof JComponent) { ((JComponent)c).revalidate(); } else { parent.validate(); //XXX revalidate should work! } } } } /** Allows support for content policies * @return Currently visible component or null */ public Component getVisibleComponent() { return visibleComp == null ? null : visibleComp.get(); } /** * ********** Implementation of LayoutManager interface ********* */ public void addLayoutComponent(String name, Component comp) { synchronized (comp.getTreeLock()) { comp.setVisible(false); // keep consistency if showComponent was already called on this // component before if (comp == getVisibleComponent()) { visibleComp = null; }
/*System.out.println("Border dump for " + comp.getName()); borderDump((javax.swing.JComponent)comp, "");*/
} }
/*private void borderDump (javax.swing.JComponent comp, String space) {
javax.swing.border.Border compBorder = comp.getBorder(); if (compBorder == null) { System.out.println(space + comp.getClass().getName() + " has no border."); } else { System.out.println(space + comp.getClass().getName() + ": " + compBorder.getClass().getName()); } Component curComp; for (int i = 0; i < comp.getComponentCount(); i++) { curComp = comp.getComponent(i); if (curComp instanceof javax.swing.JComponent) { borderDump((javax.swing.JComponent)curComp, space + " "); } }
}*/
public void removeLayoutComponent(Component comp) { synchronized (comp.getTreeLock()) { if (comp == getVisibleComponent()) { visibleComp = null; } // kick out removed component as visible, so that others // don"t have problems with hidden components comp.setVisible(true); } } public void layoutContainer(Container parent) { Component visibleComp = getVisibleComponent(); if (visibleComp != null) { synchronized (parent.getTreeLock()) { Insets insets = parent.getInsets(); visibleComp.setBounds(insets.left, insets.top, parent.getWidth() - (insets.left + insets.right), parent.getHeight() - (insets.top + insets.bottom)); } } } public Dimension minimumLayoutSize(Container parent) { return getEmptySize(); } public Dimension preferredLayoutSize(Container parent) { return getEmptySize(); } /** * Specifies default size of empty container */ private static Dimension getEmptySize() { return new Dimension(50, 50); }
}
</source>
Square Layout
<source lang="java">
/**
* The utillib library. * More information is available at http://www.jinchess.ru/. * Copyright (C) 2002 Alexander Maryanovsky. * All rights reserved. * * The utillib library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The utillib library 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 Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with utillib library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
import java.awt.*;
/**
* A LayoutManager which lays out a single component making sure its height is * always the same as its width. If the parent container"s width differs from * it height, the child will be laid out according to its x and y alignment. */
public class SquareLayout implements LayoutManager{
/** * Creates a new SquareLayout. */ public SquareLayout(){ } /** * Creates a new Container with SquareLayout which will contain the specified * component. */ public static Container createSquareContainer(Component child){ Container container = new Container(); container.setLayout(new SquareLayout()); container.add(child); return container; }
/** * Adds the specified component with the specified name to the layout. */ public void addLayoutComponent(String name, Component component){ } /** * Removes the specified component from the layout. */ public void removeLayoutComponent(Component component){ } /** * Returns the sole child of the specified container, ornull
if * none. Throws anIllegalStateException
if there is more than * one child. */ private Component getChild(Container c){ int childCount = c.getComponentCount(); if (childCount > 1) throw new IllegalStateException("May not layout more than one component"); else if (childCount == 0) return null; else return c.getComponent(childCount - 1); }
/** * Lays out the container in the specified panel. */ public void layoutContainer(Container container){ Component child = getChild(container); if (child == null) return; Dimension parentSize = container.getSize(); Insets insets = container.getInsets(); // A rectangle specifying the actual area available for layout. Rectangle rect = new Rectangle(insets.left, insets.top, parentSize.width - insets.left - insets.right, parentSize.height - insets.top - insets.bottom); int minSize = rect.width < rect.height ? rect.width : rect.height; int widthSpace = rect.width - minSize; int heightSpace = rect.height - minSize; child.setBounds(rect.x + (int)(widthSpace*child.getAlignmentX()), rect.y + (int)(heightSpace*child.getAlignmentY()), minSize, minSize); } /** * Calculates the minimum size dimensions for the specified panel given the * components in the specified parent container. */ public Dimension minimumLayoutSize(Container container){ Component child = getChild(container); if (child == null) return new Dimension(0, 0); Dimension childMinSize = child.getMinimumSize(); Insets insets = container.getInsets(); int width = childMinSize.width + insets.left + insets.right; int height = childMinSize.height + insets.top + insets.bottom; int maxSize = Math.max(width, height); return new Dimension(maxSize, maxSize); }
/** * Calculates the preferred size dimensions for the specified panel given the * components in the specified parent container. */ public Dimension preferredLayoutSize(Container container){ Component child = getChild(container); if (child == null) return new Dimension(0, 0); Dimension childPrefSize = child.getPreferredSize(); Insets insets = container.getInsets(); int width = childPrefSize.width + insets.left + insets.right; int height = childPrefSize.height + insets.top + insets.bottom; int maxSize = Math.max(width, height); return new Dimension(maxSize, maxSize); }
}
</source>
Stack Layout, uses an orientation to determine if the contents should be arranged horizontally or vertically.
<source lang="java">
/*
* StackLayout.java * 2005-07-15 */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; import javax.swing.JSeparator; import javax.swing.JToolBar; import javax.swing.SwingConstants;
/**
* Similar to BoxLayout, uses an orientation to determine if the contents * should be arranged horizontally or vertically. By default, Resizes each * item to equal width or height (depending on the orientation) based on the * maximum preferred width or height of all items. * @author Christopher Bach */
public class StackLayout implements LayoutManager {
public static final int HORIZONTAL = SwingConstants.HORIZONTAL; public static final int VERTICAL = SwingConstants.VERTICAL; private int ourOrientation = HORIZONTAL; private int ourSpacing = 0; private boolean ourDepthsMatched = true; private boolean ourLengthsMatched = false; private boolean ourFill = false; private boolean ourDrop = false; private int ourSqueezeFactor = 100;
/** * Creates a new StackLayout with a horizontal orientation. */ public StackLayout() { }
/** * Creates a new StackLayout with the specified orientation. */ public StackLayout(int orientation) { setOrientation(orientation); }
/** * Creates a new StackLayout with the specified orientation and spacing. */ public StackLayout(int orientation, int spacing) { setOrientation(orientation); setSpacing(spacing); }
/** * Creates a new StackLayout matching the component lengths and * depths as indicated. */ public StackLayout(boolean matchLengths, boolean matchDepths) { setMatchesComponentLengths(matchLengths); setMatchesComponentDepths(matchDepths); }
/** * Creates a new StackLayout with the specified orientation * and spacing, matching the component lengths and depths * as indicated. */ public StackLayout(int orientation, int spacing, boolean matchLengths, boolean matchDepths) { setOrientation(orientation); setSpacing(spacing); setMatchesComponentLengths(matchLengths); setMatchesComponentDepths(matchDepths); }
/** * Sets this StackLayout"s orientation, either * SwingConstants.HORIZONTAL or SwingConstants.VERTICAL. */ public void setOrientation(int orientation) { if (orientation == HORIZONTAL || orientation == VERTICAL) { ourOrientation = orientation; } }
/** * Returns this StackLayout"s orientation, either * SwingConstants.HORIZONTAL or SwingConstants.VERTICAL. */ public int getOrientation() { return ourOrientation; }
/** * Sets the spacing between components that this StackLayout uses * when laying out the components. */ public void setSpacing(int spacing) { ourSpacing = Math.max(0, spacing); }
/** * Returns the spacing between components that this StackLayout uses * when laying out the components. */ public int getSpacing() { return ourSpacing; }
/** * Sets whether or not the last component in the stack * should be stretched to fill any remaining space within * the parent container. The default value is false. */ public void setFillsTrailingSpace(boolean shouldFill) { ourFill = shouldFill; }
/** * Returns whether or not the last component in the stack * should be stretched to fill any remaining space within * the parent container. */ public boolean fillsTrailingSpace() { return ourFill; }
/** * Sets whether or not components in the stack that do not * fit in the parent container should be left out of the layout. * The default value is false; */ public void setDropsPartialComponents(boolean shouldDrop) { ourDrop = shouldDrop; }
/** * Returns whether or not components in the stack that do not * fit in the parent container should be left out of the layout. */ public boolean dropsPartialComponents() { return ourDrop; }
/** * Sets whether or not all components in the stack will be sized * to the same height (when in a horizontal orientation) or width * (when in a vertical orientation). The default value is true. */ public void setMatchesComponentDepths(boolean match) { ourDepthsMatched = match; }
/** * Returns whether or not all components in the stack will be sized * to the same height (when in a horizontal orientation) or width * (when in a vertical orientation). */ public boolean matchesComponentDepths() { return ourDepthsMatched; }
/** * Sets whether or not all components in the stack will be sized * to the same width (when in a horizontal orientation) or height * (when in a vertical orientation). The default value is false. */ public void setMatchesComponentLengths(boolean match) { ourLengthsMatched = match; }
/** * Returns whether or not all components in the stack will be sized * to the same width (when in a horizontal orientation) or height * (when in a vertical orientation). */ public boolean matchesComponentLengths() { return ourLengthsMatched; }
/** * Sets the percentage of a component"s preferred size that it * may be squeezed in order to attempt to fit all components * into the layout. The squeeze factor will only be applied * when this layout is set to match component lengths. * * For example, if the parent container is 100 pixels wide * and holds two buttons, the largest having a preferred * width of 80 pixels, a squeeze factor of 50 will allow each * button to be sized to as small as 40 pixels wide (50 percent * of the preferred width. * * The default value is 100. */ public void setSqueezeFactor(int factor) { if (factor < 0) ourSqueezeFactor = 0; else if (factor > 100) ourSqueezeFactor = 100; else ourSqueezeFactor = factor; }
/** * Returns the percentage of a component"s preferred size that it * may be squeezed in order to attempt to fit all components * into the layout. */ public int getSqueezeFactor() { return ourSqueezeFactor; }
////// LayoutManager implementation //////
/** * Adds the specified component with the specified name to this layout. */ public void addLayoutComponent(String name, Component comp) { }
/** * Removes the specified component from this layout. */ public void removeLayoutComponent(Component comp) { }
/** * Returns the preferred size for this layout to arrange the * indicated parent"s children. */ public Dimension preferredLayoutSize(Container parent) { if (parent instanceof JToolBar) { setOrientation( ((JToolBar)parent).getOrientation() ); } return preferredLayoutSize(parent, ourOrientation); }
/** * Returns the preferred size for this layout to arrange the * indicated parent"s children at the specified orientation. */ // public, because it"s useful - not one of the LayoutManager methods public Dimension preferredLayoutSize(Container parent, int orientation) { synchronized (parent.getTreeLock()) { Component[] comps = parent.getComponents(); Dimension total = new Dimension(0, 0); int depth = calculatePreferredDepth(comps, orientation); int length = ( ourLengthsMatched ? calculateAdjustedLength(comps, orientation, ourSpacing) : calculatePreferredLength(comps, orientation, ourSpacing) );
total.width = (orientation == HORIZONTAL ? length : depth); total.height = (orientation == HORIZONTAL ? depth : length);
Insets in = parent.getInsets(); total.width += in.left + in.right; total.height += in.top + in.bottom; return total; } }
/** * Returns the minimum size for this layout to arrange the * indicated parent"s children at the specified orientation. */ public Dimension minimumLayoutSize(Container parent) { synchronized (parent.getTreeLock()) { if (parent instanceof JToolBar) { setOrientation( ((JToolBar)parent).getOrientation() ); } Component[] comps = parent.getComponents(); Dimension total = new Dimension(0, 0); int depth = calculatePreferredDepth(comps, ourOrientation); int length = calculateMinimumLength(comps, ourOrientation, ourSpacing); total.width = (ourOrientation == HORIZONTAL ? length : depth); total.height = (ourOrientation == HORIZONTAL ? depth : length); Insets in = parent.getInsets(); total.width += in.left + in.right; total.height += in.top + in.bottom; return total; } }
/** * Lays out the child components within the indicated parent container. */ public void layoutContainer(Container parent) { synchronized (parent.getTreeLock()) { if (parent instanceof JToolBar) { setOrientation( ((JToolBar)parent).getOrientation() ); } layoutComponents(parent); } }
private void layoutComponents(Container parent) { Component[] components = parent.getComponents(); Insets in = parent.getInsets(); int maxHeight = parent.getHeight() - in.top - in.bottom; int maxWidth = parent.getWidth() - in.left - in.right; boolean horiz = (ourOrientation == HORIZONTAL);
int totalDepth = calculatePreferredDepth(components, ourOrientation); totalDepth = Math.max( totalDepth, (horiz ? maxHeight : maxWidth) ); int prefLength = ( ourLengthsMatched ? calculateAdjustedLength(components, ourOrientation, ourSpacing) : calculatePreferredLength(components, ourOrientation, ourSpacing) ); int totalLength = Math.min( prefLength, (horiz ? maxWidth : maxHeight) ); int a = (horiz ? in.left : in.top); int b = (horiz ? in.top : in.left); int l = 0, d = 0, sum = 0; int matchedLength = 0; Dimension prefsize = null; if (ourLengthsMatched) { matchedLength = ( horiz ? getMaxPrefWidth(components) : getMaxPrefHeight(components) ); if (prefLength > totalLength && ourSqueezeFactor < 100) { int minLength = calculateMinimumLength(components, ourOrientation, ourSpacing); if (minLength >= totalLength) { matchedLength = (matchedLength * ourSqueezeFactor) / 100; } else { int numSeparators = countSeparators(components); int numComponents = components.length - numSeparators; int diff = (prefLength - totalLength) / numComponents; if ((prefLength - totalLength) % numComponents > 0) diff++; matchedLength -= diff; } } }
for (int i=0; i < components.length; i++) { prefsize = components[i].getPreferredSize(); if (!ourLengthsMatched) l = (horiz ? prefsize.width : prefsize.height); else l = matchedLength; if (components[i] instanceof JSeparator) { // l = Math.min(prefsize.width, prefsize.height); l = (horiz ? prefsize.width : prefsize.height); d = totalDepth; sum += l; if (ourDrop && sum > totalLength) l = 0; } else { sum += l; if (ourDrop && sum > totalLength) l = 0; else if (ourFill && !ourLengthsMatched && i == components.length - 1) { l = Math.max( l, (horiz ? maxWidth : maxHeight) ); } if (ourDepthsMatched) d = totalDepth; else d = (horiz ? prefsize.height : prefsize.width); }
if (horiz) components[i].setBounds(a, b + (totalDepth - d) / 2, l, d); else components[i].setBounds(b + (totalDepth - d) / 2, a, d, l); a += l + ourSpacing; sum += ourSpacing; } }
/** * Returns the largest preferred width of the provided components. */ private int getMaxPrefWidth(Component[] components) { int maxWidth = 0; int componentWidth = 0; Dimension d = null; for (int i=0; i < components.length; i++) { d = components[i].getPreferredSize(); componentWidth = d.width; if (components[i] instanceof JSeparator) { componentWidth = Math.min(d.width, d.height); } maxWidth = Math.max(maxWidth, componentWidth); } return maxWidth; }
/** * Returns the largest preferred height of the provided components. */ private int getMaxPrefHeight(Component[] components) { int maxHeight = 0; int componentHeight = 0; Dimension d = null; for (int i=0; i < components.length; i++) { d = components[i].getPreferredSize(); componentHeight = d.height; if (components[i] instanceof JSeparator) { componentHeight = Math.min(d.width, d.height); } else maxHeight = Math.max(maxHeight, componentHeight); } return maxHeight; }
/** * Calculates the preferred "length" of this layout for the provided * components based on the largest component preferred size. */ private int calculateAdjustedLength(Component[] components, int orientation, int spacing) { int total = 0; int componentLength = ( orientation == HORIZONTAL ? getMaxPrefWidth(components) : getMaxPrefHeight(components) );
for (int i=0; i < components.length; i++) { if (components[i] instanceof JSeparator) { Dimension d = components[i].getPreferredSize(); // total += Math.min(d.width, d.height); total += (orientation == HORIZONTAL ? d.width : d.height); } else total += componentLength; }
int gaps = Math.max(0, spacing * (components.length - 1)); total += gaps;
return total; }
/** * Calculates the minimum "length" of this layout for the provided * components, taking the squeeze factor into account when necessary. */ private int calculateMinimumLength(Component[] components, int orientation, int spacing) { if (!ourLengthsMatched) return calculatePreferredLength( components, orientation, spacing ); if (ourSqueezeFactor == 100) return calculateAdjustedLength( components, orientation, spacing); int total = 0; int componentLength = ( orientation == HORIZONTAL ? getMaxPrefWidth(components) : getMaxPrefHeight(components) ); componentLength = (componentLength * ourSqueezeFactor) / 100;
for (int i=0; i < components.length; i++) { if (components[i] instanceof JSeparator) { Dimension d = components[i].getPreferredSize(); // total += Math.min(d.width, d.height); total += (orientation == HORIZONTAL ? d.width : d.height); } else total += componentLength; }
int gaps = Math.max(0, spacing * (components.length - 1)); total += gaps;
return total; }
/** * Calculates the preferred "length" of this layout for the provided * components. */ private int calculatePreferredLength(Component[] components, int orientation, int spacing) { int total = 0; Dimension d = null;
for (int i=0; i < components.length; i++) { d = components[i].getPreferredSize();
// if (components[i] instanceof JSeparator) // { // total += Math.min(d.width, d.height); // } // // else
total += (orientation == HORIZONTAL ? d.width : d.height); }
int gaps = Math.max(0, spacing * (components.length - 1)); total += gaps;
return total; }
/** * Returns the preferred "depth" of this layout for the provided * components. */ private int calculatePreferredDepth(Component[] components, int orientation) { if (orientation == HORIZONTAL) return getMaxPrefHeight(components); else if (orientation == VERTICAL) return getMaxPrefWidth(components); else return 0; }
private int countSeparators(Component[] components) { int count = 0; for (int i=0; i < components.length; i++) { if (components[i] instanceof JSeparator) count++; } return count; }
}
</source>
Table Layout
<source lang="java">
/**
* The utillib library. * More information is available at http://www.jinchess.ru/. * Copyright (C) 2002, 2003 Alexander Maryanovsky. * All rights reserved. * * The utillib library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The utillib library 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 Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with utillib library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager2; import java.util.Enumeration; import java.util.Hashtable; import java.util.NoSuchElementException; import java.util.Vector;
/**
* A LayoutManager which lays out the components in a table-like structure.
* Unlike GridLayout
, the sizes of the rows and columns
* are dynamic, although properly aligned. The cell sizes are determined
* according to the preferred sizes of the components and each component is
* sized to either its maximum size or the cell size. Components are positioned
* within their cells according to their X and Y alignments.
* When a new component is added, it is placed in the first empty cell, in
* lexigraphic order. A new row is created if necessary.
* To create an empty cell, simply add blank component.
*/
public class TableLayout implements LayoutManager2{
/** * The amount of columns in the table. */ private final int columnCount;
/** * The gap between columns, in pixels. */ private final int xGap;
/** * The gap between rows, in pixels. */ private final int yGap;
/** * A Vector of rows where each row is a Component array holding the components * in that row. */ private final Vector rows = new Vector();
/** * Creates a new TableLayout with the specified amount of columns, * horizontal/vertical gaps between columns/cells. */ public TableLayout(int columnCount, int xGap, int yGap){ if (columnCount <= 0) throw new IllegalArgumentException("The amount of columns must be positive"); if (xGap < 0) throw new IllegalArgumentException("The horizontal gap may not be negative: "+xGap); if (yGap < 0) throw new IllegalArgumentException("The vertical gap may not be negative: "+yGap); this.columnCount = columnCount; this.xGap = xGap; this.yGap = yGap; }
/** * Creates a new TableLayout with the specified amount of columns. */ public TableLayout(int columnCount){ this(columnCount, 0, 0); }
/** * Adds the specified component to the layout. */ public void addLayoutComponent(Component component, Object constraints){ synchronized(component.getTreeLock()){ int rowCount = rows.size(); for (int i = 0; i < rowCount; i++){ Component [] row = (Component [])rows.elementAt(i); for (int j = 0; j < row.length; j++){ if (row[j] == null){ row[j] = component; return; } } } Component [] newRow = new Component[columnCount]; newRow[0] = component; rows.addElement(newRow); } }
/** * Throws an exception. */ public void addLayoutComponent(String name, Component component){ throw new UnsupportedOperationException("deprecated addLayoutComponent(String, Component)"); }
/** * Removes the specified component from the layout. */ public void removeLayoutComponent(Component component){ synchronized(component.getTreeLock()){ int rowCount = rows.size(); outer: for (int i = 0; i < rowCount; i++){ Component [] row = (Component [])rows.elementAt(i); for (int j = 0; j < row.length; j++){ if (row[j] == component){ row[j] = null; break outer; } } } // Remove any empty rows at the end. for (int i = rowCount - 1; i >= 0; i--){ Component [] row = (Component [])rows.elementAt(i); boolean isEmpty = true; for (int j = 0; j < row.length; j++){ if (row[j] != null){ isEmpty = false; break; } } if (isEmpty) rows.removeElementAt(i); else break; } } }
/** * Returns a matrix of Dimension objects specifying the preferred sizes of the * components we are going to layout. */ private Dimension [][] getPreferredSizes(Container parent){ int rowCount = rows.size(); Dimension [][] prefSizes = new Dimension[rowCount][columnCount]; for (int i = 0; i < rowCount; i++){ Component [] row = (Component [])rows.elementAt(i); for (int j = 0; j < columnCount; j++){ Component component = row[j]; // Can only happen on the last line when all the remaining components are null as well if (component == null) break; if (component.getParent() != parent) throw new IllegalStateException("Bad parent specified"); prefSizes[i][j] = component.getPreferredSize(); } } return prefSizes; }
/** * Calculates and returns a Pair where the first object is an array holding * the column widths of our layout and the second is the rowHeights. */ private Pair calculateLayout(Dimension [][] prefSizes){ int rowCount = rows.size(); int [] columnWidths = new int[columnCount]; int [] rowHeights = new int[rowCount]; // Find the maximum preferred row heights and column widths. for (int i = 0; i < rowCount; i++){ for (int j = 0; j < columnCount; j++){ Dimension prefSize = prefSizes[i][j]; // Can only happen on the last line when all the remaining components are null as well if (prefSize == null) break; columnWidths[j] = Math.max(columnWidths[j], prefSize.width); rowHeights[i] = Math.max(rowHeights[i], prefSize.height); } } return new Pair(columnWidths, rowHeights); }
/** * Lays out the specified container. Throws an *IllegalStateException
if any of the components added via the *addLayoutComponent
method have a different parent than the * specified Container. */ public void layoutContainer(Container parent){ synchronized(parent.getTreeLock()){ int rowCount = rows.size(); Insets parentInsets = parent.getInsets(); // Collect the preferred sizes. Dimension [][] prefSizes = getPreferredSizes(parent); Pair layout = calculateLayout(prefSizes); int [] columnWidths = (int [])layout.getFirst(); int [] rowHeights = (int [])layout.getSecond(); Dimension prefParentSize = calculatePreferredLayoutSize(parent, columnWidths, rowHeights); Dimension parentSize = parent.getSize(); Dimension layoutSize = new Dimension(parentSize.width - xGap*(rowCount - 1) - parentInsets.left - parentInsets.right, parentSize.height - yGap*(columnCount - 1) - parentInsets.top - parentInsets.bottom); Dimension prefLayoutSize = new Dimension(prefParentSize.width - xGap*(rowCount - 1) - parentInsets.left - parentInsets.right, prefParentSize.height - yGap*(columnCount - 1) - parentInsets.top - parentInsets.bottom); // Layout the components. int y = parentInsets.top; for (int i = 0; i < rowCount; i++){ int x = parentInsets.left; int cellHeight = (rowHeights[i]*layoutSize.height)/prefLayoutSize.height; Component [] row = (Component [])rows.elementAt(i); for (int j = 0; j < row.length; j++){ int cellWidth = (columnWidths[j]*layoutSize.width)/prefLayoutSize.width; Component component = row[j]; // Can only happen on the last line when all the remaining components are null as well if (component == null) break; Dimension maxSize = component.getMaximumSize(); int compWidth = Math.min(maxSize.width, cellWidth); int compHeight = Math.min(maxSize.height, cellHeight); int compX = x + (int)((cellWidth - compWidth)*component.getAlignmentX()); int compY = y + (int)((cellHeight - compHeight)*component.getAlignmentY()); component.setBounds(compX, compY, compWidth, compHeight); x += cellWidth + xGap; } y += cellHeight + yGap; } } }
/** * We"re not caching anything yet, so this call is ignored. */ public void invalidateLayout(Container parent){ }
/** * Returns the preferred layout for the specified parent container. */ public Dimension preferredLayoutSize(Container parent){ synchronized(parent.getTreeLock()){ Dimension [][] prefSizes = getPreferredSizes(parent); Pair layout = calculateLayout(prefSizes); int [] columnWidths = (int [])layout.getFirst(); int [] rowHeights = (int [])layout.getSecond(); return calculatePreferredLayoutSize(parent, columnWidths, rowHeights); } }
/** * Calculates the preferred layout size for the specified preferred column * widths and row heights. */ private Dimension calculatePreferredLayoutSize(Container parent, int [] columnWidths, int [] rowHeights){ int prefWidth = 0; int prefHeight = 0; for (int i = 0; i < columnWidths.length; i++) prefWidth += columnWidths[i]; for (int i = 0; i < rowHeights.length; i++) prefHeight += rowHeights[i]; // Add the gaps prefWidth += xGap*(columnWidths.length - 1); prefHeight += yGap*(rowHeights.length - 1); // Add parent insets Insets parentInsets = parent.getInsets(); prefWidth += parentInsets.left + parentInsets.right; prefHeight += parentInsets.top + parentInsets.bottom; return new Dimension(prefWidth, prefHeight); }
/**
* Returns the same as preferredLayoutSize
.
*/
public Dimension minimumLayoutSize(Container parent){
return preferredLayoutSize(parent);
}
/** * Returns a dimension with maximum possible values. */ public Dimension maximumLayoutSize(Container parent){ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); }
/**
* Returns CENTER_ALIGNMENT
;
*/
public float getLayoutAlignmentX(Container parent) {
return Component.CENTER_ALIGNMENT;
}
/**
* Returns CENTER_ALIGNMENT
;
*/
public float getLayoutAlignmentY(Container parent) {
return Component.CENTER_ALIGNMENT;
}
} /**
* The utillib library. * More information is available at http://www.jinchess.ru/. * Copyright (C) 2002 Alexander Maryanovsky. * All rights reserved. * * The utillib library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The utillib library 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 Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with utillib library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/**
* A wrapper for any two other given objects. */ final class Pair{ /** * The first object. */ private final Object first;
/** * The second object. */ private final Object second;
/** * Creates a newPair
with the two given objects. Either of the * objects may benull
. */ public Pair(Object first, Object second){ this.first = first; this.second = second; }
/** * Returns the first object. */ public Object getFirst(){ return first; }
/** * Returns the second object. */ public Object getSecond(){ return second; }
/** * Returns a hashcode combined from the hashcodes of the two target objects. */ public int hashCode(){ int hash1 = (first == null ? 0 : first.hashCode()); int hash2 = (second == null ? 0 : second.hashCode()); return hash1^hash2; }
/**
* Returns true iff the given Object is a Pair, and its two objects are the
* same as this one"s (comparison done via Utilities.areEqual
)
*/
public boolean equals(Object o){
if (o == this)
return true;
if (!(o instanceof Pair))
return false;
Pair pair = (Pair)o;
return Utilities.areEqual(pair.first, first) && Utilities.areEqual(pair.second, second);
}
}
/** * The utillib library. * More information is available at http://www.jinchess.ru/. * Copyright (C) 2002, 2003 Alexander Maryanovsky. * All rights reserved. * * The utillib library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The utillib library 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 Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with utillib library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */
/** * A collection of general utility methods. */ class Utilities{ /** * A 0-length Object array. */ public static final Object [] EMPTY_ARRAY = new Object[0];
/** * A 0-length long array. */ public static final long [] EMPTY_LONG_ARRAY = new long[0];
/** * A 0-length int array. */ public static final int [] EMPTY_INT_ARRAY = new int[0]; /** * A 0-length short array. */ public static final short [] EMPTY_SHORT_ARRAY = new short[0]; /** * A 0-length byte array. */ public static final byte [] EMPTY_BYTE_ARRAY = new byte[0]; /** * A 0-length char array. */ public static final char [] EMPTY_CHAR_ARRAY = new char[0];
/** * A 0-length double array. */ public static final double [] EMPTY_DOUBLE_ARRAY = new double[0];
/** * A 0-length float array. */ public static final float [] EMPTY_FLOAT_ARRAY = new float[0];
/** * A 0-length String array. */ public static final String [] EMPTY_STRING_ARRAY = new String[0]; /** * An empty enumeration. */ public static final Enumeration EMPTY_ENUM = new Enumeration(){ public boolean hasMoreElements(){return false;} public Object nextElement(){throw new NoSuchElementException();} }; /** * Returnstrue
if the two specified objects are the same. * Returnsfalse
otherwise. To be considered the same, the two * references must either both be null or invokingequals
on one * of them with the other must returntrue
. */ public static boolean areEqual(Object obj1, Object obj2){ return (obj1 == obj2) || (obj1 == null ? false : obj1.equals(obj2)); }
/** * Maps the specified key to the specified value in the specified *Hashtable
. If the specified value isnull
any * existing mapping of the specified key is removed from the *Hashtable
. The old value mapped to the specified key * is returned, ornull
if no value was mapped to the key. */ public static Object put(Hashtable table, Object key, Object value){ return value == null ? table.remove(key) : table.put(key, value); }
/** * Returnstrue
if the specified object is an element of the * specified array. The specified array may not benull
. The * specified object may benull
, in which case this method will * returntrue
iff one of the indices in the array is empty * (containsnull
). */ public static boolean contains(Object [] array, Object item){ return (indexOf(array, item) != -1); }
/** * Returns the index of the first occurrance of specified object in the * specified array, or -1 if the specified object is not an element of the * specified array. The specified object may benull
in which * case the returned index will be the index of the firstnull
* in the array. */ public static int indexOf(Object [] array, Object item){ if (array == null) throw new IllegalArgumentException("The specified array may not be null"); for (int i = 0; i < array.length; i++) if (areEqual(item, array[i])) return i; return -1; }
/** * Returns the index of the first occurrance of specified integer in the * specified array, or -1 if the specified integer is not an element of the * specified array. */ public static int indexOf(int [] arr, int val){ if (arr == null) throw new IllegalArgumentException("The specified array may not be null"); for (int i = 0; i < arr.length; i++) if (arr[i] == val) return i; return -1; } /** * Converts the specified array into a string by appending all its elements * separated by a semicolon. */ public static String arrayToString(Object [] arr){ StringBuffer buf = new StringBuffer(); for (int i = 0; i < arr.length; i++){ buf.append(arr[i]); buf.append("; "); } if (arr.length > 0) buf.setLength(buf.length() - 2); // get rid of the extra "; " return buf.toString(); }
/**
* Converts the specified Hashtable
into a string by putting
* each key and value on a separate line (separated by "\n") and an arrow
* (" -> ") between them.
*/
public static String hashtableToString(Hashtable hashtable){
StringBuffer buf = new StringBuffer();
Enumeration keys = hashtable.keys();
while (keys.hasMoreElements()){
Object key = keys.nextElement();
Object value = hashtable.get(key);
buf.append(key.toString());
buf.append(" -> ");
buf.append(value.toString());
buf.append("\n");
}
return buf.toString();
}
/** * Returns the maximum element in the specified integer array. */ public static int max(int [] arr){ if (arr == null) throw new IllegalArgumentException("The specified array may not be null"); if (arr.length == 0) throw new IllegalArgumentException("The specified array must have at least one element"); int n = arr[0]; for (int i = 1; i < arr.length; i++) if (arr[i] > n) n = arr[i]; return n; }
/** * Returns a hash code for the specified double value. */ public static int hashCode(double val){ return hashCode(Double.doubleToLongBits(val)); }
/** * Returns a hash code for the specified long value. */ public static int hashCode(long val){ return (int)(val ^ (val >>> 32)); } /** * Returns the name of the package of the specified class. */ public static String getPackageName(Class c){ return getPackageName(c.getName()); } /** * Returns the name of the package of the class with the specified (full) name. */ public static String getPackageName(String className){ int lastDotIndex = className.lastIndexOf("."); return lastDotIndex == -1 ? "" : className.substring(0, lastDotIndex); } /** * Returns the short name (excluding the package name) of the specified class. */ public static String getClassName(Class c){ return getClassName(c.getName()); } /** * Returns the short name (excluding the package name) of the class with the * specified fully qualified name. */ public static String getClassName(String className){ int lastDotIndex = className.lastIndexOf("."); return lastDotIndex == -1 ? className : className.substring(lastDotIndex + 1); } } </source>
Table Layout implements LayoutManager2
<source lang="java">
/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */
import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager2; import java.util.ArrayList; public class TableLayout implements LayoutManager2 {
private int colCount; private ArrayList contents; // of Component[] private int curRow; private int curCol; private Dimension prefs; private int[] prefRow; private int[] prefCol; private double[] rowWeight; public TableLayout(int colCount) { this.colCount = colCount; this.contents = new ArrayList(); this.curRow = 0; this.curCol = 0; } public void setRowWeight(int rowIndex, double weight) { if(weight < 0) { throw new IllegalArgumentException("weight must be nonnegative"); } if(rowIndex < 0) { throw new IllegalArgumentException("row index must be nonnegative"); } if((rowWeight == null || rowIndex >= rowWeight.length) && weight != 0.0) { double[] a = new double[rowIndex + 10]; if(rowWeight != null) System.arraycopy(rowWeight, 0, a, 0, rowWeight.length); rowWeight = a; } rowWeight[rowIndex] = weight; } public void addLayoutComponent(String name, Component comp) { while(curRow >= contents.size()) { contents.add(new Component[colCount]); } Component[] rowContents = (Component[]) contents.get(curRow); rowContents[curCol] = comp; ++curCol; if(curCol == colCount) { ++curRow; curCol = 0; } prefs = null; } public void addLayoutComponent(Component comp, Object constraints) { if(constraints instanceof TableConstraints) { TableConstraints con = (TableConstraints) constraints; if(con.getRow() >= 0) curRow = con.getRow(); if(con.getCol() >= 0) curCol = con.getCol(); } addLayoutComponent("", comp); } public void removeLayoutComponent(Component comp) { for(int i = 0, n = contents.size(); i < n; i++) { Component[] row = (Component[]) contents.get(i); for(int j = 0; j < row.length; j++) { if(row[j] == comp) { row[j] = null; return; } } } prefs = null; } public Dimension preferredLayoutSize(Container parent) { if(prefs == null) { int[] prefCol = new int[colCount]; int[] prefRow = new int[contents.size()]; int height = 0; for(int i = 0; i < prefRow.length; i++) { Component[] row = (Component[]) contents.get(i); int rowHeight = 0; for(int j = 0; j < row.length; j++) { if(row[j] != null) { Dimension dim = row[j].getPreferredSize(); if(dim.height > rowHeight) rowHeight = dim.height; if(dim.width > prefCol[j]) prefCol[j] = dim.width; } } prefRow[i] = rowHeight; height += rowHeight; } int width = 0; for(int i = 0; i < prefCol.length; i++) { width += prefCol[i]; } this.prefs = new Dimension(width, height); this.prefRow = prefRow; this.prefCol = prefCol; } return new Dimension(prefs); } public Dimension minimumLayoutSize(Container parent) { return preferredLayoutSize(parent); } public Dimension maximumLayoutSize(Container parent) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } public float getLayoutAlignmentX(Container parent) { return 0.5f; } public float getLayoutAlignmentY(Container parent) { return 0.5f; } public void layoutContainer(Container parent) { Dimension pref = preferredLayoutSize(parent); int[] prefRow = this.prefRow; int[] prefCol = this.prefCol; Dimension size = parent.getSize(); double y0; int yRemaining = size.height - pref.height; double rowWeightTotal = 0.0; if(yRemaining != 0 && rowWeight != null) { for(int i = 0; i < rowWeight.length; i++) { rowWeightTotal += rowWeight[i]; } } if(rowWeightTotal == 0.0 && yRemaining > 0) { y0 = yRemaining / 2.0; } else { y0 = 0; } int x0 = (size.width - pref.width) / 2; if(x0 < 0) x0 = 0; double y = y0; for(int i = 0, n = contents.size(); i < n; i++) { Component[] row = (Component[]) contents.get(i); int yRound = (int) (y + 0.5); int x = x0; for(int j = 0; j < row.length; j++) { Component comp = row[j]; if(comp != null) { row[j].setBounds(x, yRound, prefCol[j], prefRow[i]); } x += prefCol[j]; } y += prefRow[i]; if(rowWeightTotal > 0 && i < rowWeight.length) { y += yRemaining * rowWeight[i] / rowWeightTotal; } } // TODO Auto-generated method stub } public void invalidateLayout(Container parent) { prefs = null; }
} /* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */ class TableConstraints { public static TableConstraints at(int row, int col) { return new TableConstraints(row, col); } private int col; private int row; private TableConstraints(int row, int col) { this.col = col; this.row = row; } int getRow() { return row; } int getCol() { return col; }
}
</source>
Table layout manager
<source lang="java">
// Table layout manager, with the flexibility of GridBagLayout but the ease // of use of HTML table declarations. // See http://www.parallax.co.uk/~rolf/download/table.html // Copyright (C) Rolf Howarth 1997, 1998 (rolf@parallax.co.uk) // Permission to freely use, modify and distribute this code is given, // provided this notice remains attached. This code is provided for // educational use only and no warranty as to its suitability for any // other purpose is made. // Modification history // 0.1 01 Nov 96 First version // 1.0 17 Jan 97 Minor bug fix; added column weighting. // 1.1 08 Apr 98 Don"t use methods deprecated in JDK1.1 // 1.2 16 Apr 98 Make own copy of Dimension objects as they"re not immutable import java.awt.*; import java.util.*; // Private class to parse and store the options for a single table entry
/**
* Table layout manager, with the flexibity of GridBagLayout but the ease of * use of HTML table declarations. **
use like: </br> * new TableLayout(cols) </br> * add(comp, new TableOption(..)) </br> * .. *
*/
public class TableLayout implements LayoutManager,LayoutManager2 {
private Hashtable options = new Hashtable(); private TableOption defaultOption; private int nrows=0, ncols=0; private int ncomponents=0; private Component[][] components=null; private int MinWidth=0, MinHeight=0, PrefWidth=0, PrefHeight=0; private int[] minWidth=null, minHeight=null, prefWidth=null, prefHeight=null; private int[] weight=null, columnWidth=null; private int hgap=0, vgap=0; /** * Construct a new table layout manager. * @param cols Number of columns, used when adding components to tell when to go to the next row * @param defaultAlignment Default defaultAlignment for cells if not specified at the time of adding the component * @param hgap Horizontal gap between cells and at edge (in pixels) * @param vgap Vertical gap between cells and at edge (in pixels) **/ public TableLayout(int cols, String defaultAlignment, int hgap, int vgap) { this(cols, new TableOption(defaultAlignment),hgap,vgap); } public TableLayout(int cols, TableOption defaultAlignment, int hgap, int vgap) { this.ncols = cols; // the number of columns is specified this.nrows = 0; // the number of rows is calculated this.ruponents = new Component[cols][]; this.defaultOption=defaultAlignment; this.hgap = hgap; this.vgap = vgap; } public TableLayout(int cols, String alignment) { this(cols, alignment, 0, 0); } public TableLayout(int cols) { this(cols, "", 0, 0); } public void addLayoutComponent(String alignment, Component comp) { options.put(comp, new TableOption(alignment)); } public void removeLayoutComponent(Component comp) { options.remove(comp); } // Iterate through the components, counting the number of rows taking into account // row and column spanning, then initialise the components[c][r] matrix so that // we can retrieve the component at a particular row,column position. private void loadComponents(Container parent) { ncomponents = parent.getComponentCount(); // If we haven"t allocated the right sized array for each column yet, do so now. // Note that the number of columns is fixed, but the number of rows is not know // and could in the worst case be up the number of components. Unfortunately this // means we need to allocate quite big arrays, but the alternative would require // complex multiple passes as we try to work out the effect of row spanning. if (components[0] == null || components[0].length < ncomponents) { for (int i=0; i<ncols; ++i) components[i] = new Component[ncomponents]; } // Nullify the array for (int i=0; i<ncols; ++i) { for (int j=0; j<components[i].length; ++j) components[i][j] = null; } // fill the matrix with components, taking row/column spanning into account int row=0, col=0; for (int i=0; i<ncomponents; ++i) { // get the next component and its options Component comp = parent.getComponent(i); TableOption option = (TableOption) options.get(comp); if (option==null) option = defaultOption; // handle options to force us to column 0 or to skip columns if (option.forceColumn >= 0) { if (col > option.forceColumn) ++row; col = option.forceColumn; } col += option.skipColumns; if (col>=ncols) { ++row; col=0; } // skip over any cells that are already occupied while (components[col][row] != null) { ++col; if (col>=ncols) { ++row; col=0; } } // if using colspan, will we fit on this row? if (col+option.colSpan > ncols) { ++row; col = 0; } // for now, fill all the cells that are occupied by this component for (int c=0; c<option.colSpan; ++c) for (int r=0; r<option.rowSpan; ++r) components[col+c][row+r] = comp; // advance to the next cell, ready for the next component col += option.colSpan; if (col>=ncols) { ++row; col=0; } } // now we know how many rows there are if (col == 0) nrows = row; else nrows = row+1; // now we"ve positioned our components we can thin out the cells so // we only remember the top left corner of each component for (row=0; row<nrows; ++row) { for (col=0; col<ncols; ++col) { Component comp = components[col][row]; for (int r=row; r<nrows && components[col][r]==comp; ++r) { for (int c=col; c<ncols && components[c][r]==comp; ++c) { if (r>row || c>col) components[c][r] = null; } } } } } private void measureComponents(Container parent) { // set basic metrics such as ncomponents & nrows, and load the components // into the components[][] array. loadComponents(parent); // allocate new arrays to store row and column preferred and min sizes, but // only if the old arrays aren"t big enough if (minWidth==null || minWidth.length<ncols) { minWidth = new int[ncols]; prefWidth = new int[ncols]; columnWidth = new int[ncols]; weight = new int[ncols]; } if (minHeight==null || minHeight.length<nrows) { minHeight = new int[nrows]; prefHeight = new int[nrows]; } int i; for (i=0; i<ncols; ++i) { minWidth[i] = 0; prefWidth[i] = 0; } for (i=0; i<nrows; ++i) { minHeight[i] = 0; prefHeight[i] = 0; } // measure the minimum and preferred size of each row and column for (int row=0; row<nrows; ++row) { for (int col=0; col<ncols; ++col) { Component comp = components[col][row]; if (comp != null) { TableOption option = (TableOption) options.get(comp); if (option==null) option = defaultOption; Dimension minSize = new Dimension(comp.getMinimumSize()); Dimension prefSize = new Dimension(comp.getPreferredSize()); // enforce prefSize>=minSize if (prefSize.width < minSize.width) prefSize.width = minSize.width; if (prefSize.height < minSize.height) prefSize.height = minSize.height; // divide size across all the rows or columns being spanned minSize.width /= option.colSpan; minSize.height /= option.rowSpan; prefSize.width = (prefSize.width - hgap*(option.colSpan-1)) / option.colSpan; prefSize.height = (prefSize.height - vgap*(option.rowSpan-1)) / option.rowSpan; for (int c=0; c<option.colSpan; ++c) { if (minSize.width > minWidth[col+c]) minWidth[col+c] = minSize.width; if (prefSize.width > prefWidth[col+c]) prefWidth[col+c] = prefSize.width; } for (int r=0; r<option.rowSpan; ++r) { if (minSize.height > minHeight[row+r]) minHeight[row+r] = minSize.height; if (prefSize.height > prefHeight[row+r]) prefHeight[row+r] = prefSize.height; } } } } // add rows and columns to give total min and preferred size of whole grid MinWidth = 0; MinHeight = 0; PrefWidth = hgap; PrefHeight = vgap; for (i=0; i<ncols; ++i) { MinWidth += minWidth[i]; PrefWidth += prefWidth[i] + hgap; } for (i=0; i<nrows; ++i) { MinHeight += minHeight[i]; PrefHeight += prefHeight[i] + vgap; } } public Dimension minimumLayoutSize(Container parent) { Insets insets = parent.getInsets(); measureComponents(parent); // System.out.println("Min Size: "+MinWidth+","+MinHeight); return new Dimension(insets.left + insets.right + MinWidth, insets.top + insets.bottom + MinHeight); } public Dimension preferredLayoutSize(Container parent) { Insets insets = parent.getInsets(); measureComponents(parent); // System.out.println("Pref Size: "+PrefWidth+","+PrefHeight); // System.out.println("+ insets LR "+insets.left+"+"+insets.right+", TB "+insets.top+"+"+insets.bottom); return new Dimension(insets.left + insets.right + PrefWidth, insets.top + insets.bottom + PrefHeight); } public void layoutContainer(Container parent) { Insets insets = parent.getInsets(); measureComponents(parent); int width = parent.getSize().width - (insets.left + insets.right); int height = parent.getSize().height - (insets.top + insets.bottom); // System.out.println("Resize "+width+","+height); // Decide whether to base our scaling on minimum or preferred sizes, or // a mixture of both, separately for width and height scaling. // This weighting also tells us how much of the hgap/vgap to use. double widthWeighting = 0.0; if (width >= PrefWidth || PrefWidth==MinWidth) widthWeighting = 1.0; else if (width <= MinWidth) { widthWeighting = 0.0; width = MinWidth; } else widthWeighting = (double)(width-MinWidth)/(double)(PrefWidth-MinWidth); double heightWeighting = 0.0; if (height >= PrefHeight || PrefHeight==MinHeight) heightWeighting = 1.0; else if (height <= MinHeight) { heightWeighting = 0.0; height = MinHeight; } else heightWeighting = (double)(height-MinHeight)/(double)(PrefHeight-MinHeight); // calculate scale factors to scale components to size of container, based // on weighted combination of minimum and preferred sizes double minWidthScale = (1.0 - widthWeighting) * width/MinWidth; //double prefWidthScale = widthWeighting * (width-hgap*(ncols+1))/(PrefWidth-hgap*(ncols+1)); double minHeightScale = (1.0 - heightWeighting) * height/MinHeight; double prefHeightScale = heightWeighting * (height-vgap*(nrows+1))/(PrefHeight-vgap*(nrows+1)); // only get the full amount of gap if we"re working to preferred size int vGap = (int) (vgap * heightWeighting); int hGap = (int) (hgap * widthWeighting); int y = insets.top + vGap; for (int c=0; c<ncols; ++c) weight[c] = prefWidth[c]; for (int r=0; r<nrows; ++r) { int x = insets.left + hGap; int rowHeight = (int)(minHeight[r]*minHeightScale + prefHeight[r]*prefHeightScale); // Column padding can vary from row to row, so we need several // passes through the columns for each row: // First, work out the weighting that deterimines how we distribute column padding for (int c=0; c<ncols; ++c) { Component comp = components[c][r]; if (comp != null) { TableOption option = (TableOption) options.get(comp); if (option==null) option = defaultOption; if (option.weight >= 0) weight[c] = option.weight; else if (option.weight == -1) weight[c] = prefWidth[c]; } } int totalWeight = 0; for (int c=0; c<ncols; ++c) totalWeight += weight[c]; int horizSurplus = width - hgap*(ncols+1) - PrefWidth; // Then work out column sizes, essentially preferred size + share of padding for (int c=0; c<ncols; ++c) { columnWidth[c] = (int) (minWidthScale * minWidth[c] + widthWeighting * prefWidth[c]); if (horizSurplus > 0 && totalWeight > 0) columnWidth[c] += (int) (widthWeighting * horizSurplus * weight[c] / totalWeight); } // Only now do we know enough to position all the columns within this row... for (int c=0; c<ncols; ++c) { Component comp = components[c][r]; if (comp != null) { TableOption option = (TableOption) options.get(comp); if (option==null) option = defaultOption; // cell size may be bigger than row/column size due to spanning int cellHeight = rowHeight; int cellWidth = columnWidth[c]; for (int i=1; i<option.colSpan; ++i) cellWidth += columnWidth[c+i]; for (int i=1; i<option.rowSpan; ++i) cellHeight += (int)(minHeight[r+i]*minHeightScale + prefHeight[r+i]*prefHeightScale + vGap); Dimension d = new Dimension(comp.getPreferredSize()); if (d.width > cellWidth || option.horizontal==TableOption.FILL) d.width = cellWidth; if (d.height > cellHeight || option.vertical==TableOption.FILL) d.height = cellHeight; int yoff = 0; if (option.vertical == TableOption.BOTTOM) yoff = cellHeight - d.height; else if (option.vertical == TableOption.CENTRE) yoff = (cellHeight - d.height) / 2; int xoff = 0; if (option.horizontal == TableOption.RIGHT) xoff = cellWidth - d.width; else if (option.horizontal == TableOption.CENTRE) xoff = (cellWidth - d.width) / 2; // System.out.println(" "+comp.getClass().getName()+" at ("+x+"+"+xoff+","+y+"+"+yoff+"), size "+d.width+","+d.height); comp.setBounds(x+xoff,y+yoff,d.width,d.height); } x += columnWidth[c] + hGap; } y += rowHeight + vGap; } } public void addLayoutComponent(Component comp, Object constraints) { if(constraints instanceof TableOption){ options.put(comp, constraints); } else if(constraints==null){ options.put(comp,defaultOption); } else throw new IllegalArgumentException("not a valid constraints object="+constraints); } /** * Returns the alignment along the x axis. This specifies how * the component would like to be aligned relative to other * components. The value should be a number between 0 and 1 * where 0 represents alignment along the origin, 1 is aligned * the furthest away from the origin, 0.5 is centered, etc.*
* @return the value 0.5f
to indicate centered
*/
public float getLayoutAlignmentX(Container parent) {
return 0.5f;
}
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
* <p>
* @return the value 0.5f
to indicate centered
*/
public float getLayoutAlignmentY(Container parent) {
return 0.5f;
}
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
*/
public void invalidateLayout(Container target) {
}
/**
* Returns the maximum dimensions for this layout given the components
* in the specified target container.
* @param target the container which needs to be laid out
* @see Container
* @see #minimumLayoutSize(Container)
* @see #preferredLayoutSize(Container)
* @return the maximum dimensions for this layout
*/
public Dimension maximumLayoutSize(Container target) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
}
class TableOption{
public static final int CENTRE=1, FILL=2, LEFT=3, RIGHT=4, TOP=5, BOTTOM=6;
int horizontal = CENTRE;
int vertical = CENTRE;
int rowSpan=1, colSpan=1, skipColumns=0, forceColumn=-1, weight=-2;
/**
*
* @param horizontal one of CENTRE,FILL,LEFT,RIGHT,TOP,BOTTOM
* @param vertical
*/
public TableOption(int horizontal, int vertical) {
this.horizontal = horizontal;
this.vertical = vertical;
}
public TableOption(int horizontal, int vertical, int rowSpan, int colSpan) {
this.horizontal = horizontal;
this.vertical = vertical;
this.rowSpan = rowSpan;
this.colSpan = colSpan;
}
public TableOption(int horizontal, int vertical, int rowSpan, int colSpan, int skipColumns, int forceColumn, int weight) {
this.horizontal = horizontal;
this.vertical = vertical;
this.rowSpan = rowSpan;
this.colSpan = colSpan;
this.skipColumns = skipColumns;
this.forceColumn = forceColumn;
this.weight = weight;
}
TableOption(String alignment) {
StringTokenizer tk = new StringTokenizer(alignment, ",");
while (tk.hasMoreTokens())
{
String token = tk.nextToken();
boolean ok = false;
int delim = token.indexOf("=");
if (token.equals("NW") || token.equals("W") || token.equals("SW"))
{ horizontal = LEFT; ok=true; }
if (token.equals("NE") || token.equals("E") || token.equals("SE"))
{ horizontal = RIGHT; ok=true; }
if (token.equals("N") || token.equals("C") || token.equals("F"))
{ horizontal = CENTRE; ok=true; }
if (token.equals("F") || token.equals("FH"))
{ horizontal = FILL; ok=true; }
if (token.equals("N") || token.equals("NW") || token.equals("NE"))
{ vertical = TOP; ok=true; }
if (token.equals("S") || token.equals("SW") || token.equals("SE"))
{ vertical = BOTTOM; ok=true; }
if (token.equals("W") || token.equals("C") || token.equals("E"))
{ vertical = CENTRE; ok=true; }
if (token.equals("F") || token.equals("FV"))
{ vertical = FILL; ok=true; }
if (delim>0)
{
int val = Integer.parseInt(token.substring(delim+1));
token = token.substring(0,delim);
if (token.equals("CS") && val>0)
{ colSpan = val; ok=true; }
else if (token.equals("RS") && val>0)
{ rowSpan = val; ok=true; }
else if (token.equals("SKIP") && val>0)
{ skipColumns = val; ok=true; }
else if (token.equals("COL"))
{ forceColumn = val; ok=true; }
else if (token.equals("WT"))
{ weight = val; ok=true; }
}
if (!ok) throw new IllegalArgumentException("TableOption "+token);
}
}
}
</source>
Tile Layout
<source lang="java">
import java.awt.*; import java.util.LinkedList; import java.io.Serializable; /*
* Relative Component Layout Manager * Copyright (c) 1999 John Catherino * The cajo project: https://cajo.dev.java.net * * For issues or suggestions mailto:cajo@dev.java.net * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License, at version * 2.1 of the licence, or any later version published by the Free Software * Foundation. * * 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 Lesser General Public License for more details. * * You can receive a copy of the GNU Lesser General Public License from their * website, http://fsf.org/licenses/lgpl.html; or via snail mail, Free * Software Foundation Inc., 51 Franklin Street, Boston MA 02111-1301, USA */
/**
* A rather unique LayoutManager. In addition to laying out components relative * to the container, it also supports layout relative to components within * the container. Its purpose is to support arbitrarily complex component * layouts, of an unlimited number of components, within a single container. It * can easily create complex layouts that would otherwise require many * subpanels, and multiple standard layout managers. It also can create layouts * that are completely impossible, with standard layout managers. These * features make this layout manager extremely flexible, and makes * advancedlayouts extremely fast. It just may be, the last and only * LayoutManager you"ll ever need. * <p> * * Components can be laid out above, below, left, or right of either a * referenced component in the panel, or to the panel itself. Its width and * height can be specified with similar flexibility. Absolute and proportional * bounds are also supported. In typical use, one or more "reference" * tiles are laid, and the rest of the components are set relative to them. * <p> ** Usage example:
* panel.add(new JLabel("Label text:"), new Object[]{ * new Integer(TileLayout.LEFTINDENT + TileLayout.NOOFFSET + * TileLayout.PROPWIDTH + TileLayout.FULLHEIGHT), refComponent, * new Insets(-5, 10, 5, 10), new Rectangle(0, 0, 333, 0) * // proportion rectangle 33.3%w * }); * </tt>* * </blockquote> * <p> * * Up to four alignment constraints can be specified, their order does not * matter: * * <p>
**
- Positioning constants for indent, offset, width, and height *
- A Component for placement relative to, otherwise the container *
- A Rectangle for fixed and proportional component bounds *
- Insets to trim the resulting component boundaries *
* <p> * * Note</u>: since the JRE draws components from last added * to first; the manager lays them out similarly. Therefore, in order to layout * relative to another component, the reference component must be added <u>after * the dependent one. I know this can be a drag at first, but it becomes * critically important when components are laid out on top of others, or * overlapping. This is a super cool capability of this layout manager. * * @version 1.0, 01-Nov-99 Initial release * @author John Catherino */ public final class TileLayout implements LayoutManager2, Serializable { private static final long serialVersionUID = 1L; private static final Dimension NONE = new Dimension(); private final LinkedList components = new LinkedList(); private final LinkedList constraints = new LinkedList(); private void align(Dimension cont, Object cons[], Component comp) { int align = 0; Insets insets = null; Rectangle tile = null, fixd = null; if (cons != null) { for (int i = 0; i < cons.length; i++) { // gather constraints if (cons[i] != null) { if (cons[i] instanceof Rectangle) fixd = (Rectangle)cons[i]; else if (cons[i] instanceof Insets) insets = (Insets)cons[i]; else if (cons[i] instanceof Integer) align = ((Integer)cons[i]).intValue(); else if (cons[i] instanceof Component) tile = ((Component)cons[i]).getBounds(); } } } if (tile == null) tile = new Rectangle(cont); Rectangle pref = new Rectangle(tile.getLocation(), comp.getPreferredSize()); // perform component positioning: if ((align & 0x004000) != 0) pref.width = fixd.width; else if ((align & 0x008000) != 0) pref.width = (tile.width * fixd.width + 500) / 1000; else if ((align & 0x010000) != 0) pref.width = tile.width; if ((align & 0x080000) != 0) pref.height = fixd.height; else if ((align & 0x100000) != 0) pref.height = (tile.height * fixd.height + 500) / 1000; else if ((align & 0x200000) != 0) pref.height = tile.height; if ((align & 0x000001) != 0) pref.x -= pref.width; else if ((align & 0x000002) != 0) pref.x += (tile.width - pref.width >> 1); else if ((align & 0x000004) != 0) pref.x += tile.width - pref.width; else if ((align & 0x000008) != 0) pref.x += tile.width; else if ((align & 0x000010) != 0) pref.x += fixd.x; else if ((align & 0x000020) != 0) pref.x += (tile.width * fixd.x + 500) / 1000; if ((align & 0x000040) != 0) pref.y -= pref.height; else if ((align & 0x000080) != 0) pref.y += (tile.height - pref.height >> 1); else if ((align & 0x000100) != 0) pref.y += tile.height - pref.height; else if ((align & 0x000200) != 0) pref.y += tile.height; else if ((align & 0x000400) != 0) pref.y += fixd.y; else if ((align & 0x000800) != 0) pref.y += (tile.height * fixd.y + 500) / 1000; if ((align & 0x001000) != 0) pref.setBounds(0, pref.y, pref.x + pref.width, pref.height); else if ((align & 0x002000) != 0) pref.width = cont.width - pref.x; if ((align & 0x020000) != 0) pref.setBounds(pref.x, 0, pref.width, pref.y + pref.height); else if ((align & 0x040000) != 0) pref.height = cont.height - pref.y; if (insets != null) { // apply insets, if any: pref.x += insets.left; pref.y += insets.top; pref.width -= insets.left + insets.right; pref.height -= insets.top + insets.bottom; } // Note: this can cause surprising results, so use it, if you dare. :-) // Honour component minimum size: Dimension d = comp.getMinimumSize(); if (pref.width < d.width) pref.width = d.width; if (pref.height < d.height) pref.height = d.height; comp.setBounds(pref); // now the tile is set! } /** * This constant specifies placement of the component even with the left * border of the provided reference component, otherwise to the container * itself. */ public static final int NOINDENT = 0x000000; /** * This constant specifies placement of the component with its right border * one pixel to the left of the provided reference component, otherwise to * the container itself. */ public static final int LEFTINDENT = 0x000001; /** * This constant specifies placement of the component evenly between the left * and right borders of the provided reference component, otherwise to the * container itself. */ public static final int CENTERINDENT = 0x000002; /** * This constant specifies placement of the component with its right border * evenly aligned with the right border of the provided reference component, * otherwise to the container itself. */ public static final int FULLINDENT = 0x000004; /** * This constant specifies placement of the left border of the component one * pixel to the right of the provided reference component origin, otherwise * to the container itself. */ public static final int RIGHTINDENT = 0x000008; /** * Used in conjunction with a Rectangle constraint, the x value represents * the desired component indent as a fixed number of pixels right of the * provided component origin, otherwise to the container itself. */ public static final int FIXEDINDENT = 0x000010; /** * Used in conjunction with a Rectangle constraint, the x value represents * the desired component indent as a percentage (2000 = 200.0%) of a provided * component, otherwise to the container itself. */ public static final int PROPINDENT = 0x000020; /** * This constant specifies placement of the component even with the top * border of the provided reference component, otherwise to the container * itself. */ public static final int NOOFFSET = 0x000000; /** * This constant specifies placement of the component with its bottom border * one pixel above the provided reference component, otherwise to the * container itself. */ public static final int TOPOFFSET = 0x000040; /** * This constant specifies placement of the component evenly between the top * and bottom borders of the provided reference component, otherwise to the * container itself. */ public static final int CENTEROFFSET = 0x000080; /** * This constant specifies placement of the component with its bottom border * evenly aligned with the bottom border of the provided reference component, * otherwise to the container itself. */ public static final int FULLOFFSET = 0x000100; /** * This constant specifies placement of the top border of the component one * pixel below the provided reference component origin, otherwise to the * container itself. */ public static final int BOTTOMOFFSET = 0x000200; /** * Used in conjunction with a Rectangle constraint, the y value represents * the desired component offset as a fixed number of pixels below the * provided component origin, otherwise to the container itself. */ public static final int FIXEDOFFSET = 0x000400; /** * Used in conjunction with a Rectangle constraint, the y value represents * the desired component offset as a percentage (2000 = 200.0%) of a provided * component, otherwise to the container itself. */ public static final int PROPOFFSET = 0x000800; /** * This constant specifies that the component have its preferred width, as * returned by its getPreferredSize method. */ public static final int PREFWIDTH = 0x000000; /** * This constant specifies that the component be made wide enough such that * given its computed right margin, its left margin will align with that of * its container. */ public static final int CLAMPLEFT = 0x001000; /** * This constant specifies that the component be made wide enough such that * given its computed origin, its right margin will align with that of its * container. */ public static final int CLAMPRIGHT = 0x002000; /** * Used in conjunction with a Rectangle constraint, the width value * represents the desired component width as a fixed number of pixels. */ public static final int FIXEDWIDTH = 0x004000; /** * Used in conjunction with a Rectangle constraint, the width value * represents the desired component offset as a percentage (2000 = 200.0%) of * a provided component, otherwise to the container itself. */ public static final int PROPWIDTH = 0x008000; /** * This constant specifies that the component be made exactly as wide as its * reference component, otherwise as the container itself. */ public static final int FULLWIDTH = 0x010000; /** * This constant specifies that the component have its preferred height, as * returned by its getPreferredSize method. */ public static final int PREFHEIGHT = 0x000000; /** * This constant specifies that the component be made high enough such that * given its computed bottom margin, its top margin will align with that of * its container. */ public static final int CLAMPTOP = 0x020000; /** * This constant specifies that the component be made high enough such that * given its computed origin, its bottom margin will align with that of its * container. */ public static final int CLAMPBOTTOM = 0x040000; /** * Used in conjunction with a Rectangle constraint, the height value * represents the desired component width as a fixed number of pixels. */ public static final int FIXEDHEIGHT = 0x080000; /** * Used in conjunction with a Rectangle constraint, the height value * represents the desired component offset as a percentage (2000 = 200.0%) of * a provided component, otherwise to the container itself. */ public static final int PROPHEIGHT = 0x100000; /** * This constant specifies that the component be made exactly as high as its * reference component, otherwise as the container itself. */ public static final int FULLHEIGHT = 0x200000; /** * A frequently used position, used in conjunction with a reference * component, it will locate the component directly over, with the same width * and height. */ public static final Integer ABOVE = new Integer(NOINDENT + TOPOFFSET + FULLWIDTH + FULLHEIGHT); /** * A frequently used position, used in conjunction with a reference * component, it will locate the component directly beneath, with the same * width and height. */ public static final Integer BELOW = new Integer(NOINDENT + BOTTOMOFFSET + FULLWIDTH + FULLHEIGHT); /** * A frequently used position, used in conjunction with a reference * component, it will locate the component directly adjacent, to its right, * with the same width and height. */ public static final Integer RIGHT = new Integer(RIGHTINDENT + NOOFFSET + FULLWIDTH + FULLHEIGHT); /** * A frequently used position, used in conjunction with a reference * component, it will locate the component directly adjacent, to its left, * with the same width and height. */ public static final Integer LEFT = new Integer(LEFTINDENT + NOOFFSET + FULLWIDTH + FULLHEIGHT); /** * A frequently used position, it will render the component using the exact * size of the reference component, or container. */ public static final Integer FULLSIZE = new Integer(NOINDENT + NOOFFSET + FULLWIDTH + FULLHEIGHT); /** * Nothing is performed in the constructor, it is bodyless. */ public TileLayout() {} /** * The primary component addition method. Components are added for layout, * and its constraints are provided as an Object array. Up to 4 constraints * may be specified, and their order is not important. The following are the * applicable constraints:
** <p> *
- Rectangle for fixed or proportional component bounds *
- Insets to trim the final boundaries after computation *
- Integer of TileLayout positioning constants *
- Component for relative placement, instead of container *
* * @param comp The component to be laid out within the container. * @param cons An Object[] containing 1 or more constraints. */ public void addLayoutComponent(Component comp, Object cons) { components.add(comp); constraints.add(cons); } /** * This method will make the added component exactly the same size as the * container itself. It is useful for adding wallpaper. * * @param comp The component to fill the container. * @param name The name of the component, unused by TileLayout. */ public void addLayoutComponent(String name, Component comp) { components.add(comp); constraints.add(new Object[]{ FULLSIZE }); } /** * As expected, removes the component from the ordered layout list. */ public void removeLayoutComponent(Component comp) { for (int i = 0; i < components.size(); i++) { if (components.get(i) == comp) { components.remove(i); constraints.remove(i); return; } } throw new IllegalArgumentException("Component not in container"); } /** * Lays out the components, last added to first added, according to their * specified constraints. */ public void layoutContainer(Container parent) { Dimension container = parent.getSize(); for (int i = components.size() - 1; i >= 0; i--) align(container, (Object[])constraints.get(i), (Component)components.get(i)); } /** * Bodyless implementation, as TileLayout uses no cached information. */ public void invalidateLayout(Container target) {} /** * Indicate center alignment. */ public float getLayoutAlignmentX(Container target) { return 0.5F; } /** * Indicate center alignment. */ public float getLayoutAlignmentY(Container target) { return 0.5F; } /** * Indicates no minimum size. */ public Dimension minimumLayoutSize(Container parent) { return NONE; } /** * Indicates no maximum size. */ public Dimension maximumLayoutSize(Container parent) { return NONE; } /** * Indicates no preferred size. */ public Dimension preferredLayoutSize(Container parent) { return NONE; } }
</source>
Wrapper Layout
<source lang="java">
/* GNU LESSER GENERAL PUBLIC LICENSE Copyright (C) 2006 The Lobo Project This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Contact info: lobochief@users.sourceforge.net
- /
/* * Created on Mar 19, 2005 */ import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager; /** * @author J. H. S. */ public class WrapperLayout implements LayoutManager { /* (non-Javadoc) * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.ruponent) */ public void addLayoutComponent(String arg0, Component arg1) { } /* (non-Javadoc) * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.ruponent) */ public void removeLayoutComponent(Component arg0) { } /* (non-Javadoc) * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container) */ public Dimension preferredLayoutSize(Container arg0) { java.awt.Insets insets = arg0.getInsets(); int count = arg0.getComponentCount(); if(count > 0) { Dimension d = arg0.getComponent(0).getPreferredSize(); return new Dimension(d.width + insets.left + insets.right, d.height + insets.top + insets.bottom); } else { return new Dimension(insets.left + insets.right, insets.top + insets.bottom); } } /* (non-Javadoc) * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container) */ public Dimension minimumLayoutSize(Container arg0) { java.awt.Insets insets = arg0.getInsets(); int count = arg0.getComponentCount(); if(count > 0) { Dimension d = arg0.getComponent(0).getMinimumSize(); return new Dimension(d.width + insets.left + insets.right, d.height + insets.top + insets.bottom); } else { return new Dimension(insets.left + insets.right, insets.top + insets.bottom); } } /* (non-Javadoc) * @see java.awt.LayoutManager#layoutContainer(java.awt.Container) */ public void layoutContainer(Container arg0) { int count = arg0.getComponentCount(); if(count > 0) { Component child = arg0.getComponent(0); java.awt.Insets insets = arg0.getInsets(); child.setBounds(insets.left, insets.top, arg0.getWidth() - insets.left - insets.right, arg0.getHeight() - insets.top - insets.bottom); } }
private static WrapperLayout instance = new WrapperLayout();
public static WrapperLayout getInstance() { return instance; } }
</source>
X Y Layout
<source lang="java">
//Revised from enhydra swing import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager2; import java.awt.Rectangle; import java.io.Serializable; import java.util.Hashtable; public class XYLayout implements LayoutManager2, Serializable { private static final long serialVersionUID = 200L; int width; int height; Hashtable info; static final XYConstraints defaultConstraints = new XYConstraints(); public XYLayout() { info = new Hashtable(); } public XYLayout(int width, int height) { info = new Hashtable(); this.width = width; this.height = height; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public String toString() { return String.valueOf(String.valueOf((new StringBuffer("XYLayout[width=")).append(width) .append(",height=").append(height).append("]"))); } public void addLayoutComponent(String s, Component component1) { } public void removeLayoutComponent(Component component) { info.remove(component); } public Dimension preferredLayoutSize(Container target) { return getLayoutSize(target, true); } public Dimension minimumLayoutSize(Container target) { return getLayoutSize(target, false); } public void layoutContainer(Container target) { Insets insets = target.getInsets(); int count = target.getComponentCount(); for (int i = 0; i < count; i++) { Component component = target.getComponent(i); if (component.isVisible()) { Rectangle r = getComponentBounds(component, true); component.setBounds(insets.left + r.x, insets.top + r.y, r.width, r.height); } } } public void addLayoutComponent(Component component, Object constraints) { if (constraints instanceof XYConstraints) info.put(component, constraints); } public Dimension maximumLayoutSize(Container target) { return new Dimension(0x7fffffff, 0x7fffffff); } public float getLayoutAlignmentX(Container target) { return 0.5F; } public float getLayoutAlignmentY(Container target) { return 0.5F; } public void invalidateLayout(Container container) { } Rectangle getComponentBounds(Component component, boolean doPreferred) { XYConstraints constraints = (XYConstraints) info.get(component); if (constraints == null) constraints = defaultConstraints; Rectangle r = new Rectangle(constraints.x, constraints.y, constraints.width, constraints.height); if (r.width <= 0 || r.height <= 0) { Dimension d = doPreferred ? component.getPreferredSize() : component.getMinimumSize(); if (r.width <= 0) r.width = d.width; if (r.height <= 0) r.height = d.height; } return r; } Dimension getLayoutSize(Container target, boolean doPreferred) { Dimension dim = new Dimension(0, 0); if (width <= 0 || height <= 0) { int count = target.getComponentCount(); for (int i = 0; i < count; i++) { Component component = target.getComponent(i); if (component.isVisible()) { Rectangle r = getComponentBounds(component, doPreferred); dim.width = Math.max(dim.width, r.x + r.width); dim.height = Math.max(dim.height, r.y + r.height); } } } if (width > 0) dim.width = width; if (height > 0) dim.height = height; Insets insets = target.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } class XYConstraints implements Cloneable, Serializable { int x; int y; int width; int height; public XYConstraints() { this(0, 0, 0, 0); } public XYConstraints(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int hashCode() { return x ^ y * 37 ^ width * 43 ^ height * 47; } public boolean equals(Object that) { if (that instanceof XYConstraints) { XYConstraints other = (XYConstraints) that; return other.x == x && other.y == y && other.width == width && other.height == height; } else { return false; } } public Object clone() { return new XYConstraints(x, y, width, height); } public String toString() { return String.valueOf(String.valueOf((new StringBuffer("XYConstraints[")).append(x).append(",") .append(y).append(",").append(width).append(",").append(height).append("]"))); } }
</source>