/* BasicTableUI.java --
   Copyright (C) 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
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 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.ActionMap;
import javax.swing.CellRendererPane;
import javax.swing.DefaultListSelectionModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.LookAndFeel;
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.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();
  }

  protected FocusListener focusListener;  
  protected KeyListener keyListener;   
  protected MouseInputListener	mouseInputListener;   
  protected CellRendererPane rendererPane;   
  protected JTable table;

  /** The normal cell border. */
  Border cellBorder;

  /** The action bound to KeyStrokes. */
  TableAction action;

  /**
   * Listens for changes to the tables properties.
   */
  private PropertyChangeListener propertyChangeListener;

  /**
   * Handles key events for the JTable. Key events should be handled through
   * the InputMap/ActionMap mechanism since JDK1.3. This class is only there
   * for backwards compatibility.
   * 
   * @author Roman Kennke (kennke@aicas.com)
   */
  public class KeyHandler implements KeyListener
  {

    /**
     * Receives notification that a key has been pressed and released.
     *
     * @param event the key event
     */
    public void keyTyped(KeyEvent event)
    {
      // Key events should be handled through the InputMap/ActionMap mechanism
      // since JDK1.3. This class is only there for backwards compatibility.
    }

    /**
     * Receives notification that a key has been pressed.
     *
     * @param event the key event
     */
    public void keyPressed(KeyEvent event)
    {
      // Key events should be handled through the InputMap/ActionMap mechanism
      // since JDK1.3. This class is only there for backwards compatibility.
    }

    /**
     * Receives notification that a key has been released.
     *
     * @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) 
    {
      // TODO: Implement this properly.
    }

    public void focusLost(FocusEvent e) 
    {
      // TODO: Implement this properly.
    }
  }

  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);
      ListSelectionModel rowModel = table.getSelectionModel();
      if (lo_row != -1 && hi_row != -1)
        {
          if (controlPressed && rowModel.getSelectionMode() 
              != ListSelectionModel.SINGLE_SELECTION)
            rowModel.addSelectionInterval(lo_row, hi_row);
          else
            rowModel.setSelectionInterval(lo_row, hi_row);
        }
      
      // Update the columns
      int lo_col = table.columnAtPoint(begin);
      int hi_col = table.columnAtPoint(curr);
      ListSelectionModel colModel = table.getColumnModel().
        getSelectionModel();
      if (lo_col != -1 && hi_col != -1)
        {
          if (controlPressed && colModel.getSelectionMode() != 
              ListSelectionModel.SINGLE_SELECTION)
            colModel.addSelectionInterval(lo_col, hi_col);
          else
            colModel.setSelectionInterval(lo_col, hi_col);
        }
    }

    public void mouseClicked(MouseEvent e) 
    {
      // TODO: What should be done here, if anything?
    }

    public void mouseDragged(MouseEvent e) 
    {
      if (table.isEnabled())
        {
          curr = new Point(e.getX(), e.getY());
          updateSelection(e.isControlDown());
        }
    }

    public void mouseEntered(MouseEvent e) 
    {
      // TODO: What should be done here, if anything?
    }

    public void mouseExited(MouseEvent e) 
    {
      // TODO: What should be done here, if anything?
    }

    public void mouseMoved(MouseEvent e) 
    {
      // TODO: What should be done here, if anything?
    }

    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());
          curr = new Point(e.getX(), e.getY());
          //if control is pressed and the cell is already selected, deselect it
          if (e.isControlDown() && table.
              isCellSelected(table.rowAtPoint(begin),table.columnAtPoint(begin)))
            {                                       
              table.getSelectionModel().
              removeSelectionInterval(table.rowAtPoint(begin), 
                                      table.rowAtPoint(begin));
              table.getColumnModel().getSelectionModel().
              removeSelectionInterval(table.columnAtPoint(begin), 
                                      table.columnAtPoint(begin));
            }
          else
            updateSelection(e.isControlDown());

          // If we were editing, but the moved to another cell, stop editing
          if (rowLead != rowModel.getLeadSelectionIndex() ||
              colLead != colModel.getLeadSelectionIndex())
            if (table.isEditing())
              table.editingStopped(new ChangeEvent(e));
        }
    }

    public void mouseReleased(MouseEvent e) 
    {
      if (table.isEnabled())
        {
          begin = null;
          curr = null;
        }
    }
  }

  /**
   * Listens for changes to the model property of the JTable and adjusts some
   * settings.
   *
   * @author Roman Kennke (kennke@aicas.com)
   */
  private class PropertyChangeHandler implements PropertyChangeListener
  {
    /**
     * Receives notification if one of the JTable's properties changes.
     *
     * @param ev the property change event
     */
    public void propertyChange(PropertyChangeEvent ev)
    {
      String propName = ev.getPropertyName();
      if (propName.equals("model"))
        {
          ListSelectionModel rowSel = table.getSelectionModel();
          rowSel.clearSelection();
          ListSelectionModel colSel = table.getColumnModel().getSelectionModel();
          colSel.clearSelection();
          TableModel model = table.getModel();

          // Adjust lead and anchor selection indices of the row and column
          // selection models.
          if (model.getRowCount() > 0)
            {
              rowSel.setAnchorSelectionIndex(0);
              rowSel.setLeadSelectionIndex(0);
            }
          else
            {
              rowSel.setAnchorSelectionIndex(-1);
              rowSel.setLeadSelectionIndex(-1);
            }
          if (model.getColumnCount() > 0)
            {
              colSel.setAnchorSelectionIndex(0);
              colSel.setLeadSelectionIndex(0);
            }
          else
            {
              colSel.setAnchorSelectionIndex(-1);
              colSel.setLeadSelectionIndex(-1);
            }
        }
    }
  }

  protected FocusListener createFocusListener() 
  {
    return new FocusHandler();
  }

  protected MouseInputListener createMouseInputListener() 
  {
    return new MouseInputHandler();
  }


  /**
   * Creates and returns a key listener for the JTable.
   *
   * @return a key listener for the JTable
   */
  protected KeyListener createKeyListener()
  {
    return new KeyHandler();
  }

  /**
   * Return the maximum size of the table. The maximum height is the row 
    * height times the number of rows. The maximum width is the sum of 
    * the maximum widths of each column.
    * 
    *  @param comp the component whose maximum size is being queried,
    *  this is ignored.
    *  @return a Dimension object representing the maximum size of the table,
    *  or null if the table has no elements.
   */
  public Dimension getMaximumSize(JComponent comp) 
  {
    int maxTotalColumnWidth = 0;
    for (int i = 0; i < table.getColumnCount(); i++)
      maxTotalColumnWidth += table.getColumnModel().getColumn(i).getMaxWidth();
    if (maxTotalColumnWidth == 0 || table.getRowCount() == 0)
      return null;
    return new Dimension(maxTotalColumnWidth, table.getRowCount()*table.getRowHeight());
  }

  /**
   * Return the minimum size of the table. The minimum height is the row 
    * height times the number of rows. The minimum width is the sum of 
    * the minimum widths of each column.
    * 
    *  @param comp the component whose minimum size is being queried,
    *  this is ignored.
    *  @return a Dimension object representing the minimum size of the table,
    *  or null if the table has no elements.
   */
  public Dimension getMinimumSize(JComponent comp) 
  {
    int minTotalColumnWidth = 0;
    for (int i = 0; i < table.getColumnCount(); i++)
      minTotalColumnWidth += table.getColumnModel().getColumn(i).getMinWidth();
    if (minTotalColumnWidth == 0 || table.getRowCount() == 0)
      return null;
    return new Dimension(minTotalColumnWidth, table.getRowCount()*table.getRowHeight());
  }

  public Dimension getPreferredSize(JComponent comp) 
  {
    int width = table.getColumnModel().getTotalColumnWidth();
    int height = table.getRowCount() * table.getRowHeight();
    return new Dimension(width, height);
  }

  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();
    // 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);

        parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(),
                                                  stroke.getModifiers()),
                           actionString);

        parentActionMap.put (actionString, 
                             new ActionListenerProxy (action, actionString));

      }
    // 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.
   */
  private static class ActionListenerProxy
    extends AbstractAction
  {
    ActionListener target;
    String bindingCommandName;

    public ActionListenerProxy(ActionListener li, 
                               String cmd)
    {
      target = li;
      bindingCommandName = cmd;
    }

    public void actionPerformed(ActionEvent e)
    {
      ActionEvent derivedEvent = new ActionEvent(e.getSource(),
                                                 e.getID(),
                                                 bindingCommandName,
                                                 e.getModifiers());
      target.actionPerformed(derivedEvent);
    }
  }

  /**
   * 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
  {
    /**
     * What to do when this action is called.
     *
     * @param e the ActionEvent that caused this action.
     */
    public void actionPerformed (ActionEvent e)
    {
      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();
      
      if (command.equals("selectPreviousRowExtendSelection"))
        {
          rowModel.setLeadSelectionIndex(Math.max(rowLead - 1, 0));
          colModel.setLeadSelectionIndex(colLead);
        }
      else if (command.equals("selectLastColumn"))
        {
          rowModel.setSelectionInterval(rowLead, rowLead);
          colModel.setSelectionInterval(colMax, colMax);
        }
      else if (command.equals("startEditing"))
        {
          if (table.isCellEditable(rowLead, colLead))
            table.editCellAt(rowLead,colLead);
        }
      else if (command.equals("selectFirstRowExtendSelection"))
        {              
          rowModel.setLeadSelectionIndex(0);
          colModel.setLeadSelectionIndex(colLead);
        }
      else if (command.equals("selectFirstColumn"))
        {
          rowModel.setSelectionInterval(rowLead, rowLead);
          colModel.setSelectionInterval(0, 0);
        }
      else if (command.equals("selectFirstColumnExtendSelection"))
        {
          colModel.setLeadSelectionIndex(0);
          rowModel.setLeadSelectionIndex(rowLead);
        }      
      else if (command.equals("selectLastRow"))
        {
          rowModel.setSelectionInterval(rowMax,rowMax);
          colModel.setSelectionInterval(colLead, colLead);
        }
      else if (command.equals("selectNextRowExtendSelection"))
        {
          rowModel.setLeadSelectionIndex(Math.min(rowLead + 1, rowMax));
          colModel.setLeadSelectionIndex(colLead);
        }
      else if (command.equals("selectFirstRow"))
        {
          rowModel.setSelectionInterval(0,0);
          colModel.setSelectionInterval(colLead, colLead);
        }
      else if (command.equals("selectNextColumnExtendSelection"))
        {
          colModel.setLeadSelectionIndex(Math.min(colLead + 1, colMax));
          rowModel.setLeadSelectionIndex(rowLead);
        }
      else if (command.equals("selectLastColumnExtendSelection"))
        {
          colModel.setLeadSelectionIndex(colMax);
          rowModel.setLeadSelectionIndex(rowLead);
        }
      else if (command.equals("selectPreviousColumnExtendSelection"))
        {
          colModel.setLeadSelectionIndex(Math.max(colLead - 1, 0));
          rowModel.setLeadSelectionIndex(rowLead);
        }
      else if (command.equals("selectNextRow"))
        {
          rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax),
                                        Math.min(rowLead + 1, rowMax));
          colModel.setSelectionInterval(colLead,colLead);
        }
      else if (command.equals("scrollUpExtendSelection"))
        {
          int target;
          if (rowLead == getFirstVisibleRowIndex())
            target = Math.max
              (0, rowLead - (getLastVisibleRowIndex() - 
                             getFirstVisibleRowIndex() + 1));
          else
            target = getFirstVisibleRowIndex();
          
          rowModel.setLeadSelectionIndex(target);
          colModel.setLeadSelectionIndex(colLead);
        }
      else if (command.equals("selectPreviousRow"))
        {
          rowModel.setSelectionInterval(Math.max(rowLead - 1, 0),
                                        Math.max(rowLead - 1, 0));
          colModel.setSelectionInterval(colLead,colLead);
        }
      else if (command.equals("scrollRightChangeSelection"))
        {
          int target;
          if (colLead == getLastVisibleColumnIndex())
            target = Math.min
              (colMax, colLead + (getLastVisibleColumnIndex() -
                                  getFirstVisibleColumnIndex() + 1));
          else
            target = getLastVisibleColumnIndex();
          
          colModel.setSelectionInterval(target, target);
          rowModel.setSelectionInterval(rowLead, rowLead);
        }
      else if (command.equals("selectPreviousColumn"))
        {
          rowModel.setSelectionInterval(rowLead,rowLead);
          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));
          else
            target = getFirstVisibleColumnIndex();
          
          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
          // we're currently editing.
          if (table.isEditing())
            table.editingCanceled(new ChangeEvent("cancel"));
        }
      else if (command.equals("selectNextRowCell")
               || command.equals("selectPreviousRowCell")
               || command.equals("selectNextColumnCell")
               || command.equals("selectPreviousColumnCell"))
        {
          // If nothing is selected, select the first cell in the table
          if (table.getSelectedRowCount() == 0 && 
              table.getSelectedColumnCount() == 0)
            {
              rowModel.setSelectionInterval(0, 0);
              colModel.setSelectionInterval(0, 0);
              return;
            }
          
          // If the lead selection index isn't selected (ie a remove operation
          // happened, then set the lead to the first selected cell in the
          // table
          if (!table.isCellSelected(rowLead, colLead))
            {
              rowModel.addSelectionInterval(rowModel.getMinSelectionIndex(), 
                                            rowModel.getMinSelectionIndex());
              colModel.addSelectionInterval(colModel.getMinSelectionIndex(), 
                                            colModel.getMinSelectionIndex());
              return;
            }
          
          // multRowsSelected and multColsSelected tell us if multiple rows or
          // columns are selected, respectively
          boolean multRowsSelected, multColsSelected;
          multRowsSelected = table.getSelectedRowCount() > 1 &&
            table.getRowSelectionAllowed();
          
          multColsSelected = table.getSelectedColumnCount() > 1 &&
            table.getColumnSelectionAllowed();
          
          // If there is just one selection, select the next cell, and wrap
          // when you get to the edges of the table.
          if (!multColsSelected && !multRowsSelected)
            {
              if (command.indexOf("Column") != -1) 
                advanceSingleSelection(colModel, colMax, rowModel, rowMax, 
                                       (command.equals
                                        ("selectPreviousColumnCell")));
              else
                advanceSingleSelection(rowModel, rowMax, colModel, colMax, 
                                       (command.equals 
                                        ("selectPreviousRowCell")));
              return;
            }
          
          
          // rowMinSelected and rowMaxSelected are the minimum and maximum
          // values respectively of selected cells in the row selection model
          // Similarly for colMinSelected and colMaxSelected.
          int rowMaxSelected = table.getRowSelectionAllowed() ? 
            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);
          
          else
            advanceMultipleSelection(rowModel, rowMinSelected, rowMaxSelected, 
                                     colModel, colMinSelected, colMaxSelected, 
                                     (command.equals 
                                      ("selectPreviousRowCell")), false);
        }
      else if (command.equals("selectNextColumn"))
        {
          rowModel.setSelectionInterval(rowLead,rowLead);
          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));
          else
            target = getFirstVisibleColumnIndex();
          
          colModel.setLeadSelectionIndex(target);
          rowModel.setLeadSelectionIndex(rowLead);
        }
      else if (command.equals("scrollDownChangeSelection"))
        {
          int target;
          if (rowLead == getLastVisibleRowIndex())
            target = Math.min
              (rowMax, rowLead + (getLastVisibleRowIndex() - 
                                  getFirstVisibleRowIndex() + 1));
          else
            target = getLastVisibleRowIndex();
          
          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));
          else
            target = getLastVisibleColumnIndex();
          
          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));
          else
            target = getLastVisibleRowIndex();
          
          rowModel.setLeadSelectionIndex(target);
          colModel.setLeadSelectionIndex(colLead);
        }      
      else if (command.equals("scrollUpChangeSelection"))
        {
          int target;
          if (rowLead == getFirstVisibleRowIndex())
            target = Math.max
              (0, rowLead - (getLastVisibleRowIndex() - 
                             getFirstVisibleRowIndex() + 1));
          else
            target = getFirstVisibleRowIndex();
          
          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));
                colModel.setSelectionInterval(colLead,colLead);
              }
            else
              rowModel.moveLeadSelectionIndex(Math.min(rowLead + 1, rowMax));
          }
      else if (command.equals("selectPreviousRowChangeLead"))
        {
          if (rowModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
            {
              // just selectPreviousRow
              rowModel.setSelectionInterval(Math.max(rowLead - 1, 0),
                                            Math.min(rowLead -1, 0));
              colModel.setSelectionInterval(colLead,colLead);
            }
          else
            rowModel.moveLeadSelectionIndex(Math.max(rowLead - 1, 0));
        }
      else if (command.equals("selectNextColumnChangeLead"))
        {
          if (colModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)            
            {
              // just selectNextColumn
              rowModel.setSelectionInterval(rowLead,rowLead);
              colModel.setSelectionInterval(Math.min(colLead + 1, colMax),
                                            Math.min(colLead + 1, colMax));
            }
          else
            colModel.moveLeadSelectionIndex(Math.min(colLead + 1, colMax));
        }
      else if (command.equals("selectPreviousColumnChangeLead"))
        {
          if (colModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)            
            {
              // just selectPreviousColumn
              rowModel.setSelectionInterval(rowLead,rowLead);
              colModel.setSelectionInterval(Math.max(colLead - 1, 0),
                                            Math.max(colLead - 1, 0));
              
            }
          else
            colModel.moveLeadSelectionIndex(Math.max(colLead - 1, 0));
        }
      else if (command.equals("addToSelection"))
          {
            if (!table.isEditing())
              {
                int oldRowAnchor = rowModel.getAnchorSelectionIndex();
                int oldColAnchor = colModel.getAnchorSelectionIndex();
                rowModel.addSelectionInterval(rowLead, rowLead);
                colModel.addSelectionInterval(colLead, colLead);
                rowModel.setAnchorSelectionIndex(oldRowAnchor);
                colModel.setAnchorSelectionIndex(oldColAnchor);
              }
          }
      else if (command.equals("extendTo"))
        {
          rowModel.setSelectionInterval(rowModel.getAnchorSelectionIndex(),
                                        rowLead);
          colModel.setSelectionInterval(colModel.getAnchorSelectionIndex(),
                                        colLead);
        }
      else if (command.equals("toggleAndAnchor"))
        {
          if (rowModel.isSelectedIndex(rowLead))
            rowModel.removeSelectionInterval(rowLead, rowLead);
          else
            rowModel.addSelectionInterval(rowLead, rowLead);
          
          if (colModel.isSelectedIndex(colLead))
            colModel.removeSelectionInterval(colLead, colLead);
          else
            colModel.addSelectionInterval(colLead, colLead);
          
          rowModel.setAnchorSelectionIndex(rowLead);
          colModel.setAnchorSelectionIndex(colLead);
        }
      else 
        {
          // If we're here that means we bound this TableAction class
          // to a keyboard input but we either want to ignore that input
          // or we just haven't implemented its action yet.
          
          // Uncomment the following line to print the names of unused bindings
          // when their keys are pressed
          
          // System.out.println ("not implemented: "+e.getActionCommand());
        }

      // Any commands whose keyStrokes should be used by the Editor should not
      // cause editing to be stopped: ie, the SPACE sends "addToSelection" but 
      // if the table is in editing mode, the space should not cause us to stop
      // editing because it should be used by the Editor.
      if (table.isEditing() && command != "startEditing"
          && command != "addToSelection")
        table.editingStopped(new ChangeEvent("update"));
            
      table.scrollRectToVisible
        (table.getCellRect(rowModel.getLeadSelectionIndex(), 
                           colModel.getLeadSelectionIndex(), false));
      table.repaint();
    }
    
    /**
     * Returns the column index of the first visible column.
     * @return the column index of the first visible column.
     */
    int getFirstVisibleColumnIndex()
    {
      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()
    {
      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()
    {
      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()
    {
      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)
            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
     * ENTER from within the currently selected cells.
     *
     * @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,
                                   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();

      // check if we have to wrap the "firsts" around, going to the other side
      if ((firstLead == firstMax && !reverse) || 
          (reverse && firstLead == firstMin))
        {
          firstModel.addSelectionInterval(reverse ? firstMax : firstMin, 
                                          reverse ? firstMax : firstMin);
          
          // check if we have to wrap the "seconds"
          if ((secondLead == secondMax && !reverse) || 
              (reverse && secondLead == secondMin))
            secondModel.addSelectionInterval(reverse ? secondMax : secondMin, 
                                             reverse ? secondMax : secondMin);

          // if we're not wrapping the seconds, we have to find out where we
          // are within the secondModel and advance to the next cell (or 
          // go back to the previous cell if reverse == true)
          else
            {
              int[] secondsSelected;
              if (eventIsTab && table.getRowSelectionAllowed() || 
                  !eventIsTab && table.getColumnSelectionAllowed())
                secondsSelected = eventIsTab ? 
                  table.getSelectedRows() : table.getSelectedColumns();
              else
                {
                  // if row selection is not allowed, then the entire column gets
                  // selected when you click on it, so consider ALL rows selected
                  secondsSelected = new int[numSeconds];
                  for (int i = 0; i < numSeconds; i++)
                  secondsSelected[i] = i;
                }

              // and now find the "next" index within the model
              int secondIndex = reverse ? secondsSelected.length - 1 : 0;
              if (!reverse)
                while (secondsSelected[secondIndex] <= secondLead)
                  secondIndex++;
              else
                while (secondsSelected[secondIndex] >= secondLead)
                  secondIndex--;
              
              // and select it - updating the lead selection index
              secondModel.addSelectionInterval(secondsSelected[secondIndex], 
                                               secondsSelected[secondIndex]);
            }
        }
      // We didn't have to wrap the firsts, so just find the "next" first
      // and select it, we don't have to change "seconds"
      else
        {
          int[] firstsSelected;
          if (eventIsTab && table.getColumnSelectionAllowed() || 
              !eventIsTab && table.getRowSelectionAllowed())
            firstsSelected = eventIsTab ? 
              table.getSelectedColumns() : table.getSelectedRows();
          else
            {
              // if selection not allowed, consider ALL firsts to be selected
              firstsSelected = new int[numFirsts];
              for (int i = 0; i < numFirsts; i++)
                firstsSelected[i] = i;
            }
          int firstIndex = reverse ? firstsSelected.length - 1 : 0;
          if (!reverse)
            while (firstsSelected[firstIndex] <= firstLead)
              firstIndex++;
          else 
            while (firstsSelected[firstIndex] >= firstLead)
              firstIndex--;
          firstModel.addSelectionInterval(firstsSelected[firstIndex], 
                                          firstsSelected[firstIndex]);
          secondModel.addSelectionInterval(secondLead, secondLead);
        }
    }
    
    /** 
     * 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 (TAB) or row (ENTER)
     * in the table, changing the current selection.  All cells in the table
     * are eligible, not just the ones that are currently selected.
     * @param firstModel the ListSelectionModel for columns (TAB) or rows
     * (ENTER)
     * @param firstMax the last index in firstModel
     * @param secondModel the ListSelectionModel for rows (TAB) or columns
     * (ENTER)
     * @param secondMax the last index in secondModel
     * @param reverse true if SHIFT was pressed for the event
     */

    void advanceSingleSelection (ListSelectionModel firstModel, int firstMax, 
                                 ListSelectionModel secondModel, int secondMax, 
                                 boolean reverse)
    {
      // for TABs, "first" corresponds to columns and "seconds" to rows.
      // the opposite is true for ENTERs
      int firstLead = firstModel.getLeadSelectionIndex();
      int secondLead = secondModel.getLeadSelectionIndex();
      
      // if we are going backwards subtract 2 because we later add 1
      // for a net change of -1
      if (reverse && (firstLead == 0))
        {
          // check if we have to wrap around
          if (secondLead == 0)
            secondLead += secondMax + 1;
          secondLead -= 2;
        }
      
      // do we have to wrap the "seconds"?
      if (reverse && (firstLead == 0) || !reverse && (firstLead == firstMax))
        secondModel.setSelectionInterval((secondLead + 1)%(secondMax + 1), 
                                         (secondLead + 1)%(secondMax + 1));
      // if not, just reselect the current lead
      else
        secondModel.setSelectionInterval(secondLead, secondLead);
      
      // if we are going backwards, subtract 2  because we add 1 later
      // for net change of -1
      if (reverse)
        {
          // check for wraparound
          if (firstLead == 0)
            firstLead += firstMax + 1;
          firstLead -= 2;
        }
      // select the next "first"
      firstModel.setSelectionInterval ((firstLead + 1)%(firstMax + 1), 
                                       (firstLead + 1)%(firstMax + 1));
    }
  }

  protected void installListeners() 
  {
    if (focusListener == null)
      focusListener = createFocusListener();
    table.addFocusListener(focusListener);
    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() 
  {
    // 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
  }

  protected void uninstallKeyboardActions() 
  {
    // TODO: Implement this properly.
  }

  protected void uninstallListeners() 
  {
    table.removeFocusListener(focusListener);  
    table.removeKeyListener(keyListener);
    table.removeMouseListener(mouseInputListener);    
    table.removeMouseMotionListener(mouseInputListener);
    table.removePropertyChangeListener(propertyChangeListener);
    propertyChangeListener = null;
  }

  public void installUI(JComponent comp) 
  {
    table = (JTable)comp;
    installDefaults();
    installKeyboardActions();
    installListeners();
  }

  public void uninstallUI(JComponent c) 
  {
    uninstallListeners();
    uninstallKeyboardActions();
    uninstallDefaults();    
  }

  /**
   * 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
   * table
   * @param rend A cell renderer to paint with
   * @param data The data to provide to the cell renderer
   * @param rowLead The lead selection for the rows of the table.
   * @param colLead The lead selection for the columns of the table.
   */
  void paintCell(Graphics g, int row, int col, Rectangle bounds,
                 TableCellRenderer rend, TableModel data,
                 int rowLead, int colLead)
  {
    boolean rowSelAllowed = table.getRowSelectionAllowed();
    boolean colSelAllowed = table.getColumnSelectionAllowed();
    boolean isSel = false;
    if (rowSelAllowed && colSelAllowed || !rowSelAllowed && !colSelAllowed)
      isSel = table.isCellSelected(row, col);
    else
      isSel = table.isRowSelected(row) && table.getRowSelectionAllowed()
           || table.isColumnSelected(col) && table.getColumnSelectionAllowed();

    // Determine the focused cell. The focused cell is the cell at the
    // leadSelectionIndices of the row and column selection model.
    ListSelectionModel rowSel = table.getSelectionModel();
    ListSelectionModel colSel = table.getColumnModel().getSelectionModel();
    boolean hasFocus = table.hasFocus() && table.isEnabled()
                       && rowSel.getLeadSelectionIndex() == row
                       && colSel.getLeadSelectionIndex() == col;

    Component comp = rend.getTableCellRendererComponent(table,
                                                       data.getValueAt(row, col),
                                                       isSel, hasFocus, row, col);
    
    rendererPane.paintComponent(g, comp, table, bounds);
    
    // FIXME: this is manual painting of the Caret, why doesn't the 
    // JTextField take care of this itself?
    if (comp instanceof JTextField)
      {
        Rectangle oldClip = g.getClipBounds();
        g.translate(bounds.x, bounds.y);
        g.clipRect(0, 0, bounds.width, bounds.height);
        ((JTextField)comp).getCaret().paint(g);
        g.translate(-bounds.x, -bounds.y);
        g.setClip(oldClip);
      }
  }
  
  public void paint(Graphics gfx, JComponent ignored) 
  {
    int ncols = table.getColumnCount();
    int nrows = table.getRowCount();
    if (nrows == 0 || ncols == 0)
      return;

    Rectangle clip = gfx.getClipBounds();
    TableColumnModel cols = table.getColumnModel();

    int height = table.getRowHeight();
    int x0 = 0, y0 = 0;
    int x = x0;
    int y = y0;

    Dimension gap = table.getIntercellSpacing();
    int ymax = clip.y + clip.height;
    int xmax = clip.x + clip.width;

    // paint the cell contents
    for (int c = 0; c < ncols && x < xmax; ++c)
      {
        y = y0;
        TableColumn col = cols.getColumn(c);
        int width = col.getWidth();
        int halfGapWidth = gap.width / 2;
        int halfGapHeight = gap.height / 2;
        for (int r = 0; r < nrows && y < ymax; ++r)
          {
            Rectangle bounds = new Rectangle(x + halfGapWidth,
                                             y + halfGapHeight + 1,
                                             width - gap.width + 1,
                                             height - gap.height);
            if (bounds.intersects(clip))
              {                                                     
                paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c),
                          table.getModel(),
                          table.getSelectionModel().getLeadSelectionIndex(),
                          table.getColumnModel().getSelectionModel().getLeadSelectionIndex());
              }
            y += height;
          }
        x += width;
      }

    // tighten up the x and y max bounds
    ymax = y;
    xmax = x;

    Color grid = table.getGridColor();    

    // paint vertical grid lines
    if (grid != null && table.getShowVerticalLines())
      {    
        x = x0;
        Color save = gfx.getColor();
        gfx.setColor(grid);
        boolean paintedLine = false;
        for (int c = 0; c < ncols && x < xmax; ++c)
          {
            x += cols.getColumn(c).getWidth();
            gfx.drawLine(x, y0, x, ymax);
            paintedLine = true;
          }
        gfx.setColor(save);
      }

    // paint horizontal grid lines    
    if (grid != null && table.getShowHorizontalLines())
      {    
        y = y0;
        Color save = gfx.getColor();
        gfx.setColor(grid);
        boolean paintedLine = false;
        for (int r = 0; r < nrows && y < ymax; ++r)
          {
            y += height;
            gfx.drawLine(x0, y, xmax, y);
            paintedLine = true;
          }
        gfx.setColor(save);
      }
  }
}
