summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components
diff options
context:
space:
mode:
authorBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
committerBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
commit40a9d99496e098562f090fb7ffce9e749011b131 (patch)
tree437df24d65470582e943e494a52db8ed65a881ae /projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components
parentff072dfe782f6f22123cd4ba050828d35c0d0fbd (diff)
Formatting pass
Diffstat (limited to 'projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components')
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AbsoluteLayout.java61
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlphaTextField.java593
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlternatingRowCellRenderer.java157
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterFlowLayout.java952
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterRootLayout.java268
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterTableUI.java176
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ButtonPanel.java1066
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/CheckButtonPanel.java455
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellEditor.java88
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellRenderer.java79
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ComboBoxCellRenderer.java44
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/DateTextField.java1098
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/FormattedCellRenderer.java460
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/IconCellRenderer.java1272
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ImagePanel.java91
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/InfoPanel.java2908
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyDelayTimer.java301
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyableCellEditor.java566
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/LineWrappingRenderer.java225
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/MultiLineLabel.java163
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/NumericTextField.java754
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTable.java927
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTableModel.java538
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/RadioButtonPanel.java278
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartPasswordField.java456
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartTextField.java398
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/StatusButtonPanel.java435
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TintedImageFilter.java122
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeChooser.java1134
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeTableCellRenderer.java305
30 files changed, 7663 insertions, 8707 deletions
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AbsoluteLayout.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AbsoluteLayout.java
index 1fef587..579a595 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AbsoluteLayout.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AbsoluteLayout.java
@@ -25,50 +25,43 @@ import java.awt.LayoutManager;
import java.io.Serializable;
/**
- * AbsoluteLayout specifies that all components in the
- * container will be placed according to their size
- * and their location relative to the container's origin. <br><br>
+ * AbsoluteLayout specifies that all components in the container will be placed
+ * according to their size and their location relative to the container's
+ * origin. <br>
+ * <br>
*
- * You can achieve the same effect by setting a container's
- * layout manager to null, but this class allows you to subclass
- * it if you need specific control or functionality.
+ * You can achieve the same effect by setting a container's layout manager to
+ * null, but this class allows you to subclass it if you need specific control
+ * or functionality.
*
* @author michael@mpowers.net
* @author $Author: cgruber $
* @version $Revision: 904 $
*/
-public class AbsoluteLayout implements LayoutManager, Serializable
-{
- public void addLayoutComponent(String name,
- Component comp)
- {
- }
+public class AbsoluteLayout implements LayoutManager, Serializable {
+ public void addLayoutComponent(String name, Component comp) {
+ }
- public void removeLayoutComponent(Component comp)
- {
- }
+ public void removeLayoutComponent(Component comp) {
+ }
- public Dimension preferredLayoutSize(Container parent)
- {
- return minimumLayoutSize( parent );
- }
+ public Dimension preferredLayoutSize(Container parent) {
+ return minimumLayoutSize(parent);
+ }
- public Dimension minimumLayoutSize(Container parent)
- {
- int width = 0;
- int height = 0;
+ public Dimension minimumLayoutSize(Container parent) {
+ int width = 0;
+ int height = 0;
- Component[] c = parent.getComponents();
- for ( int i = 0; i < c.length; i++ )
- {
- width = Math.max( width, c[i].getLocation().x + c[i].getBounds().width );
- height = Math.max( height, c[i].getLocation().y + c[i].getBounds().height );
- }
+ Component[] c = parent.getComponents();
+ for (int i = 0; i < c.length; i++) {
+ width = Math.max(width, c[i].getLocation().x + c[i].getBounds().width);
+ height = Math.max(height, c[i].getLocation().y + c[i].getBounds().height);
+ }
- return new Dimension( width, height );
- }
+ return new Dimension(width, height);
+ }
- public void layoutContainer(Container parent)
- {
- }
+ public void layoutContainer(Container parent) {
+ }
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlphaTextField.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlphaTextField.java
index c36f5e2..9300d35 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlphaTextField.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlphaTextField.java
@@ -19,317 +19,286 @@ License along with this library; if not, see http://www.gnu.org
package net.wotonomy.ui.swing.components;
/**
-* AlphaTextField is a "smart" text field that restricts the user's input. The
-* input can be restricted to alphabetic, alphanumeric, or all characters. The
-* maximum number of characters can also be limited.
-* The defaults for this component is alphabetic only string of unlimited length.
-*
-* @author rob@straylight.princeton.com
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
-public class AlphaTextField extends SmartTextField
-{
-
-/*******************************
-* CONSTANTS
-*******************************/
-
-/**
-* Sets the input to alphabetic characters only. The characters "a-z" and "A-Z"
-* are the only valid characters. All other characters will be ignored.
-* @see #getAlphaType()
-*/
- public static final int ALPHABETIC = 0;
-
-/**
-* Sets the input to alphanumeric characters only. The characters "a-z", "A-Z"
-* and "0-9" are the only valid characters. All other characters will be ignored.
-* @see #getAlphaType()
-*/
- public static final int ALPHANUMERIC = 1;
-
-/**
-* Sets the input to alphanumeric characters and a few special characters only.
-* The valid characters are "a-z", "A-Z", "0-9", space, "-", "_", "\", and ":".
-* This is helpful for file names (with paths) as input strings.
-* All other characters will be ignored.
-* @see #getAlphaType()
-*/
- public static final int ALPHANUMERIC_PLUS = 2;
-
-/**
-* Sets the input to all characters without restriction.
-* @see #getAlphaType()
-*/
- public static final int ALL = 3;
-
-
-/*******************************
-* DATA MEMBERS
-*******************************/
-
- // The level of input restrictions, defaults to ALPHABETIC
- private int alphaType;
-
- // The maximum length of the input string, defaults to 0, no maximum
- private int stringLength;
-
-
-/*******************************
-* PUBLIC METHODS
-*******************************/
-
-/**
-* The default constructor of this class. The default string of this text
-* field is set to the empty string (""). The maximum length is set to 0,
-* which specifies no limit.
-*/
- public AlphaTextField()
- {
- this("", 0);
- }
-
-/**
-* Constructor of this class with the initial text of the text field specified.
-* The maximum length is set to 0, which specifies no limit.
-* @param text Initial text of the text field.
-*/
- public AlphaTextField(String text)
- {
- this(text, 0);
- }
-
-/**
-* Constructor of this class with width (in columns) of the text field specified.
-* The initial text is set to the empty string (""). The maximum length is set
-* to 0, which specifies no limit.
-* @param columns The width of the text field in characters.
-*/
- public AlphaTextField(int columns)
- {
- this("", columns);
- }
-
-/**
-* Constructor of this class with width (in columns) and initial text of the
-* text field specified. The maximum length is set to 0, which specifies no limit.
-* @param text Initial text of the text field.
-* @param columns The width of the text field in characters.
-*/
- public AlphaTextField(String text, int columns)
- {
- super(text, columns);
- }
-
-/**
-* Constructor that allows the user to set the Alpha type of the text field
-* and the maximum string length.
-* @param anAlphaType The character restriction type.
-* @param aLength The maximum number of characters allowed in the string.
-*/
- public AlphaTextField(int anAlphaType, int aLength)
- {
- super( "", 0 );
- setAlphaType( anAlphaType );
- setStringLength( aLength );
- }
-
-/**
-* Gets the current restriction type of this text field.
-* @see #ALPHABETIC
-* @see #ALPHANUMERIC
-* @see #ALPHANUMERIC_PLUS
-* @see #ALL
-* @return The current restriction type as defined by the constansts of this class.
-*/
- public int getAlphaType()
- {
- return alphaType;
- }
-
-/**
-* Sets the restriction type of this text field.
-* @see #ALPHABETIC
-* @see #ALPHANUMERIC
-* @see #ALPHANUMERIC_PLUS
-* @see #ALL
-* @param newAlphaType The restriction of this text field.
-*/
- public void setAlphaType(int newAlphaType)
- {
- switch (newAlphaType)
- {
- case ALPHABETIC:
- case ALPHANUMERIC:
- case ALPHANUMERIC_PLUS:
- case ALL:
- {
- alphaType = newAlphaType;
- break;
- }
- default:
- {
- alphaType = ALPHABETIC;
- break;
- }
- }
- }
-
-/**
-* Sets the maximum string length of this text field. If the length is set to
-* zero, then there is no limit. The default string length is zero. Negative
-* sizes will set the length to zero.
-* @param newStringLength The maximum length of the string that the user can input.
-*/
- public void setStringLength(int newStringLength)
- {
- if (newStringLength < 0)
- {
- stringLength = 0;
- }
- else
- {
- stringLength = newStringLength;
- }
- }
-
-/**
-* Gets the current length of the maximum string size the user can enter.
-* @return The maximum length the string of the text field can be.
-*/
- public int getStringLength()
- {
- return stringLength;
- }
-
-
-/*******************************
-* PROTECTED METHODS
-*******************************/
-
- protected boolean isValidCharacter(char aChar)
- {
- // if its a non-printable character, then its ok
- if ((aChar < ' ') || (aChar > '~'))
- {
- return true;
- }
-
- // can only be a printable character now, check it for validation
- return isValidCharacterType(aChar);
- }
-
- protected boolean isValidString(String aString)
- {
- if (aString.length() > stringLength)
- {
- return false;
- }
-
- for (int i = 0; i < aString.length(); ++i)
- {
- if (!(isValidCharacterType(aString.charAt(i))))
- {
- return false;
- }
- }
-
- return true;
- }
-
- protected void postProcessing()
- {
- // No need to do anything.
- }
-
-
-/*******************************
-* PROTECTED METHODS
-*******************************/
-
- private boolean isValidCharacterType(char aChar)
- {
- switch (alphaType)
- {
- case ALPHABETIC:
- {
- if (!(isValidAlphabeticCharacter(aChar)))
- {
- return false;
- }
- break;
- }
- case ALPHANUMERIC:
- {
- if (!(isValidAlphanumericCharacter(aChar)))
- {
- return false;
- }
- break;
- }
- case ALPHANUMERIC_PLUS:
- {
- if (!(isValidAlphanumericPlusCharacter(aChar)))
- {
- return false;
- }
- break;
- }
- case ALL:
- {
- if (!(isValidAllCharacter(aChar)))
- {
- return false;
- }
- break;
- }
- default:
- {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean isValidAlphabeticCharacter(char aChar)
- {
- if (((aChar < 'A') || (aChar > 'Z')) && ((aChar < 'a') || (aChar > 'z')))
- {
- return false;
- }
- return true;
- }
-
- private boolean isValidAlphanumericCharacter(char aChar)
- {
- if (((aChar < 'A') || (aChar > 'Z')) && ((aChar < 'a') || (aChar > 'z')) && ((aChar < '0') || (aChar > '9')))
- {
- return false;
- }
- return true;
- }
-
- private boolean isValidAlphanumericPlusCharacter(char aChar)
- {
- if (((aChar < 'A') || (aChar > 'Z')) && ((aChar < 'a') || (aChar > 'z')) && ((aChar < '0') || (aChar > '9')))
- {
- if ((aChar != ' ') && (aChar != '_') && (aChar != '-') && (aChar != ':') && (aChar != '\\'))
- {
- return false;
- }
- }
- return true;
- }
-
- private boolean isValidAllCharacter(char aChar)
- {
- if ((aChar < ' ') || (aChar > '~'))
- {
- return false;
- }
- return true;
- }
+ * AlphaTextField is a "smart" text field that restricts the user's input. The
+ * input can be restricted to alphabetic, alphanumeric, or all characters. The
+ * maximum number of characters can also be limited. The defaults for this
+ * component is alphabetic only string of unlimited length.
+ *
+ * @author rob@straylight.princeton.com
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
+public class AlphaTextField extends SmartTextField {
+
+ /*******************************
+ * CONSTANTS
+ *******************************/
+
+ /**
+ * Sets the input to alphabetic characters only. The characters "a-z" and "A-Z"
+ * are the only valid characters. All other characters will be ignored.
+ *
+ * @see #getAlphaType()
+ */
+ public static final int ALPHABETIC = 0;
+
+ /**
+ * Sets the input to alphanumeric characters only. The characters "a-z", "A-Z"
+ * and "0-9" are the only valid characters. All other characters will be
+ * ignored.
+ *
+ * @see #getAlphaType()
+ */
+ public static final int ALPHANUMERIC = 1;
+
+ /**
+ * Sets the input to alphanumeric characters and a few special characters only.
+ * The valid characters are "a-z", "A-Z", "0-9", space, "-", "_", "\", and ":".
+ * This is helpful for file names (with paths) as input strings. All other
+ * characters will be ignored.
+ *
+ * @see #getAlphaType()
+ */
+ public static final int ALPHANUMERIC_PLUS = 2;
+
+ /**
+ * Sets the input to all characters without restriction.
+ *
+ * @see #getAlphaType()
+ */
+ public static final int ALL = 3;
+
+ /*******************************
+ * DATA MEMBERS
+ *******************************/
+
+ // The level of input restrictions, defaults to ALPHABETIC
+ private int alphaType;
+
+ // The maximum length of the input string, defaults to 0, no maximum
+ private int stringLength;
+
+ /*******************************
+ * PUBLIC METHODS
+ *******************************/
+
+ /**
+ * The default constructor of this class. The default string of this text field
+ * is set to the empty string (""). The maximum length is set to 0, which
+ * specifies no limit.
+ */
+ public AlphaTextField() {
+ this("", 0);
+ }
+
+ /**
+ * Constructor of this class with the initial text of the text field specified.
+ * The maximum length is set to 0, which specifies no limit.
+ *
+ * @param text Initial text of the text field.
+ */
+ public AlphaTextField(String text) {
+ this(text, 0);
+ }
+
+ /**
+ * Constructor of this class with width (in columns) of the text field
+ * specified. The initial text is set to the empty string (""). The maximum
+ * length is set to 0, which specifies no limit.
+ *
+ * @param columns The width of the text field in characters.
+ */
+ public AlphaTextField(int columns) {
+ this("", columns);
+ }
+
+ /**
+ * Constructor of this class with width (in columns) and initial text of the
+ * text field specified. The maximum length is set to 0, which specifies no
+ * limit.
+ *
+ * @param text Initial text of the text field.
+ * @param columns The width of the text field in characters.
+ */
+ public AlphaTextField(String text, int columns) {
+ super(text, columns);
+ }
+
+ /**
+ * Constructor that allows the user to set the Alpha type of the text field and
+ * the maximum string length.
+ *
+ * @param anAlphaType The character restriction type.
+ * @param aLength The maximum number of characters allowed in the string.
+ */
+ public AlphaTextField(int anAlphaType, int aLength) {
+ super("", 0);
+ setAlphaType(anAlphaType);
+ setStringLength(aLength);
+ }
+
+ /**
+ * Gets the current restriction type of this text field.
+ *
+ * @see #ALPHABETIC
+ * @see #ALPHANUMERIC
+ * @see #ALPHANUMERIC_PLUS
+ * @see #ALL
+ * @return The current restriction type as defined by the constansts of this
+ * class.
+ */
+ public int getAlphaType() {
+ return alphaType;
+ }
+
+ /**
+ * Sets the restriction type of this text field.
+ *
+ * @see #ALPHABETIC
+ * @see #ALPHANUMERIC
+ * @see #ALPHANUMERIC_PLUS
+ * @see #ALL
+ * @param newAlphaType The restriction of this text field.
+ */
+ public void setAlphaType(int newAlphaType) {
+ switch (newAlphaType) {
+ case ALPHABETIC:
+ case ALPHANUMERIC:
+ case ALPHANUMERIC_PLUS:
+ case ALL: {
+ alphaType = newAlphaType;
+ break;
+ }
+ default: {
+ alphaType = ALPHABETIC;
+ break;
+ }
+ }
+ }
+
+ /**
+ * Sets the maximum string length of this text field. If the length is set to
+ * zero, then there is no limit. The default string length is zero. Negative
+ * sizes will set the length to zero.
+ *
+ * @param newStringLength The maximum length of the string that the user can
+ * input.
+ */
+ public void setStringLength(int newStringLength) {
+ if (newStringLength < 0) {
+ stringLength = 0;
+ } else {
+ stringLength = newStringLength;
+ }
+ }
+
+ /**
+ * Gets the current length of the maximum string size the user can enter.
+ *
+ * @return The maximum length the string of the text field can be.
+ */
+ public int getStringLength() {
+ return stringLength;
+ }
+
+ /*******************************
+ * PROTECTED METHODS
+ *******************************/
+
+ protected boolean isValidCharacter(char aChar) {
+ // if its a non-printable character, then its ok
+ if ((aChar < ' ') || (aChar > '~')) {
+ return true;
+ }
+
+ // can only be a printable character now, check it for validation
+ return isValidCharacterType(aChar);
+ }
+
+ protected boolean isValidString(String aString) {
+ if (aString.length() > stringLength) {
+ return false;
+ }
+
+ for (int i = 0; i < aString.length(); ++i) {
+ if (!(isValidCharacterType(aString.charAt(i)))) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected void postProcessing() {
+ // No need to do anything.
+ }
+
+ /*******************************
+ * PROTECTED METHODS
+ *******************************/
+
+ private boolean isValidCharacterType(char aChar) {
+ switch (alphaType) {
+ case ALPHABETIC: {
+ if (!(isValidAlphabeticCharacter(aChar))) {
+ return false;
+ }
+ break;
+ }
+ case ALPHANUMERIC: {
+ if (!(isValidAlphanumericCharacter(aChar))) {
+ return false;
+ }
+ break;
+ }
+ case ALPHANUMERIC_PLUS: {
+ if (!(isValidAlphanumericPlusCharacter(aChar))) {
+ return false;
+ }
+ break;
+ }
+ case ALL: {
+ if (!(isValidAllCharacter(aChar))) {
+ return false;
+ }
+ break;
+ }
+ default: {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean isValidAlphabeticCharacter(char aChar) {
+ if (((aChar < 'A') || (aChar > 'Z')) && ((aChar < 'a') || (aChar > 'z'))) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isValidAlphanumericCharacter(char aChar) {
+ if (((aChar < 'A') || (aChar > 'Z')) && ((aChar < 'a') || (aChar > 'z')) && ((aChar < '0') || (aChar > '9'))) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isValidAlphanumericPlusCharacter(char aChar) {
+ if (((aChar < 'A') || (aChar > 'Z')) && ((aChar < 'a') || (aChar > 'z')) && ((aChar < '0') || (aChar > '9'))) {
+ if ((aChar != ' ') && (aChar != '_') && (aChar != '-') && (aChar != ':') && (aChar != '\\')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isValidAllCharacter(char aChar) {
+ if ((aChar < ' ') || (aChar > '~')) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlternatingRowCellRenderer.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlternatingRowCellRenderer.java
index 46d2693..fb4824c 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlternatingRowCellRenderer.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/AlternatingRowCellRenderer.java
@@ -28,102 +28,79 @@ import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
/**
-* A TableCellRenderer that wraps another TableCellRenderer
-* and sets the background to the specified color for odd-numbered rows.
-* This makes every other row appear to be a different color,
-* which helps users distinguish rows of data in densely-packed
-* tables.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
+ * A TableCellRenderer that wraps another TableCellRenderer and sets the
+ * background to the specified color for odd-numbered rows. This makes every
+ * other row appear to be a different color, which helps users distinguish rows
+ * of data in densely-packed tables.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
public class AlternatingRowCellRenderer implements TableCellRenderer {
- protected TableCellRenderer wrappedRenderer;
- protected Color alternateColor;
-
- /**
- * Default constructor uses a lighter shade of the system control color
- * and wraps a DefaultTableCellRenderer.
- */
- public AlternatingRowCellRenderer()
- {
- this( new DefaultTableCellRenderer() );
- }
-
- /**
- * Uses the specified color for the background of the alternating rows,
- * and wraps a DefaultTableCellRenderer.
- */
- public AlternatingRowCellRenderer(
- Color aColor )
- {
- this( aColor, new DefaultTableCellRenderer() );
- }
+ protected TableCellRenderer wrappedRenderer;
+ protected Color alternateColor;
- /**
- * Uses the uses a lighter shade of the system control color
- * for the background of the alternating rows,
- * and wraps the specified TableCellRenderer.
- */
- public AlternatingRowCellRenderer(
- TableCellRenderer aRenderer )
- {
- Color c = UIManager.getColor( "control" );
- c = new Color( // lighten this color just slightly
- (int) ( c.getRed() + ( ( 255 - c.getRed() ) / 1.5 ) ),
- (int) ( c.getGreen() + ( ( 255 - c.getGreen() ) / 1.5 ) ),
- (int) ( c.getBlue() + ( ( 255 - c.getBlue() ) / 1.5 ) ) );
+ /**
+ * Default constructor uses a lighter shade of the system control color and
+ * wraps a DefaultTableCellRenderer.
+ */
+ public AlternatingRowCellRenderer() {
+ this(new DefaultTableCellRenderer());
+ }
- alternateColor = c;
- wrappedRenderer = aRenderer;
- }
+ /**
+ * Uses the specified color for the background of the alternating rows, and
+ * wraps a DefaultTableCellRenderer.
+ */
+ public AlternatingRowCellRenderer(Color aColor) {
+ this(aColor, new DefaultTableCellRenderer());
+ }
- /**
- * Uses the specified color for the background of the alternating rows,
- * and wraps the specified TableCellRenderer.
- */
- public AlternatingRowCellRenderer(
- Color aColor, TableCellRenderer aRenderer )
- {
- alternateColor = aColor;
- wrappedRenderer = aRenderer;
- }
+ /**
+ * Uses the uses a lighter shade of the system control color for the background
+ * of the alternating rows, and wraps the specified TableCellRenderer.
+ */
+ public AlternatingRowCellRenderer(TableCellRenderer aRenderer) {
+ Color c = UIManager.getColor("control");
+ c = new Color( // lighten this color just slightly
+ (int) (c.getRed() + ((255 - c.getRed()) / 1.5)), (int) (c.getGreen() + ((255 - c.getGreen()) / 1.5)),
+ (int) (c.getBlue() + ((255 - c.getBlue()) / 1.5)));
- public Component getTableCellRendererComponent(
- JTable table, Object value,
- boolean isSelected, boolean hasFocus,
- int row, int column)
- {
- Component result = wrappedRenderer.getTableCellRendererComponent(
- table, value, isSelected, hasFocus, row, column );
- if ( ! isSelected )
- {
- if ( row % 2 == 0 )
- {
- if ( ! result.getBackground().equals( table.getBackground() ) )
- {
- result.setBackground( table.getBackground() );
- }
- }
- else
- {
- if ( ! result.getBackground().equals( alternateColor ) )
- {
- // jdk1.3's default renderer is opaque
- if ( result instanceof JComponent )
- {
- ((JComponent)result).setOpaque( true );
- }
-
- result.setBackground( alternateColor );
- }
- }
- }
- return result;
- }
-}
+ alternateColor = c;
+ wrappedRenderer = aRenderer;
+ }
+ /**
+ * Uses the specified color for the background of the alternating rows, and
+ * wraps the specified TableCellRenderer.
+ */
+ public AlternatingRowCellRenderer(Color aColor, TableCellRenderer aRenderer) {
+ alternateColor = aColor;
+ wrappedRenderer = aRenderer;
+ }
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
+ int row, int column) {
+ Component result = wrappedRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
+ column);
+ if (!isSelected) {
+ if (row % 2 == 0) {
+ if (!result.getBackground().equals(table.getBackground())) {
+ result.setBackground(table.getBackground());
+ }
+ } else {
+ if (!result.getBackground().equals(alternateColor)) {
+ // jdk1.3's default renderer is opaque
+ if (result instanceof JComponent) {
+ ((JComponent) result).setOpaque(true);
+ }
+ result.setBackground(alternateColor);
+ }
+ }
+ }
+ return result;
+ }
+}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterFlowLayout.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterFlowLayout.java
index 1c438b6..632fb59 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterFlowLayout.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterFlowLayout.java
@@ -25,491 +25,505 @@ import java.awt.FlowLayout;
import java.awt.Insets;
/**
- * BetterFlowLayout works just like FlowLayout, except that
- * you can specify a vertical orientation in addition to the
- * usual horizontal orientations. You can also specify that
- * all the components be sized to the same height and/or width.
- * By default, the behavior is identical to FlowLayout.
+ * BetterFlowLayout works just like FlowLayout, except that you can specify a
+ * vertical orientation in addition to the usual horizontal orientations. You
+ * can also specify that all the components be sized to the same height and/or
+ * width. By default, the behavior is identical to FlowLayout.
*
* @author michael@mpowers.net
* @author $Author: cgruber $
- * @version $Revision: 904 $
- * $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
+ * @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006)
+ * $
*/
public class BetterFlowLayout extends FlowLayout {
- /**
- * This value indicates vertical orientation and
- * that each column of components should be top-justified.
- */
- public static final int TOP = 32;
-
- /**
- * This value indicates vertical orientation and
- * that each column of components should be centered.
- */
- public static final int CENTER_VERTICAL = 16;
-
- /**
- * This value indicates vertical orientation and
- * that each column of components should be bottom-justified.
- */
- public static final int BOTTOM = 8;
-
- /**
- * Tracks orientation.
- */
- protected boolean isHorizontal = true;
-
- /**
- * Tracks component sizing of width.
- */
- protected boolean isWidthUniform = false;
- /**
- * Tracks component sizing of height.
- */
- protected boolean isHeightUniform = false;
-
- /**
- * Constructs a new Flow Layout with a centered alignment and a
- * default 5-unit horizontal and vertical gap.
- */
- public BetterFlowLayout() {
- this(CENTER, 5, 5);
- }
-
- /**
- * Constructs a new Flow Layout with the specified alignment and a
- * default 5-unit horizontal and vertical gap.
- * The value of the alignment argument must be one of
- * <code>BetterFlowLayout.LEFT</code>, <code>BetterFlowLayout.RIGHT</code>,
- * or <code>BetterFlowLayout.CENTER</code>.
- * @param align the alignment value
- */
- public BetterFlowLayout(int align) {
- this(align, 5, 5);
- }
-
- /**
- * Creates a new flow layout manager with the indicated alignment
- * and the indicated horizontal and vertical gaps.
- * <p>
- * The value of the alignment argument must be one of
- * <code>BetterFlowLayout.LEFT</code>, <code>BetterFlowLayout.RIGHT</code>,
- * or <code>BetterFlowLayout.CENTER</code>.
- * @param align the alignment value.
- * @param hgap the horizontal gap between components.
- * @param vgap the vertical gap between components.
- */
- public BetterFlowLayout(int align, int hgap, int vgap) {
- setHgap(hgap);
- setVgap(vgap);
- setAlignment(align);
- }
-
- /**
- * Sets whether all components should have the same height.
- * @param isUniform the new value.
- * @see #isHeightUniform
- */
- public void setHeightUniform(boolean isUniform) {
- isHeightUniform = isUniform;
- }
-
- /**
- * Sets whether all components should have the same width.
- * @param isUniform the new value.
- * @see #isWidthUniform
- */
- public void setWidthUniform(boolean isUniform) {
- isWidthUniform = isUniform;
- }
-
- /**
- * Determines whether all components will have the same height.
- * The uniform height will be the maximum of the preferred heights
- * of all the components in the container.
- * This value defaults to false.
- * @return whether components will have the same height.
- */
- public boolean isHeightUniform() {
- return isHeightUniform;
- }
-
- /**
- * Determines whether all components will have the same width.
- * The uniform height will be the maximum of the preferred widths
- * of all the components in the container.
- * This value defaults to false.
- * @return whether components will have the same width.
- */
- public boolean isWidthUniform() {
- return isWidthUniform;
- }
-
- /**
- * Sets the alignment for this layout.
- * Possible values for horizontal orientation are <code>LEFT</code>,
- * <code>RIGHT</code>, and <code>CENTER</code>.
- * Possible values for vertical orientation are <code>TOP</code>,
- * <code>BOTTOM</code>, and <code>CENTER_VERTICAL</code>.
- * @param align the alignment value.
- * @see java.awt.FlowLayout#getAlignment
- */
- public void setAlignment(int align) {
- if ( ( align == TOP ) || ( align == BOTTOM ) || ( align == CENTER_VERTICAL ) )
- {
- isHorizontal = false;
- }
- else
- {
- isHorizontal = true;
- }
-
- super.setAlignment( align );
- }
-
- /**
- * Returns the preferred dimensions for this layout given the components
- * in the specified target container.
- * @param target the component which needs to be laid out
- * @return the preferred dimensions to lay out the
- * subcomponents of the specified container.
- * @see Container
- * @see #minimumLayoutSize
- * @see java.awt.Container#getPreferredSize
- */
- public Dimension preferredLayoutSize(Container target) {
- if ( isHorizontal ) {
- return preferredLayoutSizeHorizontal( target );
- } else {
- return preferredLayoutSizeVertical( target );
- }
- }
-
- /**
- * Returns the preferred dimensions for this layout given the components
- * in the specified target container.
- * @param target the component which needs to be laid out
- * @return the preferred dimensions to lay out the
- * subcomponents of the specified container.
- * @see Container
- * @see #minimumLayoutSize
- * @see java.awt.Container#getPreferredSize
- */
- public Dimension preferredLayoutSizeHorizontal(Container target) {
- synchronized (target.getTreeLock()) {
- Dimension dim = new Dimension(0, 0);
- int nmembers = target.getComponentCount();
- int maxWidth = 0;
-
- for (int i = 0 ; i < nmembers ; i++) {
- Component m = target.getComponent(i);
- if (m.isVisible()) {
- Dimension d = m.getPreferredSize();
- dim.height = Math.max(dim.height, d.height);
- maxWidth = Math.max(maxWidth, d.width);
- if (i > 0) {
- dim.width += getHgap();
- }
- dim.width += d.width;
- }
- }
- if ( isWidthUniform )
- dim.width = ( maxWidth + getHgap() ) * nmembers - getHgap();
- Insets insets = target.getInsets();
- dim.width += insets.left + insets.right + getHgap()*2;
- dim.height += insets.top + insets.bottom + getVgap()*2;
- return dim;
- }
- }
-
- /**
- * Returns the preferred dimensions for this layout given the components
- * in the specified target container.
- * @param target the component which needs to be laid out
- * @return the preferred dimensions to lay out the
- * subcomponents of the specified container.
- * @see Container
- * @see #minimumLayoutSize
- * @see java.awt.Container#getPreferredSize
- */
- public Dimension preferredLayoutSizeVertical(Container target) {
- synchronized (target.getTreeLock()) {
- Dimension dim = new Dimension(0, 0);
- int nmembers = target.getComponentCount();
- int maxHeight = 0;
-
- for (int i = 0 ; i < nmembers ; i++) {
- Component m = target.getComponent(i);
- if (m.isVisible()) {
- Dimension d = m.getPreferredSize();
- dim.width = Math.max(dim.width, d.width);
- maxHeight = Math.max(maxHeight, d.height);
- if (i > 0) {
- dim.height += getVgap();
- }
- dim.height += d.height;
- }
- }
- if ( isHeightUniform )
- dim.height = ( maxHeight + getVgap() ) * nmembers - getVgap();
- Insets insets = target.getInsets();
- dim.width += insets.left + insets.right + getHgap()*2;
- dim.height += insets.top + insets.bottom + getVgap()*2;
- return dim;
- }
- }
-
- /**
- * Returns the minimum dimensions needed to layout the components
- * contained in the specified target container.
- * @param target the component which needs to be laid out
- * @return the minimum dimensions to lay out the
- * subcomponents of the specified container.
- * @see #preferredLayoutSize
- * @see java.awt.Container
- * @see java.awt.Container#doLayout
- */
- public Dimension minimumLayoutSize(Container target) {
- // preferred size is also the minimum size
- if ( isHorizontal ) {
- return preferredLayoutSizeHorizontal( target );
- } else {
- return preferredLayoutSizeVertical( target );
- }
- }
-
- /**
- * Lays out the container. This method lets each component take
- * its preferred size by reshaping the components in the
- * target container in order to satisfy the constraints of
- * this <code>BetterFlowLayout</code> object.
- * @param target the specified component being laid out.
- * @see Container
- * @see java.awt.Container#doLayout
- */
- public void layoutContainer(Container target) {
- if ( isHorizontal ) {
- layoutContainerHorizontal( target );
- } else {
- layoutContainerVertical( target );
- }
- }
-
- /**
- * Lays out the container. This method lets each component take
- * its preferred size by reshaping the components in the
- * target container in order to satisfy the constraints of
- * this <code>BetterFlowLayout</code> object.
- * @param target the specified component being laid out.
- * @see Container
- * @see java.awt.Container#doLayout
- */
- protected void layoutContainerHorizontal(Container target) {
- synchronized (target.getTreeLock()) {
- Insets insets = target.getInsets();
- int maxwidth = target.getSize().width - (insets.left + insets.right + getHgap()*2);
- int nmembers = target.getComponentCount();
- int x = 0, y = insets.top + getVgap();
- int rowh = 0, start = 0;
-
- boolean ltr = true; // target.getComponentOrientation().isLeftToRight();
- Dimension uniform = getUniformDimension( target );
-
- for (int i = 0 ; i < nmembers ; i++) {
- Component m = target.getComponent(i);
- if (m.isVisible()) {
- Dimension d = m.getPreferredSize();
- if ( isWidthUniform )
- d.width = uniform.width;
- if ( isHeightUniform )
- d.height = uniform.height;
- m.setSize(d.width, d.height);
-
- if ((x == 0) || ((x + d.width) <= maxwidth)) {
- if (x > 0) {
- x += getHgap();
- }
- x += d.width;
- rowh = Math.max(rowh, d.height);
- } else {
- moveComponentsHorizontal(target, insets.left + getHgap(), y, maxwidth - x, rowh, start, i, ltr);
- x = d.width;
- y += getVgap() + rowh;
- rowh = d.height;
- start = i;
- }
- }
- }
- moveComponentsHorizontal(target, insets.left + getHgap(), y, maxwidth - x, rowh, start, nmembers, ltr);
- }
- }
-
- /**
- * Centers the elements in the specified row, if there is any slack.
- * @param target the component which needs to be moved
- * @param x the x coordinate
- * @param y the y coordinate
- * @param width the width dimensions
- * @param height the height dimensions
- * @param rowStart the beginning of the row
- * @param rowEnd the the ending of the row
- */
- private void moveComponentsHorizontal(Container target, int x, int y, int width, int height,
- int rowStart, int rowEnd, boolean ltr) {
- synchronized (target.getTreeLock()) {
- switch (getAlignment()) {
- case LEFT:
- x += ltr ? 0 : width;
- break;
- case CENTER:
- x += width / 2;
- break;
- case RIGHT:
- x += ltr ? width : 0;
- break;
+ /**
+ * This value indicates vertical orientation and that each column of components
+ * should be top-justified.
+ */
+ public static final int TOP = 32;
+
+ /**
+ * This value indicates vertical orientation and that each column of components
+ * should be centered.
+ */
+ public static final int CENTER_VERTICAL = 16;
+
+ /**
+ * This value indicates vertical orientation and that each column of components
+ * should be bottom-justified.
+ */
+ public static final int BOTTOM = 8;
+
+ /**
+ * Tracks orientation.
+ */
+ protected boolean isHorizontal = true;
+
+ /**
+ * Tracks component sizing of width.
+ */
+ protected boolean isWidthUniform = false;
+ /**
+ * Tracks component sizing of height.
+ */
+ protected boolean isHeightUniform = false;
+
+ /**
+ * Constructs a new Flow Layout with a centered alignment and a default 5-unit
+ * horizontal and vertical gap.
+ */
+ public BetterFlowLayout() {
+ this(CENTER, 5, 5);
+ }
+
+ /**
+ * Constructs a new Flow Layout with the specified alignment and a default
+ * 5-unit horizontal and vertical gap. The value of the alignment argument must
+ * be one of <code>BetterFlowLayout.LEFT</code>,
+ * <code>BetterFlowLayout.RIGHT</code>, or <code>BetterFlowLayout.CENTER</code>.
+ *
+ * @param align the alignment value
+ */
+ public BetterFlowLayout(int align) {
+ this(align, 5, 5);
+ }
+
+ /**
+ * Creates a new flow layout manager with the indicated alignment and the
+ * indicated horizontal and vertical gaps.
+ * <p>
+ * The value of the alignment argument must be one of
+ * <code>BetterFlowLayout.LEFT</code>, <code>BetterFlowLayout.RIGHT</code>, or
+ * <code>BetterFlowLayout.CENTER</code>.
+ *
+ * @param align the alignment value.
+ * @param hgap the horizontal gap between components.
+ * @param vgap the vertical gap between components.
+ */
+ public BetterFlowLayout(int align, int hgap, int vgap) {
+ setHgap(hgap);
+ setVgap(vgap);
+ setAlignment(align);
+ }
+
+ /**
+ * Sets whether all components should have the same height.
+ *
+ * @param isUniform the new value.
+ * @see #isHeightUniform
+ */
+ public void setHeightUniform(boolean isUniform) {
+ isHeightUniform = isUniform;
+ }
+
+ /**
+ * Sets whether all components should have the same width.
+ *
+ * @param isUniform the new value.
+ * @see #isWidthUniform
+ */
+ public void setWidthUniform(boolean isUniform) {
+ isWidthUniform = isUniform;
+ }
+
+ /**
+ * Determines whether all components will have the same height. The uniform
+ * height will be the maximum of the preferred heights of all the components in
+ * the container. This value defaults to false.
+ *
+ * @return whether components will have the same height.
+ */
+ public boolean isHeightUniform() {
+ return isHeightUniform;
+ }
+
+ /**
+ * Determines whether all components will have the same width. The uniform
+ * height will be the maximum of the preferred widths of all the components in
+ * the container. This value defaults to false.
+ *
+ * @return whether components will have the same width.
+ */
+ public boolean isWidthUniform() {
+ return isWidthUniform;
+ }
+
+ /**
+ * Sets the alignment for this layout. Possible values for horizontal
+ * orientation are <code>LEFT</code>, <code>RIGHT</code>, and
+ * <code>CENTER</code>. Possible values for vertical orientation are
+ * <code>TOP</code>, <code>BOTTOM</code>, and <code>CENTER_VERTICAL</code>.
+ *
+ * @param align the alignment value.
+ * @see java.awt.FlowLayout#getAlignment
+ */
+ public void setAlignment(int align) {
+ if ((align == TOP) || (align == BOTTOM) || (align == CENTER_VERTICAL)) {
+ isHorizontal = false;
+ } else {
+ isHorizontal = true;
+ }
+
+ super.setAlignment(align);
+ }
+
+ /**
+ * Returns the preferred dimensions for this layout given the components in the
+ * specified target container.
+ *
+ * @param target the component which needs to be laid out
+ * @return the preferred dimensions to lay out the subcomponents of the
+ * specified container.
+ * @see Container
+ * @see #minimumLayoutSize
+ * @see java.awt.Container#getPreferredSize
+ */
+ public Dimension preferredLayoutSize(Container target) {
+ if (isHorizontal) {
+ return preferredLayoutSizeHorizontal(target);
+ } else {
+ return preferredLayoutSizeVertical(target);
+ }
+ }
+
+ /**
+ * Returns the preferred dimensions for this layout given the components in the
+ * specified target container.
+ *
+ * @param target the component which needs to be laid out
+ * @return the preferred dimensions to lay out the subcomponents of the
+ * specified container.
+ * @see Container
+ * @see #minimumLayoutSize
+ * @see java.awt.Container#getPreferredSize
+ */
+ public Dimension preferredLayoutSizeHorizontal(Container target) {
+ synchronized (target.getTreeLock()) {
+ Dimension dim = new Dimension(0, 0);
+ int nmembers = target.getComponentCount();
+ int maxWidth = 0;
+
+ for (int i = 0; i < nmembers; i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ Dimension d = m.getPreferredSize();
+ dim.height = Math.max(dim.height, d.height);
+ maxWidth = Math.max(maxWidth, d.width);
+ if (i > 0) {
+ dim.width += getHgap();
+ }
+ dim.width += d.width;
+ }
+ }
+ if (isWidthUniform)
+ dim.width = (maxWidth + getHgap()) * nmembers - getHgap();
+ Insets insets = target.getInsets();
+ dim.width += insets.left + insets.right + getHgap() * 2;
+ dim.height += insets.top + insets.bottom + getVgap() * 2;
+ return dim;
+ }
+ }
+
+ /**
+ * Returns the preferred dimensions for this layout given the components in the
+ * specified target container.
+ *
+ * @param target the component which needs to be laid out
+ * @return the preferred dimensions to lay out the subcomponents of the
+ * specified container.
+ * @see Container
+ * @see #minimumLayoutSize
+ * @see java.awt.Container#getPreferredSize
+ */
+ public Dimension preferredLayoutSizeVertical(Container target) {
+ synchronized (target.getTreeLock()) {
+ Dimension dim = new Dimension(0, 0);
+ int nmembers = target.getComponentCount();
+ int maxHeight = 0;
+
+ for (int i = 0; i < nmembers; i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ Dimension d = m.getPreferredSize();
+ dim.width = Math.max(dim.width, d.width);
+ maxHeight = Math.max(maxHeight, d.height);
+ if (i > 0) {
+ dim.height += getVgap();
+ }
+ dim.height += d.height;
+ }
+ }
+ if (isHeightUniform)
+ dim.height = (maxHeight + getVgap()) * nmembers - getVgap();
+ Insets insets = target.getInsets();
+ dim.width += insets.left + insets.right + getHgap() * 2;
+ dim.height += insets.top + insets.bottom + getVgap() * 2;
+ return dim;
+ }
+ }
+
+ /**
+ * Returns the minimum dimensions needed to layout the components contained in
+ * the specified target container.
+ *
+ * @param target the component which needs to be laid out
+ * @return the minimum dimensions to lay out the subcomponents of the specified
+ * container.
+ * @see #preferredLayoutSize
+ * @see java.awt.Container
+ * @see java.awt.Container#doLayout
+ */
+ public Dimension minimumLayoutSize(Container target) {
+ // preferred size is also the minimum size
+ if (isHorizontal) {
+ return preferredLayoutSizeHorizontal(target);
+ } else {
+ return preferredLayoutSizeVertical(target);
+ }
+ }
+
+ /**
+ * Lays out the container. This method lets each component take its preferred
+ * size by reshaping the components in the target container in order to satisfy
+ * the constraints of this <code>BetterFlowLayout</code> object.
+ *
+ * @param target the specified component being laid out.
+ * @see Container
+ * @see java.awt.Container#doLayout
+ */
+ public void layoutContainer(Container target) {
+ if (isHorizontal) {
+ layoutContainerHorizontal(target);
+ } else {
+ layoutContainerVertical(target);
+ }
+ }
+
+ /**
+ * Lays out the container. This method lets each component take its preferred
+ * size by reshaping the components in the target container in order to satisfy
+ * the constraints of this <code>BetterFlowLayout</code> object.
+ *
+ * @param target the specified component being laid out.
+ * @see Container
+ * @see java.awt.Container#doLayout
+ */
+ protected void layoutContainerHorizontal(Container target) {
+ synchronized (target.getTreeLock()) {
+ Insets insets = target.getInsets();
+ int maxwidth = target.getSize().width - (insets.left + insets.right + getHgap() * 2);
+ int nmembers = target.getComponentCount();
+ int x = 0, y = insets.top + getVgap();
+ int rowh = 0, start = 0;
+
+ boolean ltr = true; // target.getComponentOrientation().isLeftToRight();
+ Dimension uniform = getUniformDimension(target);
+
+ for (int i = 0; i < nmembers; i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ Dimension d = m.getPreferredSize();
+ if (isWidthUniform)
+ d.width = uniform.width;
+ if (isHeightUniform)
+ d.height = uniform.height;
+ m.setSize(d.width, d.height);
+
+ if ((x == 0) || ((x + d.width) <= maxwidth)) {
+ if (x > 0) {
+ x += getHgap();
+ }
+ x += d.width;
+ rowh = Math.max(rowh, d.height);
+ } else {
+ moveComponentsHorizontal(target, insets.left + getHgap(), y, maxwidth - x, rowh, start, i, ltr);
+ x = d.width;
+ y += getVgap() + rowh;
+ rowh = d.height;
+ start = i;
+ }
+ }
+ }
+ moveComponentsHorizontal(target, insets.left + getHgap(), y, maxwidth - x, rowh, start, nmembers, ltr);
+ }
+ }
+
+ /**
+ * Centers the elements in the specified row, if there is any slack.
+ *
+ * @param target the component which needs to be moved
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the width dimensions
+ * @param height the height dimensions
+ * @param rowStart the beginning of the row
+ * @param rowEnd the the ending of the row
+ */
+ private void moveComponentsHorizontal(Container target, int x, int y, int width, int height, int rowStart,
+ int rowEnd, boolean ltr) {
+ synchronized (target.getTreeLock()) {
+ switch (getAlignment()) {
+ case LEFT:
+ x += ltr ? 0 : width;
+ break;
+ case CENTER:
+ x += width / 2;
+ break;
+ case RIGHT:
+ x += ltr ? width : 0;
+ break;
//1.2 case LEADING:
//1.2 break;
//1.2 case TRAILING:
//1.2 x += width;
//1.2 break;
+ }
+ for (int i = rowStart; i < rowEnd; i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ if (ltr) {
+ m.setLocation(x, y + (height - m.getBounds().height) / 2);
+ } else {
+ m.setLocation(target.getBounds().width - x - m.getBounds().width,
+ y + (height - m.getBounds().height) / 2);
+ }
+ x += m.getBounds().width + getHgap();
+ }
+ }
+ }
}
- for (int i = rowStart ; i < rowEnd ; i++) {
- Component m = target.getComponent(i);
- if (m.isVisible()) {
- if (ltr) {
- m.setLocation(x, y + (height - m.getBounds().height) / 2);
- } else {
- m.setLocation(target.getBounds().width - x - m.getBounds().width, y + (height - m.getBounds().height) / 2);
- }
- x += m.getBounds().width + getHgap();
- }
+
+ /**
+ * Lays out the container. This method lets each component take its preferred
+ * size by reshaping the components in the target container in order to satisfy
+ * the constraints of this <code>BetterFlowLayout</code> object.
+ *
+ * @param target the specified component being laid out.
+ * @see Container
+ * @see java.awt.Container#doLayout
+ */
+ protected void layoutContainerVertical(Container target) {
+ synchronized (target.getTreeLock()) {
+
+ Insets insets = target.getInsets();
+ int maxheight = target.getBounds().height - (insets.top + insets.bottom + getVgap() * 2);
+ int nmembers = target.getComponentCount();
+ int y = 0, x = insets.left + getHgap();
+ int colw = 0, start = 0;
+
+ Dimension uniform = getUniformDimension(target);
+ for (int i = 0; i < nmembers; i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ Dimension d = m.getPreferredSize();
+ if (isWidthUniform)
+ d.width = uniform.width;
+ if (isHeightUniform)
+ d.height = uniform.height;
+ m.setSize(d.width, d.height);
+
+ if ((y == 0) || ((y + d.height) <= maxheight)) {
+ if (y > 0) {
+ y += getVgap();
+ }
+ y += d.height;
+ colw = Math.max(colw, d.width);
+ } else {
+ moveComponentsVertical(target, x, insets.top + getVgap(), colw, maxheight - y, start, i);
+ y = d.height;
+ x += getHgap() + colw;
+ colw = d.width;
+ start = i;
+ }
+ }
+ }
+ moveComponentsVertical(target, x, insets.top + getVgap(), colw, maxheight - y, start, nmembers);
+ }
}
- }
- }
-
- /**
- * Lays out the container. This method lets each component take
- * its preferred size by reshaping the components in the
- * target container in order to satisfy the constraints of
- * this <code>BetterFlowLayout</code> object.
- * @param target the specified component being laid out.
- * @see Container
- * @see java.awt.Container#doLayout
- */
- protected void layoutContainerVertical(Container target) {
- synchronized (target.getTreeLock()) {
-
- Insets insets = target.getInsets();
- int maxheight = target.getBounds().height - (insets.top + insets.bottom + getVgap()*2);
- int nmembers = target.getComponentCount();
- int y = 0, x = insets.left + getHgap();
- int colw = 0, start = 0;
-
- Dimension uniform = getUniformDimension( target );
- for (int i = 0 ; i < nmembers ; i++) {
- Component m = target.getComponent(i);
- if (m.isVisible()) {
- Dimension d = m.getPreferredSize();
- if ( isWidthUniform )
- d.width = uniform.width;
- if ( isHeightUniform )
- d.height = uniform.height;
- m.setSize(d.width, d.height);
-
- if ((y == 0) || ((y + d.height) <= maxheight)) {
- if (y > 0) {
- y += getVgap();
- }
- y += d.height;
- colw = Math.max(colw, d.width);
- } else {
- moveComponentsVertical(target, x, insets.top + getVgap(), colw, maxheight - y, start, i );
- y = d.height;
- x += getHgap() + colw;
- colw = d.width;
- start = i;
- }
- }
- }
- moveComponentsVertical(target, x, insets.top + getVgap(), colw, maxheight - y, start, nmembers );
- }
- }
-
- /**
- * Centers the elements in the specified row, if there is any slack.
- * @param target the component which needs to be moved
- * @param x the x coordinate
- * @param y the y coordinate
- * @param width the width dimensions
- * @param height the height dimensions
- * @param colStart the beginning of the column
- * @param colEnd the the ending of the column
- */
- private void moveComponentsVertical(Container target, int x, int y, int width, int height,
- int colStart, int colEnd) {
- synchronized (target.getTreeLock()) {
- switch (getAlignment()) {
- case TOP:
- y += 0;
- break;
- case CENTER_VERTICAL:
- y += ( height / 2 ); // - preferredLayoutSize( target ).height ) / 2 );
- break;
- case BOTTOM:
- y += height;
- break;
- }
- for (int i = colStart ; i < colEnd ; i++) {
- Component m = target.getComponent(i);
- if (m.isVisible()) {
- m.setLocation(x + (width - m.getBounds().width) / 2, y );
+
+ /**
+ * Centers the elements in the specified row, if there is any slack.
+ *
+ * @param target the component which needs to be moved
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the width dimensions
+ * @param height the height dimensions
+ * @param colStart the beginning of the column
+ * @param colEnd the the ending of the column
+ */
+ private void moveComponentsVertical(Container target, int x, int y, int width, int height, int colStart,
+ int colEnd) {
+ synchronized (target.getTreeLock()) {
+ switch (getAlignment()) {
+ case TOP:
+ y += 0;
+ break;
+ case CENTER_VERTICAL:
+ y += (height / 2); // - preferredLayoutSize( target ).height ) / 2 );
+ break;
+ case BOTTOM:
+ y += height;
+ break;
+ }
+ for (int i = colStart; i < colEnd; i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ m.setLocation(x + (width - m.getBounds().width) / 2, y);
// m.setLocation(x, y );
// m.setSize( width, m.getBounds().height ); //!
- y += m.getBounds().height + getVgap();
- }
- }
- }
- }
-
- /**
- * Returns a dimension representing the maximum preferred
- * height and width of all the components in the container.
- * @param target the container to scan.
- * @return a dimension containing the maximum values.
- */
- protected Dimension getUniformDimension(Container target) {
- Component m = null;
- Dimension preferred = null;
- int maxWidth = 0, maxHeight = 0;
- int nmembers = target.getComponentCount();
- for ( int i = 0; i < nmembers; i++ ) {
- m = target.getComponent( i );
- if ( m.isVisible() ) {
- preferred = m.getPreferredSize();
- maxWidth = Math.max( maxWidth, preferred.width );
- maxHeight = Math.max( maxHeight, preferred.height );
- }
- }
- return new Dimension( maxWidth, maxHeight );
- }
-
- /**
- * Returns a string representation of this <code>BetterFlowLayout</code>
- * object and its values.
- * @return a string representation of this layout.
- */
- public String toString() {
- String str = "";
- switch (getAlignment()) {
- case TOP: str = ",align=top"; break;
- case CENTER_VERTICAL: str = ",align=vertical"; break;
- case BOTTOM: str = ",align=bottom"; break;
- default: return super.toString();
+ y += m.getBounds().height + getVgap();
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a dimension representing the maximum preferred height and width of
+ * all the components in the container.
+ *
+ * @param target the container to scan.
+ * @return a dimension containing the maximum values.
+ */
+ protected Dimension getUniformDimension(Container target) {
+ Component m = null;
+ Dimension preferred = null;
+ int maxWidth = 0, maxHeight = 0;
+ int nmembers = target.getComponentCount();
+ for (int i = 0; i < nmembers; i++) {
+ m = target.getComponent(i);
+ if (m.isVisible()) {
+ preferred = m.getPreferredSize();
+ maxWidth = Math.max(maxWidth, preferred.width);
+ maxHeight = Math.max(maxHeight, preferred.height);
+ }
+ }
+ return new Dimension(maxWidth, maxHeight);
}
- return getClass().getName() + "[hgap=" + getHgap() + ",vgap=" + getVgap() + str + "]";
- }
+ /**
+ * Returns a string representation of this <code>BetterFlowLayout</code> object
+ * and its values.
+ *
+ * @return a string representation of this layout.
+ */
+ public String toString() {
+ String str = "";
+ switch (getAlignment()) {
+ case TOP:
+ str = ",align=top";
+ break;
+ case CENTER_VERTICAL:
+ str = ",align=vertical";
+ break;
+ case BOTTOM:
+ str = ",align=bottom";
+ break;
+ default:
+ return super.toString();
+ }
+ return getClass().getName() + "[hgap=" + getHgap() + ",vgap=" + getVgap() + str + "]";
+ }
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterRootLayout.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterRootLayout.java
index 6e23ca1..238dd14 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterRootLayout.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterRootLayout.java
@@ -28,247 +28,209 @@ import java.awt.Rectangle;
import javax.swing.JPanel;
import javax.swing.JRootPane;
-/**
-* A custom layout for a JRootPane that handles the the layout of a
-* JRootPane's layeredPane, glassPane, and menuBar, and in addition
-* handles four decorative components arranged in a border layout.
-* Add the decorative components to the JRootPane using the directional
-* constants; CENTER is reserved for the content pane and menu bar.
-*
-* @author michael@mpowers.net
-* @version $Revision: 904 $
-*/
-public class BetterRootLayout extends BorderLayout
-{
+/**
+ * A custom layout for a JRootPane that handles the the layout of a JRootPane's
+ * layeredPane, glassPane, and menuBar, and in addition handles four decorative
+ * components arranged in a border layout. Add the decorative components to the
+ * JRootPane using the directional constants; CENTER is reserved for the content
+ * pane and menu bar.
+ *
+ * @author michael@mpowers.net
+ * @version $Revision: 904 $
+ */
+public class BetterRootLayout extends BorderLayout {
/**
* Returns the amount of space the layout would like to have.
*
* @param the Container for which this layout manager is being used
* @return a Dimension object containing the layout's preferred size
* @throws ClassCastException if parent is not a JRootPane
- */
- public Dimension preferredLayoutSize(Container parent)
- {
+ */
+ public Dimension preferredLayoutSize(Container parent) {
JRootPane rootPane = (JRootPane) parent;
-
+
JPanel proxyPanel = new JPanel();
- proxyPanel.setLayout( new BorderLayout() );
-
+ proxyPanel.setLayout(new BorderLayout());
+
JPanel contentProxy = null;
- if(rootPane.getContentPane() != null) {
+ if (rootPane.getContentPane() != null) {
contentProxy = new JPanel();
- contentProxy.setMinimumSize(
- rootPane.getContentPane().getMinimumSize() );
- contentProxy.setMaximumSize(
- rootPane.getContentPane().getMaximumSize() );
- contentProxy.setPreferredSize(
- rootPane.getContentPane().getPreferredSize() );
- proxyPanel.add( contentProxy, CENTER );
+ contentProxy.setMinimumSize(rootPane.getContentPane().getMinimumSize());
+ contentProxy.setMaximumSize(rootPane.getContentPane().getMaximumSize());
+ contentProxy.setPreferredSize(rootPane.getContentPane().getPreferredSize());
+ proxyPanel.add(contentProxy, CENTER);
}
JPanel menuProxy = null;
- if(rootPane.getJMenuBar() != null) {
+ if (rootPane.getJMenuBar() != null) {
menuProxy = new JPanel();
- menuProxy.setMinimumSize(
- rootPane.getJMenuBar().getMinimumSize() );
- menuProxy.setMaximumSize(
- rootPane.getJMenuBar().getMaximumSize() );
- menuProxy.setPreferredSize(
- rootPane.getJMenuBar().getPreferredSize() );
- proxyPanel.add( menuProxy, NORTH );
+ menuProxy.setMinimumSize(rootPane.getJMenuBar().getMinimumSize());
+ menuProxy.setMaximumSize(rootPane.getJMenuBar().getMaximumSize());
+ menuProxy.setPreferredSize(rootPane.getJMenuBar().getPreferredSize());
+ proxyPanel.add(menuProxy, NORTH);
}
-
- this.addLayoutComponent( proxyPanel, CENTER );
-
- Dimension result = super.preferredLayoutSize( parent );
- this.removeLayoutComponent( proxyPanel );
-
+ this.addLayoutComponent(proxyPanel, CENTER);
+
+ Dimension result = super.preferredLayoutSize(parent);
+
+ this.removeLayoutComponent(proxyPanel);
+
proxyPanel.removeAll();
-
+
return result;
}
-
+
/**
* Returns the minimum amount of space the layout needs.
*
* @param the Container for which this layout manager is being used
* @return a Dimension object containing the layout's minimum size
* @throws ClassCastException if parent is not a JRootPane
- */
- public Dimension minimumLayoutSize(Container parent)
- {
+ */
+ public Dimension minimumLayoutSize(Container parent) {
JRootPane rootPane = (JRootPane) parent;
-
+
JPanel proxyPanel = new JPanel();
- proxyPanel.setLayout( new BorderLayout() );
-
+ proxyPanel.setLayout(new BorderLayout());
+
JPanel contentProxy = null;
- if(rootPane.getContentPane() != null) {
+ if (rootPane.getContentPane() != null) {
contentProxy = new JPanel();
- contentProxy.setMinimumSize(
- rootPane.getContentPane().getMinimumSize() );
- contentProxy.setMaximumSize(
- rootPane.getContentPane().getMaximumSize() );
- contentProxy.setPreferredSize(
- rootPane.getContentPane().getPreferredSize() );
- proxyPanel.add( contentProxy, CENTER );
+ contentProxy.setMinimumSize(rootPane.getContentPane().getMinimumSize());
+ contentProxy.setMaximumSize(rootPane.getContentPane().getMaximumSize());
+ contentProxy.setPreferredSize(rootPane.getContentPane().getPreferredSize());
+ proxyPanel.add(contentProxy, CENTER);
}
JPanel menuProxy = null;
- if(rootPane.getJMenuBar() != null) {
+ if (rootPane.getJMenuBar() != null) {
menuProxy = new JPanel();
- menuProxy.setMinimumSize(
- rootPane.getJMenuBar().getMinimumSize() );
- menuProxy.setMaximumSize(
- rootPane.getJMenuBar().getMaximumSize() );
- menuProxy.setPreferredSize(
- rootPane.getJMenuBar().getPreferredSize() );
- proxyPanel.add( menuProxy, NORTH );
+ menuProxy.setMinimumSize(rootPane.getJMenuBar().getMinimumSize());
+ menuProxy.setMaximumSize(rootPane.getJMenuBar().getMaximumSize());
+ menuProxy.setPreferredSize(rootPane.getJMenuBar().getPreferredSize());
+ proxyPanel.add(menuProxy, NORTH);
}
-
- this.addLayoutComponent( proxyPanel, CENTER );
-
- Dimension result = super.minimumLayoutSize( parent );
- this.removeLayoutComponent( proxyPanel );
-
+ this.addLayoutComponent(proxyPanel, CENTER);
+
+ Dimension result = super.minimumLayoutSize(parent);
+
+ this.removeLayoutComponent(proxyPanel);
+
proxyPanel.removeAll();
-
+
return result;
}
-
+
/**
* Returns the maximum amount of space the layout can use.
*
* @param the Container for which this layout manager is being used
* @return a Dimension object containing the layout's maximum size
* @throws ClassCastException if parent is not a JRootPane
- */
- public Dimension maximumLayoutSize(Container target)
- {
+ */
+ public Dimension maximumLayoutSize(Container target) {
JRootPane rootPane = (JRootPane) target;
-
+
JPanel proxyPanel = new JPanel();
- proxyPanel.setLayout( new BorderLayout() );
-
+ proxyPanel.setLayout(new BorderLayout());
+
JPanel contentProxy = null;
- if(rootPane.getContentPane() != null) {
+ if (rootPane.getContentPane() != null) {
contentProxy = new JPanel();
- contentProxy.setMinimumSize(
- rootPane.getContentPane().getMinimumSize() );
- contentProxy.setMaximumSize(
- rootPane.getContentPane().getMaximumSize() );
- contentProxy.setPreferredSize(
- rootPane.getContentPane().getPreferredSize() );
- proxyPanel.add( contentProxy, CENTER );
+ contentProxy.setMinimumSize(rootPane.getContentPane().getMinimumSize());
+ contentProxy.setMaximumSize(rootPane.getContentPane().getMaximumSize());
+ contentProxy.setPreferredSize(rootPane.getContentPane().getPreferredSize());
+ proxyPanel.add(contentProxy, CENTER);
}
JPanel menuProxy = null;
- if(rootPane.getJMenuBar() != null) {
+ if (rootPane.getJMenuBar() != null) {
menuProxy = new JPanel();
- menuProxy.setMinimumSize(
- rootPane.getJMenuBar().getMinimumSize() );
- menuProxy.setMaximumSize(
- rootPane.getJMenuBar().getMaximumSize() );
- menuProxy.setPreferredSize(
- rootPane.getJMenuBar().getPreferredSize() );
- proxyPanel.add( menuProxy, NORTH );
+ menuProxy.setMinimumSize(rootPane.getJMenuBar().getMinimumSize());
+ menuProxy.setMaximumSize(rootPane.getJMenuBar().getMaximumSize());
+ menuProxy.setPreferredSize(rootPane.getJMenuBar().getPreferredSize());
+ proxyPanel.add(menuProxy, NORTH);
}
-
- this.addLayoutComponent( proxyPanel, CENTER );
-
- Dimension result = super.maximumLayoutSize( target );
- this.removeLayoutComponent( proxyPanel );
-
+ this.addLayoutComponent(proxyPanel, CENTER);
+
+ Dimension result = super.maximumLayoutSize(target);
+
+ this.removeLayoutComponent(proxyPanel);
+
proxyPanel.removeAll();
-
+
return result;
}
-
+
/**
* Instructs the layout manager to perform the layout for the specified
* container.
*
* @param the Container for which this layout manager is being used
* @throws ClassCastException if parent is not a JRootPane
- */
- public void layoutContainer(Container parent)
- {
+ */
+ public void layoutContainer(Container parent) {
JRootPane rootPane = (JRootPane) parent;
-
+
Rectangle b = parent.getBounds();
Insets i = rootPane.getInsets();
int w = b.width - i.right - i.left;
int h = b.height - i.top - i.bottom;
-
+
// layout panes
- if(rootPane.getLayeredPane() != null) {
+ if (rootPane.getLayeredPane() != null) {
rootPane.getLayeredPane().setBounds(i.left, i.top, w, h);
}
- if(rootPane.getGlassPane() != null) {
+ if (rootPane.getGlassPane() != null) {
rootPane.getGlassPane().setBounds(i.left, i.top, w, h);
}
-
+
// handle proxy panel
-
+
JPanel proxyPanel = new JPanel();
- proxyPanel.setLayout( new BorderLayout() );
-
- this.addLayoutComponent( proxyPanel, CENTER );
-
- super.layoutContainer( parent );
+ proxyPanel.setLayout(new BorderLayout());
+
+ this.addLayoutComponent(proxyPanel, CENTER);
+
+ super.layoutContainer(parent);
// use proxy sizes to set sizes of layeredPane's children
Rectangle proxyRect = proxyPanel.getBounds();
- if(rootPane.getJMenuBar() != null) {
+ if (rootPane.getJMenuBar() != null) {
Rectangle menuRect = proxyPanel.getBounds();
menuRect.height = rootPane.getJMenuBar().getPreferredSize().height;
- rootPane.getJMenuBar().setBounds( menuRect );
+ rootPane.getJMenuBar().setBounds(menuRect);
proxyRect.y += menuRect.height;
proxyRect.height -= menuRect.height;
}
- if(rootPane.getContentPane() != null) {
- rootPane.getContentPane().setBounds( proxyRect );
+ if (rootPane.getContentPane() != null) {
+ rootPane.getContentPane().setBounds(proxyRect);
}
- this.removeLayoutComponent( proxyPanel );
-
+ this.removeLayoutComponent(proxyPanel);
+
proxyPanel.removeAll();
}
-
+
/**
- * Passes NORTH, SOUTH, EAST, WEST and CENTER to super implementation,
- * and ignores all others.
- */
- public void addLayoutComponent(Component comp, Object constraints)
- {
- if ( NORTH.equals( constraints ) )
- {
- super.addLayoutComponent( comp, constraints );
- }
- else
- if ( SOUTH.equals( constraints ) )
- {
- super.addLayoutComponent( comp, constraints );
- }
- else
- if ( EAST.equals( constraints ) )
- {
- super.addLayoutComponent( comp, constraints );
+ * Passes NORTH, SOUTH, EAST, WEST and CENTER to super implementation, and
+ * ignores all others.
+ */
+ public void addLayoutComponent(Component comp, Object constraints) {
+ if (NORTH.equals(constraints)) {
+ super.addLayoutComponent(comp, constraints);
+ } else if (SOUTH.equals(constraints)) {
+ super.addLayoutComponent(comp, constraints);
+ } else if (EAST.equals(constraints)) {
+ super.addLayoutComponent(comp, constraints);
+ } else if (WEST.equals(constraints)) {
+ super.addLayoutComponent(comp, constraints);
+ } else if (CENTER.equals(constraints)) {
+ super.addLayoutComponent(comp, constraints);
}
- else
- if ( WEST.equals( constraints ) )
- {
- super.addLayoutComponent( comp, constraints );
- }
- else
- if ( CENTER.equals( constraints ) )
- {
- super.addLayoutComponent( comp, constraints );
- }
-
+
// otherwise, ignore
}
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterTableUI.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterTableUI.java
index deb0eb6..cb1d48a 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterTableUI.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/BetterTableUI.java
@@ -24,100 +24,84 @@ import javax.swing.event.MouseInputListener;
import javax.swing.plaf.basic.BasicTableUI;
/**
-* BetterTableUI allows a JTable to be disabled by
-* listening for MouseEvents and then forwarding them
-* to the usual MouseInputHandler only if the table
-* is enabled. <BR><BR>
-*
-* This class also works around a bug where an editable
-* table's selection is changed when clicking in an edit
-* cell while the control key is down. This typically
-* happened while users were copying/pasting data from
-* cell to cell. <BR><BR>
-*
-* To use, call <code>JTable.setUI()</code> on any
-* JTable with a BetterTableUI as the parameter.
-*
-* @author michael@mpowers.net
-* @version $Revision: 904 $
-*/
-public class BetterTableUI extends BasicTableUI implements MouseInputListener
-{
-/**
-* The listener to get all mouse events when the table is enabled.
-*/
- protected MouseInputListener delegateHandler;
-
-/**
-* Overridden to set self as mouse listener and create delegate.
-*/
- protected MouseInputListener createMouseInputListener()
- {
- // normal handler is a protected inner class of parent
- delegateHandler = new MouseInputHandler();
-
- return this;
- }
-
- // interface MouseInputListener
-
- public void mouseClicked(MouseEvent event)
- {
- if ( (table!=null) && (table.isEnabled()) )
- {
- delegateHandler.mouseClicked(event);
- }
- }
-
- public void mouseDragged(MouseEvent event)
- {
- if ( (table!=null) && (table.isEnabled()) )
- {
- delegateHandler.mouseDragged(event);
- }
- }
-
- public void mouseEntered(MouseEvent event)
- {
- if ( (table!=null) && (table.isEnabled()) )
- {
- delegateHandler.mouseEntered(event);
- }
- }
-
- public void mouseExited(MouseEvent event)
- {
- if ( (table!=null) && (table.isEnabled()) )
- {
- delegateHandler.mouseExited(event);
- }
- }
-
- public void mouseMoved(MouseEvent event)
- {
- if ( (table!=null) && (table.isEnabled()) )
- {
- delegateHandler.mouseMoved(event);
- }
- }
-
- public void mousePressed(MouseEvent event)
- {
- if ( (table!=null) && (table.isEnabled()) )
- {
- // workaround bug - control key removes an existing selection
- if ( table.isEditing() && event.isControlDown() ) return;
-
- delegateHandler.mousePressed(event);
- }
- }
-
- public void mouseReleased(MouseEvent event)
- {
- if ( (table!=null) && (table.isEnabled()) )
- {
- delegateHandler.mouseReleased(event);
- }
- }
+ * BetterTableUI allows a JTable to be disabled by listening for MouseEvents and
+ * then forwarding them to the usual MouseInputHandler only if the table is
+ * enabled. <BR>
+ * <BR>
+ *
+ * This class also works around a bug where an editable table's selection is
+ * changed when clicking in an edit cell while the control key is down. This
+ * typically happened while users were copying/pasting data from cell to cell.
+ * <BR>
+ * <BR>
+ *
+ * To use, call <code>JTable.setUI()</code> on any JTable with a BetterTableUI
+ * as the parameter.
+ *
+ * @author michael@mpowers.net
+ * @version $Revision: 904 $
+ */
+public class BetterTableUI extends BasicTableUI implements MouseInputListener {
+ /**
+ * The listener to get all mouse events when the table is enabled.
+ */
+ protected MouseInputListener delegateHandler;
+
+ /**
+ * Overridden to set self as mouse listener and create delegate.
+ */
+ protected MouseInputListener createMouseInputListener() {
+ // normal handler is a protected inner class of parent
+ delegateHandler = new MouseInputHandler();
+
+ return this;
+ }
+
+ // interface MouseInputListener
+
+ public void mouseClicked(MouseEvent event) {
+ if ((table != null) && (table.isEnabled())) {
+ delegateHandler.mouseClicked(event);
+ }
+ }
+
+ public void mouseDragged(MouseEvent event) {
+ if ((table != null) && (table.isEnabled())) {
+ delegateHandler.mouseDragged(event);
+ }
+ }
+
+ public void mouseEntered(MouseEvent event) {
+ if ((table != null) && (table.isEnabled())) {
+ delegateHandler.mouseEntered(event);
+ }
+ }
+
+ public void mouseExited(MouseEvent event) {
+ if ((table != null) && (table.isEnabled())) {
+ delegateHandler.mouseExited(event);
+ }
+ }
+
+ public void mouseMoved(MouseEvent event) {
+ if ((table != null) && (table.isEnabled())) {
+ delegateHandler.mouseMoved(event);
+ }
+ }
+
+ public void mousePressed(MouseEvent event) {
+ if ((table != null) && (table.isEnabled())) {
+ // workaround bug - control key removes an existing selection
+ if (table.isEditing() && event.isControlDown())
+ return;
+
+ delegateHandler.mousePressed(event);
+ }
+ }
+
+ public void mouseReleased(MouseEvent event) {
+ if ((table != null) && (table.isEnabled())) {
+ delegateHandler.mouseReleased(event);
+ }
+ }
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ButtonPanel.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ButtonPanel.java
index 769e866..7d662ae 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ButtonPanel.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ButtonPanel.java
@@ -46,565 +46,527 @@ import javax.swing.JPanel;
import javax.swing.UIManager;
/**
-* ButtonPanel handles display and event broadcasting of standard buttons like
-* OK/Cancel/Save/etc. The constructor takes a list or array of strings, each
-* representing a button to appear on the panel from left to right.
-* Any button click will send an action event to all listeners with the action
-* command containing the corresponding string. Note action events are simply
-* forwarded from the buttons themselves, so the source of the event will be
-* the button, not the button panel. The button panel is the source of the
-* STATE_CHANGED events that notify about changes to the panel itself.<BR><BR>
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class ButtonPanel extends JPanel implements ActionListener, MouseMotionListener
-{
- // TODO: Button text should be read from resources.
-/**
-* Specifies a "OK" button.
-* This is also the action command sent by the OK button.
-*/
- public static final String OK = "OK";
-/**
-* Specifies a "Save" button.
-* This is also the action command sent by the Save button.
-*/
- public static final String SAVE = "Save";
-/**
-* Specifies a "Refresh" button.
-* This is also the action command sent by the Refresh button.
-*/
- public static final String REFRESH = "Refresh";
-/**
-* Specifies a "Clear All" button.
-* This is also the action command sent by the Clear All button.
-*/
- public static final String CLEAR_ALL = "Clear All";
-/**
-* Specifies a "Refresh" button.
-* This is also the action command sent by the Cancel button.
-*/
- public static final String CANCEL = "Cancel";
-/**
-* Specifies a "Yes" button.
-* This is also the action command sent by the Yes button.
-*/
- public static final String YES = "Yes";
-/**
-* Specifies a "No" button.
-* This is also the action command sent by the No button.
-*/
- public static final String NO = "No";
-/**
-* Specifies an "Add" button.
-* This is also the action command sent by the Add button.
-*/
- public static final String ADD = "Add";
-/**
-* Specifies a "Remove" button.
-* This is also the action command sent by the Remove button.
-*/
- public static final String REMOVE = "Remove";
-/**
-* This is the action command to all listeners when the button state is changed.
-*/
- public static final String STATE_CHANGED = "STATE_CHANGED";
-
-/**
-* This is the container to which buttons are added.
-*/
- protected Container buttonContainer = null; // useful for subclasses
-/**
-* This is the list of all buttons on the panel.
-*/
- protected Vector buttonList = null;
-/**
-* The insets for this panel, so they can be modified.
-*/
- protected Insets insets = new Insets( 5, 5, 5, 5 );
-
-/**
-* This is the layout manager - which must be a FlowLayout or subclass.
-*/
- protected FlowLayout buttonPanelLayout = null;
-
- // for action multicasting
- protected ActionListener actionListener = null;
-
-
-/**
-* Constructs a ButtonPanel. Three buttons are created
-* so the panel is filled when used in a GUI-builder environment.
-*/
- public ButtonPanel()
- {
- buttonList = new Vector();
- initLayout();
-
- // default labels for bean layout
- setLabels( new String[] { "One", "Two", "Three" } );
- }
-
-/**
-* This method is responsible for the initial layout of the panel.
-* Subclasses can implement different layouts, but this method
-* is responsible for initializing buttonContainer and buttonPanelLayout
-* and setting the container to use the layout.
-*/
- protected void initLayout()
- {
- this.setInsets( super.getInsets() );
- buttonContainer = this;
- buttonPanelLayout = new BetterFlowLayout( BetterFlowLayout.RIGHT );
- buttonContainer.setLayout(buttonPanelLayout);
- ((BetterFlowLayout)buttonPanelLayout).setWidthUniform( true );
-
- // setBackground( Color.blue ); // useful for debugging
- }
-
-/**
-* Constructs a ButtonPanel using specified buttons.
-* @param buttonList An array containing the strings to be used in labeling the buttons.
-*/
- public ButtonPanel( String[] buttonList )
- {
- this();
- setLabels( buttonList );
- }
-
-/**
-* Constructs a ButtonPane using specified actions. For each action, a button
-* is created, that when pressed the corresponding action is activated. The
-* "name" of the action is used as the title of the button.
-* @param actionList An array of actions to be used to create buttons with.
-*/
- public ButtonPanel( Action[] actionList )
- {
- this();
- setLabels( actionList );
- }
-
-/**
-* Creates the buttons to appear on the panel. Any existing buttons
-* are replaced. The labels are used as names and action commands
-* in addition to labels.
-* @param labels An array of strings to be used in labeling the buttons.
-* If null, all buttons will be removed.
-*/
- public void setLabels( String[] labels )
- {
- if ( labels == null )
- {
- labels = new String[] {};
- }
-
- buttonContainer.removeAll();
- this.buttonList = new Vector( labels.length );
-
- String item = null;
- Component button;
- for ( int i = 0; i < labels.length; i++ )
- {
- item = labels[i];
- if ( item != null )
- {
- button = createComponentWithLabel( item.toString() );
- this.buttonList.addElement( item );
- addComponentToPanel( button );
- button.setEnabled( this.isEnabled() );
-/*
- if ( i == 0 )
- {
- JRootPane root = SwingUtilities.getRootPane( button );
- if ( root != null )
- root.setDefaultButton( button );
- }
-*/
- }
- else
- {
- throw new IllegalArgumentException( "ButtonPanel.setButtons: nulls are not allowed." );
- }
- }
-
- this.revalidate();
- this.repaint();
- broadcastEvent( new ActionEvent( this, ActionEvent.ACTION_PERFORMED, STATE_CHANGED ) );
- }
-
-/**
-*
-*/
- public void setLabels( Action[] actions )
- {
- if ( actions == null )
- {
- actions = new Action[] {};
- }
-
- buttonContainer.removeAll();
- this.buttonList = new Vector( actions.length );
-
- Action action = null;
- Component button;
- for ( int i = 0; i < actions.length; i++ )
- {
- action = actions[i];
- if ( action != null )
- {
- String name = ( String )action.getValue( Action.NAME );
- button = createComponentWithLabel( name );
- this.buttonList.addElement( name );
- addComponentToPanel( button );
- button.setEnabled( this.isEnabled() ? action.isEnabled() : false );
-
- // Add the action to the "button" if it knows about action listeners.
- try
- {
- Method addActionListenerMethod =
- button.getClass().getMethod( "addActionListener", new Class[] { ActionListener.class } );
- addActionListenerMethod.invoke( button, new Object[] { action } );
- }
- catch ( NoSuchMethodException e ) { /* Do Nothing */ }
- catch ( IllegalAccessException e ) { e.printStackTrace(); /* TODO: Do Something? */ }
- catch ( InvocationTargetException e ) { e.printStackTrace(); /* TODO: Do Something? */ }
-
- // Create a new listener for property change events and have
- // the action broadcast to that listener.
- PropertyChangeListener pcListener = new ActionChangeListener( button );
- action.addPropertyChangeListener( pcListener );
- }
- else
- {
- throw new IllegalArgumentException( "ButtonPanel.setButtons: nulls are not allowed." );
- }
- }
-
- this.revalidate();
- this.repaint();
- broadcastEvent( new ActionEvent( this, ActionEvent.ACTION_PERFORMED, STATE_CHANGED ) );
- }
-
-
-/**
-* Gets the labels of the buttons that appear on the panel, ordered from left to right.
-* @return A new list containing strings used in labeling the buttons.
-*/
- public String[] getLabels()
- {
- String[] labels = new String[ buttonList.size() ];
- int i = 0;
- for ( Enumeration it = buttonList.elements(); it.hasMoreElements(); )
- {
- labels[i++] = it.nextElement().toString();
- }
- return labels;
- }
-
-/**
-* Gets the first component having the specified name.
-* @return A component with the specified name, or null if none match.
-*/
- public Component getButton( String aLabel )
- {
- if ( aLabel == null ) return null;
-
- Component c = null;
- int count = buttonContainer.getComponentCount();
- for ( int i = 0; i < count; i++ )
- {
- c = buttonContainer.getComponent( i );
- if ( aLabel.equals( c.getName() ) )
- {
- return c;
- }
- }
- return null;
- }
-
-/**
-* Creates a new component with the specified label.
-* The label is also used for the component's name
-* and action command, if any.
-* (This implementation returns a JButton.)
-* @param aLabel The label for the component that will be created.
-* @return The newly created component.
-*/
- protected Component createComponentWithLabel( String aLabel )
- {
- String buttonLabel = aLabel; // TODO: get string from resource
- JButton newButton = new JButton(); // might allow other types in future
- newButton.setName( aLabel );
- newButton.setText( buttonLabel );
- newButton.setActionCommand( aLabel );
- newButton.addActionListener( this );
- return newButton;
- }
-
-/**
-* Adds a component to the right-most side of the layout.
-* @param aComponent The component to be added to the layout.
-*/
- protected void addComponentToPanel( Component aComponent )
- {
- buttonContainer.add( aComponent );
- }
-
-
-/**
-* Changes the alignment of the buttons in the panel. Defaults to right-justified.
-* @param alignment A valid alignment code, per BetterFlowLayout implementation.
-* @see BetterFlowLayout
-*/
- public void setAlignment( int alignment )
- {
- buttonPanelLayout.setAlignment(alignment);
- buttonContainer.doLayout();
- }
-/**
-* Gets the alignment of the buttons in the panel.
-* @return An alignment code, per FlowLayout implementation.
-* @see FlowLayout
-*/
- public int getAlignment()
- {
- return buttonPanelLayout.getAlignment();
- }
-
-/**
-* Changes the horizontal spacing between components in the panel.
-* @param newHgap the new spacing, in pixels. May not be negative.
-*/
- public void setHgap( int newHgap )
- {
- if ( newHgap < 0 ) return; // may not be negative
- buttonPanelLayout.setHgap( newHgap );
- }
-
-/**
-* Gets the current horizontal spacing between components.
-* @return the current horizontal spacing, in pixels.
-*/
- public int getHgap()
- {
- return buttonPanelLayout.getHgap();
- }
-
-/**
-* Changes the vertical spacing between components in the panel.
-* @param newVgap the new spacing, in pixels. May not be negative.
-*/
- public void setVgap( int newVgap )
- {
- if ( newVgap < 0 ) return; // may not be negative
- buttonPanelLayout.setVgap( newVgap );
- }
-
-/**
-* Gets the current vertical spacing between components.
-* @return the current vertical spacing, in pixels.
-*/
- public int getVgap()
- {
- return buttonPanelLayout.getVgap();
- }
-
-/**
-* Changes the insets for this panel.
-* @param newInsets the new insets.
-*/
- public void setInsets( Insets newInsets )
- {
- insets = newInsets;
- }
-
-/**
-* Overridden to return the user-specified insets for this panel.
-* @return the current insets for this panel.
-*/
- public Insets getInsets()
- {
- return insets;
- }
-
-/**
-* Overridden to call setEnabled on all components on panel.
-* @param isEnabled whether to enable the panel and all components on it.
-*/
- public void setEnabled( boolean isEnabled )
- {
- super.setEnabled( isEnabled );
- int count = buttonContainer.getComponentCount();
- for ( int i = 0; i < count; i++ )
- {
- buttonContainer.getComponent( i ).setEnabled( isEnabled );
- }
- }
-
- // Action Multicast methods
-
-/**
-* Adds an action listener to the list that will be
-* notified by button events and changes in button state.
-* @param l An action listener to be notified.
-*/
- public void addActionListener(ActionListener l)
- {
- actionListener = AWTEventMulticaster.add(actionListener, l);
- }
-/**
-* Removes an action listener from the list that will be
-* notified by button events and changes in button state.
-* @param l An action listener to be removed.
-*/
- public void removeActionListener(ActionListener l)
- {
- actionListener = AWTEventMulticaster.remove(actionListener, l);
- }
-/**
-* Notifies all registered action listeners of a pending Action Event.
-* @param e An action event to be broadcast.
-*/
- protected void broadcastEvent(ActionEvent e)
- {
- if (actionListener != null)
- {
- actionListener.actionPerformed(e);
- }
- }
-
- // interface ActionListener
-
-/**
-* Called by buttons on panel and by other components that
-* might be set to broadcast events to this listener.
-* @param e An action event to be received.
-*/
- public void actionPerformed(ActionEvent e)
- {
- broadcastEvent(e);
- }
-
-/**
-* A property change listener that listens specifically for property changes
-* from action objects. This is the class that ties in the action to the
-* button. This class is added to an action as a property change listener.
-* The corresponding component is referenced by this class toe easily handle
-* updates to the component caused by changes to the action.
-*/
- public class ActionChangeListener implements PropertyChangeListener
- {
- /** The UI component that is affected by the action's changes. */
- Component theComponent;
-
- /**
- * Constructs an ActionChangeListener with the given component being
- * the recipient of the action's changes.
- * @param The component to bind with the action.
- */
- public ActionChangeListener( Component aComponent )
- {
- super();
- theComponent = aComponent;
- }
-
- /**
- * Called whenever a property changes on the action object.
- * @pram e The property change event generated by the action.
- */
- public void propertyChange( PropertyChangeEvent e )
- {
- String propertyName = e.getPropertyName();
- if ( propertyName.equals( Action.NAME ) )
- {
- String name = ( String )e.getNewValue();
- if ( theComponent instanceof AbstractButton )
- {
- AbstractButton button = ( AbstractButton )theComponent;
- String oldName = button.getName();
- button.setText( name );
- button.setName( name );
- button.setActionCommand( name );
-
- // Replace the old name of the component with the new name
- // in the ButtonPanel's list of components.
- buttonList.setElementAt( name, buttonList.indexOf( oldName ) );
- }
-
- // TODO: If component is not a button (or doesn't define the getText()
- // then what should be done.
- }
- else if ( propertyName.equals( "enabled" ) )
- {
- Boolean enabled = ( Boolean )e.getNewValue();
- theComponent.setEnabled( ButtonPanel.this.isEnabled() ? enabled.booleanValue() : false );
- }
-
- // TODO: Icon?
- }
- }
-
-
- // for testing
-
- public static void main( String[] argv )
- {
- try
- {
- UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
- }
- catch (Exception exc)
- {
-
- }
-
- JFrame dialog = new JFrame();
- BorderLayout bl = new BorderLayout( 20, 20 );
-
- ButtonPanel panel = new ButtonPanel();
+ * ButtonPanel handles display and event broadcasting of standard buttons like
+ * OK/Cancel/Save/etc. The constructor takes a list or array of strings, each
+ * representing a button to appear on the panel from left to right. Any button
+ * click will send an action event to all listeners with the action command
+ * containing the corresponding string. Note action events are simply forwarded
+ * from the buttons themselves, so the source of the event will be the button,
+ * not the button panel. The button panel is the source of the STATE_CHANGED
+ * events that notify about changes to the panel itself.<BR>
+ * <BR>
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class ButtonPanel extends JPanel implements ActionListener, MouseMotionListener {
+ // TODO: Button text should be read from resources.
+ /**
+ * Specifies a "OK" button. This is also the action command sent by the OK
+ * button.
+ */
+ public static final String OK = "OK";
+ /**
+ * Specifies a "Save" button. This is also the action command sent by the Save
+ * button.
+ */
+ public static final String SAVE = "Save";
+ /**
+ * Specifies a "Refresh" button. This is also the action command sent by the
+ * Refresh button.
+ */
+ public static final String REFRESH = "Refresh";
+ /**
+ * Specifies a "Clear All" button. This is also the action command sent by the
+ * Clear All button.
+ */
+ public static final String CLEAR_ALL = "Clear All";
+ /**
+ * Specifies a "Refresh" button. This is also the action command sent by the
+ * Cancel button.
+ */
+ public static final String CANCEL = "Cancel";
+ /**
+ * Specifies a "Yes" button. This is also the action command sent by the Yes
+ * button.
+ */
+ public static final String YES = "Yes";
+ /**
+ * Specifies a "No" button. This is also the action command sent by the No
+ * button.
+ */
+ public static final String NO = "No";
+ /**
+ * Specifies an "Add" button. This is also the action command sent by the Add
+ * button.
+ */
+ public static final String ADD = "Add";
+ /**
+ * Specifies a "Remove" button. This is also the action command sent by the
+ * Remove button.
+ */
+ public static final String REMOVE = "Remove";
+ /**
+ * This is the action command to all listeners when the button state is changed.
+ */
+ public static final String STATE_CHANGED = "STATE_CHANGED";
+
+ /**
+ * This is the container to which buttons are added.
+ */
+ protected Container buttonContainer = null; // useful for subclasses
+ /**
+ * This is the list of all buttons on the panel.
+ */
+ protected Vector buttonList = null;
+ /**
+ * The insets for this panel, so they can be modified.
+ */
+ protected Insets insets = new Insets(5, 5, 5, 5);
+
+ /**
+ * This is the layout manager - which must be a FlowLayout or subclass.
+ */
+ protected FlowLayout buttonPanelLayout = null;
+
+ // for action multicasting
+ protected ActionListener actionListener = null;
+
+ /**
+ * Constructs a ButtonPanel. Three buttons are created so the panel is filled
+ * when used in a GUI-builder environment.
+ */
+ public ButtonPanel() {
+ buttonList = new Vector();
+ initLayout();
+
+ // default labels for bean layout
+ setLabels(new String[] { "One", "Two", "Three" });
+ }
+
+ /**
+ * This method is responsible for the initial layout of the panel. Subclasses
+ * can implement different layouts, but this method is responsible for
+ * initializing buttonContainer and buttonPanelLayout and setting the container
+ * to use the layout.
+ */
+ protected void initLayout() {
+ this.setInsets(super.getInsets());
+ buttonContainer = this;
+ buttonPanelLayout = new BetterFlowLayout(BetterFlowLayout.RIGHT);
+ buttonContainer.setLayout(buttonPanelLayout);
+ ((BetterFlowLayout) buttonPanelLayout).setWidthUniform(true);
+
+ // setBackground( Color.blue ); // useful for debugging
+ }
+
+ /**
+ * Constructs a ButtonPanel using specified buttons.
+ *
+ * @param buttonList An array containing the strings to be used in labeling the
+ * buttons.
+ */
+ public ButtonPanel(String[] buttonList) {
+ this();
+ setLabels(buttonList);
+ }
+
+ /**
+ * Constructs a ButtonPane using specified actions. For each action, a button is
+ * created, that when pressed the corresponding action is activated. The "name"
+ * of the action is used as the title of the button.
+ *
+ * @param actionList An array of actions to be used to create buttons with.
+ */
+ public ButtonPanel(Action[] actionList) {
+ this();
+ setLabels(actionList);
+ }
+
+ /**
+ * Creates the buttons to appear on the panel. Any existing buttons are
+ * replaced. The labels are used as names and action commands in addition to
+ * labels.
+ *
+ * @param labels An array of strings to be used in labeling the buttons. If
+ * null, all buttons will be removed.
+ */
+ public void setLabels(String[] labels) {
+ if (labels == null) {
+ labels = new String[] {};
+ }
+
+ buttonContainer.removeAll();
+ this.buttonList = new Vector(labels.length);
+
+ String item = null;
+ Component button;
+ for (int i = 0; i < labels.length; i++) {
+ item = labels[i];
+ if (item != null) {
+ button = createComponentWithLabel(item.toString());
+ this.buttonList.addElement(item);
+ addComponentToPanel(button);
+ button.setEnabled(this.isEnabled());
+ /*
+ * if ( i == 0 ) { JRootPane root = SwingUtilities.getRootPane( button ); if (
+ * root != null ) root.setDefaultButton( button ); }
+ */
+ } else {
+ throw new IllegalArgumentException("ButtonPanel.setButtons: nulls are not allowed.");
+ }
+ }
+
+ this.revalidate();
+ this.repaint();
+ broadcastEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, STATE_CHANGED));
+ }
+
+ /**
+ *
+ */
+ public void setLabels(Action[] actions) {
+ if (actions == null) {
+ actions = new Action[] {};
+ }
+
+ buttonContainer.removeAll();
+ this.buttonList = new Vector(actions.length);
+
+ Action action = null;
+ Component button;
+ for (int i = 0; i < actions.length; i++) {
+ action = actions[i];
+ if (action != null) {
+ String name = (String) action.getValue(Action.NAME);
+ button = createComponentWithLabel(name);
+ this.buttonList.addElement(name);
+ addComponentToPanel(button);
+ button.setEnabled(this.isEnabled() ? action.isEnabled() : false);
+
+ // Add the action to the "button" if it knows about action listeners.
+ try {
+ Method addActionListenerMethod = button.getClass().getMethod("addActionListener",
+ new Class[] { ActionListener.class });
+ addActionListenerMethod.invoke(button, new Object[] { action });
+ } catch (NoSuchMethodException e) {
+ /* Do Nothing */ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ /* TODO: Do Something? */ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ /* TODO: Do Something? */ }
+
+ // Create a new listener for property change events and have
+ // the action broadcast to that listener.
+ PropertyChangeListener pcListener = new ActionChangeListener(button);
+ action.addPropertyChangeListener(pcListener);
+ } else {
+ throw new IllegalArgumentException("ButtonPanel.setButtons: nulls are not allowed.");
+ }
+ }
+
+ this.revalidate();
+ this.repaint();
+ broadcastEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, STATE_CHANGED));
+ }
+
+ /**
+ * Gets the labels of the buttons that appear on the panel, ordered from left to
+ * right.
+ *
+ * @return A new list containing strings used in labeling the buttons.
+ */
+ public String[] getLabels() {
+ String[] labels = new String[buttonList.size()];
+ int i = 0;
+ for (Enumeration it = buttonList.elements(); it.hasMoreElements();) {
+ labels[i++] = it.nextElement().toString();
+ }
+ return labels;
+ }
+
+ /**
+ * Gets the first component having the specified name.
+ *
+ * @return A component with the specified name, or null if none match.
+ */
+ public Component getButton(String aLabel) {
+ if (aLabel == null)
+ return null;
+
+ Component c = null;
+ int count = buttonContainer.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ c = buttonContainer.getComponent(i);
+ if (aLabel.equals(c.getName())) {
+ return c;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a new component with the specified label. The label is also used for
+ * the component's name and action command, if any. (This implementation returns
+ * a JButton.)
+ *
+ * @param aLabel The label for the component that will be created.
+ * @return The newly created component.
+ */
+ protected Component createComponentWithLabel(String aLabel) {
+ String buttonLabel = aLabel; // TODO: get string from resource
+ JButton newButton = new JButton(); // might allow other types in future
+ newButton.setName(aLabel);
+ newButton.setText(buttonLabel);
+ newButton.setActionCommand(aLabel);
+ newButton.addActionListener(this);
+ return newButton;
+ }
+
+ /**
+ * Adds a component to the right-most side of the layout.
+ *
+ * @param aComponent The component to be added to the layout.
+ */
+ protected void addComponentToPanel(Component aComponent) {
+ buttonContainer.add(aComponent);
+ }
+
+ /**
+ * Changes the alignment of the buttons in the panel. Defaults to
+ * right-justified.
+ *
+ * @param alignment A valid alignment code, per BetterFlowLayout implementation.
+ * @see BetterFlowLayout
+ */
+ public void setAlignment(int alignment) {
+ buttonPanelLayout.setAlignment(alignment);
+ buttonContainer.doLayout();
+ }
+
+ /**
+ * Gets the alignment of the buttons in the panel.
+ *
+ * @return An alignment code, per FlowLayout implementation.
+ * @see FlowLayout
+ */
+ public int getAlignment() {
+ return buttonPanelLayout.getAlignment();
+ }
+
+ /**
+ * Changes the horizontal spacing between components in the panel.
+ *
+ * @param newHgap the new spacing, in pixels. May not be negative.
+ */
+ public void setHgap(int newHgap) {
+ if (newHgap < 0)
+ return; // may not be negative
+ buttonPanelLayout.setHgap(newHgap);
+ }
+
+ /**
+ * Gets the current horizontal spacing between components.
+ *
+ * @return the current horizontal spacing, in pixels.
+ */
+ public int getHgap() {
+ return buttonPanelLayout.getHgap();
+ }
+
+ /**
+ * Changes the vertical spacing between components in the panel.
+ *
+ * @param newVgap the new spacing, in pixels. May not be negative.
+ */
+ public void setVgap(int newVgap) {
+ if (newVgap < 0)
+ return; // may not be negative
+ buttonPanelLayout.setVgap(newVgap);
+ }
+
+ /**
+ * Gets the current vertical spacing between components.
+ *
+ * @return the current vertical spacing, in pixels.
+ */
+ public int getVgap() {
+ return buttonPanelLayout.getVgap();
+ }
+
+ /**
+ * Changes the insets for this panel.
+ *
+ * @param newInsets the new insets.
+ */
+ public void setInsets(Insets newInsets) {
+ insets = newInsets;
+ }
+
+ /**
+ * Overridden to return the user-specified insets for this panel.
+ *
+ * @return the current insets for this panel.
+ */
+ public Insets getInsets() {
+ return insets;
+ }
+
+ /**
+ * Overridden to call setEnabled on all components on panel.
+ *
+ * @param isEnabled whether to enable the panel and all components on it.
+ */
+ public void setEnabled(boolean isEnabled) {
+ super.setEnabled(isEnabled);
+ int count = buttonContainer.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ buttonContainer.getComponent(i).setEnabled(isEnabled);
+ }
+ }
+
+ // Action Multicast methods
+
+ /**
+ * Adds an action listener to the list that will be notified by button events
+ * and changes in button state.
+ *
+ * @param l An action listener to be notified.
+ */
+ public void addActionListener(ActionListener l) {
+ actionListener = AWTEventMulticaster.add(actionListener, l);
+ }
+
+ /**
+ * Removes an action listener from the list that will be notified by button
+ * events and changes in button state.
+ *
+ * @param l An action listener to be removed.
+ */
+ public void removeActionListener(ActionListener l) {
+ actionListener = AWTEventMulticaster.remove(actionListener, l);
+ }
+
+ /**
+ * Notifies all registered action listeners of a pending Action Event.
+ *
+ * @param e An action event to be broadcast.
+ */
+ protected void broadcastEvent(ActionEvent e) {
+ if (actionListener != null) {
+ actionListener.actionPerformed(e);
+ }
+ }
+
+ // interface ActionListener
+
+ /**
+ * Called by buttons on panel and by other components that might be set to
+ * broadcast events to this listener.
+ *
+ * @param e An action event to be received.
+ */
+ public void actionPerformed(ActionEvent e) {
+ broadcastEvent(e);
+ }
+
+ /**
+ * A property change listener that listens specifically for property changes
+ * from action objects. This is the class that ties in the action to the button.
+ * This class is added to an action as a property change listener. The
+ * corresponding component is referenced by this class toe easily handle updates
+ * to the component caused by changes to the action.
+ */
+ public class ActionChangeListener implements PropertyChangeListener {
+ /** The UI component that is affected by the action's changes. */
+ Component theComponent;
+
+ /**
+ * Constructs an ActionChangeListener with the given component being the
+ * recipient of the action's changes.
+ *
+ * @param The component to bind with the action.
+ */
+ public ActionChangeListener(Component aComponent) {
+ super();
+ theComponent = aComponent;
+ }
+
+ /**
+ * Called whenever a property changes on the action object.
+ *
+ * @pram e The property change event generated by the action.
+ */
+ public void propertyChange(PropertyChangeEvent e) {
+ String propertyName = e.getPropertyName();
+ if (propertyName.equals(Action.NAME)) {
+ String name = (String) e.getNewValue();
+ if (theComponent instanceof AbstractButton) {
+ AbstractButton button = (AbstractButton) theComponent;
+ String oldName = button.getName();
+ button.setText(name);
+ button.setName(name);
+ button.setActionCommand(name);
+
+ // Replace the old name of the component with the new name
+ // in the ButtonPanel's list of components.
+ buttonList.setElementAt(name, buttonList.indexOf(oldName));
+ }
+
+ // TODO: If component is not a button (or doesn't define the getText()
+ // then what should be done.
+ } else if (propertyName.equals("enabled")) {
+ Boolean enabled = (Boolean) e.getNewValue();
+ theComponent.setEnabled(ButtonPanel.this.isEnabled() ? enabled.booleanValue() : false);
+ }
+
+ // TODO: Icon?
+ }
+ }
+
+ // for testing
+
+ public static void main(String[] argv) {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception exc) {
+
+ }
+
+ JFrame dialog = new JFrame();
+ BorderLayout bl = new BorderLayout(20, 20);
+
+ ButtonPanel panel = new ButtonPanel();
// ButtonPanel panel = new ButtonPanel( new String[] { "OkayOkay", "CancelCancel" } );
- dialog.getContentPane().setLayout( bl );
- dialog.getContentPane().add( panel, BorderLayout.CENTER );
- dialog.setLocation( 50, 50 );
- // dialog.setSize( 450, 150 );
-
- panel.setAlignment( BetterFlowLayout.CENTER_VERTICAL );
- panel.getButton( "One" ).setEnabled( false );
-
- dialog.pack();
- dialog.setVisible( true );
-
- try
- {
- BeanInfo info = Introspector.getBeanInfo( ButtonPanel.class );
- PropertyDescriptor[] props = info.getPropertyDescriptors();
- for ( int i = 0; i < props.length; i++ )
- {
- System.out.println( props[i].getName() );
- }
- }
- catch (Exception exc)
- {
- System.out.println( exc );
- }
+ dialog.getContentPane().setLayout(bl);
+ dialog.getContentPane().add(panel, BorderLayout.CENTER);
+ dialog.setLocation(50, 50);
+ // dialog.setSize( 450, 150 );
+ panel.setAlignment(BetterFlowLayout.CENTER_VERTICAL);
+ panel.getButton("One").setEnabled(false);
+ dialog.pack();
+ dialog.setVisible(true);
+ try {
+ BeanInfo info = Introspector.getBeanInfo(ButtonPanel.class);
+ PropertyDescriptor[] props = info.getPropertyDescriptors();
+ for (int i = 0; i < props.length; i++) {
+ System.out.println(props[i].getName());
+ }
+ } catch (Exception exc) {
+ System.out.println(exc);
+ }
- }
-
- public void mouseDragged(MouseEvent e)
- {
- }
-
- public void mouseMoved(MouseEvent e)
- {
- }
+ }
+ public void mouseDragged(MouseEvent e) {
+ }
+ public void mouseMoved(MouseEvent e) {
+ }
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/CheckButtonPanel.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/CheckButtonPanel.java
index 5e847ae..8116678 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/CheckButtonPanel.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/CheckButtonPanel.java
@@ -27,246 +27,223 @@ import javax.swing.JCheckBox;
import javax.swing.border.EmptyBorder;
/**
-* CheckButtonPanel is a simple extension of ButtonPanel.
-* Differences are that it uses JCheckBoxes and the
-* default alignment is vertical. The panel defaults to having
-* no buttons selected.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class CheckButtonPanel extends ButtonPanel
-{
-/**
-* Constructs a CheckButtonPanel. Three buttons are created
-* so the panel is filled when used in a GUI-builder environment.
-*/
- public CheckButtonPanel()
- {
- super();
- }
-
-/**
-* Constructs a ButtonPanel using specified buttons.
-* @param buttonList An array containing the strings to be used in labeling the buttons.
-*/
- public CheckButtonPanel( String[] buttonList )
- {
- super( buttonList );
- }
-
-/**
-* Overridden to set vertical-center alignment and zero vgap.
-*/
- protected void initLayout()
- {
- super.initLayout();
- buttonPanelLayout.setAlignment( BetterFlowLayout.CENTER_VERTICAL );
- buttonPanelLayout.setVgap( 0 );
- }
-
-/**
-* Overridden to return a JRadioButton.
-* @param aLabel The label for the component that will be created.
-* @return The newly created component.
-*/
- protected Component createComponentWithLabel( String aLabel )
- {
- String buttonLabel = aLabel;
- JCheckBox newButton = new JCheckBox();
- newButton.setName( aLabel );
- newButton.setText( buttonLabel );
- newButton.setActionCommand( aLabel );
- newButton.addActionListener( this );
-
- // reduce insets per java l&f guidelines (was 4 on each side)
- newButton.setBorder( new EmptyBorder( 1, 4, 1, 4 ) );
-
- return newButton;
- }
-
-/**
-* Sets the value of the button whose name matches the given text value.
-* @param aName A String matching the name of one of the buttons.
-* If null, empty, or not matching, nothing happens.
-* @param aValue A value to set the button.
-*/
- public void setValue(String aName, boolean aValue)
- {
- if ( aName != null )
- {
- Component c = null;
- int count = buttonContainer.getComponentCount();
- for ( int i = 0; i < count; i++ )
- {
- c = buttonContainer.getComponent( i );
- if ( c instanceof AbstractButton )
- {
- if ( c.getName().equals( aName ) )
- {
- ((AbstractButton)c).setSelected( aValue );
- c.repaint();
- return;
- }
- }
- }
- }
- // null, empty, or not matching - exit.
- System.out.println( "CheckButtonPanel.setValue: not found: " + aName );
- }
-
-/**
-* Sets the state of the specified buttons to the specified value.
-* @param aLabelArray An Array of Strings listing the buttons to be set.
-* @param aValue The value to which the specified buttons will be set.
-*/
- public void setValues(String[] aLabelArray, boolean aValue)
- {
- if ( aLabelArray != null )
- {
- for ( int i = 0; i < aLabelArray.length; i++ )
- {
- setValue( aLabelArray[i], aValue );
- }
- }
- }
-
-/**
-* Convenience method to set all checkboxes on the panel.
-* @param aValue The value to which all checkboxes on the panel will be set.
-*/
- public void setAllValues(boolean aValue)
- {
- setValues( getLabels(), aValue );
- }
-
-/**
-* Convenience method to check all boxes on the panel.
-*/
- public void checkAll()
- {
- setAllValues( true );
- }
-
-/**
-* Convenience method to clear all boxes on the panel.
-*/
- public void clearAll()
- {
- setAllValues( false );
- }
-
-/**
-* A convenience method to set only those buttons on the entire
-* panel that should be checked. Buttons not in the list are unchecked.
-* @param aLabelArray An Array of Strings listing the buttons to be set.
-*/
- public void setCheckedValues(String[] aLabelArray)
- {
- setAllValues( false );
- setValues( aLabelArray, true );
- }
-
-/**
-* Gets the labels of all checkboxes that are checked.
-* @return A List of Strings containing the labels of the boxes that are checked.
-*/
- public List getCheckedValueList()
- {
- Vector v = new Vector();
- Component c = null;
- int count = buttonContainer.getComponentCount();
- for ( int i = 0; i < count; i++ )
- {
- c = buttonContainer.getComponent( i );
- if ( c instanceof AbstractButton )
- {
- if ( ((AbstractButton)c).isSelected() )
- {
- v.addElement(c.getName());
- }
- }
- }
- return v;
- }
-
-/**
-* Gets the labels of all checkboxes that are checked.
-* @return A String Array containing the labels of the boxes that are checked.
-*/
- public String[] getCheckedValues()
- {
- List v = getCheckedValueList();
- String[] result = new String[ v.size() ];
- for ( int i = 0; i < v.size(); i++ )
- {
- result[i] = (String) v.get(i);
- }
- return result;
- }
-
-/**
-* Gets the value of the specified button.
-* @param aName A String matching the name of one of the buttons.
-* @return True if the button is checked, False if it is not checked.
-* NOTE: If the button is not found in the list, False is returned.
-*/
- public boolean getValue( String aName )
- {
- Component c = null;
- int count = buttonContainer.getComponentCount();
- for ( int i = 0; i < count; i++ )
- {
- c = buttonContainer.getComponent( i );
- if ( ( c instanceof AbstractButton ) && ( ((AbstractButton)c).isSelected() ) )
- {
- if ( ((AbstractButton)c).getText().equals( aName ) )
- {
- return ((AbstractButton)c).isSelected();
- }
- }
- }
- return false;
- }
-
- // for testing
-
- public static void main( String[] argv )
- {
- try
- {
- javax.swing.UIManager.setLookAndFeel( javax.swing.UIManager.getSystemLookAndFeelClassName() );
- }
- catch (Exception exc)
- {
-
- }
-
- javax.swing.JFrame dialog = new javax.swing.JFrame();
- java.awt.BorderLayout bl = new java.awt.BorderLayout( 20, 20 );
-
- CheckButtonPanel panel = new CheckButtonPanel( new String[] { "One", "Two", "Three" } );
-
- dialog.getContentPane().setLayout( bl );
- dialog.getContentPane().add( panel, java.awt.BorderLayout.CENTER );
- dialog.setLocation( 50, 50 );
- // dialog.setSize( 450, 150 );
-
- panel.setAlignment( BetterFlowLayout.CENTER_VERTICAL );
- panel.getButton( "One" ).setEnabled( false );
- panel.setValues( new String[] { "One" }, true );
- panel.setValue( "Three", true );
+ * CheckButtonPanel is a simple extension of ButtonPanel. Differences are that
+ * it uses JCheckBoxes and the default alignment is vertical. The panel defaults
+ * to having no buttons selected.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class CheckButtonPanel extends ButtonPanel {
+ /**
+ * Constructs a CheckButtonPanel. Three buttons are created so the panel is
+ * filled when used in a GUI-builder environment.
+ */
+ public CheckButtonPanel() {
+ super();
+ }
+
+ /**
+ * Constructs a ButtonPanel using specified buttons.
+ *
+ * @param buttonList An array containing the strings to be used in labeling the
+ * buttons.
+ */
+ public CheckButtonPanel(String[] buttonList) {
+ super(buttonList);
+ }
+
+ /**
+ * Overridden to set vertical-center alignment and zero vgap.
+ */
+ protected void initLayout() {
+ super.initLayout();
+ buttonPanelLayout.setAlignment(BetterFlowLayout.CENTER_VERTICAL);
+ buttonPanelLayout.setVgap(0);
+ }
+
+ /**
+ * Overridden to return a JRadioButton.
+ *
+ * @param aLabel The label for the component that will be created.
+ * @return The newly created component.
+ */
+ protected Component createComponentWithLabel(String aLabel) {
+ String buttonLabel = aLabel;
+ JCheckBox newButton = new JCheckBox();
+ newButton.setName(aLabel);
+ newButton.setText(buttonLabel);
+ newButton.setActionCommand(aLabel);
+ newButton.addActionListener(this);
+
+ // reduce insets per java l&f guidelines (was 4 on each side)
+ newButton.setBorder(new EmptyBorder(1, 4, 1, 4));
+
+ return newButton;
+ }
+
+ /**
+ * Sets the value of the button whose name matches the given text value.
+ *
+ * @param aName A String matching the name of one of the buttons. If null,
+ * empty, or not matching, nothing happens.
+ * @param aValue A value to set the button.
+ */
+ public void setValue(String aName, boolean aValue) {
+ if (aName != null) {
+ Component c = null;
+ int count = buttonContainer.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ c = buttonContainer.getComponent(i);
+ if (c instanceof AbstractButton) {
+ if (c.getName().equals(aName)) {
+ ((AbstractButton) c).setSelected(aValue);
+ c.repaint();
+ return;
+ }
+ }
+ }
+ }
+ // null, empty, or not matching - exit.
+ System.out.println("CheckButtonPanel.setValue: not found: " + aName);
+ }
+
+ /**
+ * Sets the state of the specified buttons to the specified value.
+ *
+ * @param aLabelArray An Array of Strings listing the buttons to be set.
+ * @param aValue The value to which the specified buttons will be set.
+ */
+ public void setValues(String[] aLabelArray, boolean aValue) {
+ if (aLabelArray != null) {
+ for (int i = 0; i < aLabelArray.length; i++) {
+ setValue(aLabelArray[i], aValue);
+ }
+ }
+ }
+
+ /**
+ * Convenience method to set all checkboxes on the panel.
+ *
+ * @param aValue The value to which all checkboxes on the panel will be set.
+ */
+ public void setAllValues(boolean aValue) {
+ setValues(getLabels(), aValue);
+ }
+
+ /**
+ * Convenience method to check all boxes on the panel.
+ */
+ public void checkAll() {
+ setAllValues(true);
+ }
+
+ /**
+ * Convenience method to clear all boxes on the panel.
+ */
+ public void clearAll() {
+ setAllValues(false);
+ }
+
+ /**
+ * A convenience method to set only those buttons on the entire panel that
+ * should be checked. Buttons not in the list are unchecked.
+ *
+ * @param aLabelArray An Array of Strings listing the buttons to be set.
+ */
+ public void setCheckedValues(String[] aLabelArray) {
+ setAllValues(false);
+ setValues(aLabelArray, true);
+ }
+
+ /**
+ * Gets the labels of all checkboxes that are checked.
+ *
+ * @return A List of Strings containing the labels of the boxes that are
+ * checked.
+ */
+ public List getCheckedValueList() {
+ Vector v = new Vector();
+ Component c = null;
+ int count = buttonContainer.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ c = buttonContainer.getComponent(i);
+ if (c instanceof AbstractButton) {
+ if (((AbstractButton) c).isSelected()) {
+ v.addElement(c.getName());
+ }
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Gets the labels of all checkboxes that are checked.
+ *
+ * @return A String Array containing the labels of the boxes that are checked.
+ */
+ public String[] getCheckedValues() {
+ List v = getCheckedValueList();
+ String[] result = new String[v.size()];
+ for (int i = 0; i < v.size(); i++) {
+ result[i] = (String) v.get(i);
+ }
+ return result;
+ }
+
+ /**
+ * Gets the value of the specified button.
+ *
+ * @param aName A String matching the name of one of the buttons.
+ * @return True if the button is checked, False if it is not checked. NOTE: If
+ * the button is not found in the list, False is returned.
+ */
+ public boolean getValue(String aName) {
+ Component c = null;
+ int count = buttonContainer.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ c = buttonContainer.getComponent(i);
+ if ((c instanceof AbstractButton) && (((AbstractButton) c).isSelected())) {
+ if (((AbstractButton) c).getText().equals(aName)) {
+ return ((AbstractButton) c).isSelected();
+ }
+ }
+ }
+ return false;
+ }
+
+ // for testing
+
+ public static void main(String[] argv) {
+ try {
+ javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception exc) {
+
+ }
+
+ javax.swing.JFrame dialog = new javax.swing.JFrame();
+ java.awt.BorderLayout bl = new java.awt.BorderLayout(20, 20);
+
+ CheckButtonPanel panel = new CheckButtonPanel(new String[] { "One", "Two", "Three" });
+
+ dialog.getContentPane().setLayout(bl);
+ dialog.getContentPane().add(panel, java.awt.BorderLayout.CENTER);
+ dialog.setLocation(50, 50);
+ // dialog.setSize( 450, 150 );
+
+ panel.setAlignment(BetterFlowLayout.CENTER_VERTICAL);
+ panel.getButton("One").setEnabled(false);
+ panel.setValues(new String[] { "One" }, true);
+ panel.setValue("Three", true);
// panel.setCheckedValues( new String[] { "Two" } );
- String[] values = panel.getCheckedValues();
- for ( int i = 0; i < values.length; i++ )
- {
- System.out.println( values[i] );
- }
+ String[] values = panel.getCheckedValues();
+ for (int i = 0; i < values.length; i++) {
+ System.out.println(values[i]);
+ }
- dialog.pack();
- dialog.setVisible( true );
+ dialog.pack();
+ dialog.setVisible(true);
- }
+ }
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellEditor.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellEditor.java
index a0a14ac..10feef7 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellEditor.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellEditor.java
@@ -29,56 +29,42 @@ import javax.swing.JCheckBox;
import javax.swing.JTable;
/**
-* A TableCellEditor that edits colors - it launches a color dialog when clicked.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
+ * A TableCellEditor that edits colors - it launches a color dialog when
+ * clicked.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
class ColorCellEditor extends DefaultCellEditor {
- Color currentColor = null;
-
- public ColorCellEditor(JButton b)
- {
- super(new JCheckBox()); // unfortunately, the constructor
- // expects a check box, combo box,
- // or text field.
- editorComponent = b;
- setClickCountToStart(1); // this is usually 1 or 2.
-
- // must do this so that editing stops when appropriate.
- b.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- fireEditingStopped();
- }
- }
- );
- }
-
- protected void fireEditingStopped()
- {
- super.fireEditingStopped();
- }
-
- public Object getCellEditorValue()
- {
- return currentColor;
- }
-
- public Component getTableCellEditorComponent(JTable table,
- Object value,
- boolean isSelected,
- int row,
- int column)
- {
- ((JButton)editorComponent).setText(value.toString());
- currentColor = (Color)value;
- return editorComponent;
- }
+ Color currentColor = null;
+
+ public ColorCellEditor(JButton b) {
+ super(new JCheckBox()); // unfortunately, the constructor
+ // expects a check box, combo box,
+ // or text field.
+ editorComponent = b;
+ setClickCountToStart(1); // this is usually 1 or 2.
+
+ // must do this so that editing stops when appropriate.
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ fireEditingStopped();
+ }
+ });
+ }
+
+ protected void fireEditingStopped() {
+ super.fireEditingStopped();
+ }
+
+ public Object getCellEditorValue() {
+ return currentColor;
+ }
+
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+ ((JButton) editorComponent).setText(value.toString());
+ currentColor = (Color) value;
+ return editorComponent;
+ }
}
-
-
-
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellRenderer.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellRenderer.java
index 0552183..2fc97bb 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellRenderer.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ColorCellRenderer.java
@@ -28,54 +28,39 @@ import javax.swing.border.Border;
import javax.swing.table.TableCellRenderer;
/**
-* A TableCellRenderer that renders colors.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
+ * A TableCellRenderer that renders colors.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
public class ColorCellRenderer extends JLabel implements TableCellRenderer {
- Border unselectedBorder = null;
- Border selectedBorder = null;
- boolean isBordered = true;
+ Border unselectedBorder = null;
+ Border selectedBorder = null;
+ boolean isBordered = true;
- public ColorCellRenderer(boolean isBordered)
- {
- super();
- this.isBordered = isBordered;
- setOpaque(true); // must do this for background to show up.
- }
+ public ColorCellRenderer(boolean isBordered) {
+ super();
+ this.isBordered = isBordered;
+ setOpaque(true); // must do this for background to show up.
+ }
- public Component getTableCellRendererComponent(
- JTable table, Object color,
- boolean isSelected, boolean hasFocus,
- int row, int column)
- {
- setBackground((Color)color);
- if (isBordered)
- {
- if (isSelected)
- {
- if (selectedBorder == null)
- {
- selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
- table.getSelectionBackground());
- }
- setBorder(selectedBorder);
- }
- else
- {
- if (unselectedBorder == null)
- {
- unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
- table.getBackground());
- }
- setBorder(unselectedBorder);
- }
- }
- return this;
- }
+ public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus,
+ int row, int column) {
+ setBackground((Color) color);
+ if (isBordered) {
+ if (isSelected) {
+ if (selectedBorder == null) {
+ selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getSelectionBackground());
+ }
+ setBorder(selectedBorder);
+ } else {
+ if (unselectedBorder == null) {
+ unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getBackground());
+ }
+ setBorder(unselectedBorder);
+ }
+ }
+ return this;
+ }
}
-
-
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ComboBoxCellRenderer.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ComboBoxCellRenderer.java
index 2bf8dd6..67cb726 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ComboBoxCellRenderer.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ComboBoxCellRenderer.java
@@ -26,32 +26,24 @@ import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
/**
-* A TableCellRenderer that paints a JComboBox. Useful if
-* you want to visibly display the JComboBox before the
-* user clicks on the cell.
-*
-* @author bsafa@intersectsoft.com
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
+ * A TableCellRenderer that paints a JComboBox. Useful if you want to visibly
+ * display the JComboBox before the user clicks on the cell.
+ *
+ * @author bsafa@intersectsoft.com
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
public class ComboBoxCellRenderer extends JComboBox implements TableCellRenderer {
- public ComboBoxCellRenderer()
- {
- super();
- setOpaque(true);
- }
-
- public Component getTableCellRendererComponent(
- JTable table, Object value,
- boolean isSelected, boolean hasFocus,
- int row, int column)
- {
- setBackground(Color.white);
- setSelectedItem(value);
- return this;
- }
+ public ComboBoxCellRenderer() {
+ super();
+ setOpaque(true);
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
+ int row, int column) {
+ setBackground(Color.white);
+ setSelectedItem(value);
+ return this;
+ }
}
-
-
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/DateTextField.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/DateTextField.java
index 18ed035..8a3b08c 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/DateTextField.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/DateTextField.java
@@ -30,601 +30,507 @@ import java.util.Vector;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
-
-/**
-* DateTextField is a "smart" text field that restricts the user's input. The
-* input is restructed to a string representing a date format.
-*
-* @author rob@straylight.princeton.com
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class DateTextField extends JTextField
-{
-
-/*******************************
-* CONSTANTS
-*******************************/
-
-/**
-* Use the current date for this text field.
-*/
- public static final int CURRENT_DATE = 0;
-
/**
-* Use blanks for this text field.
-*/
- public static final int BLANKS = 1;
-
-/**
-* Use underscores for this text field.
-*/
- public static final int UNDERSCORES = 2;
-
-/**
-* Use just a 4-digit year for this text field.
-*/
- public static final int YEAR = 3;
-
- private static final int BACKSPACE = 8;
- private static final int DELETE = 127;
- private static final int PASTE = 22; // Ctl-V
- private static final int CUT = 24; // Ctl-X
-
-
-/*******************************
-* DATA MEMEBERS
-*******************************/
- private int defaultType = CURRENT_DATE;
-
- private boolean warningMessageActive = false;
-
-
-/*******************************
-* PUBLIC METHODS
-*******************************/
-
-/**
-* Default Constructor.
-*/
- public DateTextField()
- {
- this(1, 1, 1999, 0);
-
- Calendar rightNow = Calendar.getInstance();
-
- super.setText(createDateString(rightNow.get(Calendar.MONTH) + 1,
- rightNow.get(Calendar.DATE),
- rightNow.get(Calendar.YEAR)));
- }
-
-/**
-* Constructor.
-* @param month Number of the month, January being 1.
-* @param data The day of the month.
-* @param year The year.
-*/
- public DateTextField(int month, int date, int year)
- {
- this(month, date, year, 0);
- }
-
-/**
-* Constructor.
-* @param columns Width of the text field (in characters).
-*/
- public DateTextField(int columns)
- {
- this(1, 1, 1998, columns);
-
- Calendar rightNow = Calendar.getInstance();
-
- super.setText(createDateString(rightNow.get(Calendar.MONTH) + 1,
- rightNow.get(Calendar.DATE),
- rightNow.get(Calendar.YEAR)));
- }
-
-/**
-* Constructor.
-* @param month Number of the month, January being 1.
-* @param data The day of the month.
-* @param year The year.
-* @param columns Width of the text field (in characters).
-*/
- public DateTextField(int month, int date, int year, int columns)
- {
- super("", columns);
-
- super.setText(createDateString(month, date, year));
-
- this.addFocusListener(new FocusAdapter()
- {
- public void focusLost(FocusEvent e)
- {
- if (!(e.isTemporary()))
- {
- validateDateString(e);
- }
- }
- });
- }
-
-/**
-* Sets the date type to display when the user has not entered any date yet.
-* Default is the current date.
-* @see #CURRENT_DATE
-* @see #BLANKS
-* @see #UNDERSCORES
-* @param newDefaultType The type of date to display when there is no date data.
-*/
- public void setDefaultType(int newDefaultType)
- {
- if (newDefaultType == BLANKS)
- {
- defaultType = BLANKS;
- super.setText(" / / ");
- }
- else if (newDefaultType == UNDERSCORES)
- {
- defaultType = UNDERSCORES;
- super.setText("__/__/____");
- }
- else if (newDefaultType == YEAR)
- {
- defaultType = YEAR;
- super.setText("0000");
- }
- else
- {
- defaultType = CURRENT_DATE;
-
- Calendar rightNow = Calendar.getInstance();
-
- super.setText(createDateString(rightNow.get(Calendar.MONTH) + 1,
- rightNow.get(Calendar.DATE),
- rightNow.get(Calendar.YEAR)));
- }
- }
-
-/**
-* Returns the type of date to display when there is no user input.
-* @see #CURRENT_DATE
-* @see #BLANKS
-* @see #UNDERSCORES
-* @return The type of date to display when there is no date to display.
-*/
- public int getDefaultType()
- {
- return defaultType;
- }
-
-/**
-* Sets the text field to the string representation of the specified date.
-* @param aDate The date to set the text field to.
-*/
- public void setDate(Date aDate)
- {
- Calendar aCalendar = Calendar.getInstance();
-
- aCalendar.setTime(aDate);
-
- super.setText(createDateString(aCalendar.get(Calendar.MONTH) + 1,
- aCalendar.get(Calendar.DATE),
- aCalendar.get(Calendar.YEAR)));
- }
-
-/**
-* Sets the text field directly from a Date object.
-* @param aDate The date to set the text field to.
-*/
- public void setText( Date aDate )
- {
- setDate( aDate );
- }
-
-/**
-* Sets the text field to the date specified in the string. This is overridden
-* from the parent class to insure a valid date is inputted. The format of the
-* date expected is the type of date format this text field is currently set to.
-* @param aString A string representing a date in this text field current format.
-*/
- public void setText( String aString )
- {
- Date testDate = null;
-
- if ( aString != null )
- {
- ParsePosition position = new ParsePosition( 0 );
-
- if ( defaultType == YEAR )
- {
- SimpleDateFormat yearFormatter = new SimpleDateFormat( "yyyy" );
- testDate = yearFormatter.parse( aString, position );
- }
- else
- {
- SimpleDateFormat fullDateFormatter = new SimpleDateFormat( "MM/dd/yyyy" );
- testDate = fullDateFormatter.parse( aString, position );
- }
- }
-
- // The string is not a valid date, use default value for date then.
- if ( testDate == null )
- {
- Calendar aCalendar = Calendar.getInstance();
-
- testDate = aCalendar.getTime();
- }
-
- setDate( testDate );
- }
-
-/**
-* Returns the date as represented by the date string in the text field.
-* @return The date in the text field.
-*/
- public Date getDate() throws NumberFormatException
- {
- Calendar aCalendar = Calendar.getInstance();
- int year = 1980;
- int month = 0;
- int date = 1;
- int[] tempArray = {1,3,5,7,8,10,12};
- Vector monthsWith31Days = new Vector(7);
-
- for (int i = 0; i < tempArray.length; ++i)
- {
- monthsWith31Days.addElement(new Integer(tempArray[i]));
- }
-
- aCalendar.set(year, month, date, 12, 0, 0);
-
- try
- {
- String dateString = getText();
- NumberFormatException nfException = new NumberFormatException(new String("Invalid Date String: " + dateString));
-
- if (defaultType == YEAR)
- {
- year = Integer.parseInt(dateString);
-
- aCalendar.set(year, 0, 1, 12, 0, 0);
-
- return aCalendar.getTime();
- }
-
- month = Integer.parseInt(dateString.substring(0, 2).trim());
- date = Integer.parseInt(dateString.substring(3, 5).trim());
- year = Integer.parseInt(dateString.substring(6).trim());
-
- if ((month < 1) || (month > 12))
- {
- throw nfException;
- }
-
- if ((date < 1) || (date > 31))
- {
- throw nfException;
- }
-
- if ((date == 31) && (!(monthsWith31Days.contains(new Integer(month)))))
- {
- throw nfException;
- }
-
- if ((date == 30) && (month == 2))
- {
- throw nfException;
- }
-
- if ((date == 29) && (month == 2))
- {
- if ((year % 100) == 0)
- {
- if ((year % 400) != 0)
- {
- throw nfException;
- }
- }
- else
- {
- if ((year % 4) != 0)
- {
- throw nfException;
- }
- }
- }
- }
- catch (IndexOutOfBoundsException ioobe)
- {
- NumberFormatException nfException = new NumberFormatException(new String("Invalid Date String: " + getText()));
- throw nfException;
- }
- catch (NumberFormatException nfe)
- {
- NumberFormatException nfException = new NumberFormatException(new String("Invalid Date String: " + getText()));
- throw nfException;
- }
-
- aCalendar.set(year, (month - 1), date, 12, 0, 0);
-
- return aCalendar.getTime();
- }
-
- public void processKeyEvent(KeyEvent e)
- {
- String currentString = "";
- String testString = "";
- char newChar = e.getKeyChar();
- int currentLength = 0;
- int currentCaretPosition = 0;
- int selectionStart = 0;
- int selectionEnd = 0;
- int modifierPosition = 0;
- int modifierDirection = 1;
- char modifierCharacter;
- boolean backspace = false;
- boolean delete = false;
- boolean paste = false;
- boolean cut = false;
- boolean keyPressed = false;
-
- backspace = (newChar == BACKSPACE);
- delete = (newChar == DELETE);
- paste = (newChar == PASTE);
- cut = (newChar == CUT);
-
- keyPressed = (e.paramString().startsWith("KEY_PRESSED"));
-
- if ((e.getKeyCode() == KeyEvent.VK_UNDEFINED) || ((backspace) || (delete) || (paste) || (cut))) // A "key-typed" event
- {
- if (isValidCharacter(newChar))
- {
- if ((isPrintableCharacter(newChar)) || (backspace) || (delete))
- {
- // Both the key "pressed" and key "released" events get passed
- // in here for the delete and backspace key. Only processes
- // these keys if the event is key "pressed".
- if (((backspace) || (delete)) && (!(keyPressed)))
- {
- // Don't do anything, pass through to consumption.
- }
- else
- {
- // Analyze the current contents of the field
- currentString = getText();
- currentLength = currentString.length();
-
- char[] tempText = new char[currentLength];
-
- currentCaretPosition = getCaretPosition();
-
- selectionStart = getSelectionStart();
- selectionEnd = getSelectionEnd();
-
- // if a range is selected, then get rid of it and place the caret
- // at the begginning of the range and continue processing.
- if (selectionStart != selectionEnd)
- {
- selectionEnd = selectionStart;
- setSelectionEnd(selectionEnd);
-
- currentCaretPosition = selectionStart;
- setCaretPosition(currentCaretPosition);
- }
-
- if (currentCaretPosition <= currentLength)
- {
- // a number of delete or backspace was pressed, delete and
- // backspace deletes a number and places a "space" there
-
- // if caret at start of string and the backspace pressed OR
- // caret at end of string and delete or number pressed THEN
- // don't do anything, otherwise process key stroke
- if (((currentCaretPosition == 0) && (backspace)) ||
- ((currentCaretPosition == currentLength) && (!(backspace))))
- {
- // Don't do any processing.
- }
- else
- {
- modifierPosition = currentCaretPosition;
- if (backspace)
- {
- modifierDirection = -1;
- modifierPosition += modifierDirection;
- }
-
- // Overwrite the current position with the new character
- // inputted or overwrite using a space or underscore if
- // the backspace or delete key was pressed.
- if (defaultType != YEAR)
- {
- modifierCharacter =
- ((delete)||(backspace)) ?
- ((defaultType == UNDERSCORES) ? '_' : ' ') :
- newChar;
- }
- else
- {
- // We are dealing with a 4-digit year. Overwrite
- // with new character or "0" if delete or backspace
- // was pressed.
- modifierCharacter = ((delete)||(backspace)) ? ('0') : newChar;
- }
-
- if (currentString.charAt(modifierPosition) == '/')
- {
- modifierPosition += modifierDirection;
- }
-
- for (int i = 0; i < currentLength; ++i)
- {
- if (i == modifierPosition)
- {
- tempText[i] = modifierCharacter;
- }
- else
- {
- tempText[i] = currentString.charAt(i);
- }
- }
-
- testString = new String(tempText);
- if (isValidString(testString))
- {
- super.setText(testString);
- if (backspace)
- {
- setCaretPosition(modifierPosition);
- }
- else
- {
- setCaretPosition(modifierPosition + 1);
- }
- }
- }
- }
- }
-
- e.consume();
- }
- else if ((cut) || (paste))
- {
- e.consume();
- }
- // else its a non-printable character, let it pass through
- }
- else
- {
- e.consume();
- }
- }
-
- super.processKeyEvent(e);
- }
-
- private boolean isValidCharacter(char aChar)
- {
- if (((aChar >= '!') && (aChar <= '/')) || ((aChar >= ':') && (aChar <= '~')))
- {
- return false;
- }
- return true;
- }
-
- private boolean isPrintableCharacter(char inputChar)
- {
- if ((inputChar >= ' ') && (inputChar <= '~'))
- {
- return true;
- }
- return false;
- }
-
- private boolean isValidDate(int month, int date, int year)
- {
- if ((month < 1) || (month > 12))
- {
- return false;
- }
-
- if ((date < 1) || (date > 31))
- {
- return false;
- }
-
- if ((year < 0) || (year > 9999))
- {
- return false;
- }
-
- return true;
- }
-
- private boolean isValidString(String aString)
- {
- return true;
- }
-
- private String createDateString(int month, int date, int year)
- {
- String dateString = "";
-
- if (isValidDate(month, date, year))
- {
- if (defaultType != YEAR)
- {
- if (month < 10)
- {
- dateString = "0";
- }
-
- dateString += String.valueOf(month);
- dateString += "/";
-
- if (date < 10)
- {
- dateString += "0";
- }
-
- dateString += String.valueOf(date);
- dateString += "/";
- }
-
- if (year < 1000)
- {
- dateString += "0";
- if (year < 100)
- {
- dateString += "0";
- if (year < 10)
- {
- dateString += "0";
- }
- }
- }
-
- dateString += String.valueOf(year);
- }
- else
- {
- if (defaultType == YEAR)
- {
- dateString = "1999";
- }
- else
- {
- dateString = "01/01/1999";
- }
- }
-
- return dateString;
- }
-
- private void validateDateString(FocusEvent e)
- {
- if (!(warningMessageActive))
- {
- try
- {
- getDate();
- }
- catch (NumberFormatException nfe)
- {
- System.out.println("Invalid Date String!!!");
- warningMessageActive = true;
- JOptionPane.showMessageDialog(this, "Invald Date: " + getText(), "Warning", JOptionPane.WARNING_MESSAGE);
- warningMessageActive = false;
- if (defaultType == YEAR)
- {
- super.setText("1999");
- }
- else
- {
- super.setText("01/01/1999");
- }
- }
- }
- }
+ * DateTextField is a "smart" text field that restricts the user's input. The
+ * input is restructed to a string representing a date format.
+ *
+ * @author rob@straylight.princeton.com
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class DateTextField extends JTextField {
+
+ /*******************************
+ * CONSTANTS
+ *******************************/
+
+ /**
+ * Use the current date for this text field.
+ */
+ public static final int CURRENT_DATE = 0;
+
+ /**
+ * Use blanks for this text field.
+ */
+ public static final int BLANKS = 1;
+
+ /**
+ * Use underscores for this text field.
+ */
+ public static final int UNDERSCORES = 2;
+
+ /**
+ * Use just a 4-digit year for this text field.
+ */
+ public static final int YEAR = 3;
+
+ private static final int BACKSPACE = 8;
+ private static final int DELETE = 127;
+ private static final int PASTE = 22; // Ctl-V
+ private static final int CUT = 24; // Ctl-X
+
+ /*******************************
+ * DATA MEMEBERS
+ *******************************/
+ private int defaultType = CURRENT_DATE;
+
+ private boolean warningMessageActive = false;
+
+ /*******************************
+ * PUBLIC METHODS
+ *******************************/
+
+ /**
+ * Default Constructor.
+ */
+ public DateTextField() {
+ this(1, 1, 1999, 0);
+
+ Calendar rightNow = Calendar.getInstance();
+
+ super.setText(createDateString(rightNow.get(Calendar.MONTH) + 1, rightNow.get(Calendar.DATE),
+ rightNow.get(Calendar.YEAR)));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param month Number of the month, January being 1.
+ * @param data The day of the month.
+ * @param year The year.
+ */
+ public DateTextField(int month, int date, int year) {
+ this(month, date, year, 0);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param columns Width of the text field (in characters).
+ */
+ public DateTextField(int columns) {
+ this(1, 1, 1998, columns);
+
+ Calendar rightNow = Calendar.getInstance();
+
+ super.setText(createDateString(rightNow.get(Calendar.MONTH) + 1, rightNow.get(Calendar.DATE),
+ rightNow.get(Calendar.YEAR)));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param month Number of the month, January being 1.
+ * @param data The day of the month.
+ * @param year The year.
+ * @param columns Width of the text field (in characters).
+ */
+ public DateTextField(int month, int date, int year, int columns) {
+ super("", columns);
+
+ super.setText(createDateString(month, date, year));
+
+ this.addFocusListener(new FocusAdapter() {
+ public void focusLost(FocusEvent e) {
+ if (!(e.isTemporary())) {
+ validateDateString(e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Sets the date type to display when the user has not entered any date yet.
+ * Default is the current date.
+ *
+ * @see #CURRENT_DATE
+ * @see #BLANKS
+ * @see #UNDERSCORES
+ * @param newDefaultType The type of date to display when there is no date data.
+ */
+ public void setDefaultType(int newDefaultType) {
+ if (newDefaultType == BLANKS) {
+ defaultType = BLANKS;
+ super.setText(" / / ");
+ } else if (newDefaultType == UNDERSCORES) {
+ defaultType = UNDERSCORES;
+ super.setText("__/__/____");
+ } else if (newDefaultType == YEAR) {
+ defaultType = YEAR;
+ super.setText("0000");
+ } else {
+ defaultType = CURRENT_DATE;
+
+ Calendar rightNow = Calendar.getInstance();
+
+ super.setText(createDateString(rightNow.get(Calendar.MONTH) + 1, rightNow.get(Calendar.DATE),
+ rightNow.get(Calendar.YEAR)));
+ }
+ }
+
+ /**
+ * Returns the type of date to display when there is no user input.
+ *
+ * @see #CURRENT_DATE
+ * @see #BLANKS
+ * @see #UNDERSCORES
+ * @return The type of date to display when there is no date to display.
+ */
+ public int getDefaultType() {
+ return defaultType;
+ }
+
+ /**
+ * Sets the text field to the string representation of the specified date.
+ *
+ * @param aDate The date to set the text field to.
+ */
+ public void setDate(Date aDate) {
+ Calendar aCalendar = Calendar.getInstance();
+
+ aCalendar.setTime(aDate);
+
+ super.setText(createDateString(aCalendar.get(Calendar.MONTH) + 1, aCalendar.get(Calendar.DATE),
+ aCalendar.get(Calendar.YEAR)));
+ }
+
+ /**
+ * Sets the text field directly from a Date object.
+ *
+ * @param aDate The date to set the text field to.
+ */
+ public void setText(Date aDate) {
+ setDate(aDate);
+ }
+
+ /**
+ * Sets the text field to the date specified in the string. This is overridden
+ * from the parent class to insure a valid date is inputted. The format of the
+ * date expected is the type of date format this text field is currently set to.
+ *
+ * @param aString A string representing a date in this text field current
+ * format.
+ */
+ public void setText(String aString) {
+ Date testDate = null;
+
+ if (aString != null) {
+ ParsePosition position = new ParsePosition(0);
+
+ if (defaultType == YEAR) {
+ SimpleDateFormat yearFormatter = new SimpleDateFormat("yyyy");
+ testDate = yearFormatter.parse(aString, position);
+ } else {
+ SimpleDateFormat fullDateFormatter = new SimpleDateFormat("MM/dd/yyyy");
+ testDate = fullDateFormatter.parse(aString, position);
+ }
+ }
+
+ // The string is not a valid date, use default value for date then.
+ if (testDate == null) {
+ Calendar aCalendar = Calendar.getInstance();
+
+ testDate = aCalendar.getTime();
+ }
+
+ setDate(testDate);
+ }
+
+ /**
+ * Returns the date as represented by the date string in the text field.
+ *
+ * @return The date in the text field.
+ */
+ public Date getDate() throws NumberFormatException {
+ Calendar aCalendar = Calendar.getInstance();
+ int year = 1980;
+ int month = 0;
+ int date = 1;
+ int[] tempArray = { 1, 3, 5, 7, 8, 10, 12 };
+ Vector monthsWith31Days = new Vector(7);
+
+ for (int i = 0; i < tempArray.length; ++i) {
+ monthsWith31Days.addElement(new Integer(tempArray[i]));
+ }
+
+ aCalendar.set(year, month, date, 12, 0, 0);
+
+ try {
+ String dateString = getText();
+ NumberFormatException nfException = new NumberFormatException(
+ new String("Invalid Date String: " + dateString));
+
+ if (defaultType == YEAR) {
+ year = Integer.parseInt(dateString);
+
+ aCalendar.set(year, 0, 1, 12, 0, 0);
+
+ return aCalendar.getTime();
+ }
+
+ month = Integer.parseInt(dateString.substring(0, 2).trim());
+ date = Integer.parseInt(dateString.substring(3, 5).trim());
+ year = Integer.parseInt(dateString.substring(6).trim());
+
+ if ((month < 1) || (month > 12)) {
+ throw nfException;
+ }
+
+ if ((date < 1) || (date > 31)) {
+ throw nfException;
+ }
+
+ if ((date == 31) && (!(monthsWith31Days.contains(new Integer(month))))) {
+ throw nfException;
+ }
+
+ if ((date == 30) && (month == 2)) {
+ throw nfException;
+ }
+
+ if ((date == 29) && (month == 2)) {
+ if ((year % 100) == 0) {
+ if ((year % 400) != 0) {
+ throw nfException;
+ }
+ } else {
+ if ((year % 4) != 0) {
+ throw nfException;
+ }
+ }
+ }
+ } catch (IndexOutOfBoundsException ioobe) {
+ NumberFormatException nfException = new NumberFormatException(
+ new String("Invalid Date String: " + getText()));
+ throw nfException;
+ } catch (NumberFormatException nfe) {
+ NumberFormatException nfException = new NumberFormatException(
+ new String("Invalid Date String: " + getText()));
+ throw nfException;
+ }
+
+ aCalendar.set(year, (month - 1), date, 12, 0, 0);
+
+ return aCalendar.getTime();
+ }
+
+ public void processKeyEvent(KeyEvent e) {
+ String currentString = "";
+ String testString = "";
+ char newChar = e.getKeyChar();
+ int currentLength = 0;
+ int currentCaretPosition = 0;
+ int selectionStart = 0;
+ int selectionEnd = 0;
+ int modifierPosition = 0;
+ int modifierDirection = 1;
+ char modifierCharacter;
+ boolean backspace = false;
+ boolean delete = false;
+ boolean paste = false;
+ boolean cut = false;
+ boolean keyPressed = false;
+
+ backspace = (newChar == BACKSPACE);
+ delete = (newChar == DELETE);
+ paste = (newChar == PASTE);
+ cut = (newChar == CUT);
+
+ keyPressed = (e.paramString().startsWith("KEY_PRESSED"));
+
+ if ((e.getKeyCode() == KeyEvent.VK_UNDEFINED) || ((backspace) || (delete) || (paste) || (cut))) // A "key-typed"
+ // event
+ {
+ if (isValidCharacter(newChar)) {
+ if ((isPrintableCharacter(newChar)) || (backspace) || (delete)) {
+ // Both the key "pressed" and key "released" events get passed
+ // in here for the delete and backspace key. Only processes
+ // these keys if the event is key "pressed".
+ if (((backspace) || (delete)) && (!(keyPressed))) {
+ // Don't do anything, pass through to consumption.
+ } else {
+ // Analyze the current contents of the field
+ currentString = getText();
+ currentLength = currentString.length();
+
+ char[] tempText = new char[currentLength];
+
+ currentCaretPosition = getCaretPosition();
+
+ selectionStart = getSelectionStart();
+ selectionEnd = getSelectionEnd();
+
+ // if a range is selected, then get rid of it and place the caret
+ // at the begginning of the range and continue processing.
+ if (selectionStart != selectionEnd) {
+ selectionEnd = selectionStart;
+ setSelectionEnd(selectionEnd);
+
+ currentCaretPosition = selectionStart;
+ setCaretPosition(currentCaretPosition);
+ }
+
+ if (currentCaretPosition <= currentLength) {
+ // a number of delete or backspace was pressed, delete and
+ // backspace deletes a number and places a "space" there
+
+ // if caret at start of string and the backspace pressed OR
+ // caret at end of string and delete or number pressed THEN
+ // don't do anything, otherwise process key stroke
+ if (((currentCaretPosition == 0) && (backspace))
+ || ((currentCaretPosition == currentLength) && (!(backspace)))) {
+ // Don't do any processing.
+ } else {
+ modifierPosition = currentCaretPosition;
+ if (backspace) {
+ modifierDirection = -1;
+ modifierPosition += modifierDirection;
+ }
+
+ // Overwrite the current position with the new character
+ // inputted or overwrite using a space or underscore if
+ // the backspace or delete key was pressed.
+ if (defaultType != YEAR) {
+ modifierCharacter = ((delete) || (backspace))
+ ? ((defaultType == UNDERSCORES) ? '_' : ' ')
+ : newChar;
+ } else {
+ // We are dealing with a 4-digit year. Overwrite
+ // with new character or "0" if delete or backspace
+ // was pressed.
+ modifierCharacter = ((delete) || (backspace)) ? ('0') : newChar;
+ }
+
+ if (currentString.charAt(modifierPosition) == '/') {
+ modifierPosition += modifierDirection;
+ }
+
+ for (int i = 0; i < currentLength; ++i) {
+ if (i == modifierPosition) {
+ tempText[i] = modifierCharacter;
+ } else {
+ tempText[i] = currentString.charAt(i);
+ }
+ }
+
+ testString = new String(tempText);
+ if (isValidString(testString)) {
+ super.setText(testString);
+ if (backspace) {
+ setCaretPosition(modifierPosition);
+ } else {
+ setCaretPosition(modifierPosition + 1);
+ }
+ }
+ }
+ }
+ }
+
+ e.consume();
+ } else if ((cut) || (paste)) {
+ e.consume();
+ }
+ // else its a non-printable character, let it pass through
+ } else {
+ e.consume();
+ }
+ }
+
+ super.processKeyEvent(e);
+ }
+
+ private boolean isValidCharacter(char aChar) {
+ if (((aChar >= '!') && (aChar <= '/')) || ((aChar >= ':') && (aChar <= '~'))) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isPrintableCharacter(char inputChar) {
+ if ((inputChar >= ' ') && (inputChar <= '~')) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isValidDate(int month, int date, int year) {
+ if ((month < 1) || (month > 12)) {
+ return false;
+ }
+
+ if ((date < 1) || (date > 31)) {
+ return false;
+ }
+
+ if ((year < 0) || (year > 9999)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean isValidString(String aString) {
+ return true;
+ }
+
+ private String createDateString(int month, int date, int year) {
+ String dateString = "";
+
+ if (isValidDate(month, date, year)) {
+ if (defaultType != YEAR) {
+ if (month < 10) {
+ dateString = "0";
+ }
+
+ dateString += String.valueOf(month);
+ dateString += "/";
+
+ if (date < 10) {
+ dateString += "0";
+ }
+
+ dateString += String.valueOf(date);
+ dateString += "/";
+ }
+
+ if (year < 1000) {
+ dateString += "0";
+ if (year < 100) {
+ dateString += "0";
+ if (year < 10) {
+ dateString += "0";
+ }
+ }
+ }
+
+ dateString += String.valueOf(year);
+ } else {
+ if (defaultType == YEAR) {
+ dateString = "1999";
+ } else {
+ dateString = "01/01/1999";
+ }
+ }
+
+ return dateString;
+ }
+
+ private void validateDateString(FocusEvent e) {
+ if (!(warningMessageActive)) {
+ try {
+ getDate();
+ } catch (NumberFormatException nfe) {
+ System.out.println("Invalid Date String!!!");
+ warningMessageActive = true;
+ JOptionPane.showMessageDialog(this, "Invald Date: " + getText(), "Warning",
+ JOptionPane.WARNING_MESSAGE);
+ warningMessageActive = false;
+ if (defaultType == YEAR) {
+ super.setText("1999");
+ } else {
+ super.setText("01/01/1999");
+ }
+ }
+ }
+ }
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/FormattedCellRenderer.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/FormattedCellRenderer.java
index b3e2a76..10b1b89 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/FormattedCellRenderer.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/FormattedCellRenderer.java
@@ -27,101 +27,92 @@ import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
/**
-* A cell renderer for dealing with formatted content.
-* Subclasses can specify formats or colors or styles for specific values
-* or locations in the table by overridding getFormatForContext(),
-* getForegroundForContext() and/or getBackgroundForContext().
-*
-* @author michael@mpowers.net
-* @version $Revision: 904 $
-* $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
-*/
-public class FormattedCellRenderer extends DefaultTableCellRenderer
-{
- protected Format currentFormat, defaultFormat;
- protected Color defaultForeground, defaultBackground;
- protected Font defaultFont;
-
-/**
-* Default constructor with no specified format.
-*/
- public FormattedCellRenderer()
- {
- this( (Format) null );
- }
-
-/**
-* Constructor specifying a format for renderered content.
-*/
- public FormattedCellRenderer( Format aFormat )
- {
- currentFormat = null;
- defaultFormat = aFormat;
- defaultForeground = super.getForeground();
- defaultBackground = super.getForeground();
- }
-
-/**
-* Returns the format currently in use to format cell content.
-* @return The Format that is currently being used.
-*/
- public Format getFormat()
- {
- return defaultFormat;
- }
-
-/**
-* Sets the format to be used to format cell content.
-*/
- public void setFormat( Format aFormat )
- {
- defaultFormat = aFormat;
- }
-
-/**
-* Overrides to retain the default foreground color,
-* much the same as the DefaultCellRenderer does.
-* We have to do this because DefaultCellRenderer's
-* ivars are private.
-*/
- public void setForeground(Color c) {
- super.setForeground(c);
- defaultForeground = c;
- }
-
-/**
-* Overrides to retain the default background color,
-* much the same as the DefaultCellRenderer does.
-* We have to do this because DefaultCellRenderer's
-* ivars are private.
-*/
- public void setBackground(Color c) {
- super.setBackground(c);
- defaultBackground = c;
- }
-
-/**
-* Overrides to retain the default font,
-* much the same as the DefaultCellRenderer does.
-* We have to do this because DefaultCellRenderer's
-* ivars are private.
-*/
- public void setFont(Font f) {
- super.setFont(f);
- defaultFont = f;
- }
-
-/**
-* Overridden to format the value with the appropriate Format. If the
-* value cannot be formatted with the Format, the superclass method is called.
-* @param value An Object to be formatted.
-*/
- protected void setValue(Object value)
- {
- if ( currentFormat != null )
- {
- try
- {
+ * A cell renderer for dealing with formatted content. Subclasses can specify
+ * formats or colors or styles for specific values or locations in the table by
+ * overridding getFormatForContext(), getForegroundForContext() and/or
+ * getBackgroundForContext().
+ *
+ * @author michael@mpowers.net
+ * @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006)
+ * $
+ */
+public class FormattedCellRenderer extends DefaultTableCellRenderer {
+ protected Format currentFormat, defaultFormat;
+ protected Color defaultForeground, defaultBackground;
+ protected Font defaultFont;
+
+ /**
+ * Default constructor with no specified format.
+ */
+ public FormattedCellRenderer() {
+ this((Format) null);
+ }
+
+ /**
+ * Constructor specifying a format for renderered content.
+ */
+ public FormattedCellRenderer(Format aFormat) {
+ currentFormat = null;
+ defaultFormat = aFormat;
+ defaultForeground = super.getForeground();
+ defaultBackground = super.getForeground();
+ }
+
+ /**
+ * Returns the format currently in use to format cell content.
+ *
+ * @return The Format that is currently being used.
+ */
+ public Format getFormat() {
+ return defaultFormat;
+ }
+
+ /**
+ * Sets the format to be used to format cell content.
+ */
+ public void setFormat(Format aFormat) {
+ defaultFormat = aFormat;
+ }
+
+ /**
+ * Overrides to retain the default foreground color, much the same as the
+ * DefaultCellRenderer does. We have to do this because DefaultCellRenderer's
+ * ivars are private.
+ */
+ public void setForeground(Color c) {
+ super.setForeground(c);
+ defaultForeground = c;
+ }
+
+ /**
+ * Overrides to retain the default background color, much the same as the
+ * DefaultCellRenderer does. We have to do this because DefaultCellRenderer's
+ * ivars are private.
+ */
+ public void setBackground(Color c) {
+ super.setBackground(c);
+ defaultBackground = c;
+ }
+
+ /**
+ * Overrides to retain the default font, much the same as the
+ * DefaultCellRenderer does. We have to do this because DefaultCellRenderer's
+ * ivars are private.
+ */
+ public void setFont(Font f) {
+ super.setFont(f);
+ defaultFont = f;
+ }
+
+ /**
+ * Overridden to format the value with the appropriate Format. If the value
+ * cannot be formatted with the Format, the superclass method is called.
+ *
+ * @param value An Object to be formatted.
+ */
+ protected void setValue(Object value) {
+ if (currentFormat != null) {
+ try {
// if ( ( value instanceof Number ) && ( value.toString().indexOf( "E" ) != -1 ) )
// {
@@ -132,153 +123,140 @@ public class FormattedCellRenderer extends DefaultTableCellRenderer
// System.out.println( "FormattedCellRenderer.setValue: converted = '" + currentFormat.format( value ) + "'" );
// }
- // WORKAROUND: This works around what may be a rounding bug in DecimalFormat. (PR 256/297)
- currentFormat.format( ZERO );
-
- // DEBUG: code to test for weird one/zero problem (PR 256/297)
- String result = currentFormat.format( value );
-/* above workaround seems to be working
- if ( result.equals( "1" ) )
- {
- System.out.println( "FormattedCellRenderer.setValue: Could be the ONE/ZERO problem!" );
- System.out.println( "FormattedCellRenderer.setValue: format = '" + currentFormat.getClass() + "'" );
- System.out.println( "FormattedCellRenderer.setValue: original value = '" + value + "'" );
- System.out.println( "FormattedCellRenderer.setValue: result = '" + result + "'" );
- }
-*/
- setText( result );
-
+ // WORKAROUND: This works around what may be a rounding bug in DecimalFormat.
+ // (PR 256/297)
+ currentFormat.format(ZERO);
+
+ // DEBUG: code to test for weird one/zero problem (PR 256/297)
+ String result = currentFormat.format(value);
+ /*
+ * above workaround seems to be working if ( result.equals( "1" ) ) {
+ * System.out.println(
+ * "FormattedCellRenderer.setValue: Could be the ONE/ZERO problem!" );
+ * System.out.println( "FormattedCellRenderer.setValue: format = '" +
+ * currentFormat.getClass() + "'" ); System.out.println(
+ * "FormattedCellRenderer.setValue: original value = '" + value + "'" );
+ * System.out.println( "FormattedCellRenderer.setValue: result = '" + result +
+ * "'" ); }
+ */
+ setText(result);
// setText( currentFormat.format( value ) );
- return;
- }
- catch ( IllegalArgumentException exc )
- {
- // fall back on superclass implementation
- }
- }
- super.setValue( value );
- }
-
- // FIXME: remove this when possible
- private static Double ZERO = new Double( 0.0 );
-
-/**
-* Overridden to call context delegate methods.
-*/
- public Component getTableCellRendererComponent(JTable table, Object value,
- boolean isSelected, boolean hasFocus, int row, int column)
- {
- Format format;
-
- // allow for context-sensitve formatting
- format = getFormatForContext( table, value, isSelected, hasFocus, row, column );
- if ( format != null )
- {
- currentFormat = format;
- }
- else
- {
- currentFormat = defaultFormat;
- }
-
- Color color;
-
- // allow for context-sensitve foreground color
- color = getForegroundForContext( table, value, isSelected, hasFocus, row, column );
- if ( color != null )
- {
- super.setForeground( color );
- }
- else
- {
- super.setForeground( defaultForeground );
- }
-
- // allow for context-sensitve background color
- color = getBackgroundForContext( table, value, isSelected, hasFocus, row, column );
- if ( color != null )
- {
- super.setBackground( color );
- }
- else
- {
- super.setBackground( defaultBackground );
- }
-
- // have to call this here because super defaults to table's font
- Component result =
- super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
- // NOTE: DefaultTableCellRenderer returns itself.
-
- // allow for context-sensitve font
- Font font = getFontForContext( table, value, isSelected, hasFocus, row, column );
- if ( font != null )
- {
- result.setFont( font );
- }
- else
- {
- result.setFont( defaultFont );
- }
-
- return result;
-
- }
-
-/**
-* Override this method to provide a specific format for the
-* specific cell to be rendered by this component. Any format
-* returned by this method will take precedence of the format
-* specified by setFormat(). <br><br>
-* This default implementation returns null.
-* @return A Format for this cell, or null to rely on the the
-* format specified by setFormat().
-*/
- public Format getFormatForContext(JTable table, Object value,
- boolean isSelected, boolean hasFocus, int row, int column)
- {
- return null;
- }
-
-/**
-* Override this method to provide a foreground color for the renderer.
-* Because the table specifies colors for selected cells,
-* these colors will only be used when renderering unselected cells. <br><br>
-* This default implementation returns null.
-* @return A Color for the foreground of the cell, or null to rely on
-* the table's default color scheme.
-*/
- public Color getForegroundForContext(JTable table, Object value,
- boolean isSelected, boolean hasFocus, int row, int column)
- {
- return null;
- }
-
-/**
-* Override this method to provide a background color for the renderer.
-* Because the table specifies colors for selected cells,
-* these colors will only be used when renderering unselected cells. <br><br>
-* This default implementation returns null.
-* @return A Color for the background of the cell, or null to rely on
-* the table's default color scheme.
-*/
- public Color getBackgroundForContext(JTable table, Object value,
- boolean isSelected, boolean hasFocus, int row, int column)
- {
- return null;
- }
-
-/**
-* Override this method to provide a font for the renderer.<br><br>
-* This default implementation returns null.
-* @return A Font for the cell, or null to rely on the table's default font.
-*/
- public Font getFontForContext(JTable table, Object value,
- boolean isSelected, boolean hasFocus, int row, int column)
- {
- return null;
- }
+ return;
+ } catch (IllegalArgumentException exc) {
+ // fall back on superclass implementation
+ }
+ }
+ super.setValue(value);
+ }
+
+ // FIXME: remove this when possible
+ private static Double ZERO = new Double(0.0);
+
+ /**
+ * Overridden to call context delegate methods.
+ */
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
+ int row, int column) {
+ Format format;
+
+ // allow for context-sensitve formatting
+ format = getFormatForContext(table, value, isSelected, hasFocus, row, column);
+ if (format != null) {
+ currentFormat = format;
+ } else {
+ currentFormat = defaultFormat;
+ }
+
+ Color color;
+
+ // allow for context-sensitve foreground color
+ color = getForegroundForContext(table, value, isSelected, hasFocus, row, column);
+ if (color != null) {
+ super.setForeground(color);
+ } else {
+ super.setForeground(defaultForeground);
+ }
+
+ // allow for context-sensitve background color
+ color = getBackgroundForContext(table, value, isSelected, hasFocus, row, column);
+ if (color != null) {
+ super.setBackground(color);
+ } else {
+ super.setBackground(defaultBackground);
+ }
+
+ // have to call this here because super defaults to table's font
+ Component result = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ // NOTE: DefaultTableCellRenderer returns itself.
+
+ // allow for context-sensitve font
+ Font font = getFontForContext(table, value, isSelected, hasFocus, row, column);
+ if (font != null) {
+ result.setFont(font);
+ } else {
+ result.setFont(defaultFont);
+ }
+
+ return result;
+
+ }
+
+ /**
+ * Override this method to provide a specific format for the specific cell to be
+ * rendered by this component. Any format returned by this method will take
+ * precedence of the format specified by setFormat(). <br>
+ * <br>
+ * This default implementation returns null.
+ *
+ * @return A Format for this cell, or null to rely on the the format specified
+ * by setFormat().
+ */
+ public Format getFormatForContext(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
+ int column) {
+ return null;
+ }
+
+ /**
+ * Override this method to provide a foreground color for the renderer. Because
+ * the table specifies colors for selected cells, these colors will only be used
+ * when renderering unselected cells. <br>
+ * <br>
+ * This default implementation returns null.
+ *
+ * @return A Color for the foreground of the cell, or null to rely on the
+ * table's default color scheme.
+ */
+ public Color getForegroundForContext(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
+ int column) {
+ return null;
+ }
+
+ /**
+ * Override this method to provide a background color for the renderer. Because
+ * the table specifies colors for selected cells, these colors will only be used
+ * when renderering unselected cells. <br>
+ * <br>
+ * This default implementation returns null.
+ *
+ * @return A Color for the background of the cell, or null to rely on the
+ * table's default color scheme.
+ */
+ public Color getBackgroundForContext(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
+ int column) {
+ return null;
+ }
+
+ /**
+ * Override this method to provide a font for the renderer.<br>
+ * <br>
+ * This default implementation returns null.
+ *
+ * @return A Font for the cell, or null to rely on the table's default font.
+ */
+ public Font getFontForContext(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
+ int column) {
+ return null;
+ }
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/IconCellRenderer.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/IconCellRenderer.java
index 8320d08..2d9531d 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/IconCellRenderer.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/IconCellRenderer.java
@@ -54,792 +54,654 @@ import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
/**
-* A cell renderer that displays icons in addition to text,
-* and additionally is an editor in case you want to click
-* the icon to trigger some kind of action.
-* You probably should override both getStringForContext and
-* getIconForContext to achieve your desired results.
-* To receive mouse clicks, set the same instance of the
-* renderer as the editor for the same component.<br><br>
-*
-* One notable addition is that this class is an action event
-* broadcaster. ActionEvents are broadcast when the mouse is
-* clicked on the button with an action event containing a
-* user-configurable string that defaults to CLICKED. <br><br>
-*
-* The renderer itself can be used as a JComponent if
-* you need something like a JLabel that allows you to click
-* on the icon. You will want to call setIcon and setText
-* to configure the component since the renderer method would
-* not be called. (If you add an instance of the renderer
-* to a container, you cannnot use the same instance as an
-* editor in a table, tree, or list.)
-*
-* @author michael@mpowers.net
-* @version $Revision: 904 $
-* $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
-*/
-public class IconCellRenderer extends JPanel
- implements TableCellRenderer, TableCellEditor,
- TreeCellRenderer, TreeCellEditor, ListCellRenderer,
- Runnable, ActionListener, MouseListener
-{
+ * A cell renderer that displays icons in addition to text, and additionally is
+ * an editor in case you want to click the icon to trigger some kind of action.
+ * You probably should override both getStringForContext and getIconForContext
+ * to achieve your desired results. To receive mouse clicks, set the same
+ * instance of the renderer as the editor for the same component.<br>
+ * <br>
+ *
+ * One notable addition is that this class is an action event broadcaster.
+ * ActionEvents are broadcast when the mouse is clicked on the button with an
+ * action event containing a user-configurable string that defaults to CLICKED.
+ * <br>
+ * <br>
+ *
+ * The renderer itself can be used as a JComponent if you need something like a
+ * JLabel that allows you to click on the icon. You will want to call setIcon
+ * and setText to configure the component since the renderer method would not be
+ * called. (If you add an instance of the renderer to a container, you cannnot
+ * use the same instance as an editor in a table, tree, or list.)
+ *
+ * @author michael@mpowers.net
+ * @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006)
+ * $
+ */
+public class IconCellRenderer extends JPanel implements TableCellRenderer, TableCellEditor, TreeCellRenderer,
+ TreeCellEditor, ListCellRenderer, Runnable, ActionListener, MouseListener {
public static final String CLICKED = "CLICKED";
-
+
/**
- * The panel that is re-used to render everything.
- * This is returned by getRendererForContext.
- */
- protected JPanel rendererPanel;
+ * The panel that is re-used to render everything. This is returned by
+ * getRendererForContext.
+ */
+ protected JPanel rendererPanel;
protected JLabel rendererLabel;
- protected JButton rendererButton;
+ protected JButton rendererButton;
/**
- * The panel that is used to receive mouse clicks.
- * It must be a different component from rendererPanel.
- * This is returned by getEditorForContext.
- */
- protected JPanel editorPanel;
+ * The panel that is used to receive mouse clicks. It must be a different
+ * component from rendererPanel. This is returned by getEditorForContext.
+ */
+ protected JPanel editorPanel;
protected JLabel editorLabel;
- protected JButton editorButton;
-
+ protected JButton editorButton;
+
private Object lastKnownValue;
- private JComponent lastKnownComponent;
-
+ private JComponent lastKnownComponent;
+
// do as DefaultTableCellRenderer does
private Border noFocusBorder;
private Border treeFocusBorder;
private Color unselectedForeground;
private Color unselectedBackground;
-
+
private Vector actionListeners;
private String actionCommand;
private Vector cellEditorListeners;
-
- private boolean editable;
- private boolean clickable;
-
- /**
- * Default constructor.
- */
- public IconCellRenderer()
- {
- editable = true;
- clickable = true;
-
- noFocusBorder = new EmptyBorder(1, 1, 1, 1);
- treeFocusBorder = new LineBorder(
- UIManager.getColor("Tree.selectionBorderColor") );
- setActionCommand( CLICKED );
-
- rendererPanel = new JPanel();
- rendererPanel.setLayout( new GridBagLayout() );
-
- editorPanel = this;
- editorPanel.setLayout( new GridBagLayout() );
-
- // set up constraints
- GridBagConstraints imageConstraints = new GridBagConstraints();
- imageConstraints.gridx = 0;
- GridBagConstraints labelConstraints = new GridBagConstraints();
- labelConstraints.fill = GridBagConstraints.HORIZONTAL;
- labelConstraints.gridx = 1;
- labelConstraints.weightx = 1.0;
- labelConstraints.ipadx = 1;
- labelConstraints.insets = new Insets( 0, 1, 0, 0 ); // sweat the pixel
-
- // make the editor panel go away when not in use
- // and pass through all mouse events to container
-
- //this is not very useful since editorLabel and editorButton
- //get all of the events
- editorPanel.addMouseListener( this );
-
+
+ private boolean editable;
+ private boolean clickable;
+
+ /**
+ * Default constructor.
+ */
+ public IconCellRenderer() {
+ editable = true;
+ clickable = true;
+
+ noFocusBorder = new EmptyBorder(1, 1, 1, 1);
+ treeFocusBorder = new LineBorder(UIManager.getColor("Tree.selectionBorderColor"));
+ setActionCommand(CLICKED);
+
+ rendererPanel = new JPanel();
+ rendererPanel.setLayout(new GridBagLayout());
+
+ editorPanel = this;
+ editorPanel.setLayout(new GridBagLayout());
+
+ // set up constraints
+ GridBagConstraints imageConstraints = new GridBagConstraints();
+ imageConstraints.gridx = 0;
+ GridBagConstraints labelConstraints = new GridBagConstraints();
+ labelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ labelConstraints.gridx = 1;
+ labelConstraints.weightx = 1.0;
+ labelConstraints.ipadx = 1;
+ labelConstraints.insets = new Insets(0, 1, 0, 0); // sweat the pixel
+
+ // make the editor panel go away when not in use
+ // and pass through all mouse events to container
+
+ // this is not very useful since editorLabel and editorButton
+ // get all of the events
+ editorPanel.addMouseListener(this);
+
rendererLabel = new JLabel();
- rendererLabel.setOpaque( false );
- rendererPanel.add( rendererLabel, labelConstraints );
+ rendererLabel.setOpaque(false);
+ rendererPanel.add(rendererLabel, labelConstraints);
editorLabel = new JLabel();
- editorLabel.setText( "" ); // default state
- editorLabel.setOpaque( false );
- editorPanel.add( editorLabel, labelConstraints );
+ editorLabel.setText(""); // default state
+ editorLabel.setOpaque(false);
+ editorPanel.add(editorLabel, labelConstraints);
unselectedForeground = rendererLabel.getForeground();
unselectedBackground = rendererLabel.getBackground();
-
- rendererButton = new JButton();
- rendererButton.setBorder( null );
- rendererButton.setBorderPainted( false );
- rendererButton.setContentAreaFilled( false );
- rendererButton.setFocusPainted( false );
- rendererButton.setMargin( new Insets( 0, 0, 0, 0 ) );
- rendererPanel.add( rendererButton, imageConstraints );
-
- editorButton = new JButton();
- editorButton.setEnabled( clickable ); // default state
- editorButton.setIcon( null ); // default state
- editorButton.setBorder( null );
- editorButton.setBorderPainted( false );
- editorButton.setContentAreaFilled( false );
- editorButton.setFocusPainted( false );
- editorButton.setMargin( new Insets( 0, 0, 0, 0 ) );
- editorPanel.add( editorButton, imageConstraints );
-
- editorButton.addActionListener( this );
-
- //add these in order to dispatch the MouseEvents
- //to the lastKnownComponent, and proper management of
- //DnD operations
- editorLabel.addMouseListener( this );
- editorButton.addMouseListener( this );
- }
-
-/**
-* Returns the text string currently displayed in the editor component.
-*/
- public String getText()
- {
- return editorLabel.getText();
- }
-
-/**
-* Sets the text string displayed in the editor component.
-* Default is an empty string.
-*/
- public void setText( String aString )
- {
- editorLabel.setText( aString );
- }
-/**
-* Returns the icon currently displayed in the editor component.
-*/
- public Icon getIcon()
- {
- return editorButton.getIcon();
- }
-
-/**
-* Sets the icon currently displayed in the editor component.
-* Default is null.
-*/
- public void setIcon( Icon anIcon )
- {
- editorButton.setIcon( anIcon );
- if ( !isClickable() )
- {
- editorButton.setDisabledIcon( anIcon );
- }
- }
+ rendererButton = new JButton();
+ rendererButton.setBorder(null);
+ rendererButton.setBorderPainted(false);
+ rendererButton.setContentAreaFilled(false);
+ rendererButton.setFocusPainted(false);
+ rendererButton.setMargin(new Insets(0, 0, 0, 0));
+ rendererPanel.add(rendererButton, imageConstraints);
+
+ editorButton = new JButton();
+ editorButton.setEnabled(clickable); // default state
+ editorButton.setIcon(null); // default state
+ editorButton.setBorder(null);
+ editorButton.setBorderPainted(false);
+ editorButton.setContentAreaFilled(false);
+ editorButton.setFocusPainted(false);
+ editorButton.setMargin(new Insets(0, 0, 0, 0));
+ editorPanel.add(editorButton, imageConstraints);
+
+ editorButton.addActionListener(this);
+
+ // add these in order to dispatch the MouseEvents
+ // to the lastKnownComponent, and proper management of
+ // DnD operations
+ editorLabel.addMouseListener(this);
+ editorButton.addMouseListener(this);
+ }
-/**
-* Returns whether the editor component's label text is editable.
-*/
- public boolean isEditable()
- {
- return editable;
- }
-
-/**
-* Sets whether the editor component's label text is editable.
-* Default is true. Editable text is not yet implemented.
-*/
- public void setEditable( boolean isEditable )
- {
- editable = isEditable;
- }
+ /**
+ * Returns the text string currently displayed in the editor component.
+ */
+ public String getText() {
+ return editorLabel.getText();
+ }
-/**
-* Returns whether the editor component's icon is clickable.
-*/
- public boolean isClickable()
- {
- return clickable;
- }
-
-/**
-* Sets whether the editor component's icon is clickable.
-* Default is true.
-*/
- public void setClickable( boolean isClickable )
- {
- clickable = isClickable;
- editorButton.setEnabled( clickable );
- }
+ /**
+ * Sets the text string displayed in the editor component. Default is an empty
+ * string.
+ */
+ public void setText(String aString) {
+ editorLabel.setText(aString);
+ }
-/**
-* Returns the component from getRendererForContext.
-*/
- public Component getListCellRendererComponent(JList list,
- Object value,
- int index,
- boolean isSelected,
- boolean cellHasFocus)
- {
- lastKnownComponent = list;
- return getRendererForContext(
- list, value, index, 0, isSelected, cellHasFocus, false, true );
- }
+ /**
+ * Returns the icon currently displayed in the editor component.
+ */
+ public Icon getIcon() {
+ return editorButton.getIcon();
+ }
-/**
-* Returns the component from getRendererForContext.
-*/
- public Component getTableCellRendererComponent(JTable table, Object value,
- boolean isSelected, boolean hasFocus, int row, int column)
- {
- lastKnownComponent = table;
- return getRendererForContext(
- table, value, row, column, isSelected, hasFocus, false, true );
- }
+ /**
+ * Sets the icon currently displayed in the editor component. Default is null.
+ */
+ public void setIcon(Icon anIcon) {
+ editorButton.setIcon(anIcon);
+ if (!isClickable()) {
+ editorButton.setDisabledIcon(anIcon);
+ }
+ }
-/**
-* Returns the component from getRendererForContext.
-*/
- public Component getTreeCellRendererComponent(JTree tree,
- Object value,
- boolean selected,
- boolean expanded,
- boolean leaf,
- int row,
- boolean hasFocus)
- {
- lastKnownComponent = tree;
- return getRendererForContext(
- tree, value, row, 0, selected, hasFocus, expanded, leaf );
- }
-
-/**
-* Returns getEditorForContext with the same parameters with hasFocus true.
-*/
- public Component getTableCellEditorComponent(JTable table,
- Object value, boolean isSelected, int row, int column)
- {
+ /**
+ * Returns whether the editor component's label text is editable.
+ */
+ public boolean isEditable() {
+ return editable;
+ }
+
+ /**
+ * Sets whether the editor component's label text is editable. Default is true.
+ * Editable text is not yet implemented.
+ */
+ public void setEditable(boolean isEditable) {
+ editable = isEditable;
+ }
+
+ /**
+ * Returns whether the editor component's icon is clickable.
+ */
+ public boolean isClickable() {
+ return clickable;
+ }
+
+ /**
+ * Sets whether the editor component's icon is clickable. Default is true.
+ */
+ public void setClickable(boolean isClickable) {
+ clickable = isClickable;
+ editorButton.setEnabled(clickable);
+ }
+
+ /**
+ * Returns the component from getRendererForContext.
+ */
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+ boolean cellHasFocus) {
+ lastKnownComponent = list;
+ return getRendererForContext(list, value, index, 0, isSelected, cellHasFocus, false, true);
+ }
+
+ /**
+ * Returns the component from getRendererForContext.
+ */
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
+ int row, int column) {
+ lastKnownComponent = table;
+ return getRendererForContext(table, value, row, column, isSelected, hasFocus, false, true);
+ }
+
+ /**
+ * Returns the component from getRendererForContext.
+ */
+ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
+ boolean leaf, int row, boolean hasFocus) {
+ lastKnownComponent = tree;
+ return getRendererForContext(tree, value, row, 0, selected, hasFocus, expanded, leaf);
+ }
+
+ /**
+ * Returns getEditorForContext with the same parameters with hasFocus true.
+ */
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
lastKnownValue = value;
- lastKnownComponent = table;
- return getEditorForContext(
- table, value, row, column, isSelected, true, false, true );
+ lastKnownComponent = table;
+ return getEditorForContext(table, value, row, column, isSelected, true, false, true);
}
-/**
-* Returns the component from getEditorForContext with hasFocus true.
-*/
- public Component getTreeCellEditorComponent(JTree tree,
- Object value,
- boolean isSelected,
- boolean expanded,
- boolean leaf,
- int row)
- {
-
-
- lastKnownValue = value;
- lastKnownComponent = tree;
-
- return getEditorForContext(
- tree, value, row, 0, isSelected, true, expanded, leaf );
- }
-
-/**
-* This default implementation returns a JPanel that is configured by
-* calling configureComponentForContext.
-* @return An component that is used to render content.
-*/
- public Component getRendererForContext(
- JComponent container, Object value,
- int row, int column,
- boolean isSelected, boolean hasFocus,
- boolean isExpanded, boolean isLeaf )
- {
-
-
- configureComponentForContext( rendererPanel, rendererButton, rendererLabel,
- container, value, row, column,
- isSelected, hasFocus, isExpanded, isLeaf );
+ /**
+ * Returns the component from getEditorForContext with hasFocus true.
+ */
+ public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded,
+ boolean leaf, int row) {
+
+ lastKnownValue = value;
+ lastKnownComponent = tree;
+
+ return getEditorForContext(tree, value, row, 0, isSelected, true, expanded, leaf);
+ }
+
+ /**
+ * This default implementation returns a JPanel that is configured by calling
+ * configureComponentForContext.
+ *
+ * @return An component that is used to render content.
+ */
+ public Component getRendererForContext(JComponent container, Object value, int row, int column, boolean isSelected,
+ boolean hasFocus, boolean isExpanded, boolean isLeaf) {
+
+ configureComponentForContext(rendererPanel, rendererButton, rendererLabel, container, value, row, column,
+ isSelected, hasFocus, isExpanded, isLeaf);
return rendererPanel;
- }
+ }
-/**
-* This method returns a separate component that should be visually
-* identical to the renderer component. We can't simply reuse the
-* renderer component because the renderer is still used to paint
-* the table while the editor component is displayed. Clicks are
-* received on this component.
-* This default implementation returns a JPanel that is configured by
-* calling configureComponentForContext.
-* @return A component used to receive clicks on the cell.
-*/
- public Component getEditorForContext(
- JComponent container, Object value,
- int row, int column,
- boolean isSelected, boolean hasFocus,
- boolean isExpanded, boolean isLeaf )
- {
- configureComponentForContext( editorPanel, editorButton, editorLabel,
- container, value, row, column,
- true, hasFocus, isExpanded, isLeaf ); // editor should always be selected
+ /**
+ * This method returns a separate component that should be visually identical to
+ * the renderer component. We can't simply reuse the renderer component because
+ * the renderer is still used to paint the table while the editor component is
+ * displayed. Clicks are received on this component. This default implementation
+ * returns a JPanel that is configured by calling configureComponentForContext.
+ *
+ * @return A component used to receive clicks on the cell.
+ */
+ public Component getEditorForContext(JComponent container, Object value, int row, int column, boolean isSelected,
+ boolean hasFocus, boolean isExpanded, boolean isLeaf) {
+ configureComponentForContext(editorPanel, editorButton, editorLabel, container, value, row, column, true,
+ hasFocus, isExpanded, isLeaf); // editor should always be selected
return editorPanel;
- }
+ }
-/**
-* Called to configure components
-*/
- protected void configureComponentForContext(
- JPanel component, JButton iconButton, JLabel label,
- JComponent container, Object value,
- int row, int column,
- boolean isSelected, boolean hasFocus,
- boolean isExpanded, boolean isLeaf )
- {
- if (hasFocus)
- {
- if ( container instanceof JTable )
- {
- component.setBorder(
- UIManager.getBorder("Table.focusCellHighlightBorder") );
- }
- else
- {
- component.setBorder( noFocusBorder );
- }
-
- if ( container instanceof JTree ) // was: (false)
- {
- label.setBorder( treeFocusBorder );
- }
- else
- {
- label.setBorder( noFocusBorder );
- }
- }
- else
- {
- label.setBorder(noFocusBorder);
- component.setBorder(noFocusBorder);
- }
-
- if (isSelected)
- {
- if ( container instanceof JTree )
- {
- label.setOpaque( true );
- label.setForeground(UIManager.getColor("Tree.selectionForeground"));
- label.setBackground(UIManager.getColor("Tree.selectionBackground"));
- component.setBackground(container.getBackground());
- }
- else if ( container instanceof JTable )
- {
- label.setOpaque( false );
- label.setForeground( ((JTable)container).getSelectionForeground() );
- component.setBackground(((JTable)container).getSelectionBackground());
- }
- else
- {
- label.setOpaque( false );
- label.setForeground(UIManager.getColor("Table.selectionForeground"));
- component.setBackground(UIManager.getColor("Table.selectionBackground"));
- }
- }
- else
- {
- label.setOpaque( false );
- label.setForeground(container.getForeground());
- component.setBackground(container.getBackground());
- }
-
- label.setFont(container.getFont());
-
- Icon icon = getIconForContext(
- container, value, row, column, isSelected, hasFocus, isExpanded, isLeaf );
- iconButton.setIcon( icon );
- if ( !isClickable() )
- {
- iconButton.setDisabledIcon( icon );
- }
-
- String text = getStringForContext(
- container, value, row, column, isSelected, hasFocus, isExpanded, isLeaf );
-
- if ( ( text == null ) || ( "".equals( text ) ) )
- {
- if ( ! label.getText().equals( "" ) )
- label.setText( "" );
+ /**
+ * Called to configure components
+ */
+ protected void configureComponentForContext(JPanel component, JButton iconButton, JLabel label,
+ JComponent container, Object value, int row, int column, boolean isSelected, boolean hasFocus,
+ boolean isExpanded, boolean isLeaf) {
+ if (hasFocus) {
+ if (container instanceof JTable) {
+ component.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
+ } else {
+ component.setBorder(noFocusBorder);
+ }
+
+ if (container instanceof JTree) // was: (false)
+ {
+ label.setBorder(treeFocusBorder);
+ } else {
+ label.setBorder(noFocusBorder);
+ }
+ } else {
+ label.setBorder(noFocusBorder);
+ component.setBorder(noFocusBorder);
}
- else
- {
- if ( ! label.getText().equals( text ) )
- label.setText( text );
+
+ if (isSelected) {
+ if (container instanceof JTree) {
+ label.setOpaque(true);
+ label.setForeground(UIManager.getColor("Tree.selectionForeground"));
+ label.setBackground(UIManager.getColor("Tree.selectionBackground"));
+ component.setBackground(container.getBackground());
+ } else if (container instanceof JTable) {
+ label.setOpaque(false);
+ label.setForeground(((JTable) container).getSelectionForeground());
+ component.setBackground(((JTable) container).getSelectionBackground());
+ } else {
+ label.setOpaque(false);
+ label.setForeground(UIManager.getColor("Table.selectionForeground"));
+ component.setBackground(UIManager.getColor("Table.selectionBackground"));
+ }
+ } else {
+ label.setOpaque(false);
+ label.setForeground(container.getForeground());
+ component.setBackground(container.getBackground());
+ }
+
+ label.setFont(container.getFont());
+
+ Icon icon = getIconForContext(container, value, row, column, isSelected, hasFocus, isExpanded, isLeaf);
+ iconButton.setIcon(icon);
+ if (!isClickable()) {
+ iconButton.setDisabledIcon(icon);
+ }
+
+ String text = getStringForContext(container, value, row, column, isSelected, hasFocus, isExpanded, isLeaf);
+
+ if ((text == null) || ("".equals(text))) {
+ if (!label.getText().equals(""))
+ label.setText("");
+ } else {
+ if (!label.getText().equals(text))
+ label.setText(text);
}
}
-
-/**
-* Override this method to provide an icon for the renderer.
-* This default implementation returns null.
-* @return An icon to be displayed in the cell, or null to omit the
-* icon from the cell.
-*/
- public Icon getIconForContext(
- JComponent container, Object value,
- int row, int column,
- boolean isSelected, boolean hasFocus,
- boolean isExpanded, boolean isLeaf )
- {
- return null;
- }
-/**
-* Override this method to provide a string for the renderer.
-* This default implementation returns toString on the value parameter,
-* or null if the value is null.
-* @return A string to be displayed in the cell.
-*/
- public String getStringForContext(
- JComponent container, Object value,
- int row, int column,
- boolean isSelected, boolean hasFocus,
- boolean isExpanded, boolean isLeaf )
- {
- if ( value == null ) return null;
- return value.toString();
- }
-
- /**
- * Adds the specified listener to the list of listeners
- * to be notified when the button receives a click.
- */
- public void addActionListener( ActionListener aListener )
- {
- if ( actionListeners == null )
- {
- actionListeners = new Vector( 2 );
+ /**
+ * Override this method to provide an icon for the renderer. This default
+ * implementation returns null.
+ *
+ * @return An icon to be displayed in the cell, or null to omit the icon from
+ * the cell.
+ */
+ public Icon getIconForContext(JComponent container, Object value, int row, int column, boolean isSelected,
+ boolean hasFocus, boolean isExpanded, boolean isLeaf) {
+ return null;
+ }
+
+ /**
+ * Override this method to provide a string for the renderer. This default
+ * implementation returns toString on the value parameter, or null if the value
+ * is null.
+ *
+ * @return A string to be displayed in the cell.
+ */
+ public String getStringForContext(JComponent container, Object value, int row, int column, boolean isSelected,
+ boolean hasFocus, boolean isExpanded, boolean isLeaf) {
+ if (value == null)
+ return null;
+ return value.toString();
+ }
+
+ /**
+ * Adds the specified listener to the list of listeners to be notified when the
+ * button receives a click.
+ */
+ public void addActionListener(ActionListener aListener) {
+ if (actionListeners == null) {
+ actionListeners = new Vector(2);
}
- actionListeners.add( aListener );
+ actionListeners.add(aListener);
}
-
+
/**
- * Removes the specified listener from the list of listeners
- * to be notified when the button receives a click.
- */
- public void removeActionListener( ActionListener aListener )
- {
- actionListeners.remove( aListener );
+ * Removes the specified listener from the list of listeners to be notified when
+ * the button receives a click.
+ */
+ public void removeActionListener(ActionListener aListener) {
+ actionListeners.remove(aListener);
}
-
+
/**
- * Broadcasts the specified action event to all listeners.
- */
- protected void fireActionEvent( ActionEvent anActionEvent )
- {
- if ( actionListeners == null ) return;
+ * Broadcasts the specified action event to all listeners.
+ */
+ protected void fireActionEvent(ActionEvent anActionEvent) {
+ if (actionListeners == null)
+ return;
// vector's enumeration is not fail-fast
Enumeration e = actionListeners.elements();
- while ( e.hasMoreElements() )
- {
- ((ActionListener)e.nextElement()).actionPerformed( anActionEvent );
+ while (e.hasMoreElements()) {
+ ((ActionListener) e.nextElement()).actionPerformed(anActionEvent);
}
}
-
+
/**
- * Returns the action command broadcast when this icon
- * receives a click. Defaults to CLICKED.
- */
- public String getActionCommand()
- {
+ * Returns the action command broadcast when this icon receives a click.
+ * Defaults to CLICKED.
+ */
+ public String getActionCommand() {
return actionCommand;
}
/**
- * Sets the action command broadcast when this table
- * receives a double click.
- */
- public void setActionCommand( String anActionCommand )
- {
- actionCommand = anActionCommand;
+ * Sets the action command broadcast when this table receives a double click.
+ */
+ public void setActionCommand(String anActionCommand) {
+ actionCommand = anActionCommand;
}
-
+
// interface CellEditor
/**
- * Returns lastKnownValue, although this should not be called.
- */
- public Object getCellEditorValue()
- {
+ * Returns lastKnownValue, although this should not be called.
+ */
+ public Object getCellEditorValue() {
return lastKnownValue;
}
-
+
/**
- * Returns true.
- */
- public boolean isCellEditable(EventObject anEvent)
- {
- return true;
+ * Returns true.
+ */
+ public boolean isCellEditable(EventObject anEvent) {
+ return true;
}
-
+
/**
- * Returns true.
- */
- public boolean shouldSelectCell(EventObject anEvent)
- {
+ * Returns true.
+ */
+ public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
-
+
/**
- * Fires an editing stopped event and returns true.
- */
- public boolean stopCellEditing()
- {
- ChangeEvent event = new ChangeEvent( this );
- if ( cellEditorListeners != null )
- {
+ * Fires an editing stopped event and returns true.
+ */
+ public boolean stopCellEditing() {
+ ChangeEvent event = new ChangeEvent(this);
+ if (cellEditorListeners != null) {
// vector's enumeration is not fail-fast
Enumeration e = cellEditorListeners.elements();
- while ( e.hasMoreElements() )
- {
- // broadcast editing cancelled since no value is edited
- ((CellEditorListener)e.nextElement()).editingCanceled( event );
+ while (e.hasMoreElements()) {
+ // broadcast editing cancelled since no value is edited
+ ((CellEditorListener) e.nextElement()).editingCanceled(event);
}
}
- lastKnownComponent = null;
+ lastKnownComponent = null;
return true;
}
-
- /**
- * Fires an editing cancelled event and returns true.
- */
- public void cancelCellEditing()
- {
- //HACK: cancelCellEditing() causes for the dragGesture
- //to be NOT recognized AT ALL since on the next MOUSE_PRESSED
- //the cell editor first needs to startEditing() [if in the tree
- //the CellEditorListener is a BasicTreeUI class]
- //(before the drag gesture event can be recognized).
- //Also the lastKnownComponent should not be set to null,
- //none of the mouse events won't dispathced to the lastKnownComponent
- //in that case.
-
- //Not calling it at all does seem to fix it, but what are the
- //consequences???
- //Trying to workaround this might solve it, but it introduces having
- //an extra listener (a MouseMotionListnener), which might be wasteful
- //(i.e. only if a Mouse_dragged event has been initiated, but DragGesture
- //hasn't been recognized, postpone calling this till finish the DnD event)
- //But what if do DnD and not exited ??? The mouseExited() is not called
- //anyway until the DnD event is done.
-
- ChangeEvent event = new ChangeEvent( this );
- if ( cellEditorListeners == null ) return;
+
+ /**
+ * Fires an editing cancelled event and returns true.
+ */
+ public void cancelCellEditing() {
+ // HACK: cancelCellEditing() causes for the dragGesture
+ // to be NOT recognized AT ALL since on the next MOUSE_PRESSED
+ // the cell editor first needs to startEditing() [if in the tree
+ // the CellEditorListener is a BasicTreeUI class]
+ // (before the drag gesture event can be recognized).
+ // Also the lastKnownComponent should not be set to null,
+ // none of the mouse events won't dispathced to the lastKnownComponent
+ // in that case.
+
+ // Not calling it at all does seem to fix it, but what are the
+ // consequences???
+ // Trying to workaround this might solve it, but it introduces having
+ // an extra listener (a MouseMotionListnener), which might be wasteful
+ // (i.e. only if a Mouse_dragged event has been initiated, but DragGesture
+ // hasn't been recognized, postpone calling this till finish the DnD event)
+ // But what if do DnD and not exited ??? The mouseExited() is not called
+ // anyway until the DnD event is done.
+
+ ChangeEvent event = new ChangeEvent(this);
+ if (cellEditorListeners == null)
+ return;
// vector's enumeration is not fail-fast
Enumeration e = cellEditorListeners.elements();
-
- while ( e.hasMoreElements() )
- {
- ((CellEditorListener)e.nextElement()).editingCanceled( event );
- }
-
- //DO not nullify this
- lastKnownComponent = null;
- }
-
- /**
- * Adds the specified listener to the list of listeners
- * to be notified when the table receives a double click.
- */
- public void addCellEditorListener( CellEditorListener aListener )
- {
- if ( cellEditorListeners == null )
- {
- cellEditorListeners = new Vector( 2 );
+
+ while (e.hasMoreElements()) {
+ ((CellEditorListener) e.nextElement()).editingCanceled(event);
+ }
+
+ // DO not nullify this
+ lastKnownComponent = null;
+ }
+
+ /**
+ * Adds the specified listener to the list of listeners to be notified when the
+ * table receives a double click.
+ */
+ public void addCellEditorListener(CellEditorListener aListener) {
+ if (cellEditorListeners == null) {
+ cellEditorListeners = new Vector(2);
}
- cellEditorListeners.add( aListener );
+ cellEditorListeners.add(aListener);
}
-
+
/**
- * Removes the specified listener from the list of listeners
- * to be notified when the table receives a double click.
- */
- public void removeCellEditorListener( CellEditorListener aListener )
- {
- cellEditorListeners.remove( aListener );
+ * Removes the specified listener from the list of listeners to be notified when
+ * the table receives a double click.
+ */
+ public void removeCellEditorListener(CellEditorListener aListener) {
+ cellEditorListeners.remove(aListener);
}
-
+
// interface ActionListener
-
- /**
- * Puts ourself on the end of the event queue for
- * firing our action event to all listeners.
- */
- public void actionPerformed( ActionEvent evt )
- {
- //commented out in order NOT to set lastKnownComponent to null, since
- //if this object is inside a table or tree, relying on getCellEditorValue()
- //to return the currently edited object
- //cancelCellEditing();
-
- SwingUtilities.invokeLater( this );
- }
-
+
+ /**
+ * Puts ourself on the end of the event queue for firing our action event to all
+ * listeners.
+ */
+ public void actionPerformed(ActionEvent evt) {
+ // commented out in order NOT to set lastKnownComponent to null, since
+ // if this object is inside a table or tree, relying on getCellEditorValue()
+ // to return the currently edited object
+ // cancelCellEditing();
+
+ SwingUtilities.invokeLater(this);
+ }
+
// interface Runnable
-
+
/**
- * Fires the action event to all listeners.
- * This is triggered by a click on the icon.
- */
- public void run()
- {
- fireActionEvent( new ActionEvent( this, 0, getActionCommand() ) );
+ * Fires the action event to all listeners. This is triggered by a click on the
+ * icon.
+ */
+ public void run() {
+ fireActionEvent(new ActionEvent(this, 0, getActionCommand()));
}
// interface MouseListener
-
- /**
- * Passes through editor mouse clicks to last known component.
- * (left click only)
- */
- public void mouseClicked(MouseEvent e)
- {
- if(lastKnownComponent != null){
- Object source = e.getSource();
- if(source != null)
- {
- if(source == editorPanel)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorPanel, e, lastKnownComponent ) );
-
- }
- else if(source == editorLabel)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorLabel, e, lastKnownComponent ) );
- }
-
- else if(source == editorButton)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorButton, e, lastKnownComponent ) );
- }
- }
- }
- }
-
- /**
- * Passes through editor right-mouse (popup trigger) mouse events to last known component.
- * Needed for possible displaying of popup menus on right click
- */
- public void mousePressed(MouseEvent e)
- {
- if ( e.isPopupTrigger() )
- {
- if(lastKnownComponent != null)
- {
- Object source = e.getSource();
- if(source != null)
- {
- if(source == editorPanel)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorPanel, e, lastKnownComponent ) );
- }
- else if(source == editorLabel)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorLabel, e, lastKnownComponent ) );
- }
-
- else if(source == editorButton)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorButton, e, lastKnownComponent ) );
- }
- }
- }
- }
- }
-
- /**
- * Does nothing.
- */
- public void mouseReleased(MouseEvent e)
- {
- if ( e.isPopupTrigger() )
- {
- if(lastKnownComponent != null){
-
- Object source = e.getSource();
- if(source != null)
- {
- if(source == editorPanel)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorPanel, e, lastKnownComponent ) );
- }
-
- else if(source == editorLabel)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorLabel, e, lastKnownComponent ) );
- }
-
- else if(source == editorButton)
- {
- lastKnownComponent.dispatchEvent(
- SwingUtilities.convertMouseEvent(
- editorButton, e, lastKnownComponent ) );
- }
- }
- }
- }
- }
-
- /**
- * Does nothing.
- */
- public void mouseEntered(MouseEvent e)
- {
- }
-
- /**
- * Cancels cell editing.
- */
- public void mouseExited(MouseEvent e)
- {
- Object source = e.getSource();
- if(source != null && source instanceof JComponent){
- //need to convert the Point from the source's coordinate system to editorPanel's coordinate system.
- //(note that simple editorPanel.contains(e.getPoint()) fails if source is editorButton)
-
- Point convertedPoint = SwingUtilities.convertPoint((JComponent) source, e.getPoint(), editorPanel);
-
- //check if exited from editorButton, but still inside the editorPanel (works for editorLabel as well)
- if(!editorPanel.contains(convertedPoint)){
-
- //This was getting called before, but it interfers with the DnD operation
- cancelCellEditing();
- }
- }
- }
-
- /* This might be redundant
- public void cleanUp(){
-
- //since cancelCellEditing() was never called call it now
- cancelCellEditing();
- stopCellEditing();
-
- editorButton.removeActionListener( this );
- editorPanel.removeMouseListener( this );
- editorLabel.removeMouseListener( this );
- editorButton.removeMouseListener( this );
- lastKnownComponent = null;
- lastKnownValue = null;
- }
- */
+
+ /**
+ * Passes through editor mouse clicks to last known component. (left click only)
+ */
+ public void mouseClicked(MouseEvent e) {
+ if (lastKnownComponent != null) {
+ Object source = e.getSource();
+ if (source != null) {
+ if (source == editorPanel) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorPanel, e, lastKnownComponent));
+
+ } else if (source == editorLabel) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorLabel, e, lastKnownComponent));
+ }
+
+ else if (source == editorButton) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorButton, e, lastKnownComponent));
+ }
+ }
+ }
+ }
+
+ /**
+ * Passes through editor right-mouse (popup trigger) mouse events to last known
+ * component. Needed for possible displaying of popup menus on right click
+ */
+ public void mousePressed(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ if (lastKnownComponent != null) {
+ Object source = e.getSource();
+ if (source != null) {
+ if (source == editorPanel) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorPanel, e, lastKnownComponent));
+ } else if (source == editorLabel) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorLabel, e, lastKnownComponent));
+ }
+
+ else if (source == editorButton) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorButton, e, lastKnownComponent));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Does nothing.
+ */
+ public void mouseReleased(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ if (lastKnownComponent != null) {
+
+ Object source = e.getSource();
+ if (source != null) {
+ if (source == editorPanel) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorPanel, e, lastKnownComponent));
+ }
+
+ else if (source == editorLabel) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorLabel, e, lastKnownComponent));
+ }
+
+ else if (source == editorButton) {
+ lastKnownComponent
+ .dispatchEvent(SwingUtilities.convertMouseEvent(editorButton, e, lastKnownComponent));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Does nothing.
+ */
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ /**
+ * Cancels cell editing.
+ */
+ public void mouseExited(MouseEvent e) {
+ Object source = e.getSource();
+ if (source != null && source instanceof JComponent) {
+ // need to convert the Point from the source's coordinate system to
+ // editorPanel's coordinate system.
+ // (note that simple editorPanel.contains(e.getPoint()) fails if source is
+ // editorButton)
+
+ Point convertedPoint = SwingUtilities.convertPoint((JComponent) source, e.getPoint(), editorPanel);
+
+ // check if exited from editorButton, but still inside the editorPanel (works
+ // for editorLabel as well)
+ if (!editorPanel.contains(convertedPoint)) {
+
+ // This was getting called before, but it interfers with the DnD operation
+ cancelCellEditing();
+ }
+ }
+ }
+
+ /*
+ * This might be redundant public void cleanUp(){
+ *
+ * //since cancelCellEditing() was never called call it now cancelCellEditing();
+ * stopCellEditing();
+ *
+ * editorButton.removeActionListener( this ); editorPanel.removeMouseListener(
+ * this ); editorLabel.removeMouseListener( this );
+ * editorButton.removeMouseListener( this ); lastKnownComponent = null;
+ * lastKnownValue = null; }
+ */
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ImagePanel.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ImagePanel.java
index cdaa218..4fa8e04 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ImagePanel.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/ImagePanel.java
@@ -26,79 +26,58 @@ import java.awt.image.ImageObserver;
import javax.swing.JPanel;
/**
-* A JPanel that renders an image, tiling as necessary to
-* fill the panel.
-* The preferred size of the panel is the size of the image
-* and will change until the image is fully loaded, so using
-* a media tracker is recommended.
-*
-* @author michael@mpowers.net
-* @version $Revision: 904 $
-*/
-public class ImagePanel extends JPanel implements ImageObserver
-{
+ * A JPanel that renders an image, tiling as necessary to fill the panel. The
+ * preferred size of the panel is the size of the image and will change until
+ * the image is fully loaded, so using a media tracker is recommended.
+ *
+ * @author michael@mpowers.net
+ * @version $Revision: 904 $
+ */
+public class ImagePanel extends JPanel implements ImageObserver {
protected Image image;
protected int imageWidth, imageHeight;
-
- public ImagePanel()
- {
- this( null );
- }
-
- public ImagePanel( Image anImage )
- {
- image = anImage;
- if ( anImage != null )
- {
- prepareImage( image, this );
+
+ public ImagePanel() {
+ this(null);
+ }
+
+ public ImagePanel(Image anImage) {
+ image = anImage;
+ if (anImage != null) {
+ prepareImage(image, this);
// these may return -1
- imageWidth = image.getWidth( this );
- imageHeight = image.getHeight( this );
- }
- else
- {
+ imageWidth = image.getWidth(this);
+ imageHeight = image.getHeight(this);
+ } else {
imageWidth = 0;
imageHeight = 0;
}
}
-
- protected void paintComponent(Graphics g)
- {
- if ( ( image != null ) && ( imageWidth > 0 ) && ( imageHeight > 0 ) )
- {
+
+ protected void paintComponent(Graphics g) {
+ if ((image != null) && (imageWidth > 0) && (imageHeight > 0)) {
int width = getWidth();
int height = getHeight();
-
- for ( int x = 0; x < width; x += imageWidth )
- {
- for ( int y = 0; y < height; y += imageHeight )
- {
- g.drawImage( image, x, y,
- imageWidth, imageHeight,
- getBackground(), this );
+
+ for (int x = 0; x < width; x += imageWidth) {
+ for (int y = 0; y < height; y += imageHeight) {
+ g.drawImage(image, x, y, imageWidth, imageHeight, getBackground(), this);
}
}
}
}
-
- public boolean imageUpdate(Image img,
- int infoflags,
- int x,
- int y,
- int width,
- int height)
- {
+
+ public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
imageWidth = width;
imageHeight = height;
- setPreferredSize( new Dimension( width, height ) );
- revalidate();
+ setPreferredSize(new Dimension(width, height));
+ revalidate();
repaint();
-
- if ( ( infoflags & ImageObserver.ALLBITS ) == ImageObserver.ALLBITS )
- {
- return false;
+
+ if ((infoflags & ImageObserver.ALLBITS) == ImageObserver.ALLBITS) {
+ return false;
}
return true;
}
-
+
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/InfoPanel.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/InfoPanel.java
index 55c1e36..a2c0182 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/InfoPanel.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/InfoPanel.java
@@ -49,1645 +49,1521 @@ import javax.swing.JTextField;
import javax.swing.SwingConstants;
/**
-* InfoPanel uses labels and textfields (or any other component - see below)
-* to display a list of keys and values in a well-aligned and consistent manner,
-* conforming to alignment and pixel spacing in the java look and feel
-* <a href="http://java.sun.com/products/jlf/dg/higg.htm#55417">design guidelines</a>.
-* <BR><BR>
-*
-* Each key is displayed in a label to the left of the component that contains
-* the corresponding value. Each row is displayed starting at the top of the
-* component's available area. Each row's height is the maximum preferred
-* height of its components and the field itself gets as much of the width as
-* it can, dependent on the length of the longest label. <BR><BR>
-*
-* The values in the fields can be editable, and the
-* current value can be retrieved using the key - for this reason, unique keys
-* are recommended. <BR><BR>
-*
-* As a convenience, push buttons may be placed across the
-* bottom of the panel in a manner similar to ButtonPanel. <BR><BR>
-*
-* The panel forwards any ActionEvents generated by the components and
-* buttons on it to all registered listeners. <BR><BR>
-*
-* Optionally, any component can be used instead of a textfield.
-* However, <code>get/setValueForKey()</code> and <code>get/setEditable()</code>
-* may not work for those components. Use <code>getComponentForKey()</code> to
-* access them instead.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-* $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
-*/
-public class InfoPanel extends JPanel implements ActionListener
-{
-/**
-* Special label for an empty pair - a label and component
-* that take up space but are hidden from view. This might
-* be useful for achieving certain layouts.
-*/
- public static final String HIDDEN = "(hidden)";
-
- /** Cache for the introspectComponent method */
- private static Map _method_cache =
- Collections.synchronizedMap( new HashMap(30) );
-
- protected Container listContainer = null;
- protected int hgap; // set in constructor
- protected int vgap; // set in constructor
- protected int margin; // set in constructor
- protected int columns; // set in constructor
- protected List fields = null;
- protected List labels = null;
- protected List fieldSpacers = null;
- protected ButtonPanel buttonPanel = null;
- protected boolean isEditable = true;
- protected String prefix;
- protected String postfix;
+ * InfoPanel uses labels and textfields (or any other component - see below) to
+ * display a list of keys and values in a well-aligned and consistent manner,
+ * conforming to alignment and pixel spacing in the java look and feel
+ * <a href="http://java.sun.com/products/jlf/dg/higg.htm#55417">design
+ * guidelines</a>. <BR>
+ * <BR>
+ *
+ * Each key is displayed in a label to the left of the component that contains
+ * the corresponding value. Each row is displayed starting at the top of the
+ * component's available area. Each row's height is the maximum preferred height
+ * of its components and the field itself gets as much of the width as it can,
+ * dependent on the length of the longest label. <BR>
+ * <BR>
+ *
+ * The values in the fields can be editable, and the current value can be
+ * retrieved using the key - for this reason, unique keys are recommended. <BR>
+ * <BR>
+ *
+ * As a convenience, push buttons may be placed across the bottom of the panel
+ * in a manner similar to ButtonPanel. <BR>
+ * <BR>
+ *
+ * The panel forwards any ActionEvents generated by the components and buttons
+ * on it to all registered listeners. <BR>
+ * <BR>
+ *
+ * Optionally, any component can be used instead of a textfield. However,
+ * <code>get/setValueForKey()</code> and <code>get/setEditable()</code> may not
+ * work for those components. Use <code>getComponentForKey()</code> to access
+ * them instead.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006)
+ * $
+ */
+public class InfoPanel extends JPanel implements ActionListener {
+ /**
+ * Special label for an empty pair - a label and component that take up space
+ * but are hidden from view. This might be useful for achieving certain layouts.
+ */
+ public static final String HIDDEN = "(hidden)";
+
+ /** Cache for the introspectComponent method */
+ private static Map _method_cache = Collections.synchronizedMap(new HashMap(30));
+
+ protected Container listContainer = null;
+ protected int hgap; // set in constructor
+ protected int vgap; // set in constructor
+ protected int margin; // set in constructor
+ protected int columns; // set in constructor
+ protected List fields = null;
+ protected List labels = null;
+ protected List fieldSpacers = null;
+ protected ButtonPanel buttonPanel = null;
+ protected boolean isEditable = true;
+ protected String prefix;
+ protected String postfix;
protected int labelAnchor;
protected int labelAlign;
// protected Component marginStrut = null;
- // for action multicasting
- protected ActionListener actionListener = null;
-
-/**
-* Constructs an empty InfoPanel.
-*/
- public InfoPanel()
- {
- hgap = 12; // per java l&f guidelines
- vgap = 6; // java l&f says 11
- columns = 1; // default columns
- margin = 0; // default margin: none
- prefix = ""; // default prefix: none
- postfix = ":"; // per java l&f guidelines
- fields = new ArrayList();
- labels = new ArrayList();
- labelAnchor = GridBagConstraints.NORTHWEST;
- // per java l&f guidelines (CENTER is nicer)
- labelAlign = SwingConstants.LEFT;
- // per java l&f guidelines
-
- doInitialLayout();
- }
+ // for action multicasting
+ protected ActionListener actionListener = null;
+
+ /**
+ * Constructs an empty InfoPanel.
+ */
+ public InfoPanel() {
+ hgap = 12; // per java l&f guidelines
+ vgap = 6; // java l&f says 11
+ columns = 1; // default columns
+ margin = 0; // default margin: none
+ prefix = ""; // default prefix: none
+ postfix = ":"; // per java l&f guidelines
+ fields = new ArrayList();
+ labels = new ArrayList();
+ labelAnchor = GridBagConstraints.NORTHWEST;
+ // per java l&f guidelines (CENTER is nicer)
+ labelAlign = SwingConstants.LEFT;
+ // per java l&f guidelines
+
+ doInitialLayout();
+ }
-/**
-* Constructs an InfoPanel with the specified labels
-* each paired with a blank textfield.
-* @param labelArray An Array containing the labels in the
-* order in which they should appear from top to bottom.
-* A null value produces an empty panel.
-*/
- public InfoPanel( String[] labelArray )
- {
- this();
- setLabels( labelArray );
- }
+ /**
+ * Constructs an InfoPanel with the specified labels each paired with a blank
+ * textfield.
+ *
+ * @param labelArray An Array containing the labels in the order in which they
+ * should appear from top to bottom. A null value produces an
+ * empty panel.
+ */
+ public InfoPanel(String[] labelArray) {
+ this();
+ setLabels(labelArray);
+ }
-/**
-* Creates a set of labels and empty textfields after first
-* clearing all existing components on the panel.
-* @param labelArray An Array containing the labels in the order
-* in which they should appear from top to bottom. A null
-* value will clear the panel.
-*/
- public void setLabels( String[] labelArray )
- {
- removeAll();
- if ( labelArray == null ) return; // null clears panel
- for ( int i = 0; i < labelArray.length; i++ )
- {
- addPair( labelArray[i], new JTextField() );
- }
- }
+ /**
+ * Creates a set of labels and empty textfields after first clearing all
+ * existing components on the panel.
+ *
+ * @param labelArray An Array containing the labels in the order in which they
+ * should appear from top to bottom. A null value will clear
+ * the panel.
+ */
+ public void setLabels(String[] labelArray) {
+ removeAll();
+ if (labelArray == null)
+ return; // null clears panel
+ for (int i = 0; i < labelArray.length; i++) {
+ addPair(labelArray[i], new JTextField());
+ }
+ }
-/**
-* Retrieves the labls for the components on the panel
-* in the order in which they are displayed from top WIDTH bottom.
-* These are the keys used to reference values or to reference
-* the components directly.
-* @return An Array of Strings containing the labels.
-*/
- public String[] getLabels()
- {
- int length = fields.size();
- String[] labelArray = new String[ length ];
- for ( int i = 0; i < length; i++ )
- {
- labelArray[i] = ((Component)fields.get(i)).getName();
- }
- return labelArray;
- }
-
-/**
-* Retrieves the constant used to anchor the labels in place.
-* The default value is GridBagConstraints.NORTHWEST.
-*/
- public int getLabelAnchor()
- {
+ /**
+ * Retrieves the labls for the components on the panel in the order in which
+ * they are displayed from top WIDTH bottom. These are the keys used to
+ * reference values or to reference the components directly.
+ *
+ * @return An Array of Strings containing the labels.
+ */
+ public String[] getLabels() {
+ int length = fields.size();
+ String[] labelArray = new String[length];
+ for (int i = 0; i < length; i++) {
+ labelArray[i] = ((Component) fields.get(i)).getName();
+ }
+ return labelArray;
+ }
+
+ /**
+ * Retrieves the constant used to anchor the labels in place. The default value
+ * is GridBagConstraints.NORTHWEST.
+ */
+ public int getLabelAnchor() {
return labelAnchor;
}
-/**
-* Sets the constant used to anchor the labels in place
-* and reflows the layout.
-* @param anAnchorConstant An anchor constant from
-* GridBagConstraints.
-*/
- public void setLabelAnchor( int anAnchorConstant )
- {
- labelAnchor = anAnchorConstant;
+ /**
+ * Sets the constant used to anchor the labels in place and reflows the layout.
+ *
+ * @param anAnchorConstant An anchor constant from GridBagConstraints.
+ */
+ public void setLabelAnchor(int anAnchorConstant) {
+ labelAnchor = anAnchorConstant;
updateLabels();
}
-/**
-* Retrieves the constant used to align the labels in place.
-* The default value is GridBagConstraints.CENTER.
-*/
- public int getLabelAlignment()
- {
+ /**
+ * Retrieves the constant used to align the labels in place. The default value
+ * is GridBagConstraints.CENTER.
+ */
+ public int getLabelAlignment() {
return labelAlign;
}
-/**
-* Sets the constant used to align the labels in place
-* and reflows the layout.
-* @param anAlignmentConstant LEFT, CENTER, or RIGHT constants
-* from SwingUtilities.
-*/
- public void setLabelAlignment( int anAlignmentConstant )
- {
- labelAlign = anAlignmentConstant;
+ /**
+ * Sets the constant used to align the labels in place and reflows the layout.
+ *
+ * @param anAlignmentConstant LEFT, CENTER, or RIGHT constants from
+ * SwingUtilities.
+ */
+ public void setLabelAlignment(int anAlignmentConstant) {
+ labelAlign = anAlignmentConstant;
updateLabels();
}
-
-/**
-* Factory method for creating panel spacers.
-* This implementation returns a JPanel with
-* opaque set to false. Override to customize.
-*/
- public JPanel createPanel()
- {
- JPanel result = new JPanel();
- result.setOpaque( false );
- return result;
- }
-/**
-* This method is responsible for the initial layout of the panel.
-* All labels and textfields will later added to listContainer.
-* This method is responsible for initializing listContainer.
-*/
- protected void doInitialLayout()
- {
- listContainer = createPanel();
- listContainer.setLayout( new BetterGridBagLayout() );
- this.setLayout( new BorderLayout() );
- this.add( listContainer, BorderLayout.NORTH );
+ /**
+ * Factory method for creating panel spacers. This implementation returns a
+ * JPanel with opaque set to false. Override to customize.
+ */
+ public JPanel createPanel() {
+ JPanel result = new JPanel();
+ result.setOpaque(false);
+ return result;
+ }
- //listContainer.setBackground( Color.blue ); // useful for testing
- //this.setBackground( Color.red );
- }
+ /**
+ * This method is responsible for the initial layout of the panel. All labels
+ * and textfields will later added to listContainer. This method is responsible
+ * for initializing listContainer.
+ */
+ protected void doInitialLayout() {
+ listContainer = createPanel();
+ listContainer.setLayout(new BetterGridBagLayout());
+ this.setLayout(new BorderLayout());
+ this.add(listContainer, BorderLayout.NORTH);
+
+ // listContainer.setBackground( Color.blue ); // useful for testing
+ // this.setBackground( Color.red );
+ }
-/**
-* Changes the horizontal spacing between the label and the components in the panel.
-* Note: Assumes listContainer uses a GridBagLayout.
-* @param newHgap the new spacing, in pixels. May not be negative.
-*/
- public void setHgap( int newHgap )
- {
- if ( newHgap < 0 ) return; // may not be negative
- this.hgap = newHgap;
- updateGaps();
- this.revalidate();
- this.repaint();
+ /**
+ * Changes the horizontal spacing between the label and the components in the
+ * panel. Note: Assumes listContainer uses a GridBagLayout.
+ *
+ * @param newHgap the new spacing, in pixels. May not be negative.
+ */
+ public void setHgap(int newHgap) {
+ if (newHgap < 0)
+ return; // may not be negative
+ this.hgap = newHgap;
+ updateGaps();
+ this.revalidate();
+ this.repaint();
- }
+ }
-/**
-* Gets the current horizontal spacing between components.
-* @return the current horizontal spacing, in pixels.
-*/
- public int getHgap()
- {
- return this.hgap;
- }
+ /**
+ * Gets the current horizontal spacing between components.
+ *
+ * @return the current horizontal spacing, in pixels.
+ */
+ public int getHgap() {
+ return this.hgap;
+ }
-/**
-* Changes the vertical spacing between components in the panel.
-* Note: Assumes listContainer uses a GridBagLayout.
-* @param newVgap the new spacing, in pixels. May not be negative.
-*/
- public void setVgap( int newVgap )
- {
- if ( newVgap < 0 ) return; // may not be negative
- this.vgap = newVgap;
- updateGaps();
- this.revalidate();
- this.repaint();
+ /**
+ * Changes the vertical spacing between components in the panel. Note: Assumes
+ * listContainer uses a GridBagLayout.
+ *
+ * @param newVgap the new spacing, in pixels. May not be negative.
+ */
+ public void setVgap(int newVgap) {
+ if (newVgap < 0)
+ return; // may not be negative
+ this.vgap = newVgap;
+ updateGaps();
+ this.revalidate();
+ this.repaint();
- }
+ }
-/**
-* Gets the current vertical spacing between components.
-* @return the current vertical spacing, in pixels.
-*/
- public int getVgap()
- {
- return this.vgap;
- }
+ /**
+ * Gets the current vertical spacing between components.
+ *
+ * @return the current vertical spacing, in pixels.
+ */
+ public int getVgap() {
+ return this.vgap;
+ }
-/**
-* Sets the minimum width for the labels column.
-* This left margin will grow if one of the labels
-* is wider than this value.
-* Note: assumes GridBagLayout.
-* @param newMargin the new minimum margin in pixels. May not be negative.
-*/
- public void setMargin( int newMargin )
- {
- if ( newMargin < 0 ) return; // may not be negative
- this.margin = newMargin;
-
- if ( listContainer.getLayout() instanceof GridBagLayout )
- {
- GridBagLayout gridBag = (GridBagLayout) listContainer.getLayout();
- GridBagConstraints constraints = null;
- Component c = null;
- int count = listContainer.getComponentCount();
- for ( int i = 0; i < count; i++ )
- {
- c = listContainer.getComponent( i );
- constraints = gridBag.getConstraints( c );
- if ( constraints.gridy == 0 && constraints.gridx % 2 == 0 )
- { // if this is a label spacer
- // replace it with an appropriately sized box
- listContainer.remove( c );
- listContainer.add( Box.createHorizontalStrut( this.margin ), constraints );
- }
- }
- }
-
- this.revalidate();
- this.repaint();
-
- }
+ /**
+ * Sets the minimum width for the labels column. This left margin will grow if
+ * one of the labels is wider than this value. Note: assumes GridBagLayout.
+ *
+ * @param newMargin the new minimum margin in pixels. May not be negative.
+ */
+ public void setMargin(int newMargin) {
+ if (newMargin < 0)
+ return; // may not be negative
+ this.margin = newMargin;
+
+ if (listContainer.getLayout() instanceof GridBagLayout) {
+ GridBagLayout gridBag = (GridBagLayout) listContainer.getLayout();
+ GridBagConstraints constraints = null;
+ Component c = null;
+ int count = listContainer.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ c = listContainer.getComponent(i);
+ constraints = gridBag.getConstraints(c);
+ if (constraints.gridy == 0 && constraints.gridx % 2 == 0) { // if this is a label spacer
+ // replace it with an appropriately sized
+ // box
+ listContainer.remove(c);
+ listContainer.add(Box.createHorizontalStrut(this.margin), constraints);
+ }
+ }
+ }
-/**
-* Gets the current minimum margin for the labels column.
-* @return the current minimum margin in pixels.
-*/
- public int getMargin()
- {
- return this.margin;
- }
+ this.revalidate();
+ this.repaint();
-/**
-* Sets the number of columns for the panel.
-* Label/Component pairs will start from the top left
-* and fill in to the right before wrapping to the
-* next row. The default number of columns is one.
-* Note: assumes GridBagLayout.
-* @param newColumns the new number of columns. May not be less than one.
-*/
- public void setColumns( int newColumns )
- {
- if ( newColumns < 1 ) return; // may not be less than one.
- int oldColumns = this.columns;
- this.columns = newColumns;
-
- if ( listContainer.getLayout() instanceof GridBagLayout )
- {
- GridBagLayout gridBag = (GridBagLayout) listContainer.getLayout();
- int count = listContainer.getComponentCount();
- Component[] components = listContainer.getComponents();
- GridBagConstraints[] constraints = new GridBagConstraints[ components.length ];
- for ( int i = 0; i < components.length; i++ )
- {
- constraints[i] = gridBag.getConstraints( components[i] );
- }
- listContainer.removeAll();
- for ( int i = 0; i < components.length; i++ )
- {
- if ( constraints[i].gridy != 0 )
- { // ignore first row which is reserved for spacers.
-
- // translate component to new position
- // (columns*2 accounts for two grid columns for one "actual" column)
- int index = ( constraints[i].gridy - 1 ) * oldColumns*2 + constraints[i].gridx;
- constraints[i].gridy = ( index / (newColumns*2) ) + 1;
- constraints[i].gridx = index % (newColumns*2) ;
- listContainer.add( components[i], constraints[i] );
- }
- }
- createSpacers(); // replace the spacers
- updateGaps();
- }
-
- this.revalidate();
- this.repaint();
-
- }
+ }
-/**
-* Sets the vertical weight used for determining how to distribute additional
-* vertical space in the component.
-* @param aComponent Key that exists in the layout.
-* @return weighty The weight of the component, or -1.0 if not found.
-*/
- public double getVerticalWeightForKey( String key )
- {
- Container c = getCompositeComponentForKey( key );
- if ( c == null ) return -1.0;
- if ( ! ( listContainer.getLayout() instanceof GridBagLayout ) ) return -1.0;
- GridBagLayout layout = (GridBagLayout) listContainer.getLayout();
- GridBagConstraints gbc = layout.getConstraints( c );
- return gbc.weighty;
- }
-
-/**
-* Sets the vertical weight used for determining how to distribute additional
-* vertical space in the component. By default, all weights are zero, so each
-* component gets its preferred height. If any weights are specified, then
-* additional space is allocated to those components proportionately.
-* @param aComponent Key that exists in the layout.
-* @param weighty The new weight.
-*/
- public void setVerticalWeightForKey( String key, double weighty )
- {
- Container c = getCompositeComponentForKey( key );
- if ( c == null ) return;
- if ( ! ( listContainer.getLayout() instanceof GridBagLayout ) ) return;
- GridBagLayout layout = (GridBagLayout) listContainer.getLayout();
- GridBagConstraints gbc = layout.getConstraints( c );
- gbc.weighty = weighty;
- layout.setConstraints( c, gbc );
- // handle adding on-the-fly
- updateGaps();
- this.revalidate();
- this.repaint();
- }
-
-/**
-* Gets the current number of columns.
-* @return the current number of columns.
-*/
- public int getColumns()
- {
- return this.columns;
- }
+ /**
+ * Gets the current minimum margin for the labels column.
+ *
+ * @return the current minimum margin in pixels.
+ */
+ public int getMargin() {
+ return this.margin;
+ }
+
+ /**
+ * Sets the number of columns for the panel. Label/Component pairs will start
+ * from the top left and fill in to the right before wrapping to the next row.
+ * The default number of columns is one. Note: assumes GridBagLayout.
+ *
+ * @param newColumns the new number of columns. May not be less than one.
+ */
+ public void setColumns(int newColumns) {
+ if (newColumns < 1)
+ return; // may not be less than one.
+ int oldColumns = this.columns;
+ this.columns = newColumns;
+
+ if (listContainer.getLayout() instanceof GridBagLayout) {
+ GridBagLayout gridBag = (GridBagLayout) listContainer.getLayout();
+ int count = listContainer.getComponentCount();
+ Component[] components = listContainer.getComponents();
+ GridBagConstraints[] constraints = new GridBagConstraints[components.length];
+ for (int i = 0; i < components.length; i++) {
+ constraints[i] = gridBag.getConstraints(components[i]);
+ }
+ listContainer.removeAll();
+ for (int i = 0; i < components.length; i++) {
+ if (constraints[i].gridy != 0) { // ignore first row which is reserved for spacers.
+
+ // translate component to new position
+ // (columns*2 accounts for two grid columns for one "actual" column)
+ int index = (constraints[i].gridy - 1) * oldColumns * 2 + constraints[i].gridx;
+ constraints[i].gridy = (index / (newColumns * 2)) + 1;
+ constraints[i].gridx = index % (newColumns * 2);
+ listContainer.add(components[i], constraints[i]);
+ }
+ }
+ createSpacers(); // replace the spacers
+ updateGaps();
+ }
+
+ this.revalidate();
+ this.repaint();
-/**
-* Appends a label containing a key and the specified component
-* to the bottom of the panel. Any registered action listeners
-* will receive action events from the component - the key corresponding
-* to the component will be used as the action command.
-* @param key A string that will be displayed in a label, preferrably unique.
-* @param component A component that will be placed next to the label.
-* If null, a blank JPanel will be used.
-*/
- public void addPair( String key, Component component )
- {
- addRow( key, new Component[] { component } );
}
-
-/**
-* Appends a label containing a key and the specified component
-* to the bottom of the panel. Any registered action listeners
-* will receive action events from the component - the key corresponding
-* to the component will be used as the action command.
-* @param key A string that will be displayed in a label, preferrably unique.
-* @param component A component that will be placed next to the label.
-* If null, a blank JPanel will appear.
-*/
- public void addRow( String key, Component component )
- {
- addRow( key, new Component[] { component } );
+
+ /**
+ * Sets the vertical weight used for determining how to distribute additional
+ * vertical space in the component.
+ *
+ * @param aComponent Key that exists in the layout.
+ * @return weighty The weight of the component, or -1.0 if not found.
+ */
+ public double getVerticalWeightForKey(String key) {
+ Container c = getCompositeComponentForKey(key);
+ if (c == null)
+ return -1.0;
+ if (!(listContainer.getLayout() instanceof GridBagLayout))
+ return -1.0;
+ GridBagLayout layout = (GridBagLayout) listContainer.getLayout();
+ GridBagConstraints gbc = layout.getConstraints(c);
+ return gbc.weighty;
}
-
-/**
-* Appends a label containing a key and the specified components
-* to the bottom of the panel. Any registered action listeners
-* will receive action events from the component - the key corresponding
-* to the component will be used as the action command.
-* @param key A string that will be displayed in a label, preferrably unique.
-* @param components An array of components that will be placed next to the label.
-* Any nulls in the list will be replaced with blank JPanels.
-*/
- public void addRow(
- String key, Component[] components )
- {
- addCompositeComponent( key, makeCompositeComponent( key, components ) );
+
+ /**
+ * Sets the vertical weight used for determining how to distribute additional
+ * vertical space in the component. By default, all weights are zero, so each
+ * component gets its preferred height. If any weights are specified, then
+ * additional space is allocated to those components proportionately.
+ *
+ * @param aComponent Key that exists in the layout.
+ * @param weighty The new weight.
+ */
+ public void setVerticalWeightForKey(String key, double weighty) {
+ Container c = getCompositeComponentForKey(key);
+ if (c == null)
+ return;
+ if (!(listContainer.getLayout() instanceof GridBagLayout))
+ return;
+ GridBagLayout layout = (GridBagLayout) listContainer.getLayout();
+ GridBagConstraints gbc = layout.getConstraints(c);
+ gbc.weighty = weighty;
+ layout.setConstraints(c, gbc);
+ // handle adding on-the-fly
+ updateGaps();
+ this.revalidate();
+ this.repaint();
}
-/**
-* Appends a label containing a key and the specified components
-* to the bottom of the panel. Any registered action listeners
-* will receive action events from the components - the key corresponding
-* to the component will be used as the action command.
-* @param key A string that will be displayed in a label, preferrably unique.
-* @param west A component that will appear to the left of the other components,
-* as wide as its preferred width and as tall as the tallest of the other components.
-* A null will be replaced with a blank JPanel.
-* @param center A component that will appear between the other components,
-* taking up available space.
-* A null will be replaced with a blank JPanel.
-* @param east A component that will appear to the right of the other components,
-* as wide as its preferred width and as tall as the tallest of the other components.
-* A null will be replaced with a blank JPanel.
-*/
- public void addRow(
- String key, Component west, Component center, Component east )
- {
- addCompositeComponent( key,
- makeCompositeComponent( key,
- west, center, east ) );
+ /**
+ * Gets the current number of columns.
+ *
+ * @return the current number of columns.
+ */
+ public int getColumns() {
+ return this.columns;
}
-/**
-* Appends a label containing a key and the specified components
-* to the bottom of the panel. Any registered action listeners
-* will receive action events from the components - the key corresponding
-* to the component will be used as the action command.
-* @param key A string that will be displayed in a label, preferrably unique.
-* @param west A component that will appear to the left of the other components,
-* as wide as its preferred width and as tall as the tallest of the other components.
-* A null will be replaced with a blank JPanel.
-* @param north A component that will appear above all the other components,
-* as tall as its preferred height and as wide as the info panel itself.
-* @param center A component that will appear between the other components,
-* taking up available space. A null will be replaced with a blank JPanel.
-* @param south A component that will appear below all the other components,
-* as tall as its preferred height and as wide as the info panel itself.
-* @param east A component that will appear to the right of the other components,
-* as wide as its preferred width and as tall as the tallest of the other components.
-* A null will be replaced with a blank JPanel.
-*/
- public void addRow(
- String key, Component west, Component north,
- Component center, Component south, Component east )
- {
- addCompositeComponent( key,
- makeCompositeComponent( key,
- west, north, center, south, east ) );
+ /**
+ * Appends a label containing a key and the specified component to the bottom of
+ * the panel. Any registered action listeners will receive action events from
+ * the component - the key corresponding to the component will be used as the
+ * action command.
+ *
+ * @param key A string that will be displayed in a label, preferrably
+ * unique.
+ * @param component A component that will be placed next to the label. If null,
+ * a blank JPanel will be used.
+ */
+ public void addPair(String key, Component component) {
+ addRow(key, new Component[] { component });
}
-/**
-* Produces a container that contains the specified components,
-* using GridLayout. Nulls are ignored.
-* This implementation returns a JPanel.
-*/
- protected Container makeCompositeComponent(
- String key, Component[] components )
- {
+ /**
+ * Appends a label containing a key and the specified component to the bottom of
+ * the panel. Any registered action listeners will receive action events from
+ * the component - the key corresponding to the component will be used as the
+ * action command.
+ *
+ * @param key A string that will be displayed in a label, preferrably
+ * unique.
+ * @param component A component that will be placed next to the label. If null,
+ * a blank JPanel will appear.
+ */
+ public void addRow(String key, Component component) {
+ addRow(key, new Component[] { component });
+ }
+
+ /**
+ * Appends a label containing a key and the specified components to the bottom
+ * of the panel. Any registered action listeners will receive action events from
+ * the component - the key corresponding to the component will be used as the
+ * action command.
+ *
+ * @param key A string that will be displayed in a label, preferrably
+ * unique.
+ * @param components An array of components that will be placed next to the
+ * label. Any nulls in the list will be replaced with blank
+ * JPanels.
+ */
+ public void addRow(String key, Component[] components) {
+ addCompositeComponent(key, makeCompositeComponent(key, components));
+ }
+
+ /**
+ * Appends a label containing a key and the specified components to the bottom
+ * of the panel. Any registered action listeners will receive action events from
+ * the components - the key corresponding to the component will be used as the
+ * action command.
+ *
+ * @param key A string that will be displayed in a label, preferrably unique.
+ * @param west A component that will appear to the left of the other
+ * components, as wide as its preferred width and as tall as the
+ * tallest of the other components. A null will be replaced with a
+ * blank JPanel.
+ * @param center A component that will appear between the other components,
+ * taking up available space. A null will be replaced with a blank
+ * JPanel.
+ * @param east A component that will appear to the right of the other
+ * components, as wide as its preferred width and as tall as the
+ * tallest of the other components. A null will be replaced with a
+ * blank JPanel.
+ */
+ public void addRow(String key, Component west, Component center, Component east) {
+ addCompositeComponent(key, makeCompositeComponent(key, west, center, east));
+ }
+
+ /**
+ * Appends a label containing a key and the specified components to the bottom
+ * of the panel. Any registered action listeners will receive action events from
+ * the components - the key corresponding to the component will be used as the
+ * action command.
+ *
+ * @param key A string that will be displayed in a label, preferrably unique.
+ * @param west A component that will appear to the left of the other
+ * components, as wide as its preferred width and as tall as the
+ * tallest of the other components. A null will be replaced with a
+ * blank JPanel.
+ * @param north A component that will appear above all the other components, as
+ * tall as its preferred height and as wide as the info panel
+ * itself.
+ * @param center A component that will appear between the other components,
+ * taking up available space. A null will be replaced with a blank
+ * JPanel.
+ * @param south A component that will appear below all the other components, as
+ * tall as its preferred height and as wide as the info panel
+ * itself.
+ * @param east A component that will appear to the right of the other
+ * components, as wide as its preferred width and as tall as the
+ * tallest of the other components. A null will be replaced with a
+ * blank JPanel.
+ */
+ public void addRow(String key, Component west, Component north, Component center, Component south, Component east) {
+ addCompositeComponent(key, makeCompositeComponent(key, west, north, center, south, east));
+ }
+
+ /**
+ * Produces a container that contains the specified components, using
+ * GridLayout. Nulls are ignored. This implementation returns a JPanel.
+ */
+ protected Container makeCompositeComponent(String key, Component[] components) {
JPanel panel = createPanel();
- if ( components.length != 0 )
- {
- panel.setLayout( new GridLayout( 1, components.length, hgap, vgap ) );
+ if (components.length != 0) {
+ panel.setLayout(new GridLayout(1, components.length, hgap, vgap));
Component c;
- for ( int i = 0; i < components.length; i++ )
- {
+ for (int i = 0; i < components.length; i++) {
c = components[i];
- if ( c != null )
- {
- introspectComponent( c, key );
- panel.add( c );
+ if (c != null) {
+ introspectComponent(c, key);
+ panel.add(c);
}
}
}
return panel;
}
-/**
-* Produces a container that contains the specified components,
-* using BorderLayout. Nulls are ignored.
-* This implementation returns a JPanel.
-*/
- protected Container makeCompositeComponent(
- String key, Component west, Component center, Component east )
- {
+ /**
+ * Produces a container that contains the specified components, using
+ * BorderLayout. Nulls are ignored. This implementation returns a JPanel.
+ */
+ protected Container makeCompositeComponent(String key, Component west, Component center, Component east) {
JPanel panel = createPanel();
- panel.setLayout( new BorderLayout( hgap, vgap ) );
+ panel.setLayout(new BorderLayout(hgap, vgap));
- if ( west != null )
- {
- introspectComponent( west, key );
- panel.add( west, BorderLayout.WEST );
+ if (west != null) {
+ introspectComponent(west, key);
+ panel.add(west, BorderLayout.WEST);
}
-
- if ( center != null )
- {
- introspectComponent( center, key );
- panel.add( center, BorderLayout.CENTER );
+
+ if (center != null) {
+ introspectComponent(center, key);
+ panel.add(center, BorderLayout.CENTER);
}
-
- if ( east != null )
- {
- introspectComponent( east, key );
- panel.add( east, BorderLayout.EAST );
+
+ if (east != null) {
+ introspectComponent(east, key);
+ panel.add(east, BorderLayout.EAST);
}
-
+
return panel;
}
-/**
-* Produces a container that contains the specified components,
-* using BorderLayout. Nulls are ignored.
-* This implementation returns a JPanel.
-*/
- protected Container makeCompositeComponent(
- String key, Component west, Component north,
- Component center, Component south, Component east )
- {
+ /**
+ * Produces a container that contains the specified components, using
+ * BorderLayout. Nulls are ignored. This implementation returns a JPanel.
+ */
+ protected Container makeCompositeComponent(String key, Component west, Component north, Component center,
+ Component south, Component east) {
JPanel panel = createPanel();
- panel.setLayout( new BorderLayout( hgap, vgap ) );
+ panel.setLayout(new BorderLayout(hgap, vgap));
- if ( west != null )
- {
- introspectComponent( west, key );
- panel.add( west, BorderLayout.WEST );
+ if (west != null) {
+ introspectComponent(west, key);
+ panel.add(west, BorderLayout.WEST);
}
-
- if ( north != null )
- {
- introspectComponent( north, key );
- panel.add( north, BorderLayout.WEST );
+
+ if (north != null) {
+ introspectComponent(north, key);
+ panel.add(north, BorderLayout.WEST);
}
-
- if ( center != null )
- {
- introspectComponent( center, key );
- panel.add( center, BorderLayout.CENTER );
+
+ if (center != null) {
+ introspectComponent(center, key);
+ panel.add(center, BorderLayout.CENTER);
}
-
- if ( south != null )
- {
- introspectComponent( south, key );
- panel.add( south, BorderLayout.CENTER );
+
+ if (south != null) {
+ introspectComponent(south, key);
+ panel.add(south, BorderLayout.CENTER);
}
-
- if ( east != null )
- {
- introspectComponent( east, key );
- panel.add( east, BorderLayout.EAST );
+
+ if (east != null) {
+ introspectComponent(east, key);
+ panel.add(east, BorderLayout.EAST);
}
-
+
return panel;
}
-/**
-* Override to return a specific component to be used
-* as a label. This implementation calls createLabel().
-*/
- protected Component createLabelForKey( String aKey )
- {
- return createLabel();
+ /**
+ * Override to return a specific component to be used as a label. This
+ * implementation calls createLabel().
+ */
+ protected Component createLabelForKey(String aKey) {
+ return createLabel();
}
-/**
-* Provided for backwards compatibility, and called by
-* the default implementation of createLabelForKey.
-* This implementation returns a JLabel.
-*/
- protected JLabel createLabel()
- {
- return new JLabel();
+ /**
+ * Provided for backwards compatibility, and called by the default
+ * implementation of createLabelForKey. This implementation returns a JLabel.
+ */
+ protected JLabel createLabel() {
+ return new JLabel();
}
-/**
-* Appends a label containing a key and the specified component
-* to the bottom of the panel. Any registered action listeners
-* will receive action events from the component - the key corresponding
-* to the component will be used as the action command.
-* @param key A string that will be displayed in a label, preferrably unique.
-* @param component A component that will be placed next to the label.
-* If null, a stock JTextField will be used.
-*/
- protected void addCompositeComponent( String key, Component component )
- {
- if ( key == null )
- {
- key = "";
- }
- Component label = createLabelForKey( key );
- Component field = component;
- if ( field == null )
- {
- field = new JTextField( 15 ); // default to 15 columns
- }
- field.setName( key ); // for association and reference
- label.setName( key ); // ditto
- if ( label instanceof JLabel )
- {
- ((JLabel)label).setHorizontalAlignment( labelAlign );
- ((JLabel)label).setLabelFor( field ); // for accessibility
- }
- if ( "".equals( key ) )
- {
- setText( label, "" );
- }
- else
- {
- setText( label, prefix + key + postfix );
- }
- field.setEnabled( this.isEditable ); // was: setEditable
-
- GridBagConstraints gbc = new GridBagConstraints();
-
- if ( listContainer.getComponentCount() == 0 )
- { // we've just initialized or called removeAll
- createSpacers();
- }
-
- gbc.gridx = ( fields.size() % this.columns ) * 2;
- gbc.gridy = ( fields.size() / this.columns ) + 1; // spacer is at index zero
- gbc.weightx = 0.0;
- gbc.weighty = 0.0;
- gbc.anchor = this.labelAnchor;
- gbc.fill = GridBagConstraints.HORIZONTAL;
- listContainer.add( label, gbc );
+ /**
+ * Appends a label containing a key and the specified component to the bottom of
+ * the panel. Any registered action listeners will receive action events from
+ * the component - the key corresponding to the component will be used as the
+ * action command.
+ *
+ * @param key A string that will be displayed in a label, preferrably
+ * unique.
+ * @param component A component that will be placed next to the label. If null,
+ * a stock JTextField will be used.
+ */
+ protected void addCompositeComponent(String key, Component component) {
+ if (key == null) {
+ key = "";
+ }
+ Component label = createLabelForKey(key);
+ Component field = component;
+ if (field == null) {
+ field = new JTextField(15); // default to 15 columns
+ }
+ field.setName(key); // for association and reference
+ label.setName(key); // ditto
+ if (label instanceof JLabel) {
+ ((JLabel) label).setHorizontalAlignment(labelAlign);
+ ((JLabel) label).setLabelFor(field); // for accessibility
+ }
+ if ("".equals(key)) {
+ setText(label, "");
+ } else {
+ setText(label, prefix + key + postfix);
+ }
+ field.setEnabled(this.isEditable); // was: setEditable
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ if (listContainer.getComponentCount() == 0) { // we've just initialized or called removeAll
+ createSpacers();
+ }
+
+ gbc.gridx = (fields.size() % this.columns) * 2;
+ gbc.gridy = (fields.size() / this.columns) + 1; // spacer is at index zero
+ gbc.weightx = 0.0;
+ gbc.weighty = 0.0;
+ gbc.anchor = this.labelAnchor;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ listContainer.add(label, gbc);
gbc.fill = GridBagConstraints.BOTH;
- gbc.gridx = gbc.gridx + 1;
- //FIXME: components default to the labelAnchor - should be different?
- gbc.weightx = 1.0;
- gbc.weighty = 0.0;
-
- listContainer.add( field, gbc );
-
- if ( key.equals( HIDDEN ) )
- { // these components are not to be shown
- setText( label, " " );
- field.setVisible( false );
- }
-
- fields.add( field ); // using list not map to allow for duplicate keys
- labels.add( label ); // ditto
-
- // handle adding on-the-fly
- updateGaps();
- this.revalidate();
- this.repaint();
- }
+ gbc.gridx = gbc.gridx + 1;
+ // FIXME: components default to the labelAnchor - should be different?
+ gbc.weightx = 1.0;
+ gbc.weighty = 0.0;
-/**
-* Introspects a component to set the action command and to add the
-* InfoPanel to its list of ActionListeners.
-* @param aComponent The Component to be introspected.
-* @param aKey The action command to be set.
-*/
- protected void introspectComponent( Component aComponent, String aKey )
- {
- // try to set properties of whatever component this might be
- try {
- Method [] methods =
- (Method []) _method_cache.get( aComponent.getClass() );
- if (methods == null) {
- Class componentClass = aComponent.getClass();
- BeanInfo info =
- Introspector.getBeanInfo( componentClass );
-
- MethodDescriptor[] descriptors =
- info.getMethodDescriptors();
- Method setMethod = null;
- Method addMethod = null;
- for ( int i = 0;
- ((setMethod == null || addMethod == null) &&
- i < descriptors.length);
- i++ )
- {
- Method m = descriptors[i].getMethod();
- String name = m.getName ();
- if ( setMethod == null &&
- name.equals( "setActionCommand" ) )
- {
- setMethod = m;
- }
- else if ( addMethod == null &&
- name.equals( "addActionListener" ) )
- {
- addMethod = m;
- }
- }
-
- methods = new Method [] {setMethod, addMethod};
- _method_cache.put (componentClass, methods);
- }
- if (methods [0] != null) {
- methods [0].invoke( aComponent, new Object[] { aKey } );
- }
- if (methods [1] != null) {
- methods [1].invoke( aComponent, new Object[] { this } );
- listenedToComponents.add( aComponent );
- }
- }
- catch ( Exception exc )
- { // error occured while introspecting... move along.
- System.out.println( "InfoPanel.introspectComponent: " + exc );
- }
- }
-
-/**
-* Called to populate a label component with the specified text.
-* This implementation attempts to call setText(String) on the component.
-* Override to customize.
-*/
- protected void setText( Component c, String text )
- {
- try
- {
- Method m = c.getClass().getMethod( "setText", new Class[] { String.class } );
- if ( m != null )
- {
- m.invoke( c, new Object[] { text } );
- }
- }
- catch ( Exception exc )
- {
- // no such method: ignore
- }
- }
+ listContainer.add(field, gbc);
-/**
-* Creates spacer components on the reserved first grid row
-* for each column of labels and fields.
-* This allows us to set the margin for those label columns,
-* and set the preferred width of the field columns.
-* A list containing the field spacers should be assigned to
-* the fieldSpacers instance variable.
-*/
- private void createSpacers()
- {
- if ( listContainer.getLayout() instanceof GridBagLayout )
- {
- // insert spacers for labels column
- GridBagLayout gridBag = (GridBagLayout) listContainer.getLayout();
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.gridy = 0;
- constraints.fill = GridBagConstraints.HORIZONTAL;
-
- fieldSpacers = new LinkedList();
- Component fieldSpacer;
- for ( int i = 0; i < this.columns; i++ )
- {
- constraints.gridx = i * 2;
- listContainer.add( Box.createHorizontalStrut( this.margin ), constraints );
-
- constraints.gridx = i * 2 + 1;
- fieldSpacer = Box.createHorizontalStrut( 0 );
- fieldSpacers.add( fieldSpacer );
- listContainer.add( fieldSpacer, constraints );
- }
- }
- }
+ if (key.equals(HIDDEN)) { // these components are not to be shown
+ setText(label, " ");
+ field.setVisible(false);
+ }
-/**
-* Updates the insets for all components.
-*/
- protected void updateGaps()
- {
- if ( listContainer.getLayout() instanceof GridBagLayout )
- {
- GridBagLayout layout = (GridBagLayout) listContainer.getLayout();
- Component c = null;
- GridBagConstraints gbc = null;
- double totalWeightY = 0.0;
- int count = listContainer.getComponentCount();
- int i;
- for ( i = 0; i < count; i++ )
- {
- c = listContainer.getComponent( i );
- gbc = layout.getConstraints( c );
- totalWeightY += gbc.weighty;
- if ( (gbc.gridx + 1) % ( this.columns * 2 ) == 0 )
- { // if last component in row
- gbc.insets = new Insets( 0, 0, this.vgap, 0 );
- }
- else
- {
- if ( gbc.gridx % 2 == 0 )
- { // is a label column - NOTE: uses eleven pixels before component, per l&f guide
- gbc.insets = new Insets( 0, 0, this.vgap, 11 );
- }
- else
- { // is a component column
- if ( gbc.gridy != 0 )
- {
- if ( c instanceof JPanel ) ((JPanel)c).setPreferredSize( null );
- gbc.insets = new Insets( 0, 0, this.vgap, this.hgap );
- }
- }
- }
- layout.setConstraints( c, gbc );
- }
-
- //hack: gridbag clumps components in center if weighty is zero
- // if sum of weighty is zero, top-justify the list container
- this.remove( listContainer );
- if ( totalWeightY == 0.0 )
- {
- this.add( listContainer, BorderLayout.NORTH );
- }
- else // put list container in center so it will grow
- {
- this.add( listContainer, BorderLayout.CENTER );
- }
- }
- }
+ fields.add(field); // using list not map to allow for duplicate keys
+ labels.add(label); // ditto
-/**
-* Updates the label alignment.
-*/
- protected void updateLabels()
- {
- if ( listContainer.getLayout() instanceof GridBagLayout )
- {
- GridBagLayout layout = (GridBagLayout) listContainer.getLayout();
- Component c = null;
- GridBagConstraints gbc = null;
+ // handle adding on-the-fly
+ updateGaps();
+ this.revalidate();
+ this.repaint();
+ }
+
+ /**
+ * Introspects a component to set the action command and to add the InfoPanel to
+ * its list of ActionListeners.
+ *
+ * @param aComponent The Component to be introspected.
+ * @param aKey The action command to be set.
+ */
+ protected void introspectComponent(Component aComponent, String aKey) {
+ // try to set properties of whatever component this might be
+ try {
+ Method[] methods = (Method[]) _method_cache.get(aComponent.getClass());
+ if (methods == null) {
+ Class componentClass = aComponent.getClass();
+ BeanInfo info = Introspector.getBeanInfo(componentClass);
+
+ MethodDescriptor[] descriptors = info.getMethodDescriptors();
+ Method setMethod = null;
+ Method addMethod = null;
+ for (int i = 0; ((setMethod == null || addMethod == null) && i < descriptors.length); i++) {
+ Method m = descriptors[i].getMethod();
+ String name = m.getName();
+ if (setMethod == null && name.equals("setActionCommand")) {
+ setMethod = m;
+ } else if (addMethod == null && name.equals("addActionListener")) {
+ addMethod = m;
+ }
+ }
+
+ methods = new Method[] { setMethod, addMethod };
+ _method_cache.put(componentClass, methods);
+ }
+ if (methods[0] != null) {
+ methods[0].invoke(aComponent, new Object[] { aKey });
+ }
+ if (methods[1] != null) {
+ methods[1].invoke(aComponent, new Object[] { this });
+ listenedToComponents.add(aComponent);
+ }
+ } catch (Exception exc) { // error occured while introspecting... move along.
+ System.out.println("InfoPanel.introspectComponent: " + exc);
+ }
+ }
+
+ /**
+ * Called to populate a label component with the specified text. This
+ * implementation attempts to call setText(String) on the component. Override to
+ * customize.
+ */
+ protected void setText(Component c, String text) {
+ try {
+ Method m = c.getClass().getMethod("setText", new Class[] { String.class });
+ if (m != null) {
+ m.invoke(c, new Object[] { text });
+ }
+ } catch (Exception exc) {
+ // no such method: ignore
+ }
+ }
+
+ /**
+ * Creates spacer components on the reserved first grid row for each column of
+ * labels and fields. This allows us to set the margin for those label columns,
+ * and set the preferred width of the field columns. A list containing the field
+ * spacers should be assigned to the fieldSpacers instance variable.
+ */
+ private void createSpacers() {
+ if (listContainer.getLayout() instanceof GridBagLayout) {
+ // insert spacers for labels column
+ GridBagLayout gridBag = (GridBagLayout) listContainer.getLayout();
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.gridy = 0;
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+
+ fieldSpacers = new LinkedList();
+ Component fieldSpacer;
+ for (int i = 0; i < this.columns; i++) {
+ constraints.gridx = i * 2;
+ listContainer.add(Box.createHorizontalStrut(this.margin), constraints);
+
+ constraints.gridx = i * 2 + 1;
+ fieldSpacer = Box.createHorizontalStrut(0);
+ fieldSpacers.add(fieldSpacer);
+ listContainer.add(fieldSpacer, constraints);
+ }
+ }
+ }
+
+ /**
+ * Updates the insets for all components.
+ */
+ protected void updateGaps() {
+ if (listContainer.getLayout() instanceof GridBagLayout) {
+ GridBagLayout layout = (GridBagLayout) listContainer.getLayout();
+ Component c = null;
+ GridBagConstraints gbc = null;
+ double totalWeightY = 0.0;
+ int count = listContainer.getComponentCount();
+ int i;
+ for (i = 0; i < count; i++) {
+ c = listContainer.getComponent(i);
+ gbc = layout.getConstraints(c);
+ totalWeightY += gbc.weighty;
+ if ((gbc.gridx + 1) % (this.columns * 2) == 0) { // if last component in row
+ gbc.insets = new Insets(0, 0, this.vgap, 0);
+ } else {
+ if (gbc.gridx % 2 == 0) { // is a label column - NOTE: uses eleven pixels before component, per l&f
+ // guide
+ gbc.insets = new Insets(0, 0, this.vgap, 11);
+ } else { // is a component column
+ if (gbc.gridy != 0) {
+ if (c instanceof JPanel)
+ ((JPanel) c).setPreferredSize(null);
+ gbc.insets = new Insets(0, 0, this.vgap, this.hgap);
+ }
+ }
+ }
+ layout.setConstraints(c, gbc);
+ }
+
+ // hack: gridbag clumps components in center if weighty is zero
+ // if sum of weighty is zero, top-justify the list container
+ this.remove(listContainer);
+ if (totalWeightY == 0.0) {
+ this.add(listContainer, BorderLayout.NORTH);
+ } else // put list container in center so it will grow
+ {
+ this.add(listContainer, BorderLayout.CENTER);
+ }
+ }
+ }
+
+ /**
+ * Updates the label alignment.
+ */
+ protected void updateLabels() {
+ if (listContainer.getLayout() instanceof GridBagLayout) {
+ GridBagLayout layout = (GridBagLayout) listContainer.getLayout();
+ Component c = null;
+ GridBagConstraints gbc = null;
Iterator it = labels.iterator();
- while ( it.hasNext() )
- {
- c = (Component) it.next();
- if ( c instanceof JLabel )
- {
- ((JLabel)c).setHorizontalAlignment( labelAlign );
- }
- gbc = layout.getConstraints( c );
- gbc.anchor = this.labelAnchor;
- layout.setConstraints( c, gbc );
- }
- }
- }
+ while (it.hasNext()) {
+ c = (Component) it.next();
+ if (c instanceof JLabel) {
+ ((JLabel) c).setHorizontalAlignment(labelAlign);
+ }
+ gbc = layout.getConstraints(c);
+ gbc.anchor = this.labelAnchor;
+ layout.setConstraints(c, gbc);
+ }
+ }
+ }
-/**
-* Convenience method that uses a stock JTextField.
-* @param key A string that will be displayed in a label, preferrably unique.
-* @param value A string that will be displayed in a textfield.
-*/
- public void addPair( String key, String value )
- {
- addPair( key, value, null );
- }
+ /**
+ * Convenience method that uses a stock JTextField.
+ *
+ * @param key A string that will be displayed in a label, preferrably unique.
+ * @param value A string that will be displayed in a textfield.
+ */
+ public void addPair(String key, String value) {
+ addPair(key, value, null);
+ }
-/**
-* Convenience method that uses the specified JTextField or subclass
-* and sets it to the specified value.
-* @param key A string that will be displayed in a label, preferrably unique.
-* @param value A string that will be displayed in a textfield.
-* @param textField A JTextField or subclass that will be used to display the value.
-* If null, a stock JTextField will be used.
-*/
- public void addPair( String key, String value, JTextField textField )
- {
- if ( value == null )
- {
- value = "";
- }
- JTextField field = textField;
- if ( field == null )
- {
- field = new JTextField( 15 ); // default to 15 columns
- }
- else
- {
- field = textField;
- }
- field.setText( value );
-
- addPair( key, (Component) field );
- }
+ /**
+ * Convenience method that uses the specified JTextField or subclass and sets it
+ * to the specified value.
+ *
+ * @param key A string that will be displayed in a label, preferrably
+ * unique.
+ * @param value A string that will be displayed in a textfield.
+ * @param textField A JTextField or subclass that will be used to display the
+ * value. If null, a stock JTextField will be used.
+ */
+ public void addPair(String key, String value, JTextField textField) {
+ if (value == null) {
+ value = "";
+ }
+ JTextField field = textField;
+ if (field == null) {
+ field = new JTextField(15); // default to 15 columns
+ } else {
+ field = textField;
+ }
+ field.setText(value);
-/**
-* Removes all components from the list. Buttons, if any,
-* will remain unchanged - use setButtons( null ) to remove
-* them. NOTE: does not call super.removeAll().
-*/
- public void removeAll()
- {
- Object component;
- Method method;
- Class[] paramClasses = new Class[] { ActionListener.class };
- Object[] paramObjects = new Object[] { this };
-
- Iterator iterator = listenedToComponents.iterator();
- while ( iterator.hasNext() )
- {
- component = iterator.next();
- try
- {
- method = component.getClass().getMethod( "removeActionListener", paramClasses );
- if ( method != null )
- {
- method.invoke( component, paramObjects );
- }
- }
- catch ( Exception exception )
- {
- // No removeActionListener() method, move along.
- }
- }
-
- listenedToComponents.clear();
-
- listContainer.removeAll();
- fields.clear();
- labels.clear();
- this.revalidate();
- this.repaint();
-
- //FIXME: It is very confusing that this
- // implementation does not call super.removeAll().
- }
+ addPair(key, (Component) field);
+ }
-/**
-* Adds one or buttons to the bottom of the panel with the specified labels
-* from left to right. Any action listeners will receive action events
-* from clicks on these buttons - the supplied label will be used as the action command.
-* @param buttons A string array containing the strings to be used for the button labels
-* and action commands. A null value will remove the button panel.
-* @see ButtonPanel
-*/
- public void setButtons( String[] buttons )
- {
- if ( buttonPanel == null )
- {
- buttonPanel = new ButtonPanel();
- buttonPanel.setInsets( new Insets( 6, 0, 0, 0 ) );
- // button panel has a 11-pixel top inset
- // and java l&f guide says 17-pixels before command buttons
- buttonPanel.addActionListener( this );
- this.add( buttonPanel, BorderLayout.SOUTH );
- }
- if ( buttons == null )
- {
- this.remove( buttonPanel );
- buttonPanel = null;
- }
- else
- {
- buttonPanel.setLabels( buttons );
- }
-
- this.revalidate();
- this.repaint();
- }
- protected Collection listenedToComponents = new LinkedList();
+ /**
+ * Removes all components from the list. Buttons, if any, will remain unchanged
+ * - use setButtons( null ) to remove them. NOTE: does not call
+ * super.removeAll().
+ */
+ public void removeAll() {
+ Object component;
+ Method method;
+ Class[] paramClasses = new Class[] { ActionListener.class };
+ Object[] paramObjects = new Object[] { this };
+
+ Iterator iterator = listenedToComponents.iterator();
+ while (iterator.hasNext()) {
+ component = iterator.next();
+ try {
+ method = component.getClass().getMethod("removeActionListener", paramClasses);
+ if (method != null) {
+ method.invoke(component, paramObjects);
+ }
+ } catch (Exception exception) {
+ // No removeActionListener() method, move along.
+ }
+ }
-/**
-* Retrieves the names of the buttons that are displayed, if any.
-* @return A string array containing the strings used for the button labels
-* and action commands, or null if no buttons have been created.
-* @see ButtonPanel
-*/
- public String[] getButtons()
- {
- if ( buttonPanel == null )
- {
- return null; // none created
- }
+ listenedToComponents.clear();
- return buttonPanel.getLabels();
- }
+ listContainer.removeAll();
+ fields.clear();
+ labels.clear();
+ this.revalidate();
+ this.repaint();
-/**
-* Retrieves the actual button panel, if any.
-* @return A button panel, or null if none has been created.
-* @see ButtonPanel
-*/
- public ButtonPanel getButtonPanel()
- {
- return buttonPanel;
- }
+ // FIXME: It is very confusing that this
+ // implementation does not call super.removeAll().
+ }
+ /**
+ * Adds one or buttons to the bottom of the panel with the specified labels from
+ * left to right. Any action listeners will receive action events from clicks on
+ * these buttons - the supplied label will be used as the action command.
+ *
+ * @param buttons A string array containing the strings to be used for the
+ * button labels and action commands. A null value will remove
+ * the button panel.
+ * @see ButtonPanel
+ */
+ public void setButtons(String[] buttons) {
+ if (buttonPanel == null) {
+ buttonPanel = new ButtonPanel();
+ buttonPanel.setInsets(new Insets(6, 0, 0, 0));
+ // button panel has a 11-pixel top inset
+ // and java l&f guide says 17-pixels before command buttons
+ buttonPanel.addActionListener(this);
+ this.add(buttonPanel, BorderLayout.SOUTH);
+ }
+ if (buttons == null) {
+ this.remove(buttonPanel);
+ buttonPanel = null;
+ } else {
+ buttonPanel.setLabels(buttons);
+ }
-/**
-* Sets whether the values displayed in the panel should be editable. Defaults to true.
-* @param isEditable Whether the values should be editable.
-*/
- public void setEditable( boolean isEditable )
- {
- this.isEditable = isEditable;
- Iterator enumeration = fields.iterator();
- while ( enumeration.hasNext() )
- {
- ( (Component) enumeration.next() ).setEnabled( isEditable );
- }
- }
+ this.revalidate();
+ this.repaint();
+ }
-/**
-* Gets whether the values displayed in the panel are editable.
-* @return Whether the values should be editable.
-*/
- public boolean isEditable()
- {
- return this.isEditable;
- }
+ protected Collection listenedToComponents = new LinkedList();
+
+ /**
+ * Retrieves the names of the buttons that are displayed, if any.
+ *
+ * @return A string array containing the strings used for the button labels and
+ * action commands, or null if no buttons have been created.
+ * @see ButtonPanel
+ */
+ public String[] getButtons() {
+ if (buttonPanel == null) {
+ return null; // none created
+ }
-/**
-* Sets the field associated with the key to the specified value.
-* Note: If the component does not respond to setText() or setString()
-* or setValue() the value will not be set. JTextFields and the like will work.
-* @param key A string representing the key associated with the field. Nulls are converted to an empty string.
-* @param value A object to be displayed in the specified field. Nulls are converted to an empty string.
-*/
- public void setValueForKey( String key, Object value )
- {
- setValueForKey( key, value, 0 );
+ return buttonPanel.getLabels();
}
-
-/**
-* Sets the field associated with the key to the specified value.
-* Note: If the component does not respond to setText() or setString()
-* or setValue() the value will not be set. JTextFields and the like will work.
-* @param key A string representing the key associated with the field. Nulls are converted to an empty string.
-* @param value A object to be displayed in the specified field. Nulls are converted to an empty string.
-*/
- public void setValueForKey( String key, Object value, int index )
- {
- if ( key == null )
- {
- key = "";
- }
-
- Container field = null;
- for ( int i = 0; i < fields.size(); i++ )
- {
- field = (Container) fields.get(i);
- if ( key.equals( field.getName() ) )
- {
- setValueForIndex( index, i, value );
+
+ /**
+ * Retrieves the actual button panel, if any.
+ *
+ * @return A button panel, or null if none has been created.
+ * @see ButtonPanel
+ */
+ public ButtonPanel getButtonPanel() {
+ return buttonPanel;
+ }
+
+ /**
+ * Sets whether the values displayed in the panel should be editable. Defaults
+ * to true.
+ *
+ * @param isEditable Whether the values should be editable.
+ */
+ public void setEditable(boolean isEditable) {
+ this.isEditable = isEditable;
+ Iterator enumeration = fields.iterator();
+ while (enumeration.hasNext()) {
+ ((Component) enumeration.next()).setEnabled(isEditable);
+ }
+ }
+
+ /**
+ * Gets whether the values displayed in the panel are editable.
+ *
+ * @return Whether the values should be editable.
+ */
+ public boolean isEditable() {
+ return this.isEditable;
+ }
+
+ /**
+ * Sets the field associated with the key to the specified value. Note: If the
+ * component does not respond to setText() or setString() or setValue() the
+ * value will not be set. JTextFields and the like will work.
+ *
+ * @param key A string representing the key associated with the field. Nulls
+ * are converted to an empty string.
+ * @param value A object to be displayed in the specified field. Nulls are
+ * converted to an empty string.
+ */
+ public void setValueForKey(String key, Object value) {
+ setValueForKey(key, value, 0);
+ }
+
+ /**
+ * Sets the field associated with the key to the specified value. Note: If the
+ * component does not respond to setText() or setString() or setValue() the
+ * value will not be set. JTextFields and the like will work.
+ *
+ * @param key A string representing the key associated with the field. Nulls
+ * are converted to an empty string.
+ * @param value A object to be displayed in the specified field. Nulls are
+ * converted to an empty string.
+ */
+ public void setValueForKey(String key, Object value, int index) {
+ if (key == null) {
+ key = "";
+ }
+
+ Container field = null;
+ for (int i = 0; i < fields.size(); i++) {
+ field = (Container) fields.get(i);
+ if (key.equals(field.getName())) {
+ setValueForIndex(index, i, value);
return;
- }
+ }
}
- // else not found - ignore
- }
-
-/**
-* Sets the first field at the specified row index to the specified value.
-* Note: If the component does not respond to setText() or setString()
-* or setValue() the value will not be set. JTextFields and the like will work.
-* @param row The row index of the component.
-* @param value A object to be displayed in the specified field.
-* Nulls are converted to an empty string.
-*/
- public void setValueForIndex( int row, Object value )
- {
- setValueForIndex( row, 0, value );
+ // else not found - ignore
}
-
-/**
-* Sets the field at the specified row index and column index to the specified value.
-* Note: If the component does not respond to setText() or setString()
-* or setValue() the value will not be set. JTextFields and the like will work.
-* @param row The row index of the component.
-* @param index The column index of the component.
-* @param value A object to be displayed in the specified field.
-* Nulls are converted to an empty string.
-*/
- public void setValueForIndex( int row, int col, Object value )
- {
- Container field = (Container) fields.get( row );
- Component c = field.getComponent( col );
- setValueForComponent( c, value );
+
+ /**
+ * Sets the first field at the specified row index to the specified value. Note:
+ * If the component does not respond to setText() or setString() or setValue()
+ * the value will not be set. JTextFields and the like will work.
+ *
+ * @param row The row index of the component.
+ * @param value A object to be displayed in the specified field. Nulls are
+ * converted to an empty string.
+ */
+ public void setValueForIndex(int row, Object value) {
+ setValueForIndex(row, 0, value);
}
-
+ /**
+ * Sets the field at the specified row index and column index to the specified
+ * value. Note: If the component does not respond to setText() or setString() or
+ * setValue() the value will not be set. JTextFields and the like will work.
+ *
+ * @param row The row index of the component.
+ * @param index The column index of the component.
+ * @param value A object to be displayed in the specified field. Nulls are
+ * converted to an empty string.
+ */
+ public void setValueForIndex(int row, int col, Object value) {
+ Container field = (Container) fields.get(row);
+ Component c = field.getComponent(col);
+ setValueForComponent(c, value);
+ }
-/**
-* Sets the value in the field at the specified index.
-* Note: If the component does not respond to setText() or setString()
-* or setValue() this method will return null. JTextFields and the like will work.
-* @param A valid index.
-* @param value A object to be displayed in the specified field.
-*/
- protected void setValueForComponent( Component aComponent, Object value )
- {
- // try to set a text or string property
- try {
- BeanInfo info = Introspector.getBeanInfo( aComponent.getClass() );
- MethodDescriptor[] methods = info.getMethodDescriptors();
- for ( int i = 0; i < methods.length; i++ )
- {
- Method m = methods[i].getMethod();
- Class[] paramTypes = m.getParameterTypes();
- if ( paramTypes.length == 1 )
- {
- if ( m.getName().equals( "setText" ) )
- {
- if ( paramTypes[0].getName().equals( String.class.getName() ) )
- {
- m.invoke( aComponent, new Object[] { value } );
- }
- }
- if ( m.getName().equals( "setString" ) )
- {
- if ( paramTypes[0].getName().equals( String.class.getName() ) )
- {
- m.invoke( aComponent, new Object[] { value } );
- }
- }
- if ( m.getName().equals( "setValue" ) )
- {
- if ( paramTypes[0].getName().equals( Object.class.getName() ) )
- {
- m.invoke( aComponent, new Object[] { value } );
- }
- }
- }
- }
- }
- catch ( Exception exc )
- { // error occured while introspecting... move along.
- // FIXME: should log error in ErrorManager
- System.out.println( "InfoPanel.setValueForComponent: " + exc );
- }
- }
+ /**
+ * Sets the value in the field at the specified index. Note: If the component
+ * does not respond to setText() or setString() or setValue() this method will
+ * return null. JTextFields and the like will work.
+ *
+ * @param A valid index.
+ * @param value A object to be displayed in the specified field.
+ */
+ protected void setValueForComponent(Component aComponent, Object value) {
+ // try to set a text or string property
+ try {
+ BeanInfo info = Introspector.getBeanInfo(aComponent.getClass());
+ MethodDescriptor[] methods = info.getMethodDescriptors();
+ for (int i = 0; i < methods.length; i++) {
+ Method m = methods[i].getMethod();
+ Class[] paramTypes = m.getParameterTypes();
+ if (paramTypes.length == 1) {
+ if (m.getName().equals("setText")) {
+ if (paramTypes[0].getName().equals(String.class.getName())) {
+ m.invoke(aComponent, new Object[] { value });
+ }
+ }
+ if (m.getName().equals("setString")) {
+ if (paramTypes[0].getName().equals(String.class.getName())) {
+ m.invoke(aComponent, new Object[] { value });
+ }
+ }
+ if (m.getName().equals("setValue")) {
+ if (paramTypes[0].getName().equals(Object.class.getName())) {
+ m.invoke(aComponent, new Object[] { value });
+ }
+ }
+ }
+ }
+ } catch (Exception exc) { // error occured while introspecting... move along.
+ // FIXME: should log error in ErrorManager
+ System.out.println("InfoPanel.setValueForComponent: " + exc);
+ }
+ }
-/**
-* Gets the value in the field at the specified index.
-* Note: If the component does not respond to getText() or getString()
-* or getSelectedItem() this method will return null. JTextFields and the like will work.
-* @param A valid index.
-* @return An object representing the value in the field at the specified index,
-* or null if the component does not have a text property or if the index is out of bounds.
-*/
- public Object getValueForIndex( int anIndex )
- {
- return getValueForIndex( anIndex, 0 );
- }
+ /**
+ * Gets the value in the field at the specified index. Note: If the component
+ * does not respond to getText() or getString() or getSelectedItem() this method
+ * will return null. JTextFields and the like will work.
+ *
+ * @param A valid index.
+ * @return An object representing the value in the field at the specified index,
+ * or null if the component does not have a text property or if the
+ * index is out of bounds.
+ */
+ public Object getValueForIndex(int anIndex) {
+ return getValueForIndex(anIndex, 0);
+ }
-/**
-* Gets the value in the field at the specified row and column.
-* Note: If the component does not respond to getText() or getString()
-* or getSelectedItem() this method will return null. JTextFields and the like will work.
-* @param A valid index.
-* @return An object representing the value in the field at the specified index,
-* or null if the component does not have a text property or if the index is out of bounds.
-*/
- public Object getValueForIndex( int row, int col )
- {
- if ( ( row >= fields.size() ) || ( row < 0 ) )
- { // out of bounds
- return null;
- }
-
- Container field = (Container) fields.get( row );
- Component c = field.getComponent( col );
- return getValueForComponent( c );
- }
+ /**
+ * Gets the value in the field at the specified row and column. Note: If the
+ * component does not respond to getText() or getString() or getSelectedItem()
+ * this method will return null. JTextFields and the like will work.
+ *
+ * @param A valid index.
+ * @return An object representing the value in the field at the specified index,
+ * or null if the component does not have a text property or if the
+ * index is out of bounds.
+ */
+ public Object getValueForIndex(int row, int col) {
+ if ((row >= fields.size()) || (row < 0)) { // out of bounds
+ return null;
+ }
-/**
-* Gets the value in the field associated with the key.
-* Note: If the component does not respond to getText() or getString()
-* or getSelectedItem() this method will return null. JTextFields and the like will work.
-* @param key An string representing the key associated with the field. Nulls are converted to an empty string.
-* @return An object representing the value in the field associated with the key,
-* or null if the key does not exist or if the component does not have a text property.
-*/
- public Object getValueForKey( String key )
- {
- return getValueForKey( key, 0 );
+ Container field = (Container) fields.get(row);
+ Component c = field.getComponent(col);
+ return getValueForComponent(c);
}
-/**
-* Gets the value in the field associated with the key.
-* Note: If the component does not respond to getText() or getString()
-* or getSelectedItem() this method will return null. JTextFields and the like will work.
-* @param key An string representing the key associated with the field. Nulls are converted to an empty string.
-* @return An object representing the value in the field associated with the key,
-* or null if the key does not exist or if the component does not have a text property.
-*/
- public Object getValueForKey( String key, int index )
- {
- if ( key == null )
- {
- key = "";
- }
-
- Container field = null;
- Iterator enumeration = fields.iterator();
- while ( enumeration.hasNext() )
- { // finds first value in list with specified key
- field = (Container) enumeration.next();
- if ( key.equals( field.getName() ) )
- {
- Component c = field.getComponent( index );
- if ( c != null )
- {
- return getValueForComponent( c );
+ /**
+ * Gets the value in the field associated with the key. Note: If the component
+ * does not respond to getText() or getString() or getSelectedItem() this method
+ * will return null. JTextFields and the like will work.
+ *
+ * @param key An string representing the key associated with the field. Nulls
+ * are converted to an empty string.
+ * @return An object representing the value in the field associated with the
+ * key, or null if the key does not exist or if the component does not
+ * have a text property.
+ */
+ public Object getValueForKey(String key) {
+ return getValueForKey(key, 0);
+ }
+
+ /**
+ * Gets the value in the field associated with the key. Note: If the component
+ * does not respond to getText() or getString() or getSelectedItem() this method
+ * will return null. JTextFields and the like will work.
+ *
+ * @param key An string representing the key associated with the field. Nulls
+ * are converted to an empty string.
+ * @return An object representing the value in the field associated with the
+ * key, or null if the key does not exist or if the component does not
+ * have a text property.
+ */
+ public Object getValueForKey(String key, int index) {
+ if (key == null) {
+ key = "";
+ }
+
+ Container field = null;
+ Iterator enumeration = fields.iterator();
+ while (enumeration.hasNext()) { // finds first value in list with specified key
+ field = (Container) enumeration.next();
+ if (key.equals(field.getName())) {
+ Component c = field.getComponent(index);
+ if (c != null) {
+ return getValueForComponent(c);
}
- }
- }
- // else not found
- return null;
- }
+ }
+ }
+ // else not found
+ return null;
+ }
-/**
-* Gets the value in the specified component.
-* Note: If the component does not respond to getText() or getString()
-* or getSelectedItem() this method will return null. JTextFields and the like will work.
-* @param aComponent The specified component.
-* @return An object representing the value in the component.
-* or null if the component does not have a text property.
-*/
- protected Object getValueForComponent( Component aComponent )
- {
- // try to get a text or string property
- try
- {
- BeanInfo info = Introspector.getBeanInfo( aComponent.getClass() );
- MethodDescriptor[] methods = info.getMethodDescriptors();
- for ( int i = 0; i < methods.length; i++ )
- {
- Method m = methods[i].getMethod();
- Class[] paramTypes = m.getParameterTypes();
- if ( m.getName().equals( "getText" ) )
- {
- if ( paramTypes.length == 0 )
- {
- return m.invoke( aComponent, new Object[] {} );
- }
- }
- if ( m.getName().equals( "getString" ) )
- {
- if ( paramTypes.length == 0 )
- {
- return m.invoke( aComponent, new Object[] {} );
- }
- }
- if ( m.getName().equals( "getSelectedItem" ) )
- {
- if ( paramTypes.length == 0 )
- {
- return m.invoke( aComponent, new Object[] {} );
- }
- }
- // TODO: should also handle variants of setValue()
- }
- }
- catch ( Exception exc )
- { // error occured while introspecting... move along.
- System.out.println( "InfoPanel.getValueFromComponent: " + exc );
- }
-
- // not found
- return null;
- }
+ /**
+ * Gets the value in the specified component. Note: If the component does not
+ * respond to getText() or getString() or getSelectedItem() this method will
+ * return null. JTextFields and the like will work.
+ *
+ * @param aComponent The specified component.
+ * @return An object representing the value in the component. or null if the
+ * component does not have a text property.
+ */
+ protected Object getValueForComponent(Component aComponent) {
+ // try to get a text or string property
+ try {
+ BeanInfo info = Introspector.getBeanInfo(aComponent.getClass());
+ MethodDescriptor[] methods = info.getMethodDescriptors();
+ for (int i = 0; i < methods.length; i++) {
+ Method m = methods[i].getMethod();
+ Class[] paramTypes = m.getParameterTypes();
+ if (m.getName().equals("getText")) {
+ if (paramTypes.length == 0) {
+ return m.invoke(aComponent, new Object[] {});
+ }
+ }
+ if (m.getName().equals("getString")) {
+ if (paramTypes.length == 0) {
+ return m.invoke(aComponent, new Object[] {});
+ }
+ }
+ if (m.getName().equals("getSelectedItem")) {
+ if (paramTypes.length == 0) {
+ return m.invoke(aComponent, new Object[] {});
+ }
+ }
+ // TODO: should also handle variants of setValue()
+ }
+ } catch (Exception exc) { // error occured while introspecting... move along.
+ System.out.println("InfoPanel.getValueFromComponent: " + exc);
+ }
-/**
-* Gets the component associated with the key as a JTextField, for backwards compatibility.
-* @param key A string representing the key associated with the component. Nulls are converted to an empty string.
-* @return A JTextField that contains the value associated with the key,
-* or null if the key does not exist or if the component is not a JTextField.
-*/
- public JTextField getFieldForKey( String key )
- {
- Component c = getComponentForKey( key );
- if ( c instanceof JTextField )
- {
- return (JTextField) c;
- }
- return null;
- }
+ // not found
+ return null;
+ }
-/**
-* Gets the component associated with the key. If more than one component is associated
-* with the key, returns the first such component.
-* @param key A string representing the key associated with the component.
-* Nulls are converted to an empty string.
-* @return A component that contains the value associated with the key,
-* or null if the key does not exist.
-*/
- public Component getComponentForKey( String key )
- {
- return getComponentForKey( key, 0 );
+ /**
+ * Gets the component associated with the key as a JTextField, for backwards
+ * compatibility.
+ *
+ * @param key A string representing the key associated with the component. Nulls
+ * are converted to an empty string.
+ * @return A JTextField that contains the value associated with the key, or null
+ * if the key does not exist or if the component is not a JTextField.
+ */
+ public JTextField getFieldForKey(String key) {
+ Component c = getComponentForKey(key);
+ if (c instanceof JTextField) {
+ return (JTextField) c;
+ }
+ return null;
}
-/**
-* Gets the component associated with the key and index.
-* @param key A string representing the key associated with the component.
-* Nulls are converted to an empty string.
-* @return A component that contains the value associated with the key,
-* or null if the key does not exist.
-*/
- public Component getComponentForKey( String key, int index )
- {
- Container c = getCompositeComponentForKey( key );
- if ( c == null ) return null;
- return c.getComponent( index );
- }
+ /**
+ * Gets the component associated with the key. If more than one component is
+ * associated with the key, returns the first such component.
+ *
+ * @param key A string representing the key associated with the component. Nulls
+ * are converted to an empty string.
+ * @return A component that contains the value associated with the key, or null
+ * if the key does not exist.
+ */
+ public Component getComponentForKey(String key) {
+ return getComponentForKey(key, 0);
+ }
-/**
-* Gets the component at the specified row. If more than one component exists
-* on that row, returns the first such component.
-* @return A component or null if the row does not exist.
-*/
- public Object getComponentForIndex( int row )
- {
- return getComponentForIndex( row, 0 );
- }
+ /**
+ * Gets the component associated with the key and index.
+ *
+ * @param key A string representing the key associated with the component. Nulls
+ * are converted to an empty string.
+ * @return A component that contains the value associated with the key, or null
+ * if the key does not exist.
+ */
+ public Component getComponentForKey(String key, int index) {
+ Container c = getCompositeComponentForKey(key);
+ if (c == null)
+ return null;
+ return c.getComponent(index);
+ }
-/**
-* Gets the component at the specified row and column.
-* @return A component or null if the index is out of bounds.
-*/
- public Object getComponentForIndex( int row, int col )
- {
- if ( ( row > fields.size() ) || ( row < 0 ) )
- { // out of bounds
- return null;
- }
-
- Container field = (Container) fields.get( row );
- return field.getComponent( col );
- }
+ /**
+ * Gets the component at the specified row. If more than one component exists on
+ * that row, returns the first such component.
+ *
+ * @return A component or null if the row does not exist.
+ */
+ public Object getComponentForIndex(int row) {
+ return getComponentForIndex(row, 0);
+ }
-/**
-* Gets the container associated with the key.
-* @param key A string representing the key associated with the component.
-* Nulls are converted to an empty string.
-* @return A component that contains the value associated with the key,
-* or null if the key does not exist.
-*/
- protected Container getCompositeComponentForKey( String key )
- {
- if ( key == null )
- {
- key = "";
- }
-
- JPanel field = null;
- Iterator enumeration = fields.iterator();
- while ( enumeration.hasNext() )
- { // finds first value in list with specified key
- field = (JPanel) enumeration.next();
- if ( key.equals( field.getName() ) )
- {
- return field;
- }
- }
-
- // else not found
- return null;
- }
+ /**
+ * Gets the component at the specified row and column.
+ *
+ * @return A component or null if the index is out of bounds.
+ */
+ public Object getComponentForIndex(int row, int col) {
+ if ((row > fields.size()) || (row < 0)) { // out of bounds
+ return null;
+ }
-/**
-* Provided for backwards compatibility: calls getLabelComponentForKey.
-* @param key A string representing the key associated with the compoent.
-* Nulls are converted to an empty string.
-* @return Component label object associated with the key, or null if the key does not exist
-* or if the label component is not an instance of JLabel.
-*/
- public JLabel getLabelForKey( String key )
- {
- Component result = getLabelComponentForKey( key );
- if ( result instanceof JLabel ) return (JLabel) result;
- return null;
- }
-
-/**
-* Get the label component associated with the key.
-* @param key A string representing the key associated with the compoent.
-* Nulls are converted to an empty string.
-* @return Component label object associated with the key, or null if the key does not exist.
-*/
- public Component getLabelComponentForKey( String key )
- {
- if ( key == null )
- {
- key = "";
- }
-
- Component label = null;
- Iterator enumeration = labels.iterator();
- while ( enumeration.hasNext() )
- { // finds first value in list with specified key
- label = (Component) enumeration.next();
- if ( key.equals( label.getName() ) )
- {
- return label;
- }
- }
-
- // else not found
- return null;
- }
+ Container field = (Container) fields.get(row);
+ return field.getComponent(col);
+ }
-/**
-* Replaces the first component associated with the key. Any value in the existing
-* component will be copied to the new component.
-* @param key A string representing the key to be associated with the component.
-* Nulls are converted to an empty string.
-* @param c A component to be placed next to the label corresponding to the key.
-* Nulls are converted to a JTextField.
-*/
- public void setComponentForKey( String key, Component c )
- {
- setComponentForKey( key, c, 0 );
+ /**
+ * Gets the container associated with the key.
+ *
+ * @param key A string representing the key associated with the component. Nulls
+ * are converted to an empty string.
+ * @return A component that contains the value associated with the key, or null
+ * if the key does not exist.
+ */
+ protected Container getCompositeComponentForKey(String key) {
+ if (key == null) {
+ key = "";
+ }
+
+ JPanel field = null;
+ Iterator enumeration = fields.iterator();
+ while (enumeration.hasNext()) { // finds first value in list with specified key
+ field = (JPanel) enumeration.next();
+ if (key.equals(field.getName())) {
+ return field;
+ }
+ }
+
+ // else not found
+ return null;
}
-
-/**
-* Replaces the component associated with the key. Any value in the existing
-* component will be copied to the new component.
-* @param key A string representing the key to be associated with the component.
-* Nulls are converted to an empty string.
-* @param c A component to be placed next to the label corresponding to the key.
-* Nulls are converted to a JTextField.
-*/
- public void setComponentForKey( String key, Component c, int index )
- {
- if ( c == null )
- {
- c = new JTextField( 15 );
- }
- if ( key == null )
- {
- key = "";
- }
-
- Container container = this.getCompositeComponentForKey( key );
- Component field = container.getComponent( index );
- Object value = this.getValueForKey( key, index );
- if ( field != null )
- {
- container.remove( index );
- container.add( c, index );
- c.setEnabled( this.isEditable );
- introspectComponent( c, key );
- setValueForComponent( c, value );
- }
- }
-/**
-* Replaces the first component in the specified row. Any value in the existing
-* component will be copied to the new component.
-* @param row A valid index.
-* @param c A component to be placed next to the label corresponding to the key.
-*/
- public void setComponentForIndex( int row, Component c )
- {
- setComponentForIndex( row, 0, c );
+ /**
+ * Provided for backwards compatibility: calls getLabelComponentForKey.
+ *
+ * @param key A string representing the key associated with the compoent. Nulls
+ * are converted to an empty string.
+ * @return Component label object associated with the key, or null if the key
+ * does not exist or if the label component is not an instance of
+ * JLabel.
+ */
+ public JLabel getLabelForKey(String key) {
+ Component result = getLabelComponentForKey(key);
+ if (result instanceof JLabel)
+ return (JLabel) result;
+ return null;
}
-
-/**
-* Replaces the component associated with the key. Any value in the existing
-* component will be copied to the new component.
-* @param row A valid index.
-* @param c A component to be placed next to the label corresponding to the key.
-*/
- public void setComponentForIndex( int row, int col, Component c )
- {
- setComponentForKey( getLabels()[row], c, col );
- }
-/**
-* Sets the string that appears before each label's text on the panel.
-* @param aString A String to be used as the label prefix.
-*/
- public void setLabelPrefix( String aString )
- {
- prefix = aString;
- setLabels( getLabels() ); // force refresh
- }
+ /**
+ * Get the label component associated with the key.
+ *
+ * @param key A string representing the key associated with the compoent. Nulls
+ * are converted to an empty string.
+ * @return Component label object associated with the key, or null if the key
+ * does not exist.
+ */
+ public Component getLabelComponentForKey(String key) {
+ if (key == null) {
+ key = "";
+ }
-/**
-* Gets the string that appears before each label's text on the panel.
-* Defaults to "", an empty string.
-* @return A String that is currently used as the label prefix.
-*/
- public String getLabelPrefix()
- {
- return prefix;
- }
+ Component label = null;
+ Iterator enumeration = labels.iterator();
+ while (enumeration.hasNext()) { // finds first value in list with specified key
+ label = (Component) enumeration.next();
+ if (key.equals(label.getName())) {
+ return label;
+ }
+ }
-/**
-* Sets the string that appears after each label's text on the panel.
-* Defaults to ": ", a colon followed by a space.
-* @param aString A String to be used as the label postfix.
-*/
- public void setLabelPostfix( String aString )
- {
- postfix = aString;
- setLabels( getLabels() ); // force refresh
- }
+ // else not found
+ return null;
+ }
-/**
-* Gets the string that appears after each label's text on the panel.
-* @return A String that is currently used as the label postfix.
-*/
- public String getLabelPostfix()
- {
- return postfix;
- }
+ /**
+ * Replaces the first component associated with the key. Any value in the
+ * existing component will be copied to the new component.
+ *
+ * @param key A string representing the key to be associated with the component.
+ * Nulls are converted to an empty string.
+ * @param c A component to be placed next to the label corresponding to the
+ * key. Nulls are converted to a JTextField.
+ */
+ public void setComponentForKey(String key, Component c) {
+ setComponentForKey(key, c, 0);
+ }
-/**
-* Adds an action listener to the list that will be
-* notified by events occurring in the panel.
-* @param l An action listener to be notified.
-*/
- public void addActionListener(ActionListener l)
- {
- actionListener = AWTEventMulticaster.add(actionListener, l);
- }
-/**
-* Removes an action listener from the list that will be
-* notified by events occurring in the panel.
-* @param l An action listener to be removed.
-*/
- public void removeActionListener(ActionListener l)
- {
- actionListener = AWTEventMulticaster.remove(actionListener, l);
- }
-/**
-* Notifies all registered action listeners of a pending Action Event.
-* @param e An action event to be broadcast.
-*/
- protected void broadcastEvent(ActionEvent e)
- {
- if (actionListener != null)
- {
- actionListener.actionPerformed(e);
- }
- }
+ /**
+ * Replaces the component associated with the key. Any value in the existing
+ * component will be copied to the new component.
+ *
+ * @param key A string representing the key to be associated with the component.
+ * Nulls are converted to an empty string.
+ * @param c A component to be placed next to the label corresponding to the
+ * key. Nulls are converted to a JTextField.
+ */
+ public void setComponentForKey(String key, Component c, int index) {
+ if (c == null) {
+ c = new JTextField(15);
+ }
+ if (key == null) {
+ key = "";
+ }
- // interface ActionListener
+ Container container = this.getCompositeComponentForKey(key);
+ Component field = container.getComponent(index);
+ Object value = this.getValueForKey(key, index);
+ if (field != null) {
+ container.remove(index);
+ container.add(c, index);
+ c.setEnabled(this.isEditable);
+ introspectComponent(c, key);
+ setValueForComponent(c, value);
+ }
+ }
-/**
-* Called by buttons on panel and by other components that
-* might be set to broadcast events to this listener.
-* Simply forwards the action event unchanged.
-* @param e An action event to be received.
-*/
- public void actionPerformed(ActionEvent e)
- {
+ /**
+ * Replaces the first component in the specified row. Any value in the existing
+ * component will be copied to the new component.
+ *
+ * @param row A valid index.
+ * @param c A component to be placed next to the label corresponding to the
+ * key.
+ */
+ public void setComponentForIndex(int row, Component c) {
+ setComponentForIndex(row, 0, c);
+ }
+
+ /**
+ * Replaces the component associated with the key. Any value in the existing
+ * component will be copied to the new component.
+ *
+ * @param row A valid index.
+ * @param c A component to be placed next to the label corresponding to the
+ * key.
+ */
+ public void setComponentForIndex(int row, int col, Component c) {
+ setComponentForKey(getLabels()[row], c, col);
+ }
+
+ /**
+ * Sets the string that appears before each label's text on the panel.
+ *
+ * @param aString A String to be used as the label prefix.
+ */
+ public void setLabelPrefix(String aString) {
+ prefix = aString;
+ setLabels(getLabels()); // force refresh
+ }
+
+ /**
+ * Gets the string that appears before each label's text on the panel. Defaults
+ * to "", an empty string.
+ *
+ * @return A String that is currently used as the label prefix.
+ */
+ public String getLabelPrefix() {
+ return prefix;
+ }
+
+ /**
+ * Sets the string that appears after each label's text on the panel. Defaults
+ * to ": ", a colon followed by a space.
+ *
+ * @param aString A String to be used as the label postfix.
+ */
+ public void setLabelPostfix(String aString) {
+ postfix = aString;
+ setLabels(getLabels()); // force refresh
+ }
+
+ /**
+ * Gets the string that appears after each label's text on the panel.
+ *
+ * @return A String that is currently used as the label postfix.
+ */
+ public String getLabelPostfix() {
+ return postfix;
+ }
+
+ /**
+ * Adds an action listener to the list that will be notified by events occurring
+ * in the panel.
+ *
+ * @param l An action listener to be notified.
+ */
+ public void addActionListener(ActionListener l) {
+ actionListener = AWTEventMulticaster.add(actionListener, l);
+ }
+
+ /**
+ * Removes an action listener from the list that will be notified by events
+ * occurring in the panel.
+ *
+ * @param l An action listener to be removed.
+ */
+ public void removeActionListener(ActionListener l) {
+ actionListener = AWTEventMulticaster.remove(actionListener, l);
+ }
+
+ /**
+ * Notifies all registered action listeners of a pending Action Event.
+ *
+ * @param e An action event to be broadcast.
+ */
+ protected void broadcastEvent(ActionEvent e) {
+ if (actionListener != null) {
+ actionListener.actionPerformed(e);
+ }
+ }
+
+ // interface ActionListener
+
+ /**
+ * Called by buttons on panel and by other components that might be set to
+ * broadcast events to this listener. Simply forwards the action event
+ * unchanged.
+ *
+ * @param e An action event to be received.
+ */
+ public void actionPerformed(ActionEvent e) {
// if ( e.getSource() instanceof AbstractButton )
// {
- broadcastEvent(e);
+ broadcastEvent(e);
// }
- }
-
- /**
- * GridBagLayout allocates weightx only after considering
- * the preferred width of the components in a column.
- * We'd prefer that preferred width wasn't considered,
- * so that the layout worked more like a html-table.
- * GridBagLayout is poorly factored for subclassing,
- * so this code is going to get a little bit ugly.
- * Really, what good is a protected method that returns
- * a private class? Would have liked to just override
- * getLayoutInfo and be done with it.
- */
- private class BetterGridBagLayout extends GridBagLayout
- {
- public Dimension preferredLayoutSize(Container parent)
- {
- preprocess();
- return super.preferredLayoutSize( parent );
- }
-
- public Dimension minimumLayoutSize(Container parent)
- {
- preprocess();
- return super.minimumLayoutSize( parent );
- }
-
-
- public void layoutContainer(Container parent)
- {
- preprocess();
- super.layoutContainer( parent );
- }
-
- protected void preprocess()
- {
- if ( fieldSpacers == null ) return;
- Iterator i;
-
- // find the field with the widest preferred size
- Component c;
- int maxWidth = 0;
- i = fields.iterator();
- while ( i.hasNext() )
- {
- c = (Component) i.next();
- maxWidth = Math.max( maxWidth,
- Math.max( c.getPreferredSize().width, c.getMinimumSize().width ) );
- }
-
- // set each column's spacers to that preferred size
- Dimension min = new Dimension( 0, 0 );
- Dimension pref = new Dimension( maxWidth, 0 );
- i = fieldSpacers.iterator();
- while ( i.hasNext() )
- {
- ((Box.Filler)i.next()).changeShape( min, pref, pref );
- }
- }
- }
-}
+ }
+
+ /**
+ * GridBagLayout allocates weightx only after considering the preferred width of
+ * the components in a column. We'd prefer that preferred width wasn't
+ * considered, so that the layout worked more like a html-table. GridBagLayout
+ * is poorly factored for subclassing, so this code is going to get a little bit
+ * ugly. Really, what good is a protected method that returns a private class?
+ * Would have liked to just override getLayoutInfo and be done with it.
+ */
+ private class BetterGridBagLayout extends GridBagLayout {
+ public Dimension preferredLayoutSize(Container parent) {
+ preprocess();
+ return super.preferredLayoutSize(parent);
+ }
+
+ public Dimension minimumLayoutSize(Container parent) {
+ preprocess();
+ return super.minimumLayoutSize(parent);
+ }
+
+ public void layoutContainer(Container parent) {
+ preprocess();
+ super.layoutContainer(parent);
+ }
+
+ protected void preprocess() {
+ if (fieldSpacers == null)
+ return;
+ Iterator i;
+
+ // find the field with the widest preferred size
+ Component c;
+ int maxWidth = 0;
+ i = fields.iterator();
+ while (i.hasNext()) {
+ c = (Component) i.next();
+ maxWidth = Math.max(maxWidth, Math.max(c.getPreferredSize().width, c.getMinimumSize().width));
+ }
+ // set each column's spacers to that preferred size
+ Dimension min = new Dimension(0, 0);
+ Dimension pref = new Dimension(maxWidth, 0);
+ i = fieldSpacers.iterator();
+ while (i.hasNext()) {
+ ((Box.Filler) i.next()).changeShape(min, pref, pref);
+ }
+ }
+ }
+}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyDelayTimer.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyDelayTimer.java
index b73c74d..31bdb70 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyDelayTimer.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyDelayTimer.java
@@ -28,161 +28,150 @@ import java.awt.event.KeyListener;
import javax.swing.Timer;
/**
-* KeyDelayTimer is a utility that listens for KeyEvents from one
-* or more components. After receiving a KeyEvents the timer will
-* broadcast an action event if a specified time interval passes without
-* a subsequent KeyEvent.<BR><BR>
-*
-* This utility is useful for implementing any kind of auto-complete
-* feature in a user interface.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-* $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
-*/
-public class KeyDelayTimer implements ActionListener, KeyListener
-{
- // delay timer for keypress-sensitve events
- protected Timer keyTimer = null;
- protected Component lastFieldTouched = null;
- protected long timeLastFieldTouched = 0;
- protected int interval = 400; // adjust as needed
-
- // for action multicasting
- protected ActionListener actionListener = null;
-
-/**
-* Default constructor.
-*/
- public KeyDelayTimer()
- {
- keyTimer = new Timer( interval, this );
- }
-
-/**
-* Convenience constructor.
-* @param listener An action listener to be notified of delay events.
-*/
- public KeyDelayTimer( ActionListener listener )
- {
- this();
- addActionListener( listener );
- }
-
-/**
-* Returns the last component that generated a KeyEvent.
-* @return The component that sent the most recent KeyEvent.
-*/
- public Component getComponent()
- {
- return lastFieldTouched;
- }
-
-/**
-* Returns the number of milliseconds before an ActionEvent is generated.
-* The default is 400.
-* @return The current delay interval in milliseconds.
-*/
- public int getInterval()
- {
- return interval;
- }
-
-/**
-* Sets the number of milliseconds before an ActionEvent will be generated
-* after a KeyEvent is received.
-* @param millis The new delay interval in milliseconds.
-*/
- public void setInterval( int millis )
- {
- interval = millis;
- keyTimer.setDelay( interval / 2 );
- }
-
- // interface KeyListener
-
- public void keyTyped(KeyEvent e)
- {
- }
- public void keyPressed(KeyEvent e)
- {
- }
-
-/**
-* Receives key events from one or more components.
-* Records the component and the time this event was received,
-* then starts the timer.
-* @param e The key event in question.
-*/
- public void keyReleased(KeyEvent e)
- { // handles keystrokes in the textfields (except ENTER and ESCAPE)
- if ( ( Character.isLetterOrDigit( e.getKeyChar() ) )
- || ( e.getKeyCode() == KeyEvent.VK_SPACE )
- || ( e.getKeyCode() == KeyEvent.VK_DELETE )
- || ( e.getKeyCode() == KeyEvent.VK_BACK_SPACE ) )
- {
- this.lastFieldTouched = e.getComponent();
- this.timeLastFieldTouched = System.currentTimeMillis();
- this.keyTimer.start();
- return;
- }
- }
-
- // interface ActionListener
-
-/**
-* Receives ActionEvents from the internal timer.
-* If the interval has passed without another KeyEvent,
-* an ActionEvent is broadcast, with the name of this class
-* as the ActionCommand, and the internal timer is stopped.
-* @param e The action event in question.
-*/
- public void actionPerformed(ActionEvent e)
- {
- if ( e.getSource() == keyTimer )
- {
- if ( System.currentTimeMillis() - this.timeLastFieldTouched > interval )
- {
- this.keyTimer.stop();
- broadcastEvent( new ActionEvent( this, ActionEvent.ACTION_PERFORMED, this.getClass().getName() ) );
- }
- return;
- }
- }
-
- // Action Multicast methods
-
-/**
-* Adds an action listener to the list that will be
-* notified by button events and changes in button state.
-* @param l An action listener to be notified.
-*/
- public void addActionListener(ActionListener l)
- {
- actionListener = AWTEventMulticaster.add(actionListener, l);
- }
-/**
-* Removes an action listener from the list that will be
-* notified by button events and changes in button state.
-* @param l An action listener to be removed.
-*/
- public void removeActionListener(ActionListener l)
- {
- actionListener = AWTEventMulticaster.remove(actionListener, l);
- }
-/**
-* Notifies all registered action listeners of a pending Action Event.
-* @param e An action event to be broadcast.
-*/
- protected void broadcastEvent(ActionEvent e)
- {
- if (actionListener != null)
- {
- actionListener.actionPerformed(e);
- }
- }
+ * KeyDelayTimer is a utility that listens for KeyEvents from one or more
+ * components. After receiving a KeyEvents the timer will broadcast an action
+ * event if a specified time interval passes without a subsequent KeyEvent.<BR>
+ * <BR>
+ *
+ * This utility is useful for implementing any kind of auto-complete feature in
+ * a user interface.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006)
+ * $
+ */
+public class KeyDelayTimer implements ActionListener, KeyListener {
+ // delay timer for keypress-sensitve events
+ protected Timer keyTimer = null;
+ protected Component lastFieldTouched = null;
+ protected long timeLastFieldTouched = 0;
+ protected int interval = 400; // adjust as needed
+
+ // for action multicasting
+ protected ActionListener actionListener = null;
+
+ /**
+ * Default constructor.
+ */
+ public KeyDelayTimer() {
+ keyTimer = new Timer(interval, this);
+ }
+
+ /**
+ * Convenience constructor.
+ *
+ * @param listener An action listener to be notified of delay events.
+ */
+ public KeyDelayTimer(ActionListener listener) {
+ this();
+ addActionListener(listener);
+ }
+
+ /**
+ * Returns the last component that generated a KeyEvent.
+ *
+ * @return The component that sent the most recent KeyEvent.
+ */
+ public Component getComponent() {
+ return lastFieldTouched;
+ }
+
+ /**
+ * Returns the number of milliseconds before an ActionEvent is generated. The
+ * default is 400.
+ *
+ * @return The current delay interval in milliseconds.
+ */
+ public int getInterval() {
+ return interval;
+ }
+
+ /**
+ * Sets the number of milliseconds before an ActionEvent will be generated after
+ * a KeyEvent is received.
+ *
+ * @param millis The new delay interval in milliseconds.
+ */
+ public void setInterval(int millis) {
+ interval = millis;
+ keyTimer.setDelay(interval / 2);
+ }
+
+ // interface KeyListener
+
+ public void keyTyped(KeyEvent e) {
+ }
+
+ public void keyPressed(KeyEvent e) {
+ }
+
+ /**
+ * Receives key events from one or more components. Records the component and
+ * the time this event was received, then starts the timer.
+ *
+ * @param e The key event in question.
+ */
+ public void keyReleased(KeyEvent e) { // handles keystrokes in the textfields (except ENTER and ESCAPE)
+ if ((Character.isLetterOrDigit(e.getKeyChar())) || (e.getKeyCode() == KeyEvent.VK_SPACE)
+ || (e.getKeyCode() == KeyEvent.VK_DELETE) || (e.getKeyCode() == KeyEvent.VK_BACK_SPACE)) {
+ this.lastFieldTouched = e.getComponent();
+ this.timeLastFieldTouched = System.currentTimeMillis();
+ this.keyTimer.start();
+ return;
+ }
+ }
+
+ // interface ActionListener
+
+ /**
+ * Receives ActionEvents from the internal timer. If the interval has passed
+ * without another KeyEvent, an ActionEvent is broadcast, with the name of this
+ * class as the ActionCommand, and the internal timer is stopped.
+ *
+ * @param e The action event in question.
+ */
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == keyTimer) {
+ if (System.currentTimeMillis() - this.timeLastFieldTouched > interval) {
+ this.keyTimer.stop();
+ broadcastEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, this.getClass().getName()));
+ }
+ return;
+ }
+ }
+
+ // Action Multicast methods
+
+ /**
+ * Adds an action listener to the list that will be notified by button events
+ * and changes in button state.
+ *
+ * @param l An action listener to be notified.
+ */
+ public void addActionListener(ActionListener l) {
+ actionListener = AWTEventMulticaster.add(actionListener, l);
+ }
+
+ /**
+ * Removes an action listener from the list that will be notified by button
+ * events and changes in button state.
+ *
+ * @param l An action listener to be removed.
+ */
+ public void removeActionListener(ActionListener l) {
+ actionListener = AWTEventMulticaster.remove(actionListener, l);
+ }
+
+ /**
+ * Notifies all registered action listeners of a pending Action Event.
+ *
+ * @param e An action event to be broadcast.
+ */
+ protected void broadcastEvent(ActionEvent e) {
+ if (actionListener != null) {
+ actionListener.actionPerformed(e);
+ }
+ }
}
-
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyableCellEditor.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyableCellEditor.java
index 95b8a19..f64e607 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyableCellEditor.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/KeyableCellEditor.java
@@ -40,311 +40,265 @@ import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
/**
-* A table cell editor customized for keyboard navigation, much like
-* working with a spreadsheet. The default cell editor unfortunately
-* does none of these things:
-* <ul>
-* <li> Selects text on start of editing.
-* <li> Up and down keys move edit cell up and down.
-* <li> Right and left keys move cell when selection caret is at end of text.
-* <li> Escape cancels editing.
-* <li> Enter commits edit.
-* <li> Edits are properly committed on lost focus.
-* <li> Tab and shift-tab work as expected.
-* <li> Cell selection moves with the edit cell.
-* </ul>
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-* $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
-*/
-public class KeyableCellEditor implements TableCellEditor, FocusListener,
- KeyListener, Serializable
-{
- List listeners;
- JTextField textField;
- Object lastValue;
- Format currentFormat;
-
- JTable table;
-
-/**
-* Default constructor - a standard JTextField will be used for editing.
-*/
- public KeyableCellEditor()
- {
- this( (JTextField) null );
- }
-
-/**
-* Constructor specifying a type of JTextField to be used for editing.
-* The JTextField will have its border replaced with a black line border.
-* @param aTextField A JTextField or subclass for editing values.
-*/
- public KeyableCellEditor( JTextField aTextField )
- {
- listeners = new Vector();
- lastValue = null;
-
- // default to stock JTextField
- textField = aTextField;
- if ( textField == null )
- {
- textField = new JTextField();
- }
-
- textField.setBorder(new LineBorder(Color.black));
-
- // handle arrow keys while caret is showing
- textField.addKeyListener( this );
-
- // handle lost focus
- textField.addFocusListener( this );
- }
-
- public Component getTableCellEditorComponent(JTable table,
- Object value,
- boolean isSelected,
- int row,
- int column)
- {
- this.table = table;
- table.removeKeyListener( this ); // if any
- table.addKeyListener( this );
- return getEditorComponent( value );
- }
-
- protected Component getEditorComponent( Object value )
- {
- if ( value != null )
- {
- textField.setText( value.toString() );
- }
- else
- {
- textField.setText( "" );
- }
-
- if ( value instanceof Number )
- {
- textField.setHorizontalAlignment(JTextField.RIGHT);
- }
- else
- {
- textField.setHorizontalAlignment(JTextField.LEFT);
- }
-
- // remember original value
- lastValue = value;
-
- // select all text and get focus
- textField.selectAll();
- textField.requestFocus();
-
- return textField;
- }
-
- public Object getCellEditorValue()
- {
- return lastValue;
- }
-
- public boolean isCellEditable(EventObject anEvent)
- {
- // key events should replace the selection
- // NOTE: For whatever reason, key events trigger result in a null parameter
- if ( anEvent == null )
- {
- textField.setText("");
- textField.requestFocus();
- return true;
- }
-
- return true;
- }
-
- public boolean shouldSelectCell(EventObject anEvent)
- { // System.out.println( "KeyableCellEditor.shouldSelectCell: " + anEvent );
-
- // key events should replace the selection
- // NOTE: For whatever reason, key events are not generated
- if ( anEvent instanceof KeyEvent )
- {
- textField.setText("");
- textField.requestFocus();
- return true;
- }
-
- // otherwise, select all text and continue
- textField.selectAll();
- textField.requestFocus();
-
- return true;
- }
-
- public boolean stopCellEditing()
- {
- lastValue = textField.getText();
- fireEditingStopped();
- table.removeKeyListener( this ); // if any
- return true;
- }
-
- public void cancelCellEditing()
- {
- fireEditingCanceled();
- table.removeKeyListener( this ); // if any
- }
-
- public void addCellEditorListener(CellEditorListener l)
- {
- listeners.add( l );
- }
-
- public void removeCellEditorListener(CellEditorListener l)
- {
- listeners.remove( l );
- }
-
- protected void fireEditingCanceled()
- {
- ChangeEvent event = new ChangeEvent( this );
- Iterator it = new ArrayList( listeners ).iterator(); // copy to prevent modification exception
- while ( it.hasNext() )
- {
- ((CellEditorListener)it.next()).editingCanceled( event );
- }
- }
-
- protected void fireEditingStopped()
- {
- ChangeEvent event = new ChangeEvent( this );
- Iterator it = new ArrayList( listeners ).iterator(); // copy to prevent modification exception
- while ( it.hasNext() )
- {
- ((CellEditorListener)it.next()).editingStopped( event );
- }
- }
-
- protected void onEnterKey()
- {
- stopCellEditing();
- }
-
- protected void onEscapeKey()
- {
- cancelCellEditing();
- }
-
- protected void moveEditCell( int dRow, int dCol )
- {
- if ( table == null ) return;
- int row = table.getSelectedRow() + dRow;
- int col = table.getSelectedColumn() + dCol;
-
- row = Math.max( 0, row );
- row = Math.min( row, table.getRowCount() - 1 );
- col = Math.max( 0, col );
- col = Math.min( col, table.getColumnCount() - 1 );
-
- stopCellEditing();
- table.setRowSelectionInterval( row, row );
- table.setColumnSelectionInterval( col, col );
- table.editCellAt( row, col );
- textField.selectAll();
- textField.requestFocus();
- }
-
- // interface KeyListener
-
- public void keyTyped(KeyEvent e)
- { // System.out.println( "KeyableCellEditor.keyTyped: " + KeyEvent.getKeyText( e.getKeyCode() ) );
- }
-
- public void keyPressed(KeyEvent e)
- { // System.out.println( "KeyableCellEditor.keyPressed: " + KeyEvent.getKeyText( e.getKeyCode() ) );
-
- // catch LEFT and RIGHT here before JTextField consumes them
-
- int keyCode = e.getKeyCode();
- if ( keyCode == KeyEvent.VK_LEFT )
- {
- if ( textField.getSelectionStart() == 0 )
- {
- moveEditCell( 0, -1 );
- e.consume();
- return;
- }
- }
- if ( keyCode == KeyEvent.VK_RIGHT )
- {
- if ( textField.getSelectionEnd() == textField.getText().length() )
- {
- moveEditCell( 0, 1 );
- e.consume();
- return;
- }
- }
- if ( keyCode == KeyEvent.VK_UP )
- {
- moveEditCell( -1, 0 );
- e.consume();
- return;
- }
- if ( keyCode == KeyEvent.VK_DOWN )
- {
- moveEditCell( 1, 0 );
- e.consume();
- return;
- }
- }
-
- public void keyReleased(KeyEvent e)
- { // System.out.println( "KeyableCellEditor.keyReleased: " + KeyEvent.getKeyText( e.getKeyCode() ) );
-
- // catch ENTER here to allow JTextField to process it as well
-
- int keyCode = e.getKeyCode();
- if ( keyCode == KeyEvent.VK_ENTER )
- {
- onEnterKey();
- return;
- }
- if ( keyCode == KeyEvent.VK_ESCAPE )
- {
- onEscapeKey();
- return;
- }
-
- // tabs are apparently only received on key release
- if ( keyCode == KeyEvent.VK_TAB )
- {
- if ( e.isShiftDown() )
- {
- moveEditCell( 0, -1 );
- }
- else
- {
- moveEditCell( 0, 1 );
- }
- e.consume();
- return;
- }
-
- }
-
- // interface FocusListener
-
- public void focusGained(FocusEvent e)
- { // System.out.println( "focusGained: " );
- }
-
- public void focusLost(FocusEvent e)
- { // System.out.println( "focusLost: " );
- stopCellEditing();
- }
+ * A table cell editor customized for keyboard navigation, much like working
+ * with a spreadsheet. The default cell editor unfortunately does none of these
+ * things:
+ * <ul>
+ * <li>Selects text on start of editing.
+ * <li>Up and down keys move edit cell up and down.
+ * <li>Right and left keys move cell when selection caret is at end of text.
+ * <li>Escape cancels editing.
+ * <li>Enter commits edit.
+ * <li>Edits are properly committed on lost focus.
+ * <li>Tab and shift-tab work as expected.
+ * <li>Cell selection moves with the edit cell.
+ * </ul>
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006)
+ * $
+ */
+public class KeyableCellEditor implements TableCellEditor, FocusListener, KeyListener, Serializable {
+ List listeners;
+ JTextField textField;
+ Object lastValue;
+ Format currentFormat;
+
+ JTable table;
+
+ /**
+ * Default constructor - a standard JTextField will be used for editing.
+ */
+ public KeyableCellEditor() {
+ this((JTextField) null);
+ }
+
+ /**
+ * Constructor specifying a type of JTextField to be used for editing. The
+ * JTextField will have its border replaced with a black line border.
+ *
+ * @param aTextField A JTextField or subclass for editing values.
+ */
+ public KeyableCellEditor(JTextField aTextField) {
+ listeners = new Vector();
+ lastValue = null;
+
+ // default to stock JTextField
+ textField = aTextField;
+ if (textField == null) {
+ textField = new JTextField();
+ }
+
+ textField.setBorder(new LineBorder(Color.black));
+
+ // handle arrow keys while caret is showing
+ textField.addKeyListener(this);
+
+ // handle lost focus
+ textField.addFocusListener(this);
+ }
+
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+ this.table = table;
+ table.removeKeyListener(this); // if any
+ table.addKeyListener(this);
+ return getEditorComponent(value);
+ }
+
+ protected Component getEditorComponent(Object value) {
+ if (value != null) {
+ textField.setText(value.toString());
+ } else {
+ textField.setText("");
+ }
+
+ if (value instanceof Number) {
+ textField.setHorizontalAlignment(JTextField.RIGHT);
+ } else {
+ textField.setHorizontalAlignment(JTextField.LEFT);
+ }
+
+ // remember original value
+ lastValue = value;
+
+ // select all text and get focus
+ textField.selectAll();
+ textField.requestFocus();
+
+ return textField;
+ }
+
+ public Object getCellEditorValue() {
+ return lastValue;
+ }
+
+ public boolean isCellEditable(EventObject anEvent) {
+ // key events should replace the selection
+ // NOTE: For whatever reason, key events trigger result in a null parameter
+ if (anEvent == null) {
+ textField.setText("");
+ textField.requestFocus();
+ return true;
+ }
+
+ return true;
+ }
+
+ public boolean shouldSelectCell(EventObject anEvent) { // System.out.println( "KeyableCellEditor.shouldSelectCell: "
+ // + anEvent );
+
+ // key events should replace the selection
+ // NOTE: For whatever reason, key events are not generated
+ if (anEvent instanceof KeyEvent) {
+ textField.setText("");
+ textField.requestFocus();
+ return true;
+ }
+
+ // otherwise, select all text and continue
+ textField.selectAll();
+ textField.requestFocus();
+
+ return true;
+ }
+
+ public boolean stopCellEditing() {
+ lastValue = textField.getText();
+ fireEditingStopped();
+ table.removeKeyListener(this); // if any
+ return true;
+ }
+
+ public void cancelCellEditing() {
+ fireEditingCanceled();
+ table.removeKeyListener(this); // if any
+ }
+
+ public void addCellEditorListener(CellEditorListener l) {
+ listeners.add(l);
+ }
+
+ public void removeCellEditorListener(CellEditorListener l) {
+ listeners.remove(l);
+ }
+
+ protected void fireEditingCanceled() {
+ ChangeEvent event = new ChangeEvent(this);
+ Iterator it = new ArrayList(listeners).iterator(); // copy to prevent modification exception
+ while (it.hasNext()) {
+ ((CellEditorListener) it.next()).editingCanceled(event);
+ }
+ }
+
+ protected void fireEditingStopped() {
+ ChangeEvent event = new ChangeEvent(this);
+ Iterator it = new ArrayList(listeners).iterator(); // copy to prevent modification exception
+ while (it.hasNext()) {
+ ((CellEditorListener) it.next()).editingStopped(event);
+ }
+ }
+
+ protected void onEnterKey() {
+ stopCellEditing();
+ }
+
+ protected void onEscapeKey() {
+ cancelCellEditing();
+ }
+
+ protected void moveEditCell(int dRow, int dCol) {
+ if (table == null)
+ return;
+ int row = table.getSelectedRow() + dRow;
+ int col = table.getSelectedColumn() + dCol;
+
+ row = Math.max(0, row);
+ row = Math.min(row, table.getRowCount() - 1);
+ col = Math.max(0, col);
+ col = Math.min(col, table.getColumnCount() - 1);
+
+ stopCellEditing();
+ table.setRowSelectionInterval(row, row);
+ table.setColumnSelectionInterval(col, col);
+ table.editCellAt(row, col);
+ textField.selectAll();
+ textField.requestFocus();
+ }
+
+ // interface KeyListener
+
+ public void keyTyped(KeyEvent e) { // System.out.println( "KeyableCellEditor.keyTyped: " + KeyEvent.getKeyText(
+ // e.getKeyCode() ) );
+ }
+
+ public void keyPressed(KeyEvent e) { // System.out.println( "KeyableCellEditor.keyPressed: " + KeyEvent.getKeyText(
+ // e.getKeyCode() ) );
+
+ // catch LEFT and RIGHT here before JTextField consumes them
+
+ int keyCode = e.getKeyCode();
+ if (keyCode == KeyEvent.VK_LEFT) {
+ if (textField.getSelectionStart() == 0) {
+ moveEditCell(0, -1);
+ e.consume();
+ return;
+ }
+ }
+ if (keyCode == KeyEvent.VK_RIGHT) {
+ if (textField.getSelectionEnd() == textField.getText().length()) {
+ moveEditCell(0, 1);
+ e.consume();
+ return;
+ }
+ }
+ if (keyCode == KeyEvent.VK_UP) {
+ moveEditCell(-1, 0);
+ e.consume();
+ return;
+ }
+ if (keyCode == KeyEvent.VK_DOWN) {
+ moveEditCell(1, 0);
+ e.consume();
+ return;
+ }
+ }
+
+ public void keyReleased(KeyEvent e) { // System.out.println( "KeyableCellEditor.keyReleased: " +
+ // KeyEvent.getKeyText( e.getKeyCode() ) );
+
+ // catch ENTER here to allow JTextField to process it as well
+
+ int keyCode = e.getKeyCode();
+ if (keyCode == KeyEvent.VK_ENTER) {
+ onEnterKey();
+ return;
+ }
+ if (keyCode == KeyEvent.VK_ESCAPE) {
+ onEscapeKey();
+ return;
+ }
+
+ // tabs are apparently only received on key release
+ if (keyCode == KeyEvent.VK_TAB) {
+ if (e.isShiftDown()) {
+ moveEditCell(0, -1);
+ } else {
+ moveEditCell(0, 1);
+ }
+ e.consume();
+ return;
+ }
+
+ }
+
+ // interface FocusListener
+
+ public void focusGained(FocusEvent e) { // System.out.println( "focusGained: " );
+ }
+
+ public void focusLost(FocusEvent e) { // System.out.println( "focusLost: " );
+ stopCellEditing();
+ }
}
-
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/LineWrappingRenderer.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/LineWrappingRenderer.java
index 4a7f07e..326d825 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/LineWrappingRenderer.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/LineWrappingRenderer.java
@@ -31,124 +31,111 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
-* A list cell renderer that wraps its text to subsequent lines
-* depending on the length of text string and the width of the
-* parent list.
-*
-* This renderer depends on listening to the parent list's viewport
-* and fixing the list's width to match the viewport's size.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @date $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
-* @revision $Revision: 904 $
-*/
-public class LineWrappingRenderer extends MultiLineLabel
- implements ListCellRenderer, ChangeListener
-{
- protected static Border noFocusBorder;
-
- protected JList list;
- protected JViewport viewport;
- protected int preferredWidth;
-
-/**
-* Required constructor. The renderer keeps a reference to
-* the list in which it is used and its viewport. This list
-* is the only list that may use this renderer. The renderer
-* will use the current size of the list to determine where
-* lines will initially break.
-* @param containerList The list that will be using this renderer.
-*/
- public LineWrappingRenderer( JList containerList )
- {
- super();
- setLineWrap(true);
- noFocusBorder = new EmptyBorder(1, 1, 1, 1);
-
- list = containerList;
- preferredWidth = 400;
- if ( list.getParent() instanceof JViewport )
- {
- viewport = (JViewport) list.getParent();
- viewport.addChangeListener( this );
- int newWidth = viewport.getExtentSize().width;
- if ( newWidth > 0 ) preferredWidth = newWidth;
- }
- else
- {
- // should function adequately in absence of a viewport
- // System.err.println( "LineWrappingRenderer.init: list.getParent = " + list.getParent() );
- }
- }
-
-/**
-* Returns the preferred size of the label, with width
-* constrained to the current width.
-* @return the size
-*/
- public Dimension getPreferredSize()
- {
- int width = getWidth();
- if ( width != preferredWidth )
- {
- // if component has not yet been placed within the list
- if ( width < list.getWidth() / 2 ) width = list.getWidth();
- preferredWidth = width;
- }
- return new Dimension( preferredWidth, super.getPreferredSize().height );
- }
-
-/**
-* Returns this component with the width set to the
-* width of the specified JList.
-* @return this component.
-*/
- public Component getListCellRendererComponent (
- JList list,
- Object value,
- int index,
- boolean isSelected,
- boolean cellHasFocus )
- { // System.out.println( "LineWrappingRenderer.getListCellRendererComponent:" );
-
- if ( list != this.list )
- {
- System.err.println( "LineWrappingRenderer.getListCellRendererComponent: " +
- "warning: the list using the renderer is not the list specified in the constructor." );
- }
-
- if (isSelected)
- {
- setBackground(this.list.getSelectionBackground());
- setForeground(this.list.getSelectionForeground());
- }
- else
- {
- setBackground(this.list.getBackground());
- setForeground(this.list.getForeground());
- }
-
- setText((value == null) ? "" : value.toString());
-
- setEnabled(this.list.isEnabled());
- setFont(this.list.getFont());
- setBorder( (cellHasFocus) ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder );
-
- return this;
- }
-
-/**
-* Overridden to respond to viewport changes.
-*/
- public void stateChanged(ChangeEvent e)
- {
- int newWidth = viewport.getExtentSize().width;
- if ( newWidth > 0 ) preferredWidth = newWidth;
-
- // set fixed width on list
- list.setFixedCellWidth( preferredWidth );
- setSize( preferredWidth, super.getSize().height );
- }
+ * A list cell renderer that wraps its text to subsequent lines depending on the
+ * length of text string and the width of the parent list.
+ *
+ * This renderer depends on listening to the parent list's viewport and fixing
+ * the list's width to match the viewport's size.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @date $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
+ * @revision $Revision: 904 $
+ */
+public class LineWrappingRenderer extends MultiLineLabel implements ListCellRenderer, ChangeListener {
+ protected static Border noFocusBorder;
+
+ protected JList list;
+ protected JViewport viewport;
+ protected int preferredWidth;
+
+ /**
+ * Required constructor. The renderer keeps a reference to the list in which it
+ * is used and its viewport. This list is the only list that may use this
+ * renderer. The renderer will use the current size of the list to determine
+ * where lines will initially break.
+ *
+ * @param containerList The list that will be using this renderer.
+ */
+ public LineWrappingRenderer(JList containerList) {
+ super();
+ setLineWrap(true);
+ noFocusBorder = new EmptyBorder(1, 1, 1, 1);
+
+ list = containerList;
+ preferredWidth = 400;
+ if (list.getParent() instanceof JViewport) {
+ viewport = (JViewport) list.getParent();
+ viewport.addChangeListener(this);
+ int newWidth = viewport.getExtentSize().width;
+ if (newWidth > 0)
+ preferredWidth = newWidth;
+ } else {
+ // should function adequately in absence of a viewport
+ // System.err.println( "LineWrappingRenderer.init: list.getParent = " +
+ // list.getParent() );
+ }
+ }
+
+ /**
+ * Returns the preferred size of the label, with width constrained to the
+ * current width.
+ *
+ * @return the size
+ */
+ public Dimension getPreferredSize() {
+ int width = getWidth();
+ if (width != preferredWidth) {
+ // if component has not yet been placed within the list
+ if (width < list.getWidth() / 2)
+ width = list.getWidth();
+ preferredWidth = width;
+ }
+ return new Dimension(preferredWidth, super.getPreferredSize().height);
+ }
+
+ /**
+ * Returns this component with the width set to the width of the specified
+ * JList.
+ *
+ * @return this component.
+ */
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+ boolean cellHasFocus) { // System.out.println( "LineWrappingRenderer.getListCellRendererComponent:" );
+
+ if (list != this.list) {
+ System.err.println("LineWrappingRenderer.getListCellRendererComponent: "
+ + "warning: the list using the renderer is not the list specified in the constructor.");
+ }
+
+ if (isSelected) {
+ setBackground(this.list.getSelectionBackground());
+ setForeground(this.list.getSelectionForeground());
+ } else {
+ setBackground(this.list.getBackground());
+ setForeground(this.list.getForeground());
+ }
+
+ setText((value == null) ? "" : value.toString());
+
+ setEnabled(this.list.isEnabled());
+ setFont(this.list.getFont());
+ setBorder((cellHasFocus) ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
+
+ return this;
+ }
+
+ /**
+ * Overridden to respond to viewport changes.
+ */
+ public void stateChanged(ChangeEvent e) {
+ int newWidth = viewport.getExtentSize().width;
+ if (newWidth > 0)
+ preferredWidth = newWidth;
+
+ // set fixed width on list
+ list.setFixedCellWidth(preferredWidth);
+ setSize(preferredWidth, super.getSize().height);
+ }
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/MultiLineLabel.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/MultiLineLabel.java
index b5f8a9b..ce362c9 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/MultiLineLabel.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/MultiLineLabel.java
@@ -23,113 +23,100 @@ import javax.swing.LookAndFeel;
import javax.swing.text.Highlighter;
/**
-* A custom JTextArea that looks and feels like a JLabel, but supports
-* line wrapping. This works a lot more like the IFC label component.
-* NOTE: doesn't support icons (yet).
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @date $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
-* @revision $Revision: 904 $
-*/
-public class MultiLineLabel extends JTextArea
-{
+ * A custom JTextArea that looks and feels like a JLabel, but supports line
+ * wrapping. This works a lot more like the IFC label component. NOTE: doesn't
+ * support icons (yet).
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @date $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
+ * @revision $Revision: 904 $
+ */
+public class MultiLineLabel extends JTextArea {
/**
- * Saves a reference to the original highlighter
- * to enable/disable text selection.
- */
+ * Saves a reference to the original highlighter to enable/disable text
+ * selection.
+ */
protected Highlighter originalHighlighter;
-
-/*
-* Creates a MultiLineLabel instance with an empty string for the title.
-*/
- public MultiLineLabel()
- {
- super();
- // turn on wrapping and disable editing and highlighting
+ /*
+ * Creates a MultiLineLabel instance with an empty string for the title.
+ */
+ public MultiLineLabel() {
+ super();
- setLineWrap(true);
- setWrapStyleWord(true);
- setEditable(false);
- setSelectable( false );
- }
+ // turn on wrapping and disable editing and highlighting
-/*
-* Creates a MultiLineLabel instance with the specified text.
-* @param text The specified text.
-*/
- public MultiLineLabel( String text )
- {
- super( text );
+ setLineWrap(true);
+ setWrapStyleWord(true);
+ setEditable(false);
+ setSelectable(false);
+ }
- // turn on wrapping and disable editing and highlighting
+ /*
+ * Creates a MultiLineLabel instance with the specified text.
+ *
+ * @param text The specified text.
+ */
+ public MultiLineLabel(String text) {
+ super(text);
- setLineWrap(true);
- setWrapStyleWord(true);
- setEditable(false);
- setSelectable( false );
- }
+ // turn on wrapping and disable editing and highlighting
-/*
-* Overridden to look like a label.
-* @param text The specified text.
-*/
- public void updateUI()
- {
- // got the implementation idea from usenet
+ setLineWrap(true);
+ setWrapStyleWord(true);
+ setEditable(false);
+ setSelectable(false);
+ }
- super.updateUI();
+ /*
+ * Overridden to look like a label.
+ *
+ * @param text The specified text.
+ */
+ public void updateUI() {
+ // got the implementation idea from usenet
- // turn on wrapping and disable editing and highlighting
+ super.updateUI();
- setLineWrap(true);
- setWrapStyleWord(true);
- setEditable(false);
- setSelectable( false );
+ // turn on wrapping and disable editing and highlighting
- // Set the text area's border, colors and font to
- // that of a label
+ setLineWrap(true);
+ setWrapStyleWord(true);
+ setEditable(false);
+ setSelectable(false);
- LookAndFeel.installBorder(this, "Label.border");
+ // Set the text area's border, colors and font to
+ // that of a label
- LookAndFeel.installColorsAndFont(this,
- "Label.background",
- "Label.foreground",
- "Label.font");
- }
+ LookAndFeel.installBorder(this, "Label.border");
-/**
-* Sets whether text is selectable.
-* Default is non-selectable text.
-*/
- public void setSelectable( boolean selectable )
- {
- if ( selectable )
- {
- setHighlighter( originalHighlighter );
- }
- else
- {
+ LookAndFeel.installColorsAndFont(this, "Label.background", "Label.foreground", "Label.font");
+ }
+
+ /**
+ * Sets whether text is selectable. Default is non-selectable text.
+ */
+ public void setSelectable(boolean selectable) {
+ if (selectable) {
+ setHighlighter(originalHighlighter);
+ } else {
originalHighlighter = getHighlighter();
- setHighlighter( null );
+ setHighlighter(null);
}
}
-
-/**
-* Gets whether text is selectable.
-* Default is non-selectable text.
-*/
- public boolean isSelectable()
- {
- return ( getHighlighter() != null );
+
+ /**
+ * Gets whether text is selectable. Default is non-selectable text.
+ */
+ public boolean isSelectable() {
+ return (getHighlighter() != null);
}
-/**
-* Overridden to return false.
-*/
- public boolean isFocusTraversable()
- {
+ /**
+ * Overridden to return false.
+ */
+ public boolean isFocusTraversable() {
return false;
- }
+ }
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/NumericTextField.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/NumericTextField.java
index b3d2d03..dee8f27 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/NumericTextField.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/NumericTextField.java
@@ -19,416 +19,346 @@ License along with this library; if not, see http://www.gnu.org
package net.wotonomy.ui.swing.components;
/**
-* NumericTextField is a "smart" text field that restricts the user's input. The
-* input is restructed to numeric only wich can be of two types: integer and real
-* numbers. A range can also be placed on the text field. The default type is
-* integer, with the being (Integer.MIN_VALUE, Integer.MAX_VALUE).
-*
-* @author rob@straylight.princeton.com
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
-public class NumericTextField extends SmartTextField
-{
-
-/*******************************
-* CONSTANTS
-*******************************/
-
-/**
-* Restrict the text input to integers (whole numbers) only.
-*/
- public final static int INTEGER = 0;
-
-/**
-* Restrict the text input to floating-point numbers only.
-*/
- public final static int FLOAT = 1;
-
- private Number maximumValue = null;
- private Number minimumValue = null;
-
- private boolean sign = false;
- private int newCaretPosition = 0;
- private int valueType = INTEGER;
-
-
-/*******************************
-* PUBLIC METHODS
-*******************************/
-
-/**
-* Default constructor.
-*/
- public NumericTextField()
- {
- this("", 0);
- }
-
-/**
-* Constructor.
-* @param text The initial string the text field is set to.
-*/
- public NumericTextField(String text)
- {
- this(text, 0);
- }
-
-/**
-* Constructor.
-* @param columns Width of the text field (in characters).
-*/
- public NumericTextField(int columns)
- {
- this("", columns);
- }
-
-/**
-* Constructor.
-* @param text The initial string the text field is set to.
-* @param columns Width of the text field (in characters).
-*/
- public NumericTextField(String text, int columns)
- {
- super(text, columns);
- }
-
-/**
-* Sets the upper limit of the range of numbers to accept.
-* @param newMaximumValue The maximum number accepted by the text field.
-*/
- public void setMaximumValue(double newMaximumValue)
- {
- if (newMaximumValue >= 0)
- {
- maximumValue = new Double( newMaximumValue );
- }
- else
- {
- maximumValue = null;
- }
- }
-
-/**
-* Returns the upper limit of the range of numbers to accept.
-* @return The maximum number accepted by this text field.
-*/
- public double getMaximumValue()
- {
- if ( valueType == INTEGER )
- {
- return (maximumValue == null) ? (double) Integer.MAX_VALUE : maximumValue.doubleValue();
- }
- else
- {
- return (maximumValue == null) ? Double.MAX_VALUE : maximumValue.doubleValue();
- }
- }
-
-/**
-* Sets the lower limit of the range of numbers to accept.
-* @param newMinimumValue The minimum number accepted by the text field.
-*/
- public void setMinimumValue(double newMinimumValue)
- {
- if (newMinimumValue <= 0)
- {
- minimumValue = new Double( newMinimumValue );
- }
- else
- {
- minimumValue = null;
- }
- }
-
-/**
-* Returns the lower limit of the range of numbers to accept.
-* @return The minimum number accepted by this text field.
-*/
- public double getMinimumValue()
- {
- if ( valueType == INTEGER )
- {
- return (minimumValue == null) ? (double) Integer.MIN_VALUE : minimumValue.doubleValue();
- }
- else
- {
- return (minimumValue == null) ? -1.0*Double.MAX_VALUE : minimumValue.doubleValue();
- // NOTE: Double.MIN_VALUE returns the smallest positive value - oooops.
- }
- }
-
-/**
-* Sets which type of number this text field can accept.
-* @see #INTEGER
-* @see #FLOAT
-* @param newValueType The type of number to accept.
-*/
- public void setValueType(int newValueType)
- {
- if ((newValueType != INTEGER) && (newValueType != FLOAT))
- {
- valueType = INTEGER;
- }
- else
- {
- valueType = newValueType;
- }
- }
-
-/**
-* Returns which type of number this text field accepts. The default is
-* integer.
-* @see #INTEGER
-* @see #FLOAT
-* @return The type of number to accept.
-*/
- public int getValueType()
- {
- return valueType;
- }
-
-/**
-* Returns the integer numeric value of the string in the text field. The type
-* can be either integer of float.
-* @return The current value in the text field.
-*/
- public int getIntValue()
- {
- int value = 0;
-
- try
- {
- value = Integer.parseInt(getText());
- }
- catch (NumberFormatException e)
- {
- try
- {
- Double dValue = Double.valueOf(getText());
- value = dValue.intValue();
- }
- catch (NumberFormatException ignored) {}
- }
-
- return value;
- }
-
-/**
-* Sets the text field to integer value specified.
-* @param aValue An integer value to display in the text field.
-*/
- public void setIntValue(int aValue)
- {
- setText(Integer.toString(aValue));
- }
-
-/**
-* Returns the real number numeric value of the string in the text field. The type
-* can be either integer of float.
-* @return The current value in the text field.
-*/
- public double getDoubleValue()
- {
- Double value = new Double(0);
-
- try
- {
- value = Double.valueOf(getText());
- }
- catch (NumberFormatException ignored) {}
-
- return value.doubleValue();
- }
-
-/**
-* Sets the text field to the double value specified. If the text field type is
-* FLOAT then the the number is display as a real number. If the text field
-* type is INTEGER then the number is converted to a whole number for displaying.
-* @param aValue A double value to display in the text field.
-*/
- public void setDoubleValue(double aValue)
- {
- Double temp = new Double(aValue);
-
- if (valueType == FLOAT)
- {
- setText(temp.toString());
- }
- else
- {
- setText(Integer.toString(temp.intValue()));
- }
- }
-
-/*******************************
-* PROTECTED METHODS
-*******************************/
-
- protected boolean isValidCharacter(char aChar)
- {
- if (((aChar >= ' ') && (aChar <= '/')) || ((aChar >= ':') && (aChar <= '~')))
- {
- if (aChar == '.')
- {
- if ( valueType == FLOAT )
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- else if (aChar == '-')
- {
- if ( getMinimumValue() < 0 )
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- else if (aChar == '+')
- {
- if ( getMaximumValue() >= 0 )
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- return false;
- }
- return true;
- }
-
- protected boolean isValidString(String aString)
- {
- int iValue = 0;
- double dValue = 0.0;
-
- String tempString = new String(scanForSignChar(aString));
-
- if ( valueType == INTEGER )
- {
- try
- {
- iValue = Integer.parseInt(tempString);
- }
- catch (NumberFormatException e1)
- {
- if ((tempString.compareTo("-") == 0) && (getMinimumValue() < 0.0))
- {
- iValue = 0;
- }
- else
- {
- return false;
- }
- }
- if ((((double)iValue) < getMinimumValue()) || (((double)iValue) > getMaximumValue()))
- {
- return false;
- }
- }
- else
- {
- // Double.valueOf requires a zero before the decimal point
- if ( tempString.startsWith( "." ) )
- {
- tempString = "0" + tempString;
- }
- try
- {
- dValue = Double.valueOf(tempString).doubleValue();
- }
- catch (NumberFormatException e2)
- {
- if ((tempString.compareTo("-") == 0) && (getMinimumValue() < 0.0))
- {
- dValue = 0.0;
- }
- else
- {
- return false;
- }
- }
-
- if ((dValue < getMinimumValue()) || (dValue > getMaximumValue()))
- {
- return false;
- }
- }
-
- return true;
- }
-
- protected void postProcessing()
- {
- if (sign)
- {
- setText(scanForSignChar(getText()));
- setCaretPosition(newCaretPosition);
- }
- sign = false;
- }
-
-
-/*******************************
-* PRIVATE METHODS
-*******************************/
-
- private String scanForSignChar(String aString)
- {
- String newString = "";
- boolean positive = false;
- boolean negative = false;
- int oldCaretPosition = getCaretPosition();
- int charactersAdded = 0;
-
- newCaretPosition = 0;
-
- if (aString.length() <= 0)
- {
- return aString;
- }
-
- for (int i = 0; i < aString.length(); ++i)
- {
- switch (aString.charAt(i))
- {
- case '+': positive = true;
- break;
- case '-': negative = true;
- break;
- default: newString += aString.charAt(i);
- charactersAdded++;
- break;
- }
-
- if ((i + 1) == oldCaretPosition)
- {
- newCaretPosition = charactersAdded;
- }
- }
-
- if ((!(positive)) && (negative))
- {
- newString = "-" + newString;
- newCaretPosition++;
- }
-
- if (positive || negative)
- {
- sign = true;
- }
-
- return newString;
- }
+ * NumericTextField is a "smart" text field that restricts the user's input. The
+ * input is restructed to numeric only wich can be of two types: integer and
+ * real numbers. A range can also be placed on the text field. The default type
+ * is integer, with the being (Integer.MIN_VALUE, Integer.MAX_VALUE).
+ *
+ * @author rob@straylight.princeton.com
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
+public class NumericTextField extends SmartTextField {
+
+ /*******************************
+ * CONSTANTS
+ *******************************/
+
+ /**
+ * Restrict the text input to integers (whole numbers) only.
+ */
+ public final static int INTEGER = 0;
+
+ /**
+ * Restrict the text input to floating-point numbers only.
+ */
+ public final static int FLOAT = 1;
+
+ private Number maximumValue = null;
+ private Number minimumValue = null;
+
+ private boolean sign = false;
+ private int newCaretPosition = 0;
+ private int valueType = INTEGER;
+
+ /*******************************
+ * PUBLIC METHODS
+ *******************************/
+
+ /**
+ * Default constructor.
+ */
+ public NumericTextField() {
+ this("", 0);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param text The initial string the text field is set to.
+ */
+ public NumericTextField(String text) {
+ this(text, 0);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param columns Width of the text field (in characters).
+ */
+ public NumericTextField(int columns) {
+ this("", columns);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param text The initial string the text field is set to.
+ * @param columns Width of the text field (in characters).
+ */
+ public NumericTextField(String text, int columns) {
+ super(text, columns);
+ }
+
+ /**
+ * Sets the upper limit of the range of numbers to accept.
+ *
+ * @param newMaximumValue The maximum number accepted by the text field.
+ */
+ public void setMaximumValue(double newMaximumValue) {
+ if (newMaximumValue >= 0) {
+ maximumValue = new Double(newMaximumValue);
+ } else {
+ maximumValue = null;
+ }
+ }
+
+ /**
+ * Returns the upper limit of the range of numbers to accept.
+ *
+ * @return The maximum number accepted by this text field.
+ */
+ public double getMaximumValue() {
+ if (valueType == INTEGER) {
+ return (maximumValue == null) ? (double) Integer.MAX_VALUE : maximumValue.doubleValue();
+ } else {
+ return (maximumValue == null) ? Double.MAX_VALUE : maximumValue.doubleValue();
+ }
+ }
+
+ /**
+ * Sets the lower limit of the range of numbers to accept.
+ *
+ * @param newMinimumValue The minimum number accepted by the text field.
+ */
+ public void setMinimumValue(double newMinimumValue) {
+ if (newMinimumValue <= 0) {
+ minimumValue = new Double(newMinimumValue);
+ } else {
+ minimumValue = null;
+ }
+ }
+
+ /**
+ * Returns the lower limit of the range of numbers to accept.
+ *
+ * @return The minimum number accepted by this text field.
+ */
+ public double getMinimumValue() {
+ if (valueType == INTEGER) {
+ return (minimumValue == null) ? (double) Integer.MIN_VALUE : minimumValue.doubleValue();
+ } else {
+ return (minimumValue == null) ? -1.0 * Double.MAX_VALUE : minimumValue.doubleValue();
+ // NOTE: Double.MIN_VALUE returns the smallest positive value - oooops.
+ }
+ }
+
+ /**
+ * Sets which type of number this text field can accept.
+ *
+ * @see #INTEGER
+ * @see #FLOAT
+ * @param newValueType The type of number to accept.
+ */
+ public void setValueType(int newValueType) {
+ if ((newValueType != INTEGER) && (newValueType != FLOAT)) {
+ valueType = INTEGER;
+ } else {
+ valueType = newValueType;
+ }
+ }
+
+ /**
+ * Returns which type of number this text field accepts. The default is integer.
+ *
+ * @see #INTEGER
+ * @see #FLOAT
+ * @return The type of number to accept.
+ */
+ public int getValueType() {
+ return valueType;
+ }
+
+ /**
+ * Returns the integer numeric value of the string in the text field. The type
+ * can be either integer of float.
+ *
+ * @return The current value in the text field.
+ */
+ public int getIntValue() {
+ int value = 0;
+
+ try {
+ value = Integer.parseInt(getText());
+ } catch (NumberFormatException e) {
+ try {
+ Double dValue = Double.valueOf(getText());
+ value = dValue.intValue();
+ } catch (NumberFormatException ignored) {
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * Sets the text field to integer value specified.
+ *
+ * @param aValue An integer value to display in the text field.
+ */
+ public void setIntValue(int aValue) {
+ setText(Integer.toString(aValue));
+ }
+
+ /**
+ * Returns the real number numeric value of the string in the text field. The
+ * type can be either integer of float.
+ *
+ * @return The current value in the text field.
+ */
+ public double getDoubleValue() {
+ Double value = new Double(0);
+
+ try {
+ value = Double.valueOf(getText());
+ } catch (NumberFormatException ignored) {
+ }
+
+ return value.doubleValue();
+ }
+
+ /**
+ * Sets the text field to the double value specified. If the text field type is
+ * FLOAT then the the number is display as a real number. If the text field type
+ * is INTEGER then the number is converted to a whole number for displaying.
+ *
+ * @param aValue A double value to display in the text field.
+ */
+ public void setDoubleValue(double aValue) {
+ Double temp = new Double(aValue);
+
+ if (valueType == FLOAT) {
+ setText(temp.toString());
+ } else {
+ setText(Integer.toString(temp.intValue()));
+ }
+ }
+
+ /*******************************
+ * PROTECTED METHODS
+ *******************************/
+
+ protected boolean isValidCharacter(char aChar) {
+ if (((aChar >= ' ') && (aChar <= '/')) || ((aChar >= ':') && (aChar <= '~'))) {
+ if (aChar == '.') {
+ if (valueType == FLOAT) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (aChar == '-') {
+ if (getMinimumValue() < 0) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (aChar == '+') {
+ if (getMaximumValue() >= 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ protected boolean isValidString(String aString) {
+ int iValue = 0;
+ double dValue = 0.0;
+
+ String tempString = new String(scanForSignChar(aString));
+
+ if (valueType == INTEGER) {
+ try {
+ iValue = Integer.parseInt(tempString);
+ } catch (NumberFormatException e1) {
+ if ((tempString.compareTo("-") == 0) && (getMinimumValue() < 0.0)) {
+ iValue = 0;
+ } else {
+ return false;
+ }
+ }
+ if ((((double) iValue) < getMinimumValue()) || (((double) iValue) > getMaximumValue())) {
+ return false;
+ }
+ } else {
+ // Double.valueOf requires a zero before the decimal point
+ if (tempString.startsWith(".")) {
+ tempString = "0" + tempString;
+ }
+ try {
+ dValue = Double.valueOf(tempString).doubleValue();
+ } catch (NumberFormatException e2) {
+ if ((tempString.compareTo("-") == 0) && (getMinimumValue() < 0.0)) {
+ dValue = 0.0;
+ } else {
+ return false;
+ }
+ }
+
+ if ((dValue < getMinimumValue()) || (dValue > getMaximumValue())) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected void postProcessing() {
+ if (sign) {
+ setText(scanForSignChar(getText()));
+ setCaretPosition(newCaretPosition);
+ }
+ sign = false;
+ }
+
+ /*******************************
+ * PRIVATE METHODS
+ *******************************/
+
+ private String scanForSignChar(String aString) {
+ String newString = "";
+ boolean positive = false;
+ boolean negative = false;
+ int oldCaretPosition = getCaretPosition();
+ int charactersAdded = 0;
+
+ newCaretPosition = 0;
+
+ if (aString.length() <= 0) {
+ return aString;
+ }
+
+ for (int i = 0; i < aString.length(); ++i) {
+ switch (aString.charAt(i)) {
+ case '+':
+ positive = true;
+ break;
+ case '-':
+ negative = true;
+ break;
+ default:
+ newString += aString.charAt(i);
+ charactersAdded++;
+ break;
+ }
+
+ if ((i + 1) == oldCaretPosition) {
+ newCaretPosition = charactersAdded;
+ }
+ }
+
+ if ((!(positive)) && (negative)) {
+ newString = "-" + newString;
+ newCaretPosition++;
+ }
+
+ if (positive || negative) {
+ sign = true;
+ }
+
+ return newString;
+ }
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTable.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTable.java
index 9db2834..996f8e0 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTable.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTable.java
@@ -47,233 +47,235 @@ import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
/**
-* PropertyEditorTable is a table designed to display and edit the properties
-* of an object. Because JTable assumes all cells in a column display
-* the same data type, we have to subclass to determine the class
-* based on the cell contents.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
+ * PropertyEditorTable is a table designed to display and edit the properties of
+ * an object. Because JTable assumes all cells in a column display the same data
+ * type, we have to subclass to determine the class based on the cell contents.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
public class PropertyEditorTable extends JTable {
//
// Constructors
//
- /**
- * Constructs a default JTable which is initialized with a default
- * data model, a default column model, and a default selection
- * model.
- *
- * @see #createDefaultDataModel
- * @see #createDefaultColumnModel
- * @see #createDefaultSelectionModel
- */
- public PropertyEditorTable() {
- super(null, null, null);
- }
-
- /**
- * Constructs a JTable which is initialized with <i>dm</i> as the
- * data model, a default column model, and a default selection
- * model.
- *
- * @param dm The data model for the table
- * @see #createDefaultColumnModel
- * @see #createDefaultSelectionModel
- */
- public PropertyEditorTable(TableModel dm) {
- super(dm, null, null);
- }
-
- /**
- * Constructs a JTable which is initialized with <i>dm</i> as the
- * data model, <i>cm</i> as the column model, and a default selection
- * model.
- *
- * @param dm The data model for the table
- * @param cm The column model for the table
- * @see #createDefaultSelectionModel
- */
- public PropertyEditorTable(TableModel dm, TableColumnModel cm) {
- super(dm, cm, null);
- }
-
- /**
- * Constructs a JTable which is initialized with <i>dm</i> as the
- * data model, <i>cm</i> as the column model, and <i>sm</i> as the
- * selection model. If any of the parameters are <b>null</b> this
- * method will initialize the table with the corresponding
- * default model. The <i>autoCreateColumnsFromModel</i> flag is set
- * to false if <i>cm</i> is non-null, otherwise it is set to true
- * and the column model is populated with suitable TableColumns
- * for the columns in <i>dm</i>.
- *
- * @param dm The data model for the table
- * @param cm The column model for the table
- * @param sm The row selection model for the table
- * @see #createDefaultDataModel
- * @see #createDefaultColumnModel
- * @see #createDefaultSelectionModel
- */
- public PropertyEditorTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
- super( dm, cm, sm );
+ /**
+ * Constructs a default JTable which is initialized with a default data model, a
+ * default column model, and a default selection model.
+ *
+ * @see #createDefaultDataModel
+ * @see #createDefaultColumnModel
+ * @see #createDefaultSelectionModel
+ */
+ public PropertyEditorTable() {
+ super(null, null, null);
}
- /**
- * Constructs a JTable with <i>numRows</i> and <i>numColumns</i> of
- * empty cells using the DefaultTableModel. The columns will have
- * names of the form "A", "B", "C", etc.
- *
- * @param numRows The number of rows the table holds
- * @param numColumns The number of columns the table holds
- */
- public PropertyEditorTable(int numRows, int numColumns) {
- super( numRows, numColumns );
- }
-
- /**
- * Constructs a JTable to display the values in the Vector of Vectors,
- * <i>rowData</i>, with column names, <i>columnNames</i>.
- * The Vectors contained in <i>rowData</i> should contain the values
- * for that row. In other words, the value of the cell at row 1,
- * column 5 can be obtained with the following code:
- * <p>
- * <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
- * <p>
- * All rows must be of the same length as <i>columnNames</i>.
- * <p>
- * @param rowData The data for the new table
- * @param columnNames Names of each column
- */
- public PropertyEditorTable(final Vector rowData, final Vector columnNames) {
- super( rowData, columnNames );
- }
-
- /**
- * Constructs a JTable to display the values in the two dimensional array,
- * <i>rowData</i>, with column names, <i>columnNames</i>.
- * <i>rowData</i> is an Array of rows, so the value of the cell at row 1,
- * column 5 can be obtained with the following code:
- * <p>
- * <pre> rowData[1][5]; </pre>
- * <p>
- * All rows must be of the same length as <i>columnNames</i>.
- * <p>
- * @param rowData The data for the new table
- * @param columnNames Names of each column
- */
- public PropertyEditorTable(final Object[][] rowData, final Object[] columnNames) {
- super( rowData, columnNames );
+ /**
+ * Constructs a JTable which is initialized with <i>dm</i> as the data model, a
+ * default column model, and a default selection model.
+ *
+ * @param dm The data model for the table
+ * @see #createDefaultColumnModel
+ * @see #createDefaultSelectionModel
+ */
+ public PropertyEditorTable(TableModel dm) {
+ super(dm, null, null);
}
- /**
- * Returns the type of the column at the specified view position.
- *
- * @return the type of the column at position <I>column</I> in the view
- * where the first column is column 0.
+ /**
+ * Constructs a JTable which is initialized with <i>dm</i> as the data model,
+ * <i>cm</i> as the column model, and a default selection model.
*
- * Modified mln: now a wrapper for getCellClass()
+ * @param dm The data model for the table
+ * @param cm The column model for the table
+ * @see #createDefaultSelectionModel
+ */
+ public PropertyEditorTable(TableModel dm, TableColumnModel cm) {
+ super(dm, cm, null);
+ }
+
+ /**
+ * Constructs a JTable which is initialized with <i>dm</i> as the data model,
+ * <i>cm</i> as the column model, and <i>sm</i> as the selection model. If any
+ * of the parameters are <b>null</b> this method will initialize the table with
+ * the corresponding default model. The <i>autoCreateColumnsFromModel</i> flag
+ * is set to false if <i>cm</i> is non-null, otherwise it is set to true and the
+ * column model is populated with suitable TableColumns for the columns in
+ * <i>dm</i>.
*
- */
- public Class getColumnClass(int column) {
- return getCellClass( 0, column );
- }
-
- /**
- * Returns the type of the cell at the specified view position.
- *
- * @return the type of the cell at position <I>row</I>, <I>column</I> in the view
- * where the first column is column 0.
+ * @param dm The data model for the table
+ * @param cm The column model for the table
+ * @param sm The row selection model for the table
+ * @see #createDefaultDataModel
+ * @see #createDefaultColumnModel
+ * @see #createDefaultSelectionModel
+ */
+ public PropertyEditorTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
+ super(dm, cm, sm);
+ }
+
+ /**
+ * Constructs a JTable with <i>numRows</i> and <i>numColumns</i> of empty cells
+ * using the DefaultTableModel. The columns will have names of the form "A",
+ * "B", "C", etc.
*
- * Modified mln: new methods
+ * @param numRows The number of rows the table holds
+ * @param numColumns The number of columns the table holds
+ */
+ public PropertyEditorTable(int numRows, int numColumns) {
+ super(numRows, numColumns);
+ }
+
+ /**
+ * Constructs a JTable to display the values in the Vector of Vectors,
+ * <i>rowData</i>, with column names, <i>columnNames</i>. The Vectors contained
+ * in <i>rowData</i> should contain the values for that row. In other words, the
+ * value of the cell at row 1, column 5 can be obtained with the following code:
+ * <p>
+ *
+ * <pre>
+ * ((Vector) rowData.elementAt(1)).elementAt(5);
+ * </pre>
+ * <p>
+ * All rows must be of the same length as <i>columnNames</i>.
+ * <p>
+ *
+ * @param rowData The data for the new table
+ * @param columnNames Names of each column
+ */
+ public PropertyEditorTable(final Vector rowData, final Vector columnNames) {
+ super(rowData, columnNames);
+ }
+
+ /**
+ * Constructs a JTable to display the values in the two dimensional array,
+ * <i>rowData</i>, with column names, <i>columnNames</i>. <i>rowData</i> is an
+ * Array of rows, so the value of the cell at row 1, column 5 can be obtained
+ * with the following code:
+ * <p>
+ *
+ * <pre>
+ * rowData[1][5];
+ * </pre>
+ * <p>
+ * All rows must be of the same length as <i>columnNames</i>.
+ * <p>
+ *
+ * @param rowData The data for the new table
+ * @param columnNames Names of each column
+ */
+ public PropertyEditorTable(final Object[][] rowData, final Object[] columnNames) {
+ super(rowData, columnNames);
+ }
+
+ /**
+ * Returns the type of the column at the specified view position.
+ *
+ * @return the type of the column at position <I>column</I> in the view where
+ * the first column is column 0.
+ *
+ * Modified mln: now a wrapper for getCellClass()
+ *
+ */
+ public Class getColumnClass(int column) {
+ return getCellClass(0, column);
+ }
+
+ /**
+ * Returns the type of the cell at the specified view position.
+ *
+ * @return the type of the cell at position <I>row</I>, <I>column</I> in the
+ * view where the first column is column 0.
*
- */
- public Class getCellClass(int row, int column) {
+ * Modified mln: new methods
+ *
+ */
+ public Class getCellClass(int row, int column) {
TableModel model = getModel();
- if ( model instanceof PropertyEditorTableModel )
- return ((PropertyEditorTableModel)model).getCellClass( row, column );
- else
+ if (model instanceof PropertyEditorTableModel)
+ return ((PropertyEditorTableModel) model).getCellClass(row, column);
+ else
return model.getColumnClass(convertColumnIndexToModel(column));
- }
-
- /**
- * Return an appropriate renderer for the cell specified by this this row and
- * column. If the TableColumn for this column has a non-null renderer, return that.
- * If not, find the class of the data in this column (using getColumnClass())
- * and return the default renderer for this type of data.
- *
- * @param row the row of the cell to render, where 0 is the first
- * @param column the column of the cell to render, where 0 is the first
+ }
+
+ /**
+ * Return an appropriate renderer for the cell specified by this this row and
+ * column. If the TableColumn for this column has a non-null renderer, return
+ * that. If not, find the class of the data in this column (using
+ * getColumnClass()) and return the default renderer for this type of data.
+ *
+ * @param row the row of the cell to render, where 0 is the first
+ * @param column the column of the cell to render, where 0 is the first
+ *
+ * Modified mln: calls getCellClass if there's no column model
*
- * Modified mln: calls getCellClass if there's no column model
+ */
+ public TableCellRenderer getCellRenderer(int row, int column) {
+ TableColumn tableColumn = getColumnModel().getColumn(column);
+ TableCellRenderer renderer = tableColumn.getCellRenderer();
+ if (renderer == null) {
+ renderer = getDefaultRenderer(getCellClass(row, column));
+ }
+ return renderer;
+ }
+
+ /**
+ * Return an appropriate editor for the cell specified by this this row and
+ * column. If the TableColumn for this column has a non-null editor, return
+ * that. If not, find the class of the data in this column (using
+ * getColumnClass()) and return the default editor for this type of data.
*
- */
- public TableCellRenderer getCellRenderer(int row, int column) {
- TableColumn tableColumn = getColumnModel().getColumn(column);
- TableCellRenderer renderer = tableColumn.getCellRenderer();
- if (renderer == null) {
- renderer = getDefaultRenderer(getCellClass(row, column));
- }
- return renderer;
- }
-
-
- /**
- * Return an appropriate editor for the cell specified by this this row and
- * column. If the TableColumn for this column has a non-null editor, return that.
- * If not, find the class of the data in this column (using getColumnClass())
- * and return the default editor for this type of data.
- *
- * @param row the row of the cell to edit, where 0 is the first
- * @param column the column of the cell to edit, where 0 is the first
+ * @param row the row of the cell to edit, where 0 is the first
+ * @param column the column of the cell to edit, where 0 is the first
*
- * Modified mp: calls getCellClass if there's no column model
+ * Modified mp: calls getCellClass if there's no column model
*
- */
- public TableCellEditor getCellEditor(int row, int column) {
- TableColumn tableColumn = getColumnModel().getColumn(column);
- TableCellEditor editor = tableColumn.getCellEditor();
- if (editor == null) {
- editor = getDefaultEditor(getCellClass(row, column));
- }
- return editor;
- }
+ */
+ public TableCellEditor getCellEditor(int row, int column) {
+ TableColumn tableColumn = getColumnModel().getColumn(column);
+ TableCellEditor editor = tableColumn.getCellEditor();
+ if (editor == null) {
+ editor = getDefaultEditor(getCellClass(row, column));
+ }
+ return editor;
+ }
protected void createDefaultRenderers() {
super.createDefaultRenderers();
-/* // copying this code here as a sample of creating a renderer
- // Dates
- DefaultTableCellRenderer dateRenderer = new DefaultTableCellRenderer() {
- DateFormat formatter = DateFormat.getDateInstance();
- public void setValue(Object value) {
- setText((value == null) ? "" : formatter.format(value)); }
- };
- dateRenderer.setHorizontalAlignment(JLabel.RIGHT);
- setDefaultRenderer(Date.class, dateRenderer);
-*/
-
- DefaultTableCellRenderer fontRenderer = new DefaultTableCellRenderer() {
- public void setValue(Object value) {
- setText( getFontDescription( (Font) value ) );
+ /*
+ * // copying this code here as a sample of creating a renderer // Dates
+ * DefaultTableCellRenderer dateRenderer = new DefaultTableCellRenderer() {
+ * DateFormat formatter = DateFormat.getDateInstance(); public void
+ * setValue(Object value) { setText((value == null) ? "" :
+ * formatter.format(value)); } };
+ * dateRenderer.setHorizontalAlignment(JLabel.RIGHT);
+ * setDefaultRenderer(Date.class, dateRenderer);
+ */
+
+ DefaultTableCellRenderer fontRenderer = new DefaultTableCellRenderer() {
+ public void setValue(Object value) {
+ setText(getFontDescription((Font) value));
}
};
- fontRenderer.setHorizontalAlignment(JLabel.RIGHT);
- setDefaultRenderer(Font.class, fontRenderer);
+ fontRenderer.setHorizontalAlignment(JLabel.RIGHT);
+ setDefaultRenderer(Font.class, fontRenderer);
- setUpColorRenderer( this );
- setUpMethodRenderer( this );
- }
+ setUpColorRenderer(this);
+ setUpMethodRenderer(this);
+ }
- protected String getFontDescription( Font f ) {
+ protected String getFontDescription(Font f) {
String s;
- if ( f != null ) {
+ if (f != null) {
s = f.getName();
- if ( f.isBold() ) s += " Bold";
- if ( f.isItalic() ) s += " Italic";
+ if (f.isBold())
+ s += " Bold";
+ if (f.isItalic())
+ s += " Italic";
s += " " + f.getSize();
} else {
s = "";
@@ -281,292 +283,263 @@ public class PropertyEditorTable extends JTable {
return s;
}
- protected void createDefaultEditors() {
+ protected void createDefaultEditors() {
super.createDefaultEditors();
-/* // copying this code here as a sample of creating an editor
- // Numbers
- JTextField rightAlignedTextField = new JTextField();
- rightAlignedTextField.setHorizontalAlignment(JTextField.RIGHT);
- rightAlignedTextField.setBorder(new LineBorder(Color.black));
- setDefaultEditor(Number.class, new DefaultCellEditor(rightAlignedTextField));
-
- // Booleans
- JCheckBox centeredCheckBox = new JCheckBox();
- centeredCheckBox.setHorizontalAlignment(JCheckBox.CENTER);
- setDefaultEditor(Boolean.class, new DefaultCellEditor(centeredCheckBox));
-*/
- setUpColorEditor( this );
- setUpMethodEditor( this );
+ /*
+ * // copying this code here as a sample of creating an editor // Numbers
+ * JTextField rightAlignedTextField = new JTextField();
+ * rightAlignedTextField.setHorizontalAlignment(JTextField.RIGHT);
+ * rightAlignedTextField.setBorder(new LineBorder(Color.black));
+ * setDefaultEditor(Number.class, new DefaultCellEditor(rightAlignedTextField));
+ *
+ * // Booleans JCheckBox centeredCheckBox = new JCheckBox();
+ * centeredCheckBox.setHorizontalAlignment(JCheckBox.CENTER);
+ * setDefaultEditor(Boolean.class, new DefaultCellEditor(centeredCheckBox));
+ */
+ setUpColorEditor(this);
+ setUpMethodEditor(this);
}
-
- // following code lifted from:
+ // following code lifted from:
// http://java.sun.com/docs/books/tutorial/ui/swing/example-swing/TableDialogEditDemo.java
- class ColorRenderer extends JLabel
- implements TableCellRenderer {
- Border unselectedBorder = null;
- Border selectedBorder = null;
- boolean isBordered = true;
-
- public ColorRenderer(boolean isBordered) {
- super();
- this.isBordered = isBordered;
- this.setOpaque(true); //MUST do this for background to show up.
- }
-
- public Component getTableCellRendererComponent(
- JTable table, Object color,
- boolean isSelected, boolean hasFocus,
- int row, int column) {
- this.setBackground((Color)color);
- if (isBordered) {
- if (isSelected) {
- if (selectedBorder == null) {
- selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
- table.getSelectionBackground());
- }
- this.setBorder(selectedBorder);
- } else {
- if (unselectedBorder == null) {
- unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
- table.getBackground());
- }
- this.setBorder(unselectedBorder);
- }
- }
- return this;
- }
- }
-
- private void setUpColorRenderer(JTable table) {
- table.setDefaultRenderer(Color.class,
- new ColorRenderer(true));
- }
-
- //Set up the editor for the Color cells.
- private void setUpColorEditor(JTable table) {
- //First, set up the button that brings up the dialog.
- final JButton button = new JButton("") {
- public void setText(String s) {
- //Button never shows text -- only color.
- }
- };
- button.setBackground(Color.white);
- button.setBorderPainted(false);
- button.setMargin(new Insets(0,0,0,0));
-
- //Now create an editor to encapsulate the button, and
- //set it up as the editor for all Color cells.
- final ColorEditor colorEditor = new ColorEditor(button);
- table.setDefaultEditor(Color.class, colorEditor);
-
- //Set up the dialog that the button brings up.
- final JColorChooser colorChooser = new JColorChooser();
- //XXX: PENDING: add the following when setPreviewPanel
- //XXX: starts working.
- //JComponent preview = new ColorRenderer(false);
- //preview.setPreferredSize(new Dimension(50, 10));
- //colorChooser.setPreviewPanel(preview);
- ActionListener okListener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- colorEditor.currentColor = colorChooser.getColor();
- }
- };
- final JDialog dialog = JColorChooser.createDialog(button,
- "Pick a Color",
- true,
- colorChooser,
- okListener,
- null); //XXXDoublecheck this is OK
-
- //Here's the code that brings up the dialog.
- button.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- button.setBackground(colorEditor.currentColor);
- colorChooser.setColor(colorEditor.currentColor);
- //Without the following line, the dialog comes up
- //in the middle of the screen.
- //dialog.setLocationRelativeTo(button);
- dialog.show();
- }
- });
- }
-
- /*
- * The editor button that brings up the dialog.
- * We extend DefaultCellEditor for convenience,
- * even though it mean we have to create a dummy
- * check box. Another approach would be to copy
- * the implementation of TableCellEditor methods
- * from the source code for DefaultCellEditor.
- */
- class ColorEditor extends DefaultCellEditor {
- Color currentColor = null;
-
- public ColorEditor(JButton b) {
- super(new JCheckBox()); //Unfortunately, the constructor
- //expects a check box, combo box,
- //or text field.
- editorComponent = b;
- setClickCountToStart(1); //This is usually 1 or 2.
-
- //Must do this so that editing stops when appropriate.
- b.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- fireEditingStopped();
- }
- });
- }
-
- protected void fireEditingStopped() {
- super.fireEditingStopped();
- }
-
- public Object getCellEditorValue() {
- return currentColor;
- }
-
- public Component getTableCellEditorComponent(JTable table,
- Object value,
- boolean isSelected,
- int row,
- int column) {
- ((JButton)editorComponent).setText(value.toString());
- currentColor = (Color)value;
- return editorComponent;
- }
- }
-
- class MethodRenderer extends JLabel
- implements TableCellRenderer {
-
- Method theMethod = null;
- JTable theTable = null;
-
- public MethodRenderer() {
- super();
- }
-
- public Component getTableCellRendererComponent(
- JTable table, Object method,
- boolean isSelected, boolean hasFocus,
- int row, int column) {
- theMethod = (Method) method;
- theTable = table;
- setText( " " + theMethod.getReturnType().getName() );
- return this;
- }
- }
-
- private void setUpMethodRenderer(JTable table) {
- table.setDefaultRenderer(Method.class,
- new MethodRenderer());
- }
-
- /*
- * We extend DefaultCellEditor for convenience,
- * as with ColorEditor.
- */
- class MethodEditor extends DefaultCellEditor {
- Method theMethod = null;
- JTable theTable = null;
-
- public MethodEditor(JButton b) {
- super(new JCheckBox()); //Unfortunately, the constructor
- //expects a check box, combo box,
- //or text field.
- editorComponent = b;
- setClickCountToStart(1); //This is usually 1 or 2.
-
- //Must do this so that editing stops when appropriate.
- b.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- fireEditingStopped();
- }
- });
- }
-
- protected void fireEditingStopped() {
- super.fireEditingStopped();
- }
-
- public Object getCellEditorValue() {
- return theMethod;
- }
-
- public Component getTableCellEditorComponent(JTable table,
- Object value,
- boolean isSelected,
- int row,
- int column) {
- ((JButton)editorComponent).setText(value.toString());
- theMethod = (Method)value;
- theTable = table;
- return editorComponent;
- }
- }
-
- //Set up the editor for the Method cells.
- private void setUpMethodEditor(PropertyEditorTable table) {
- //First, set up the button that brings up the dialog.
- final JButton button = new JButton("invoking method") {
- public void setText(String s) {
- //Button never shows text -- only color.
- }
- };
- button.setBackground(Color.white);
- button.setBorderPainted(false);
- button.setMargin(new Insets(0,0,0,0));
-
- //Now create an editor to encapsulate the button, and
- //set it up as the editor for all Color cells.
- final MethodEditor methodEditor = new MethodEditor(button);
- table.setDefaultEditor(Method.class, methodEditor);
-
- // handle the button-click
- final PropertyEditorTable theTable = table;
- button.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
-
- Component parent = SwingUtilities.getRoot( theTable );
- if ( parent == null ) parent = theTable;
-
- Cursor oldCursor = parent.getCursor();
- parent.setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );
-
- Object result = null;
- Object inspectedObject = ((PropertyEditorTableModel)
- methodEditor.theTable.getModel()).inspectedObject;
- try
- {
- methodEditor.theMethod.setAccessible( true );
- result = methodEditor.theMethod.invoke(
- inspectedObject, (Object[])null );
- }
- catch ( Exception exc )
- {
- System.err.println( "PropertyEditorTable.MethodRenderer.actionPerformed: " +
- "Error occurred: " + exc );
- }
- theTable.methodInvoked( inspectedObject, methodEditor.theMethod, result );
-
- parent.setCursor( oldCursor );
- }
- });
- }
+ class ColorRenderer extends JLabel implements TableCellRenderer {
+ Border unselectedBorder = null;
+ Border selectedBorder = null;
+ boolean isBordered = true;
-/**
-* Called by the method cell editor when a method is invoked.
-* @param anObject The object upon which the method was invoked.
-* @param aMethod The method that was invoked.
-* @param aResult The result of the method invocation; may be null.
-*/
- public void methodInvoked( Object anObject, Method aMethod, Object aResult )
- {
- System.out.println( aMethod.getName() + ": " + aResult );
- }
-}
+ public ColorRenderer(boolean isBordered) {
+ super();
+ this.isBordered = isBordered;
+ this.setOpaque(true); // MUST do this for background to show up.
+ }
+ public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus,
+ int row, int column) {
+ this.setBackground((Color) color);
+ if (isBordered) {
+ if (isSelected) {
+ if (selectedBorder == null) {
+ selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getSelectionBackground());
+ }
+ this.setBorder(selectedBorder);
+ } else {
+ if (unselectedBorder == null) {
+ unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getBackground());
+ }
+ this.setBorder(unselectedBorder);
+ }
+ }
+ return this;
+ }
+ }
+
+ private void setUpColorRenderer(JTable table) {
+ table.setDefaultRenderer(Color.class, new ColorRenderer(true));
+ }
+ // Set up the editor for the Color cells.
+ private void setUpColorEditor(JTable table) {
+ // First, set up the button that brings up the dialog.
+ final JButton button = new JButton("") {
+ public void setText(String s) {
+ // Button never shows text -- only color.
+ }
+ };
+ button.setBackground(Color.white);
+ button.setBorderPainted(false);
+ button.setMargin(new Insets(0, 0, 0, 0));
+
+ // Now create an editor to encapsulate the button, and
+ // set it up as the editor for all Color cells.
+ final ColorEditor colorEditor = new ColorEditor(button);
+ table.setDefaultEditor(Color.class, colorEditor);
+
+ // Set up the dialog that the button brings up.
+ final JColorChooser colorChooser = new JColorChooser();
+ // XXX: PENDING: add the following when setPreviewPanel
+ // XXX: starts working.
+ // JComponent preview = new ColorRenderer(false);
+ // preview.setPreferredSize(new Dimension(50, 10));
+ // colorChooser.setPreviewPanel(preview);
+ ActionListener okListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ colorEditor.currentColor = colorChooser.getColor();
+ }
+ };
+ final JDialog dialog = JColorChooser.createDialog(button, "Pick a Color", true, colorChooser, okListener, null); // XXXDoublecheck
+ // this
+ // is
+ // OK
+
+ // Here's the code that brings up the dialog.
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ button.setBackground(colorEditor.currentColor);
+ colorChooser.setColor(colorEditor.currentColor);
+ // Without the following line, the dialog comes up
+ // in the middle of the screen.
+ // dialog.setLocationRelativeTo(button);
+ dialog.show();
+ }
+ });
+ }
+
+ /*
+ * The editor button that brings up the dialog. We extend DefaultCellEditor for
+ * convenience, even though it mean we have to create a dummy check box. Another
+ * approach would be to copy the implementation of TableCellEditor methods from
+ * the source code for DefaultCellEditor.
+ */
+ class ColorEditor extends DefaultCellEditor {
+ Color currentColor = null;
+
+ public ColorEditor(JButton b) {
+ super(new JCheckBox()); // Unfortunately, the constructor
+ // expects a check box, combo box,
+ // or text field.
+ editorComponent = b;
+ setClickCountToStart(1); // This is usually 1 or 2.
+
+ // Must do this so that editing stops when appropriate.
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ fireEditingStopped();
+ }
+ });
+ }
+
+ protected void fireEditingStopped() {
+ super.fireEditingStopped();
+ }
+
+ public Object getCellEditorValue() {
+ return currentColor;
+ }
+
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
+ int column) {
+ ((JButton) editorComponent).setText(value.toString());
+ currentColor = (Color) value;
+ return editorComponent;
+ }
+ }
+
+ class MethodRenderer extends JLabel implements TableCellRenderer {
+
+ Method theMethod = null;
+ JTable theTable = null;
+
+ public MethodRenderer() {
+ super();
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object method, boolean isSelected,
+ boolean hasFocus, int row, int column) {
+ theMethod = (Method) method;
+ theTable = table;
+ setText(" " + theMethod.getReturnType().getName());
+ return this;
+ }
+ }
+
+ private void setUpMethodRenderer(JTable table) {
+ table.setDefaultRenderer(Method.class, new MethodRenderer());
+ }
+
+ /*
+ * We extend DefaultCellEditor for convenience, as with ColorEditor.
+ */
+ class MethodEditor extends DefaultCellEditor {
+ Method theMethod = null;
+ JTable theTable = null;
+
+ public MethodEditor(JButton b) {
+ super(new JCheckBox()); // Unfortunately, the constructor
+ // expects a check box, combo box,
+ // or text field.
+ editorComponent = b;
+ setClickCountToStart(1); // This is usually 1 or 2.
+
+ // Must do this so that editing stops when appropriate.
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ fireEditingStopped();
+ }
+ });
+ }
+
+ protected void fireEditingStopped() {
+ super.fireEditingStopped();
+ }
+
+ public Object getCellEditorValue() {
+ return theMethod;
+ }
+
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
+ int column) {
+ ((JButton) editorComponent).setText(value.toString());
+ theMethod = (Method) value;
+ theTable = table;
+ return editorComponent;
+ }
+ }
+
+ // Set up the editor for the Method cells.
+ private void setUpMethodEditor(PropertyEditorTable table) {
+ // First, set up the button that brings up the dialog.
+ final JButton button = new JButton("invoking method") {
+ public void setText(String s) {
+ // Button never shows text -- only color.
+ }
+ };
+ button.setBackground(Color.white);
+ button.setBorderPainted(false);
+ button.setMargin(new Insets(0, 0, 0, 0));
+
+ // Now create an editor to encapsulate the button, and
+ // set it up as the editor for all Color cells.
+ final MethodEditor methodEditor = new MethodEditor(button);
+ table.setDefaultEditor(Method.class, methodEditor);
+
+ // handle the button-click
+ final PropertyEditorTable theTable = table;
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+
+ Component parent = SwingUtilities.getRoot(theTable);
+ if (parent == null)
+ parent = theTable;
+
+ Cursor oldCursor = parent.getCursor();
+ parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
+ Object result = null;
+ Object inspectedObject = ((PropertyEditorTableModel) methodEditor.theTable.getModel()).inspectedObject;
+ try {
+ methodEditor.theMethod.setAccessible(true);
+ result = methodEditor.theMethod.invoke(inspectedObject, (Object[]) null);
+ } catch (Exception exc) {
+ System.err
+ .println("PropertyEditorTable.MethodRenderer.actionPerformed: " + "Error occurred: " + exc);
+ }
+ theTable.methodInvoked(inspectedObject, methodEditor.theMethod, result);
+
+ parent.setCursor(oldCursor);
+ }
+ });
+ }
+
+ /**
+ * Called by the method cell editor when a method is invoked.
+ *
+ * @param anObject The object upon which the method was invoked.
+ * @param aMethod The method that was invoked.
+ * @param aResult The result of the method invocation; may be null.
+ */
+ public void methodInvoked(Object anObject, Method aMethod, Object aResult) {
+ System.out.println(aMethod.getName() + ": " + aResult);
+ }
+}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTableModel.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTableModel.java
index f6a2a8d..f6f80f2 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTableModel.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/PropertyEditorTableModel.java
@@ -31,30 +31,28 @@ import javax.swing.Timer;
import javax.swing.table.AbstractTableModel;
/**
-* PropertyEditorTableModel introspects an object to facilitate
-* editing it in a PropertyTable.
-*
-* Because the model always reflects the current state of the
-* inspected object, it is useful to have a table update at
-* automated intervals. By default, this feature is turned off.
-* If you turn it on, you'll want to remember to turn it off
-* when you're done with the table model.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class PropertyEditorTableModel extends AbstractTableModel implements ActionListener
-{
+ * PropertyEditorTableModel introspects an object to facilitate editing it in a
+ * PropertyTable.
+ *
+ * Because the model always reflects the current state of the inspected object,
+ * it is useful to have a table update at automated intervals. By default, this
+ * feature is turned off. If you turn it on, you'll want to remember to turn it
+ * off when you're done with the table model.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class PropertyEditorTableModel extends AbstractTableModel implements ActionListener {
protected Object inspectedObject = null;
final String[] columnNames = { "Property", "Value" };
- static final String METHOD_TAG = " ";
+ static final String METHOD_TAG = " ";
Vector properties = new Vector();
Hashtable methods = new Hashtable(0);
- public void setObject( Object o ) {
+ public void setObject(Object o) {
inspectedObject = o;
Class c = o.getClass();
Method[] m = c.getMethods();
@@ -62,67 +60,56 @@ public class PropertyEditorTableModel extends AbstractTableModel implements Acti
properties = new Vector();
methods = new Hashtable(m.length, 1F);
String name, propertyName;
- for ( int i = 0; i < m.length; i++ ) {
+ for (int i = 0; i < m.length; i++) {
// if ( m[i].getName().startsWith( "get" ) )
// System.out.println( m[i].getName() + ": " + m[i].getReturnType().getName() );
// get methods
- if (
- ( ( m[i].getName().startsWith( "get" ) ) || ( m[i].getName().startsWith( "is" ) ) )
- && ( m[i].getParameterTypes().length == 0 )
- ) {
- name = m[i].getName();
- if ( m[i].getName().startsWith( "is" ) ) {
- propertyName = name.substring( 2, name.length() );
- // probably should only add "is" methods if accompanied by "set" method
- } else { // "get"
- propertyName = name.substring( 3, name.length() );
- }
- if (
- ( m[i].getReturnType().getName().equals( String.class.getName() ) )
- || ( m[i].getReturnType().getName().equals( "boolean" ) )
- || ( m[i].getReturnType().getName().equals( "int" ) )
- || ( m[i].getReturnType().getName().equals( "float" ) )
- || ( m[i].getReturnType().getName().equals( "char" ) )
- || ( m[i].getReturnType().getName().equals( Color.class.getName() ) )
- || ( m[i].getReturnType().getName().equals( Font.class.getName() ) )
- ) {
- properties.addElement( propertyName ); // put property
- methods.put( name, m[i] ); // put method
+ if (((m[i].getName().startsWith("get")) || (m[i].getName().startsWith("is")))
+ && (m[i].getParameterTypes().length == 0)) {
+ name = m[i].getName();
+ if (m[i].getName().startsWith("is")) {
+ propertyName = name.substring(2, name.length());
+ // probably should only add "is" methods if accompanied by "set" method
+ } else { // "get"
+ propertyName = name.substring(3, name.length());
}
- else
- {
- // handle unknown types as invokable methods:
- properties.addElement( propertyName + METHOD_TAG );
- methods.put( propertyName + METHOD_TAG, m[i] );
- }
- }
- else
+ if ((m[i].getReturnType().getName().equals(String.class.getName()))
+ || (m[i].getReturnType().getName().equals("boolean"))
+ || (m[i].getReturnType().getName().equals("int"))
+ || (m[i].getReturnType().getName().equals("float"))
+ || (m[i].getReturnType().getName().equals("char"))
+ || (m[i].getReturnType().getName().equals(Color.class.getName()))
+ || (m[i].getReturnType().getName().equals(Font.class.getName()))) {
+ properties.addElement(propertyName); // put property
+ methods.put(name, m[i]); // put method
+ } else {
+ // handle unknown types as invokable methods:
+ properties.addElement(propertyName + METHOD_TAG);
+ methods.put(propertyName + METHOD_TAG, m[i]);
+ }
+ } else
// set methods
- if ( ( m[i].getName().startsWith( "set" ) ) &&
- ( m[i].getParameterTypes().length == 1 ) ) {
+ if ((m[i].getName().startsWith("set")) && (m[i].getParameterTypes().length == 1)) {
name = m[i].getName();
- if (
- ( m[i].getParameterTypes()[0].getName().equals( String.class.getName() ) )
- || ( m[i].getParameterTypes()[0].getName().equals( "boolean" ) )
- || ( m[i].getParameterTypes()[0].getName().equals( "int" ) )
- || ( m[i].getParameterTypes()[0].getName().equals( "float" ) )
- || ( m[i].getParameterTypes()[0].getName().equals( Color.class.getName() ) )
+ if ((m[i].getParameterTypes()[0].getName().equals(String.class.getName()))
+ || (m[i].getParameterTypes()[0].getName().equals("boolean"))
+ || (m[i].getParameterTypes()[0].getName().equals("int"))
+ || (m[i].getParameterTypes()[0].getName().equals("float"))
+ || (m[i].getParameterTypes()[0].getName().equals(Color.class.getName()))
// || ( m[i].getParameterTypes()[0].getName().equals( Font.class.getName() ) )
) {
// System.out.println( "Accepted: " + name + ": " + m[i].getParameterTypes()[0].getName() );
- methods.put( name, m[i] ); // set method
+ methods.put(name, m[i]); // set method
} else {
// System.out.println( "Rejected: " + name + ": " + m[i].getParameterTypes()[0].getName() );
}
+ } else
+ // zero-parameter methods to be invoked on click
+ if (m[i].getParameterTypes().length == 0) {
+ properties.addElement(m[i].getName() + METHOD_TAG);
+ methods.put(m[i].getName() + METHOD_TAG, m[i]);
}
- else
- // zero-parameter methods to be invoked on click
- if ( m[i].getParameterTypes().length == 0 )
- {
- properties.addElement( m[i].getName() + METHOD_TAG );
- methods.put( m[i].getName() + METHOD_TAG, m[i] );
- }
}
@@ -131,288 +118,259 @@ public class PropertyEditorTableModel extends AbstractTableModel implements Acti
}
public int getColumnCount() {
- return columnNames.length;
+ return columnNames.length;
}
public int getRowCount() {
- return properties.size();
+ return properties.size();
}
public String getColumnName(int col) {
- return columnNames[col];
+ return columnNames[col];
}
public Object getValueAt(int row, int col) {
- if ( col == 0 )
- return properties.elementAt( row );
- else
- {
+ if (col == 0)
+ return properties.elementAt(row);
+ else {
Method m = null;
- m = (Method) methods.get( "get" + ( (String) properties.elementAt( row ) ) ) ;
- if ( m == null ) // try "is"
- m = (Method) methods.get( "is" + ( (String) properties.elementAt( row ) ) ) ;
- if ( m == null ) { // try entire method name
- m = (Method) methods.get( (String) properties.elementAt( row ) ) ;
- if ( m != null ) return m;
- }
+ m = (Method) methods.get("get" + ((String) properties.elementAt(row)));
+ if (m == null) // try "is"
+ m = (Method) methods.get("is" + ((String) properties.elementAt(row)));
+ if (m == null) { // try entire method name
+ m = (Method) methods.get((String) properties.elementAt(row));
+ if (m != null)
+ return m;
+ }
try {
- return m.invoke( inspectedObject, (Object[])null );
- } catch ( Exception exc ) {
- System.out.println( "InspectorFrame.tableModel.getValueAt: error occured while reflecting: " );
- System.out.println( exc );
+ return m.invoke(inspectedObject, (Object[]) null);
+ } catch (Exception exc) {
+ System.out.println("InspectorFrame.tableModel.getValueAt: error occured while reflecting: ");
+ System.out.println(exc);
}
return null;
}
}
- public Class getColumnClass( int col ) {
+ public Class getColumnClass(int col) {
// System.out.println( "getColumnClass" );
-/* try {
- throw new Exception();
- } catch ( Exception exc ) {
- exc.printStackTrace( System.out );
- }
-*/ return new String().getClass();
+ /*
+ * try { throw new Exception(); } catch ( Exception exc ) { exc.printStackTrace(
+ * System.out ); }
+ */ return new String().getClass();
}
public Class getCellClass(int row, int col) {
// System.out.println( "getCellClass" );
-/*
-
- Class c;
- Method m = (Method) methods.get( "set" + ( (String) properties.elementAt( row ) ) ) ;
- if ( m == null )
- c = new Object().getClass();
- else {
- c = m.getParameterTypes()[0];
-
- // special case for boolean
- if ( c.getName().equals( "boolean" ) )
- c = new Boolean(true).getClass();
-
- // special case for int
- if ( c.getName().equals( "int" ) )
- c = new Integer(0).getClass();
- }
- System.out.println( row + ": " + c.getName() );
- return c;
-*/
+ /*
+ *
+ * Class c; Method m = (Method) methods.get( "set" + ( (String)
+ * properties.elementAt( row ) ) ) ; if ( m == null ) c = new
+ * Object().getClass(); else { c = m.getParameterTypes()[0];
+ *
+ * // special case for boolean if ( c.getName().equals( "boolean" ) ) c = new
+ * Boolean(true).getClass();
+ *
+ * // special case for int if ( c.getName().equals( "int" ) ) c = new
+ * Integer(0).getClass(); } System.out.println( row + ": " + c.getName() );
+ * return c;
+ */
// return new String().getClass();
- Object o = getValueAt( row, col );
- if ( o == null ) o = "null";
+ Object o = getValueAt(row, col);
+ if (o == null)
+ o = "null";
return o.getClass();
}
/*
- * Don't need to implement this method unless your table's
- * editable.
- */
+ * Don't need to implement this method unless your table's editable.
+ */
public boolean isCellEditable(int row, int col) {
- //Note that the data/cell address is constant,
- //no matter where the cell appears onscreen.
- if (col < 1) {
- return false;
- } else {
- // handle method invocation
- if ( ((String)properties.elementAt(row)).endsWith(METHOD_TAG) ) return true;
- // handle read-only properties
- Method m = (Method) methods.get( "set" + ( (String) properties.elementAt( row ) ) ) ;
- if ( m == null )
+ // Note that the data/cell address is constant,
+ // no matter where the cell appears onscreen.
+ if (col < 1) {
return false;
- else
- return true;
- }
+ } else {
+ // handle method invocation
+ if (((String) properties.elementAt(row)).endsWith(METHOD_TAG))
+ return true;
+ // handle read-only properties
+ Method m = (Method) methods.get("set" + ((String) properties.elementAt(row)));
+ if (m == null)
+ return false;
+ else
+ return true;
+ }
}
/*
- * Don't need to implement this method unless your table's
- * data can change.
- */
+ * Don't need to implement this method unless your table's data can change.
+ */
public void setValueAt(Object value, int row, int col) {
- // test for inspected object
- if ( inspectedObject == null ) return;
- // handle method invocation - no need to update values
- if ( ((String)properties.elementAt(row)).endsWith( METHOD_TAG ) )
- {
- fireTableDataChanged();
- return;
- };
-
- // handle writable properties
- Method m = (Method) methods.get( "set" + ( (String) properties.elementAt( row ) ) ) ;
+ // test for inspected object
+ if (inspectedObject == null)
+ return;
+ // handle method invocation - no need to update values
+ if (((String) properties.elementAt(row)).endsWith(METHOD_TAG)) {
+ fireTableDataChanged();
+ return;
+ }
+ ;
+
+ // handle writable properties
+ Method m = (Method) methods.get("set" + ((String) properties.elementAt(row)));
String parameterType = m.getParameterTypes()[0].getName();
// ugly cast code
- if (
- ( parameterType.equals( "int" ) )
- || ( parameterType.equals( "java.lang.Integer" ) )
- )
- {
- try {
- value = new Integer((String)value);
- } catch (NumberFormatException e) {
- System.out.println("PropertyEditorTableModel.setValueAt: User attempted to enter non-integer"
- + " value (" + value
- + ") into an integer-only column.");
- }
+ if ((parameterType.equals("int")) || (parameterType.equals("java.lang.Integer"))) {
+ try {
+ value = new Integer((String) value);
+ } catch (NumberFormatException e) {
+ System.out.println("PropertyEditorTableModel.setValueAt: User attempted to enter non-integer"
+ + " value (" + value + ") into an integer-only column.");
+ }
}
Object[] parameters = { value };
try {
- m.invoke( inspectedObject, parameters );
- if ( inspectedObject instanceof Component ) {
- Component c = (Component)inspectedObject;
- if ( c.getParent() != null )
+ m.invoke(inspectedObject, parameters);
+ if (inspectedObject instanceof Component) {
+ Component c = (Component) inspectedObject;
+ if (c.getParent() != null)
c.getParent().repaint();
}
- } catch ( Exception exc ) {
- System.out.println( "PropertyEditorTableModel.setValueAt: error occured while reflecting: " );
- System.out.println( exc );
+ } catch (Exception exc) {
+ System.out.println("PropertyEditorTableModel.setValueAt: error occured while reflecting: ");
+ System.out.println(exc);
}
fireTableDataChanged();
}
+ protected void sort(Vector v) {
+ quickSort(v, 0, v.size() - 1);
+ }
- protected void sort(Vector v){
- quickSort(v, 0, v.size()-1);
- }
-
-
- // Liberated from the BasicDirectoryModel which was...
- // Liberated from the 1.1 SortDemo
-
- // This is a generic version of C.A.R Hoare's Quick Sort
- // algorithm. This will handle arrays that are already
- // sorted, and arrays with duplicate keys.<BR>
- //
- // If you think of a one dimensional array as going from
- // the lowest index on the left to the highest index on the right
- // then the parameters to this function are lowest index or
- // left and highest index or right. The first time you call
- // this function it will be with the parameters 0, a.length - 1.
- //
- // @param a an integer array
- // @param lo0 left boundary of array partition
- // @param hi0 right boundary of array partition
- private void quickSort(Vector v, int lo0, int hi0) {
- int lo = lo0;
- int hi = hi0;
- String mid;
-
- if (hi0 > lo0) {
- // Arbitrarily establishing partition element as the midpoint of
- // the array.
- mid = (String) v.elementAt((lo0 + hi0) / 2);
-
- // loop through the array until indices cross
- while(lo <= hi) {
- // find the first element that is greater than or equal to
- // the partition element starting from the left Index.
- //
- // Nasty to have to cast here. Would it be quicker
- // to copy the vectors into arrays and sort the arrays?
- while((lo < hi0) && lt((String)v.elementAt(lo), mid)) {
- ++lo;
- }
+ // Liberated from the BasicDirectoryModel which was...
+ // Liberated from the 1.1 SortDemo
+
+ // This is a generic version of C.A.R Hoare's Quick Sort
+ // algorithm. This will handle arrays that are already
+ // sorted, and arrays with duplicate keys.<BR>
+ //
+ // If you think of a one dimensional array as going from
+ // the lowest index on the left to the highest index on the right
+ // then the parameters to this function are lowest index or
+ // left and highest index or right. The first time you call
+ // this function it will be with the parameters 0, a.length - 1.
+ //
+ // @param a an integer array
+ // @param lo0 left boundary of array partition
+ // @param hi0 right boundary of array partition
+ private void quickSort(Vector v, int lo0, int hi0) {
+ int lo = lo0;
+ int hi = hi0;
+ String mid;
+
+ if (hi0 > lo0) {
+ // Arbitrarily establishing partition element as the midpoint of
+ // the array.
+ mid = (String) v.elementAt((lo0 + hi0) / 2);
+
+ // loop through the array until indices cross
+ while (lo <= hi) {
+ // find the first element that is greater than or equal to
+ // the partition element starting from the left Index.
+ //
+ // Nasty to have to cast here. Would it be quicker
+ // to copy the vectors into arrays and sort the arrays?
+ while ((lo < hi0) && lt((String) v.elementAt(lo), mid)) {
+ ++lo;
+ }
+
+ // find an element that is smaller than or equal to
+ // the partition element starting from the right Index.
+ while ((hi > lo0) && lt(mid, (String) v.elementAt(hi))) {
+ --hi;
+ }
+
+ // if the indexes have not crossed, swap
+ if (lo <= hi) {
+ swap(v, lo, hi);
+ ++lo;
+ --hi;
+ }
+ }
+
+ // If the right index has not reached the left side of array
+ // must now sort the left partition.
+ if (lo0 < hi) {
+ quickSort(v, lo0, hi);
+ }
+
+ // If the left index has not reached the right side of array
+ // must now sort the right partition.
+ if (lo < hi0) {
+ quickSort(v, lo, hi0);
+ }
- // find an element that is smaller than or equal to
- // the partition element starting from the right Index.
- while((hi > lo0) && lt(mid, (String)v.elementAt(hi))) {
- --hi;
}
+ }
+
+ private void swap(Vector a, int i, int j) {
+ Object T = a.elementAt(i);
+ a.setElementAt(a.elementAt(j), i);
+ a.setElementAt(T, j);
+ }
+
+ protected boolean lt(String a, String b) {
+ return a.compareTo(b) < 0;
+ }
+
+ // automated updates
- // if the indexes have not crossed, swap
- if(lo <= hi) {
- swap(v, lo, hi);
- ++lo;
- --hi;
+ private boolean autoUpdating = false;
+ private int updateInterval = 2000; // one-second delay on average
+ protected Timer timer = null;
+
+ public boolean isAutoUpdating() {
+ return autoUpdating;
+ }
+
+ public void setAutoUpdating(boolean shouldAutoUpdate) {
+ if (shouldAutoUpdate) {
+ if (timer == null) {
+ timer = new Timer(updateInterval, this);
+ timer.setRepeats(true);
+ timer.start();
+ }
+ } else {
+ if (timer != null) {
+ timer.stop();
+ timer = null;
+ }
}
- }
+ autoUpdating = shouldAutoUpdate;
+ }
+
+ public int getUpdateInterval() {
+ return updateInterval;
+ }
- // If the right index has not reached the left side of array
- // must now sort the left partition.
- if(lo0 < hi) {
- quickSort(v, lo0, hi);
- }
+ public void setUpdateInterval(int anInterval) {
+ if (timer != null) {
+ timer.setDelay(anInterval);
+ }
- // If the left index has not reached the right side of array
- // must now sort the right partition.
- if(lo < hi0) {
- quickSort(v, lo, hi0);
- }
+ updateInterval = anInterval;
+ }
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource() == timer) {
+ fireTableDataChanged();
+ }
}
- }
-
- private void swap(Vector a, int i, int j) {
- Object T = a.elementAt(i);
- a.setElementAt(a.elementAt(j), i);
- a.setElementAt(T, j);
- }
-
- protected boolean lt(String a, String b) {
- return a.compareTo(b) < 0;
- }
-
- // automated updates
-
- private boolean autoUpdating = false;
- private int updateInterval = 2000; // one-second delay on average
- protected Timer timer = null;
-
- public boolean isAutoUpdating()
- {
- return autoUpdating;
- }
-
- public void setAutoUpdating( boolean shouldAutoUpdate )
- {
- if ( shouldAutoUpdate )
- {
- if ( timer == null )
- {
- timer = new Timer( updateInterval, this );
- timer.setRepeats( true );
- timer.start();
- }
- }
- else
- {
- if ( timer != null )
- {
- timer.stop();
- timer = null;
- }
- }
-
- autoUpdating = shouldAutoUpdate;
- }
-
- public int getUpdateInterval()
- {
- return updateInterval;
- }
-
- public void setUpdateInterval( int anInterval )
- {
- if ( timer != null )
- {
- timer.setDelay( anInterval );
- }
-
- updateInterval = anInterval;
- }
-
- public void actionPerformed( ActionEvent evt )
- {
- if ( evt.getSource() == timer )
- {
- fireTableDataChanged();
- }
- }
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/RadioButtonPanel.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/RadioButtonPanel.java
index 2956c71..62cbc2c 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/RadioButtonPanel.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/RadioButtonPanel.java
@@ -26,149 +26,139 @@ import javax.swing.JRadioButton;
import javax.swing.border.EmptyBorder;
/**
-* RadioButtonPanel is a simple extension of ButtonPanel.
-* Differences are that it uses radio buttons and the
-* default alignment is vertical. The radio buttons are
-* placed in a ButtonGroup and the panel defaults to having
-* no buttons selected.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-* $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) $
-*/
-public class RadioButtonPanel extends ButtonPanel
-{
-/**
-* A ButtonGroup to help manage button state.
-*/
- protected ButtonGroup buttonGroup;
-
-/**
-* ButtonGroup does not make it easy to unselect all buttons.
-* The preferred way to do it is actually to create a hidden button.
-*/
- protected JRadioButton hiddenButton;
-
-/**
-* Constructs a RadioButtonPanel. Three buttons are created
-* so the panel is filled when used in a GUI-builder environment.
-*/
- public RadioButtonPanel()
- {
- super();
- }
-
-/**
-* Constructs a ButtonPanel using specified buttons.
-* @param buttonList An array containing the strings to be used in labeling the buttons.
-*/
- public RadioButtonPanel( String[] buttonList )
- {
- super( buttonList );
- }
-
-/**
-* Overridden to set vertical-center alignment and 2-pixel vgap.
-*/
- protected void initLayout()
- {
- super.initLayout();
- buttonPanelLayout.setAlignment( BetterFlowLayout.CENTER_VERTICAL );
- buttonPanelLayout.setVgap( 2 ); // looks nicer than java l&f recommendation (imho)
- }
-
-/**
-* Overridden to return a JRadioButton.
-* @param aLabel The label for the component that will be created.
-* @return The newly created component.
-*/
- protected Component createComponentWithLabel( String aLabel )
- {
- String buttonLabel = aLabel;
- JRadioButton newButton = new JRadioButton();
- newButton.setName( aLabel );
- newButton.setText( buttonLabel );
- newButton.setActionCommand( aLabel );
- newButton.addActionListener( this );
-
- // reduce insets per java l&f guidelines (was 4 on each side)
- newButton.setBorder( new EmptyBorder( 0, 4, 0, 4 ) );
-
- if ( buttonGroup == null )
- {
- buttonGroup = new ButtonGroup();
-
- // cheesy hack to allow a buttongroup to have no items selected.
- // note that the button is not added to container or buttonList.
- hiddenButton = new JRadioButton( "Hidden Button" );
- buttonGroup.add( hiddenButton );
- }
- buttonGroup.add( newButton );
-
- return newButton;
- }
-
-/**
-* Selects the button whose name matches the given text value.
-* @param newText A String matching the name of one of the buttons.
-* If null, empty, or not matching, all buttons are deselected.
-*/
- public void setValue(String aName)
- {
- if ( aName != null )
- {
- Component c = null;
- int count = buttonContainer.getComponentCount();
- for ( int i = 0; i < count; i++ )
- {
- c = buttonContainer.getComponent( i );
- if ( c instanceof AbstractButton )
- {
- if ( c.getName().equals( aName ) )
- {
- ((AbstractButton)c).setSelected( true );
- return;
- }
- }
- }
- }
-
- // null, empty, or not matching - deselect all
- hiddenButton.setSelected( true );
- }
-
-/**
-* Gets the name of the currently selected button.
-* @return A string matching the name of the currently selected button,
-* or null of no button is selected.
-*/
- public String getValue()
- {
- String result = null;
- Component c = null;
- int count = buttonContainer.getComponentCount();
- for ( int i = 0; i < count; i++ )
- {
- c = buttonContainer.getComponent( i );
- if ( ( c instanceof AbstractButton ) && ( ((AbstractButton)c).isSelected() ) )
- {
- return c.getName();
- }
- }
- return result;
- }
-
-/**
-* Tests whether the specified value is checked.
-* @param aValue A value to be tested.
-* @return True if the specified value is checked, otherwise false.
-*/
- public boolean getValue( String aValue )
- {
- if ( aValue == null ) return false;
- return aValue.equals( getValue() );
- }
+ * RadioButtonPanel is a simple extension of ButtonPanel. Differences are that
+ * it uses radio buttons and the default alignment is vertical. The radio
+ * buttons are placed in a ButtonGroup and the panel defaults to having no
+ * buttons selected.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006)
+ * $
+ */
+public class RadioButtonPanel extends ButtonPanel {
+ /**
+ * A ButtonGroup to help manage button state.
+ */
+ protected ButtonGroup buttonGroup;
+
+ /**
+ * ButtonGroup does not make it easy to unselect all buttons. The preferred way
+ * to do it is actually to create a hidden button.
+ */
+ protected JRadioButton hiddenButton;
+
+ /**
+ * Constructs a RadioButtonPanel. Three buttons are created so the panel is
+ * filled when used in a GUI-builder environment.
+ */
+ public RadioButtonPanel() {
+ super();
+ }
+
+ /**
+ * Constructs a ButtonPanel using specified buttons.
+ *
+ * @param buttonList An array containing the strings to be used in labeling the
+ * buttons.
+ */
+ public RadioButtonPanel(String[] buttonList) {
+ super(buttonList);
+ }
+
+ /**
+ * Overridden to set vertical-center alignment and 2-pixel vgap.
+ */
+ protected void initLayout() {
+ super.initLayout();
+ buttonPanelLayout.setAlignment(BetterFlowLayout.CENTER_VERTICAL);
+ buttonPanelLayout.setVgap(2); // looks nicer than java l&f recommendation (imho)
+ }
+
+ /**
+ * Overridden to return a JRadioButton.
+ *
+ * @param aLabel The label for the component that will be created.
+ * @return The newly created component.
+ */
+ protected Component createComponentWithLabel(String aLabel) {
+ String buttonLabel = aLabel;
+ JRadioButton newButton = new JRadioButton();
+ newButton.setName(aLabel);
+ newButton.setText(buttonLabel);
+ newButton.setActionCommand(aLabel);
+ newButton.addActionListener(this);
+
+ // reduce insets per java l&f guidelines (was 4 on each side)
+ newButton.setBorder(new EmptyBorder(0, 4, 0, 4));
+
+ if (buttonGroup == null) {
+ buttonGroup = new ButtonGroup();
+
+ // cheesy hack to allow a buttongroup to have no items selected.
+ // note that the button is not added to container or buttonList.
+ hiddenButton = new JRadioButton("Hidden Button");
+ buttonGroup.add(hiddenButton);
+ }
+ buttonGroup.add(newButton);
+
+ return newButton;
+ }
+
+ /**
+ * Selects the button whose name matches the given text value.
+ *
+ * @param newText A String matching the name of one of the buttons. If null,
+ * empty, or not matching, all buttons are deselected.
+ */
+ public void setValue(String aName) {
+ if (aName != null) {
+ Component c = null;
+ int count = buttonContainer.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ c = buttonContainer.getComponent(i);
+ if (c instanceof AbstractButton) {
+ if (c.getName().equals(aName)) {
+ ((AbstractButton) c).setSelected(true);
+ return;
+ }
+ }
+ }
+ }
+
+ // null, empty, or not matching - deselect all
+ hiddenButton.setSelected(true);
+ }
+
+ /**
+ * Gets the name of the currently selected button.
+ *
+ * @return A string matching the name of the currently selected button, or null
+ * of no button is selected.
+ */
+ public String getValue() {
+ String result = null;
+ Component c = null;
+ int count = buttonContainer.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ c = buttonContainer.getComponent(i);
+ if ((c instanceof AbstractButton) && (((AbstractButton) c).isSelected())) {
+ return c.getName();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Tests whether the specified value is checked.
+ *
+ * @param aValue A value to be tested.
+ * @return True if the specified value is checked, otherwise false.
+ */
+ public boolean getValue(String aValue) {
+ if (aValue == null)
+ return false;
+ return aValue.equals(getValue());
+ }
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartPasswordField.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartPasswordField.java
index 6914cf6..55ba2f7 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartPasswordField.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartPasswordField.java
@@ -26,249 +26,227 @@ import java.awt.event.KeyEvent;
import javax.swing.JPasswordField;
/**
- * SmartPasswordField is an extention of JPasswordField. It does everything
- * a JPassword does, as well as limit the number of characters. The user
- * of this class can specify that a password can only have a maximum of
- * 10 characters for instance.
+ * SmartPasswordField is an extention of JPasswordField. It does everything a
+ * JPassword does, as well as limit the number of characters. The user of this
+ * class can specify that a password can only have a maximum of 10 characters
+ * for instance.
*
* @author rob@straylight.princeton.com
* @author $Author: cgruber $
* @version $Revision: 904 $
*/
-public class SmartPasswordField extends JPasswordField
-{
-
-/*******************************
-* CONSTANTS
-*******************************/
- private static final int BACKSPACE = 8;
- private static final int DELETE = 127;
- private static final int SPACE = 32;
- private static final int DASH = 45;
- private static final int UNDERSCORE = 95;
- private static final int PERIOD = 46;
- private static final int PASTE = 22; // Ctl-V
-
- private int passwordLength = Integer.MAX_VALUE;
-
-/*******************************
-* PUBLIC METHODS
-*******************************/
-
-/**
-* Default constructor.
-*/
- public SmartPasswordField()
- {
- super();
- }
-
-/**
-* This constructor allows the user to set the maximum length of the password.
-* @param aLength The maximum length of the password.
-*/
- public SmartPasswordField( int aLength )
- {
- this();
- setPasswordLength( aLength );
- }
-
-/**
-* Sets the maximum lenght of the password. The value must be 0 or greater.
-* If the length specified is less than 0, then no action occurs.
-* @param aLength The maximum lenght of the password.
-*/
- public void setPasswordLength( int aLength )
- {
- if ( aLength >= 0 )
- {
- passwordLength = aLength;
- }
- }
-
-/**
-* Returns the current maximum length of the password.
-* @return The current maximum length of the password.
-*/
- public int getPasswordLength()
- {
- return passwordLength;
- }
-
-/**
-* This method processes a key event. This event is generated by input from the
-* keyboard when this text field has the focus. This method is called for every
-* key that is pressed and released on the keyboard. This includes modifier
-* keys like the shift and alt keys. This class looks at the key and determines
-* if the key is valid input given the restrictions of this class. <BR> <BR>
-* @param e A key event generated by a keyboard action.
-*/
- public void processKeyEvent(KeyEvent e)
- {
- String currentText = "";
- String testString = "";
- char newChar = e.getKeyChar();
- int currentLength = 0;
- int selectionStart = 0;
- int selectionEnd = 0;
- int endOfHead = 0;
- int startOfTail = 0;
- boolean backspace = false;
- boolean delete = false;
- boolean paste = false;
- boolean insertionPoint = false;
- boolean selectionAtStart = false;
- boolean selectionAtEnd = false;
-
- backspace = (newChar == BACKSPACE);
- delete = (newChar == DELETE);
- paste = (newChar == PASTE);
-
- if ((e.getKeyCode() == KeyEvent.VK_UNDEFINED) || ((backspace) || (delete) || (paste))) // A "key-typed" event
- {
- if (isValidCharacter(newChar))
- {
-
- if ((isPrintableCharacter(newChar)) || (backspace) || (delete) || (paste))
- {
- // Analyze the current contents of the field
- currentText = new String( getPassword() );
- currentLength = currentText.length();
-
- selectionStart = getSelectionStart();
- selectionEnd = getSelectionEnd();
-
- insertionPoint = (selectionStart == selectionEnd);
- selectionAtStart = (selectionStart == 0);
- selectionAtEnd = (selectionEnd >= currentLength);
- if (selectionEnd > currentLength)
- {
- setSelectionEnd(currentLength);
- }
-
- // Generate new string
- if (selectionStart > 0) // Create head of test string
- {
- endOfHead = selectionStart;
- if (insertionPoint && backspace)
- {
- endOfHead -= 1;
- }
- testString += currentText.substring(0, endOfHead);
- }
-
- if (!(backspace || delete || paste)) // Add the new character
- {
- testString += newChar;
- }
-
- if (paste) // Add the string from the clipboard
- {
- Transferable data = getToolkit().getSystemClipboard().getContents(this);
- if (data != null)
- {
- try
- {
- String clipString = (String)data.getTransferData(DataFlavor.stringFlavor);
- testString += clipString;
- }
- catch (java.io.IOException ioe)
- {
- // Do nothing
- }
- catch (UnsupportedFlavorException ufe)
- {
- // Do nothing
- }
- }
- }
-
- if (selectionEnd < currentLength) // Add the tail of the string
- {
- startOfTail = selectionEnd;
- if (insertionPoint && delete)
- {
- startOfTail += 1;
- }
- testString += currentText.substring(startOfTail);
- }
-
- }
-
- if (testString.compareTo("") != 0) // Null string is OK
- {
- if (!(isValidString(testString)))
- {
- e.consume();
- }
- }
- }
- else
- {
- e.consume();
- }
- }
- super.processKeyEvent(e);
-
- postProcessing();
- }
-
-
-/*******************************
-* PROTECTED METHODS
-*******************************/
-
-/**
-* Returns whether the inputted character is valid or not. In this case all
-* characters are valid input.
-* @param aChar A character to perform the validity test with.
-* @return True if the character is valid for this subclassed text field. <BR>
-* False is the character is not valid.
-*/
- protected boolean isValidCharacter(char aChar)
- {
- return true;
- }
-
-/**
-* Returns whether a string is valid for this text field. As the user types from
-* the keyboard, this method is called to determine if the new string in the text
-* field is valid based upon the restriction of this class. The length of the
-* new string is checked against the maximum password length.
-* @param aString The string to perform the validity check with.
-* @return True if the length of the string is less than or equal to the maximum length.
-* False if the character is not valud.
-*/
- protected boolean isValidString(String aString)
- {
- if ( aString.length() > passwordLength )
- {
- return false;
- }
-
- return true;
- }
-
-/**
-* This class does not need any post processing.
-*/
- protected void postProcessing()
- {
- /* Do Nothing */
- }
-
-
-/*******************************
-* PRIVATE METHODS
-*******************************/
-
- private boolean isPrintableCharacter(char inputChar)
- {
- if ((inputChar >= ' ') && (inputChar <= '~'))
- {
- return true;
- }
- return false;
- }
+public class SmartPasswordField extends JPasswordField {
+
+ /*******************************
+ * CONSTANTS
+ *******************************/
+ private static final int BACKSPACE = 8;
+ private static final int DELETE = 127;
+ private static final int SPACE = 32;
+ private static final int DASH = 45;
+ private static final int UNDERSCORE = 95;
+ private static final int PERIOD = 46;
+ private static final int PASTE = 22; // Ctl-V
+
+ private int passwordLength = Integer.MAX_VALUE;
+
+ /*******************************
+ * PUBLIC METHODS
+ *******************************/
+
+ /**
+ * Default constructor.
+ */
+ public SmartPasswordField() {
+ super();
+ }
+
+ /**
+ * This constructor allows the user to set the maximum length of the password.
+ *
+ * @param aLength The maximum length of the password.
+ */
+ public SmartPasswordField(int aLength) {
+ this();
+ setPasswordLength(aLength);
+ }
+
+ /**
+ * Sets the maximum lenght of the password. The value must be 0 or greater. If
+ * the length specified is less than 0, then no action occurs.
+ *
+ * @param aLength The maximum lenght of the password.
+ */
+ public void setPasswordLength(int aLength) {
+ if (aLength >= 0) {
+ passwordLength = aLength;
+ }
+ }
+
+ /**
+ * Returns the current maximum length of the password.
+ *
+ * @return The current maximum length of the password.
+ */
+ public int getPasswordLength() {
+ return passwordLength;
+ }
+
+ /**
+ * This method processes a key event. This event is generated by input from the
+ * keyboard when this text field has the focus. This method is called for every
+ * key that is pressed and released on the keyboard. This includes modifier keys
+ * like the shift and alt keys. This class looks at the key and determines if
+ * the key is valid input given the restrictions of this class. <BR>
+ * <BR>
+ *
+ * @param e A key event generated by a keyboard action.
+ */
+ public void processKeyEvent(KeyEvent e) {
+ String currentText = "";
+ String testString = "";
+ char newChar = e.getKeyChar();
+ int currentLength = 0;
+ int selectionStart = 0;
+ int selectionEnd = 0;
+ int endOfHead = 0;
+ int startOfTail = 0;
+ boolean backspace = false;
+ boolean delete = false;
+ boolean paste = false;
+ boolean insertionPoint = false;
+ boolean selectionAtStart = false;
+ boolean selectionAtEnd = false;
+
+ backspace = (newChar == BACKSPACE);
+ delete = (newChar == DELETE);
+ paste = (newChar == PASTE);
+
+ if ((e.getKeyCode() == KeyEvent.VK_UNDEFINED) || ((backspace) || (delete) || (paste))) // A "key-typed" event
+ {
+ if (isValidCharacter(newChar)) {
+
+ if ((isPrintableCharacter(newChar)) || (backspace) || (delete) || (paste)) {
+ // Analyze the current contents of the field
+ currentText = new String(getPassword());
+ currentLength = currentText.length();
+
+ selectionStart = getSelectionStart();
+ selectionEnd = getSelectionEnd();
+
+ insertionPoint = (selectionStart == selectionEnd);
+ selectionAtStart = (selectionStart == 0);
+ selectionAtEnd = (selectionEnd >= currentLength);
+ if (selectionEnd > currentLength) {
+ setSelectionEnd(currentLength);
+ }
+
+ // Generate new string
+ if (selectionStart > 0) // Create head of test string
+ {
+ endOfHead = selectionStart;
+ if (insertionPoint && backspace) {
+ endOfHead -= 1;
+ }
+ testString += currentText.substring(0, endOfHead);
+ }
+
+ if (!(backspace || delete || paste)) // Add the new character
+ {
+ testString += newChar;
+ }
+
+ if (paste) // Add the string from the clipboard
+ {
+ Transferable data = getToolkit().getSystemClipboard().getContents(this);
+ if (data != null) {
+ try {
+ String clipString = (String) data.getTransferData(DataFlavor.stringFlavor);
+ testString += clipString;
+ } catch (java.io.IOException ioe) {
+ // Do nothing
+ } catch (UnsupportedFlavorException ufe) {
+ // Do nothing
+ }
+ }
+ }
+
+ if (selectionEnd < currentLength) // Add the tail of the string
+ {
+ startOfTail = selectionEnd;
+ if (insertionPoint && delete) {
+ startOfTail += 1;
+ }
+ testString += currentText.substring(startOfTail);
+ }
+
+ }
+
+ if (testString.compareTo("") != 0) // Null string is OK
+ {
+ if (!(isValidString(testString))) {
+ e.consume();
+ }
+ }
+ } else {
+ e.consume();
+ }
+ }
+ super.processKeyEvent(e);
+
+ postProcessing();
+ }
+
+ /*******************************
+ * PROTECTED METHODS
+ *******************************/
+
+ /**
+ * Returns whether the inputted character is valid or not. In this case all
+ * characters are valid input.
+ *
+ * @param aChar A character to perform the validity test with.
+ * @return True if the character is valid for this subclassed text field. <BR>
+ * False is the character is not valid.
+ */
+ protected boolean isValidCharacter(char aChar) {
+ return true;
+ }
+
+ /**
+ * Returns whether a string is valid for this text field. As the user types from
+ * the keyboard, this method is called to determine if the new string in the
+ * text field is valid based upon the restriction of this class. The length of
+ * the new string is checked against the maximum password length.
+ *
+ * @param aString The string to perform the validity check with.
+ * @return True if the length of the string is less than or equal to the maximum
+ * length. False if the character is not valud.
+ */
+ protected boolean isValidString(String aString) {
+ if (aString.length() > passwordLength) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * This class does not need any post processing.
+ */
+ protected void postProcessing() {
+ /* Do Nothing */
+ }
+
+ /*******************************
+ * PRIVATE METHODS
+ *******************************/
+
+ private boolean isPrintableCharacter(char inputChar) {
+ if ((inputChar >= ' ') && (inputChar <= '~')) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartTextField.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartTextField.java
index cee37e1..5092179 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartTextField.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/SmartTextField.java
@@ -27,218 +27,204 @@ import javax.swing.JTextField;
/**
* SmartTextField is an abstract class for that allows the text field to
- * intelligently analyze the user's input in real-time. As the user enters
+ * intelligently analyze the user's input in real-time. As the user enters
* keystrokes, the generated string is analyzed to determine if the new string
* is valid based on the criteria of the concrete classes that extend this
- * class. An invalid keystroke is rejected and not displayed in the text
- * field. This class can be extended to to create smart text fields that only
- * accept integers or floating points number or alphabetic strings of maximum
- * length. These are several examples.
+ * class. An invalid keystroke is rejected and not displayed in the text field.
+ * This class can be extended to to create smart text fields that only accept
+ * integers or floating points number or alphabetic strings of maximum length.
+ * These are several examples.
*
* @author rob@straylight.princeton.com
* @author $Author: cgruber $
* @version $Revision: 904 $
*/
-public abstract class SmartTextField extends JTextField
-{
-
-/*******************************
-* CONSTANTS
-*******************************/
- private static final int BACKSPACE = 8;
- private static final int DELETE = 127;
- private static final int SPACE = 32;
- private static final int DASH = 45;
- private static final int UNDERSCORE = 95;
- private static final int PERIOD = 46;
- private static final int PASTE = 22; // Ctl-V
-
-
-/*******************************
-* PUBLIC METHODS
-*******************************/
-
-/**
-* This method processes a key event. This event is generated by input from the
-* keyboard when this text field has the focus. This method is called for every
-* key that is pressed and released on the keyboard. This includes modifier
-* keys like the shift and alt keys. This class looks at the key and determines
-* if the key is valid input given the restrictions of the concrete sub-classes. <BR> <BR>
-* Example - A smart text field only allows alphabetic characters. If the key
-* pressed is a "2" then this method will determine that the key is invalid and
-* "consume" the key event. <BR> <BR>
-* Note - Every printable character has a "TYPED" key event. Currentlt under
-* Java 1.2.1 this does not happen. Bug 4186905 relating this bug has been
-* fixed and is awaiting release.
-* @param e A key event generated by a keyboard action.
-*/
- public void processKeyEvent(KeyEvent e)
- {
- String currentText = "";
- String testString = "";
- char newChar = e.getKeyChar();
- int currentLength = 0;
- int selectionStart = 0;
- int selectionEnd = 0;
- int endOfHead = 0;
- int startOfTail = 0;
- boolean backspace = false;
- boolean delete = false;
- boolean paste = false;
- boolean insertionPoint = false;
- boolean selectionAtStart = false;
- boolean selectionAtEnd = false;
-
- backspace = (newChar == BACKSPACE);
- delete = (newChar == DELETE);
- paste = (newChar == PASTE);
-
- if ((e.getKeyCode() == KeyEvent.VK_UNDEFINED) || ((backspace) || (delete) || (paste))) // A "key-typed" event
- {
- if (isValidCharacter(newChar))
- {
-
- if ((isPrintableCharacter(newChar)) || (backspace) || (delete) || (paste))
- {
- // Analyze the current contents of the field
- currentText = getText();
- currentLength = currentText.length();
-
- selectionStart = getSelectionStart();
- selectionEnd = getSelectionEnd();
-
- insertionPoint = (selectionStart == selectionEnd);
- selectionAtStart = (selectionStart == 0);
- selectionAtEnd = (selectionEnd >= currentLength);
- if (selectionEnd > currentLength)
- {
- setSelectionEnd(currentLength);
- }
-
- // Generate new string
- if (selectionStart > 0) // Create head of test string
- {
- endOfHead = selectionStart;
- if (insertionPoint && backspace)
- {
- endOfHead -= 1;
- }
- testString += currentText.substring(0, endOfHead);
- }
-
- if (!(backspace || delete || paste)) // Add the new character
- {
- testString += newChar;
- }
-
- if (paste) // Add the string from the clipboard
- {
- Transferable data = getToolkit().getSystemClipboard().getContents(this);
- if (data != null)
- {
- try
- {
- String clipString = (String)data.getTransferData(DataFlavor.stringFlavor);
- testString += clipString;
- }
- catch (java.io.IOException ioe)
- {
- // Do nothing
- }
- catch (UnsupportedFlavorException ufe)
- {
- // Do nothing
- }
- }
- }
-
- if (selectionEnd < currentLength) // Add the tail of the string
- {
- startOfTail = selectionEnd;
- if (insertionPoint && delete)
- {
- startOfTail += 1;
- }
- testString += currentText.substring(startOfTail);
- }
-
- }
-
- if (testString.compareTo("") != 0) // Null string is OK
- {
- if (!(isValidString(testString)))
- {
- e.consume();
- }
- }
- }
- else
- {
- e.consume();
- }
- }
- super.processKeyEvent(e);
-
- postProcessing();
- }
-
-
-/*******************************
-* PROTECTED METHODS
-*******************************/
-
-/**
-* Default constructor for this class. The initial text of the smart text field
-* can be specified as well as the size (in characters) of the text field.
-* @param text The initial string that is displayed in the text field.
-* @param columns THe width of the text field in characters.
-*/
- protected SmartTextField(String text, int columns)
- {
- super(text, columns);
- }
-
-/**
-* Returns whether a character is valid for this text field. As the user types
-* from the keyboard, this method is called to determine if the character is a
-* valid character based in the restrictions of the subclass.
-* @param aChar A character to perform the validity test with.
-* @return True if the character is valid for this subclassed text field. <BR>
-* False is the character is not valid.
-*/
- abstract protected boolean isValidCharacter(char aChar);
-
-/**
-* Returns whether a string is valid for this text field. As the user types from
-* the keyboard, this method is called to determine if the new string in the text
-* field is valid based upon the restriction of the subclass. This is done after
-* the character has been determined to be valid since there can be restrictions
-* placed on the text string as a whole, such a maximum length or date format.
-* @param aString The string to perform the validity check with.
-* @return True if the string is valid for this subclassed text field. <BR>
-* False if the character is not valud.
-*/
- abstract protected boolean isValidString(String aString);
-
-/**
-* This method is used by the any subclass that need to complete any processing
-* of the text string in the text field after all the requirement checks have
-* been performed.
-*/
- abstract protected void postProcessing();
-
-
-/*******************************
-* PRIVATE METHODS
-*******************************/
-
- private boolean isPrintableCharacter(char inputChar)
- {
- if ((inputChar >= ' ') && (inputChar <= '~'))
- {
- return true;
- }
- return false;
- }
+public abstract class SmartTextField extends JTextField {
+
+ /*******************************
+ * CONSTANTS
+ *******************************/
+ private static final int BACKSPACE = 8;
+ private static final int DELETE = 127;
+ private static final int SPACE = 32;
+ private static final int DASH = 45;
+ private static final int UNDERSCORE = 95;
+ private static final int PERIOD = 46;
+ private static final int PASTE = 22; // Ctl-V
+
+ /*******************************
+ * PUBLIC METHODS
+ *******************************/
+
+ /**
+ * This method processes a key event. This event is generated by input from the
+ * keyboard when this text field has the focus. This method is called for every
+ * key that is pressed and released on the keyboard. This includes modifier keys
+ * like the shift and alt keys. This class looks at the key and determines if
+ * the key is valid input given the restrictions of the concrete sub-classes.
+ * <BR>
+ * <BR>
+ * Example - A smart text field only allows alphabetic characters. If the key
+ * pressed is a "2" then this method will determine that the key is invalid and
+ * "consume" the key event. <BR>
+ * <BR>
+ * Note - Every printable character has a "TYPED" key event. Currentlt under
+ * Java 1.2.1 this does not happen. Bug 4186905 relating this bug has been fixed
+ * and is awaiting release.
+ *
+ * @param e A key event generated by a keyboard action.
+ */
+ public void processKeyEvent(KeyEvent e) {
+ String currentText = "";
+ String testString = "";
+ char newChar = e.getKeyChar();
+ int currentLength = 0;
+ int selectionStart = 0;
+ int selectionEnd = 0;
+ int endOfHead = 0;
+ int startOfTail = 0;
+ boolean backspace = false;
+ boolean delete = false;
+ boolean paste = false;
+ boolean insertionPoint = false;
+ boolean selectionAtStart = false;
+ boolean selectionAtEnd = false;
+
+ backspace = (newChar == BACKSPACE);
+ delete = (newChar == DELETE);
+ paste = (newChar == PASTE);
+
+ if ((e.getKeyCode() == KeyEvent.VK_UNDEFINED) || ((backspace) || (delete) || (paste))) // A "key-typed" event
+ {
+ if (isValidCharacter(newChar)) {
+
+ if ((isPrintableCharacter(newChar)) || (backspace) || (delete) || (paste)) {
+ // Analyze the current contents of the field
+ currentText = getText();
+ currentLength = currentText.length();
+
+ selectionStart = getSelectionStart();
+ selectionEnd = getSelectionEnd();
+
+ insertionPoint = (selectionStart == selectionEnd);
+ selectionAtStart = (selectionStart == 0);
+ selectionAtEnd = (selectionEnd >= currentLength);
+ if (selectionEnd > currentLength) {
+ setSelectionEnd(currentLength);
+ }
+
+ // Generate new string
+ if (selectionStart > 0) // Create head of test string
+ {
+ endOfHead = selectionStart;
+ if (insertionPoint && backspace) {
+ endOfHead -= 1;
+ }
+ testString += currentText.substring(0, endOfHead);
+ }
+
+ if (!(backspace || delete || paste)) // Add the new character
+ {
+ testString += newChar;
+ }
+
+ if (paste) // Add the string from the clipboard
+ {
+ Transferable data = getToolkit().getSystemClipboard().getContents(this);
+ if (data != null) {
+ try {
+ String clipString = (String) data.getTransferData(DataFlavor.stringFlavor);
+ testString += clipString;
+ } catch (java.io.IOException ioe) {
+ // Do nothing
+ } catch (UnsupportedFlavorException ufe) {
+ // Do nothing
+ }
+ }
+ }
+
+ if (selectionEnd < currentLength) // Add the tail of the string
+ {
+ startOfTail = selectionEnd;
+ if (insertionPoint && delete) {
+ startOfTail += 1;
+ }
+ testString += currentText.substring(startOfTail);
+ }
+
+ }
+
+ if (testString.compareTo("") != 0) // Null string is OK
+ {
+ if (!(isValidString(testString))) {
+ e.consume();
+ }
+ }
+ } else {
+ e.consume();
+ }
+ }
+ super.processKeyEvent(e);
+
+ postProcessing();
+ }
+
+ /*******************************
+ * PROTECTED METHODS
+ *******************************/
+
+ /**
+ * Default constructor for this class. The initial text of the smart text field
+ * can be specified as well as the size (in characters) of the text field.
+ *
+ * @param text The initial string that is displayed in the text field.
+ * @param columns THe width of the text field in characters.
+ */
+ protected SmartTextField(String text, int columns) {
+ super(text, columns);
+ }
+
+ /**
+ * Returns whether a character is valid for this text field. As the user types
+ * from the keyboard, this method is called to determine if the character is a
+ * valid character based in the restrictions of the subclass.
+ *
+ * @param aChar A character to perform the validity test with.
+ * @return True if the character is valid for this subclassed text field. <BR>
+ * False is the character is not valid.
+ */
+ abstract protected boolean isValidCharacter(char aChar);
+
+ /**
+ * Returns whether a string is valid for this text field. As the user types from
+ * the keyboard, this method is called to determine if the new string in the
+ * text field is valid based upon the restriction of the subclass. This is done
+ * after the character has been determined to be valid since there can be
+ * restrictions placed on the text string as a whole, such a maximum length or
+ * date format.
+ *
+ * @param aString The string to perform the validity check with.
+ * @return True if the string is valid for this subclassed text field. <BR>
+ * False if the character is not valud.
+ */
+ abstract protected boolean isValidString(String aString);
+
+ /**
+ * This method is used by the any subclass that need to complete any processing
+ * of the text string in the text field after all the requirement checks have
+ * been performed.
+ */
+ abstract protected void postProcessing();
+
+ /*******************************
+ * PRIVATE METHODS
+ *******************************/
+
+ private boolean isPrintableCharacter(char inputChar) {
+ if ((inputChar >= ' ') && (inputChar <= '~')) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/StatusButtonPanel.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/StatusButtonPanel.java
index 3d9a85b..ba9f361 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/StatusButtonPanel.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/StatusButtonPanel.java
@@ -34,243 +34,228 @@ import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
/**
-* StatusButtonPanel extends ButtonPanel to provide a space
-* to display status messages in a consistent manner.<BR><BR>
-* Messages are erased after a certain predefined interval,
-* defaulting to 10 seconds.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class StatusButtonPanel extends ButtonPanel
-{
-/**
-* This is the action command to all listeners when the status text is changed.
-*/
- public static final String STATUS_CHANGED = "STATUS_CHANGED";
-
- // note: weirdness happens if you initialize
- // this variable. Because it is set by initLayout
- // and initLayout is called by the superclass constructor,
- // this variable would get initialized after initLayout
- // is called...
- protected Component statusComponent; // = null;
-
- protected Timer timer = null;
- protected int interval = 10000; // adjust as needed
-
-/**
-* Constructs a StatusButtonPanel. Three buttons are created
-* so the panel is filled when used in a GUI-builder environment.
-*/
- public StatusButtonPanel()
- {
- super();
- setupTimer();
- }
-
-/**
-* Constructs a StatusButtonPanel using specified buttons.
-* @param buttonList An array containing the strings to be used in labeling the buttons.
-*/
- public StatusButtonPanel( String[] buttonList )
- {
- super( buttonList );
- setupTimer();
- }
-
-/**
-* Initializes the timer instance variable.
-*/
- protected void setupTimer()
- {
- timer = new Timer( interval, this );
- timer.addActionListener( this );
- timer.setRepeats( false );
- timer.start();
- }
-
-/**
-* Returns the number of milliseconds before the status message is cleared.
-* The default is 10000.
-* @return The current delay interval in milliseconds.
-*/
- public int getDelayInterval()
- {
- return interval;
- }
-
-/**
-* Sets the number of milliseconds before the status message is cleared.
-* @param millis The new delay interval in milliseconds.
-*/
- public void setDelayInterval( int millis )
- {
- interval = millis;
- timer.setDelay( interval );
- }
-
-/**
-* Returns the visual component used to display the status.
-* @return A component used for displaying status.
-*/
- public Component getStatusComponent()
- {
- return statusComponent;
-
- }
-/**
-* Receives ActionEvents from the internal timer.
-* @param e The action event in question.
-*/
- public void actionPerformed(ActionEvent e)
- {
- if ( e.getSource() == timer )
- {
- setText( "" );
- return;
- }
-
- // otherwise continue with superclass implementation
- super.actionPerformed( e );
- }
-
-/**
-* This method is responsible for the initial layout of the panel.
-* Subclasses can implement different layouts, but this method
-* is responsible for initializing buttonPanelLayout to a valid
-* layout manager and setting this panel to use it. This method
-* must should initialize statusComponent to a component that ideally
-* has get/setText methods, although this is not required.
-*/
- protected void initLayout()
- {
-
- statusComponent = new JTextField();
- JTextField textField = (JTextField) statusComponent;
- textField.setColumns( 20 );
- textField.setBackground( getBackground() );
- textField.setEditable( false );
+ * StatusButtonPanel extends ButtonPanel to provide a space to display status
+ * messages in a consistent manner.<BR>
+ * <BR>
+ * Messages are erased after a certain predefined interval, defaulting to 10
+ * seconds.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class StatusButtonPanel extends ButtonPanel {
+ /**
+ * This is the action command to all listeners when the status text is changed.
+ */
+ public static final String STATUS_CHANGED = "STATUS_CHANGED";
+
+ // note: weirdness happens if you initialize
+ // this variable. Because it is set by initLayout
+ // and initLayout is called by the superclass constructor,
+ // this variable would get initialized after initLayout
+ // is called...
+ protected Component statusComponent; // = null;
+
+ protected Timer timer = null;
+ protected int interval = 10000; // adjust as needed
+
+ /**
+ * Constructs a StatusButtonPanel. Three buttons are created so the panel is
+ * filled when used in a GUI-builder environment.
+ */
+ public StatusButtonPanel() {
+ super();
+ setupTimer();
+ }
+
+ /**
+ * Constructs a StatusButtonPanel using specified buttons.
+ *
+ * @param buttonList An array containing the strings to be used in labeling the
+ * buttons.
+ */
+ public StatusButtonPanel(String[] buttonList) {
+ super(buttonList);
+ setupTimer();
+ }
+
+ /**
+ * Initializes the timer instance variable.
+ */
+ protected void setupTimer() {
+ timer = new Timer(interval, this);
+ timer.addActionListener(this);
+ timer.setRepeats(false);
+ timer.start();
+ }
+
+ /**
+ * Returns the number of milliseconds before the status message is cleared. The
+ * default is 10000.
+ *
+ * @return The current delay interval in milliseconds.
+ */
+ public int getDelayInterval() {
+ return interval;
+ }
+
+ /**
+ * Sets the number of milliseconds before the status message is cleared.
+ *
+ * @param millis The new delay interval in milliseconds.
+ */
+ public void setDelayInterval(int millis) {
+ interval = millis;
+ timer.setDelay(interval);
+ }
+
+ /**
+ * Returns the visual component used to display the status.
+ *
+ * @return A component used for displaying status.
+ */
+ public Component getStatusComponent() {
+ return statusComponent;
+
+ }
+
+ /**
+ * Receives ActionEvents from the internal timer.
+ *
+ * @param e The action event in question.
+ */
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == timer) {
+ setText("");
+ return;
+ }
+
+ // otherwise continue with superclass implementation
+ super.actionPerformed(e);
+ }
+
+ /**
+ * This method is responsible for the initial layout of the panel. Subclasses
+ * can implement different layouts, but this method is responsible for
+ * initializing buttonPanelLayout to a valid layout manager and setting this
+ * panel to use it. This method must should initialize statusComponent to a
+ * component that ideally has get/setText methods, although this is not
+ * required.
+ */
+ protected void initLayout() {
+
+ statusComponent = new JTextField();
+ JTextField textField = (JTextField) statusComponent;
+ textField.setColumns(20);
+ textField.setBackground(getBackground());
+ textField.setEditable(false);
// statusComponent = new PickListPanel(); // for testing
- this.setLayout( new GridBagLayout() );
-
- GridBagConstraints gbc =
- new GridBagConstraints();
- gbc.gridx = GridBagConstraints.RELATIVE;
- gbc.gridy = GridBagConstraints.RELATIVE;
- gbc.gridwidth = 1;
- gbc.gridheight = 1;
- gbc.weightx = 1.0;
- gbc.weighty = 0.0;
- gbc.anchor = GridBagConstraints.CENTER;
- gbc.fill = GridBagConstraints.HORIZONTAL;
- gbc.insets = new Insets(0, 5, 0, 10);
- gbc.ipadx = 0;
- gbc.ipady = 0;
+ this.setLayout(new GridBagLayout());
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.gridx = GridBagConstraints.RELATIVE;
+ gbc.gridy = GridBagConstraints.RELATIVE;
+ gbc.gridwidth = 1;
+ gbc.gridheight = 1;
+ gbc.weightx = 1.0;
+ gbc.weighty = 0.0;
+ gbc.anchor = GridBagConstraints.CENTER;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets = new Insets(0, 5, 0, 10);
+ gbc.ipadx = 0;
+ gbc.ipady = 0;
//1.2 new GridBagConstraints(GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0,
//1.2 GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 10), 0, 0 );
- this.add( statusComponent, gbc );
-
- buttonContainer = new JPanel();
- buttonPanelLayout = new BetterFlowLayout();
- buttonContainer.setLayout(buttonPanelLayout);
- buttonPanelLayout.setAlignment( BetterFlowLayout.RIGHT );
- ((BetterFlowLayout)buttonPanelLayout).setWidthUniform( true );
- gbc.weightx = 0.0;
- gbc.insets = new Insets( 0, 0, 0, 0 );
- this.add( buttonContainer, gbc );
- }
-
-/**
-* Sets the text to appear in the status area.
-* @param newText A string to appear in the status area. Nulls are allowed.
-*/
- public void setText(String newText)
- {
- // TODO: should use property introspection instead
-
- // use reflection to call the "setText" method, if any.
- try
- {
- Class c = statusComponent.getClass();
- Method m = c.getMethod( "setText", new Class[] { new String().getClass() } );
- m.invoke( statusComponent, new Object[] { newText } );
- broadcastEvent( new ActionEvent( this, ActionEvent.ACTION_PERFORMED, STATUS_CHANGED ) );
- statusComponent.paint( statusComponent.getGraphics() );
- }
- catch ( Exception exc )
- {
- // "setText" method does not exist; do nothing.
- }
-
- // if non-empty string, start the timer
- if ( ! "".equals( newText ) )
- {
- timer.restart();
- }
- }
-
-/**
-* Gets the text in the status area.
-* @return The string being displayed in the status area.
-*/
- public String getText()
- {
- // TODO: should use property introspection instead
-
- String value = "";
- // use reflection to call the "setText" method, if any.
- try
- {
- Class c = statusComponent.getClass();
- Method m = c.getMethod( "getText", (Class[])null );
- value = (String) m.invoke( statusComponent, (Object[])null );
- }
- catch ( Exception exc )
- {
- // "getText" method does not exist; do nothing.
- }
- return value;
- }
-
- // for testing
-
- public static void main( String[] argv )
- {
- try
- {
- UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
- }
- catch (Exception exc)
- {
-
- }
-
- JFrame dialog = new JFrame();
- BorderLayout bl = new BorderLayout( 20, 20 );
+ this.add(statusComponent, gbc);
+
+ buttonContainer = new JPanel();
+ buttonPanelLayout = new BetterFlowLayout();
+ buttonContainer.setLayout(buttonPanelLayout);
+ buttonPanelLayout.setAlignment(BetterFlowLayout.RIGHT);
+ ((BetterFlowLayout) buttonPanelLayout).setWidthUniform(true);
+ gbc.weightx = 0.0;
+ gbc.insets = new Insets(0, 0, 0, 0);
+ this.add(buttonContainer, gbc);
+ }
+
+ /**
+ * Sets the text to appear in the status area.
+ *
+ * @param newText A string to appear in the status area. Nulls are allowed.
+ */
+ public void setText(String newText) {
+ // TODO: should use property introspection instead
+
+ // use reflection to call the "setText" method, if any.
+ try {
+ Class c = statusComponent.getClass();
+ Method m = c.getMethod("setText", new Class[] { new String().getClass() });
+ m.invoke(statusComponent, new Object[] { newText });
+ broadcastEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, STATUS_CHANGED));
+ statusComponent.paint(statusComponent.getGraphics());
+ } catch (Exception exc) {
+ // "setText" method does not exist; do nothing.
+ }
+
+ // if non-empty string, start the timer
+ if (!"".equals(newText)) {
+ timer.restart();
+ }
+ }
+
+ /**
+ * Gets the text in the status area.
+ *
+ * @return The string being displayed in the status area.
+ */
+ public String getText() {
+ // TODO: should use property introspection instead
+
+ String value = "";
+ // use reflection to call the "setText" method, if any.
+ try {
+ Class c = statusComponent.getClass();
+ Method m = c.getMethod("getText", (Class[]) null);
+ value = (String) m.invoke(statusComponent, (Object[]) null);
+ } catch (Exception exc) {
+ // "getText" method does not exist; do nothing.
+ }
+ return value;
+ }
+
+ // for testing
+
+ public static void main(String[] argv) {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception exc) {
+
+ }
+
+ JFrame dialog = new JFrame();
+ BorderLayout bl = new BorderLayout(20, 20);
// StatusButtonPanel panel = new StatusButtonPanel();
// System.out.println( panel.statusComponent );
- StatusButtonPanel panel = new StatusButtonPanel( new String[] { "Okay", "Cancel" } );
+ StatusButtonPanel panel = new StatusButtonPanel(new String[] { "Okay", "Cancel" });
- dialog.getContentPane().setLayout( bl );
- dialog.getContentPane().add( panel, BorderLayout.SOUTH );
- dialog.setLocation( 50, 50 );
- // dialog.setSize( 450, 150 );
- dialog.pack();
- dialog.setVisible( true );
+ dialog.getContentPane().setLayout(bl);
+ dialog.getContentPane().add(panel, BorderLayout.SOUTH);
+ dialog.setLocation(50, 50);
+ // dialog.setSize( 450, 150 );
+ dialog.pack();
+ dialog.setVisible(true);
- panel.setBorder( new EmptyBorder( 5, 5, 5, 5 ) );
- panel.setAlignment( BetterFlowLayout.RIGHT );
+ panel.setBorder(new EmptyBorder(5, 5, 5, 5));
+ panel.setAlignment(BetterFlowLayout.RIGHT);
// panel.getButton( "One" ).setEnabled( false );
- panel.setText( "File saved." );
- System.out.println( panel.getText() );
- }
+ panel.setText("File saved.");
+ System.out.println(panel.getText());
+ }
}
-
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TintedImageFilter.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TintedImageFilter.java
index a51ed16..b15a660 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TintedImageFilter.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TintedImageFilter.java
@@ -22,79 +22,75 @@ import java.awt.Color;
import java.awt.image.RGBImageFilter;
/**
- * TintedImageFilter tints all gray pixels half-way towards
- * the value passed into the constructor. This "tints" a
- * mostly grayscale image. This has proven useful for tinting
- * user interface decorative images towards one of the SystemColor
- * constants to better mesh with a platform look and feel.
+ * TintedImageFilter tints all gray pixels half-way towards the value passed
+ * into the constructor. This "tints" a mostly grayscale image. This has proven
+ * useful for tinting user interface decorative images towards one of the
+ * SystemColor constants to better mesh with a platform look and feel.
*
* @author michael@mpowers.net
* @author $Author: cgruber $
* @version $Revision: 893 $
*/
- public class TintedImageFilter extends RGBImageFilter
- {
- double redOffset, greenOffset, blueOffset;
-
- public TintedImageFilter( Color aColor )
- {
- canFilterIndexColorModel = true;
- redOffset = getOffset( aColor.getRed() );
- greenOffset = getOffset( aColor.getGreen() );
- blueOffset = getOffset( aColor.getBlue() );
- }
-
- /**
- * Calculates the offset used to modify color
- * values. This method returns half the difference
- * between the specified color level and 192.
- */
- protected double getOffset( int colorValue )
- {
- return ( colorValue - 192 ) / 2;
- }
+public class TintedImageFilter extends RGBImageFilter {
+ double redOffset, greenOffset, blueOffset;
- public int filterRGB(int x, int y, int rgb)
- {
+ public TintedImageFilter(Color aColor) {
+ canFilterIndexColorModel = true;
+ redOffset = getOffset(aColor.getRed());
+ greenOffset = getOffset(aColor.getGreen());
+ blueOffset = getOffset(aColor.getBlue());
+ }
+
+ /**
+ * Calculates the offset used to modify color values. This method returns half
+ * the difference between the specified color level and 192.
+ */
+ protected double getOffset(int colorValue) {
+ return (colorValue - 192) / 2;
+ }
+
+ public int filterRGB(int x, int y, int rgb) {
+
+ int red = (rgb & 0xff0000) >> 16;
+ int green = (rgb & 0x00ff00) >> 8;
+ int blue = (rgb & 0x0000ff);
+
+ // if roughly black
+ if (red + green + blue < 30)
+ return rgb;
+
+ // if roughly gray
+ if ((Math.abs(red - green) < 10) && (Math.abs(red - blue) < 10)) {
+ red += redOffset;
+ if (red < 0)
+ red = 0;
+ if (red > 255)
+ red = 255;
+ green += greenOffset;
+ if (green < 0)
+ green = 0;
+ if (green > 255)
+ green = 255;
+ blue += blueOffset;
+ if (blue < 0)
+ blue = 0;
+ if (blue > 255)
+ blue = 255;
+
+ return new Color(red, green, blue).getRGB();
+ }
+
+ return rgb;
+ }
+}
- int red = ( rgb & 0xff0000 ) >> 16;
- int green = ( rgb & 0x00ff00 ) >> 8;
- int blue = ( rgb & 0x0000ff );
-
- // if roughly black
- if ( red + green + blue < 30 ) return rgb;
-
- // if roughly gray
- if ( ( Math.abs( red - green ) < 10 )
- && ( Math.abs( red - blue ) < 10 ) )
- {
- red += redOffset;
- if ( red < 0 ) red = 0;
- if ( red > 255 ) red = 255;
- green += greenOffset;
- if ( green < 0 ) green = 0;
- if ( green > 255 ) green = 255;
- blue += blueOffset;
- if ( blue < 0 ) blue = 0;
- if ( blue > 255 ) blue = 255;
-
- return new Color( red, green, blue ).getRGB();
- }
-
- return rgb;
- }
- }
-
/*
- * $Log$
- * Revision 1.1 2006/02/16 13:22:22 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * $Log$ Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.2 2001/01/18 21:27:04 mpowers
- * Made the tinting a little darker.
+ * Revision 1.2 2001/01/18 21:27:04 mpowers Made the tinting a little darker.
*
- * Revision 1.1 2001/01/12 17:36:27 mpowers
- * Contributing TintedImageFilter.
+ * Revision 1.1 2001/01/12 17:36:27 mpowers Contributing TintedImageFilter.
*
*
*/
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeChooser.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeChooser.java
index f0bb6c2..f5ab50c 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeChooser.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeChooser.java
@@ -66,662 +66,538 @@ import javax.swing.tree.TreeSelectionModel;
import net.wotonomy.foundation.internal.WotonomyException;
/**
-* TreeChooser is a FileChooser-like panel that
-* uses a TreeModel as a data source. It basically
-* provides an alternative to JTree for rendering
-* and manipulating tree-like data.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class TreeChooser extends JPanel
- implements ActionListener, ListSelectionListener,
- TreeSelectionListener, TreeModelListener, ListCellRenderer
-{
- /**
- * The TreeChooser responds to this action command
- * by calling displayPrevious().
- */
+ * TreeChooser is a FileChooser-like panel that uses a TreeModel as a data
+ * source. It basically provides an alternative to JTree for rendering and
+ * manipulating tree-like data.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class TreeChooser extends JPanel
+ implements ActionListener, ListSelectionListener, TreeSelectionListener, TreeModelListener, ListCellRenderer {
+ /**
+ * The TreeChooser responds to this action command by calling displayPrevious().
+ */
public static final String BACK = "Back";
- /**
- * The TreeChooser responds to this action command
- * by calling displayHome().
- */
+ /**
+ * The TreeChooser responds to this action command by calling displayHome().
+ */
public static final String HOME = "Home";
- /**
- * The TreeChooser responds to this action command
- * by calling displayParent().
- */
+ /**
+ * The TreeChooser responds to this action command by calling displayParent().
+ */
public static final String UP = "Up";
- /**
- * The TreeChooser responds to this action command
- * by attempting to navigate to the first node in
- * the current selection and display that node's children.
- */
+ /**
+ * The TreeChooser responds to this action command by attempting to navigate to
+ * the first node in the current selection and display that node's children.
+ */
public static final String SELECT = "Select";
protected JList contents;
- protected JComboBox pathCombo;
+ protected JComboBox pathCombo;
protected JToolBar toolBar;
-
+
protected TreeModel model;
protected TreeSelectionModel selectionModel;
- protected TreeCellRenderer renderer;
- protected TreePath displayPath;
- protected Stack pathStack;
- protected int pathIndent;
-
- private ChooserComboBoxModel comboBoxModel;
- private JTree bogusJTree; // needed for tree cell renderer
- private Dimension preferredSize;
-
- public TreeChooser()
- {
- preferredSize = new Dimension( 300, 200 );
- model = new DefaultTreeModel( new DefaultMutableTreeNode( "Root" ) );
- displayPath = new TreePath( model.getRoot() );
- selectionModel = new DefaultTreeSelectionModel();
- renderer = new DefaultTreeCellRenderer();
- pathStack = new Stack();
- pathIndent = 0; // 16;
- comboBoxModel = new ChooserComboBoxModel( this );
-
- bogusJTree = new JTree();
- bogusJTree.setModel( model );
+ protected TreeCellRenderer renderer;
+ protected TreePath displayPath;
+ protected Stack pathStack;
+ protected int pathIndent;
+
+ private ChooserComboBoxModel comboBoxModel;
+ private JTree bogusJTree; // needed for tree cell renderer
+ private Dimension preferredSize;
+
+ public TreeChooser() {
+ preferredSize = new Dimension(300, 200);
+ model = new DefaultTreeModel(new DefaultMutableTreeNode("Root"));
+ displayPath = new TreePath(model.getRoot());
+ selectionModel = new DefaultTreeSelectionModel();
+ renderer = new DefaultTreeCellRenderer();
+ pathStack = new Stack();
+ pathIndent = 0; // 16;
+ comboBoxModel = new ChooserComboBoxModel(this);
+
+ bogusJTree = new JTree();
+ bogusJTree.setModel(model);
init();
- displayHome();
-
- stopListening(); // clear existing listeners
- startListening();
- }
-
- public Dimension getPreferredSize()
- {
- return preferredSize;
- }
-
- protected void init()
- {
- this.setLayout( new BorderLayout( 10, 10 ) );
-
+ displayHome();
+
+ stopListening(); // clear existing listeners
+ startListening();
+ }
+
+ public Dimension getPreferredSize() {
+ return preferredSize;
+ }
+
+ protected void init() {
+ this.setLayout(new BorderLayout(10, 10));
+
contents = initList();
- contents.getSelectionModel().setSelectionMode(
- ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
- // synchs with DefaultTreeSelectionModel
-
- JScrollPane scrollPane = new JScrollPane( contents );
- scrollPane.setPreferredSize( new Dimension( 200, 150 ) );
- this.add( scrollPane, BorderLayout.CENTER );
-
- Component previewPane = initPreviewPane();
- if ( previewPane != null )
- {
- this.add( previewPane, BorderLayout.EAST );
- }
-
+ contents.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ // synchs with DefaultTreeSelectionModel
+
+ JScrollPane scrollPane = new JScrollPane(contents);
+ scrollPane.setPreferredSize(new Dimension(200, 150));
+ this.add(scrollPane, BorderLayout.CENTER);
+
+ Component previewPane = initPreviewPane();
+ if (previewPane != null) {
+ this.add(previewPane, BorderLayout.EAST);
+ }
+
JPanel navigationPanel = new JPanel();
- navigationPanel.setLayout( new BorderLayout( 10, 10 ) );
- this.add( navigationPanel, BorderLayout.NORTH );
-
+ navigationPanel.setLayout(new BorderLayout(10, 10));
+ this.add(navigationPanel, BorderLayout.NORTH);
+
pathCombo = initComboBox();
- if ( pathCombo != null )
- {
- pathCombo.setModel( comboBoxModel );
+ if (pathCombo != null) {
+ pathCombo.setModel(comboBoxModel);
// put combo in a grid bag to handle varying
- // heights of JToolBars across platforms
+ // heights of JToolBars across platforms
JPanel panel = new JPanel();
- panel.setLayout( new GridBagLayout() );
+ panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
- panel.add( pathCombo, gbc );
- navigationPanel.add( panel, BorderLayout.CENTER );
- }
-
+ panel.add(pathCombo, gbc);
+ navigationPanel.add(panel, BorderLayout.CENTER);
+ }
+
Component toolBar = initToolBar();
- if ( toolBar != null )
- {
- navigationPanel.add( toolBar, BorderLayout.EAST );
- }
-
- }
-
- /**
- * Creates tool bar or return null if no tool bar is desired.
- * This implementation returns a JToolBar containing buttons
- * for BACK, UP, and HOME.
- */
- protected Component initToolBar()
- {
+ if (toolBar != null) {
+ navigationPanel.add(toolBar, BorderLayout.EAST);
+ }
+
+ }
+
+ /**
+ * Creates tool bar or return null if no tool bar is desired. This
+ * implementation returns a JToolBar containing buttons for BACK, UP, and HOME.
+ */
+ protected Component initToolBar() {
JToolBar toolBar = new JToolBar();
- toolBar.setFloatable( false );
- JButton button;
- button = new JButton( UIManager.getIcon("FileChooser.upFolderIcon") );
- button.setActionCommand( UP );
- button.addActionListener( this );
- toolBar.add( button );
- button = new JButton( UIManager.getIcon("FileChooser.homeFolderIcon") );
- button.setActionCommand( HOME );
- button.addActionListener( this );
- toolBar.add( button );
-/*
- button = new JButton( UIManager.getIcon("FileChooser.newFolderIcon") );
- button.setActionCommand( BACK );
- button.addActionListener( this );
- toolBar.add( button );
-*/
- return toolBar;
- }
-
- /**
- * Creates the component that is used to display a preview of the
- * selected item(s) in the content area. This component would listen
- * to the selection model to update itself when the selected items change.
- * Return null to omit this component.
- * This implementation returns null.
- */
- protected Component initPreviewPane()
- {
- return null;
- }
-
- /**
- * Creates the JComboBox that is used to render the path leading to
- * the displayed contents. Return null to omit this combo box.
- * This implementation returns a stock JComboBox that uses this
- * class as its cell renderer.
- */
- protected JComboBox initComboBox()
- {
- JComboBox comboBox = new JComboBox();
- comboBox.setRenderer( this );
- return comboBox;
- }
-
- /**
- * Creates the JList that is used to render the path leading to
- * the displayed contents. This method may not return null.
- * This implementation returns a stock JList that uses this
- * class as its cell renderer and fires a SELECT action event
- * on double click.
- */
- protected JList initList()
- {
- JList list = new JList();
- list.setCellRenderer( this );
- list.addMouseListener( new MouseAdapter()
- {
- public void mouseClicked( MouseEvent evt )
- {
- if ( evt.getClickCount() > 1 )
- {
- actionPerformed( new ActionEvent( this, 0, SELECT ) );
- }
- }
- });
- return list;
- }
-
- /**
- * Begins listening to the specified tree model
- * and tree selection model.
- */
- protected void startListening()
- {
- model.addTreeModelListener( this );
- selectionModel.addTreeSelectionListener( this );
- contents.addListSelectionListener( this );
- }
-
- /**
- * Stops listening to the specified tree model
- * and tree selection model.
- */
- protected void stopListening()
- {
- model.removeTreeModelListener( this );
- selectionModel.removeTreeSelectionListener( this );
- contents.removeListSelectionListener( this );
- }
-
- /**
- * Returns the TreeModel used by the TreeChooser.
- */
- public TreeModel getModel()
- {
- return model;
- }
-
- /**
- * Sets the TreeModel used by the TreeChooser.
- */
- public void setModel( TreeModel aTreeModel )
- {
- stopListening();
- model = aTreeModel;
- bogusJTree.setModel( aTreeModel );
- pathStack.removeAllElements();
- startListening();
- displayHome();
- }
-
- /**
- * Returns the TreeSelectionModel used by the TreeChooser.
- */
- public TreeSelectionModel getSelectionModel()
- {
- return selectionModel;
- }
-
- /**
- * Sets the TreeSelectionModel used by the TreeChooser.
- */
- public void setSelectionModel( TreeSelectionModel aSelectionModel )
- {
- selectionModel = aSelectionModel;
- if ( aSelectionModel.getSelectionMode() ==
- TreeSelectionModel.SINGLE_TREE_SELECTION )
- {
- contents.getSelectionModel().setSelectionMode(
- ListSelectionModel.SINGLE_SELECTION );
- }
- else
- {
- contents.getSelectionModel().setSelectionMode(
- ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
- }
- updateSelection();
- }
-
- /**
- * Returns the TreeCellRenderer used by the TreeChooser.
- */
- public TreeCellRenderer getRenderer()
- {
- return renderer;
- }
-
- /**
- * Sets the TreeCellRenderer used by the TreeChooser.
- */
- public void setRenderer( TreeCellRenderer aRenderer )
- {
- renderer = aRenderer;
- updateContents();
- }
-
- /**
- * Displays the "home" directory.
- * This implementation displays the root node's children.
- */
- public void displayHome()
- {
- setDisplayPath( null );
- }
-
- /**
- * Displays the parent path of the currently displayed path.
- */
- public void displayParent()
- {
- setDisplayPath( displayPath.getParentPath() );
- }
-
- /**
- * Displays the last displayed path before the current one,
- * emulating the behavior of a "back" button.
- */
- public void displayPrevious()
- {
- if ( pathStack.empty() )
- {
- displayHome();
- }
- else
- {
- setDisplayPathDirect( (TreePath) pathStack.pop() );
- updateContents();
- }
- }
-
- /**
- * Pushes the previous item onto the stack, sets
- * the display path, and then updates the contents.
- * If aPath is null, the root node's children are displayed.
- */
- public void setDisplayPath( TreePath aPath )
- {
- if ( aPath == null )
- {
- aPath = new TreePath( getModel().getRoot() );
- }
- if ( ! displayPath.equals ( aPath ) )
- {
- pathStack.push( displayPath );
- setDisplayPathDirect( aPath );
- }
- updateContents();
- }
-
- /**
- * Sets the displayPath field and does not
- * update the stack nor update the contents.
- */
- protected void setDisplayPathDirect( TreePath aPath )
- {
- displayPath = aPath;
- }
-
- /**
- * Gets the currently displayed path.
- */
- public TreePath getDisplayPath()
- {
- return displayPath;
- }
-
- /**
- * Called when selected path changes or when model indicates
- * that the displayed path has changed.
- */
- protected void updateContents()
- {
- stopListening();
-
- // update combo box
- comboBoxModel.fireContentsChanged();
-
- // update list contents
- Object displayedObject = displayPath.getLastPathComponent();
-/*
-//FIXME: this display group doesn't seem to be getting the sort orderings from parent
-if ( displayedObject instanceof net.wotonomy.ui.EODisplayGroup )
-System.out.println( ((net.wotonomy.ui.EODisplayGroup)displayedObject).displayedObjects() );
-*/
- int count = model.getChildCount( displayedObject );
- Object[] children = new Object[ count ];
- for ( int i = 0; i < count; i++ )
- {
- children[i] = model.getChild( displayedObject, i );
- }
- contents.setListData( children );
-
- startListening();
-
- // synchronize the selection
- updateSelection();
- }
-
- /**
- * Updates the selection in the list to reflect the
- * selection in the tree selection model.
- */
- public void updateSelection()
- {
- int index;
- Object last = displayPath.getLastPathComponent();
- TreePath[] selectionPaths = selectionModel.getSelectionPaths();
- if ( selectionPaths != null )
- {
- List selectedIndices = new LinkedList();
- for ( int i = 0; i < selectionPaths.length; i++ )
- {
- if ( displayPath.equals( selectionPaths[i].getParentPath() ) )
- {
- index = getModel().getIndexOfChild(
- last, selectionPaths[i].getLastPathComponent() );
- if ( index != -1 )
- {
- selectedIndices.add( new Integer( index ) );
- }
- else // should never happen
- {
- throw new WotonomyException(
- "Could not find child of displayed node." );
- }
- }
- }
- int[] selected = new int[ selectedIndices.size() ];
- for ( int i = 0; i < selected.length; i++ )
- {
- selected[i] = ((Integer)selectedIndices.get(i)).intValue();
- }
- stopListening();
- contents.setSelectedIndices( selected );
- startListening();
- }
- }
-
- // interface TreeModelListener
-
- public void treeNodesChanged( TreeModelEvent evt )
- {
-/*
- if ( displayPath.getLastPathComponent().toString().equals(
- evt.getTreePath().getLastPathComponent().toString() ) )
- {
-System.out.println( "TreeChooser.treeNodesChanged: " + count++ );
-*/
- updateContents();
-/*
- }
- else
- {
- System.out.println( evt.getTreePath() + " != " + displayPath );
- }
-*/
- }
-
- public void treeNodesInserted( TreeModelEvent evt )
- {
+ toolBar.setFloatable(false);
+ JButton button;
+ button = new JButton(UIManager.getIcon("FileChooser.upFolderIcon"));
+ button.setActionCommand(UP);
+ button.addActionListener(this);
+ toolBar.add(button);
+ button = new JButton(UIManager.getIcon("FileChooser.homeFolderIcon"));
+ button.setActionCommand(HOME);
+ button.addActionListener(this);
+ toolBar.add(button);
+ /*
+ * button = new JButton( UIManager.getIcon("FileChooser.newFolderIcon") );
+ * button.setActionCommand( BACK ); button.addActionListener( this );
+ * toolBar.add( button );
+ */
+ return toolBar;
+ }
+
+ /**
+ * Creates the component that is used to display a preview of the selected
+ * item(s) in the content area. This component would listen to the selection
+ * model to update itself when the selected items change. Return null to omit
+ * this component. This implementation returns null.
+ */
+ protected Component initPreviewPane() {
+ return null;
+ }
+
+ /**
+ * Creates the JComboBox that is used to render the path leading to the
+ * displayed contents. Return null to omit this combo box. This implementation
+ * returns a stock JComboBox that uses this class as its cell renderer.
+ */
+ protected JComboBox initComboBox() {
+ JComboBox comboBox = new JComboBox();
+ comboBox.setRenderer(this);
+ return comboBox;
+ }
+
+ /**
+ * Creates the JList that is used to render the path leading to the displayed
+ * contents. This method may not return null. This implementation returns a
+ * stock JList that uses this class as its cell renderer and fires a SELECT
+ * action event on double click.
+ */
+ protected JList initList() {
+ JList list = new JList();
+ list.setCellRenderer(this);
+ list.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent evt) {
+ if (evt.getClickCount() > 1) {
+ actionPerformed(new ActionEvent(this, 0, SELECT));
+ }
+ }
+ });
+ return list;
+ }
+
+ /**
+ * Begins listening to the specified tree model and tree selection model.
+ */
+ protected void startListening() {
+ model.addTreeModelListener(this);
+ selectionModel.addTreeSelectionListener(this);
+ contents.addListSelectionListener(this);
+ }
+
+ /**
+ * Stops listening to the specified tree model and tree selection model.
+ */
+ protected void stopListening() {
+ model.removeTreeModelListener(this);
+ selectionModel.removeTreeSelectionListener(this);
+ contents.removeListSelectionListener(this);
+ }
+
+ /**
+ * Returns the TreeModel used by the TreeChooser.
+ */
+ public TreeModel getModel() {
+ return model;
+ }
+
+ /**
+ * Sets the TreeModel used by the TreeChooser.
+ */
+ public void setModel(TreeModel aTreeModel) {
+ stopListening();
+ model = aTreeModel;
+ bogusJTree.setModel(aTreeModel);
+ pathStack.removeAllElements();
+ startListening();
+ displayHome();
+ }
+
+ /**
+ * Returns the TreeSelectionModel used by the TreeChooser.
+ */
+ public TreeSelectionModel getSelectionModel() {
+ return selectionModel;
+ }
+
+ /**
+ * Sets the TreeSelectionModel used by the TreeChooser.
+ */
+ public void setSelectionModel(TreeSelectionModel aSelectionModel) {
+ selectionModel = aSelectionModel;
+ if (aSelectionModel.getSelectionMode() == TreeSelectionModel.SINGLE_TREE_SELECTION) {
+ contents.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ } else {
+ contents.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ }
+ updateSelection();
+ }
+
+ /**
+ * Returns the TreeCellRenderer used by the TreeChooser.
+ */
+ public TreeCellRenderer getRenderer() {
+ return renderer;
+ }
+
+ /**
+ * Sets the TreeCellRenderer used by the TreeChooser.
+ */
+ public void setRenderer(TreeCellRenderer aRenderer) {
+ renderer = aRenderer;
+ updateContents();
+ }
+
+ /**
+ * Displays the "home" directory. This implementation displays the root node's
+ * children.
+ */
+ public void displayHome() {
+ setDisplayPath(null);
+ }
+
+ /**
+ * Displays the parent path of the currently displayed path.
+ */
+ public void displayParent() {
+ setDisplayPath(displayPath.getParentPath());
+ }
+
+ /**
+ * Displays the last displayed path before the current one, emulating the
+ * behavior of a "back" button.
+ */
+ public void displayPrevious() {
+ if (pathStack.empty()) {
+ displayHome();
+ } else {
+ setDisplayPathDirect((TreePath) pathStack.pop());
+ updateContents();
+ }
+ }
+
+ /**
+ * Pushes the previous item onto the stack, sets the display path, and then
+ * updates the contents. If aPath is null, the root node's children are
+ * displayed.
+ */
+ public void setDisplayPath(TreePath aPath) {
+ if (aPath == null) {
+ aPath = new TreePath(getModel().getRoot());
+ }
+ if (!displayPath.equals(aPath)) {
+ pathStack.push(displayPath);
+ setDisplayPathDirect(aPath);
+ }
+ updateContents();
+ }
+
+ /**
+ * Sets the displayPath field and does not update the stack nor update the
+ * contents.
+ */
+ protected void setDisplayPathDirect(TreePath aPath) {
+ displayPath = aPath;
+ }
+
+ /**
+ * Gets the currently displayed path.
+ */
+ public TreePath getDisplayPath() {
+ return displayPath;
+ }
+
+ /**
+ * Called when selected path changes or when model indicates that the displayed
+ * path has changed.
+ */
+ protected void updateContents() {
+ stopListening();
+
+ // update combo box
+ comboBoxModel.fireContentsChanged();
+
+ // update list contents
+ Object displayedObject = displayPath.getLastPathComponent();
+ /*
+ * //FIXME: this display group doesn't seem to be getting the sort orderings
+ * from parent if ( displayedObject instanceof net.wotonomy.ui.EODisplayGroup )
+ * System.out.println(
+ * ((net.wotonomy.ui.EODisplayGroup)displayedObject).displayedObjects() );
+ */
+ int count = model.getChildCount(displayedObject);
+ Object[] children = new Object[count];
+ for (int i = 0; i < count; i++) {
+ children[i] = model.getChild(displayedObject, i);
+ }
+ contents.setListData(children);
+
+ startListening();
+
+ // synchronize the selection
+ updateSelection();
+ }
+
+ /**
+ * Updates the selection in the list to reflect the selection in the tree
+ * selection model.
+ */
+ public void updateSelection() {
+ int index;
+ Object last = displayPath.getLastPathComponent();
+ TreePath[] selectionPaths = selectionModel.getSelectionPaths();
+ if (selectionPaths != null) {
+ List selectedIndices = new LinkedList();
+ for (int i = 0; i < selectionPaths.length; i++) {
+ if (displayPath.equals(selectionPaths[i].getParentPath())) {
+ index = getModel().getIndexOfChild(last, selectionPaths[i].getLastPathComponent());
+ if (index != -1) {
+ selectedIndices.add(new Integer(index));
+ } else // should never happen
+ {
+ throw new WotonomyException("Could not find child of displayed node.");
+ }
+ }
+ }
+ int[] selected = new int[selectedIndices.size()];
+ for (int i = 0; i < selected.length; i++) {
+ selected[i] = ((Integer) selectedIndices.get(i)).intValue();
+ }
+ stopListening();
+ contents.setSelectedIndices(selected);
+ startListening();
+ }
+ }
+
+ // interface TreeModelListener
+
+ public void treeNodesChanged(TreeModelEvent evt) {
+ /*
+ * if ( displayPath.getLastPathComponent().toString().equals(
+ * evt.getTreePath().getLastPathComponent().toString() ) ) { System.out.println(
+ * "TreeChooser.treeNodesChanged: " + count++ );
+ */
+ updateContents();
+ /*
+ * } else { System.out.println( evt.getTreePath() + " != " + displayPath ); }
+ */
+ }
+
+ public void treeNodesInserted(TreeModelEvent evt) {
// updateContents();
- }
-
- public void treeNodesRemoved( TreeModelEvent evt )
- {
+ }
+
+ public void treeNodesRemoved(TreeModelEvent evt) {
// updateContents();
- }
-
- public void treeStructureChanged( TreeModelEvent evt )
- {
- if ( ( evt.getTreePath().equals( displayPath ) )
- || ( evt.getTreePath().isDescendant( displayPath ) ) )
- {
+ }
+
+ public void treeStructureChanged(TreeModelEvent evt) {
+ if ((evt.getTreePath().equals(displayPath)) || (evt.getTreePath().isDescendant(displayPath))) {
// setDisplayPath( evt.getTreePath() );
- }
-
- displayHome();
- }
-
- // interface TreeSelectionListener
-
- /**
- * Called when the tree selection model's value changes.
- * This is presumably an external change, so this calls
- * updateSelection.
- */
- public void valueChanged( TreeSelectionEvent evt )
- {
- updateSelection();
- }
-
- // interface ListSelectionListener
-
- /**
- * Called when user changes the selection in the list.
- * This implementation updates the tree selection model
- * with the corresponding selection.
- */
- public void valueChanged( ListSelectionEvent evt )
- {
- if ( ! evt.getValueIsAdjusting() )
- {
- Object last = displayPath.getLastPathComponent();
- int[] selection = contents.getSelectedIndices();
- TreePath[] selectionPaths = new TreePath[ selection.length ];
- for ( int i = 0; i < selection.length; i++ )
- {
- selectionPaths[i] = displayPath.pathByAddingChild(
- getModel().getChild( last, selection[i] ) );
- }
- selectionModel.setSelectionPaths( selectionPaths );
- }
-
- }
-
- // interface ListCellRenderer
-
- /**
- * This method returns the component returned by the tree cell renderer.
- */
- public Component getListCellRendererComponent(
- JList list,
- Object value,
- int index,
- boolean isSelected,
- boolean cellHasFocus )
- {
- boolean isLeaf = ( model.isLeaf( value ) );
-
- bogusJTree.setForeground( list.getForeground() );
- bogusJTree.setBackground( list.getBackground() );
-
- JComponent result = (JComponent) renderer.getTreeCellRendererComponent(
- bogusJTree, value, isSelected, (list != contents),
- isLeaf, index, cellHasFocus );
-/*
- if ( ( list != contents ) && ( index > -1 ) )
- {
- result.setBorder(
- BorderFactory.createEmptyBorder( 0, index*pathIndent, 0, 0 ) );
- }
- else
- {
- result.setBorder(
- BorderFactory.createEmptyBorder() );
- }
-*/
- return result;
- }
-
- // interface ActionListener
-
- public void actionPerformed( ActionEvent evt )
- {
- String command = evt.getActionCommand();
-
- if ( HOME.equals( command ) )
- {
- displayHome();
- }
- else
- if ( UP.equals( command ) )
- {
- displayParent();
- }
- else
- if ( BACK.equals( command ) )
- {
- displayPrevious();
- }
- else
- if ( SELECT.equals( command ) )
- {
- Cursor oldCursor = getCursor();
- setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );
-
- int index = contents.getSelectedIndex();
- // if selection
- if ( index != -1 )
- {
- Object parent = displayPath.getLastPathComponent();
- Object child = getModel().getChild( parent, index );
- // if selected item is not a leaf
- if ( getModel().getChildCount( child ) > 0 )
- {
- // navigate to selected item
- setDisplayPath( displayPath.pathByAddingChild( child ) );
- }
- }
-
- setCursor( oldCursor );
- }
-
- }
-
- private class ChooserComboBoxModel implements ComboBoxModel
- {
- TreeChooser treeChooser;
- Vector listeners;
-
- ChooserComboBoxModel( TreeChooser aTreeChooser )
- {
- treeChooser = aTreeChooser;
- listeners = new Vector();
- }
-
- public int getSize()
- {
- return treeChooser.displayPath.getPathCount();
- }
-
- public Object getElementAt(int index)
- {
- return treeChooser.displayPath.getPathComponent( index );
- }
-
- public Object getSelectedItem()
- {
- return treeChooser.displayPath.getLastPathComponent();
- }
-
- public void setSelectedItem(Object anItem)
- {
- if ( ! (
- treeChooser.displayPath.getLastPathComponent().equals( anItem ) ) )
- {
- Object[] items = treeChooser.displayPath.getPath();
- TreePath path = new TreePath( getModel().getRoot() );
- for ( int i = 1; i < items.length; i++ )
- {
- if ( path.getLastPathComponent() == anItem )
- {
- treeChooser.setDisplayPath( path );
- return;
- }
- path = path.pathByAddingChild( items[i] );
- }
- }
- }
-
- public void addListDataListener(ListDataListener l)
- {
- listeners.add( l );
- }
-
- public void removeListDataListener(ListDataListener l)
- {
- listeners.remove( l );
- }
-
- public void fireContentsChanged()
- {
- Enumeration e = listeners.elements();
- while ( e.hasMoreElements() )
- {
- ((ListDataListener)e.nextElement()).contentsChanged(
- new ListDataEvent(
- this, ListDataEvent.CONTENTS_CHANGED, 0, getSize() ) );
- }
- }
- }
-
-}
+ }
+
+ displayHome();
+ }
+
+ // interface TreeSelectionListener
+
+ /**
+ * Called when the tree selection model's value changes. This is presumably an
+ * external change, so this calls updateSelection.
+ */
+ public void valueChanged(TreeSelectionEvent evt) {
+ updateSelection();
+ }
+ // interface ListSelectionListener
+ /**
+ * Called when user changes the selection in the list. This implementation
+ * updates the tree selection model with the corresponding selection.
+ */
+ public void valueChanged(ListSelectionEvent evt) {
+ if (!evt.getValueIsAdjusting()) {
+ Object last = displayPath.getLastPathComponent();
+ int[] selection = contents.getSelectedIndices();
+ TreePath[] selectionPaths = new TreePath[selection.length];
+ for (int i = 0; i < selection.length; i++) {
+ selectionPaths[i] = displayPath.pathByAddingChild(getModel().getChild(last, selection[i]));
+ }
+ selectionModel.setSelectionPaths(selectionPaths);
+ }
+
+ }
+
+ // interface ListCellRenderer
+
+ /**
+ * This method returns the component returned by the tree cell renderer.
+ */
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+ boolean cellHasFocus) {
+ boolean isLeaf = (model.isLeaf(value));
+
+ bogusJTree.setForeground(list.getForeground());
+ bogusJTree.setBackground(list.getBackground());
+
+ JComponent result = (JComponent) renderer.getTreeCellRendererComponent(bogusJTree, value, isSelected,
+ (list != contents), isLeaf, index, cellHasFocus);
+ /*
+ * if ( ( list != contents ) && ( index > -1 ) ) { result.setBorder(
+ * BorderFactory.createEmptyBorder( 0, index*pathIndent, 0, 0 ) ); } else {
+ * result.setBorder( BorderFactory.createEmptyBorder() ); }
+ */
+ return result;
+ }
+
+ // interface ActionListener
+
+ public void actionPerformed(ActionEvent evt) {
+ String command = evt.getActionCommand();
+
+ if (HOME.equals(command)) {
+ displayHome();
+ } else if (UP.equals(command)) {
+ displayParent();
+ } else if (BACK.equals(command)) {
+ displayPrevious();
+ } else if (SELECT.equals(command)) {
+ Cursor oldCursor = getCursor();
+ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
+ int index = contents.getSelectedIndex();
+ // if selection
+ if (index != -1) {
+ Object parent = displayPath.getLastPathComponent();
+ Object child = getModel().getChild(parent, index);
+ // if selected item is not a leaf
+ if (getModel().getChildCount(child) > 0) {
+ // navigate to selected item
+ setDisplayPath(displayPath.pathByAddingChild(child));
+ }
+ }
+
+ setCursor(oldCursor);
+ }
+
+ }
+
+ private class ChooserComboBoxModel implements ComboBoxModel {
+ TreeChooser treeChooser;
+ Vector listeners;
+
+ ChooserComboBoxModel(TreeChooser aTreeChooser) {
+ treeChooser = aTreeChooser;
+ listeners = new Vector();
+ }
+
+ public int getSize() {
+ return treeChooser.displayPath.getPathCount();
+ }
+
+ public Object getElementAt(int index) {
+ return treeChooser.displayPath.getPathComponent(index);
+ }
+
+ public Object getSelectedItem() {
+ return treeChooser.displayPath.getLastPathComponent();
+ }
+
+ public void setSelectedItem(Object anItem) {
+ if (!(treeChooser.displayPath.getLastPathComponent().equals(anItem))) {
+ Object[] items = treeChooser.displayPath.getPath();
+ TreePath path = new TreePath(getModel().getRoot());
+ for (int i = 1; i < items.length; i++) {
+ if (path.getLastPathComponent() == anItem) {
+ treeChooser.setDisplayPath(path);
+ return;
+ }
+ path = path.pathByAddingChild(items[i]);
+ }
+ }
+ }
+
+ public void addListDataListener(ListDataListener l) {
+ listeners.add(l);
+ }
+
+ public void removeListDataListener(ListDataListener l) {
+ listeners.remove(l);
+ }
+
+ public void fireContentsChanged() {
+ Enumeration e = listeners.elements();
+ while (e.hasMoreElements()) {
+ ((ListDataListener) e.nextElement())
+ .contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, getSize()));
+ }
+ }
+ }
+
+}
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeTableCellRenderer.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeTableCellRenderer.java
index fbf3791..c6e1a99 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeTableCellRenderer.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/components/TreeTableCellRenderer.java
@@ -32,193 +32,158 @@ import javax.swing.JViewport;
import javax.swing.table.TableCellRenderer;
/**
-* A TableCellRenderer that paints a portion of a JTree.
-* Extends JViewport to take advantage of buffering and
-* fast blitting (avoids repeated clipping and repainting).
-* Defaults opaque to false: to see selection background
-* painted, call setOpaque( true ).
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
+ * A TableCellRenderer that paints a portion of a JTree. Extends JViewport to
+ * take advantage of buffering and fast blitting (avoids repeated clipping and
+ * repainting). Defaults opaque to false: to see selection background painted,
+ * call setOpaque( true ).
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
public class TreeTableCellRenderer extends JViewport implements TableCellRenderer, MouseListener {
- JTree tree;
- Component emptyComponent;
- JTable delegateTable;
- int lastKnownColumn;
-
- /**
- * Constructor takes a JTree and modifies it by setting
- * rootVisible to false, showsRootHandles to true,
- * opaque to false, and border to null.
- */
- public TreeTableCellRenderer( JTree aTree )
- {
- setView( aTree );
- setBorder( null );
- tree = aTree;
- tree.setRootVisible( false );
- tree.setShowsRootHandles( true );
- tree.setBorder( null );
- tree.setOpaque( false );
-
- Object renderer = tree.getCellRenderer();
- if ( renderer instanceof JComponent )
- {
- ((JComponent)renderer).setOpaque( false );
- }
- Object editor = tree.getCellEditor();
- if ( editor instanceof JComponent )
- {
- ((JComponent)editor).setOpaque( false );
- }
-
- this.setOpaque( false );
- emptyComponent = new JLabel();
- }
-
- public Component getTableCellRendererComponent(
- JTable table, Object value,
- boolean isSelected, boolean hasFocus,
- int row, int column)
- {
- if ( isSelected )
- {
- setForeground( table.getSelectionForeground() );
- setBackground( table.getSelectionBackground() );
- }
- else
- {
- setForeground( table.getForeground() );
- setBackground( table.getBackground() );
- }
-
- lastKnownColumn = column;
- if ( delegateTable != table )
- {
- if ( delegateTable != null )
- {
- delegateTable.removeMouseListener( this );
- }
- table.addMouseListener( this );
- delegateTable = table;
- }
-
- Rectangle rect = tree.getRowBounds( row );
- if ( rect != null )
- {
- setViewPosition( new Point( 0 /*rect.x*/, rect.y ) );
-
- //FIXME: this causes problems for some LAFs (like Metal):
- // in particular, the table height seems to get stuck.
- //if ( table.getRowHeight( row ) != rect.height )
- //{
- // table.setRowHeight( row, rect.height );
- //}
- return this;
- }
- else
- {
- return emptyComponent;
- }
- }
-
- public void mouseClicked(MouseEvent e)
- {
- delegateToTree( e );
- }
-
- public void mousePressed(MouseEvent e)
- {
- delegateToTree( e );
- }
-
- public void mouseReleased(MouseEvent e)
- {
- delegateToTree( e );
- }
-
- public void mouseEntered(MouseEvent e)
- {
- delegateToTree( e );
- }
-
- public void mouseExited(MouseEvent e)
- {
- delegateToTree( e );
- }
-
- protected void delegateToTree(MouseEvent e)
- {
- int col = delegateTable.getColumnModel().getColumnIndexAtX( e.getX() );
- if ( col == lastKnownColumn )
- {
- Rectangle nodeRect = tree.getRowBounds( 0 );
- Rectangle cellRect = delegateTable.getCellRect( -1, col, false );
- if ( nodeRect != null )
- {
- e.translatePoint( -cellRect.x, nodeRect.y );
- tree.dispatchEvent( // e );
- new MouseEvent( tree, e.getID(), e.getWhen(), e.getModifiers(),
- e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger() ) );
- }
- }
- }
-
- public void repaint()
- {
- //if ( delegateTable != null ) delegateTable.repaint();
-
- // not calling super.repaint() does not seem to cause
- // any problems so we're not doing it.
- }
+ JTree tree;
+ Component emptyComponent;
+ JTable delegateTable;
+ int lastKnownColumn;
+
+ /**
+ * Constructor takes a JTree and modifies it by setting rootVisible to false,
+ * showsRootHandles to true, opaque to false, and border to null.
+ */
+ public TreeTableCellRenderer(JTree aTree) {
+ setView(aTree);
+ setBorder(null);
+ tree = aTree;
+ tree.setRootVisible(false);
+ tree.setShowsRootHandles(true);
+ tree.setBorder(null);
+ tree.setOpaque(false);
+
+ Object renderer = tree.getCellRenderer();
+ if (renderer instanceof JComponent) {
+ ((JComponent) renderer).setOpaque(false);
+ }
+ Object editor = tree.getCellEditor();
+ if (editor instanceof JComponent) {
+ ((JComponent) editor).setOpaque(false);
+ }
+
+ this.setOpaque(false);
+ emptyComponent = new JLabel();
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
+ int row, int column) {
+ if (isSelected) {
+ setForeground(table.getSelectionForeground());
+ setBackground(table.getSelectionBackground());
+ } else {
+ setForeground(table.getForeground());
+ setBackground(table.getBackground());
+ }
+
+ lastKnownColumn = column;
+ if (delegateTable != table) {
+ if (delegateTable != null) {
+ delegateTable.removeMouseListener(this);
+ }
+ table.addMouseListener(this);
+ delegateTable = table;
+ }
+
+ Rectangle rect = tree.getRowBounds(row);
+ if (rect != null) {
+ setViewPosition(new Point(0 /* rect.x */, rect.y));
+
+ // FIXME: this causes problems for some LAFs (like Metal):
+ // in particular, the table height seems to get stuck.
+ // if ( table.getRowHeight( row ) != rect.height )
+ // {
+ // table.setRowHeight( row, rect.height );
+ // }
+ return this;
+ } else {
+ return emptyComponent;
+ }
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ delegateToTree(e);
+ }
+
+ public void mousePressed(MouseEvent e) {
+ delegateToTree(e);
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ delegateToTree(e);
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ delegateToTree(e);
+ }
+
+ public void mouseExited(MouseEvent e) {
+ delegateToTree(e);
+ }
+
+ protected void delegateToTree(MouseEvent e) {
+ int col = delegateTable.getColumnModel().getColumnIndexAtX(e.getX());
+ if (col == lastKnownColumn) {
+ Rectangle nodeRect = tree.getRowBounds(0);
+ Rectangle cellRect = delegateTable.getCellRect(-1, col, false);
+ if (nodeRect != null) {
+ e.translatePoint(-cellRect.x, nodeRect.y);
+ tree.dispatchEvent( // e );
+ new MouseEvent(tree, e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY(),
+ e.getClickCount(), e.isPopupTrigger()));
+ }
+ }
+ }
+
+ public void repaint() {
+ // if ( delegateTable != null ) delegateTable.repaint();
+
+ // not calling super.repaint() does not seem to cause
+ // any problems so we're not doing it.
+ }
}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:19:05 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:19:05 cgruber Update imports and maven
+ * dependencies.
*
- * Revision 1.1 2006/02/16 13:22:22 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.11 2003/08/06 23:07:53 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.11 2003/08/06 23:07:53 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.10 2002/04/12 20:07:35 mpowers
- * Fixed cool/annoying view position.
+ * Revision 1.10 2002/04/12 20:07:35 mpowers Fixed cool/annoying view position.
*
- * Revision 1.9 2002/04/09 18:12:21 mpowers
- * Fixes for 1.4.
+ * Revision 1.9 2002/04/09 18:12:21 mpowers Fixes for 1.4.
*
- * Revision 1.8 2002/03/22 22:39:24 mpowers
- * Can now move column to any position in the table.
+ * Revision 1.8 2002/03/22 22:39:24 mpowers Can now move column to any position
+ * in the table.
*
- * Revision 1.7 2002/03/11 03:13:22 mpowers
- * Adjusting for viewport position; no longer responding to repaint().
+ * Revision 1.7 2002/03/11 03:13:22 mpowers Adjusting for viewport position; no
+ * longer responding to repaint().
*
- * Revision 1.6 2002/03/07 23:04:36 mpowers
- * Refining TreeColumnAssociation.
+ * Revision 1.6 2002/03/07 23:04:36 mpowers Refining TreeColumnAssociation.
*
- * Revision 1.5 2002/03/05 23:18:28 mpowers
- * Added documentation.
- * Added isSelectionPaintedImmediate and isSelectionTracking attributes
- * to TableAssociation.
- * Added getTableAssociation to TableColumnAssociation.
+ * Revision 1.5 2002/03/05 23:18:28 mpowers Added documentation. Added
+ * isSelectionPaintedImmediate and isSelectionTracking attributes to
+ * TableAssociation. Added getTableAssociation to TableColumnAssociation.
*
- * Revision 1.3 2002/02/27 23:19:17 mpowers
- * Refactoring of TreeAssociation to create TreeModelAssociation parent.
+ * Revision 1.3 2002/02/27 23:19:17 mpowers Refactoring of TreeAssociation to
+ * create TreeModelAssociation parent.
*
- * Revision 1.2 2002/02/18 23:13:55 mpowers
- * Only setting row height when needed.
+ * Revision 1.2 2002/02/18 23:13:55 mpowers Only setting row height when needed.
*
- * Revision 1.1 2002/02/18 03:46:08 mpowers
- * Implemented TreeTableCellRenderer.
+ * Revision 1.1 2002/02/18 03:46:08 mpowers Implemented TreeTableCellRenderer.
*
*
*/
-
-