My last 'fix' for BasicListUI introduced some new misbehaviour in JList
rendering. This should be fixed by this patch.

2005-11-15  Roman Kennke  <[EMAIL PROTECTED]>

        * javax/swing/plaf/basic/BasicListUI.java
        Fixed API docs all over to better explain the changed (but
correct)
        behaviour.
        (convertYToRow): Added some short-circuits for special cases.
Update
        the layout state if necessary. Fixed to match the JDK behaviour.
        Added API docs to better explain the behaviour.
        (updateLayoutState): When a fixedCellHeight is set, then use the
        cellHeight field, otherwise use the cellHeights array.
        (uninstallDefaults): Removed unnecessary statement.
        (paintBackground): Removed unnecessary method.
        (paintCell): Removed some commented-out code.
        (paint): Removed call to paintBackground().
        (locationToIndex): Removed unused statement.


/Roman
Index: javax/swing/plaf/basic/BasicListUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicListUI.java,v
retrieving revision 1.38
diff -u -r1.38 BasicListUI.java
--- javax/swing/plaf/basic/BasicListUI.java	10 Nov 2005 20:32:23 -0000	1.38
+++ javax/swing/plaf/basic/BasicListUI.java	15 Nov 2005 13:09:08 -0000
@@ -38,7 +38,6 @@
 
 package javax.swing.plaf.basic;
 
-import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.Graphics;
@@ -650,7 +649,11 @@
   /** Saved reference to the list this UI was created for. */
   protected JList list;
 
-  /** The height of a single cell in the list. */
+  /**
+   * The height of a single cell in the list. This field is used when the
+   * fixedCellHeight property of the list is set. Otherwise this field is
+   * set to <code>-1</code> and [EMAIL PROTECTED] #cellHeights} is used instead.
+   */
   protected int cellHeight;
 
   /** The width of a single cell in the list. */
@@ -658,7 +661,9 @@
 
   /** 
    * An array of varying heights of cells in the list, in cases where each
-   * cell might have a different height.
+   * cell might have a different height. This field is used when the
+   * <code>fixedCellHeight</code> property of the list is not set. Otherwise
+   * this field is <code>null</code> and [EMAIL PROTECTED] #cellHeight} is used.
    */
   protected int[] cellHeights;
 
@@ -772,19 +777,51 @@
    * @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
+   *         if the list model is empty
+   *
+   * @specnote This method is specified to return -1 for an invalid Y
+   *           coordinate. However, some simple tests show that the behaviour
+   *           is to return the index of the last list element for an Y
+   *           coordinate that lies outside of the list bounds (even for
+   *           negative indices). <code>-1</code>
+   *           is only returned if the list model is empty.
    */
   protected int convertYToRow(int y0)
   {
-    for (int row = 0; row < cellHeights.length; ++row)
-      {
-        int h = getRowHeight(row);
+    if (list.getModel().getSize() == 0)
+      return -1;
+
+    // When y0 < 0, then the JDK returns the maximum row index of the list. So
+    // do we.
+    if (y0 < 0)
+      return list.getModel().getSize() - 1;
 
-        if (y0 < h)
-          return row;
-        y0 -= h;
+    // Update the layout if necessary.
+    maybeUpdateLayoutState();
+
+    int index = list.getModel().getSize() - 1;;
+
+    // If a fixed cell height is set, then we can work more efficient.
+    if (cellHeight > 0)
+      {
+        index = Math.max(y0 / cellHeight, index);
       }
-    return -1;
+    // If we have no fixed cell height, we must add up each cell height up
+    // to y0.
+    else
+      {
+        int h = 0;
+        for (int row = 0; row < cellHeights.length; ++row)
+          {
+            h += cellHeights[row];
+            if (y0 < h)
+              {
+                index = row;
+                break;
+              }
+          }
+      }
+    return index;
   }
 
   /**
@@ -802,14 +839,14 @@
     ListCellRenderer rend = list.getCellRenderer();
     // Update the cellHeight(s) fields.
     int fixedCellHeight = list.getFixedCellHeight();
-    if (fixedCellHeight >= 0)
+    if (fixedCellHeight > 0)
       {
         cellHeight = fixedCellHeight;
-        for (int i = 0; i < cellHeights.length; ++i)
-          cellHeights[i] = cellHeight;
+        cellHeights = null;
       }
     else
       {
+        cellHeight = -1;
         for (int i = 0; i < nrows; ++i)
           {
             Component flyweight =
@@ -819,14 +856,12 @@
                       list.getSelectionModel().getAnchorSelectionIndex() == i);
             Dimension dim = flyweight.getPreferredSize();
             cellHeights[i] = dim.height;
-            // Compute average cell height (little hack here).
-            cellHeight = (cellHeight * i + cellHeights[i]) / (i + 1);
           }
       }
 
     // Update the cellWidth field.
     int fixedCellWidth = list.getFixedCellWidth();
-    if (fixedCellWidth >= 0)
+    if (fixedCellWidth > 0)
       cellWidth = fixedCellWidth;
     else
       {
@@ -900,7 +935,6 @@
    */
   protected void uninstallDefaults()
   {
-    UIDefaults defaults = UIManager.getLookAndFeelDefaults();
     list.setForeground(null);
     list.setBackground(null);
     list.setSelectionForeground(null);
@@ -1068,22 +1102,6 @@
   }
 
   /**
-   * 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
-   */
-  private 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
@@ -1105,14 +1123,12 @@
     Component comp = rend.getListCellRendererComponent(list,
                                                        data.getElementAt(row),
                                                        0, isSel, hasFocus);
-    //comp.setBounds(new Rectangle(0, 0, bounds.width, bounds.height));
-    //comp.paint(g);
     rendererPane.paintComponent(g, comp, list, bounds);
   }
 
   /**
-   * Paints the list by calling [EMAIL PROTECTED] #paintBackground} and then repeatedly
-   * calling [EMAIL PROTECTED] #paintCell} for each visible cell in the list.
+   * Paints the list by repeatedly calling [EMAIL PROTECTED] #paintCell} for each visible
+   * cell in the list.
    *
    * @param g The graphics context to paint with
    * @param c Ignored; uses the saved [EMAIL PROTECTED] JList} reference 
@@ -1129,11 +1145,11 @@
     ListSelectionModel sel = list.getSelectionModel();
     int lead = sel.getLeadSelectionIndex();
     Rectangle clip = g.getClipBounds();
-    paintBackground(g, list);
 
     int startIndex = list.locationToIndex(new Point(clip.x, clip.y));
     int endIndex = list.locationToIndex(new Point(clip.x + clip.width,
                                                   clip.y + clip.height));
+    
     for (int row = startIndex; row <= endIndex; ++row)
       {
         Rectangle bounds = getCellBounds(list, row, row);
@@ -1143,13 +1159,15 @@
   }
 
   /**
-   * Computes the index of a list cell given a point within the list.
+   * Computes the index of a list cell given a point within the list. If the
+   * location lies outside the bounds of the list, the greatest index in the
+   * list model is returned.
    *
    * @param list the list which on which the computation is based on
    * @param location the coordinates
    *
    * @return the index of the list item that is located at the given
-   *         coordinates or <code>null</code> if the location is invalid
+   *         coordinates or <code>-1</code> if the list model is empty
    */
   public int locationToIndex(JList list, Point location)
   {
@@ -1199,7 +1217,6 @@
         int numberOfItems2 = list.getModel().getSize();
         int cellsPerRow2 = numberOfItems2 / visibleRows2 + 1;
 
-        Dimension listDim2 = list.getSize();
         int gridX2 = Math.min(location.x / cellWidth, cellsPerRow2 - 1);
         int gridY2 = Math.min(location.y / cellHeight, visibleRows2);
         index = gridY2 + gridX2 * visibleRows2;
_______________________________________________
Classpath-patches mailing list
Classpath-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath-patches

Reply via email to