In JDK5 Sun added a useful method to Swing. LookAndFeel.installProperty()
allows UI delegates to install primitive typed properties just like
UIResources, despite the fact that the primitive types cannot inherit
from UIResource.
I have investigated this and found the the supported properties depend on
the actual type of the component. I have summarized my findings in the
API docs to LookAndFeel.installProperty(). The implementation of that
method delegates to a package private method in JComponent (and its
subclasses), which keeps some internal state to determine if a property
has been set by a client program or by a UI delegate.
2006-04-05 Roman Kennke <[EMAIL PROTECTED]>
* javax/swing/LookAndFeel.java
(installProperty): New method. Allows primitive typed properties
to be handled like UIResources.
* javax/swing/AbstractButton.java
(clientBorderPaintedSet): New field.
(clientRolloverEnabledSet): New field.
(clientIconTextGapSet): New field.
(clientContentAreaFilledSet): New field.
(setRolloverEnabled): Set the client field to true.
(setBorderPainted): Likewise.
(setIconTextGap): Likewise.
(setContentAreaFilled): Likewise.
(setUIProperty): New helper method.
* javax/swing/JComponent.java
(clientOpaqueSet): New field.
(clientAutoscrollsSet): New field.
(setAutoscrolls): Set the client field to true.
(setOpaque): Likewise.
(setUIProperty): New helper method.
* javax/swing/JDesktopPane.java
(clientDragModeSet): New field.
(setDragMode): Set the client field to true.
(setUIProperty): New helper method.
* javax/swing/JSplitPane.java
(clientDividerSizeSet): New field.
(clientOneTouchExpandableSet): New field.
(setDividerSize): Set the client field to true.
(setOneTouchExpandable): Likewise.
(setUIProperty): New helper method.
* javax/swing/JTable.java
(clientRowHeightSet): New field.
(setRowHeight): Set the client field to true.
(setUIProperty): New helper method.
* javax/swing/JTree.java
(clientRowHeightSet): New field.
(clientScrollsOnExpandSet): New field.
(clientShowsRootHandlesSet): New field.
(setRowHeight): Set the client field to true.
(setShowsRootHandles): Likewise.
(setScrollsOnExpand): Likewise.
(setUIProperty): New helper method.
/Roman
Index: javax/swing/AbstractButton.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/AbstractButton.java,v
retrieving revision 1.52
diff -u -1 -0 -r1.52 AbstractButton.java
--- javax/swing/AbstractButton.java 23 Mar 2006 23:22:39 -0000 1.52
+++ javax/swing/AbstractButton.java 5 Apr 2006 14:51:57 -0000
@@ -270,20 +270,56 @@
/**
* Listener the button uses to receive PropertyChangeEvents from its
* Action.
*/
PropertyChangeListener actionPropertyChangeListener;
/** ChangeEvent that is fired to button's ChangeEventListeners */
protected ChangeEvent changeEvent = new ChangeEvent(this);
/**
+ * Indicates if the borderPainted property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientBorderPaintedSet = false;
+
+ /**
+ * Indicates if the rolloverEnabled property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientRolloverEnabledSet = false;
+
+ /**
+ * Indicates if the iconTextGap property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientIconTextGapSet = false;
+
+ /**
+ * Indicates if the contentAreaFilled property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientContentAreaFilledSet = false;
+
+ /**
* Fired in a PropertyChangeEvent when the "borderPainted" property changes.
*/
public static final String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted";
/**
* Fired in a PropertyChangeEvent when the "contentAreaFilled" property
* changes.
*/
public static final String CONTENT_AREA_FILLED_CHANGED_PROPERTY =
"contentAreaFilled";
@@ -932,20 +968,21 @@
/**
* Set the "rolloverEnabled" property. When rollover is enabled, and the
* look and feel supports it, the button will change its icon to
* rolloverIcon, when the mouse passes over it.
*
* @param r Whether or not to enable rollover icon changes
*/
public void setRolloverEnabled(boolean r)
{
+ clientRolloverEnabledSet = true;
if (rollOverEnabled != r)
{
rollOverEnabled = r;
firePropertyChange(ROLLOVER_ENABLED_CHANGED_PROPERTY, !r, r);
revalidate();
repaint();
}
}
/**
@@ -1164,20 +1201,21 @@
/**
* Set the value of the "borderPainted" property. If set to
* <code>false</code>, the button's look and feel class should not paint
* a border for the button. The default is <code>true</code>.
*
* @param b The new value of the property.
*/
public void setBorderPainted(boolean b)
{
+ clientBorderPaintedSet = true;
if (borderPainted == b)
return;
boolean old = borderPainted;
borderPainted = b;
firePropertyChange(BORDER_PAINTED_CHANGED_PROPERTY, old, b);
revalidate();
repaint();
}
/**
@@ -1314,20 +1352,21 @@
/**
* Set the value of the [EMAIL PROTECTED] #iconTextGap} property.
*
* @param i The new value of the property
*
* @since 1.4
*/
public void setIconTextGap(int i)
{
+ clientIconTextGapSet = true;
if (iconTextGap == i)
return;
int old = iconTextGap;
iconTextGap = i;
firePropertyChange("iconTextGap", new Integer(old), new Integer(i));
revalidate();
repaint();
}
@@ -1947,20 +1986,21 @@
* Sets the value of the button's "contentAreaFilled" property. This
* property indicates whether the area surrounding the text and icon of
* the button should be filled by the look and feel class. If this
* property is <code>false</code>, the look and feel class should leave
* the content area transparent.
*
* @param b The new value of the "contentAreaFilled" property
*/
public void setContentAreaFilled(boolean b)
{
+ clientContentAreaFilledSet = true;
if (contentAreaFilled == b)
return;
// The JDK sets the opaque property to the value of the contentAreaFilled
// property, so should we do.
setOpaque(b);
boolean old = contentAreaFilled;
contentAreaFilled = b;
firePropertyChange(CONTENT_AREA_FILLED_CHANGED_PROPERTY, old, b);
}
@@ -2074,11 +2114,65 @@
*
* @since 1.4
*/
public void setMultiClickThreshhold(long threshhold)
{
if (threshhold < 0)
throw new IllegalArgumentException();
multiClickThreshhold = threshhold;
}
+
+ /**
+ * Helper method for
+ * [EMAIL PROTECTED] LookAndFeel#installProperty(JComponent, String, Object)}.
+ *
+ * @param propertyName the name of the property
+ * @param value the value of the property
+ *
+ * @throws IllegalArgumentException if the specified property cannot be set
+ * by this method
+ * @throws ClassCastException if the property value does not match the
+ * property type
+ * @throws NullPointerException if <code>c</code> or
+ * <code>propertyValue</code> is <code>null</code>
+ */
+ void setUIProperty(String propertyName, Object value)
+ {
+ if (propertyName.equals("borderPainted"))
+ {
+ if (! clientBorderPaintedSet)
+ {
+ setBorderPainted(((Boolean) value).booleanValue());
+ clientBorderPaintedSet = false;
+ }
+ }
+ else if (propertyName.equals("rolloverEnabled"))
+ {
+ if (! clientRolloverEnabledSet)
+ {
+ setRolloverEnabled(((Boolean) value).booleanValue());
+ clientRolloverEnabledSet = false;
+ }
+ }
+ else if (propertyName.equals("iconTextGap"))
+ {
+ if (! clientIconTextGapSet)
+ {
+ setIconTextGap(((Integer) value).intValue());
+ clientIconTextGapSet = false;
+ }
+ }
+ else if (propertyName.equals("contentAreaFilled"))
+ {
+ if (! clientContentAreaFilledSet)
+ {
+ setContentAreaFilled(((Boolean) value).booleanValue());
+ clientContentAreaFilledSet = false;
+ }
+ }
+ else
+ {
+ super.setUIProperty(propertyName, value);
+ }
+ }
}
Index: javax/swing/JComponent.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.110
diff -u -1 -0 -r1.110 JComponent.java
--- javax/swing/JComponent.java 31 Mar 2006 12:33:05 -0000 1.110
+++ javax/swing/JComponent.java 5 Apr 2006 14:52:00 -0000
@@ -604,20 +604,38 @@
public static final int WHEN_IN_FOCUSED_WINDOW = 2;
/**
* Indicates if this component is completely dirty or not. This is used
* by the RepaintManager's
* [EMAIL PROTECTED] RepaintManager#isCompletelyDirty(JComponent)} method.
*/
boolean isCompletelyDirty = false;
/**
+ * Indicates if the opaque property has been set by a client program or by
+ * the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientOpaqueSet = false;
+
+ /**
+ * Indicates if the autoscrolls property has been set by a client program or
+ * by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientAutoscrollsSet = false;
+
+ /**
* Creates a new <code>JComponent</code> instance.
*/
public JComponent()
{
super();
setDropTarget(new DropTarget());
defaultLocale = Locale.getDefault();
debugGraphicsOptions = DebugGraphics.NONE_OPTION;
setRequestFocusEnabled(true);
}
@@ -2537,20 +2555,21 @@
}
/**
* Set the value of the [EMAIL PROTECTED] #autoscrolls} property.
*
* @param a The new value of the property
*/
public void setAutoscrolls(boolean a)
{
autoscrolls = a;
+ clientAutoscrollsSet = true;
}
/**
* Set the value of the [EMAIL PROTECTED] #debugGraphicsOptions} property.
*
* @param debugOptions The new value of the property
*/
public void setDebugGraphicsOptions(int debugOptions)
{
debugGraphicsOptions = debugOptions;
@@ -2730,20 +2749,21 @@
* Set the value of the [EMAIL PROTECTED] #opaque} property.
*
* @param isOpaque The new value of the property
*
* @see ComponentUI#update
*/
public void setOpaque(boolean isOpaque)
{
boolean oldOpaque = opaque;
opaque = isOpaque;
+ clientOpaqueSet = true;
firePropertyChange("opaque", oldOpaque, opaque);
}
/**
* Set the value of the visible property.
*
* If the value is changed, then the AncestorListeners of this component
* and all its children (recursivly) are notified.
*
* @param v The new value of the property
@@ -3405,11 +3425,51 @@
// Now we have to update the keyboard manager's hashtable
KeyboardManager km = KeyboardManager.getManager();
// This is a poor strategy, should be improved. We currently
// delete all the old bindings for the component and then register
// the current bindings.
km.clearBindingsForComp(changed.getComponent());
km.registerEntireMap((ComponentInputMap)
getInputMap(WHEN_IN_FOCUSED_WINDOW));
}
+
+ /**
+ * Helper method for
+ * [EMAIL PROTECTED] LookAndFeel#installProperty(JComponent, String, Object)}.
+ *
+ * @param propertyName the name of the property
+ * @param value the value of the property
+ *
+ * @throws IllegalArgumentException if the specified property cannot be set
+ * by this method
+ * @throws ClassCastException if the property value does not match the
+ * property type
+ * @throws NullPointerException if <code>c</code> or
+ * <code>propertyValue</code> is <code>null</code>
+ */
+ void setUIProperty(String propertyName, Object value)
+ {
+ if (propertyName.equals("opaque"))
+ {
+ if (! clientOpaqueSet)
+ {
+ setOpaque(((Boolean) value).booleanValue());
+ clientOpaqueSet = false;
+ }
+ }
+ else if (propertyName.equals("autoscrolls"))
+ {
+ if (! clientAutoscrollsSet)
+ {
+ setAutoscrolls(((Boolean) value).booleanValue());
+ clientAutoscrollsSet = false;
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException
+ ("Unsupported property for LookAndFeel.installProperty(): "
+ + propertyName);
+ }
+ }
}
Index: javax/swing/JDesktopPane.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JDesktopPane.java,v
retrieving revision 1.13
diff -u -1 -0 -r1.13 JDesktopPane.java
--- javax/swing/JDesktopPane.java 13 Mar 2006 21:33:37 -0000 1.13
+++ javax/swing/JDesktopPane.java 5 Apr 2006 14:52:00 -0000
@@ -78,20 +78,29 @@
/** The selected frame in the JDesktopPane. */
private transient JInternalFrame selectedFrame;
/** The JDesktopManager to use for acting on JInternalFrames. */
transient DesktopManager desktopManager;
/** The drag mode used by the JDesktopPane. */
private transient int dragMode = LIVE_DRAG_MODE;
/**
+ * Indicates if the dragMode property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientDragModeSet = false;
+
+ /**
* AccessibleJDesktopPane
*/
protected class AccessibleJDesktopPane extends AccessibleJComponent
{
/** DOCUMENT ME! */
private static final long serialVersionUID = 6079388927946077570L;
/**
* Constructor AccessibleJDesktopPane
*/
@@ -146,20 +155,22 @@
* @param mode The drag mode to use.
*
* @throws IllegalArgumentException If the drag mode given is not
* LIVE_DRAG_MODE or OUTLINE_DRAG_MODE.
*/
public void setDragMode(int mode)
{
if ((mode != LIVE_DRAG_MODE) && (mode != OUTLINE_DRAG_MODE))
throw new IllegalArgumentException("Drag mode not valid.");
+ clientDragModeSet = true;
+
// FIXME: Unsupported mode.
if (mode == OUTLINE_DRAG_MODE)
// throw new IllegalArgumentException("Outline drag modes are
// unsupported.");
mode = LIVE_DRAG_MODE;
dragMode = mode;
}
/**
@@ -323,11 +334,41 @@
*
* @return AccessibleContext
*/
public AccessibleContext getAccessibleContext()
{
if (accessibleContext == null)
accessibleContext = new AccessibleJDesktopPane();
return accessibleContext;
}
+
+ /**
+ * Helper method for
+ * [EMAIL PROTECTED] LookAndFeel#installProperty(JComponent, String, Object)}.
+ *
+ * @param propertyName the name of the property
+ * @param value the value of the property
+ *
+ * @throws IllegalArgumentException if the specified property cannot be set
+ * by this method
+ * @throws ClassCastException if the property value does not match the
+ * property type
+ * @throws NullPointerException if <code>c</code> or
+ * <code>propertyValue</code> is <code>null</code>
+ */
+ void setUIProperty(String propertyName, Object value)
+ {
+ if (propertyName.equals("dragMode"))
+ {
+ if (! clientDragModeSet)
+ {
+ setDragMode(((Integer) value).intValue());
+ clientDragModeSet = false;
+ }
+ }
+ else
+ {
+ super.setUIProperty(propertyName, value);
+ }
+ }
}
Index: javax/swing/JSplitPane.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JSplitPane.java,v
retrieving revision 1.13
diff -u -1 -0 -r1.13 JSplitPane.java
--- javax/swing/JSplitPane.java 13 Mar 2006 21:33:37 -0000 1.13
+++ javax/swing/JSplitPane.java 5 Apr 2006 14:52:00 -0000
@@ -216,20 +216,38 @@
/** The component on the top or left. */
protected Component leftComponent;
/** The component on the right or bottom. */
protected Component rightComponent;
/** Determines how extra space should be allocated. */
private transient double resizeWeight;
/**
+ * Indicates if the dividerSize property has been set by a client program or
+ * by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientDividerSizeSet = false;
+
+ /**
+ * Indicates if the oneTouchExpandable property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientOneTouchExpandableSet = false;
+
+ /**
* Creates a new JSplitPane object with the given orientation, layout mode,
* and left and right components.
*
* @param newOrientation The orientation to use.
* @param newContinuousLayout The layout mode to use.
* @param newLeftComponent The left component.
* @param newRightComponent The right component.
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
@@ -665,20 +683,21 @@
}
}
/**
* This method sets the size of the divider.
*
* @param newSize The size of the divider.
*/
public void setDividerSize(int newSize)
{
+ clientDividerSizeSet = true;
if (newSize != dividerSize)
{
int oldSize = dividerSize;
dividerSize = newSize;
firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, dividerSize);
}
}
// This doesn't appear to do anything when set from user side.
// so it probably is only used from the UI side to change the
@@ -716,20 +735,21 @@
/**
* This method sets whether the divider has one touch expandable buttons.
* The one touch expandable buttons can expand the size of either component
* to the maximum allowed size.
*
* @param newValue Whether the divider will have one touch expandable
* buttons.
*/
public void setOneTouchExpandable(boolean newValue)
{
+ clientOneTouchExpandableSet = true;
if (newValue != oneTouchExpandable)
{
boolean oldValue = oneTouchExpandable;
oneTouchExpandable = newValue;
firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue,
oneTouchExpandable);
}
}
/**
@@ -815,11 +835,49 @@
/**
* This method returns a string identifier to determine which UI class it
* needs.
*
* @return A string that identifies it's UI class.
*/
public String getUIClassID()
{
return "SplitPaneUI";
}
+
+ /**
+ * Helper method for
+ * [EMAIL PROTECTED] LookAndFeel#installProperty(JComponent, String, Object)}.
+ *
+ * @param propertyName the name of the property
+ * @param value the value of the property
+ *
+ * @throws IllegalArgumentException if the specified property cannot be set
+ * by this method
+ * @throws ClassCastException if the property value does not match the
+ * property type
+ * @throws NullPointerException if <code>c</code> or
+ * <code>propertyValue</code> is <code>null</code>
+ */
+ void setUIProperty(String propertyName, Object value)
+ {
+ if (propertyName.equals("dividerSize"))
+ {
+ if (! clientDividerSizeSet)
+ {
+ setDividerSize(((Integer) value).intValue());
+ clientDividerSizeSet = false;
+ }
+ }
+ else if (propertyName.equals("oneTouchExpandable"))
+ {
+ if (! clientOneTouchExpandableSet)
+ {
+ setOneTouchExpandable(((Boolean) value).booleanValue());
+ clientOneTouchExpandableSet = false;
+ }
+ }
+ else
+ {
+ super.setUIProperty(propertyName, value);
+ }
+ }
}
Index: javax/swing/JTable.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JTable.java,v
retrieving revision 1.94
diff -u -1 -0 -r1.94 JTable.java
--- javax/swing/JTable.java 31 Mar 2006 22:03:44 -0000 1.94
+++ javax/swing/JTable.java 5 Apr 2006 14:52:01 -0000
@@ -1568,20 +1568,29 @@
* activated.
*/
private boolean surrendersFocusOnKeystroke = false;
/**
* A Rectangle object to be reused in [EMAIL PROTECTED] #getCellRect}.
*/
private Rectangle rectCache = new Rectangle();
/**
+ * Indicates if the rowHeight property has been set by a client program or by
+ * the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientRowHeightSet = false;
+
+ /**
* Creates a new <code>JTable</code> instance.
*/
public JTable ()
{
this(null, null, null);
}
/**
* Creates a new <code>JTable</code> instance with the given number
* of rows and columns.
@@ -2740,21 +2749,23 @@
/**
* Set the value of the [EMAIL PROTECTED] #rowHeight} property.
*
* @param r The new value of the rowHeight property
*/
public void setRowHeight(int r)
{
if (r < 1)
throw new IllegalArgumentException();
-
+
+ clientRowHeightSet = true;
+
rowHeight = r;
revalidate();
repaint();
}
/**
* Sets the value of the rowHeight property for the specified
* row.
*
* @param rh is the new rowHeight
@@ -3783,11 +3794,41 @@
* @return whether cell editors of this table should receive keyboard focus
* when the editor is activated by a keystroke
*
* @since 1.4
*/
public boolean getSurrendersFocusOnKeystroke()
{
// TODO: Implement functionality of this property (in UI impl).
return surrendersFocusOnKeystroke;
}
+
+ /**
+ * Helper method for
+ * [EMAIL PROTECTED] LookAndFeel#installProperty(JComponent, String, Object)}.
+ *
+ * @param propertyName the name of the property
+ * @param value the value of the property
+ *
+ * @throws IllegalArgumentException if the specified property cannot be set
+ * by this method
+ * @throws ClassCastException if the property value does not match the
+ * property type
+ * @throws NullPointerException if <code>c</code> or
+ * <code>propertyValue</code> is <code>null</code>
+ */
+ void setUIProperty(String propertyName, Object value)
+ {
+ if (propertyName.equals("rowHeight"))
+ {
+ if (! clientRowHeightSet)
+ {
+ setRowHeight(((Integer) value).intValue());
+ clientRowHeightSet = false;
+ }
+ }
+ else
+ {
+ super.setUIProperty(propertyName, value);
+ }
+ }
}
Index: javax/swing/JTree.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JTree.java,v
retrieving revision 1.59
diff -u -1 -0 -r1.59 JTree.java
--- javax/swing/JTree.java 20 Mar 2006 11:26:04 -0000 1.59
+++ javax/swing/JTree.java 5 Apr 2006 14:52:02 -0000
@@ -1436,20 +1436,47 @@
*/
protected transient TreeModelListener treeModelListener;
/**
* Redirects TreeSelectionEvents so that the source is this JTree.
*/
protected TreeSelectionRedirector selectionRedirector =
new TreeSelectionRedirector();
/**
+ * Indicates if the rowHeight property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientRowHeightSet = false;
+
+ /**
+ * Indicates if the scrollsOnExpand property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientScrollsOnExpandSet = false;
+
+ /**
+ * Indicates if the showsRootHandles property has been set by a client
+ * program or by the UI.
+ *
+ * @see #setUIProperty(String, Object)
+ * @see LookAndFeel#installProperty(JComponent, String, Object)
+ */
+ private boolean clientShowsRootHandlesSet = false;
+
+ /**
* Creates a new <code>JTree</code> object.
*/
public JTree()
{
this(createTreeModel(null));
}
/**
* Creates a new <code>JTree</code> object.
*
@@ -1919,20 +1946,22 @@
firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
}
public boolean getShowsRootHandles()
{
return showsRootHandles;
}
public void setShowsRootHandles(boolean flag)
{
+ clientShowsRootHandlesSet = true;
+
if (showsRootHandles == flag)
return;
boolean oldValue = showsRootHandles;
showsRootHandles = flag;
firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue, flag);
}
public TreeCellEditor getCellEditor()
{
@@ -2018,20 +2047,22 @@
firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, large);
}
public int getRowHeight()
{
return rowHeight;
}
public void setRowHeight(int height)
{
+ clientRowHeightSet = true;
+
if (rowHeight == height)
return;
int oldValue = rowHeight;
rowHeight = height;
firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, height);
}
public boolean isFixedRowHeight()
{
@@ -2107,20 +2138,21 @@
scrollPathToVisible(getPathForRow(row));
}
public boolean getScrollsOnExpand()
{
return scrollsOnExpand;
}
public void setScrollsOnExpand(boolean scroll)
{
+ clientScrollsOnExpandSet = true;
if (scrollsOnExpand == scroll)
return;
boolean oldValue = scrollsOnExpand;
scrollsOnExpand = scroll;
firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue, scroll);
}
public void setSelectionPath(TreePath path)
{
@@ -2937,11 +2969,57 @@
/**
* Sent when the tree has changed enough that we need to resize the bounds,
* but not enough that we need to remove the expanded node set (e.g nodes
* were expanded or collapsed, or nodes were inserted into the tree). You
* should never have to invoke this, the UI will invoke this as it needs to.
*/
public void treeDidChange()
{
repaint();
}
+
+ /**
+ * Helper method for
+ * [EMAIL PROTECTED] LookAndFeel#installProperty(JComponent, String, Object)}.
+ *
+ * @param propertyName the name of the property
+ * @param value the value of the property
+ *
+ * @throws IllegalArgumentException if the specified property cannot be set
+ * by this method
+ * @throws ClassCastException if the property value does not match the
+ * property type
+ * @throws NullPointerException if <code>c</code> or
+ * <code>propertyValue</code> is <code>null</code>
+ */
+ void setUIProperty(String propertyName, Object value)
+ {
+ if (propertyName.equals("rowHeight"))
+ {
+ if (! clientRowHeightSet)
+ {
+ setRowHeight(((Integer) value).intValue());
+ clientRowHeightSet = false;
+ }
+ }
+ else if (propertyName.equals("scrollsOnExpand"))
+ {
+ if (! clientScrollsOnExpandSet)
+ {
+ setScrollsOnExpand(((Boolean) value).booleanValue());
+ clientScrollsOnExpandSet = false;
+ }
+ }
+ else if (propertyName.equals("showsRootHandles"))
+ {
+ if (! clientShowsRootHandlesSet)
+ {
+ setShowsRootHandles(((Boolean) value).booleanValue());
+ clientShowsRootHandlesSet = false;
+ }
+ }
+ else
+ {
+ super.setUIProperty(propertyName, value);
+ }
+ }
}
Index: javax/swing/LookAndFeel.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/LookAndFeel.java,v
retrieving revision 1.17
diff -u -1 -0 -r1.17 LookAndFeel.java
--- javax/swing/LookAndFeel.java 14 Mar 2006 15:11:27 -0000 1.17
+++ javax/swing/LookAndFeel.java 5 Apr 2006 14:52:02 -0000
@@ -377,11 +377,57 @@
* Convenience method for un-installing a component's default border on the
* specified component if the border is currently an instance of UIResource.
*
* @param c the component (<code>null</code> not permitted).
*/
public static void uninstallBorder(JComponent c)
{
if (c.getBorder() instanceof UIResource)
c.setBorder(null);
}
+
+ /**
+ * This methods installs a UI property if it hasn't already been set by an
+ * application. This method is used by UI delegates that install a default
+ * value for a property with a primitive type but do not want to override
+ * a value that has been set by an application.
+ *
+ * The supported properties depend on the actual type of the component and
+ * are listed in the table below. The supported properties are of course
+ * inherited to subclasses.
+ *
+ * <table>
+ * <tr><th>Type</th><th>Supported properties</th></tr>
+ * <tr><td><code>JComponent</code></td>
+ * <td><code>opaque, autoscrolls</code></td></tr>
+ * <tr><td><code>AbstractButton</code></td>
+ * <td><code>borderPainted, rolloverEnabled, iconTextGap,
+ * contentAreaFilled</code></td></tr>
+ * <tr><td><code>JDesktopPane</code></td>
+ * <td><code>dragMode</code></td></tr>
+ * <tr><td><code>JSplitPane</code></td>
+ * <td><code>dividerSize, oneTouchExpandable</code></td></tr>
+ * <tr><td><code>JTable</code></td>
+ * <td><code>rowHeight</code></td></tr>
+ * <tr><td><code>JTree</code></td>
+ * <td><code>rowHeight, scrollsOnExpand, showsRootHandles</code></td></tr>
+ * </table>
+ *
+ * @param c the component to install the property to
+ * @param propertyName the name of the property
+ * @param value the value of the property
+ *
+ * @throws IllegalArgumentException if the specified property cannot be set
+ * by this method
+ * @throws ClassCastException if the property value does not match the
+ * property type
+ * @throws NullPointerException if <code>c</code> or
+ * <code>propertyValue</code> is <code>null</code>
+ *
+ * @since 1.5
+ */
+ public static void installProperty(JComponent c, String propertyName,
+ Object value)
+ {
+ c.setUIProperty(propertyName, value);
+ }
}