org.jdesktop.swingx
Class MultiSplitLayout

java.lang.Object
  extended by org.jdesktop.swingx.MultiSplitLayout
All Implemented Interfaces:
LayoutManager

public class MultiSplitLayout
extends Object
implements LayoutManager

The MultiSplitLayout layout manager recursively arranges its components in row and column groups called "Splits". Elements of the layout are separated by gaps called "Dividers". The overall layout is defined with a simple tree model whose nodes are instances of MultiSplitLayout.Split, MultiSplitLayout.Divider, and MultiSplitLayout.Leaf. Named Leaf nodes represent the space allocated to a component that was added with a constraint that matches the Leaf's name. Extra space is distributed among row/column siblings according to their 0.0 to 1.0 weight. If no weights are specified then the last sibling always gets all of the extra space, or space reduction.

Although MultiSplitLayout can be used with any Container, it's the default layout manager for MultiSplitPane. MultiSplitPane supports interactively dragging the Dividers, accessibility, and other features associated with split panes.

All properties in this class are bound: when a properties value is changed, all PropertyChangeListeners are fired.

See Also:
JXMultiSplitPane

Nested Class Summary
static class MultiSplitLayout.ColSplit
           
static class MultiSplitLayout.Divider
          Models a single vertical/horiztonal divider.
static class MultiSplitLayout.InvalidLayoutException
          The specified Node is either the wrong type or was configured incorrectly.
static class MultiSplitLayout.Leaf
          Models a java.awt Component child.
static class MultiSplitLayout.Node
          Base class for the nodes that model a MultiSplitLayout.
static class MultiSplitLayout.RowSplit
           
static class MultiSplitLayout.Split
          Defines a vertical or horizontal subdivision into two or more tiles.
 
Field Summary
static int DEFAULT_LAYOUT
           
static int NO_MIN_SIZE_LAYOUT
           
static int USER_MIN_SIZE_LAYOUT
           
 
Constructor Summary
MultiSplitLayout()
          Create a MultiSplitLayout with a default model with a single Leaf node named "default".
MultiSplitLayout(boolean layoutByWeight)
          Create a MultiSplitLayout with a default model with a single Leaf node named "default".
MultiSplitLayout(MultiSplitLayout.Node model)
          Create a MultiSplitLayout with the specified model.
 
Method Summary
 void addLayoutComponent(String name, Component child)
          Add a component to this MultiSplitLayout.
 void addPropertyChangeListener(PropertyChangeListener listener)
           
 void displayNode(String name, boolean visible)
          Show/Hide nodes.
 MultiSplitLayout.Divider dividerAt(int x, int y)
          Return the Divider whose bounds contain the specified point, or null if there isn't one.
 List<MultiSplitLayout.Divider> dividersThatOverlap(Rectangle r)
          Return the Dividers whose bounds overlap the specified Rectangle.
 Component getComponentForNode(MultiSplitLayout.Node n)
          Get the component associated with a MultiSplitLayout.Node
 int getDividerSize()
          Returns the width of Dividers in Split rows, and the height of Dividers in Split columns.
 boolean getFloatingDividers()
           
 boolean getLayoutByWeight()
          Get the layoutByWeight falg.
 int getLayoutMode()
          Get the layout mode
 MultiSplitLayout.Node getModel()
          Return the root of the tree of Split, Leaf, and Divider nodes that define this layout.
 String getNameForComponent(Component child)
          Get the name used to map a component
 MultiSplitLayout.Node getNodeForComponent(Component comp)
          Get the MultiSplitLayout.Node associated with a component
 MultiSplitLayout.Node getNodeForComponent(MultiSplitLayout.Split split, Component comp)
          Get the MultiSplitLayout.Node associated with a component
 MultiSplitLayout.Node getNodeForName(MultiSplitLayout.Split split, String name)
          Get the MultiSplitLayout.Node associated with a component
 MultiSplitLayout.Node getNodeForName(String name)
          Get the MultiSplitLayout.Node associated with a component
 PropertyChangeListener[] getPropertyChangeListeners()
           
 boolean getRemoveDividers()
           
 int getUserMinSize()
          Get the minimum node size
 boolean hasModel()
          Is there a valid model for the layout?
 void layoutByWeight(Container parent)
          Set the size of the child components to match the weights of the children.
 void layoutContainer(Container parent)
          Compute the bounds of all of the Split/Divider/Leaf Nodes in the layout model, and then set the bounds of each child component with a matching Leaf Node.
 Dimension maximumNodeSize(MultiSplitLayout.Node root)
          Get the maximum size of this node.
 Dimension minimumLayoutSize(Container parent)
          Calculates the minimum size dimensions for the specified container, given the components it contains.
 Dimension minimumNodeSize(MultiSplitLayout.Node root)
          Get the minimum size of this node.
static MultiSplitLayout.Node parseModel(String s)
          A convenience method that converts a string to a MultiSplitLayout model (a tree of Nodes) using a a simple syntax.
 Dimension preferredLayoutSize(Container parent)
          Calculates the preferred size dimensions for the specified container, given the components it contains.
static void printModel(MultiSplitLayout.Node root)
          Print the tree with enough detail for simple debugging.
 void removeLayoutComponent(Component child)
          Removes the specified component from the layout.
 void removeLayoutNode(String name)
          Removes the specified node from the layout.
 void removePropertyChangeListener(PropertyChangeListener listener)
           
 void setDividerSize(int dividerSize)
          Sets the width of Dividers in Split rows, and the height of Dividers in Split columns.
 void setFloatingDividers(boolean floatingDividers)
          If true, Leaf node bounds match the corresponding component's preferred size and Splits/Dividers are resized accordingly.
 void setLayoutByWeight(boolean state)
          Sset the layoutByWeight falg.
 void setLayoutMode(int layoutMode)
          Set the layout mode.
 void setModel(MultiSplitLayout.Node model)
          Set the root of the tree of Split, Leaf, and Divider nodes that define this layout.
 void setRemoveDividers(boolean removeDividers)
          If true, the next divider is removed when a component is removed from the layout.
 void setUserMinSize(int minSize)
          Set the user defined minimum size support in the USER_MIN_SIZE_LAYOUT layout mode.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

DEFAULT_LAYOUT

public static final int DEFAULT_LAYOUT
See Also:
Constant Field Values

NO_MIN_SIZE_LAYOUT

public static final int NO_MIN_SIZE_LAYOUT
See Also:
Constant Field Values

USER_MIN_SIZE_LAYOUT

public static final int USER_MIN_SIZE_LAYOUT
See Also:
Constant Field Values
Constructor Detail

MultiSplitLayout

public MultiSplitLayout()
Create a MultiSplitLayout with a default model with a single Leaf node named "default". #see setModel


MultiSplitLayout

public MultiSplitLayout(boolean layoutByWeight)
Create a MultiSplitLayout with a default model with a single Leaf node named "default".

Parameters:
layoutByWeight - if true the layout is initialized in proportion to the node weights rather than the component preferred sizes. #see setModel

MultiSplitLayout

public MultiSplitLayout(MultiSplitLayout.Node model)
Create a MultiSplitLayout with the specified model. #see setModel

Method Detail

layoutByWeight

public void layoutByWeight(Container parent)
Set the size of the child components to match the weights of the children. If the components to not all specify a weight then the available layout space is divided equally between the components.


getComponentForNode

public Component getComponentForNode(MultiSplitLayout.Node n)
Get the component associated with a MultiSplitLayout.Node

Parameters:
n - the layout node
Returns:
the component handled by the layout or null if not found

getNodeForComponent

public MultiSplitLayout.Node getNodeForComponent(Component comp)
Get the MultiSplitLayout.Node associated with a component

Parameters:
comp - the component being positioned by the layout
Returns:
the node associated with the component

getNodeForName

public MultiSplitLayout.Node getNodeForName(String name)
Get the MultiSplitLayout.Node associated with a component

Parameters:
name - the name used to associate a component with the layout
Returns:
the node associated with the component

getNameForComponent

public String getNameForComponent(Component child)
Get the name used to map a component

Parameters:
child - the component
Returns:
the name used to map the component or null if no mapping is found

getNodeForComponent

public MultiSplitLayout.Node getNodeForComponent(MultiSplitLayout.Split split,
                                                 Component comp)
Get the MultiSplitLayout.Node associated with a component

Parameters:
split - the layout split that owns the requested node
comp - the component being positioned by the layout
Returns:
the node associated with the component

getNodeForName

public MultiSplitLayout.Node getNodeForName(MultiSplitLayout.Split split,
                                            String name)
Get the MultiSplitLayout.Node associated with a component

Parameters:
split - the layout split that owns the requested node
name - the name used to associate a component with the layout
Returns:
the node associated with the component

hasModel

public boolean hasModel()
Is there a valid model for the layout?

Returns:
true if there is a model

addPropertyChangeListener

public void addPropertyChangeListener(PropertyChangeListener listener)

removePropertyChangeListener

public void removePropertyChangeListener(PropertyChangeListener listener)

getPropertyChangeListeners

public PropertyChangeListener[] getPropertyChangeListeners()

getModel

public MultiSplitLayout.Node getModel()
Return the root of the tree of Split, Leaf, and Divider nodes that define this layout.

Returns:
the value of the model property
See Also:
setModel(org.jdesktop.swingx.MultiSplitLayout.Node)

setModel

public void setModel(MultiSplitLayout.Node model)
Set the root of the tree of Split, Leaf, and Divider nodes that define this layout. The model can be a Split node (the typical case) or a Leaf. The default value of this property is a Leaf named "default".

Parameters:
model - the root of the tree of Split, Leaf, and Divider node
Throws:
IllegalArgumentException - if model is a Divider or null
See Also:
getModel()

getDividerSize

public int getDividerSize()
Returns the width of Dividers in Split rows, and the height of Dividers in Split columns.

Returns:
the value of the dividerSize property
See Also:
setDividerSize(int)

setDividerSize

public void setDividerSize(int dividerSize)
Sets the width of Dividers in Split rows, and the height of Dividers in Split columns. The default value of this property is the same as for JSplitPane Dividers.

Parameters:
dividerSize - the size of dividers (pixels)
Throws:
IllegalArgumentException - if dividerSize < 0
See Also:
getDividerSize()

getFloatingDividers

public boolean getFloatingDividers()
Returns:
the value of the floatingDividers property
See Also:
setFloatingDividers(boolean)

setFloatingDividers

public void setFloatingDividers(boolean floatingDividers)
If true, Leaf node bounds match the corresponding component's preferred size and Splits/Dividers are resized accordingly. If false then the Dividers define the bounds of the adjacent Split and Leaf nodes. Typically this property is set to false after the (MultiSplitPane) user has dragged a Divider.

See Also:
getFloatingDividers()

getRemoveDividers

public boolean getRemoveDividers()
Returns:
the value of the removeDividers property
See Also:
setRemoveDividers(boolean)

setRemoveDividers

public void setRemoveDividers(boolean removeDividers)
If true, the next divider is removed when a component is removed from the layout. If false, only the node itself is removed. Normally the next divider should be removed from the layout when a component is removed.

Parameters:
removeDividers - true to removed the next divider whena component is removed from teh layout

addLayoutComponent

public void addLayoutComponent(String name,
                               Component child)
Add a component to this MultiSplitLayout. The name should match the name property of the Leaf node that represents the bounds of child. After layoutContainer() recomputes the bounds of all of the nodes in the model, it will set this child's bounds to the bounds of the Leaf node with name. Note: if a component was already added with the same name, this method does not remove it from its parent.

Specified by:
addLayoutComponent in interface LayoutManager
Parameters:
name - identifies the Leaf node that defines the child's bounds
child - the component to be added
See Also:
removeLayoutComponent(java.awt.Component)

removeLayoutComponent

public void removeLayoutComponent(Component child)
Removes the specified component from the layout.

Specified by:
removeLayoutComponent in interface LayoutManager
Parameters:
child - the component to be removed
See Also:
addLayoutComponent(java.lang.String, java.awt.Component)

removeLayoutNode

public void removeLayoutNode(String name)
Removes the specified node from the layout.

Parameters:
name - the name of the component to be removed
See Also:
addLayoutComponent(java.lang.String, java.awt.Component)

displayNode

public void displayNode(String name,
                        boolean visible)
Show/Hide nodes. Any dividers that are no longer required due to one of the nodes being made visible/invisible are also shown/hidder. The visibility of the component managed by the node is also changed by this method

Parameters:
name - the node name
visible - the new node visible state

minimumNodeSize

public Dimension minimumNodeSize(MultiSplitLayout.Node root)
Get the minimum size of this node. Sums the minumum sizes of rows or columns to get the overall minimum size for the layout node, including the dividers.

Parameters:
root - the node whose size is required.
Returns:
the minimum size.

maximumNodeSize

public Dimension maximumNodeSize(MultiSplitLayout.Node root)
Get the maximum size of this node. Sums the minumum sizes of rows or columns to get the overall maximum size for the layout node, including the dividers.

Parameters:
root - the node whose size is required.
Returns:
the minimum size.

preferredLayoutSize

public Dimension preferredLayoutSize(Container parent)
Description copied from interface: java.awt.LayoutManager
Calculates the preferred size dimensions for the specified container, given the components it contains.

Specified by:
preferredLayoutSize in interface LayoutManager
Parameters:
parent - the container to be laid out
See Also:
LayoutManager.minimumLayoutSize(java.awt.Container)

minimumLayoutSize

public Dimension minimumLayoutSize(Container parent)
Description copied from interface: java.awt.LayoutManager
Calculates the minimum size dimensions for the specified container, given the components it contains.

Specified by:
minimumLayoutSize in interface LayoutManager
Parameters:
parent - the component to be laid out
See Also:
LayoutManager.preferredLayoutSize(java.awt.Container)

getLayoutMode

public int getLayoutMode()
Get the layout mode

Returns:
current layout mode

setLayoutMode

public void setLayoutMode(int layoutMode)
Set the layout mode. By default this layout uses the preferred and minimum sizes of the child components. To ignore the minimum size set the layout mode to MultiSplitLayout.LAYOUT_NO_MIN_SIZE.

Parameters:
layoutMode - the layout mode
  • DEFAULT_LAYOUT - use the preferred and minimum sizes when sizing the children
  • LAYOUT_NO_MIN_SIZE - ignore the minimum size when sizing the children

getUserMinSize

public int getUserMinSize()
Get the minimum node size

Returns:
the minimum size

setUserMinSize

public void setUserMinSize(int minSize)
Set the user defined minimum size support in the USER_MIN_SIZE_LAYOUT layout mode.

Parameters:
minSize - the new minimum size

getLayoutByWeight

public boolean getLayoutByWeight()
Get the layoutByWeight falg. If the flag is true the layout initializes itself using the model weights

Returns:
the layoutByWeight

setLayoutByWeight

public void setLayoutByWeight(boolean state)
Sset the layoutByWeight falg. If the flag is true the layout initializes itself using the model weights

Parameters:
state - the new layoutByWeight to set

layoutContainer

public void layoutContainer(Container parent)
Compute the bounds of all of the Split/Divider/Leaf Nodes in the layout model, and then set the bounds of each child component with a matching Leaf Node.

Specified by:
layoutContainer in interface LayoutManager
Parameters:
parent - the container to be laid out

dividerAt

public MultiSplitLayout.Divider dividerAt(int x,
                                          int y)
Return the Divider whose bounds contain the specified point, or null if there isn't one.

Parameters:
x - x coordinate
y - y coordinate
Returns:
the Divider at x,y

dividersThatOverlap

public List<MultiSplitLayout.Divider> dividersThatOverlap(Rectangle r)
Return the Dividers whose bounds overlap the specified Rectangle.

Parameters:
r - target Rectangle
Returns:
the Dividers that overlap r
Throws:
IllegalArgumentException - if the Rectangle is null

parseModel

public static MultiSplitLayout.Node parseModel(String s)
A convenience method that converts a string to a MultiSplitLayout model (a tree of Nodes) using a a simple syntax. Nodes are represented by parenthetical expressions whose first token is one of ROW/COLUMN/LEAF. ROW and COLUMN specify horizontal and vertical Split nodes respectively, LEAF specifies a Leaf node. A Leaf's name and weight can be specified with attributes, name=myLeafName weight=myLeafWeight. Similarly, a Split's weight can be specified with weight=mySplitWeight.

For example, the following expression generates a horizontal Split node with three children: the Leafs named left and right, and a Divider in between:

 (ROW (LEAF name=left) (LEAF name=right weight=1.0))
 

Dividers should not be included in the string, they're added automatcially as needed. Because Leaf nodes often only need to specify a name, one can specify a Leaf by just providing the name. The previous example can be written like this:

 (ROW left (LEAF name=right weight=1.0))
 

Here's a more complex example. One row with three elements, the first and last of which are columns with two leaves each:

 (ROW (COLUMN weight=0.5 left.top left.bottom)
      (LEAF name=middle)
      (COLUMN weight=0.5 right.top right.bottom))
 

This syntax is not intended for archiving or configuration files . It's just a convenience for examples and tests.

Returns:
the Node root of a tree based on s.

printModel

public static void printModel(MultiSplitLayout.Node root)
Print the tree with enough detail for simple debugging.