com.jgoodies.forms.util
Class DefaultUnitConverter

java.lang.Object
  extended by com.jgoodies.forms.util.AbstractUnitConverter
      extended by com.jgoodies.forms.util.DefaultUnitConverter
All Implemented Interfaces:
UnitConverter

public final class DefaultUnitConverter
extends AbstractUnitConverter

This is the default implementation of the UnitConverter interface. It converts horizontal and vertical dialog base units to pixels.

The horizontal base unit is equal to the average width, in pixels, of the characters in the system font; the vertical base unit is equal to the height, in pixels, of the font. Each horizontal base unit is equal to 4 horizontal dialog units; each vertical base unit is equal to 8 vertical dialog units.

The DefaultUnitConverter computes dialog base units using a default font and a test string for the average character width. You can configure the font and the test string via the bound Bean properties defaultDialogFont and averageCharacterWidthTestString. See also Microsoft's suggestion for a custom computation here.

Since the Forms 1.1 this converter logs font information at the CONFIG level.

Version:
$Revision: 54721 $
Author:
Karsten Lentzsch
See Also:
UnitConverter, Size, Sizes

Nested Class Summary
private static class DefaultUnitConverter.DialogBaseUnits
          Describes horizontal and vertical dialog base units.
private  class DefaultUnitConverter.LookAndFeelChangeHandler
          Listens to changes of the Look and Feel and invalidates the cache.
 
Field Summary
private  java.lang.String averageCharWidthTestString
          Holds the string that is used to compute the average character width.
private  java.util.Map cachedDialogBaseUnits
          Maps FontMetrics to horizontal dialog base units.
private  DefaultUnitConverter.DialogBaseUnits cachedGlobalDialogBaseUnits
          Holds the cached global dialog base units that are used if a component is not (yet) available - for example in a Border.
private  java.beans.PropertyChangeSupport changeSupport
          If any PropertyChangeListeners have been registered, the changeSupport field describes them.
private  java.awt.Font defaultDialogFont
          Holds the font that is used to compute the global dialog base units.
private static DefaultUnitConverter instance
          Holds the sole instance that will be lazily instantiated.
private static java.util.logging.Logger LOGGER
           
 
Constructor Summary
private DefaultUnitConverter()
          Constructs a DefaultUnitConverter and registers a listener that handles changes in the look&feel.
 
Method Summary
 void addPropertyChangeListener(java.beans.PropertyChangeListener listener)
          Adds a PropertyChangeListener to the listener list.
 void addPropertyChangeListener(java.lang.String propertyName, java.beans.PropertyChangeListener listener)
          Adds a PropertyChangeListener to the listener list for a specific property.
private  DefaultUnitConverter.DialogBaseUnits computeDialogBaseUnits(java.awt.FontMetrics metrics)
          Computes and returns the horizontal dialog base units.
private  DefaultUnitConverter.DialogBaseUnits computeGlobalDialogBaseUnits()
          Computes the global dialog base units.
private  java.awt.Component createDefaultGlobalComponent()
          Creates and returns a component that is used to lookup the default font metrics.
 java.lang.String getAverageCharacterWidthTestString()
          Returns the string used to compute the average character width.
 java.awt.Font getDefaultDialogFont()
          Lazily creates and returns the dialog font used to compute the dialog base units.
private  DefaultUnitConverter.DialogBaseUnits getDialogBaseUnits(java.awt.Component c)
          Looks up and returns the dialog base units for the given component.
protected  double getDialogBaseUnitsX(java.awt.Component component)
          Returns the cached or computed horizontal dialog base units.
protected  double getDialogBaseUnitsY(java.awt.Component component)
          Returns the cached or computed vertical dialog base units for the given component.
private  DefaultUnitConverter.DialogBaseUnits getGlobalDialogBaseUnits()
          Lazily computes and answer the global dialog base units.
static DefaultUnitConverter getInstance()
          Lazily instantiates and returns the sole instance.
private  void invalidateCaches()
          Invalidates the caches.
private  java.awt.Font lookupDefaultDialogFont()
          Looks up and returns the font used by buttons.
 void removePropertyChangeListener(java.beans.PropertyChangeListener listener)
          Removes a PropertyChangeListener from the listener list.
 void removePropertyChangeListener(java.lang.String propertyName, java.beans.PropertyChangeListener listener)
          Removes a PropertyChangeListener from the listener list for a specific property.
 void setAverageCharacterWidthTestString(java.lang.String newTestString)
          Sets a string that will be used to compute the average character width.
 void setDefaultDialogFont(java.awt.Font newFont)
          Sets a dialog font that will be used to compute the dialog base units.
 
Methods inherited from class com.jgoodies.forms.util.AbstractUnitConverter
centimeterAsPixel, centimeterAsPixel, computeAverageCharWidth, dialogUnitXAsPixel, dialogUnitXAsPixel, dialogUnitYAsPixel, dialogUnitYAsPixel, getDefaultScreenResolution, getScreenResolution, inchAsPixel, inchAsPixel, millimeterAsPixel, millimeterAsPixel, pointAsPixel, pointAsPixel
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

LOGGER

private static final java.util.logging.Logger LOGGER

instance

private static DefaultUnitConverter instance
Holds the sole instance that will be lazily instantiated.


averageCharWidthTestString

private java.lang.String averageCharWidthTestString
Holds the string that is used to compute the average character width. By default this is just "X".


defaultDialogFont

private java.awt.Font defaultDialogFont
Holds the font that is used to compute the global dialog base units. By default it is lazily created in method #getDefaultDialogFont, which in turn looks up a font in method #lookupDefaultDialogFont.


changeSupport

private java.beans.PropertyChangeSupport changeSupport
If any PropertyChangeListeners have been registered, the changeSupport field describes them.

See Also:
addPropertyChangeListener(PropertyChangeListener), addPropertyChangeListener(String, PropertyChangeListener), removePropertyChangeListener(PropertyChangeListener), removePropertyChangeListener(String, PropertyChangeListener)

cachedGlobalDialogBaseUnits

private DefaultUnitConverter.DialogBaseUnits cachedGlobalDialogBaseUnits
Holds the cached global dialog base units that are used if a component is not (yet) available - for example in a Border.


cachedDialogBaseUnits

private java.util.Map cachedDialogBaseUnits
Maps FontMetrics to horizontal dialog base units. This is a second-level cache, that stores dialog base units for a FontMetrics object.

Constructor Detail

DefaultUnitConverter

private DefaultUnitConverter()
Constructs a DefaultUnitConverter and registers a listener that handles changes in the look&feel.

Method Detail

getInstance

public static DefaultUnitConverter getInstance()
Lazily instantiates and returns the sole instance.

Returns:
the lazily instantiated sole instance

getAverageCharacterWidthTestString

public java.lang.String getAverageCharacterWidthTestString()
Returns the string used to compute the average character width. By default it is initialized to "X".

Returns:
the test string used to compute the average character width

setAverageCharacterWidthTestString

public void setAverageCharacterWidthTestString(java.lang.String newTestString)
Sets a string that will be used to compute the average character width. By default it is initialized to "X". You can provide other test strings, for example:

Parameters:
newTestString - the test string to be used
Throws:
java.lang.IllegalArgumentException - if the test string is empty
java.lang.NullPointerException - if the test string is null

getDefaultDialogFont

public java.awt.Font getDefaultDialogFont()
Lazily creates and returns the dialog font used to compute the dialog base units.

Returns:
the font used to compute the dialog base units

setDefaultDialogFont

public void setDefaultDialogFont(java.awt.Font newFont)
Sets a dialog font that will be used to compute the dialog base units.

Parameters:
newFont - the default dialog font to be set

getDialogBaseUnitsX

protected double getDialogBaseUnitsX(java.awt.Component component)
Returns the cached or computed horizontal dialog base units.

Specified by:
getDialogBaseUnitsX in class AbstractUnitConverter
Parameters:
component - a Component that provides the font and graphics
Returns:
the horizontal dialog base units

getDialogBaseUnitsY

protected double getDialogBaseUnitsY(java.awt.Component component)
Returns the cached or computed vertical dialog base units for the given component.

Specified by:
getDialogBaseUnitsY in class AbstractUnitConverter
Parameters:
component - a Component that provides the font and graphics
Returns:
the vertical dialog base units

getGlobalDialogBaseUnits

private DefaultUnitConverter.DialogBaseUnits getGlobalDialogBaseUnits()
Lazily computes and answer the global dialog base units. Should be re-computed if the l&f, platform, or screen changes.

Returns:
a cached DialogBaseUnits object used globally if no container is available

getDialogBaseUnits

private DefaultUnitConverter.DialogBaseUnits getDialogBaseUnits(java.awt.Component c)
Looks up and returns the dialog base units for the given component. In case the component is null the global dialog base units are answered.

Before we compute the dialog base units we check whether they have been computed and cached before - for the same component FontMetrics.

Parameters:
c - the component that provides the graphics object
Returns:
the DialogBaseUnits object for the given component

computeDialogBaseUnits

private DefaultUnitConverter.DialogBaseUnits computeDialogBaseUnits(java.awt.FontMetrics metrics)
Computes and returns the horizontal dialog base units. Honors the font, font size and resolution.

Implementation Note: 14dluY map to 22 pixel for 8pt Tahoma on 96 dpi. I could not yet manage to compute the Microsoft compliant font height. Therefore this method adds a correction value that seems to work well with the vast majority of desktops.

TODO: Revise the computation of vertical base units as soon as there are more information about the original computation in Microsoft environments.

Parameters:
metrics - the FontMetrics used to measure the dialog font
Returns:
the horizontal and vertical dialog base units

computeGlobalDialogBaseUnits

private DefaultUnitConverter.DialogBaseUnits computeGlobalDialogBaseUnits()
Computes the global dialog base units. The current implementation assumes a fixed 8pt font and on 96 or 120 dpi. A better implementation should ask for the main dialog font and should honor the current screen resolution.

Should be re-computed if the l&f, platform, or screen changes.

Returns:
a DialogBaseUnits object used globally if no container is available

lookupDefaultDialogFont

private java.awt.Font lookupDefaultDialogFont()
Looks up and returns the font used by buttons. First, tries to request the button font from the UIManager; if this fails a JButton is created and asked for its font.

Returns:
the font used for a standard button

createDefaultGlobalComponent

private java.awt.Component createDefaultGlobalComponent()
Creates and returns a component that is used to lookup the default font metrics. The current implementation creates a JPanel. Since this panel has no parent, it has no toolkit assigned. And so, requesting the font metrics will end up using the default toolkit and its deprecated method ToolKit#getFontMetrics().

TODO: Consider publishing this method and providing a setter, so that an API user can set a realized component that has a toolkit assigned.

Returns:
a component used to compute the default font metrics

invalidateCaches

private void invalidateCaches()
Invalidates the caches. Resets the global dialog base units and clears the Map from FontMetrics to dialog base units. This is invoked after a change of the look&feel.


addPropertyChangeListener

public void addPropertyChangeListener(java.beans.PropertyChangeListener listener)
Adds a PropertyChangeListener to the listener list. The listener is registered for all bound properties of this class.

If listener is null, no exception is thrown and no action is performed.

Parameters:
listener - the PropertyChangeListener to be added
See Also:
removePropertyChangeListener(PropertyChangeListener), removePropertyChangeListener(String, PropertyChangeListener), addPropertyChangeListener(String, PropertyChangeListener)

removePropertyChangeListener

public void removePropertyChangeListener(java.beans.PropertyChangeListener listener)
Removes a PropertyChangeListener from the listener list. This method should be used to remove PropertyChangeListeners that were registered for all bound properties of this class.

If listener is null, no exception is thrown and no action is performed.

Parameters:
listener - the PropertyChangeListener to be removed
See Also:
addPropertyChangeListener(PropertyChangeListener), addPropertyChangeListener(String, PropertyChangeListener), removePropertyChangeListener(String, PropertyChangeListener)

addPropertyChangeListener

public void addPropertyChangeListener(java.lang.String propertyName,
                                      java.beans.PropertyChangeListener listener)
Adds a PropertyChangeListener to the listener list for a specific property. The specified property may be user-defined.

Note that if this Model is inheriting a bound property, then no event will be fired in response to a change in the inherited property.

If listener is null, no exception is thrown and no action is performed.

Parameters:
propertyName - one of the property names listed above
listener - the PropertyChangeListener to be added
See Also:
removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener), addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)

removePropertyChangeListener

public void removePropertyChangeListener(java.lang.String propertyName,
                                         java.beans.PropertyChangeListener listener)
Removes a PropertyChangeListener from the listener list for a specific property. This method should be used to remove PropertyChangeListeners that were registered for a specific bound property.

If listener is null, no exception is thrown and no action is performed.

Parameters:
propertyName - a valid property name
listener - the PropertyChangeListener to be removed
See Also:
addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener), removePropertyChangeListener(java.beans.PropertyChangeListener)