I fixed a couple of bugs in JTable and BasicTableUI, and added the
variable row height feature.

2006-05-16  Roman Kennke <[EMAIL PROTECTED]>

        PR 26521
        * javax/swing/JTable.java
        (rowHeights): New field.
        (initializeLocalVars): Call setRowHeigt instead of rowHeight=,
        in order to initialize rowHeights correctly.
        (tableChanged): Nullify rowHeights when model changes. Only
        create default columns from model when corresponding property
        is set. Sync table model with rowHeights as appropriate.
        (valueChanged): Call repaint with the correct rectangle.
        (rowAtPoint): Handle rowHeights.
        (getCellRect): Mostly rewritten. Check for boundaries
        of model and return (0,0,0,0) or (0,0,width,height) when
outside.
        Handle component orientation. Round correctly.
        (getRowHeight(int)): Implemented for variable row height.
        (setRowHeight(int,int)): Implemented for variable row height.
        (setRowHeight(int)): Nullify rowHeights.
        (setModel): Notify tableChanged().
        * javax/swing/plaf/basic/BasicTableUI.java
        (installDefaults): Create rendererPane in installUI.
        (installUI): Create and install rendererPane.
        (uninstallUI): Uninstall rendererPane and nullify rendererPane
        and table.
        (paint): Correctly handle rowMargin.

/Roman

-- 
“Improvement makes straight roads, but the crooked roads, without
Improvement, are roads of Genius.” - William Blake
Index: javax/swing/JTable.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JTable.java,v
retrieving revision 1.104
diff -u -1 -0 -r1.104 JTable.java
--- javax/swing/JTable.java	16 May 2006 13:46:45 -0000	1.104
+++ javax/swing/JTable.java	16 May 2006 19:26:30 -0000
@@ -1598,20 +1598,35 @@
   /**
    * Indicates if the rowHeight property has been set by a client program or by
    * the UI.
    *
    * @see #setUIProperty(String, Object)
    * @see LookAndFeel#installProperty(JComponent, String, Object)
    */
   private boolean clientRowHeightSet = false;
 
   /**
+   * Stores the sizes and positions of each row, when using non-uniform row
+   * heights. Initially the height of all rows is equal and stored in
+   * {link #rowHeight}. However, when an application calls
+   * [EMAIL PROTECTED] #setRowHeight(int,int)}, the table switches to non-uniform
+   * row height mode which stores the row heights in the SizeSequence
+   * object instead.
+   *
+   * @see #setRowHeight(int)
+   * @see #getRowHeight()
+   * @see #getRowHeight(int)
+   * @see #setRowHeight(int, int)
+   */
+  private SizeSequence rowHeights;
+
+  /**
    * Creates a new <code>JTable</code> instance.
    */
   public JTable ()
   {
     this(null, null, null);
   }
 
   /**
    * Creates a new <code>JTable</code> instance with the given number
    * of rows and columns.
@@ -1737,21 +1752,21 @@
       createDefaultColumnsFromModel();
     this.columnModel.addColumnModelListener(this);
     
     this.defaultRenderersByColumnClass = new Hashtable();
     createDefaultRenderers();
 
     this.defaultEditorsByColumnClass = new Hashtable();
     createDefaultEditors();
 
     this.autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS;
-    this.rowHeight = 16;
+    setRowHeight(16);
     this.rowMargin = 1;
     this.rowSelectionAllowed = true;
     // this.accessibleContext = new AccessibleJTable();
     this.cellEditor = null;
     // COMPAT: Both Sun and IBM have drag enabled
     this.dragEnabled = true;
     this.preferredViewportSize = new Dimension(450,400);
     this.showHorizontalLines = true;
     this.showVerticalLines = true;
     this.editingColumn = -1;
@@ -1968,52 +1983,62 @@
   /**
    * Invoked when the table changes.
    * <code>null</code> means everything changed.
    */
   public void tableChanged (TableModelEvent event)
   {
     // update the column model from the table model if the structure has
     // changed and the flag autoCreateColumnsFromModel is set
     if ((event == null || (event.getFirstRow() == TableModelEvent.HEADER_ROW))
 	&& autoCreateColumnsFromModel)
-      createDefaultColumnsFromModel();
+      {
+        rowHeights = null;
+        if (getAutoCreateColumnsFromModel())
+          createDefaultColumnsFromModel();
+        resizeAndRepaint();
+        return;
+      }
 
     // If the structure changes, we need to revalidate, since that might
     // affect the size parameters of the JTable. Otherwise we only need
     // to perform a repaint to update the view.
     if (event == null || event.getType() == TableModelEvent.INSERT)
       {
         // Sync selection model with data model.
         if (event != null)
           {
             int first = event.getFirstRow();
             if (first < 0)
               first = 0;
             int last = event.getLastRow();
             if (last < 0)
               last = getRowCount() - 1;
             selectionModel.insertIndexInterval(first, last - first + 1, true);
+            if (rowHeights != null)
+              rowHeights.insertEntries(first, last - first + 1, rowHeight);
           }
         revalidate();
       }
     if (event == null || event.getType() == TableModelEvent.DELETE)
       {
         // Sync selection model with data model.
         if (event != null)
           {
             int first = event.getFirstRow();
             if (first < 0)
               first = 0;
             int last = event.getLastRow();
             if (last < 0)
               last = getRowCount() - 1;
             selectionModel.removeIndexInterval(first, last);
+            if (rowHeights != null)
+              rowHeights.removeEntries(first, last - first + 1);
           }
         if (dataModel.getRowCount() == 0)
           clearSelection();
         revalidate();
       }
     repaint();
   }
 
   /**
    * Invoked when another table row is selected. It is not recommended
@@ -2021,21 +2046,21 @@
    */
   public void valueChanged (ListSelectionEvent event)
   {
     // Repaint the changed region.
     int first = Math.max(0, Math.min(getRowCount() - 1, event.getFirstIndex()));
     int last = Math.max(0, Math.min(getRowCount() - 1, event.getLastIndex()));
     Rectangle rect1 = getCellRect(first, 0, false);
     Rectangle rect2 = getCellRect(last, getColumnCount() - 1, false);
     SwingUtilities.computeUnion(rect2.x, rect2.y, rect2.width, rect2.height,
                                 rect1);
-    repaint(rect2);
+    repaint(rect1);
   }
 
  /**
    * Returns index of the column that contains specified point 
    * or -1 if this table doesn't contain this point.
    *
    * @param point point to identify the column
    * @return index of the column that contains specified point or 
    * -1 if this table doesn't contain this point.
    */
@@ -2063,24 +2088,30 @@
    * 
    * @param point point to identify the row
    * @return index of the row that contains specified point or -1 if this table
    *         doesn't contain this point.
    */
   public int rowAtPoint(Point point)
   {
     if (point != null)
       {
         int nrows = getRowCount();
-        int height = getRowHeight() + getRowMargin();
+        int r;
         int y = point.y;
+        if (rowHeights == null)
+          {
+            int height = getRowHeight();
+            r = y / height;
+          }
+        else
+          r = rowHeights.getIndex(y);
 
-        int r = y / height;
         if (r < 0 || r >= nrows)
           return -1;
         else
           return r;
       }
     else
       return -1;
   }
 
   /** 
@@ -2096,41 +2127,84 @@
    * @param includeSpacing whether or not to include the cell margins in the
    * resulting cell. If <code>false</code>, the result will only contain the
    * inner area of the target cell, not including its margins.
    *
    * @return a rectangle enclosing the specified cell
    */
   public Rectangle getCellRect(int row,
                                int column,
                                boolean includeSpacing)
   {
-    int height = getRowHeight(row);
-    int width = columnModel.getColumn(column).getWidth();
-    int x_gap = columnModel.getColumnMargin();
-    int y_gap = rowMargin;
-
-    column = Math.max(0, Math.min(column, getColumnCount() - 1));
-    row = Math.max(0, Math.min(row, getRowCount() - 1));
+    Rectangle cellRect = new Rectangle(0, 0, 0, 0);
 
-    int x = 0;
-    int y = (height + y_gap) * row;
+    // Check for valid range vertically.
+    if (row >= getRowCount())
+      {
+        cellRect.height = getHeight();
+      }
+    else if (row >= 0)
+      {
+        cellRect.height = getRowHeight(row);
+        if (rowHeights == null)
+          cellRect.y = row * cellRect.height;
+        else
+          cellRect.y = rowHeights.getPosition(row);
 
-    for (int i = 0; i < column; ++i)
-      x += columnModel.getColumn(i).getWidth();
-    
-    Rectangle rect = new Rectangle();
+        if (! includeSpacing)
+          {
+            // The rounding here is important.
+            int rMargin = getRowMargin();
+            cellRect.y += rMargin / 2;
+            cellRect.height -= rMargin;
+          }
+      }
+    // else row < 0, y = height = 0
 
-    if (includeSpacing)
-      rect.setBounds(x, y, width, height +y_gap);
+    // Check for valid range horizontally.
+    if (column < 0)
+      {
+        if (! getComponentOrientation().isLeftToRight())
+          {
+            cellRect.x = getWidth();
+          }
+      }
+    else if (column >= getColumnCount())
+      {
+        if (getComponentOrientation().isLeftToRight())
+          {
+            cellRect.x = getWidth();
+          }
+      }
     else
-      rect.setBounds(x, y, width - x_gap, height);
-    return rect;
+      {
+        TableColumnModel tcm = getColumnModel();
+        if (getComponentOrientation().isLeftToRight())
+          {
+            for (int i = 0; i < column; i++)
+              cellRect.x += tcm.getColumn(i).getWidth();
+          }
+        else
+          {
+            for (int i = tcm.getColumnCount() - 1; i > column; i--)
+              cellRect.x += tcm.getColumn(i).getWidth();
+          }
+        cellRect.width = tcm.getColumn(column).getWidth();
+        if (! includeSpacing)
+          {
+            // The rounding here is important.
+            int cMargin = tcm.getColumnMargin();
+            cellRect.x += cMargin / 2;
+            cellRect.width -= cMargin;
+          }
+      }
+
+    return cellRect;
   }
 
   public void clearSelection()
   {
     selectionModel.clearSelection();
     getColumnModel().getSelectionModel().clearSelection();
   }
 
   /**
    * Get the value of the selectedRow property by delegation to
@@ -2427,23 +2501,24 @@
     return rowHeight;
   }
 
   /**
    * Get the height of the specified row.
    *
    * @param row the row whose height to return
    */
   public int getRowHeight(int row)
   {
-    // FIXME: return the height of the specified row
-    // which may be different from the general rowHeight
-    return rowHeight;
+    int rh = rowHeight;
+    if (rowHeights != null)
+      rh = rowHeights.getSize(row);
+    return rh;
   }
 
 
   /**
    * Get the value of the [EMAIL PROTECTED] #rowMargin} property.
    *
    * @return The current value of the property
    */
   public int getRowMargin()
   {
@@ -2789,47 +2864,55 @@
    * @param a The new value of the autoResizeMode property
    */ 
   public void setAutoResizeMode(int a)
   {
     autoResizeMode = a;
     revalidate();
     repaint();
   }
 
   /**
-   * Set the value of the [EMAIL PROTECTED] #rowHeight} property.
+   * Sets the height for all rows in the table. If you want to change the
+   * height of a single row instead, use [EMAIL PROTECTED] #setRowHeight(int, int)}.
    *
-   * @param r The new value of the rowHeight property
+   * @param r the height to set for all rows
+   *
+   * @see #getRowHeight()
+   * @see #setRowHeight(int, int)
+   * @see #getRowHeight(int)
    */ 
   public void setRowHeight(int r)
   {
     if (r < 1)
       throw new IllegalArgumentException();
 
     clientRowHeightSet = true;
 
     rowHeight = r;
+    rowHeights = null;
     revalidate();
     repaint();
   }
   
   /**
-   * Sets the value of the rowHeight property for the specified
-   * row.
+   * Sets the height of a single row in the table.
    * 
-   * @param rh is the new rowHeight
-   * @param row is the row to change the rowHeight of
+   * @param rh the new row height
+   * @param row the row to change the height of
    */
   public void setRowHeight(int row, int rh)
   {
-     setRowHeight(rh);
-     // FIXME: not implemented
+    if (rowHeights == null)
+      {
+        rowHeights = new SizeSequence(getRowCount(), rowHeight);
+      }
+    rowHeights.setSize(row, rh);
   }
   
   /**
    * Set the value of the [EMAIL PROTECTED] #rowMargin} property.
    *
    * @param r The new value of the rowMargin property
    */ 
   public void setRowMargin(int r)
   {
     rowMargin = r;
@@ -2887,20 +2970,24 @@
       dataModel.removeTableModelListener(this);
     
     if (m != null)
       {
         // Set property.
         dataModel = m;
 
         // Add table as TableModelListener to new model.
         dataModel.addTableModelListener(this);
 
+        // Notify the tableChanged method.
+        tableChanged(new TableModelEvent(dataModel,
+                                         TableModelEvent.HEADER_ROW));
+
         // Automatically create columns.
         if (autoCreateColumnsFromModel)
           createDefaultColumnsFromModel();
       }
 
     // This property is bound, so we fire a property change event.
     firePropertyChange("model", oldModel, dataModel);
 
     // Repaint table.
     revalidate();
@@ -3875,11 +3962,12 @@
           {
             setRowHeight(((Integer) value).intValue());
             clientRowHeightSet = false;
           }
       }
     else
       {
         super.setUIProperty(propertyName, value);
       }
   }
+
 }
Index: javax/swing/plaf/basic/BasicTableUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTableUI.java,v
retrieving revision 1.50
diff -u -1 -0 -r1.50 BasicTableUI.java
--- javax/swing/plaf/basic/BasicTableUI.java	4 May 2006 12:11:50 -0000	1.50
+++ javax/swing/plaf/basic/BasicTableUI.java	16 May 2006 19:26:30 -0000
@@ -421,21 +421,20 @@
   }
 
   protected void installDefaults() 
   {
     LookAndFeel.installColorsAndFont(table, "Table.background",
                                      "Table.foreground", "Table.font");
     table.setGridColor(UIManager.getColor("Table.gridColor"));
     table.setSelectionForeground(UIManager.getColor("Table.selectionForeground"));
     table.setSelectionBackground(UIManager.getColor("Table.selectionBackground"));
     table.setOpaque(true);
-    rendererPane = new CellRendererPane();
   }
 
   protected void installKeyboardActions() 
   {
     InputMap ancestorMap = (InputMap) UIManager.get("Table.ancestorInputMap");
     InputMapUIResource parentInputMap = new InputMapUIResource();
     // FIXME: The JDK uses a LazyActionMap for parentActionMap
     ActionMap parentActionMap = new ActionMapUIResource();
     action = new TableAction();
     Object keys[] = ancestorMap.allKeys();
@@ -1181,30 +1180,37 @@
     table.removeKeyListener(keyListener);
     table.removeMouseListener(mouseInputListener);    
     table.removeMouseMotionListener(mouseInputListener);
     table.removePropertyChangeListener(propertyChangeListener);
     propertyChangeListener = null;
   }
 
   public void installUI(JComponent comp) 
   {
     table = (JTable)comp;
+    rendererPane = new CellRendererPane();
+    table.add(rendererPane);
+
     installDefaults();
     installKeyboardActions();
     installListeners();
   }
 
   public void uninstallUI(JComponent c) 
   {
     uninstallListeners();
     uninstallKeyboardActions();
-    uninstallDefaults();    
+    uninstallDefaults(); 
+
+    table.remove(rendererPane);
+    rendererPane = null;
+    table = null;
   }
 
   /**
    * Paints a single cell in the table.
    *
    * @param g The graphics context to paint in
    * @param row The row number to paint
    * @param col The column 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
@@ -1250,44 +1256,43 @@
     int rowMargin = table.getRowMargin();
 
     TableColumnModel cmodel = table.getColumnModel();
     int [] widths = new int[cn+1];
     for (int i = c0; i <=cn ; i++)
       {
         widths[i] = cmodel.getColumn(i).getWidth() - columnMargin;
       }
     
     Rectangle bounds = table.getCellRect(r0, c0, false);
-
     // The left boundary of the area being repainted.
     int left = bounds.x;
     
     // The top boundary of the area being repainted.
     int top = bounds.y;
     
     // The bottom boundary of the area being repainted.
     int bottom;
     
     // paint the cell contents
     Color grid = table.getGridColor();    
     for (int r = r0; r <= rn; ++r)
       {
         for (int c = c0; c <= cn; ++c)
           {
             bounds.width = widths[c];
             paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c));
             bounds.x += widths[c] + columnMargin;
           }
         bounds.x = left;
-        bounds.y += table.getRowHeight(r) + rowMargin;
+        bounds.y += table.getRowHeight(r);
         // Update row height for tables with custom heights.
-        bounds.height = table.getRowHeight(r + 1);
+        bounds.height = table.getRowHeight(r + 1) - rowMargin;
       }
     
     bottom = bounds.y - rowMargin;
 
     // paint vertical grid lines
     if (grid != null && table.getShowVerticalLines())
       {    
         Color save = gfx.getColor();
         gfx.setColor(grid);
         int x = left - columnMargin;
@@ -1304,17 +1309,17 @@
     // paint horizontal grid lines    
     if (grid != null && table.getShowHorizontalLines())
       {    
         Color save = gfx.getColor();
         gfx.setColor(grid);
         int y = top - rowMargin;
         for (int r = r0; r <= rn; ++r)
           {
             // The horizontal grid is draw below the cells, so we 
             // add before drawing.
-            y += table.getRowHeight(r) + rowMargin;
+            y += table.getRowHeight(r);// + rowMargin;
             gfx.drawLine(left, y, p2.x, y);
           }
         gfx.setColor(save);
       }
   }
 }

Attachment: signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil

Reply via email to