ChessLayout Tutorial

Warning - Tutorial Still Under Construction

Welcome to the ChessLayout Tutorial.  The ChessLayout is a Java class useful to Java Programmers who need a flexible, easy-to-use Java LayoutManager to arrange Java AWT Components. To understand this tutorial, you should understand Java Containers, Components and LayoutManagers.

Here are the Javadoc descriptions for ChessLayout and ChessPiece.

1. Introduction

The ChessLayout arranges the Components within a Container as if they were ChessPieces on a ChessBoard. However the layout is much more flexible than a regular chess board in the following ways:
The ChessBoard may contain any number of rows and columns.

The rows and columns are of variable height/width.

ChessPieces may occupy more than one square on the ChessBoard.

Multiple ChessPieces may occupy the same square.

ChessPieces are of variable size, and may be centered, stretched, or placed against the side of a row or column.

The ChessLayout parameters which determine how the ChessBoard looks are the following: The ChessPiece parameters associated with each Component include: The java.awt.Container and java.awt.Component Parameters:

2. ChessLayout Demo

That's enough information to understand the ChessLayout in operation.  When you click on the button below, you will activate the ChessLayoutTest, a demo applet which uses ChessLayout to display a collection of buttons:

The demo brings up a ChessBoard Window showing the ChessLayout in action, and a ChessEdit Window that allows you to modify the ChessBoard.

The ChessBoard Window is a simple collection of slightly modified java.awt.Button Components arranged by a ChessLayout LayoutManager. When you click on the Buttons they turn red to indicate the Button ChessPiece is selected.  Multiple Buttons can be selected at the same time.

The ChessEdit Window allows you to modify both the ChessLayout Parameters that modify the entire ChessLayout, or any Collection of ChessPieces.   There are 3 tabs on the ChessEdit window:

The ChessLayout tab lets you edit the ChessLayout parameters for the entire ChessBoard.  It also has some handy buttons for resizing the Window to its MinimumSize, PreferredSize, or to slowly resize it by a few pixels.

The ChessEdit tab lets you edit the currently selected ChessPieces.  It also has some controls at the bottom for determining what is displayed on each ChessPiece, and to create/delete ChessPieces.

The HTML tab shows the HTML Applet description necessary to for the ChessLayoutTest Applet to create the current layout.  The author used this tab to cut and paste examples into this tutorial.

The Java tab shows the Java code needed to build the current ChessBoard, displaying the ChessPieces with regular java.awt.Buttons.  This tab can be used to cut and paste sample code into your own programs, if you like.  But its really here to show you that complex grid-type layouts can be easily done with very good-looking machine generated, and even better looking hand-generated code.

Try clicking on the ChessPieces to select them, select the various tabs on the ChessEdit, and resize the ChessBoard to get a feel for the operation of the ChessLayout and ChessPiece classes.   Don't worry about messing up the example.  You can just close it, and then click the button on this web page to respawn the original window.  Try the following:

Resize the ChessBoard.  Note that all the Components resize evenly.  We will change that in later examples.  Note that when you make the window really small, some of the Components are obscured to the bottom-right of the Container.  When this happens, you have resized the Container smaller than its MinimumSize.

Select the ChessLayout tab and click on the resizing buttons to see what they do.  Its important to know that the Buttons shown by the ChessLayoutTest always return a MinimumSize of 25 by 25, and a Preferred Size of 50 by 50.

Note that the number of rows and cols shown are the number of rows and columns on the ChessBoard.   You can make these numbers larger if you like, but you can't make them smaller than the number of active rows/columns on the ChessBoard.  If you make them larger, you will initially be creating rows/columns of zero height or width.  This may not do what you expect.

On the ChessLayout tab, inspect the Border values, and change them if you like.   Note that this immediately changes the border between the inner rim of the window, and the outer ChessPieces.

Note the Row and Column parameters in the center of the ChessLayout tab. These change the elasticity of the chess rows and columns, and the distance (gaps) between the rows and columns.  We'll talk more about those in the next section.

Select the ChessPiece tab, then click on several of the Buttons (also called ChessPieces) on the ChessBoard.  You'll see that the ChessPiece tab always reflects the parameter values of the selected ChessPieces.  If all the selected ChessPieces have the same value for a parameter, that parameter value is shown.  If they have different values the keyword Varies is shown to indicate that.

Note that at the bottom of the ChessEdit tab there is a Choice Box to change the display on the ChessBoard buttons.  When select a parameter, you see the buttons on the ChessBoard change to show that parameter.

Try clicking on the create/delete buttons at the bottom right of the ChessEdit tab.  You'll discover that you can add buttons to the ChessBoard, or delete the currently selected buttons.

3. ChessLayout Properties

The basic properties of the ChessLayout itself are:

  1. The integer number of rows, and number of columns in the layout.
  2. The outside border of the layout (an Insets Object).
  3. The row/column gap vectors which specify the gaps (respectively) between the rows and columns of the layout.
  4. The row/column elasticity vectors that specify how the rows and columns should be stretched when there is available space in the layout.

All of these properties may be specified in the ChessLayout constructor and/or they may be set later with set/get methods on the ChessLayout object.

In the examples, these parameters may be viewed and changed in the ChessEdit window under the ChessLayout tab.

3.1 Borders and Row/Column Gaps

The example below modifies the previous example to show the effect of Borders and Row/Column Gaps.

This applet is identical to the example applet in section 2, except that outside borders of 6 pixels are placed around all components, and inside gaps of 10 pixels are placed between the outer row/columns and the inner row/columns.

Note that both the Border and the Gaps are inflexible.  They have exactly the same dimensions regardless of how the window is resized.

3.2 Row/Column Elasticity

In the previous examples, you might have noticed that all the buttons resized evenly, so that they all had the same height and width.  This occurred because they were all initially the same size, and all the rows and columns had the same elasticity.

The applet below is similar to one in section 2, except that the rows and columns differ in their elasticity:

You should note that when this ChessBoard initially appears, it is identical to the first example.  Its appearance is different only when you resize it to be larger than its PreferredSize.

In this example, the row elasticity vector is [1 0 0 1] and the column elasticity vector is [0 1 3 1 0].  You can see this in the ChessEdit window under the ChessLayout tab, in the Row Parameters and Column Parameters.

Note that when you make the window taller than its PreferredSize, rows 0, 3 evenly absorb all the extra height, while rows 1, 2 never become taller.  This is because the ChessBoard stretches proportional to the row Elasticity, and rows 0,3 are infinitely more elastic (value 1) than rows 1,2 (value 0).

When you make the window wider than its PreferredSize, the columns absorb the extra width according to the column elasticity.  Note that the behavior is consistent with the column elasticity values [0 1 3 1 0] shown in the ChessLayout properties.  In particular columns 1, 3 each absorb 1/5 and column 2 absorbs 3/5 of any added window width.

In this example, when the window becomes smaller than its PreferredSize, it operates very differently, and row/column elasticity has no effect.  This is true with most, but not all typical layouts.

3.3 ChessLayout Resizing Rules.

By now, you are probably curious about the ChessLayout resizing rules.  In fact they are very simple, and are given below:

  1. All Components are initially set to their PreferredSize, and positioned on a row/column grid.  The row/column sizes are then adjusted to make the layout as small as possible. 

  2. If the available space is smaller than the Preferred Size in either the row or column dimension, the layout is reduced in size by proportionally shrinking all components in that dimension between their PreferredSize and MinimumSize until the layout is reduced to fit the available space, or all components have been reduced to their MinimumSize.

  3. After all components are initially sized according to rules 1-2, then if any extra space in any dimension remains, all rows and columns are stretched in each dimension proportional to their row/column elasticity values until all extra space is allocated, and all constraints of the layout hold tight.

Note the components are never sized below their MinimumSize, so that when the container size is smaller than the layout MinimumSize, some components may be obscured outside the right/bottom of the container.  The author believes this to be more esthetically pleasing than to resize individual components below their MinimumSize.

Currently layout borders, and row/column gaps, and component insets do not shrink when doing so might avoid placing components outside the layout dimensions.  This might change sometime in the future.

4 ChessPiece Properties

As previously mentioned, in the ChessLayout there is normally a ChessPiece object associated with each component in the container.  This section should help you understand the properties of the ChessPiece object.  All of these properties are accessible under the ChessPiece tab in the ChessEdit window.

Note for experts: Actually, components need not have associated ChessPieces.  If you add a component to a layout without specifying a ChessPiece, then the ChessLayout manger will completely ignore the component, and you can size and position it yourself, however you like.  This may be useful in some advanced applications.

4.1 Horizontal/Vertical Position

Each ChessPiece specifies a horizontal and vertical position for its associated component.  These determine how a component is positioned and sized when the row/column space where its positioned is larger than the component needs to be.

The horizontal position specifies how the component is positioned between the columns on the chessboard.   It may be positioned at the left edge, the right edge, centered, or stretched to fit.

In a similar fashion, the vertical position specifies the component row positioning.  The component may be positioned at the top edge, the bottom edge, centered, or stretched to fit.

In all the previous examples, the vertical/horizontal position of all components was set to STRETCH.  This caused the components to fill all available space between the rows and columns.

The example below shows a 4x4 chessboard with 16 components.  These components demonstrate the 16 possible combinations of vertical and horizontal positioning:

In the example, all components in the same column have the same horizontal positioning, while all components in the same row have the same vertical positioning.  From left to right the horizontal positioning is LEFT, CENTER, STRETCH, RIGHT.  From top to bottom the vertical positioning is TOP, CENTER, STRETCH, BOTTOM.

You can see the positioning of each piece if you select the ChessPiece tab, and at the bottom left set the button display Choice Box to HorizontalPosition or VerticalPosition.  You can then see the horizontal or vertical position of each ChessPiece shown as the Button title.

When you stretch the window beyond its PreferredSize, you should notice that gaps open between the components according to their vertical/horizontal positioning.  Take a few moments to verify that the components resize as they should.

Also note that (in this example) when the chessboard is smaller than its PreferredSize, the vertical/horizontal positioning has no effect.  That's because all the components are the same size, and the rows/columns are sized to fit exactly.  Remember that horizontal and vertical positioning takes effect only when the natural size of the component is smaller than the space where its placed.

4.2 Insets

A ChessPiece may include an Insets object to request extra space above, below, to the left or the right of the component.  The example below modifies the first example by adding an Insets(10,10,10,10) object to the center ChessPiece:

This feature is useful because it allows you to specify Insets for any component without using inheritance.

4.3 MinimumSize and PreferredSize overrides

You may override the MinimumSize and/or PreferredSize for any component on the chessboard by setting its ChessPiece attributes MinimumWidth, MinimumHeight, PreferredWidth, and PreferredHeight.

If you are very clever, you may have noticed that all the components in the section 4.1 example had their MinimumWidth and MinimumHeight set to 30.

The example below is a 2x2 chessboard with only two components:

The upper-left component has a MinimumSize override of 100x100.  Since the ChessLayout does not allow a component to have a smaller PreferredSize than its MinimumSize, its PreferredSize in this example becomes 100x100 as well.

The lower-right component has a MinimumSize override of 50x50, and a PreferredSize Override of 200x200.

Select the ChessPiece tab and click the MinimumSize and PreferredSize buttons at the bottom of the window.   You should notice that when you click on MinimumSize the upper-left component is twice the dimension of the lower-right component.  When you click on PreferredSize the ratio is reversed.

5 Advanced Topics

6 Comparison to GridBagLayout

The Author wrote ChessLayout because he found none of the available Java LayoutManagers adequate to construct complex layouts.  The best of these is the java.awt.GridBagLayout.  However GridBag is complex to use, and the interface code is difficult to follow.  This LayoutManager also performs poorly when the Container is sized smaller than its PreferredSize.

ChessLayout was designed to replace GridBag.  It does everything GridBag does, and adds a few new features.  It also has a much more intuitive interface, and has much nicer sizing behavior.

Below we compare the ChessLayout with the GridBagLayout to generate the example Container given in the GridBagLayout JavaDoc.  The author suggests you inspect the code, resize the two applets, and decide for yourself which behaves more to your liking.

Here is the code for ChessLayoutExample and GridBagLayoutExample