bb.gui
Class GroupPanel

java.lang.Object
  extended by java.awt.Component
      extended by java.awt.Container
          extended by javax.swing.JComponent
              extended by javax.swing.JPanel
                  extended by bb.gui.GroupPanel
All Implemented Interfaces:
ImageObserver, MenuContainer, Serializable, Accessible

public class GroupPanel
extends JPanel

A Swing container that resembles the AWT container Box: it always lays out its Components in a single line (that can be either horizontal or vertical), and it does not allow the LayoutManager to be changed from what it was constructed with.

Besides being an AWT widget, Box is not as easy to use as it could be. In particular, it usually requires the user to add a Border to it to effect spacing with its parent Container. Likewise, it requires the user to add explicit "glue", "strut" or "rigid areas" Components inside it to effect spacing and sizing among its contents.

In contrast, this class is always configured to automatically insert gaps between Components that touch the edge of the parent Container, as well as gaps between Components inside it. Consequently, usage is trivial: an instance is created via one of the factory methods, and then you simply add those Components you really care about to it. For example, here is how you can create a Container that holds a horizontal row of buttons:


        JButton button1 = new JButton("button1");
        JButton button2 = new JButton("button2");
                // then do whatever configuration is need on those buttons, like add ActionListeners

                // can easily create a Container to hold all those buttons as follows:
        GroupPanel panel = GroupPanel.makeHorizontal();
        panel.add( button1 );
        panel.add( button2 );
 

Like typical Java GUI code, this class is not multithread safe: it expects to only be called by EventQueue's dispatch thread. This threading limitation is checked in every public method.

Author:
Brent Boyer
See Also:
Serialized Form

Nested Class Summary
static class GroupPanel.Axis
          Enum of the possible orientations of the axis that components will be laid out along.
static class GroupPanel.UnitTest
          See the Overview page of the project's javadocs for a general description of this unit test class.
 
Nested classes/interfaces inherited from class javax.swing.JPanel
JPanel.AccessibleJPanel
 
Nested classes/interfaces inherited from class javax.swing.JComponent
JComponent.AccessibleJComponent
 
Nested classes/interfaces inherited from class java.awt.Container
Container.AccessibleAWTContainer
 
Nested classes/interfaces inherited from class java.awt.Component
Component.AccessibleAWTComponent, Component.BaselineResizeBehavior, Component.BltBufferStrategy, Component.FlipBufferStrategy
 
Field Summary
private  GroupPanel.Axis axis
          Contract: is never null.
private  GroupLayout groupLayout
          Contract: is never null.
private  GroupLayout.Group groupParallel
          Contract: is never null.
private  GroupLayout.Group groupSequential
          Contract: is never null.
 
Fields inherited from class javax.swing.JComponent
accessibleContext, listenerList, TOOL_TIP_TEXT_KEY, ui, UNDEFINED_CONDITION, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, WHEN_FOCUSED, WHEN_IN_FOCUSED_WINDOW
 
Fields inherited from class java.awt.Component
BOTTOM_ALIGNMENT, CENTER_ALIGNMENT, LEFT_ALIGNMENT, RIGHT_ALIGNMENT, TOP_ALIGNMENT
 
Fields inherited from interface java.awt.image.ImageObserver
ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH
 
Constructor Summary
GroupPanel(GroupPanel.Axis axis, boolean isDoubleBuffered)
          Constructs a new GroupPanel with the specified GroupPanel.Axis and buffering strategy.
 
Method Summary
protected  void addImpl(Component comp, Object constraints, int index)
           
private  void initLayout()
           
static GroupPanel makeHorizontal()
          Returns a new GroupPanel with a horizontal GroupLayout layout manager and a double buffer.
static GroupPanel makeVertical()
          Returns a new GroupPanel with a vertical GroupLayout layout manager and a double buffer.
private  void readObject(ObjectInputStream ois)
          Customizes deserialization.
 void setLayout(LayoutManager mgr)
          Overrides the superclass version to forbid changing the LayoutManager after construction.
 
Methods inherited from class javax.swing.JPanel
getAccessibleContext, getUI, getUIClassID, paramString, setUI, updateUI
 
Methods inherited from class javax.swing.JComponent
addAncestorListener, addNotify, addVetoableChangeListener, computeVisibleRect, contains, createToolTip, disable, enable, firePropertyChange, firePropertyChange, firePropertyChange, fireVetoableChange, getActionForKeyStroke, getActionMap, getAlignmentX, getAlignmentY, getAncestorListeners, getAutoscrolls, getBaseline, getBaselineResizeBehavior, getBorder, getBounds, getClientProperty, getComponentGraphics, getComponentPopupMenu, getConditionForKeyStroke, getDebugGraphicsOptions, getDefaultLocale, getFontMetrics, getGraphics, getHeight, getInheritsPopupMenu, getInputMap, getInputMap, getInputVerifier, getInsets, getInsets, getListeners, getLocation, getMaximumSize, getMinimumSize, getNextFocusableComponent, getPopupLocation, getPreferredSize, getRegisteredKeyStrokes, getRootPane, getSize, getToolTipLocation, getToolTipText, getToolTipText, getTopLevelAncestor, getTransferHandler, getVerifyInputWhenFocusTarget, getVetoableChangeListeners, getVisibleRect, getWidth, getX, getY, grabFocus, isDoubleBuffered, isLightweightComponent, isManagingFocus, isOpaque, isOptimizedDrawingEnabled, isPaintingForPrint, isPaintingTile, isRequestFocusEnabled, isValidateRoot, paint, paintBorder, paintChildren, paintComponent, paintImmediately, paintImmediately, print, printAll, printBorder, printChildren, printComponent, processComponentKeyEvent, processKeyBinding, processKeyEvent, processMouseEvent, processMouseMotionEvent, putClientProperty, registerKeyboardAction, registerKeyboardAction, removeAncestorListener, removeNotify, removeVetoableChangeListener, repaint, repaint, requestDefaultFocus, requestFocus, requestFocus, requestFocusInWindow, requestFocusInWindow, resetKeyboardActions, reshape, revalidate, scrollRectToVisible, setActionMap, setAlignmentX, setAlignmentY, setAutoscrolls, setBackground, setBorder, setComponentPopupMenu, setDebugGraphicsOptions, setDefaultLocale, setDoubleBuffered, setEnabled, setFocusTraversalKeys, setFont, setForeground, setInheritsPopupMenu, setInputMap, setInputVerifier, setMaximumSize, setMinimumSize, setNextFocusableComponent, setOpaque, setPreferredSize, setRequestFocusEnabled, setToolTipText, setTransferHandler, setUI, setVerifyInputWhenFocusTarget, setVisible, unregisterKeyboardAction, update
 
Methods inherited from class java.awt.Container
add, add, add, add, add, addContainerListener, addPropertyChangeListener, addPropertyChangeListener, applyComponentOrientation, areFocusTraversalKeysSet, countComponents, deliverEvent, doLayout, findComponentAt, findComponentAt, getComponent, getComponentAt, getComponentAt, getComponentCount, getComponents, getComponentZOrder, getContainerListeners, getFocusTraversalKeys, getFocusTraversalPolicy, getLayout, getMousePosition, insets, invalidate, isAncestorOf, isFocusCycleRoot, isFocusCycleRoot, isFocusTraversalPolicyProvider, isFocusTraversalPolicySet, layout, list, list, locate, minimumSize, paintComponents, preferredSize, printComponents, processContainerEvent, processEvent, remove, remove, removeAll, removeContainerListener, setComponentZOrder, setFocusCycleRoot, setFocusTraversalPolicy, setFocusTraversalPolicyProvider, transferFocusBackward, transferFocusDownCycle, validate, validateTree
 
Methods inherited from class java.awt.Component
action, add, addComponentListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addInputMethodListener, addKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, bounds, checkImage, checkImage, coalesceEvents, contains, createImage, createImage, createVolatileImage, createVolatileImage, disableEvents, dispatchEvent, enable, enableEvents, enableInputMethods, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, getBackground, getBounds, getColorModel, getComponentListeners, getComponentOrientation, getCursor, getDropTarget, getFocusCycleRootAncestor, getFocusListeners, getFocusTraversalKeysEnabled, getFont, getForeground, getGraphicsConfiguration, getHierarchyBoundsListeners, getHierarchyListeners, getIgnoreRepaint, getInputContext, getInputMethodListeners, getInputMethodRequests, getKeyListeners, getLocale, getLocation, getLocationOnScreen, getMouseListeners, getMouseMotionListeners, getMousePosition, getMouseWheelListeners, getName, getParent, getPeer, getPropertyChangeListeners, getPropertyChangeListeners, getSize, getToolkit, getTreeLock, gotFocus, handleEvent, hasFocus, hide, imageUpdate, inside, isBackgroundSet, isCursorSet, isDisplayable, isEnabled, isFocusable, isFocusOwner, isFocusTraversable, isFontSet, isForegroundSet, isLightweight, isMaximumSizeSet, isMinimumSizeSet, isPreferredSizeSet, isShowing, isValid, isVisible, keyDown, keyUp, list, list, list, location, lostFocus, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, paintAll, postEvent, prepareImage, prepareImage, processComponentEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processMouseWheelEvent, remove, removeComponentListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removePropertyChangeListener, removePropertyChangeListener, repaint, repaint, repaint, resize, resize, setBounds, setBounds, setComponentOrientation, setCursor, setDropTarget, setFocusable, setFocusTraversalKeysEnabled, setIgnoreRepaint, setLocale, setLocation, setLocation, setName, setSize, setSize, show, show, size, toString, transferFocus, transferFocusUpCycle
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

axis

private final GroupPanel.Axis axis
Contract: is never null.


groupLayout

private transient GroupLayout groupLayout
Contract: is never null.


groupParallel

private transient GroupLayout.Group groupParallel
Contract: is never null.


groupSequential

private transient GroupLayout.Group groupSequential
Contract: is never null.

Constructor Detail

GroupPanel

public GroupPanel(GroupPanel.Axis axis,
                  boolean isDoubleBuffered)
           throws IllegalArgumentException,
                  IllegalStateException
Constructs a new GroupPanel with the specified GroupPanel.Axis and buffering strategy.

Parameters:
axis - specifes the direction that components will be laid out along
isDoubleBuffered - a boolean, true for double-buffering, which uses additional memory space to achieve fast, flicker-free updates
Throws:
IllegalArgumentException - if axis is null or is not a recognized value
IllegalStateException - if calling thread is not EventQueue's dispatch thread
Method Detail

makeHorizontal

public static GroupPanel makeHorizontal()
                                 throws IllegalStateException
Returns a new GroupPanel with a horizontal GroupLayout layout manager and a double buffer.

Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread

makeVertical

public static GroupPanel makeVertical()
                               throws IllegalStateException
Returns a new GroupPanel with a vertical GroupLayout layout manager and a double buffer.

Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread

initLayout

private void initLayout()
                 throws IllegalArgumentException
Throws:
IllegalArgumentException

readObject

private void readObject(ObjectInputStream ois)
                 throws IllegalStateException,
                        ClassNotFoundException,
                        IOException,
                        NotActiveException
Customizes deserialization.

Background: the sole issue is that Sun screwed up and failed to make GroupLayout implement Serializable. This class's GroupLayout-related fields are all transient, so no problem here. Unfortunately, our superlass, JPanel, retains a reference to the layout manager and we have no control over its serialization.

The solution is that we use a GroupLayout2 for groupLayout, since it is serializable in some sense. Well, GroupLayout2 does not actually write or read any data during serialization, but at least it does not throw any Exceptions. This enables serialization of this class to proceed without modification (which is why there is no implementation of writeObject).

To deserialize here, this method first calls ObjectInputStream.defaultReadObject(), which restores all of this class's non-transient state as well as its superclass's (including all the components that were added). Then, since it has its axis field available, it only need call initLayout to recreate the GroupLayout-related fields.

Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread
ClassNotFoundException - if the class of a serialized object could not be found
IOException - if an I/O problem occurs
NotActiveException

addImpl

protected void addImpl(Component comp,
                       Object constraints,
                       int index)
Overrides:
addImpl in class Container

setLayout

public void setLayout(LayoutManager mgr)
               throws IllegalStateException
Overrides the superclass version to forbid changing the LayoutManager after construction.

Overrides:
setLayout in class Container
Throws:
IllegalStateException - if construction has finished ()