Java/Swing JFC/Customized Layout
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 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.
/*
* 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
}
}
A layout manager that spaces components over six columns in seven different formats.
/*
* 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).
* <P>
* 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.
* <table>
* <tr>
* <td>C</td>
* <td>1 component in this row (spread across all six columns).</td>
* </tr>
* <tr>
* <td>LC</td>
* <td>2 components, a label in the 1st column, and a component using the
* remaining 5 columns).</td>
* </tr>
* <tr>
* <td>LCB</td>
* <td>3 components, a label in the 1st column, a component spread across
* the next 4, and a button in the last column.</td>
* </tr>
* <tr>
* <td>LCLC</td>
* <td>4 components, a label in column 1, a component in 2-3, a label in
* 4 and a component in 5-6.</td>
* </tr>
* <tr>
* <td>LCLCB</td>
* <td>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.</td>
* </tr>
* <tr>
* <td>LCBLC</td>
* <td>5 components, a label in column 1, a component in 2, a button in 3,
* a label in 4, a component in 5-6.</td>
* </tr>
* <tr>
* <td>LCBLCB</td>
* <td>6 components, one in each column.</td>
* </tr>
* </table>
* <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 <code>true</code> 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
}
}
Applet GUI demo of TreeLayout layout manager
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, <I>then </I> 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 <EM>must
* </EM> 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 <em>must</em> 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 <em>must</em> have been
* previously added. If either component has not previously been added, this
* injunction is silently ignored. Cycles are <em>not</em> 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);
}
}
}
}
}
A simple layoutmanager to overlay all components of a parent.
/*
* 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 component <code>comp</code> to the layout,
* associating it
* with the string specified by <code>name</code>.
*
* @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);
}
}
}
Basically two (or more) columns of different, but constant, widths
/*
* 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:
*
* <PRE>
*
* Login: _______________
* Password: _______________
*
* </PRE>
*
* Basically two (or more) columns of different, but constant, widths. <b>Note:
* all columns must be the same height! </b>.
* <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. <b>Note: </b> As with GridLayout, the
* number of items added <B>must </B> 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);
}
}
}
Center Layout
/*
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;
}
}
ColumnLayout
/*
* 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);
}
}
Compents are laid out in a circle.
/*
* 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);
}
}
Customized layout manager
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);
}
}
}
}
Custom Layout Demo
/* 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 + "]";
}
}
Custom layout: EdgeLayout
/*
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);
}
}
}
}
}
DividerLayout is layout that divides two components with the column of actions
/*
* $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>
* <code>DividerLayout</code> 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.
* </p>
* <p>
* Components are indicated as {@link #WEST}, {@link #EAST} and {@link #CENTER}.
* </p>
*
* @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);
}
}
}
Flex Layout
// 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.<BR><BR>
* <B>General design issues:</B><BR>
* 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.<BR><BR>
* Second, decide which row/column expand (this is done by the setColProp/setRowProp
* methods).<BR><BR>
* Third, add components to container (layout) giving proper constraints.<BR><BR>
* <B>Example:</B><BR><PRE>
* 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)
* </PRE><BR>
* <I>Description:</I><BR>
* 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.<BR>
* 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.<BR>
* line 4: the layout is added to the container.<BR>
* 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.<BR>
* 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.<BR><BR>
* The complete command string is:<BR><PRE>
* "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)
* </PRE>
* <B>Notes:</B><BR>
* - if a component occupies more than 1 cell in x direction, its preferred width is NOT
* taken into account (same for y).<BR>
* - if a column / row is empty, its size is set to a default value. This value can be
* changed using setXNullgap/setYNullgap methods.
* <BR><BR>
* 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;
}
}
GraphPaperLayout
/* 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 <code>GraphPaperLayout</code> 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.
* <p>
* <code><pre>
*
* 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));
* }
* }
* </pre></code>
*
* @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
* in <code>getLargestCellSize()</code> 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
* in <code>getLargestCellSize()</code> 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
}
}
Place components at exact locations (x, y, width, height) and then determine how they behave when the window containing them (their parent) is resized
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);
}
}
Relative Layout Manager for Java J2SE
/*
* 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 <em>not</em> mandate that the user can"t resize you --
* see any book on UI design for <em>that</em> 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:
*
* <pre>
* setLayout(null);
* setSize(331, 241);
* label1 = new Label("Info Applet", Label.CENTER);
* add(label1);
* label1.setBounds(91, 19, 107, 15);
* </pre>
*
* </p>
* <p>
* <em>Bleaarrgghh!!!</em> To make it work properly at all resolutions and
* survive user-initiated resize actions, change it to
*
* <pre>
*
* setLayout(new RelativeLayout(331,241,false);
* label1=new Label("Info Applet", Label.CENTER);
* add("91,19", label1);
*
* </pre>
*
* Note that it"s actually <EM>less</EM> work to get it right. Symantec,
* Microsoft, and others, please take note!
* </p>
*
* @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 <EM>Note</EM>: the
* "name" <EM>must</EM> contain x, y location, ie., <BR>
* add("" + 320 + "," + 100, new Button("Quit")); <BR>
* or <BR>
* add("320,100", new Button("Quit"). <BR>
* 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;
}
}
}
Specialised layout manager for a grid of components.
/*
* 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
}
}
Special simple layout used in TabbedContainer
/*
* 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);
}
}
Square Layout
/**
* 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, or <code>null</code> if
* none. Throws an <code>IllegalStateException</code> 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);
}
}
Stack Layout, uses an orientation to determine if the contents should be arranged horizontally or vertically.
/*
* 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;
}
}
Table Layout
/**
* 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 <code>GridLayout</code>, 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
* <code>IllegalStateException</code> if any of the components added via the
* <code>addLayoutComponent</code> 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 <code>preferredLayoutSize</code>.
*/
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 <code>CENTER_ALIGNMENT</code>;
*/
public float getLayoutAlignmentX(Container parent) {
return Component.CENTER_ALIGNMENT;
}
/**
* Returns <code>CENTER_ALIGNMENT</code>;
*/
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 new <code>Pair</code> with the two given objects. Either of the
* objects may be <code>null</code>.
*/
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 <code>Utilities.areEqual</code>)
*/
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();}
};
/**
* Returns <code>true</code> if the two specified objects are the same.
* Returns <code>false</code> otherwise. To be considered the same, the two
* references must either both be null or invoking <code>equals</code> on one
* of them with the other must return <code>true</code>.
*/
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
* <code>Hashtable</code>. If the specified value is <code>null</code> any
* existing mapping of the specified key is removed from the
* <code>Hashtable</code>. The old value mapped to the specified key
* is returned, or <code>null</code> 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);
}
/**
* Returns <code>true</code> if the specified object is an element of the
* specified array. The specified array may not be <code>null</code>. The
* specified object may be <code>null</code>, in which case this method will
* return <code>true</code> iff one of the indices in the array is empty
* (contains <code>null</code>).
*/
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 be <code>null</code> in which
* case the returned index will be the index of the first <code>null</code>
* 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 <code>Hashtable</code> 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);
}
}
Table Layout implements LayoutManager2
/* 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;
}
}
Table layout manager
// 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.
*
* <p>use like: </br>
* new TableLayout(cols) </br>
* add(comp, new TableOption(..)) </br>
* ..
* </p>
*/
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.
* <p>
* @return the value <code>0.5f</code> 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 <code>0.5f</code> 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);
}
}
}
Tile Layout
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 <i>within</i>
* 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 <i>impossible</i>, 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 <i>"reference"</i>
* tiles are laid, and the rest of the components are set relative to them.
* <p>
*
* Usage example:<blockquote><tt><pre>
* 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></pre>
*
* </blockquote>
* <p>
*
* Up to four alignment constraints can be specified, their order does not
* matter:
*
* <p>
* <ul>
* <li> Positioning constants for indent, offset, width, and height
* <li> A Component for placement relative to, otherwise the container
* <li> A Rectangle for fixed and proportional component bounds
* <li> Insets to trim the resulting component boundaries
* </ul>
* <p>
*
* <u><i>Note</u>:</i> since the JRE <i>draws</i> 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</u>
* 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 <i>super cool</i> 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:
* <ul>
* <p>
* <li> Rectangle for fixed or proportional component bounds
* <li> Insets to trim the final boundaries after computation
* <li> Integer of TileLayout positioning constants
* <li> Component for relative placement, instead of container
* </ul>
*
* @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; }
}
Wrapper Layout
/*
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;
}
}
X Y Layout
//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("]")));
}
}