This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][gui] Implementation of JList and related classes


hi,

I just committed this to java-gui-branch. enables somewhat-working
JList, JListModel, JListSelectionModel, etc.

2004-02-25 Graydon Hoare <graydon@redhat.com>

	* javax/swing/AbstractButton.java: Add "final" qualifiers.
	* javax/swing/JList.java: Reimplement.
	* javax/swing/DefaultListSelectionModel.java: Reimplement.
	* javax/swing/plaf/basic/BasicListUI.java: Reimplement.
	* javax/swing/plaf/basic/BasicLookAndFeel.java: Add "purple" values.
	* javax/swing/ListModel.java: Javadoc.
	* javax/swing/ListSelectionModel.java: Add missing methods.
	* javax/swing/AbstractListModel.java: Javadoc and corrections.
	* javax/swing/DefaultListModel.java: Javadoc and corrections.
	* javax/swing/ListModel.java: Javadoc and corrections.
	* javax/swing/DefaultListCellRenderer.java: Minor tidying.
--- javax/swing/AbstractButton.java	12 Feb 2004 00:17:23 -0000	1.5
+++ javax/swing/AbstractButton.java	25 Feb 2004 23:56:22 -0000
@@ -233,61 +233,61 @@
   PropertyChangeListener actionPropertyChangeListener;
   
   /** Fired in a PropertyChangeEvent when the "borderPainted" property changes. */
-  public static String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted";
+  public static final String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted";
   
   /** Fired in a PropertyChangeEvent when the "contentAreaFilled" property changes. */
-  public static String CONTENT_AREA_FILLED_CHANGED_PROPERTY = "contentAreaFilled";
+  public static final String CONTENT_AREA_FILLED_CHANGED_PROPERTY = "contentAreaFilled";
   
   /** Fired in a PropertyChangeEvent when the "disabledIcon" property changes. */
-  public static String DISABLED_ICON_CHANGED_PROPERTY = "disabledIcon";
+  public static final String DISABLED_ICON_CHANGED_PROPERTY = "disabledIcon";
   
   /** Fired in a PropertyChangeEvent when the "disabledSelectedIcon" property changes. */
-  public static String DISABLED_SELECTED_ICON_CHANGED_PROPERTY = "disabledSelectedIcon";
+  public static final String DISABLED_SELECTED_ICON_CHANGED_PROPERTY = "disabledSelectedIcon";
   
   /** Fired in a PropertyChangeEvent when the "focusPainted" property changes. */
-  public static String FOCUS_PAINTED_CHANGED_PROPERTY = "focusPainted";
+  public static final String FOCUS_PAINTED_CHANGED_PROPERTY = "focusPainted";
 
   /** Fired in a PropertyChangeEvent when the "horizontalAlignment" property changes. */
-  public static String HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY = "horizontalAlignment";
+  public static final String HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY = "horizontalAlignment";
 
   /** Fired in a PropertyChangeEvent when the "horizontalTextPosition" property changes. */
-  public static String HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY = "horizontalTextPosition";
+  public static final String HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY = "horizontalTextPosition";
 
   /** Fired in a PropertyChangeEvent when the "icon" property changes. */
-  public static String ICON_CHANGED_PROPERTY = "icon";
+  public static final String ICON_CHANGED_PROPERTY = "icon";
 
   /** Fired in a PropertyChangeEvent when the "margin" property changes. */
-  public static String MARGIN_CHANGED_PROPERTY = "margin";
+  public static final String MARGIN_CHANGED_PROPERTY = "margin";
 
   /** Fired in a PropertyChangeEvent when the "mnemonic" property changes. */
-  public static String MNEMONIC_CHANGED_PROPERTY = "mnemonic";
+  public static final String MNEMONIC_CHANGED_PROPERTY = "mnemonic";
 
   /** Fired in a PropertyChangeEvent when the "model" property changes. */
-  public static String MODEL_CHANGED_PROPERTY = "model";
+  public static final String MODEL_CHANGED_PROPERTY = "model";
 
   /** Fired in a PropertyChangeEvent when the "pressedIcon" property changes. */
-  public static String PRESSED_ICON_CHANGED_PROPERTY = "pressedIcon";
+  public static final String PRESSED_ICON_CHANGED_PROPERTY = "pressedIcon";
 
   /** Fired in a PropertyChangeEvent when the "rolloverEnabled" property changes. */
-  public static String ROLLOVER_ENABLED_CHANGED_PROPERTY = "rolloverEnabled";
+  public static final String ROLLOVER_ENABLED_CHANGED_PROPERTY = "rolloverEnabled";
 
   /** Fired in a PropertyChangeEvent when the "rolloverIcon" property changes. */
-  public static String ROLLOVER_ICON_CHANGED_PROPERTY = "rolloverIcon";
+  public static final String ROLLOVER_ICON_CHANGED_PROPERTY = "rolloverIcon";
   
   /** Fired in a PropertyChangeEvent when the "rolloverSelectedIcon" property changes. */
-  public static String ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY = "rolloverSelectedIcon";
+  public static final String ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY = "rolloverSelectedIcon";
   
   /** Fired in a PropertyChangeEvent when the "selectedIcon" property changes. */
-  public static String SELECTED_ICON_CHANGED_PROPERTY = "selectedIcon";
+  public static final String SELECTED_ICON_CHANGED_PROPERTY = "selectedIcon";
 
   /** Fired in a PropertyChangeEvent when the "text" property changes. */
-  public static String TEXT_CHANGED_PROPERTY = "text";
+  public static final String TEXT_CHANGED_PROPERTY = "text";
 
   /** Fired in a PropertyChangeEvent when the "verticalAlignment" property changes. */
-  public static String VERTICAL_ALIGNMENT_CHANGED_PROPERTY = "verticalAlignment";
+  public static final String VERTICAL_ALIGNMENT_CHANGED_PROPERTY = "verticalAlignment";
 
   /** Fired in a PropertyChangeEvent when the "verticalTextPosition" property changes. */
-  public static String VERTICAL_TEXT_POSITION_CHANGED_PROPERTY = "verticalTextPosition";
+  public static final String VERTICAL_TEXT_POSITION_CHANGED_PROPERTY = "verticalTextPosition";
 
     /**
    * A Java Accessibility extension of the AbstractButton.
@@ -1612,7 +1612,7 @@
    *
    * @return The current rollover selected icon
    */
-  Icon getRolloverSelectedIcon()
+  public Icon getRolloverSelectedIcon()
   {
     return rollover_selected_icon;
   }
@@ -1648,8 +1648,8 @@
    *
    * @return The current selected icon
    */
-  Icon getSelectedIcon()
+  public Icon getSelectedIcon()
   {
     return selected_icon;
   }
--- javax/swing/JList.java	12 Feb 2004 00:17:23 -0000	1.4
+++ javax/swing/JList.java	25 Feb 2004 23:56:23 -0000
@@ -35,10 +35,10 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package javax.swing;
 
 import java.awt.Color;
+import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.util.Vector;
@@ -46,92 +46,527 @@
 import javax.accessibility.AccessibleContext;
 import javax.swing.event.ListDataEvent;
 import javax.swing.event.ListDataListener;
+import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 import javax.swing.plaf.ListUI;
 
+
+/**
+ * <p>This class is a facade over three separate objects: {@link
+ * javax.swing.ListModel}, {@link javax.swing.ListSelectionModel} and
+ * {@link javax.swing.plaf.ListUI}. The facade represents a unified "list"
+ * concept, with independently replacable (possibly client-provided) models
+ * for its contents and its current selection. In addition, each element in
+ * the list is rendered via a strategy class {@link
+ * javax.swing.ListCellRenderer}.</p>
+ *
+ * <p>Lists have many properties, some of which are stored in this class
+ * while others are delegated to the list's model or selection. The
+ * following properties are available:</p>
+ *
+ * <table>
+ * <tr><th>Property                       </th><th>Stored in</th><th>Bound?</th></tr>
+ * <tr><td>accessibleContext              </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>anchorSelectionIndex           </td><td>selection</td><td>no    </td></tr>
+ * <tr><td>cellRenderer                   </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>dragEnabled                    </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>firstVisibleIndex              </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>fixedCellHeight                </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>fixedCellWidth                 </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>lastVisibleIndex               </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>layoutOrientation              </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>leadSelectionIndex             </td><td>selection</td><td>no    </td></tr>
+ * <tr><td>maxSelectionIndex              </td><td>selection</td><td>no    </td></tr>
+ * <tr><td>minSelectionIndex              </td><td>selection</td><td>no    </td></tr>
+ * <tr><td>model                          </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>opaque                         </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>preferredScrollableViewportSize</td><td>list     </td><td>no    </td></tr>
+ * <tr><td>prototypeCellValue             </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>scrollableTracksViewportHeight </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>scrollableTracksViewportWidth  </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>selectedIndex                  </td><td>selection</td><td>no    </td></tr>
+ * <tr><td>selectedIndices                </td><td>selection</td><td>no    </td></tr>
+ * <tr><td>selectedValue                  </td><td>model    </td><td>no    </td></tr>
+ * <tr><td>selectedValues                 </td><td>model    </td><td>no    </td></tr>
+ * <tr><td>selectionBackground            </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>selectionEmpty                 </td><td>selection</td><td>no    </td></tr>
+ * <tr><td>selectionForeground            </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>selectionMode                  </td><td>selection</td><td>no    </td></tr>
+ * <tr><td>selectionModel                 </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>UI                             </td><td>list     </td><td>yes   </td></tr>
+ * <tr><td>UIClassID                      </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>valueIsAdjusting               </td><td>list     </td><td>no    </td></tr>
+ * <tr><td>visibleRowCount                </td><td>list     </td><td>no    </td></tr>
+ * </table> 
+ *
+ * @author Graydon Hoare (graydon&064;redhat.com)
+ */
+
 public class JList extends JComponent implements Accessible, Scrollable
 {
   private static final long serialVersionUID = 4406629526391098046L;
 
-    Color select_back, select_fore;
-    ListCellRenderer render;
-    int visibles = 8;
+  /** 
+   * Constant value used in "layoutOrientation" property. This value means
+   * that cells are laid out in multiple columns "newspaper style",
+   * filling horizontally first, then vertically. 
+   */
+  public static int HORIZONTAL_WRAP = 1;
+
+  /** 
+   * Constant value used in "layoutOrientation" property. This value means
+   * that cells are laid out in a single vertical column. This is the default. 
+   */
+  public static int VERTICAL = 2;
+
+  /** 
+   * Constant value used in "layoutOrientation" property. This value means
+   * that cells are laid out in multiple columns "newspaper style", filling
+   * vertically first, then horizontally. 
+   */
+  public static int VERTICAL_WRAP = 3;
+  
+  /** Fired in a PropertyChangeEvent when the "cellRenderer" property changes. */
+  public static final String CELL_RENDERER_PROPERTY_CHANGED = "cellRenderer";
+
+  /** Fired in a PropertyChangeEvent when the "fixedCellHeight" property changes. */
+  public static final String FIXED_CELL_HEIGHT_PROPERTY_CHANGED = "fixedCellHeight";
+
+  /** Fired in a PropertyChangeEvent when the "fixedCellWidth" property changes. */
+  public static final String FIXED_CELL_WIDTH_PROPERTY_CHANGED = "fixedCellWidth";
+
+  /** Fired in a PropertyChangeEvent when the "layoutOrientation" property changes. */
+  public static final String LAYOUT_ORIENTATION_PROPERTY_CHANGED = "layoutOrientation";
+
+  /** Fired in a PropertyChangeEvent when the "model" property changes. */
+  public static final String MODEL_PROPERTY_CHANGED = "model";
+
+  /** Fired in a PropertyChangeEvent when the "prototypeCellValue" property changes. */
+  public static final String PROTOTYPE_CELL_VALUE_PROPERTY_CHANGED = "prototypeCellValue";
+
+  /** Fired in a PropertyChangeEvent when the "selectionBackground" property changes. */
+  public static final String SELECTION_BACKGROUND_PROPERTY_CHANGED = "selectionBackground";
+
+  /** Fired in a PropertyChangeEvent when the "selectionForeground" property changes. */
+  public static final String SELECTION_FOREGROUND_PROPERTY_CHANGED = "selectionForeground";
+
+  /** Fired in a PropertyChangeEvent when the "selectionModel" property changes. */
+  public static final String SELECTION_MODEL_PROPERTY_CHANGED = "selectionModel";
+
+
+  /**
+   * This property indicates whether "drag and drop" functions are enabled
+   * on the list.
+   */
+  boolean dragEnabled;
+
+  /** This property provides a strategy for rendering cells in the list. */
+  ListCellRenderer cellRenderer;
+
+  /**
+   * This property indicates an fixed width to assign to all cells in the
+   * list. If its value is <code>-1</code>, no width has been
+   * assigned. This value can be set explicitly, or implicitly by setting
+   * the {@link #prototypeCellValue} property.
+   */
+  int fixedCellWidth;
+  
+  /**
+   * This property indicates an fixed height to assign to all cells in the
+   * list. If its value is <code>-1</code>, no height has been
+   * assigned. This value can be set explicitly, or implicitly by setting
+   * the {@link #prototypeCellValue} property.
+   */
+  int fixedCellHeight;
+
+  /** 
+   * This property holds the current layout orientation of the list, which
+   * is one of the integer constants {@link #VERTICAL}, {@link
+   * #VERTICAL_WRAP}, or {@link #HORIZONTAL_WRAP}. 
+   */
+
+  int layoutOrientation;
     
+  /** This property holds the data elements displayed by the list. */
     ListModel          model;
-    ListSelectionModel sel_model;
 
+  /**
+   * <p>This property holds a reference to a "prototype" data value --
+   * typically a String -- which is used to calculate the {@link
+   * #fixedCellWidth} and {@link #fixedCellHeight} properties, using the
+   * {@link #cellRenderer} property to acquire a component to render the
+   * prototype.</p>
+   *
+   * <p>It is important that you <em>not</em> set this value to a
+   * component. It has to be a <em>data value</em> such as the objects you
+   * would find in the list's model. Setting it to a component will have
+   * undefined (and undesirable) affects. </p>
+   */
+  Object prototypeCellValue;
+
+  /** 
+   * This property specifies a foreground color for the selected cells in
+   * the list. When {@link ListCellRenderer.getListCellRendererComponent}
+   * is called with a selected cell object, the component returned will
+   * have its "foreground" set to this color.
+   */
+  Color selectionBackground;
+
+  /** 
+   * This property specifies a background color for the selected cells in
+   * the list. When {@link ListCellRenderer.getListCellRendererComponent}
+   * is called with a selected cell object, the component returned will
+   * have its "background" property set to this color.
+   */
+  Color selectionForeground;
+
+  /** 
+   * This property holds a description of which data elements in the {@link
+   * #model} property should be considered "selected", when displaying and
+   * interacting with the list.
+   */
+  ListSelectionModel selectionModel;
+
+
+  /**
+   * This property indicates that the list's selection is currently
+   * "adjusting" -- perhaps due to a user actively dragging the mouse over
+   * multiple list elements -- and is therefore likely to change again in
+   * the near future. A {@link ListSelectionListener} might choose to delay
+   * updating its view of the list's selection until this property is
+   * false, meaning that the adjustment has completed.
+   */
+  boolean valueIsAdjusting;
+
+  /** 
+   * This property indicates a <em>preference</em> for the number of rows
+   * displayed in the list, and will scale the
+   * {@link #preferredScrollableViewportSize} property accordingly. The actual
+   * number of displayed rows, when the list is placed in a real {@link
+   * Viewport} or other component, may be greater or less than this number.
+   */
+  int visibleRowCount;
+
+
+
+  /**
+   * Fire a {@link ListSelectionEvent} to all the registered ListSelectionListeners.
+   */
+  void fireSelectionValueChanged(int firstIndex, int lastIndex, boolean isAdjusting) 
+  {
+    ListSelectionEvent evt = new ListSelectionEvent(this, firstIndex, lastIndex, isAdjusting);
+    ListSelectionListener listeners[] = getListSelectionListeners();
+    for (int i = 0; i < listeners.length; ++i)
+      {
+        listeners[i].valueChanged(evt);
+      }
+  }
+
+
+  /**
+   * This private listener propagates {@link ListSelectionEvent} events
+   * from the list's "selectionModel" property to the list's {@link
+   * ListSelectionListener} listeners. It also listens to {@link
+   * ListDataEvent} events from the list's {@link #model} property. If this
+   * class receives either type of event, it triggers repainting of the
+   * list.
+   */
+  private class ListListener 
+    implements ListSelectionListener, ListDataListener
+  {
+    // ListDataListener events
+    public void contentsChanged(ListDataEvent event)
+    {
+      JList.this.repaint();
+    }
+    public void intervalAdded(ListDataEvent event)
+    {
+      JList.this.repaint();
+    }
+    public void intervalRemoved(ListDataEvent event)
+    {
+      JList.this.repaint();
+    }
+    // ListSelectionListener events
+    public void valueChanged(ListSelectionEvent event)
+    {
+      JList.this.fireSelectionValueChanged(event.firstIndex,
+                                           event.lastIndex,
+                                           event.isAdjusting);
+      JList.this.repaint();
+    }
+  };
+
+  /** 
+   * Shared ListListener instance, subscribed to both the current {@link
+   * #model} and {@link #selectionModel} properties of the list.
+   */
+  ListListener listListener;
+
+
+  /**
+   * Creates a new JList object.
+   */
     public JList()
     {	
 	init();
     }
 
+  /**
+   * Creates a new JList object.
+   *
+   * @param listData Initial data to populate the list with
+   */
     public JList(Object[] listData)
     {
 	init();
 	setListData(listData);
     }
 
-
+  /**
+   * Creates a new JList object.
+   *
+   * @param listData Initial data to populate the list with
+   */
     public JList(Vector listData)
     {
 	init();
 	setListData(listData);
     }
 
-
+  /**
+   * Creates a new JList object.
+   *
+   * @param listData Initial data to populate the list with
+   */
     public JList(ListModel listData)
     {
 	init();
 	setModel(listData);
     }
+
     void init()
     {
-	render = new DefaultCellRenderer();
+    dragEnabled = false;
+    fixedCellHeight = -1;
+    fixedCellWidth = -1;
+    layoutOrientation = VERTICAL;
+    opaque = true;
+    valueIsAdjusting = false;
+    visibleRowCount = 8;
 	
-	sel_model = new DefaultListSelectionModel();
-	setModel(new DefaultListModel());
+    cellRenderer = new DefaultListCellRenderer();
+    listListener = new ListListener();
 
-	select_back = new Color(0,0,255);
-	select_fore = new Color(255,255,255);
+    setModel(new DefaultListModel());
+    setSelectionModel(new DefaultListSelectionModel());
 
 	updateUI();
     }
 
+  /**
+   * Gets the value of the {@link #fixedCellHeight} property. This property
+   * may be <code>-1</code> to indicate that no cell height has been
+   * set. This property is also set implicitly when the
+   * {@link #prototypeCellValue} property is set.
+   *
+   * @return The current value of the property 
+   * 
+   * @see #fixedCellHeight
+   * @see #setFixedCellHeight
+   * @see #setPrototypeCellValue
+   */
+  public int getFixedCellHeight()
+  {
+    return fixedCellHeight;
+  }
+
+  /**
+   * Sets the value of the {@link #fixedCellHeight} property. This property
+   * may be <code>-1</code> to indicate that no cell height has been
+   * set. This property is also set implicitly when the {@link
+   * #prototypeCellValue} property is set, but setting it explicitly
+   * overrides the height computed from {@link #prototypeCellValue}.
+   *
+   * @see #getFixedCellHeight
+   * @see #getPrototypeCellValue
+   */
+  public void setFixedCellHeight(int h)
+  {
+    int old = fixedCellHeight;
+    fixedCellHeight = h;
+    firePropertyChange(FIXED_CELL_WIDTH_PROPERTY_CHANGED, old, h);
+  }
+
+
+  /**
+   * Gets the value of the {@link #fixedCellWidth} property. This property
+   * may be <code>-1</code> to indicate that no cell width has been
+   * set. This property is also set implicitly when the {@link
+   * #prototypeCellValue} property is set.
+   *
+   * @return The current value of the property 
+   * 
+   * @see #setFixedCellWidth
+   * @see #setPrototypeCellValue
+   */
+  public int getFixedCellWidth()
+  {
+    return fixedCellWidth;
+  }
+
+  /**
+   * Sets the value of the {@link #fixedCellWidth} property. This property
+   * may be <code>-1</code> to indicate that no cell width has been
+   * set. This property is also set implicitly when the {@link
+   * #prototypeCellValue} property is set, but setting it explicitly
+   * overrides the width computed from {@link #prototypeCellValue}.
+   *
+   * @see #getFixedCellWidth
+   * @see #getPrototypeCellValue
+   */
+  public void setFixedCellWidth(int h)
+  {
+    int old = fixedCellHeight;
+    fixedCellHeight = h;
+    firePropertyChange(FIXED_CELL_HEIGHT_PROPERTY_CHANGED, old, h);
+  }
+
+
+  /** 
+   * Gets the value of the {@link #visibleRowCount} property. 
+   *
+   * @return the current value of the property.
+   */
     
     public int getVisibleRowCount()
-    { return visibles; }
-    public void setVisibleRowCount(int visibleRowCount)
     {
-	visibles =  visibleRowCount;
-	invalidate();
+    return visibleRowCount;
+  }
+
+  /**
+   * Sets the value of the {@link #visibleRowCount} property. 
+   *
+   * @param visibleRowCount The new property value
+   */
+  public void setVisibleRowCount(int vc)
+  {
+    visibleRowCount = vc;
+    revalidate();
 	repaint();
     }
 
+  /**
+   * Adds a {@link ListSelectionListener} to the listener list for this
+   * list. The listener will be called back with a {@link
+   * ListSelectionEvent} any time the list's {@link #selectionModel}
+   * property changes. The source of such events will be the JList,
+   * not the selection model.
+   *
+   * @param listener The new listener to add
+   */
   public void addListSelectionListener (ListSelectionListener listener)
   {
-    sel_model.addListSelectionListener (listener);
+    listenerList.add (ListSelectionListener.class, listener);
   }
   
+  /**
+   * Removes a {@link ListSelectionListener} from the listener list for
+   * this list. The listener will no longer be called when the list's
+   * {@link #selectionModel} changes.
+   *
+   * @param listener The listener to remove
+   */
   public void removeListSelectionListener (ListSelectionListener listener)
   {
-    sel_model.removeListSelectionListener (listener);
+    listenerList.remove(ListSelectionListener.class, listener);
   }
 
   /**
+   * Returns an array of all ListSelectionListeners subscribed to this
+   * list. 
+   *
+   * @return The current subscribed listeners
+   *
    * @since 1.4
    */
   public ListSelectionListener[] getListSelectionListeners()
   {
-    throw new Error ("not implemented");
+    return (ListSelectionListener[]) getListeners(ListSelectionListener.class);
+  }
+
+  /**
+   * Sets the list's "selectionMode" property, which simply mirrors the
+   * same property on the list's {@link #selectionModel} property. This
+   * property should be one of the integer constants
+   * <code>SINGLE_SELECTION</code>, <code>SINGLE_INTERVAL_SELECTION</code>,
+   * or <code>MULTIPLE_INTERVAL_SELECTION</code> from the {@link
+   * ListSelectionModel} interface.
+   *
+   * @param a The new selection mode
+   */
+  public void setSelectionMode(int a)
+  {
+    selectionModel.setSelectionMode(a);
   }
 
-    void setSelectionMode(int a)
-    {  sel_model.setSelectionMode(a);   }
-    void setSelectedIndex(int a)
-    {  sel_model.setSelectionInterval(a,a); }
-    int getSelectedIndex()
-    {	return sel_model.getMinSelectionIndex();    }
-    Object getSelectedValue()
+  /**
+   * Adds the interval <code>[a,a]</code> to the set of selections managed
+   * by this list's {@link #selectionModel} property. Depending on the
+   * selection mode, this may cause existing selections to become invalid,
+   * or may simply expand the set of selections. 
+   *
+   * @param a A number in the half-open range <code>[0, x)</code> where
+   * <code>x = getModel.getSize()</code>, indicating the index of an
+   * element in the list to select.
+   *
+   * @see #setSelectionMode
+   * @see #selectionModel
+   */
+  public void setSelectedIndex(int a)
+  {
+    selectionModel.setSelectionInterval(a, a);
+  }
+
+  /**
+   * Returns the minimum index of an element in the list which is currently
+   * selected.
+   *
+   * @return A number in the half-open range <code>[0, x)</code> where
+   * <code>x = getModel.getSize()</code>, indicating the minimum index of
+   * an element in the list for which the element is selected, or
+   * <code>-1</code> if no elements are selected
+   */
+  public int getSelectedIndex()
+  {
+    return selectionModel.getMinSelectionIndex();
+  }
+
+  /**
+   * Indicates whether the list element at a given index value is
+   * currently selected.
+   *
+   * @param a The index to check 
+   * @return <code>true</code> if <code>a</code> is the index of a selected
+   * list element
+   */
+  public boolean isSelectedIndex(int a)
+  {
+    return selectionModel.isSelectedIndex(a);
+  }
+
+  /**
+   * Returns the first value in the list's {@link #model} property which is
+   * selected, according to the list's {@link #selectionModel} property.
+   * This is equivalent to calling
+   * <code>getModel()getElementAt(getSelectedIndex())</code>, with a check
+   * for the special index value of <code>-1</code> which returns null
+   * <code>null</code>.
+   *
+   * @return The first selected element, or <code>null</code> if no element
+   * is selected.
+   */
+  public Object getSelectedValue()
     {  
 	int index = getSelectedIndex();
 	if (index == -1)
@@ -139,116 +574,360 @@
 	return getModel().getElementAt(index);
     }
 
-    Color getSelectionBackground()
-    { return select_back;    }    
-    Color getSelectionForeground()
-    { return select_fore;    }
+  /**
+   * Gets the value of the {@link #selectionBackground} property.
+   *
+   * @return The current value of the property
+   */
+  public Color getSelectionBackground()
+  {
+    return selectionBackground;
+  }
+
+  /**
+   * Sets the value of the {@link #selectionBackground} property.
+   *
+   * @param c The new value of the property
+   */
+  public void setSelectionBackground(Color c)
+  {
+    Color old = selectionBackground;
+    selectionBackground = c;
+    firePropertyChange(SELECTION_BACKGROUND_PROPERTY_CHANGED, old, c);
+    repaint();
+  }
 
+  /**
+   * Gets the value of the {@link #selectionForeground} property.
+   *
+   * @return The current value of the property
+   */
+  public Color getSelectionForeground()
+  {
+    return selectionForeground;
+  }
+  
+  /**
+   * Sets the value of the {@link #selectionForeground} property.
+   *
+   * @param c The new value of the property
+   */
+  public void setSelectionForeground(Color c)
+  {
+    Color old = selectionForeground;
+    selectionForeground = c;
+    firePropertyChange(SELECTION_FOREGROUND_PROPERTY_CHANGED, old, c);
+  }
 
+  /**
+   * Sets the {@link #model} property of the list to a new anonymous
+   * {@link AbstractListModel} subclass which accesses the provided Object
+   * array directly.
+   *
+   * @param listData The object array to build a new list model on
+   * @see #setModel
+   */
     public void setListData(final Object[] listData)
     {
-	class AL extends AbstractListModel
+    setModel(new AbstractListModel()
 	{
-	    public int getSize()              { return listData.length; }
-	    public Object getElementAt(int i) { return listData[i];     }
-	};
+          public int getSize()
+          {
+            return listData.length;
+          }
 	
-	setModel (new AL());
+          public Object getElementAt(int i)
+          {
+            return listData[i];
+          }
+        });
     }
     
+  /**
+   * Sets the {@link #model} property of the list to a new anonymous {@link
+   * AbstractListModel} subclass which accesses the provided vector
+   * directly.
+   *
+   * @param listData The object array to build a new list model on
+   * @see #setModel
+   */
     public void setListData(final Vector listData)
     {
-	class AL extends AbstractListModel 
+    setModel(new AbstractListModel()
 	{
-	    public int getSize()              { return listData.size(); }
-	    public Object getElementAt(int i) { return listData.elementAt(i); }
-	};
-	
-        setModel (new AL());
+          public int getSize()
+          {
+            return listData.size();
     }
     
+          public Object getElementAt(int i)
+          {
+            return listData.elementAt(i);
+          }
+        });
+  }
     
+  /**
+   * Gets the value of the {@link #cellRenderer} property. 
+   *
+   * @return The current value of the property
+   */
     public ListCellRenderer getCellRenderer()
-    {    return  render; }
-    public void setCellRenderer(ListCellRenderer cellRenderer)
     {
-	render = cellRenderer;
-	invalidate();
-	repaint();
+    return cellRenderer;
     }
     
-    public void setModel(ListModel model)
-    {
-	ListDataListener l = new ListDataListener()
+  /**
+   * Sets the value of the {@link #celLRenderer} property.
+   *
+   * @param cellRenderer The new property value
+   */
+  public void setCellRenderer(ListCellRenderer cr)
 	    {
-		public void intervalAdded(ListDataEvent e) {
-		    repaint();
-		}
-		public void intervalRemoved(ListDataEvent e) {
+    ListCellRenderer old = cellRenderer;
+    cellRenderer = cr;
+    firePropertyChange(CELL_RENDERER_PROPERTY_CHANGED, old, cr);
+    revalidate();
 		    repaint();
 		}
-		public void contentsChanged(ListDataEvent e) {
-		    repaint();
+
+  /**
+   * Gets the value of the {@link #model} property. 
+   *
+   * @return The current value of the property
+   */
+  public ListModel getModel()
+  {
+    return model;
 		}
-	    };
 	
-	this.model = model;  
-	model.addListDataListener(l);	
+  /**
+   * Sets the value of the {@link #model} property. The list's {@link
+   * #listListener} is unsubscribed from the existing model, if it exists,
+   * and re-subscribed to the new model.
+   *
+   * @param model The new property value
+   */
+  public void setModel(ListModel m)
+  {
+    ListModel old = model;
+    if (old != null)
+      old.removeListDataListener(listListener);
+    model = m;
+    if (model != null)
+      model.addListDataListener(listListener);
+    firePropertyChange(MODEL_PROPERTY_CHANGED, old, m);
     }
 
-    public ListModel getModel() 
-    {  return model;        }
     
+  public ListSelectionModel getSelectionModel()
+  {
+    return selectionModel;
+  }
     
+  /**
+   * Sets the value of the {@link #selectionModel} property. The list's
+   * {@link #listListener} is unsubscribed from the existing selection
+   * model, if it exists, and re-subscribed to the new selection model.
+   *
+   * @param l The new property value
+   */
+  public void setSelectionModel(ListSelectionModel l)
+  {
+    ListSelectionModel old = selectionModel;
+    if (old != null)
+      old.removeListSelectionListener(listListener);
+    selectionModel = l;
+    if (selectionModel != null)
+      selectionModel.addListSelectionListener(listListener);
+    firePropertyChange(SELECTION_MODEL_PROPERTY_CHANGED, old, l);
+  }
+
+  /**
+   * Gets the value of the UI property.
+   *
+   * @return The current property value
+   */
     public ListUI getUI()
-    {  return (ListUI) ui;    }
+  {
+    return (ListUI) ui;
+  }
+
+  /**
+   * Sets the value of the UI property.
+   *
+   * @param ui The new property value
+   */
     public void setUI(ListUI ui)
-    {   super.setUI(ui);      }
+  {
+    super.setUI(ui);
+  }
 
+  /**
+   * Calls {@link #setUI} with the {@link ListUI} subclass
+   * returned from calling {@link UIManager#getUI}.
+   */
     public void updateUI()
     {
         setUI((ListUI)UIManager.getUI(this));
     }
 
+  /**
+   * Return the class identifier for the list's UI property.  This should
+   * be the constant string <code>"ListUI"</code>, and map to an
+   * appropriate UI class in the {@link UIManager}.
+   *
+   * @return The class identifier
+   */
     public String getUIClassID()
     {
 	return "ListUI";
     }
 
 
+  /**
+   * Returns the current value of the {@link #prototypeCellValue}
+   * property. This property holds a reference to a "prototype" data value
+   * -- typically a String -- which is used to calculate the {@link
+   * #fixedCellWidth} and {@link #fixedCellHeight} properties, using the
+   * {@link #cellRenderer} property to acquire a component to render the
+   * prototype.
+   *
+   * @return The current prototype cell value
+   * @see #setPrototypeCellValue
+   */
+  public Object getPrototypeCellValue()
+  {
+    return prototypeCellValue;
+  }
+
+  /**
+   * <p>Set the {@link #prototypeCellValue} property. This property holds a
+   * reference to a "prototype" data value -- typically a String -- which
+   * is used to calculate the {@link #fixedCellWidth} and {@link
+   * #fixedCellHeight} properties, using the {@link #cellRenderer} property
+   * to acquire a component to render the prototype.</p>
+   *
+   * <p>It is important that you <em>not</em> set this value to a
+   * component. It has to be a <em>data value</em> such as the objects you
+   * would find in the list's model. Setting it to a component will have
+   * undefined (and undesirable) affects. </p>
+   *
+   * @param obj The new prototype cell value
+   * @see #getPrototypeCellValue
+   */
+  public void setPrototypeCellValue(Object obj)
+  {
+    Object old = prototypeCellValue;
+    Component comp = getCellRenderer()
+      .getListCellRendererComponent(this, obj, 0, false, false); 
+    Dimension d = comp.getPreferredSize();
+    fixedCellWidth = d.width;
+    fixedCellHeight = d.height;
+    prototypeCellValue = obj;
+    firePropertyChange(PROTOTYPE_CELL_VALUE_PROPERTY_CHANGED, old, obj);
+  }
+
     public AccessibleContext getAccessibleContext()
     {
       return null;
     }
 
+  /**
+   * Returns a size indicating how much space this list would like to
+   * consume, when contained in a scrollable viewport. This is part of the
+   * {@link Scrollable} interface, which interacts with {@link
+   * ScrollPaneLayout} and {@link Viewport} to define scrollable objects.
+   *
+   * @return The preferred size, or <code>null</code>
+   */
     public Dimension getPreferredScrollableViewportSize()
     {
 	return null;
     }
 
+  /**
+   * <p>Return the number of pixels the list must scroll in order to move a
+   * "unit" of the list into the provided visible rectangle. When the
+   * provided direction is positive, the call describes a "downwards"
+   * scroll, which will be exposing a cell at a <em>greater</em> index in
+   * the list than those elements currently showing. Then the provided
+   * direction is negative, the call describes an "upwards" scroll, which
+   * will be exposing a cell at a <em>lesser</em> index in the list than
+   * those elements currently showing.</p>
+   *
+   * <p>If the provided orientation is <code>HORIZONTAL</code>, the above
+   * comments refer to "rightwards" for positive direction, and "leftwards"
+   * for negative.</p>
+   * 
+   *
+   * @param visibleRect The rectangle to scroll an element into
+   * @param orientation One of the numeric consants <code>VERTICAL</code>
+   * or <code>HORIZONTAL</code>
+   * @param direction An integer indicating the scroll direction: positive means
+   * forwards (down, right), negative means backwards (up, left)
+   *
+   * @return The scrollable unit increment, in pixels
+   */
     public int getScrollableUnitIncrement(Rectangle visibleRect,
-					  int orientation,
-					  int direction)
+                                        int orientation, int direction)
     {
 	return 1;
     }
 
+  /**
+   * <p>Return the number of pixels the list must scroll in order to move a
+   * "block" of the list into the provided visible rectangle. When the
+   * provided direction is positive, the call describes a "downwards"
+   * scroll, which will be exposing a cell at a <em>greater</em> index in
+   * the list than those elements currently showing. Then the provided
+   * direction is negative, the call describes an "upwards" scroll, which
+   * will be exposing a cell at a <em>lesser</em> index in the list than
+   * those elements currently showing.</p>
+   *
+   * <p>If the provided orientation is <code>HORIZONTAL</code>, the above
+   * comments refer to "rightwards" for positive direction, and "leftwards"
+   * for negative.</p>
+   * 
+   *
+   * @param visibleRect The rectangle to scroll an element into
+   * @param orientation One of the numeric consants <code>VERTICAL</code>
+   * or <code>HORIZONTAL</code>
+   * @param direction An integer indicating the scroll direction: positive means
+   * forwards (down, right), negative means backwards (up, left)
+   *
+   * @return The scrollable unit increment, in pixels
+   */
     public int getScrollableBlockIncrement(Rectangle visibleRect,
-					   int orientation,
-					   int direction)
+                                         int orientation, int direction)
     {
 	return 1;
     }
 
+  /**
+   * Gets the value of the {@link #scrollableTracksViewportWidth} property.
+   *
+   * @return <code>true</code> if the viewport is larger (horizontally)
+   * than the list and the list should be expanded to fit the viewport;
+   * <code>false</code> if the viewport is smaller than the list and the
+   * list should scroll (horizontally) within the viewport
+   */
     public boolean getScrollableTracksViewportWidth()
     {
 	return false;
     }
 
+  /**
+   * Gets the value of the {@link #scrollableTracksViewportWidth} property.
+   *
+   * @return <code>true</code> if the viewport is larger (vertically)
+   * than the list and the list should be expanded to fit the viewport;
+   * <code>false</code> if the viewport is smaller than the list and the
+   * list should scroll (vertically) within the viewport
+   */
     public boolean getScrollableTracksViewportHeight()
     {
 	return false;
     }
-    
 }
--- javax/swing/DefaultListSelectionModel.java	27 Jan 2004 18:55:11 -0000	1.4
+++ javax/swing/DefaultListSelectionModel.java	25 Feb 2004 23:56:23 -0000
@@ -35,141 +35,506 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package javax.swing;
 
 import java.io.Serializable;
 import java.util.EventListener;
-import java.util.Vector;
+import java.util.BitSet;
 import javax.swing.event.EventListenerList;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 
-public class DefaultListSelectionModel implements Cloneable, ListSelectionModel, Serializable
+
+/**
+ * <p>This class provides a default implementation of {@link
+ * ListSelectioModel}, which is used by {@link javax.swing.JList} and
+ * similar classes to manage the selection status of a number of data
+ * elements. </p>
+ *
+ * <p>The class is organized <em>abstractly</em> as a set of intervals of
+ * integers. Each interval indicates an inclusive range of indices in a
+ * list -- held by some other object and unknown to this class -- which is
+ * considered "selected". There are various accessors for querying and
+ * modifying the set of intervals, with simplified forms accepting a single
+ * index, representing an interval with only one element. </p>
+ */
+public class DefaultListSelectionModel implements Cloneable,
+                                                  ListSelectionModel,
+                                                  Serializable
 {
+
+  /** The list of ListSelectionListeners subscribed to this selection model. */
   protected EventListenerList listenerList = new EventListenerList();
   
-    int mode = SINGLE_SELECTION;
 
-    Vector sel = new Vector();
+  /** 
+   * The current list selection mode. Must be one of the numeric constants
+   * <code>SINGLE_SELECTION</code>, <code>SINGLE_INTERVAL_SELECTION</code>
+   * or <code>MULTIPLE_INTERVAL_SELECTION</code> from {@link
+   * ListSelectionModel}. The default value is
+   * <code>MULTIPLE_INTERVAL_SELECTION</code>.
+   */
+  int selectionMode = MULTIPLE_INTERVAL_SELECTION;
 
-    class Range
-    {
-	int i0, i1;
 
-	Range(int a, int b)
-	{
-	    if (a > b)
+  /**
+   * The index of the "lead" of the most recent selection. The lead is the
+   * second argument in any call to {@link #setSelectionInterval}, {@link
+   * #addSelectionInterval} or {@link #removeSelectionInterval}. Generally
+   * the lead refers to the most recent position a user dragged their mouse
+   * over.
+   */
+  int leadSelectionIndex = -1;
+
+
+  /**
+   * The index of the "anchor" of the most recent selection. The anchor is
+   * the first argument in any call to {@link #setSelectionInterval},
+   * {@link #addSelectionInterval} or {@link
+   * #removeSelectionInterval}. Generally the anchor refers to the first
+   * recent position a user clicks when they begin to drag their mouse over
+   * a list.
+   *
+   * @see #getAnchorSelectionIndex
+   * @see #setAnchorSelectionIndex
+   */
+  int anchorSelectionIndex = -1;
+
+
+  /**
+   * controls the range of indices provided in any {@link
+   * ListSelectionEvent} fired by the selectionModel. Let
+   * <code>[A,L]</code> be the range of indices between {@link
+   * anchorSelectionIndex} and {@link leadSelectionIndex} inclusive, and
+   * let <code>[i0,i1]</code> be the range of indices changed in a given
+   * call which generates a {@link ListSelectionEvent}. Then when this
+   * property is <code>true</code>, the {@link ListSelectionEvent} contains
+   * the range <code>[A,L] union [i0,i1]</code>; when <code>false</code> it
+   * will contain only <code>[i0,i1]</code>. The default is
+   * <code>true</code>.
+   *
+   * @see #isLeadAnchorNotificationEnabled
+   * @see #setLeadAnchorNotificationEnabled
+   */
+  boolean leadAnchorNotificationEnabled = true;
+
+
+  /**
+   * Whether the selection is currently "adjusting". Any {@link
+   * ListSelectionEvent} events constructed in response to changes in this
+   * list selection model will have their {@link
+   * ListSelectionEvent#isAdjusting} field set to this value.
+   *
+   * @see #getValueIsAdjusting
+   * @see #setValueIsAdjusting
+   */
+  boolean valueIsAdjusting = false;
+
+
+  /** 
+   * The current set of "intervals", represented simply by a {@link
+   * java.util.BitSet}. A set bit indicates a selected index, whereas a
+   * cleared bit indicates a non-selected index.
+   */
+  BitSet sel = new BitSet();
+
+
+  /**
+   * Gets the value of the {@link #selectionMode} property.
+   *
+   * @return The current value of the property
+   */
+  public int getSelectionMode()
 		{
-		    i0 = b;
-		    i1 = a;
+    return selectionMode;
 		}
-	    else
+
+  /**
+   * Sets the value of the {@link #selectionMode} property.
+   *
+   * @param a The new value of the property
+   */
+  public void setSelectionMode(int a)
 		{
-		    i0 = a; 
-		    i1 = b;
-		}
+    selectionMode = a;
 	}
+
+  /**
+   * Gets the value of the {@link #anchorSelectionIndex} property.
+   * 
+   * @return The current property value
+   *
+   * @see #setAnchorSelectionIndex
+   */
+  public int getAnchorSelectionIndex()
+  {
+    return anchorSelectionIndex;
     }
 
+  /**
+   * Sets the value of the {@link #anchorSelectionIndex} property.
+   * 
+   * @param anchorIndex The new property value
+   *
+   * @see #getAnchorSelectionIndex
+   */
+  public void setAnchorSelectionIndex(int anchorIndex)
+  {
+    anchorSelectionIndex = anchorIndex;
+  }
     
-    public int getMinSelectionIndex()
+  /**
+   * Gets the value of the {@link #leadSelectionIndex} property.
+   * 
+   * @return The current property value
+   *
+   * @see #setLeadSelectionIndex
+   */
+  public int getLeadSelectionIndex()
     {
-	if (isSelectionEmpty())
-	    return -1;
+    return leadSelectionIndex;
+  }
 	
-	boolean first = true;
-	int min = -1;
-	for (int i=0;i<sel.size();i++)
+  /**
+   * <p>Sets the value of the {@link #anchorSelectionIndex} property. As a
+   * side effect, alters the selection status of two ranges of indices. Let
+   * <code>OL</code> be the old lead selection index, <code>NL</code> be
+   * the new lead selection index, and <code>A</code> be the anchor
+   * selection index. Then if <code>A</code> is a valid selection index,
+   * one of two things happens depending on the seleciton status of
+   * <code>A</code>:</p>
+   *
+   * <ul>
+   *
+   * <li><code>isSelectedIndex(A) == true</code>: set <code>[A,OL]</code>
+   * to <em>deselected</em>, then set <code>[A,NL]</code> to
+   * <em>selected</em>.</li>
+   *
+   * <li><code>isSelectedIndex(A) == false</code>: set <code>[A,OL]</code>
+   * to <em>selected</em>, then set <code>[A,NL]</code> to
+   * <em>deselected</em>.</li>
+   *
+   * </ul>
+   *
+   * <p>This method generates at most a single {@link ListSelectionEvent}
+   * despite changing multiple ranges. The range of values provided to the
+   * {@link ListSelectionEvent} includes only the minimum range of values
+   * which changed selection status between the beginning and end of the
+   * method.</p>
+   * 
+   * @param anchorIndex The new property value
+   *
+   * @see #getAnchorSelectionIndex
+   */
+  public void setLeadSelectionIndex(int leadIndex)
 	    {
-		Range r = (Range) sel.get(i);
+    int oldLeadIndex = leadSelectionIndex;
+    leadSelectionIndex = leadIndex;
+
+    if (anchorSelectionIndex == -1)
+      return;
+
+    int R1 = Math.min(anchorSelectionIndex, oldLeadIndex);
+    int R2 = Math.max(anchorSelectionIndex, oldLeadIndex);
+    int S1 = Math.min(anchorSelectionIndex, leadIndex);
+    int S2 = Math.max(anchorSelectionIndex, leadIndex);
 
-		if (first)
+    int lo = Math.min(R1, S1);
+    int hi = Math.max(R2, S2);
+
+    BitSet oldRange = sel.get(lo, hi+1);
+
+    if (isSelectedIndex(anchorSelectionIndex))
 		    {
-			min = r.i0;
-			first = false;
+        sel.clear(R1, R2+1);
+        sel.set(S1, S2+1);
 		    }	
 		else
 		    {
-			if (r.i0 > min)
-			    {
-				min = r.i0;
-			    }
+        sel.set(R1, R2+1);
+        sel.clear(S1, S2+1);
 		    }
+    
+    BitSet newRange = sel.get(lo, hi+1);
+    newRange.xor(oldRange);
+
+    int beg = sel.nextSetBit(0), end = -1;
+    for(int i=beg; i >= 0; i=sel.nextSetBit(i+1)) 
+      { 
+        end = i;
 	    }
-	return min;
+    fireSelectionValueChanged(beg, end, valueIsAdjusting);    
     }
 
-    public int getMaxSelectionIndex()
+  /**
+   * Gets the value of the {@link #leadAnchorNotificationEnabled} property.
+   * 
+   * @return The current property value
+   *
+   * @see #setLeadAnchorNotificationEnabled
+   */
+  public boolean isLeadAnchorNotificationEnabled()
     {
-	if (isSelectionEmpty())
-	    return -1;
+    return leadAnchorNotificationEnabled;
+  }
 
-	boolean first = true;
-	int max = -1;
-	for (int i=1;i<sel.size();i++)
+  /**
+   * Sets the value of the {@link #leadAnchorNotificationEnabled} property.
+   * 
+   * @param flag The new property value
+   *
+   * @see #getLeadAnchorNotificationEnabled
+   */
+  public void setLeadAnchorNotificationEnabled(boolean l)
 	    {
-		Range r = (Range) sel.get(i);
+    leadAnchorNotificationEnabled = l;
+  }
+
 		
-		if (first)
+  /**
+   * Gets the value of the {@link #valueIsAdjusting} property.
+   *
+   * @return The current property value
+   *
+   * @see #setValueIsAdjusting
+   */
+  public boolean getValueIsAdjusting()
 		    {
-			max = r.i1;
+    return valueIsAdjusting;
 		    }
-		else
-		    {
-			if (r.i1 > max)
+
+  /**
+   * Sets the value of the {@link #valueIsAdjusting} property.
+   *
+   * @param v The new property value
+   *
+   * @see #getValueIsAdjusting
+   */
+  public void setValueIsAdjusting(boolean v)
 			    {
-				max = r.i1;
-			    }
-		    }
+    valueIsAdjusting = v;
 	    }
-	return max;
+
+  /**
+   * Determines whether the selection is empty.
+   *
+   * @return <code>true</code> if the selection is empty, otherwise
+   * <code>false</code>
+   */
+  public boolean isSelectionEmpty()
+  {
+    return sel.isEmpty();
     }
 
-    public boolean isSelectedIndex(int a)
+
+  /**
+   * Gets the smallest index which is currently a member of a selection
+   * interval.
+   *
+   * @return The least integer <code>i</code> such that <code>i >=
+   * 0</code> and <code>i</code> is a member of a selected interval, or
+   * <code>-1</code> if there are no selected intervals
+   *
+   * @see #getMaxSelectionIndex
+   */
+  public int getMinSelectionIndex()
     {
-	for (int i=0;i<sel.size();i++)
+    if (isSelectionEmpty())
+      return -1;
+    
+    return sel.nextSetBit(0);
+  }
+
+  /**
+   * Gets the largest index which is currently a member of a selection
+   * interval.
+   *
+   * @return The greatest integer <code>i</code> such that <code>i >=
+   * 0</code> and <code>i</code> is a member of a selected interval, or
+   * <code>-1</code> if there are no selected intervals
+   *
+   * @see #getMinSelectionIndex
+   */
+  public int getMaxSelectionIndex()
 	    {
-		Range r = (Range) sel.get(i);
-		if (r.i0 <= a &&
-		    r.i1 >= a)
+    if (isSelectionEmpty())
+      return -1;
+
+    int mx = -1;
+    for(int i=sel.nextSetBit(0); i >= 0; i=sel.nextSetBit(i+1)) 
 		    {
-			return true;
+        mx = i;
 		    }
+    return mx;
 	    }
-	return false;
+
+  /**
+   * Determines whether a particular index is a member of a selection
+   * interval.
+   *
+   * @param a The index to search for
+   *
+   * @return <code>true</code> if the index is a member of a selection interval,
+   * otherwise <code>false</code>
+   */
+  public boolean isSelectedIndex(int a)
+  {
+    return sel.get(a);
     }
 
+  /**
+   * If the {@link #selectionMode} property is equal to
+   * <code>SINGLE_SELECTION</code> or
+   * <code>SINGLE_INTERVAL_SELECTION</code>, equivalent to calling
+   * <code>setSelectionInterval(index1, index2)</code>; otherwise adds the
+   * range <code>[index0, index1]</code> to the selection interval set.
+   *
+   * @param index0 The beginning of the range of indices to select
+   * @param index1 The end of the range of indices to select
+   *
+   * @see #setSelectionInterval
+   * @see #removeSelectionInterval
+   */
+  public void addSelectionInterval(int index0, int index1) 
+  {
+    if (selectionMode == SINGLE_SELECTION
+        || selectionMode == SINGLE_INTERVAL_SELECTION)
+      sel.clear();
+    
+    if (selectionMode == SINGLE_SELECTION)
+      index0 = index1;
 
-    public int getSelectionMode()
-    { return mode; }
-    public void setSelectionMode(int a)
-    {	mode = a;    }
+    int lo = Math.min(index0, index1);
+    int hi = Math.max(index0, index1);
 
-    boolean isSelectionEmpty() 
+    sel.set(lo, hi+1);
+    fireSelectionValueChanged(lo, hi, valueIsAdjusting);
+  }
+
+
+  /**
+   * Deselects all indices in the inclusive range
+   * <code>[index0,index1]</code>.
+   *
+   * @param index0 The beginning of the range of indices to deselect
+   * @param index1 The end of the range of indices to deselect
+   *
+   * @see #addSelectionInterval
+   * @see #setSelectionInterval
+   */
+  public void removeSelectionInterval(int index0,
+                                      int index1)
     {
-	return sel.size() == 0;
+    int lo = Math.min(index0, index1);
+    int hi = Math.max(index0, index1);
+    sel.clear(lo, hi+1); 
+    fireSelectionValueChanged(lo, hi, valueIsAdjusting);
     }
 
+  /**
+   * Removes all intervals in the selection set.
+   */
     public void clearSelection()
     {
-	sel.removeAllElements();
+    int sz = sel.size();
+    sel.clear();
+    fireSelectionValueChanged(0, sz, valueIsAdjusting);
     }
 
+  /**
+   * Clears the current selection and marks a given interval as
+   * "selected". If the current selection mode is
+   * <code>SINGLE_SELECTION</code> only the index <code>index2</code> is
+   * selected.
+   *
+   * @param index0 The low end of the new selection 
+   * @param index1 The high end of the new selection
+   */
     public void setSelectionInterval(int index0, int index1) 
     {
-	if (mode == SINGLE_SELECTION)
+    sel.clear();
+    if (selectionMode == SINGLE_SELECTION)
+      index0 = index1;
+
+    int lo = Math.min(index0, index1);
+    int hi = Math.max(index0, index1);
+    sel.set(lo, hi+1);
+    fireSelectionValueChanged(lo, hi, valueIsAdjusting);
+  }
+
+  /**
+   * Inserts a number of indices either before or after a particular
+   * position in the set of indices. Renumbers all indices after the
+   * inserted range. The new indices in the inserted range are not
+   * selected. This method is typically called to synchronize the selection
+   * model with an inserted range of elements in a {@link ListModel}.
+   *
+   * @param index The position to insert indices at
+   * @param length The number of indices to insert
+   * @param before Indicates whether to insert the indices before the index
+   * or after it
+   */
+  public void insertIndexInterval(int index,
+                                  int length,
+                                  boolean before)
+  {
+    if (!before)
+      {        
+        index++;
+        length--;
+      }
+    BitSet tmp = sel.get(index, sel.size());
+    sel.clear(index, sel.size());
+    int n = tmp.size();
+    for (int i = 0; i < n; ++i)
+      sel.set(index + length + i, tmp.get(i));
+  }
+
+  /**
+   * Removes a range from the set of indices. Renumbers all indices after
+   * the removed range. This method is typically called to synchronize the
+   * selection model with a deleted range of elements in a {@link
+   * ListModel}.
+   *
+   * @param index0 The first index to remove (inclusive)
+   * @param index1 The last index to remove (inclusive)
+   */
+  public void removeIndexInterval(int index0,
+                                  int index1)
 	    {
-		sel.removeAllElements();
+    int lo = Math.min(index0, index1);
+    int hi = Math.max(index0, index1);
+
+    BitSet tmp = sel.get(hi, sel.size());
+    sel.clear(lo, sel.size());
+    int n = tmp.size();
+    for (int i = 0; i < n; ++i)
+      sel.set(lo + i, tmp.get(i));
 	    }
 
-	sel.addElement(new Range(index0, index1));
+  /**
+   * Fires a {@link ListSelectionEvent} to all the listeners of type {@link
+   * ListSelectionListener} registered with this selection model.
+   *
+   * @param firstIndex The low index of the changed range
+   * @param lastIndex The high index of the changed range
+   * @param isAdjusting Whether this change is part of a seqence of adjustments
+   * made to the selection, such as during interactive scrolling
+   */
+  public void fireSelectionValueChanged(int firstIndex, int lastIndex,
+                                        boolean isAdjusting)
+  {
+    ListSelectionEvent evt = new ListSelectionEvent(this, firstIndex,
+                                                    lastIndex, isAdjusting);
+    ListSelectionListener[] listeners = getListSelectionListeners();
+    for (int i = 0; i < listeners.length; ++i)
+      listeners[i].valueChanged(evt);
     }
 
   /**
    * Adds a listener.
    *
-   * @param listener the listener to add
+   * @param listener The listener to add
    *
    * @see removeListSelectionListener
    * @see getListSelectionListeners
@@ -182,7 +547,7 @@
   /**
    * Removes a registered listener.
    *
-   * @param listener the listener to remove
+   * @param listener The listener to remove
    *
    * @see addListSelectionListener
    * @see getListSelectionListeners
@@ -195,11 +560,12 @@
   /**
    * Returns an array of all registerers listeners.
    * 
-   * @return the array
+   * @param listenerType The type of listener to retrieve
    * 
-   * @since 1.3
+   * @return The array
    *
    * @see getListSelectionListener
+   * @since 1.3
    */
   public EventListener[] getListeners (Class listenerType)
   {
@@ -211,12 +577,11 @@
    *
    * @return the array
    * 
-   * @since 1.4
-   *
    * @see addListSelectionListener
    * @see removeListSelectionListener
    * @see getListeners
+   * @since 1.4
    */
   public ListSelectionListener[] getListSelectionListeners()
   {
--- javax/swing/ListModel.java	10 Jan 2004 21:07:43 -0000	1.2
+++ javax/swing/ListModel.java	25 Feb 2004 23:56:23 -0000
@@ -36,14 +36,46 @@
 exception statement from your version. */
 
 package javax.swing;
-
 import javax.swing.event.ListDataListener;
 
+/**
+ * This is an interface to general list-like data, typically used as the
+ * model object of a {@link JList} component.
+ *
+ * @author Graydon Hoare (graydon&064;redhat.com)
+ */
 public interface ListModel
 {    
+  /**
+   * Return the number of data elements in the list.
+   *
+   * @return The number of data elements in the list
+   */
   int getSize();
+
+  /**
+   * Retrieves a data element at a specified index.
+   *
+   * @param index The index of the element to retrieve
+   *
+   * @return The data element at the specified index
+   */
   Object getElementAt(int index);
+
+  /**
+   * Add a listener object to this model. The listener will be called
+   * any time the set of elements in the model is changed.
+   *
+   * @param l The listener to add
+   */
   void addListDataListener(ListDataListener l);
+
+  /**
+   * Add a listener object to this model. The listener will no longer be
+   * called when the set of elements in the model is changed.
+   *
+   * @param l The listener to remove
+   */
   void removeListDataListener(ListDataListener l);
 }
--- javax/swing/ListSelectionModel.java	12 Oct 2003 13:20:49 -0000	1.3
+++ javax/swing/ListSelectionModel.java	25 Feb 2004 23:56:23 -0000
@@ -44,7 +44,7 @@
 {
     int SINGLE_SELECTION = 0;
     int SINGLE_INTERVAL_SELECTION = 1;
-    int MULTIPLE_INTERVAL_SELECTION = 1;
+  int MULTIPLE_INTERVAL_SELECTION = 2;
 
     void setSelectionMode(int a);
     int getSelectionMode();
@@ -53,12 +53,29 @@
     
     int getMinSelectionIndex();
     int getMaxSelectionIndex();
+
     boolean isSelectedIndex(int a);
 
+  boolean isSelectionEmpty();
     void setSelectionInterval(int index0, int index1);
+  void addSelectionInterval(int index0,
+                            int index1);
+  void removeSelectionInterval(int index0,
+                               int index1);
+  void insertIndexInterval(int index,
+                           int length,
+                           boolean before);
+  void removeIndexInterval(int index0,
+                           int index1);
+
+  int getAnchorSelectionIndex();
+  void setAnchorSelectionIndex(int index);
+  int getLeadSelectionIndex();
+  void setLeadSelectionIndex(int index);
 
-    
+  void setValueIsAdjusting(boolean valueIsAdjusting);
+  boolean getValueIsAdjusting();
 
     void addListSelectionListener(ListSelectionListener listener);
     void removeListSelectionListener(ListSelectionListener listener);    
--- javax/swing/AbstractListModel.java	11 Jun 2003 13:20:39 -0000	1.5
+++ javax/swing/AbstractListModel.java	25 Feb 2004 23:56:23 -0000
@@ -40,35 +40,34 @@
 import java.io.Serializable;
 import java.util.EventListener;
 import javax.swing.event.EventListenerList;
-import javax.swing.event.ListDataListener;
 import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
+
 
 /**
  * AbstractListModel
- * A2uthor	Ronald Veldema
+ *
+ * @author Ronald Veldema
  * @author	Andrew Selkirk
  * @version	1.0
  */
-public abstract class AbstractListModel
-  implements ListModel, Serializable
+public abstract class AbstractListModel implements ListModel, Serializable
 {
   static final long serialVersionUID = -3285184064379168730L;
 
-  /**
-   * listenerList
-   */
-  protected EventListenerList listenerList = new EventListenerList ();
+  /** List of ListDataListeners called for each change to the list. */
+  protected EventListenerList listenerList;
   
-  /**
-   * Constructor AbstractListModel
-   */
   public AbstractListModel ()
   {
+    listenerList = new EventListenerList();
   }
 
   /**
-   * addListDataListener
-   * @param listener TODO
+   * Add a listener object to this model. The listener will be called
+   * any time the set of elements in the model is changed.
+   *
+   * @param listener The listener to add
    */
   public void addListDataListener(ListDataListener listener) 
   {
@@ -76,8 +75,10 @@
   }
 
   /**
-   * removeListDataListener
-   * @param listener TODO
+   * Add a listener object to this model. The listener will no longer be
+   * called when the set of elements in the model is changed.
+   *
+   * @param listener The listener to remove
    */
   public void removeListDataListener(ListDataListener listener)
   {
@@ -85,12 +86,18 @@
   }
 
   /**
-   * fireContentsChanged
-   * @param source TODO
-   * @param startIndex TODO
-   * @param endIndex TODO
+   * Call {@link ListDataListener#contentsChanged} on each element of the
+   * {@link listenerList} which is a {@link ListDataListener}. The event
+   * fired has type {@ListDataEvent.CONTENTS_CHANGED} and represents a
+   * change to the data elements in the range [startIndex, endIndex]
+   * inclusive.
+   *
+   * @param source The source of the change, typically <code>this</code>
+   * @param startIndex The index of the first element which changed
+   * @param endIndex The index of the last element which changed
    */
-  protected void fireContentsChanged(Object source, int startIndex, int endIndex)
+  protected void fireContentsChanged(Object source, int startIndex,
+                                     int endIndex)
   {
     // Variables
     ListDataEvent event;
@@ -114,10 +121,15 @@
   }
 
   /**
-   * fireIntervalAdded
-   * @param source TODO
-   * @param startIndex TODO
-   * @param endIndex TODO
+   * Call {@link ListDataListener#intervalAdded} on each element of the
+   * {@link listenerList} which is a {@link ListDataListener}. The event
+   * fired has type {@ListDataEvent.INTERVAL_ADDED} and represents an
+   * addition of the data elements in the range [startIndex, endIndex]
+   * inclusive.
+   *
+   * @param source The source of the change, typically <code>this</code>
+   * @param startIndex The index of the first new element
+   * @param endIndex The index of the last new element
    */
   protected void fireIntervalAdded (Object source, int startIndex, int endIndex)
   {
@@ -128,8 +140,8 @@
     int index;
 
     // Create Event
-    event = new ListDataEvent (source, ListDataEvent.INTERVAL_ADDED, startIndex,
-                               endIndex);
+    event = new ListDataEvent(source, ListDataEvent.INTERVAL_ADDED,
+                              startIndex, endIndex);
 
     // Get Listeners
     listeners = getListDataListeners ();
@@ -143,10 +155,15 @@
   }
 
   /**
-   * fireIntervalRemoved
-   * @param source TODO
-   * @param startIndex TODO
-   * @param endIndex TODO
+   * Call {@link ListDataListener#intervalRemoved} on each element of the
+   * {@link listenerList} which is a {@link ListDataListener}. The event
+   * fired has type {@ListDataEvent.INTERVAL_REMOVED} and represents a
+   * removal of the data elements in the range [startIndex, endIndex]
+   * inclusive.
+   *
+   * @param source The source of the change, typically <code>this</code>
+   * @param startIndex The index of the first element removed
+   * @param endIndex The index of the last element removed
    */
   protected void fireIntervalRemoved (Object source, int startIndex,
                                      int endIndex)
@@ -173,9 +190,13 @@
   }
 
   /**
-   * getListeners
-   * @param listenerType TODO
-   * @returns EventListener[]
+   * Return the subset of {@link EventListener} objects found in this
+   * object's {@link listenerList} which are elements of the specified
+   * type.
+   *
+   * @param listenerType The type of listeners to select
+   *
+   * @return The set of listeners of the specified type
    */
   public EventListener[] getListeners (Class listenerType)
   {
@@ -183,8 +204,10 @@
   }
 
   /**
-   * getListDataListeners
+   * A synonym for <code>getListeners(ListDataListener.class)</code>.
+   *
+   * @return The set of ListDataListeners found in the {@link listenerList}
    */
   public ListDataListener[] getListDataListeners ()
   {
--- javax/swing/DefaultListModel.java	5 Feb 2004 18:48:53 -0000	1.3
+++ javax/swing/DefaultListModel.java	25 Feb 2004 23:56:23 -0000
@@ -35,501 +35,475 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package javax.swing;
 
-import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.NoSuchElementException;
 import java.util.Vector;
 
 /**
- * DefaultListModel
+ * This is a default subclass of the {@link AbstractListModel}, used by
+ * {@link javax.swing.JList} and similar objects as the model of a list of
+ * values. The implementation is based on an underlying {@link
+ * java.util.Vector}.
+ *
  * @author	Andrew Selkirk
- * @version	1.0
+ * @author Graydon Hoare (graydon&064;redhat.com)
  */
+
 public class DefaultListModel extends AbstractListModel
 {
   private static final long serialVersionUID = 2315945659722172272L;
 
-	//-------------------------------------------------------------
-	// Variables --------------------------------------------------
-	//-------------------------------------------------------------
-
-	/**
-	 * elements.  Note: Sun obviously implemented the storage as a
-	 * Vector according to the similar API on this class.  I choose
-	 * instead to implement the model with a proper collection object.
-	 * Is this a good choice?  Probably not (ya..I know there are
-	 * sync issues by doing this)
-	 */
-	private ArrayList elements = new ArrayList();
-
-
-	//-------------------------------------------------------------
-	// Initialization ---------------------------------------------
-	//-------------------------------------------------------------
-
 	/**
-	 * Constructor DefaultListModel
+   * The vector of elements in this list model.
 	 */
-	public DefaultListModel() {
-		// TODO
-	} // DefaultListModel()
-
-
-	//-------------------------------------------------------------
-	// Methods ----------------------------------------------------
-	//-------------------------------------------------------------
+  private Vector elements = new Vector();
 
 	/**
-	 * elementAt
-	 * @param index TODO
-	 * @returns Object
+   * Gets an element of the list at the provided index.
+   *
+   * @param index The index of the element to get
+   *
+   * @return The object at the given index
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds of the list <code>[0, size())</code>
 	 */
-	public Object elementAt(int index) {
-		return elements.get(index);
-	} // elementAt()
+  public Object elementAt(int index)
+  {
+    return elements.elementAt(index);
+  }
 
 	/**
-	 * toString
-	 * @returns String
+   * Convert the list to a string representation.
+   *
+   * @return A string representation of the list
 	 */
-	public String toString() {
+  public String toString()
+  {
 		return elements.toString();
-	} // toString()
+  }
 
 	/**
-	 * indexOf
-	 * @param element TODO
-	 * @returns int
+   * Gets the first index of a particular element in the list.
+   *
+   * @param element The element to search for
+   *
+   * @return The first index in the list at which an object
+   * <code>obj</code> exists such that <code>obj.equals(element)</code> is
+   * <code>true</code>; if no such object exists, the method returns
+   * <code>-1</code>
 	 */
-	public int indexOf(Object element) {
+  public int indexOf(Object element)
+  {
 		return elements.indexOf(element);
-	} // indexOf()
+  }
 
 	/**
-	 * indexOf
-	 * @param element TODO
-	 * @param startIndex TODO
-	 * @returns int
+   * Gets the first index of a particular element in a list which occurs
+   * <em>at or after</em> a particular index.
+   *
+   * @param element The element to search for
+   * @param startIndex The index to begin searching at
+   *
+   * @return The first index in the list, greater than or equal to
+   * <code>startIndex</code>, at which an object <code>obj</code> exists
+   * such that <code>obj.equals(element)</code> is <code>true</code>; if no
+   * such object exists, the method returns <code>-1</code>
 	 */
-	public int indexOf(Object element, int startIndex) {
-
-		// Variables
-		int		index;
-		Object	test;
-
-		// Process Elements
-		for (index = startIndex; index < elements.size(); index++) {
-			test = elements.get(index);
-			if (test.equals(element) == true) {
-				return index;
-			} // if
-		} // for
-		return -1;
-
-	} // indexOf()
+  public int indexOf(Object element, int startIndex)
+  {
+    return elements.indexOf(element, startIndex);
+  }
 
 	/**
-	 * lastIndexOf
-	 * @param element TODO
-	 * @returns int
+   * Gets the last index of a particular element in the list.
+   *
+   * @param element The element to search for
+   *
+   * @return The last index in the list at which an object
+   * <code>obj</code> exists such that <code>obj.equals(element)</code> is
+   * <code>true</code>; if no such object exists, the method returns
+   * <code>-1</code>
 	 */
-	public int lastIndexOf(Object element) {
+  public int lastIndexOf(Object element)
+  {
 		return elements.lastIndexOf(element);
-	} // lastIndexOf()
+  }
 
 	/**
-	 * lastIndexOf
-	 * @param element TODO
-	 * @param endIndex TODO
-	 * @returns int
+   * Gets the last index of a particular element in a list which occurs
+   * <em>at or before</em> a particular index.
+   *
+   * @param element The element to search for
+   * @param endIndex The index to finish searching at
+   *
+   * @return The last index in the list, less than to or equal to
+   * <code>endIndexIndex</code>, at which an object <code>obj</code> exists
+   * such that <code>obj.equals(element)</code> is <code>true</code>; if no
+   * such object exists, the method returns <code>-1</code>
 	 */
-	public int lastIndexOf(Object element, int endIndex) {
-
-		// Variables
-		int		index;
-		Object	test;
-
-		// Process Elements
-		for (index = endIndex; index >= 0; index--) {
-			test = elements.get(index);
-			if (test.equals(element) == true) {
-				return index;
-			} // if
-		} // for
-		return -1;
-
-	} // lastIndexOf()
+  public int lastIndexOf(Object element, int endIndex)
+  {
+    return elements.lastIndexOf(element, endIndex);
+  }
 
 	/**
-	 * get
-	 * @param index TODO
-	 * @returns Object
+   * Gets the list element at a particular index.
+   *
+   * @param index The index to get the list value at
+   *
+   * @return The list value at the provided index
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds of the list <code>[0, size())</code>
 	 */
-	public Object get(int index) {
+  public Object get(int index)
+  {
 		return elements.get(index);
-	} // get()
+  }
 
 	/**
-	 * set
-	 * @param index TODO
-	 * @param element TODO
-	 * @returns Object
+   * Sets the list element at a particular index.
+   *
+   * @param index The list index at which to set a value 
+   * @param element The value to set at the specified index
+   *
+   * @return The value previously held at the specified index
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds of the list <code>[0, size())</code>
 	 */
-	public Object set(int index, Object element) {
-
-		// Variables
+  public Object set(int index, Object element)
+  {
 		Object	result;
-
-		// Process Action
 		result = elements.set(index, element);
-
-		// Send event
 		fireContentsChanged(this, index, index);
-
 		return result;
-
-	} // set()
+  }
 
 	/**
-	 * add
-	 * @param index TODO
-	 * @param element TODO
+   * Inserts an element at a particular index in the list. Each element at
+   * index <code>i >= index</code> is shifted to position <code>i+1</code>.
+   * If <code>index</code> is equal to <code>size()</code>, this is
+   * equivalent to appending an element to the array. Any
+   * <code>index</code> greater than <code>size()</code> is illegal.
+   *
+   * @param index The index to insert the element at
+   * @param element The element to insert at the index
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds <code>[0, size()]</code>
 	 */
-	public void add(int index, Object element) {
-
-		// Process Action
+  public void add(int index, Object element)
+  {
 		elements.add(index, element);
-
-		// Send event
 		fireContentsChanged(this, index, index);
-
-	} // add()
+  }
 
 	/**
-	 * addElement
-	 * @param element TODO
+   * Inserts an element at the end of the list. This is equivalent to
+   * calling <code>list.add(list.size(), element)</code>.
+   *
+   * @param element The element to add to the list
 	 */
-	public void addElement(Object element) {
-
-		// Process Action
+  public void addElement(Object element)
+  {
 		elements.add(element);
-
-		// Send event
 		fireIntervalAdded(this, elements.size(), elements.size());
-
-	} // addElement()
+  }
 
 	/**
-	 * size
-	 * @returns int
+   * Gets the number of elements in the list.
+   *
+   * @return The number of elements in the list
 	 */
-	public int size() {
+  public int size()
+  {
 		return elements.size();
-	} // size()
+  }
 
 	/**
-	 * toArray
-	 * @returns Object[]
+   * Gets an array containing the elements of the list.
+   *
+   * @return An array of the objects in the list, in the order they occur
+   * in the list
 	 */
-	public Object[] toArray() {
+  public Object[] toArray()
+  {
 		return elements.toArray();
-	} // toArray()
+  }
 
 	/**
-	 * contains
-	 * @param element TODO
-	 * @returns boolean
+   * Determines whether a particular element is a member of the list.
+   *
+   * @param element The element to search for
+   *
+   * @return <code>true</code> if <code>element</code> is a member of the
+   * list, otherwise <code>false</code>
 	 */
-	public boolean contains(Object element) {
+  public boolean contains(Object element)
+  {
 		return elements.contains(element);
-	} // contains()
+  }
 
 	/**
-	 * copyInto
-	 * @param array TODO
+   * Copies the list into a provided array. The provided array must be at
+   * least as large as the list.
+   *
+   * @param array The array to copy the list into
+   * 
+   * @throws IndexOutOfBoundsException if the array is too small to hold the
+   * elements of the list
 	 */
-	public void copyInto(Object[] array) {
-
-		// Variables
-		int		index;
-		int		size;
-		Object[]	srcArray;
-
-		// Initialize
-		size = size();
-		srcArray = toArray();
-
-		// Process Elements
-		for (index = 0; index < size; index++) {
-			array[index] = srcArray[index];
-		} // for
-
-	} // copyInto()
+  public void copyInto(Object[] array)
+  {
+    elements.copyInto(array);
+  }
 
 	/**
-	 * clear
+   * Erases all the elements of the list, setting the list's size to 0.
 	 */
-	public void clear() {
-
-		// Process Action
+  public void clear()
+  {
 		elements.clear();
-
-		// Send event
 		fireIntervalRemoved(this, 0, elements.size());
-
-	} // clear()
+  }
 
 	/**
-	 * remove
-	 * @param index TODO
-	 * @returns Object
+   * Removes the element at a particular index from the list.
+   *
+   * @param index The index of the element to remove
+   *
+   * @return The value at the index, which has been removed from the list
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds of the list <code>[0, size())</code>
 	 */
-	public Object remove(int index) {
-
-		// Variables
+  public Object remove(int index)
+  {
 		Object	result;
-
-		// Process Action
 		result = elements.remove(index);
-
-		// Send event
 		fireIntervalRemoved(this, index, index);
-
 		return result;
-
-	} // remove()
+  }
 
 	/**
-	 * isEmpty
-	 * @returns boolean
+   * Determines whether the list is empty.
+   *
+   * @return <code>true</code> if the list is empty, otherwise
+   * <code>false</code>
 	 */
-	public boolean isEmpty() {
+  public boolean isEmpty()
+  {
 		return elements.isEmpty();
-	} // isEmpty()
+  }
 
 	/**
-	 * elements
-	 * @returns Enumeration
+   * Returns an {@link java.util.Enumeration} over the elements of the list.
+   *
+   * @return A new enumeration which iterates over the list
 	 */
-	public Enumeration elements() {
-
-		// TODO
-		// Note: This is a pathetic implementation.  If Vector
-		// was used for storage, this wouldn't be an issue.  I'll
-		// have to implement an Enumeration inner class sometime.
-
-		// Variables
-		Vector	vector;
-
-		// Get Enumeration
-		vector = new Vector(elements);
-		return vector.elements();
-
-	} // elements()
+  public Enumeration elements()
+  {
+    return elements.elements();
+  }
 
 	/**
-	 * trimToSize
+   * Sets the capacity of the list to be equal to its size. The list's capacity
+   * is the number of elements it can hold before it needs to be reallocated.
+   * The list's size is the number of elements it currently holds. 
 	 */
-	public void trimToSize() {
+  public void trimToSize()
+  {
 		elements.trimToSize();
-	} // trimToSize()
+  }
 
 	/**
-	 * ensureCapacity
-	 * @param size TODO
+   * Ensures that the list's capacity is at least equal to
+   * <code>size</code>. The list's capacity is the number of elements it
+   * can hold before it needs to be reallocated.
+   *
+   * @param size The capacity to ensure the list can hold
 	 */
-	public void ensureCapacity(int size) {
+  public void ensureCapacity(int size)
+  {
 		elements.ensureCapacity(size);
-	} // ensureCapacity()
+  }
 
 	/**
-	 * setSize
-	 * @param size TODO
+   * Sets the size of the list to a particular value. If the specified size
+   * is greater than the current size, the values at the excess list
+   * indices are set to <code>null</code>.  If the specified size is less
+   * than the current size, the excess elements are removed from the list.
+   *
+   * @param size The new size to set the list to
 	 */
-	public void setSize(int size) {
-		elements.ensureCapacity(size);
-	} // setSize()
+  public void setSize(int size)
+  {
+    elements.setSize(size);
+  }
 
 	/**
-	 * capacity
-	 * @returns int
+   * Gets the capacity of the list. The list's capacity is the number of
+   * elements it can hold before it needs to be reallocated. 
+   *
+   * @return The capacity of the list
 	 */
-	public int capacity() {
-		return elements.size();
-	} // capacity()
+  public int capacity()
+  {
+    return elements.capacity();
+  }
 
 	/**
-	 * firstElement
-	 * @returns Object
+   * Gets the first element in the list.
+   *
+   * @return The first element in the list
 	 */
-	public Object firstElement() {
-
-		// Variables
-		Object	element;
-
-		try {
-			element = elements.get(0);
-			return element;
-		} catch (IndexOutOfBoundsException e) {
-			throw new NoSuchElementException();
-		} // try
-
-	} // firstElement()
+  public Object firstElement()
+  {
+    return elements.firstElement();
+  }
 
 	/**
-	 * lastElement
-	 * @returns Object
+   * Gets the last element in the list.
+   *
+   * @return The last element in the list
 	 */
-	public Object lastElement() {
-
-		// Variables
-		Object	element;
-
-		try {
-			element = elements.get(elements.size() - 1);
-			return element;
-		} catch (ArrayIndexOutOfBoundsException e) {
-			throw new NoSuchElementException();
-		} // try
-
-	} // lastElement()
+  public Object lastElement()
+  {
+    return elements.lastElement();
+  }
 
 	/**
-	 * setElementAt
-	 * @param element TODO
-	 * @param index TODO
+   * Sets the list element at a particular index.
+   *
+   * @param element The value to set at the specified index
+   * @param index The list index at which to set a value 
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds of the list <code>[0, size())</code>
 	 */
-	public void setElementAt(Object element, int index) {
-
-		// Process Action
-		elements.set(index, element);
-
-		// Send event
+  public void setElementAt(Object element, int index)
+  {
+    elements.setElementAt(element, index);
 		fireContentsChanged(this, index, index);
-
-	} // setElementAt()
+  }
 
 	/**
-	 * removeElementAt
-	 * @param index TODO
+   * Removes the element at a particular index from the list.
+   *
+   * @param index The index of the element to remove
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds of the list <code>[0, size())</code>
 	 */
-	public void removeElementAt(int index) {
-
-		// Process Action
+  public void removeElementAt(int index)
+  {
 		elements.remove(index);
-
-		// Send event
 		fireIntervalRemoved(this, index, index);
-
-	} // removeElementAt()
+  }
 
 	/**
-	 * insertElementAt
-	 * @param element TODO
-	 * @param index TODO
+   * Inserts an element at a particular index in the list. Each element at
+   * index <code>i >= index</code> is shifted to position <code>i+1</code>.
+   * If <code>index</code> is equal to <code>size()</code>, this is
+   * equivalent to appending an element to the array. Any
+   * <code>index</code> greater than <code>size()</code> is illegal.
+   *
+   * @param element The element to insert at the index
+   * @param index The index to insert the element at
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds <code>[0, size()]</code>
 	 */
-	public void insertElementAt(Object element, int index) {
-
-		// Process Action
-		elements.add(index, element);
-
-		// Send event
-		fireIntervalRemoved(this, index, index);
-
-	} // insertElementAt()
+  public void insertElementAt(Object element, int index)
+  {
+    elements.insertElementAt(element, index);
+    fireIntervalAdded(this, index, index);
+  }
 
 	/**
-	 * removeElement
-	 * @param element TODO
-	 * @returns boolean
+   * Removes the first occurrence of a particular element in the list. If the
+   * element does not exist in the list, nothing happens.
+   *
+   * @param element The element to remove
+   *
+   * @return <code>true</code> if the element existed in the list (and was
+   * removed), <code>false</code> otherwise
 	 */
-	public boolean removeElement(Object element) {
-
-		// Variables
+  public boolean removeElement(Object element)
+  {
 		int		index;
-
 		index = elements.indexOf(element);
-		if (index != -1) {
+    if (index != -1)
+      {
 			elements.remove(index);
-
-			// Send event
 			fireIntervalRemoved(this, index, index);
-
 			return true;
-
-		} // if
-
+      }
 		return false;
-
-	} // removeElement()
+  }
 
 	/**
-	 * removeAllElements
+   * Remove all elements in the list.
 	 */
-	public void removeAllElements() {
-
-		// Variables
+  public void removeAllElements()
+  {
 		int		size;
-
 		size = size();
-
-		if (size > 0) {
-
-			// Process Action
+    if (size > 0)
+      {
 			elements.clear();
-
-			// Send event
 			fireIntervalRemoved(this, 0, size - 1);
-
-		} // if
-
-	} // removeAllElements()
+      }
+  }
 
 	/**
-	 * removeRange
-	 * @param startIndex TODO
-	 * @param endIndex TODO
+   * Remove all elements between <code>startIndex</code> and
+   * <code>endIndex</code> inclusive.
+   *
+   * @param startIndex The first index in the range to remove
+   * @param endIndex The last index in the range to remove
+   *
+   * @throws ArrayIndexOutOfBoundsException if either index is outside the
+   * valid range of indices for this list <code>[0, size())</code>
+   * @throws IllegalArgumentException if <code>startIndex > endIndex</code>
 	 */
-	public void removeRange(int startIndex, int endIndex) {
-
-		// Variables
+  public void removeRange(int startIndex, int endIndex)
+  {
 		int		index;
-
-		// Check Indices
-		if (startIndex > endIndex) {
+    if (startIndex > endIndex)
 			throw new IllegalArgumentException();
-		} // if
-
-		// Process Elements
-		for (index = endIndex; index >= startIndex; index--) {
+    for (index = endIndex; index >= startIndex; index--)
 			elements.remove(index);
-		} // for
-
-		// Send event
 		fireIntervalRemoved(this, startIndex, endIndex);
-
-	} // removeRange()
+  }
 
 	/**
-	 * getSize
-	 * @returns int
+   * Gets the size of the list.
+   *
+   * @return The number of elements currently in the list
 	 */
-	public int getSize() {
+  public int getSize()
+  {
 		return elements.size();
-	} // getSize()
+  }
 
 	/**
-	 * getElementAt
-	 * @param index TODO
-	 * @returns Object
+   * Gets the list element at a particular index.
+   *
+   * @param index The index to get the list value at
+   *
+   * @return The list value at the provided index
+   *
+   * @throws ArrayIndexOutOfBoundsException If the provided index is
+   * outside the bounds of the list <code>[0, size())</code>
 	 */
-	public Object getElementAt(int index) {
+  public Object getElementAt(int index)
+  {
 		return elements.get(index);
-	} // getElementAt()
-
-
-} // DefaultListModel
+  }
+}
--- javax/swing/DefaultListCellRenderer.java	9 Jan 2004 10:18:47 -0000	1.3
+++ javax/swing/DefaultListCellRenderer.java	25 Feb 2004 23:56:23 -0000
@@ -42,214 +42,76 @@
 import java.io.Serializable;
 import javax.swing.border.Border;
 
+
 /**
  * DefaultListCellRenderer
+ *
  * @author	Andrew Selkirk
  * @version	1.0
  */
-public class DefaultListCellRenderer extends JLabel 
-		implements ListCellRenderer, Serializable
+public class DefaultListCellRenderer 
+  extends JLabel implements ListCellRenderer, Serializable
 {
   static final long serialVersionUID = 7708947179685189462L;
 
-	//-------------------------------------------------------------
-	// Classes ----------------------------------------------------
-	//-------------------------------------------------------------
-
-	/**
-	 * UIResource
-	 */
 	public static class UIResource extends DefaultListCellRenderer 
-			implements javax.swing.plaf.UIResource {
-
-		//-------------------------------------------------------------
-		// Initialization ---------------------------------------------
-		//-------------------------------------------------------------
-
-		/**
-		 * Constructor UIResource
-		 */
-		public UIResource() {
-			// TODO
-		} // UIResource()
-
-
-	} // UIResource
-
-
-	//-------------------------------------------------------------
-	// Variables --------------------------------------------------
-	//-------------------------------------------------------------
+    implements javax.swing.plaf.UIResource
+  {
+    public UIResource()
+    {
+    }
+  }
 
-	/**
-	 * noFocusBorder
-	 */
+  /** noFocusBorder */
 	protected static Border noFocusBorder = null; // TODO
 
-
-	//-------------------------------------------------------------
-	// Initialization ---------------------------------------------
-	//-------------------------------------------------------------
-
-	/**
-	 * Constructor DefaultListCellRenderer
-	 */
-	public DefaultListCellRenderer() {
-		// TODO
-	} // DefaultListCellRenderer()
-
-
-	//-------------------------------------------------------------
-	// Methods ----------------------------------------------------
-	//-------------------------------------------------------------
-
 	/**
 	 * getListCellRendererComponent
+   *
 	 * @param list TODO
 	 * @param value TODO
 	 * @param index TODO
 	 * @param isSelected TODO
 	 * @param cellHasFocus TODO
-	 * @returns Component
-	 */
-	public Component getListCellRendererComponent(JList list,
-			Object value, int index, boolean isSelected, boolean cellHasFocus) {
-		return null; // TODO
-	} // getListCellRendererComponent()
-
-	/**
-	 * validate
-	 */
-	public void validate() {
-		// TODO
-	} // validate()
-
-	/**
-	 * revalidate
-	 */
-	public void revalidate() {
-		// TODO
-	} // revalidate()
-
-	/**
-	 * repaint
-	 * @param tm TODO
-	 * @param x TODO
-	 * @param y TODO
-	 * @param w TODO
-	 * @param h TODO
-	 */
-	public void repaint(long tm, int x, int y, int w, int h) {
-		// TODO
-	} // repaint()
-
-	/**
-	 * repaint
-	 * @param rect TODO
-	 */
-	public void repaint(Rectangle rect) {
-		// TODO
-	} // repaint()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
-	 */
-	protected void firePropertyChange(String propertyName,
-			Object oldValue, Object newValue) {
-		// TODO
-	} // firePropertyChange()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
-	 */
-	public void firePropertyChange(String propertyName, 
-			byte oldValue, byte newValue) {
-		// TODO
-	} // firePropertyChange()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
-	 */
-	public void firePropertyChange(String propertyName, 
-			char oldValue, char newValue) {
-		// TODO
-	} // firePropertyChange()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
-	 */
-	public void firePropertyChange(String propertyName, 
-			short oldValue, short newValue) {
-		// TODO
-	} // firePropertyChange()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
+   *
+   * @return Component
 	 */
-	public void firePropertyChange(String propertyName, 
-			int oldValue, int newValue) {
-		// TODO
-	} // firePropertyChange()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
-	 */
-	public void firePropertyChange(String propertyName, 
-			long oldValue, long newValue) {
-		// TODO
-	} // firePropertyChange()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
-	 */
-	public void firePropertyChange(String propertyName, 
-			float oldValue, float newValue) {
-		// TODO
-	} // firePropertyChange()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
-	 */
-	public void firePropertyChange(String propertyName, 
-			double oldValue, double newValue) {
-		// TODO
-	} // firePropertyChange()
-
-	/**
-	 * firePropertyChange
-	 * @param propertyName TODO
-	 * @param oldValue TODO
-	 * @param newValue TODO
-	 */
-	public void firePropertyChange(String propertyName, 
-			boolean oldValue, boolean newValue) {
-		// TODO
-	} // firePropertyChange()
-
+  public Component getListCellRendererComponent(JList list, Object value,
+                                                int index, boolean isSelected,
+                                                boolean cellHasFocus)
+  {
+    String s = value.toString();
+    setText(s);
+    setOpaque(true);
 
-} // DefaultListCellRenderer
+    if (isSelected)
+      {
+        setBackground(list.getSelectionBackground());
+        setForeground(list.getSelectionForeground());
+      }
+    else
+      {
+        setBackground(list.getBackground());
+        setForeground(list.getForeground());
+      }
+
+    setEnabled(list.isEnabled());
+    setFont(list.getFont());
+    return this;
+  }
+
+  public void validate() {}
+  public void revalidate() {}
+  public void repaint(long tm, int x, int y, int w, int h) {}
+  public void repaint(Rectangle rect) {}
+  protected void firePropertyChange(String propertyName, Object oldValue, Object newValue){}
+  public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {}
+  public void firePropertyChange(String propertyName, char oldValue, char newValue) {} 
+  public void firePropertyChange(String propertyName, short oldValue, short newValue) {}
+  public void firePropertyChange(String propertyName, int oldValue, int newValue) {}
+  public void firePropertyChange(String propertyName, long oldValue, long newValue) {}
+  public void firePropertyChange(String propertyName, float oldValue, float newValue) {}
+  public void firePropertyChange(String propertyName, double oldValue, double newValue) {}
+  public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
+}
--- javax/swing/plaf/basic/BasicListUI.java	10 Jan 2004 21:59:30 -0000	1.4
+++ javax/swing/plaf/basic/BasicListUI.java	25 Feb 2004 23:56:23 -0000
@@ -35,7 +35,6 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package javax.swing.plaf.basic;
 
 import java.awt.Color;
@@ -44,141 +43,664 @@
 import java.awt.Graphics;
 import java.awt.Point;
 import java.awt.Rectangle;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import javax.swing.JComponent;
 import javax.swing.JList;
 import javax.swing.ListCellRenderer;
+import javax.swing.ListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.MouseInputListener;
 import javax.swing.plaf.ComponentUI;
 import javax.swing.plaf.ListUI;
 
+
+/**
+ * The Basic Look and Feel UI delegate for the 
+ * JList.
+ */
 public class BasicListUI extends ListUI
 {
-    int gap_between_cells;
-    Color textColor, disabledTextColor, pressedBackgroundColor, normalBackgroundColor;
-    
+  /**
+   * A helper class which listens for {@link FocusEvents}
+   * from the JList.
+   */
+  class FocusHandler implements FocusListener
+  {
+    /**
+     * Called when the JList acquires focus.
+     *
+     * @param e The FocusEvent representing focus acquisition
+     */
+    public void focusGained(FocusEvent e)
+    {
+      repaintCellFocus();
+    }
 
-    public static ComponentUI createUI(final JComponent c) 
+    /**
+     * Called when the JList loses focus.
+     *
+     * @param e The FocusEvent representing focus loss
+     */
+    public void focusLost(FocusEvent e)
     {
-	return new BasicButtonUI();
+      repaintCellFocus();
     }
 
+    /**
+     * Helper method to repaint the focused cell's 
+     * lost or acquired focus state.
+     */
+    void repaintCellFocus()
+    {
+    }
+  }
     
-    public void installUI(final JComponent c) 
+  /**
+   * A helper class which listens for {@link ListDataEvent}s generated by
+   * the {@link JList}'s {@link ListModel}.
+   *
+   * @see javax.swing.JList#model
+   */
+  class ListDataHandler implements ListDataListener
+  {
+    /**
+     * Called when a general change has happened in the model which cannot
+     * be represented in terms of a simple addition or deletion.
+     *
+     * @param e The event representing the change
+     */
+    public void contentsChanged(ListDataEvent e)
     {
-	super.installUI(c);
+      // System.err.println(this + ".contentsChanged(" + e + ")");
+      BasicListUI.this.damageLayout();
+    }
 
-	textColor                = new Color(0,0,0);
-	disabledTextColor        = new Color(130, 130, 130);
-	pressedBackgroundColor   = new Color(150,150,150);
-	normalBackgroundColor    = new Color(192,192,192);
+    /**
+     * Called when an interval of objects has been added to the model.
+     *
+     * @param e The event representing the addition
+     */
+    public void intervalAdded(ListDataEvent e)
+    {
+      // System.err.println(this + ".intervalAdded(" + e + ")");
+      BasicListUI.this.damageLayout();
     }
 
-    public Dimension getPreferredSize(JComponent c) 
+    /**
+     * Called when an inteval of objects has been removed from the model.
+     *
+     * @param e The event representing the removal
+     */
+    public void intervalRemoved(ListDataEvent e)
     {
-	JList l = (JList) c;
+      // System.err.println(this + ".intervalRemoved(" + e + ")");
+      BasicListUI.this.damageLayout();
+    }
+  }
 
-	System.out.println("XXXXXXXXXXXXXXXxx   getPreferredSize------------> " + l);
+  /**
+   * A helper class which listens for {@link ListSelectionEvent}s
+   * from the {@link JList}'s {@link ListSelectionModel}.
+   */
+  class ListSelectionHandler implements ListSelectionListener
+  {
+    /**
+     * Called when the list selection changes.  
+     *
+     * @param e The event representing the change
+     */
+    public void valueChanged(ListSelectionEvent e)
+    {
+      //       System.err.println(this + ".valueChanged(" + e + ")");
+    }
+  }
 
+  /**
+   * A helper class which listens for {@link MouseEvent}s 
+   * from the {@link JList}.
+   */
+  class MouseInputHandler implements MouseInputListener
+  {
+    /**
+     * Called when a mouse button press/release cycle completes
+     * on the {@link JList}
+     *
+     * @param event The event representing the mouse click
+     */
+    public void mouseClicked(MouseEvent event)
+    {
+    }
 	
-	int rows = l.getVisibleRowCount();
+    /**
+     * Called when a mouse button is pressed down on the
+     * {@link JList}.
+     *
+     * @param event The event representing the mouse press
+     */
+    public void mousePressed(MouseEvent event)
+    {
+      // System.err.println("got mouse click event " + event);
+      int row = BasicListUI.this.convertYToRow(event.y);
+      if (row == -1)
+        return;
 
-	ListCellRenderer render = l.getCellRenderer();
+      // System.err.println("clicked on row " + row);
+      BasicListUI.this.list.setSelectedIndex(row);
+    }
 	
-	int width  = 200;
-	int height = rows * 16; 
+    /**
+     * Called when a mouse button is released on
+     * the {@link JList}
+     *
+     * @param event The event representing the mouse press
+     */
+    public void mouseReleased(MouseEvent event)
+    {
+    }
 	
-	if (l.getModel().getSize() == 0)
+    /**
+     * Called when the mouse pointer enters the area bounded
+     * by the {@link JList}
+     *
+     * @param event The event representing the mouse entry
+     */
+    public void mouseEntered(MouseEvent event)
 	    {
-		return new Dimension(width, height);
 	    }
 
-	System.out.println("BASIC_LIST_UI ====-> " + l.getModel().getElementAt(0));
+    /**
+     * Called when the mouse pointer leaves the area bounded
+     * by the {@link JList}
+     *
+     * @param event The event representing the mouse exit
+     */
+    public void mouseExited(MouseEvent event)
+    {
+    }
 
-	Component elt = render.getListCellRendererComponent(l,
-							    l.getModel().getElementAt(0),
-							    0,            
-							    false,
-							    false);
-	Dimension a = elt.getPreferredSize();
-	if (a == null)
+    /**
+     * Called when the mouse pointer moves over the area bounded
+     * by the {@link JList} while a button is held down.
+     *
+     * @param event The event representing the mouse drag
+     */
+    public void mouseDragged(MouseEvent event)
 	    {
-		return new Dimension(width, height);
 	    }
 
-	return new Dimension(a.width,
-			     a.height * rows);
+    /**
+     * Called when the mouse pointer moves over the area bounded
+     * by the {@link JList}.
+     *
+     * @param event The event representing the mouse move
+     */
+    public void mouseMoved(MouseEvent event)
+    {
+    }
     }
 
-    public void paintBackground(Graphics g,
-			 JComponent c)
+  /**
+   * Helper class which listens to {@link PropertyChangeEvent}s
+   * from the {@link JList}.
+   */
+  class PropertyChangeHandler implements PropertyChangeListener
+  {
+    /**
+     * Called when the {@link JList} changes one of its bound properties.
+     *
+     * @param e The event representing the property change
+     */
+    public void propertyChange(PropertyChangeEvent e)
     {
-	Dimension size = getPreferredSize(c);
+      // System.err.println(this + ".propertyChange(" + e + ")");
+      if (e.source == BasicListUI.this.list)
+        {
+          if (e.oldValue != null && e.oldValue instanceof ListModel)
+            ((ListModel) e.oldValue).removeListDataListener(BasicListUI.this.listDataListener);
 
-	g.setColor(normalBackgroundColor);
-	g.fillRect(0,0,size.width, size.height);  
+          if (e.newValue != null && e.newValue instanceof ListModel)
+            ((ListModel) e.newValue).addListDataListener(BasicListUI.this.listDataListener);
+        }
+      BasicListUI.this.damageLayout();
+    }
     }
 
-    public void paint(Graphics g, 
-		      JComponent c)
+  /**
+   * Creates a new BasicListUI for the component.
+   *
+   * @param c The component to create a UI for
+   *
+   * @return A new UI
+   */
+  public static ComponentUI createUI(final JComponent c)
     {      
-	JList l = (JList) c;
+    return new BasicListUI();
+  }
 
-	int rows = l.getVisibleRowCount();
+  /** The current focus listener. */
+  FocusHandler focusListener;
 
-	ListCellRenderer render = l.getCellRenderer();
+  /** The data listener listening to the model. */
+  ListDataHandler listDataListener;
 
-	System.out.println("RENDER-JLIST: " + rows + ", " + l.getModel().getSize());
+  /** The selection listener listening to the selection model. */
+  ListSelectionHandler listSelectionListener;
 
-	paintBackground(g, c);
+  /** The mouse listener listening to the list. */
+  MouseInputHandler mouseInputListener;
+
+  /** The property change listener listening to the list. */
+  PropertyChangeHandler propertyChangeListener;
+
+  /** Saved reference to the list this UI was created for. */
+  JList list;
+
+  /** The height of a single cell in the list. */
+  int cellHeight;
+
+  /** The width of a single cell in the list. */
+  int cellWidth;
+
+  /** 
+   * An array of varying heights of cells in the list, in cases where each
+   * cell might have a different height.
+   */
+  int[] cellHeights;
+
+  /**
+   * A simple counter. When nonzero, indicates that the UI class is out of
+   * date with respect to the underlying list, and must recalculate the
+   * list layout before painting or performing size calculations.
+   */
+  int updateLayoutStateNeeded;
+
+  /**
+   * Calculate the height of a particular row. If there is a fixed {@link
+   * #cellHeight}, return it; otherwise return the specific row height
+   * requested from the {@link #cellHeights} array. If the requested row
+   * is invalid, return <code>-1</code>.
+   *
+   * @param row The row to get the height of
+   *
+   * @return The height, in pixels, of the specified row
+   */
+  int getRowHeight(int row)
+  {
+    if (row < 0 || row >= cellHeights.length)
+      return -1;
+    else if (cellHeight != -1)
+      return cellHeight;
+    else
+      return cellHeights[row];
+  }
 
-	if (l.getModel().getSize() == 0)
-	    return;
+  /**
+   * Calculate the bounds of a particular cell, considering the upper left
+   * corner of the list as the origin position <code>(0,0)</code>.
+   *
+   * @param l Ignored; calculates over <code>this.list</code>
+   * @param index1 The first row to include in the bounds
+   * @param index2 The last row to incude in the bounds
+   *
+   * @return A rectangle encompassing the range of rows between 
+   * <code>index1</code> and <code>index2</code> inclusive
+   */
+  public Rectangle getCellBounds(JList l, int index1, int index2)
+  {
+    if (l != list || cellWidth == -1)
+      return null;
+
+    int lo = Math.min(index1, index2);
+    int hi = Math.max(index1, index2);
+    Rectangle lobounds = new Rectangle(0, convertRowToY(lo), cellWidth,
+                                       getRowHeight(lo));
+    Rectangle hibounds = new Rectangle(0, convertRowToY(hi), cellWidth,
+                                       getRowHeight(hi));
+    return lobounds.union(hibounds);
+  }
+
+  /**
+   * Calculate the Y coordinate of the upper edge of a particular row,
+   * considering the Y coordinate <code>0</code> to occur at the top of the
+   * list.
+   *
+   * @param row The row to calculate the Y coordinate of
+   *
+   * @return The Y coordinate of the specified row, or <code>-1</code> if
+   * the specified row number is invalid
+   */
+  int convertRowToY(int row)
+  {
+    int y = 0;
+    for (int i = 0; i < row; ++i)
+      {
+        int h = getRowHeight(i);
+        if (h == -1)
+          return -1;
+        y += h;
+      }
+    return y;
+  }
+
+  /**
+   * Calculate the row number containing a particular Y coordinate,
+   * considering the Y coodrinate <code>0</code> to occur at the top of the
+   * list.
+   *
+   * @param y0 The Y coordinate to calculate the row number for
+   *
+   * @return The row number containing the specified Y value, or <code>-1</code>
+   * if the specified Y coordinate is invalid
+   */
+  int convertYToRow(int y0)
+  {
+    for (int row = 0; row < cellHeights.length; ++row)
+      {
+        int h = getRowHeight(row);
+
+        // System.err.println("convertYToRow(" + y0 + ") vs. " + h);
+        if (y0 < h)
+          return row;
+        y0 -= h;
+      }
+    return -1;
+  }
 
-	// use element 0 to figure out how big we are:
-	Component elt = render.getListCellRendererComponent(l,
-							    l.getModel().getElementAt(0),
-							    0,       
-							    false,
+  /**
+   * Recomputes the {@link #cellHeights}, {@link #cellHeight}, and {@link
+   * #cellWidth} properties by examining the variouis properties of the
+   * {@link JList}.
+   */
+  void updateLayoutState()
+  {
+    int nrows = list.getModel().getSize();
+    cellHeight = -1;
+    cellWidth = -1;
+    if (cellHeights == null || cellHeights.length != nrows)
+      cellHeights = new int[nrows];
+    if (list.getFixedCellHeight() == -1 || list.getFixedCellWidth() == -1)
+      {
+        ListCellRenderer rend = list.getCellRenderer();
+        for (int i = 0; i < nrows; ++i)
+          {
+            Component flyweight = rend.getListCellRendererComponent(list,
+                                                                    list.getModel()
+                                                                        .getElementAt(i),
+                                                                    0, false,
 							    false);
-	Dimension dim = elt.getPreferredSize();
+            Dimension dim = flyweight.getPreferredSize();
+            cellHeights[i] = dim.height;
+            cellWidth = Math.max(cellWidth, dim.width);
+          }
+      }
+    else
+      {
+        cellHeight = list.getFixedCellHeight();
+        cellWidth = list.getFixedCellWidth();
+      }
+  }
 	
-	Rectangle a = new Rectangle(0,
-				    0,
-				    dim.width,
-				    dim.height);
+  /**
+   * Marks the current layout as damaged and requests revalidation from the
+   * JList.
+   *
+   * @see #updateLayoutStateNeeded
+   */
+  void damageLayout()
+  {
+    updateLayoutStateNeeded = 1;
+    list.revalidate();
+  }
 
-	for (int i=0;i<l.getModel().getSize();i++)
+  /**
+   * Calls {@link #updateLayoutState} if {@link #updateLayoutStateNeeded}
+   * is nonzero, then resets {@link #updateLayoutStateNeeded} to zero.
+   */
+  void maybeUpdateLayoutState()
 	    {
-		boolean is_sel = false;
-		boolean has_focus = false;
+    // System.err.println(this + ".maybeUpdateLayoutState()");
+    if (updateLayoutStateNeeded != 0)
+      {
+        updateLayoutState();
+        updateLayoutStateNeeded = 0;
+      }
+  }
 
-		Component comp = render.getListCellRendererComponent(l,
-								     l.getModel().getElementAt(i),
-								     i,            
-								     is_sel,
-								     has_focus);
+  /**
+   * Creates a new BasicListUI object.
+   */
+  public BasicListUI()
+  {
+    focusListener = new FocusHandler();
+    listDataListener = new ListDataHandler();
+    listSelectionListener = new ListSelectionHandler();
+    mouseInputListener = new MouseInputHandler();
+    propertyChangeListener = new PropertyChangeHandler();
+    updateLayoutStateNeeded = 1;
+  }
 
-		//System.out.println("AAAAA=> " + a + ", " + comp + ", index = " + i);
+  /**
+   * Installs various default settings (mostly colors) from the {@link
+   * UIDefaults} into the {@link JList}
+   *
+   * @see #uninstallDefaults
+   */
+  void installDefaults()
+  {
+    UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+    list.setForeground(defaults.getColor("List.foreground"));
+    list.setBackground(defaults.getColor("List.background"));
+    list.setSelectionForeground(defaults.getColor("List.selectionForeground"));
+    list.setSelectionBackground(defaults.getColor("List.selectionBackground"));
+  }
 
-		comp.setBounds(a);
+  /**
+   * Resets to <code>null</code> those defaults which were installed in 
+   * {@link #installDefaults}
+   */
+  void uninstallDefaults()
+  {
+    UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+    list.setForeground(null);
+    list.setBackground(null);
+    list.setSelectionForeground(null);
+    list.setSelectionBackground(null);
+  }
 
-		comp.paint(g);
+  /**
+   * Attaches all the listeners we have in the UI class to the {@link
+   * JList}, its model and its selection model.
+   *
+   * @see #uninstallListeners
+   */
+  void installListeners()
+  {
+    list.addFocusListener(focusListener);
+    list.getModel().addListDataListener(listDataListener);
+    list.addListSelectionListener(listSelectionListener);
+    list.addMouseListener(mouseInputListener);
+    list.addMouseMotionListener(mouseInputListener);
+    list.addPropertyChangeListener(propertyChangeListener);
+  }
 
-		a.y += dim.height + gap_between_cells;
+  /**
+   * Detaches all the listeners we attached in {@link #installListeners}.
+   */
+  void uninstallListeners()
+  {
+    list.removeFocusListener(focusListener);
+    list.getModel().removeListDataListener(listDataListener);
+    list.removeListSelectionListener(listSelectionListener);
+    list.removeMouseListener(mouseInputListener);
+    list.removeMouseMotionListener(mouseInputListener);
+    list.removePropertyChangeListener(propertyChangeListener);
 	    }
+
+  /**
+   * Installs keyboard actions for this UI in the {@link JList}.
+   */
+  void installKeyboardActions()
+  {
     }
 
-  public int locationToIndex(JList list, Point location)
+  /**
+   * Uninstalls keyboard actions for this UI in the {@link JList}.
+   */
+  void uninstallKeyboardActions()
   {
-    throw new Error ("Not implemented");
   }
 
-  public Point indexToLocation(JList list, int index)
+  /**
+   * Installs the various aspects of the UI in the {@link JList}. In
+   * particular, calls {@link #installDefaults}, {@link #installListeners}
+   * and {@link #installKeyboardActions}. Also saves a reference to the
+   * provided component, cast to a {@link JList}.
+   *
+   * @param c The {@link JList} to install the UI into
+   */
+  public void installUI(final JComponent c)
+  {
+    super.installUI(c);
+    list = (JList) c;
+    installDefaults();
+    installListeners();
+    installKeyboardActions();
+    // System.err.println(this + ".installUI()");
+    maybeUpdateLayoutState();
+  }
+
+  /**
+   * Uninstalls all the aspects of the UI which were installed in {@link
+   * #installUI}. When finished uninstalling, drops the saved reference to
+   * the {@link JList}.
+   *
+   * @param c Ignored; the UI is uninstalled from the {@link JList}
+   * reference saved during the call to {@link #installUI}
+   */
+  public void uninstallUI(final JComponent c)
+  {
+    uninstallKeyboardActions();
+    uninstallListeners();
+    uninstallDefaults();
+    list = null;
+  }
+
+  /**
+   * Gets the maximum size this list can assume.
+   *
+   * @param c The component to measure the size of
+   *
+   * @return A new Dimension representing the component's maximum size
+   */
+  public Dimension getMaximumSize(JComponent c)
+  {
+    return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+  }
+
+  /**
+   * Gets the size this list would prefer to assume. This is calculated by
+   * calling {@link #getCellBounds} over the entire list.
+   *
+   * @param c Ignored; uses the saved {@link JList} reference 
+   *
+   * @return DOCUMENT ME!
+   */
+  public Dimension getPreferredSize(JComponent c)
+  {
+    maybeUpdateLayoutState();
+    if (list.getModel().getSize() == 0)
+      return new Dimension(0, 0);
+    Rectangle bounds = getCellBounds(list, 0, list.getModel().getSize() - 1);
+    return bounds.getSize();
+  }
+
+  /**
+   * Paints the packground of the list using the background color
+   * of the specified component.
+   *
+   * @param g The graphics context to paint in
+   * @param c The component to paint the background of
+   */
+  public void paintBackground(Graphics g, JComponent c)
+  {
+    Dimension size = getPreferredSize(c);
+    Color save = g.getColor();
+    g.setColor(c.getBackground());
+    g.fillRect(0, 0, size.width, size.height);
+    g.setColor(save);
+  }
+
+  /**
+   * Paints a single cell in the list.
+   *
+   * @param g The graphics context to paint in
+   * @param row The row number to paint
+   * @param bounds The bounds of the cell to paint, assuming a coordinate
+   * system beginning at <code>(0,0)</code> in the upper left corner of the
+   * list
+   * @param rend A cell renderer to paint with
+   * @param data The data to provide to the cell renderer
+   * @param sel A selection model to provide to the cell renderer
+   * @param lead The lead selection index of the list
+   */
+  void paintCell(Graphics g, int row, Rectangle bounds, ListCellRenderer rend,
+                 ListModel data, ListSelectionModel sel, int lead)
+  {
+    boolean is_sel = list.isSelectedIndex(row);
+    boolean has_focus = false;
+    Component comp = rend.getListCellRendererComponent(list,
+                                                       data.getElementAt(row),
+                                                       0, is_sel, has_focus);
+    g.translate(bounds.x, bounds.y);
+    comp.setBounds(new Rectangle(0, 0, bounds.width, bounds.height));
+    comp.paint(g);
+    g.translate(-bounds.x, -bounds.y);
+  }
+
+  /**
+   * Paints the list by calling {@link #paintBackground} and then repeatedly
+   * calling {@link #paintCell} for each visible cell in the list.
+   *
+   * @param g The graphics context to paint with
+   * @param c Ignored; uses the saved {@link JList} reference 
+   */
+  public void paint(Graphics g, JComponent c)
+  {
+    int nrows = Math.min(list.getVisibleRowCount(), list.getModel().getSize());
+    if (nrows == 0)
+      return;
+
+    maybeUpdateLayoutState();
+    ListCellRenderer render = list.getCellRenderer();
+    ListModel model = list.getModel();
+    ListSelectionModel sel = list.getSelectionModel();
+    int lead = sel.getLeadSelectionIndex();
+    paintBackground(g, list);
+
+    for (int row = 0; row < nrows; ++row)
+      {
+        Rectangle bounds = getCellBounds(list, row, row);
+        paintCell(g, row, bounds, render, model, sel, lead);
+      }
+  }
+
+  public int locationToIndex(JList list, Point location)
   {
     throw new Error ("Not implemented");
   }
 
-  public Rectangle getCellBounds(JList list, int index1, int index2)
+  public Point indexToLocation(JList list, int index)
   {
     throw new Error ("Not implemented");
   }
--- javax/swing/plaf/basic/BasicLookAndFeel.java	19 Feb 2004 18:59:11 -0000	1.4.2.4
+++ javax/swing/plaf/basic/BasicLookAndFeel.java	25 Feb 2004 23:56:23 -0000
@@ -226,6 +226,13 @@
   protected void initComponentDefaults(UIDefaults defaults)
   {
     Object[] uiDefaults;
+    
+    // The JDK's default L&F happens to use these three purple shades
+    // extensively.
+    Color lightPurple = new Color(0xCC, 0xCC, 0xFF);
+    Color midPurple = new Color(0x99, 0x99, 0xCC);
+    Color darkPurple = new Color(0x66, 0x66, 0x99);
+
     uiDefaults = new Object[] {
 
       "AbstractUndoableEdit.undoText", "Undo",
@@ -275,8 +282,8 @@
       "CheckBoxMenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12),
       "CheckBoxMenuItem.foreground", new ColorUIResource(Color.black),
       "CheckBoxMenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
-      "CheckBoxMenuItem.selectionBackground", new ColorUIResource(0, 0, 128),
-      "CheckBoxMenuItem.selectionForeground", new ColorUIResource(Color.white),
+      "CheckBoxMenuItem.selectionBackground", new ColorUIResource(lightPurple),
+      "CheckBoxMenuItem.selectionForeground", new ColorUIResource(Color.black),
       "ColorChooser.background", new ColorUIResource(Color.lightGray),
       "ColorChooser.cancelText", "Cancel",
       "ColorChooser.font", new FontUIResource("Dialog", Font.PLAIN, 12),
@@ -316,8 +323,8 @@
       "ComboBox.disabledForeground", new ColorUIResource(Color.gray),
       "ComboBox.font", new FontUIResource("SansSerif", Font.PLAIN, 12),
       "ComboBox.foreground", new ColorUIResource(Color.black),
-      "ComboBox.selectionBackground", new ColorUIResource(0, 0, 128),
-      "ComboBox.selectionForeground", new ColorUIResource(Color.white),
+      "ComboBox.selectionBackground", new ColorUIResource(lightPurple),
+      "ComboBox.selectionForeground", new ColorUIResource(Color.black),
       "Desktop.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
         "KP_LEFT", "left",
         "KP_RIGHT", "right",
@@ -412,8 +419,8 @@
       "FocusManagerClassName", "TODO",
       "FormView.resetButtonText", "Reset",
       "FormView.submitButtonText", "Submit Query",
-      "InternalFrame.activeTitleBackground", new ColorUIResource(0, 0, 128),
-      "InternalFrame.activeTitleForeground", new ColorUIResource(Color.white),
+      "InternalFrame.activeTitleBackground", new ColorUIResource(lightPurple),
+      "InternalFrame.activeTitleForeground", new ColorUIResource(Color.black),
       "InternalFrame.border", new BorderUIResource.CompoundBorderUIResource(null,
                                                                             null),
       "InternalFrame.closeIcon", BasicIconFactory.createEmptyFrameIcon(),
@@ -458,8 +465,8 @@
         "KP_DOWN", "selectNextRow"
       }),
       "List.foreground", new ColorUIResource(Color.black),
-      "List.selectionBackground", new ColorUIResource(0, 0, 128),
-      "List.selectionForeground", new ColorUIResource(Color.white),
+      "List.selectionBackground", new ColorUIResource(0xCC, 0xCC, 0xFF),
+      "List.selectionForeground", new ColorUIResource(Color.black),
       "Menu.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 12),
       "Menu.acceleratorForeground", new ColorUIResource(Color.black),
       "Menu.acceleratorSelectionForeground", new ColorUIResource(Color.white),
@@ -485,8 +492,8 @@
         "ENTER", "return",
         "SPACE", "return"
       },
-      "Menutext.selectionBackground", new ColorUIResource(0, 0, 128),
-      "Menu.selectionForeground", new ColorUIResource(Color.white),
+      "Menutext.selectionBackground", new ColorUIResource(lightPurple),
+      "Menu.selectionForeground", new ColorUIResource(Color.black),
       "MenuBar.background", new ColorUIResource(Color.lightGray),
       "MenuBar.border", new BasicBorders.MenuBarBorder(null, null),
       "MenuBar.font", new FontUIResource("Dialog", Font.PLAIN, 12),
@@ -506,8 +513,8 @@
       "MenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12),
       "MenuItem.foreground", new ColorUIResource(Color.black),
       "MenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
-      "MenuItem.selectionBackground", new ColorUIResource(0, 0, 128),
-      "MenuItem.selectionForeground", new ColorUIResource(Color.white),
+      "MenuItem.selectionBackground", new ColorUIResource(lightPurple),
+      "MenuItem.selectionForeground", new ColorUIResource(Color.black),
       "OptionPane.background", new ColorUIResource(Color.lightGray),
       "OptionPane.border", new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0),
       "OptionPane.buttonAreaBorder", new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0),
@@ -547,8 +554,8 @@
                                                              0),
                                       "notify-field-accept")},
       "PasswordField.margin", new InsetsUIResource(0, 0, 0, 0),
-      "PasswordField.selectionBackground", new ColorUIResource(0, 0, 128),
-      "PasswordField.selectionForeground", new ColorUIResource(Color.white),
+      "PasswordField.selectionBackground", new ColorUIResource(lightPurple),
+      "PasswordField.selectionForeground", new ColorUIResource(Color.black),
       "PopupMenu.background", new ColorUIResource(Color.lightGray),
       "PopupMenu.border", new BorderUIResource.BevelBorderUIResource(0),
       "PopupMenu.font", new FontUIResource("Dialog", Font.PLAIN, 12),
@@ -558,8 +565,8 @@
       "ProgressBar.cellLength", new Integer(1),
       "ProgressBar.cellSpacing", new Integer(0),
       "ProgressBar.font", new FontUIResource("Dialog", Font.PLAIN, 12),
-      "ProgressBar.foreground", new ColorUIResource(0, 0, 128),
-      "ProgressBar.selectionBackground", new ColorUIResource(0, 0, 128),
+      "ProgressBar.foreground", new ColorUIResource(midPurple),
+      "ProgressBar.selectionBackground", new ColorUIResource(lightPurple),
       "ProgressBar.selectionForeground", new ColorUIResource(Color.lightGray),
       "ProgressBar.repaintInterval", new Integer(250),
       "ProgressBar.cycleTime", new Integer(6000),
@@ -592,8 +599,8 @@
       "RadioButtonMenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12),
       "RadioButtonMenuItem.foreground", new ColorUIResource(Color.black),
       "RadioButtonMenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
-      "RadioButtonMenuItem.selectionBackground", new ColorUIResource(0, 0, 128),
-      "RadioButtonMenuItem.selectionForeground", new ColorUIResource(Color.white),
+      "RadioButtonMenuItem.selectionBackground", new ColorUIResource(lightPurple),
+      "RadioButtonMenuIt