org.nihongoresources.flowlayoutplusplus
Class BetterFlowLayout

java.lang.Object
  extended by org.nihongoresources.flowlayoutplusplus.BetterFlowLayout
All Implemented Interfaces:
java.awt.event.ComponentListener, java.awt.LayoutManager, java.util.EventListener
Direct Known Subclasses:
TestBetterFlowLayout

public class BetterFlowLayout
extends java.lang.Object
implements java.awt.LayoutManager, java.awt.event.ComponentListener

This is a layout manager akin to FlowLayout, except it offers one feature that has been missing from FlowLayout for years: it allows you to force content to be placed on the next line. Why this isn't in FlowLayout is a bit of a mystery, but anyone who ever tried to write their own simple text editor with glyph-level event handling will have probably pulled their hair out in frustration at the lack of a proper layout manager for content. I know I did. So I wrote this one. Enjoy. Technical details: Content for this layout manager has to be added using empty constraints. Normally, you'd add a panel as follows: JPanel panel = new JPanel(); panel.add(new JLabel("label text")); However, that assumes there is no layout manager. Instead, you'll have to use the unconstrained layout managed add method: JPanel panel = new JPanel(); panel.setLayout(new BetterFlowLayout()); panel.add("", new JLabel("label text")); This will ensure the layout manager gets its greasy little mitts on the added component. Also, there are several parameters that can be set on this layout manager, most important of which are the spacing parameters, aking to hgap and vgap in FlowLayout. However, in this layout manager they're called the linespacing and the newblockbreakheight. The linespacing value, set and got with the obviously named methods, determines how many pixels of visual spacing there is between lines. The newblockbreakheight value, set and got with the equally obviously named methods, determines the number of pixels between blocks of content in addition to the linespacing. This means that if line spacing is set to 10 pixels, and the blocl break height is also 10 pixels, there will be 20 pixels of spacing between blocks. Alignment is done per line. This means that horizontal alignment does what you expect it to (except for justify, which is not quite refined enough to work properly) but vertical alignment does not: because it operates per line what it will not do is align all the content to the top, middle or bottom of the container. Instead, it will vertically align within the sentence, so that all components on the line up either line up at the top, line up at the bottom, or line up at center height. set(...) methods all return the layout manager itself, so you can chain set operations during construction: That pretty much covers the explanation, so enjoy having access to this class, it's certainly making a difference in my life...

Author:
Mike "Pomax" Kamermans, http://pomax.nihongoresources.com TODO: since this kind of flow layout is flow-inside-blocks layout, the components should really be contained in block objects, so that useful methods like getBlockCount(), getBlock(int) and getBlockContaining(Component) can be used to set individual block properties (= expert layout control). Alignment and spacing parameters would be assumed the layout manager's during normal component adding, but could be manipulated on a per-block basis.

Field Summary
protected  java.util.Vector<java.awt.Component> components
           
static int DEFAULT_BLOCK_BREAK_HEIGHT
           
static int DEFAULT_LINE_SPACING
           
static int HORIZONTAL_ALIGN_CENTER
          Horizontally aligns components to the center of the screen.
static int HORIZONTAL_ALIGN_JUSTIFY
          Horizontally aligns components so that they are equally spaced out, touching both the left and right of the screen.
static int HORIZONTAL_ALIGN_LEFT
          Horizontally aligns components to the left of the screen.
static int HORIZONTAL_ALIGN_RIGHT
          Horizontally aligns components to the right of the screen.
static int VERTICAL_ALIGN_BOTTOM
          Vertically aligns components to the bottom of the screen.
static int VERTICAL_ALIGN_MIDDLE
          Vertically aligns components to the center of the screen.
static int VERTICAL_ALIGN_TOP
          Vertically aligns components to the top of the screen.
 
Constructor Summary
BetterFlowLayout()
          default construction horizontally aligns left, and vertically aligns to top (because these don't require any calculation offsetting)
BetterFlowLayout(int linespacing, int blockbreakheight, int horizontalAlignment, int verticalAlignment)
          explicitly realigned constructor
 
Method Summary
 void addLayoutComponent(java.lang.String constraints, java.awt.Component component)
          When we add a new component, the preferred size of the container that this layout manager applies to may have duly changed.
 BetterFlowLayout addNewLine()
          Calling this method will make the layout manager add a virtual "newline" to the layout.
 BetterFlowLayout addNewLine(int gapsize)
          Calling this method will make the layout manager add a virtual "newline" to the layout, with a gap after it of the indicated number of pixels instead of the normal line spacing value
 void componentHidden(java.awt.event.ComponentEvent e)
          Does nothing
 void componentMoved(java.awt.event.ComponentEvent e)
          A moved component changes the absolute coordinates for all components
 void componentResized(java.awt.event.ComponentEvent e)
          A resized component means we need to layout everything anew
 void componentShown(java.awt.event.ComponentEvent e)
          Does nothing
 int getBlockBreakHeight()
          Lets you look up which block spacing the layout manager is set to use
 int getHAlign()
          Lets you look at which horizontal alignment is currently being used
 int getLineSpacing()
          Lets you look up which line spacing the layout manager is set to use.
 int getVAlign()
          Lets you look at which vertical alignment is currently being used
 void layoutContainer(java.awt.Container parent)
           
 java.awt.Dimension minimumLayoutSize(java.awt.Container parent)
          The minimum layout size is always the same as the preferred size.
 java.awt.Dimension preferredLayoutSize(java.awt.Container owner)
          A simple implicit constraint: we may never be wider than the container we are a layout manager for, so the reported Dimension will always be parent.width by whatever height this leads to for our contained components.
 void removeLayoutComponent(java.awt.Component comp)
          Removes an indicated component from the list of components in the container.
 BetterFlowLayout setBlockBreakHeight(int blockbreakheight)
          Sets the vertical space to follow a newblock instruction.
 BetterFlowLayout setHAlign(int halign)
          Set the horizontal alignment for "lines" of components for this layout manager.
 BetterFlowLayout setLineSpacing(int linespacing)
          Sets the vertical spacing that should follow a newline instruction.
 BetterFlowLayout setVAlign(int valign)
          Set the vertical alignment inside "lines" of non-uniformly sized components for this layout manager.
 BetterFlowLayout startNewBlock()
          Calling this method will make the layout manager add a virtual "newline" to the layout, followed by a paragraph break.
 BetterFlowLayout startNewBlock(int gapsize)
          Calling this method will make the layout manager add a virtual "newline" to the layout, followed by a paragraph break of the indicated number of pixels, rather than the normal block break value.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

components

protected java.util.Vector<java.awt.Component> components

DEFAULT_LINE_SPACING

public static final int DEFAULT_LINE_SPACING
See Also:
Constant Field Values

DEFAULT_BLOCK_BREAK_HEIGHT

public static final int DEFAULT_BLOCK_BREAK_HEIGHT
See Also:
Constant Field Values

HORIZONTAL_ALIGN_LEFT

public static final int HORIZONTAL_ALIGN_LEFT
Horizontally aligns components to the left of the screen. If a component leads to overflow on the right, it is placed on a new line.

See Also:
Constant Field Values

HORIZONTAL_ALIGN_CENTER

public static final int HORIZONTAL_ALIGN_CENTER
Horizontally aligns components to the center of the screen. If a component leads to overflow on the left and right, it is placed on a new line.

See Also:
Constant Field Values

HORIZONTAL_ALIGN_RIGHT

public static final int HORIZONTAL_ALIGN_RIGHT
Horizontally aligns components to the right of the screen. If a component leads to overflow on the left, it is placed on a new line.

See Also:
Constant Field Values

HORIZONTAL_ALIGN_JUSTIFY

public static final int HORIZONTAL_ALIGN_JUSTIFY
Horizontally aligns components so that they are equally spaced out, touching both the left and right of the screen. If a component leads to the overflow, it is placed on a new line.

See Also:
Constant Field Values

VERTICAL_ALIGN_TOP

public static final int VERTICAL_ALIGN_TOP
Vertically aligns components to the top of the screen. Lines are arranged ordered based on addition (earlier lines show up above later lines).

See Also:
Constant Field Values

VERTICAL_ALIGN_MIDDLE

public static final int VERTICAL_ALIGN_MIDDLE
Vertically aligns components to the center of the screen. Lines are arranged ordered based on addition (earlier lines show up above later lines), but stay centered until vertical overflow occurs, in which case vertical alignment is ignored for further layout management.

See Also:
Constant Field Values

VERTICAL_ALIGN_BOTTOM

public static final int VERTICAL_ALIGN_BOTTOM
Vertically aligns components to the bottom of the screen. Lines are arranged ordered based on addition (earlier lines show up above later lines), but stay bottom aligned vertical overflow occurs, in which case vertical alignment is ignored for further layout management.

See Also:
Constant Field Values
Constructor Detail

BetterFlowLayout

public BetterFlowLayout()
default construction horizontally aligns left, and vertically aligns to top (because these don't require any calculation offsetting)


BetterFlowLayout

public BetterFlowLayout(int linespacing,
                        int blockbreakheight,
                        int horizontalAlignment,
                        int verticalAlignment)
explicitly realigned constructor

Parameters:
horizontalAlignment -
verticalAlignment -
Method Detail

addNewLine

public BetterFlowLayout addNewLine()
Calling this method will make the layout manager add a virtual "newline" to the layout.


addNewLine

public BetterFlowLayout addNewLine(int gapsize)
Calling this method will make the layout manager add a virtual "newline" to the layout, with a gap after it of the indicated number of pixels instead of the normal line spacing value


setLineSpacing

public BetterFlowLayout setLineSpacing(int linespacing)
Sets the vertical spacing that should follow a newline instruction. By default this value is zero.

Parameters:
linespacing - The number of pixels between lines of components

getLineSpacing

public int getLineSpacing()
Lets you look up which line spacing the layout manager is set to use.

Returns:
number of pixels between lines

startNewBlock

public BetterFlowLayout startNewBlock()
Calling this method will make the layout manager add a virtual "newline" to the layout, followed by a paragraph break.


startNewBlock

public BetterFlowLayout startNewBlock(int gapsize)
Calling this method will make the layout manager add a virtual "newline" to the layout, followed by a paragraph break of the indicated number of pixels, rather than the normal block break value.


setBlockBreakHeight

public BetterFlowLayout setBlockBreakHeight(int blockbreakheight)
Sets the vertical space to follow a newblock instruction. This value does not add any space to the top of the managed content, and is only used when a startNewBlock() call forces the layout manager to acknowledge a new content block is started. This value is 15 pixels by default.

Parameters:
blockbreakheight - The number of pixels space above an explicitly created new block

getBlockBreakHeight

public int getBlockBreakHeight()
Lets you look up which block spacing the layout manager is set to use

Returns:
the number of pixels between blocks (note: not corrected for line spacing; this compounds)

setHAlign

public BetterFlowLayout setHAlign(int halign)
Set the horizontal alignment for "lines" of components for this layout manager.

Parameters:
halign - can be any of the predefined HORIZONTAL_ALIGN_xxxxxx constants.

getHAlign

public int getHAlign()
Lets you look at which horizontal alignment is currently being used

Returns:
one of the HORIZONTAL_ALIGN_xxxxxx constants

setVAlign

public BetterFlowLayout setVAlign(int valign)
Set the vertical alignment inside "lines" of non-uniformly sized components for this layout manager. Note that this does not align all the content to the top, middle or bottom of the container, it only applies to vertical alignment within lines of components. For top/middle/bottom alignment of the full content, stick the container this layout manager is a manger for, inside another panel, and give it a single-container layout management that effects the desired valign.

Parameters:
valign - can be any of the predefined VERTICAL_ALIGN_xxxxxx constants.

getVAlign

public int getVAlign()
Lets you look at which vertical alignment is currently being used

Returns:
one of the VERTICAL_ALIGN_xxxxxx constants

addLayoutComponent

public void addLayoutComponent(java.lang.String constraints,
                               java.awt.Component component)
When we add a new component, the preferred size of the container that this layout manager applies to may have duly changed. For now, there are no explicit contraints handled yet, although no doubt this will at some point be useful to have. A component that is added more than once will not be added to the collection a second time, as layout managers position components using setBounds, and a component cannot be in two places at the same time. If you wish to add the same component multiple times, create copies that are deep enough to have unique Component properties.

Specified by:
addLayoutComponent in interface java.awt.LayoutManager

removeLayoutComponent

public void removeLayoutComponent(java.awt.Component comp)
Removes an indicated component from the list of components in the container.

Specified by:
removeLayoutComponent in interface java.awt.LayoutManager

minimumLayoutSize

public java.awt.Dimension minimumLayoutSize(java.awt.Container parent)
The minimum layout size is always the same as the preferred size.

Specified by:
minimumLayoutSize in interface java.awt.LayoutManager

preferredLayoutSize

public java.awt.Dimension preferredLayoutSize(java.awt.Container owner)
A simple implicit constraint: we may never be wider than the container we are a layout manager for, so the reported Dimension will always be parent.width by whatever height this leads to for our contained components.

Specified by:
preferredLayoutSize in interface java.awt.LayoutManager

layoutContainer

public void layoutContainer(java.awt.Container parent)
Specified by:
layoutContainer in interface java.awt.LayoutManager

componentHidden

public void componentHidden(java.awt.event.ComponentEvent e)
Does nothing

Specified by:
componentHidden in interface java.awt.event.ComponentListener

componentShown

public void componentShown(java.awt.event.ComponentEvent e)
Does nothing

Specified by:
componentShown in interface java.awt.event.ComponentListener

componentMoved

public void componentMoved(java.awt.event.ComponentEvent e)
A moved component changes the absolute coordinates for all components

Specified by:
componentMoved in interface java.awt.event.ComponentListener

componentResized

public void componentResized(java.awt.event.ComponentEvent e)
A resized component means we need to layout everything anew

Specified by:
componentResized in interface java.awt.event.ComponentListener