This implements and fixes a couple of things in BasicTableUI:

1. The FocusHandler should refresh the lead cell on focus change. The lead cell is usually painted differently to highlight the currently focused cell.

2. The MouseHandler has some unused methods which have been marked unimplemented, but are really only there to implement the MouseListener interfaces. I removed the throws NotImplementedException.

3. The TableAction is now static and shared between all JTable instances. This uses the __command__ hack from my previous patch to avoid the need for lots of Action instances to be created.

4. The installKeyboardActions now use the same pattern that I implemented in some other classes too (use LookAndFeel methods for fetching the InputMap, cache ActionMap in UIDefaults, share both the InputMap and ActionMap between component instances, etc).

2006-07-26  Roman Kennke  <[EMAIL PROTECTED]>

        * javax/swing/plaf/basic/BasicTableUI.java
        (FocusHandler.focusGained): Implemented to refresh the
        lead cell.
        (FocusHandler.focusLost): Implemented to refresh the
        lead cell.
        (FocusHandler.repaintLeadCell): New helper method.
        (MouseInputHandler.mouseEntered): Do nothing here.
        (MouseInputHandler.mouseExited): Do nothing here.
        (MouseInputHandler.mouseMoved): Do nothing here.
        (installKeyboardActions): Rewritten to use a shared InputMap
        and ActionMap and correctly install the maps via SwingUtilities
        methods.
        (getActionMap): New helper method.
        (createDefaultActions): New helper method.
        (ActionListenerProxy): Removed unneeded class.
        (TableAction): Made class static.
        (TableAction.actionPerformed): Determine table by fetching
        the event source. Pass the table to helper methods.
        Use __command__ hack to determine the action command.
        (TableAction.getFirstVisibleColumnIndex): Get table as argument.
        (TableAction.getLastVisibleColumnIndex): Get table as argument.
        (TableAction.getFirstVisibleRowIndex): Get table as argument.
        (TableAction.getLastVisibleRowIndex): Get table as argument.
        (TableAction.advanceMultipleSelection): Get table as argument.
        (uninstallDefaults): Do nothing here.
        (uninstallKeyboardActions): Uninstall the keyboard actions.


/Roman
Index: javax/swing/plaf/basic/BasicTableUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTableUI.java,v
retrieving revision 1.55
diff -u -1 -2 -r1.55 BasicTableUI.java
--- javax/swing/plaf/basic/BasicTableUI.java	4 Jul 2006 18:00:48 -0000	1.55
+++ javax/swing/plaf/basic/BasicTableUI.java	26 Jul 2006 09:58:56 -0000
@@ -29,61 +29,59 @@
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 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 gnu.classpath.NotImplementedException;
-
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.ComponentOrientation;
 import java.awt.Dimension;
 import java.awt.Graphics;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.FocusEvent;
 import java.awt.event.FocusListener;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 import java.awt.event.MouseEvent;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 
 import javax.swing.AbstractAction;
+import javax.swing.Action;
 import javax.swing.ActionMap;
 import javax.swing.CellRendererPane;
 import javax.swing.DefaultCellEditor;
 import javax.swing.DefaultListSelectionModel;
 import javax.swing.InputMap;
 import javax.swing.JComponent;
 import javax.swing.JTable;
-import javax.swing.KeyStroke;
 import javax.swing.ListSelectionModel;
 import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
+import javax.swing.TransferHandler;
 import javax.swing.UIManager;
 import javax.swing.border.Border;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.MouseInputListener;
 import javax.swing.plaf.ActionMapUIResource;
 import javax.swing.plaf.ComponentUI;
-import javax.swing.plaf.InputMapUIResource;
 import javax.swing.plaf.TableUI;
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 import javax.swing.table.TableColumn;
 import javax.swing.table.TableColumnModel;
 import javax.swing.table.TableModel;
 
 public class BasicTableUI extends TableUI
 {
   public static ComponentUI createUI(JComponent comp) 
   {
     return new BasicTableUI();
@@ -155,32 +153,55 @@
      *
      * @param event the key event
      */
     public void keyReleased(KeyEvent event)
     {
       // Key events should be handled through the InputMap/ActionMap mechanism
       // since JDK1.3. This class is only there for backwards compatibility.
     }
   }
 
   public class FocusHandler implements FocusListener
   {
-    public void focusGained(FocusEvent e) throws NotImplementedException
+    public void focusGained(FocusEvent e)
     {
-      // TODO: Implement this properly.
+      // The only thing that is affected by a focus change seems to be
+      // how the lead cell is painted. So we repaint this cell.
+      repaintLeadCell();
     }
 
-    public void focusLost(FocusEvent e) throws NotImplementedException
+    public void focusLost(FocusEvent e)
     {
-      // TODO: Implement this properly.
+      // The only thing that is affected by a focus change seems to be
+      // how the lead cell is painted. So we repaint this cell.
+      repaintLeadCell();
+    }
+
+    /**
+     * Repaints the lead cell in response to a focus change, to refresh
+     * the display of the focus indicator.
+     */
+    private void repaintLeadCell()
+    {
+      int rowCount = table.getRowCount();
+      int columnCount = table.getColumnCount();
+      int rowLead = table.getSelectionModel().getLeadSelectionIndex();
+      int columnLead = table.getColumnModel().getSelectionModel().
+                                                       getLeadSelectionIndex();
+      if (rowLead >= 0 && rowLead < rowCount && columnLead >= 0
+          && columnLead < columnCount)
+        {
+          Rectangle dirtyRect = table.getCellRect(rowLead, columnLead, false);
+          table.repaint(dirtyRect);
+        }
     }
   }
 
   public class MouseInputHandler implements MouseInputListener
   {
     Point begin, curr;
 
     private void updateSelection(boolean controlPressed)
     {
       // Update the rows
       int lo_row = table.rowAtPoint(begin);
       int hi_row  = table.rowAtPoint(curr);
@@ -233,38 +254,37 @@
         }
     }
 
     public void mouseDragged(MouseEvent e) 
     {
       if (table.isEnabled())
         {
           curr = new Point(e.getX(), e.getY());
           updateSelection(e.isControlDown());
         }
     }
 
-    public void mouseEntered(MouseEvent e) 
-    throws NotImplementedException
+    public void mouseEntered(MouseEvent e)
     {
-      // TODO: What should be done here, if anything?
+      // Nothing to do here.
     }
 
-    public void mouseExited(MouseEvent e) throws NotImplementedException
+    public void mouseExited(MouseEvent e)
     {
-      // TODO: What should be done here, if anything?
+      // Nothing to do here.
     }
 
-    public void mouseMoved(MouseEvent e) throws NotImplementedException
+    public void mouseMoved(MouseEvent e)
     {
-      // TODO: What should be done here, if anything?
+      // Nothing to do here.
     }
 
     public void mousePressed(MouseEvent e) 
     {
       if (table.isEnabled())
         {
           ListSelectionModel rowModel = table.getSelectionModel();
           ListSelectionModel colModel = table.getColumnModel().getSelectionModel();
           int rowLead = rowModel.getLeadSelectionIndex();
           int colLead = colModel.getLeadSelectionIndex();
 
           begin = new Point(e.getX(), e.getY());
@@ -448,114 +468,153 @@
   }
 
   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);
   }
 
+  /**
+   * Installs keyboard actions on the table.
+   */
   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();
-    // Register key bindings in the UI InputMap-ActionMap pair
-    for (int i = 0; i < keys.length; i++)
-      {
-        KeyStroke stroke = (KeyStroke) keys[i];
-        String actionString = (String) ancestorMap.get(stroke);
+    // Install the input map.
+    InputMap inputMap =
+      (InputMap) SharedUIDefaults.get("Table.ancestorInputMap");
+    SwingUtilities.replaceUIInputMap(table,
+                                 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
+                                 inputMap);
 
-        parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(),
-                                                  stroke.getModifiers()),
-                           actionString);
-
-        parentActionMap.put(actionString, 
-                            new ActionListenerProxy(action, actionString));
+    // FIXME: The JDK uses a LazyActionMap for parentActionMap
+    SwingUtilities.replaceUIActionMap(table, getActionMap());
 
-      }
-    // Set the UI InputMap-ActionMap pair to be the parents of the
-    // JTable's InputMap-ActionMap pair
-    parentInputMap.setParent(table.getInputMap(
-        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).getParent());
-    parentActionMap.setParent(table.getActionMap().getParent());
-    table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
-      setParent(parentInputMap);
-    table.getActionMap().setParent(parentActionMap);
   }
 
   /**
-   * This class is used to mimmic the behaviour of the JDK when registering
-   * keyboard actions.  It is the same as the private class used in JComponent
-   * for the same reason.  This class receives an action event and dispatches
-   * it to the true receiver after altering the actionCommand property of the
-   * event.
+   * Fetches the action map from  the UI defaults, or create a new one
+   * if the action map hasn't been initialized.
+   *
+   * @return the action map
    */
-  private static class ActionListenerProxy
-    extends AbstractAction
+  private ActionMap getActionMap()
+  {
+    ActionMap am = (ActionMap) UIManager.get("Table.actionMap");
+    if (am == null)
+      {
+        am = createDefaultActions();
+        UIManager.getLookAndFeelDefaults().put("Tree.actionMap", am);
+      }
+    return am;
+  }
+
+  private ActionMap createDefaultActions()
   {
-    ActionListener target;
-    String bindingCommandName;
+    ActionMapUIResource am = new ActionMapUIResource();
+    Action action = new TableAction();
 
-    public ActionListenerProxy(ActionListener li, 
-                               String cmd)
-    {
-      target = li;
-      bindingCommandName = cmd;
-    }
+    am.put("cut", TransferHandler.getCutAction());
+    am.put("copy", TransferHandler.getCopyAction());
+    am.put("paste", TransferHandler.getPasteAction());
+
+    am.put("cancel", action);
+    am.put("selectAll", action);
+    am.put("clearSelection", action);
+    am.put("startEditing", action);
+
+    am.put("selectNextRow", action);
+    am.put("selectNextRowCell", action);
+    am.put("selectNextRowExtendSelection", action);
+    am.put("selectNextRowChangeLead", action);
+
+    am.put("selectPreviousRow", action);
+    am.put("selectPreviousRowCell", action);
+    am.put("selectPreviousRowExtendSelection", action);
+    am.put("selectPreviousRowChangeLead", action);
+
+    am.put("selectNextColumn", action);
+    am.put("selectNextColumnCell", action);
+    am.put("selectNextColumnExtendSelection", action);
+    am.put("selectNextColumnChangeLead", action);
+
+    am.put("selectPreviousColumn", action);
+    am.put("selectPreviousColumnCell", action);
+    am.put("selectPreviousColumnExtendSelection", action);
+    am.put("selectPreviousColumnChangeLead", action);
+
+    am.put("scrollLeftChangeSelection", action);
+    am.put("scrollLeftExtendSelection", action);
+    am.put("scrollRightChangeSelection", action);
+    am.put("scrollRightExtendSelection", action);
+
+    am.put("scrollUpChangeSelection", action);
+    am.put("scrollUpExtendSelection", action);
+    am.put("scrollDownChangeSelection", action);
+    am.put("scrolldownExtendSelection", action);
+
+    am.put("selectFirstColumn", action);
+    am.put("selectFirstColumnExtendSelection", action);
+    am.put("selectLastColumn", action);
+    am.put("selectLastColumnExtendSelection", action);
+
+    am.put("selectFirstRow", action);
+    am.put("selectFirstRowExtendSelection", action);
+    am.put("selectLastRow", action);
+    am.put("selectLastRowExtendSelection", action);
+
+    am.put("addToSelection", action);
+    am.put("toggleAndAnchor", action);
+    am.put("extendTo", action);
+    am.put("moveSelectionTo", action);
 
-    public void actionPerformed(ActionEvent e)
-    {
-      ActionEvent derivedEvent = new ActionEvent(e.getSource(),
-                                                 e.getID(),
-                                                 bindingCommandName,
-                                                 e.getModifiers());
-      target.actionPerformed(derivedEvent);
-    }
+    return am;
   }
 
   /**
    * This class implements the actions that we want to happen
    * when specific keys are pressed for the JTable.  The actionPerformed
    * method is called when a key that has been registered for the JTable
    * is received.
    */
-  class TableAction extends AbstractAction
+  private static class TableAction
+    extends AbstractAction
   {
     /**
      * What to do when this action is called.
      *
      * @param e the ActionEvent that caused this action.
      */
     public void actionPerformed(ActionEvent e)
     {
+      JTable table = (JTable) e.getSource();
+
       DefaultListSelectionModel rowModel 
           = (DefaultListSelectionModel) table.getSelectionModel();
       DefaultListSelectionModel colModel 
           = (DefaultListSelectionModel) table.getColumnModel().getSelectionModel();
 
       int rowLead = rowModel.getLeadSelectionIndex();
       int rowMax = table.getModel().getRowCount() - 1;
       
       int colLead = colModel.getLeadSelectionIndex();
       int colMax = table.getModel().getColumnCount() - 1;
-      
-      String command = e.getActionCommand();
-      
+
+      // The command with which the action has been called is stored
+      // in this undocumented action value. This allows us to have only
+      // one Action instance to serve all keyboard input for JTable.
+      String command = (String) getValue("__command__");
       if (command.equals("selectPreviousRowExtendSelection"))
         {
           rowModel.setLeadSelectionIndex(Math.max(rowLead - 1, 0));
         }
       else if (command.equals("selectLastColumn"))
         {
           colModel.setSelectionInterval(colMax, colMax);
         }
       else if (command.equals("startEditing"))
         {
           if (table.isCellEditable(rowLead, colLead))
             table.editCellAt(rowLead, colLead);
@@ -595,63 +654,64 @@
       else if (command.equals("selectPreviousColumnExtendSelection"))
         {
           colModel.setLeadSelectionIndex(Math.max(colLead - 1, 0));
         }
       else if (command.equals("selectNextRow"))
         {
           rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax),
                                         Math.min(rowLead + 1, rowMax));
         }
       else if (command.equals("scrollUpExtendSelection"))
         {
           int target;
-          if (rowLead == getFirstVisibleRowIndex())
-            target = Math.max(0, rowLead - (getLastVisibleRowIndex() 
-                - getFirstVisibleRowIndex() + 1));
+          if (rowLead == getFirstVisibleRowIndex(table))
+            target = Math.max(0, rowLead - (getLastVisibleRowIndex(table) 
+                - getFirstVisibleRowIndex(table) + 1));
           else
-            target = getFirstVisibleRowIndex();
+            target = getFirstVisibleRowIndex(table);
           
           rowModel.setLeadSelectionIndex(target);
           colModel.setLeadSelectionIndex(colLead);
         }
       else if (command.equals("selectPreviousRow"))
         {
           rowModel.setSelectionInterval(Math.max(rowLead - 1, 0),
                                         Math.max(rowLead - 1, 0));
         }
       else if (command.equals("scrollRightChangeSelection"))
         {
           int target;
-          if (colLead == getLastVisibleColumnIndex())
-            target = Math.min(colMax, colLead + (getLastVisibleColumnIndex() 
-                - getFirstVisibleColumnIndex() + 1));
+          if (colLead == getLastVisibleColumnIndex(table))
+            target = Math.min(colMax, colLead
+                              + (getLastVisibleColumnIndex(table)
+                              - getFirstVisibleColumnIndex(table) + 1));
           else
-            target = getLastVisibleColumnIndex();
+            target = getLastVisibleColumnIndex(table);
           
           colModel.setSelectionInterval(target, target);
           rowModel.setSelectionInterval(rowLead, rowLead);
         }
       else if (command.equals("selectPreviousColumn"))
         {
           colModel.setSelectionInterval(Math.max(colLead - 1, 0),
                                         Math.max(colLead - 1, 0));
         }
       else if (command.equals("scrollLeftChangeSelection"))
         {
           int target;
-          if (colLead == getFirstVisibleColumnIndex())
-            target = Math.max(0, colLead - (getLastVisibleColumnIndex() 
-                - getFirstVisibleColumnIndex() + 1));
+          if (colLead == getFirstVisibleColumnIndex(table))
+            target = Math.max(0, colLead - (getLastVisibleColumnIndex(table) 
+                                 - getFirstVisibleColumnIndex(table) + 1));
           else
-            target = getFirstVisibleColumnIndex();
+            target = getFirstVisibleColumnIndex(table);
           
           colModel.setSelectionInterval(target, target);
           rowModel.setSelectionInterval(rowLead, rowLead);
         }
       else if (command.equals("clearSelection"))
         {
           table.clearSelection();
         }
       else if (command.equals("cancel"))
         {
           // FIXME: implement other parts of "cancel" like undo-ing last
           // selection.  Right now it just calls editingCancelled if
@@ -715,103 +775,107 @@
             rowModel.getMaxSelectionIndex() : table.getModel().getRowCount() - 1;
           int rowMinSelected = table.getRowSelectionAllowed() ? 
             rowModel.getMinSelectionIndex() : 0; 
           int colMaxSelected = table.getColumnSelectionAllowed() ? 
             colModel.getMaxSelectionIndex() : 
             table.getModel().getColumnCount() - 1;
           int colMinSelected = table.getColumnSelectionAllowed() ? 
             colModel.getMinSelectionIndex() : 0;
           
           // If there are multiple rows and columns selected, select the next
           // cell and wrap at the edges of the selection.  
           if (command.indexOf("Column") != -1) 
-            advanceMultipleSelection(colModel, colMinSelected, colMaxSelected, 
-                rowModel, rowMinSelected, rowMaxSelected, 
-                command.equals("selectPreviousColumnCell"), true);
+            advanceMultipleSelection(table, colModel, colMinSelected,
+                                     colMaxSelected, rowModel, rowMinSelected,
+                                     rowMaxSelected,
+                                    command.equals("selectPreviousColumnCell"),
+                                    true);
           
           else
-            advanceMultipleSelection(rowModel, rowMinSelected, rowMaxSelected, 
-                colModel, colMinSelected, colMaxSelected, 
-                command.equals("selectPreviousRowCell"), false);
+            advanceMultipleSelection(table, rowModel, rowMinSelected,
+                                     rowMaxSelected, colModel, colMinSelected,
+                                     colMaxSelected,
+                                     command.equals("selectPreviousRowCell"),
+                                     false);
         }
       else if (command.equals("selectNextColumn"))
         {
           colModel.setSelectionInterval(Math.min(colLead + 1, colMax),
                                         Math.min(colLead + 1, colMax));
         }
       else if (command.equals("scrollLeftExtendSelection"))
         {
           int target;
-          if (colLead == getFirstVisibleColumnIndex())
-            target = Math.max(0, colLead - (getLastVisibleColumnIndex() 
-                - getFirstVisibleColumnIndex() + 1));
+          if (colLead == getFirstVisibleColumnIndex(table))
+            target = Math.max(0, colLead - (getLastVisibleColumnIndex(table) 
+                                 - getFirstVisibleColumnIndex(table) + 1));
           else
-            target = getFirstVisibleColumnIndex();
+            target = getFirstVisibleColumnIndex(table);
           
           colModel.setLeadSelectionIndex(target);
           rowModel.setLeadSelectionIndex(rowLead);
         }
       else if (command.equals("scrollDownChangeSelection"))
         {
           int target;
-          if (rowLead == getLastVisibleRowIndex())
-            target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex() 
-                - getFirstVisibleRowIndex() + 1));
+          if (rowLead == getLastVisibleRowIndex(table))
+            target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex(table)
+                                      - getFirstVisibleRowIndex(table) + 1));
           else
-            target = getLastVisibleRowIndex();
+            target = getLastVisibleRowIndex(table);
           
           rowModel.setSelectionInterval(target, target);
           colModel.setSelectionInterval(colLead, colLead);
         }
       else if (command.equals("scrollRightExtendSelection"))
         {
           int target;
-          if (colLead == getLastVisibleColumnIndex())
-            target = Math.min(colMax, colLead + (getLastVisibleColumnIndex() 
-                - getFirstVisibleColumnIndex() + 1));
+          if (colLead == getLastVisibleColumnIndex(table))
+            target = Math.min(colMax, colLead + (getLastVisibleColumnIndex(table) 
+                - getFirstVisibleColumnIndex(table) + 1));
           else
-            target = getLastVisibleColumnIndex();
+            target = getLastVisibleColumnIndex(table);
           
           colModel.setLeadSelectionIndex(target);
           rowModel.setLeadSelectionIndex(rowLead);
         }
       else if (command.equals("selectAll"))
         {
           table.selectAll();
         }
       else if (command.equals("selectLastRowExtendSelection"))
         {
           rowModel.setLeadSelectionIndex(rowMax);
           colModel.setLeadSelectionIndex(colLead);
         }
       else if (command.equals("scrollDownExtendSelection"))
         {
           int target;
-          if (rowLead == getLastVisibleRowIndex())
-            target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex() 
-                - getFirstVisibleRowIndex() + 1));
+          if (rowLead == getLastVisibleRowIndex(table))
+            target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex(table) 
+                - getFirstVisibleRowIndex(table) + 1));
           else
-            target = getLastVisibleRowIndex();
+            target = getLastVisibleRowIndex(table);
           
           rowModel.setLeadSelectionIndex(target);
           colModel.setLeadSelectionIndex(colLead);
         }      
       else if (command.equals("scrollUpChangeSelection"))
         {
           int target;
-          if (rowLead == getFirstVisibleRowIndex())
-            target = Math.max(0, rowLead - (getLastVisibleRowIndex() 
-                - getFirstVisibleRowIndex() + 1));
+          if (rowLead == getFirstVisibleRowIndex(table))
+            target = Math.max(0, rowLead - (getLastVisibleRowIndex(table) 
+                - getFirstVisibleRowIndex(table) + 1));
           else
-            target = getFirstVisibleRowIndex();
+            target = getFirstVisibleRowIndex(table);
           
           rowModel.setSelectionInterval(target, target);
           colModel.setSelectionInterval(colLead, colLead);
         }
       else if (command.equals("selectNextRowChangeLead"))
           {
             if (rowModel.getSelectionMode() 
                 != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
               {
                 // just "selectNextRow"
                 rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax),
                                               Math.min(rowLead + 1, rowMax));
@@ -918,76 +982,76 @@
           && command != "addToSelection")
         table.editingStopped(new ChangeEvent("update"));
             
       table.scrollRectToVisible(table.getCellRect(
           rowModel.getLeadSelectionIndex(), colModel.getLeadSelectionIndex(), 
           false));
     }
     
     /**
      * Returns the column index of the first visible column.
      * @return the column index of the first visible column.
      */
-    int getFirstVisibleColumnIndex()
+    int getFirstVisibleColumnIndex(JTable table)
     {
       ComponentOrientation or = table.getComponentOrientation();
       Rectangle r = table.getVisibleRect();
       if (!or.isLeftToRight())
         r.translate((int) r.getWidth() - 1, 0);
       return table.columnAtPoint(r.getLocation());
     }
     
     /**
      * Returns the column index of the last visible column.
      *
      */
-    int getLastVisibleColumnIndex()
+    int getLastVisibleColumnIndex(JTable table)
     {
       ComponentOrientation or = table.getComponentOrientation();
       Rectangle r = table.getVisibleRect();
       if (or.isLeftToRight())
         r.translate((int) r.getWidth() - 1, 0);
       return table.columnAtPoint(r.getLocation());      
     }
     
     /**
      * Returns the row index of the first visible row.
      *
      */
-    int getFirstVisibleRowIndex()
+    int getFirstVisibleRowIndex(JTable table)
     {
       ComponentOrientation or = table.getComponentOrientation();
       Rectangle r = table.getVisibleRect();
       if (!or.isLeftToRight())
         r.translate((int) r.getWidth() - 1, 0);
       return table.rowAtPoint(r.getLocation());
     }
     
     /**
      * Returns the row index of the last visible row.
      *
      */
-    int getLastVisibleRowIndex()
+    int getLastVisibleRowIndex(JTable table)
     {
       ComponentOrientation or = table.getComponentOrientation();
       Rectangle r = table.getVisibleRect();
       r.translate(0, (int) r.getHeight() - 1);
       if (or.isLeftToRight())
         r.translate((int) r.getWidth() - 1, 0);
       // The next if makes sure that we don't return -1 simply because
       // there is white space at the bottom of the table (ie, the display
       // area is larger than the table)
       if (table.rowAtPoint(r.getLocation()) == -1)
         {
-          if (getFirstVisibleRowIndex() == -1)
+          if (getFirstVisibleRowIndex(table) == -1)
             return -1;
           else
             return table.getModel().getRowCount() - 1;
         }
       return table.rowAtPoint(r.getLocation());
     }
 
     /**
      * A helper method for the key bindings.  Used because the actions
      * for TAB, SHIFT-TAB, ENTER, and SHIFT-ENTER are very similar.
      *
      * Selects the next (previous if SHIFT pressed) column for TAB, or row for
@@ -995,25 +1059,26 @@
      *
      * @param firstModel the ListSelectionModel for columns (TAB) or
      * rows (ENTER)
      * @param firstMin the first selected index in firstModel
      * @param firstMax the last selected index in firstModel
      * @param secondModel the ListSelectionModel for rows (TAB) or 
      * columns (ENTER)
      * @param secondMin the first selected index in secondModel
      * @param secondMax the last selected index in secondModel
      * @param reverse true if shift was held for the event
      * @param eventIsTab true if TAB was pressed, false if ENTER pressed
      */
-    void advanceMultipleSelection(ListSelectionModel firstModel, int firstMin,
+    void advanceMultipleSelection(JTable table, ListSelectionModel firstModel,
+                                  int firstMin,
                                   int firstMax, ListSelectionModel secondModel, 
                                   int secondMin, int secondMax, boolean reverse,
                                   boolean eventIsTab)
     {
       // If eventIsTab, all the "firsts" correspond to columns, otherwise, to 
       // rows "seconds" correspond to the opposite
       int firstLead = firstModel.getLeadSelectionIndex();
       int secondLead = secondModel.getLeadSelectionIndex();
       int numFirsts = eventIsTab ? 
         table.getModel().getColumnCount() : table.getModel().getRowCount();
       int numSeconds = eventIsTab ? 
         table.getModel().getRowCount() : table.getModel().getColumnCount();
@@ -1159,47 +1224,42 @@
     if (keyListener == null)
       keyListener = createKeyListener();
     table.addKeyListener(keyListener);
     if (mouseInputListener == null)
       mouseInputListener = createMouseInputListener();
     table.addMouseListener(mouseInputListener);    
     table.addMouseMotionListener(mouseInputListener);
     if (propertyChangeListener == null)
       propertyChangeListener = new PropertyChangeHandler();
     table.addPropertyChangeListener(propertyChangeListener);
   }
 
-  protected void uninstallDefaults() throws NotImplementedException
+  /**
+   * Uninstalls UI defaults that have been installed by
+   * [EMAIL PROTECTED] #installDefaults()}.
+   */
+  protected void uninstallDefaults()
   {
-    // TODO: this method used to do the following which is not
-    // quite right (at least it breaks apps that run fine with the
-    // JDK):
-    //
-    // table.setFont(null);
-    // table.setGridColor(null);
-    // table.setForeground(null);
-    // table.setBackground(null);
-    // table.setSelectionForeground(null);
-    // table.setSelectionBackground(null);
-    //
-    // This would leave the component in a corrupt state, which is
-    // not acceptable. A possible solution would be to have component
-    // level defaults installed, that get overridden by the UI defaults
-    // and get restored in this method. I am not quite sure about this
-    // though. / Roman Kennke
+    // Nothing to do here for now.
   }
 
-  protected void uninstallKeyboardActions() throws NotImplementedException
+  /**
+   * Uninstalls the keyboard actions that have been installed by
+   * [EMAIL PROTECTED] #installKeyboardActions()}.
+   */
+  protected void uninstallKeyboardActions()
   {
-    // TODO: Implement this properly.
+    SwingUtilities.replaceUIInputMap(table, JComponent.
+                                     WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
+    SwingUtilities.replaceUIActionMap(table, null);
   }
 
   protected void uninstallListeners() 
   {
     table.removeFocusListener(focusListener);  
     table.removeKeyListener(keyListener);
     table.removeMouseListener(mouseInputListener);    
     table.removeMouseMotionListener(mouseInputListener);
     table.removePropertyChangeListener(propertyChangeListener);
     propertyChangeListener = null;
   }
 

Reply via email to