1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing.table;
  27 
  28 import sun.swing.table.DefaultTableCellHeaderRenderer;
  29 
  30 import java.util.*;
  31 import java.awt.*;
  32 import java.awt.event.*;
  33 
  34 import javax.swing.*;
  35 import javax.swing.event.*;
  36 import javax.swing.plaf.*;
  37 import javax.accessibility.*;
  38 
  39 import java.beans.PropertyChangeListener;
  40 import java.beans.Transient;
  41 
  42 import java.io.ObjectOutputStream;
  43 import java.io.ObjectInputStream;
  44 import java.io.IOException;
  45 
  46 import sun.awt.AWTAccessor;
  47 import sun.awt.AWTAccessor.MouseEventAccessor;
  48 
  49 /**
  50  * This is the object which manages the header of the <code>JTable</code>.
  51  * <p>
  52  * <strong>Warning:</strong>
  53  * Serialized objects of this class will not be compatible with
  54  * future Swing releases. The current serialization support is
  55  * appropriate for short term storage or RMI between applications running
  56  * the same version of Swing.  As of 1.4, support for long term storage
  57  * of all JavaBeans&trade;
  58  * has been added to the <code>java.beans</code> package.
  59  * Please see {@link java.beans.XMLEncoder}.
  60  *
  61  * @author Alan Chung
  62  * @author Philip Milne
  63  * @see javax.swing.JTable
  64  */
  65 public class JTableHeader extends JComponent implements TableColumnModelListener, Accessible
  66 {
  67     /**
  68      * @see #getUIClassID
  69      * @see #readObject
  70      */
  71     private static final String uiClassID = "TableHeaderUI";
  72 
  73 //
  74 // Instance Variables
  75 //
  76     /**
  77      * The table for which this object is the header;
  78      * the default is <code>null</code>.
  79      */
  80     protected JTable table;
  81 
  82     /**
  83      * The <code>TableColumnModel</code> of the table header.
  84      */
  85     protected TableColumnModel  columnModel;
  86 
  87     /**
  88      * If true, reordering of columns are allowed by the user;
  89      * the default is true.
  90      */
  91     protected boolean   reorderingAllowed;
  92 
  93     /**
  94      * If true, resizing of columns are allowed by the user;
  95      * the default is true.
  96      */
  97     protected boolean   resizingAllowed;
  98 
  99     /**
 100      * Obsolete as of Java 2 platform v1.3.  Real time repaints, in response
 101      * to column dragging or resizing, are now unconditional.
 102      */
 103     /*
 104      * If this flag is true, then the header will repaint the table as
 105      * a column is dragged or resized; the default is true.
 106      */
 107     protected boolean   updateTableInRealTime;
 108 
 109     /** The index of the column being resized. <code>null</code> if not resizing. */
 110     transient protected TableColumn     resizingColumn;
 111 
 112     /** The index of the column being dragged. <code>null</code> if not dragging. */
 113     transient protected TableColumn     draggedColumn;
 114 
 115     /** The distance from its original position the column has been dragged. */
 116     transient protected int     draggedDistance;
 117 
 118     /**
 119       *  The default renderer to be used when a <code>TableColumn</code>
 120       *  does not define a <code>headerRenderer</code>.
 121       */
 122     private TableCellRenderer defaultRenderer;
 123 
 124 //
 125 // Constructors
 126 //
 127 
 128     /**
 129      *  Constructs a <code>JTableHeader</code> with a default
 130      *  <code>TableColumnModel</code>.
 131      *
 132      * @see #createDefaultColumnModel
 133      */
 134     public JTableHeader() {
 135         this(null);
 136     }
 137 
 138     /**
 139      *  Constructs a <code>JTableHeader</code> which is initialized with
 140      *  <code>cm</code> as the column model.  If <code>cm</code> is
 141      *  <code>null</code> this method will initialize the table header
 142      *  with a default <code>TableColumnModel</code>.
 143      *
 144      * @param cm        the column model for the table
 145      * @see #createDefaultColumnModel
 146      */
 147     public JTableHeader(TableColumnModel cm) {
 148         super();
 149 
 150         //setFocusable(false); // for strict win/mac compatibility mode,
 151                                // this method should be invoked
 152 
 153         if (cm == null)
 154             cm = createDefaultColumnModel();
 155         setColumnModel(cm);
 156 
 157         // Initialize local ivars
 158         initializeLocalVars();
 159 
 160         // Get UI going
 161         updateUI();
 162     }
 163 
 164 //
 165 // Local behavior attributes
 166 //
 167 
 168     /**
 169      *  Sets the table associated with this header.
 170      *  @param  table   the new table
 171      *  @beaninfo
 172      *   bound: true
 173      *   description: The table associated with this header.
 174      */
 175     public void setTable(JTable table) {
 176         JTable old = this.table;
 177         this.table = table;
 178         firePropertyChange("table", old, table);
 179     }
 180 
 181     /**
 182       *  Returns the table associated with this header.
 183       *  @return  the <code>table</code> property
 184       */
 185     public JTable getTable() {
 186         return table;
 187     }
 188 
 189     /**
 190      *  Sets whether the user can drag column headers to reorder columns.
 191      *
 192      * @param   reorderingAllowed       true if the table view should allow
 193      *                                  reordering; otherwise false
 194      * @see     #getReorderingAllowed
 195      * @beaninfo
 196      *  bound: true
 197      *  description: Whether the user can drag column headers to reorder columns.
 198      */
 199     public void setReorderingAllowed(boolean reorderingAllowed) {
 200         boolean old = this.reorderingAllowed;
 201         this.reorderingAllowed = reorderingAllowed;
 202         firePropertyChange("reorderingAllowed", old, reorderingAllowed);
 203     }
 204 
 205     /**
 206      * Returns true if the user is allowed to rearrange columns by
 207      * dragging their headers, false otherwise. The default is true. You can
 208      * rearrange columns programmatically regardless of this setting.
 209      *
 210      * @return  the <code>reorderingAllowed</code> property
 211      * @see     #setReorderingAllowed
 212      */
 213     public boolean getReorderingAllowed() {
 214         return reorderingAllowed;
 215     }
 216 
 217     /**
 218      *  Sets whether the user can resize columns by dragging between headers.
 219      *
 220      * @param   resizingAllowed         true if table view should allow
 221      *                                  resizing
 222      * @see     #getResizingAllowed
 223      * @beaninfo
 224      *  bound: true
 225      *  description: Whether the user can resize columns by dragging between headers.
 226      */
 227     public void setResizingAllowed(boolean resizingAllowed) {
 228         boolean old = this.resizingAllowed;
 229         this.resizingAllowed = resizingAllowed;
 230         firePropertyChange("resizingAllowed", old, resizingAllowed);
 231     }
 232 
 233     /**
 234      * Returns true if the user is allowed to resize columns by dragging
 235      * between their headers, false otherwise. The default is true. You can
 236      * resize columns programmatically regardless of this setting.
 237      *
 238      * @return  the <code>resizingAllowed</code> property
 239      * @see     #setResizingAllowed
 240      */
 241     public boolean getResizingAllowed() {
 242         return resizingAllowed;
 243     }
 244 
 245     /**
 246      * Returns the the dragged column, if and only if, a drag is in
 247      * process, otherwise returns <code>null</code>.
 248      *
 249      * @return  the dragged column, if a drag is in
 250      *          process, otherwise returns <code>null</code>
 251      * @see     #getDraggedDistance
 252      */
 253     public TableColumn getDraggedColumn() {
 254         return draggedColumn;
 255     }
 256 
 257     /**
 258      * Returns the column's horizontal distance from its original
 259      * position, if and only if, a drag is in process. Otherwise, the
 260      * the return value is meaningless.
 261      *
 262      * @return  the column's horizontal distance from its original
 263      *          position, if a drag is in process, otherwise the return
 264      *          value is meaningless
 265      * @see     #getDraggedColumn
 266      */
 267     public int getDraggedDistance() {
 268         return draggedDistance;
 269     }
 270 
 271     /**
 272      * Returns the resizing column.  If no column is being
 273      * resized this method returns <code>null</code>.
 274      *
 275      * @return  the resizing column, if a resize is in process, otherwise
 276      *          returns <code>null</code>
 277      */
 278     public TableColumn getResizingColumn() {
 279         return resizingColumn;
 280     }
 281 
 282     /**
 283      * Obsolete as of Java 2 platform v1.3.  Real time repaints, in response to
 284      * column dragging or resizing, are now unconditional.
 285      */
 286     /*
 287      *  Sets whether the body of the table updates in real time when
 288      *  a column is resized or dragged.
 289      *
 290      * @param   flag                    true if tableView should update
 291      *                                  the body of the table in real time
 292      * @see #getUpdateTableInRealTime
 293      */
 294     public void setUpdateTableInRealTime(boolean flag) {
 295         updateTableInRealTime = flag;
 296     }
 297 
 298     /**
 299      * Obsolete as of Java 2 platform v1.3.  Real time repaints, in response to
 300      * column dragging or resizing, are now unconditional.
 301      */
 302     /*
 303      * Returns true if the body of the table view updates in real
 304      * time when a column is resized or dragged.  User can set this flag to
 305      * false to speed up the table's response to user resize or drag actions.
 306      * The default is true.
 307      *
 308      * @return  true if the table updates in real time
 309      * @see #setUpdateTableInRealTime
 310      */
 311     public boolean getUpdateTableInRealTime() {
 312         return updateTableInRealTime;
 313     }
 314 
 315     /**
 316      * Sets the default renderer to be used when no <code>headerRenderer</code>
 317      * is defined by a <code>TableColumn</code>.
 318      * @param  defaultRenderer  the default renderer
 319      * @since 1.3
 320      */
 321     public void setDefaultRenderer(TableCellRenderer defaultRenderer) {
 322         this.defaultRenderer = defaultRenderer;
 323     }
 324 
 325     /**
 326      * Returns the default renderer used when no <code>headerRenderer</code>
 327      * is defined by a <code>TableColumn</code>.
 328      * @return the default renderer
 329      * @since 1.3
 330      */
 331     @Transient
 332     public TableCellRenderer getDefaultRenderer() {
 333         return defaultRenderer;
 334     }
 335 
 336     /**
 337      * Returns the index of the column that <code>point</code> lies in, or -1 if it
 338      * lies out of bounds.
 339      *
 340      * @return  the index of the column that <code>point</code> lies in, or -1 if it
 341      *          lies out of bounds
 342      */
 343     public int columnAtPoint(Point point) {
 344         int x = point.x;
 345         if (!getComponentOrientation().isLeftToRight()) {
 346             x = getWidthInRightToLeft() - x - 1;
 347         }
 348         return getColumnModel().getColumnIndexAtX(x);
 349     }
 350 
 351     /**
 352      * Returns the rectangle containing the header tile at <code>column</code>.
 353      * When the <code>column</code> parameter is out of bounds this method uses the
 354      * same conventions as the <code>JTable</code> method <code>getCellRect</code>.
 355      *
 356      * @return  the rectangle containing the header tile at <code>column</code>
 357      * @see JTable#getCellRect
 358      */
 359     public Rectangle getHeaderRect(int column) {
 360         Rectangle r = new Rectangle();
 361         TableColumnModel cm = getColumnModel();
 362 
 363         r.height = getHeight();
 364 
 365         if (column < 0) {
 366             // x = width = 0;
 367             if( !getComponentOrientation().isLeftToRight() ) {
 368                 r.x = getWidthInRightToLeft();
 369             }
 370         }
 371         else if (column >= cm.getColumnCount()) {
 372             if( getComponentOrientation().isLeftToRight() ) {
 373                 r.x = getWidth();
 374             }
 375         }
 376         else {
 377             for(int i = 0; i < column; i++) {
 378                 r.x += cm.getColumn(i).getWidth();
 379             }
 380             if( !getComponentOrientation().isLeftToRight() ) {
 381                 r.x = getWidthInRightToLeft() - r.x - cm.getColumn(column).getWidth();
 382             }
 383 
 384             r.width = cm.getColumn(column).getWidth();
 385         }
 386         return r;
 387     }
 388 
 389 
 390     /**
 391      * Allows the renderer's tips to be used if there is text set.
 392      * @param  event  the location of the event identifies the proper
 393      *                          renderer and, therefore, the proper tip
 394      * @return the tool tip for this component
 395      */
 396     public String getToolTipText(MouseEvent event) {
 397         String tip = null;
 398         Point p = event.getPoint();
 399         int column;
 400 
 401         // Locate the renderer under the event location
 402         if ((column = columnAtPoint(p)) != -1) {
 403             TableColumn aColumn = columnModel.getColumn(column);
 404             TableCellRenderer renderer = aColumn.getHeaderRenderer();
 405             if (renderer == null) {
 406                 renderer = defaultRenderer;
 407             }
 408             Component component = renderer.getTableCellRendererComponent(
 409                               getTable(), aColumn.getHeaderValue(), false, false,
 410                               -1, column);
 411 
 412             // Now have to see if the component is a JComponent before
 413             // getting the tip
 414             if (component instanceof JComponent) {
 415                 // Convert the event to the renderer's coordinate system
 416                 MouseEvent newEvent;
 417                 Rectangle cellRect = getHeaderRect(column);
 418 
 419                 p.translate(-cellRect.x, -cellRect.y);
 420                 newEvent = new MouseEvent(component, event.getID(),
 421                                           event.getWhen(), event.getModifiers(),
 422                                           p.x, p.y, event.getXOnScreen(), event.getYOnScreen(),
 423                                           event.getClickCount(),
 424                                           event.isPopupTrigger(), MouseEvent.NOBUTTON);
 425                 MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
 426                 meAccessor.setCausedByTouchEvent(newEvent,
 427                     meAccessor.isCausedByTouchEvent(event));
 428 
 429                 tip = ((JComponent)component).getToolTipText(newEvent);
 430             }
 431         }
 432 
 433         // No tip from the renderer get our own tip
 434         if (tip == null)
 435             tip = getToolTipText();
 436 
 437         return tip;
 438     }
 439 
 440 //
 441 // Managing TableHeaderUI
 442 //
 443 
 444     /**
 445      * Returns the look and feel (L&amp;F) object that renders this component.
 446      *
 447      * @return the <code>TableHeaderUI</code> object that renders this component
 448      */
 449     public TableHeaderUI getUI() {
 450         return (TableHeaderUI)ui;
 451     }
 452 
 453     /**
 454      * Sets the look and feel (L&amp;F) object that renders this component.
 455      *
 456      * @param ui  the <code>TableHeaderUI</code> L&amp;F object
 457      * @see UIDefaults#getUI
 458      */
 459     public void setUI(TableHeaderUI ui){
 460         if (this.ui != ui) {
 461             super.setUI(ui);
 462             repaint();
 463         }
 464     }
 465 
 466     /**
 467      * Notification from the <code>UIManager</code> that the look and feel
 468      * (L&amp;F) has changed.
 469      * Replaces the current UI object with the latest version from the
 470      * <code>UIManager</code>.
 471      *
 472      * @see JComponent#updateUI
 473      */
 474     public void updateUI(){
 475         setUI((TableHeaderUI)UIManager.getUI(this));
 476 
 477         TableCellRenderer renderer = getDefaultRenderer();
 478         if (renderer instanceof Component) {
 479             SwingUtilities.updateComponentTreeUI((Component)renderer);
 480         }
 481     }
 482 
 483 
 484     /**
 485      * Returns the suffix used to construct the name of the look and feel
 486      * (L&amp;F) class used to render this component.
 487      * @return the string "TableHeaderUI"
 488      *
 489      * @return "TableHeaderUI"
 490      * @see JComponent#getUIClassID
 491      * @see UIDefaults#getUI
 492      */
 493     public String getUIClassID() {
 494         return uiClassID;
 495     }
 496 
 497 
 498 //
 499 // Managing models
 500 //
 501 
 502 
 503     /**
 504      *  Sets the column model for this table to <code>newModel</code> and registers
 505      *  for listener notifications from the new column model.
 506      *
 507      * @param   columnModel     the new data source for this table
 508      * @exception IllegalArgumentException
 509      *                          if <code>newModel</code> is <code>null</code>
 510      * @see     #getColumnModel
 511      * @beaninfo
 512      *  bound: true
 513      *  description: The object governing the way columns appear in the view.
 514      */
 515     public void setColumnModel(TableColumnModel columnModel) {
 516         if (columnModel == null) {
 517             throw new IllegalArgumentException("Cannot set a null ColumnModel");
 518         }
 519         TableColumnModel old = this.columnModel;
 520         if (columnModel != old) {
 521             if (old != null) {
 522                 old.removeColumnModelListener(this);
 523             }
 524             this.columnModel = columnModel;
 525             columnModel.addColumnModelListener(this);
 526 
 527             firePropertyChange("columnModel", old, columnModel);
 528             resizeAndRepaint();
 529         }
 530     }
 531 
 532     /**
 533      * Returns the <code>TableColumnModel</code> that contains all column information
 534      * of this table header.
 535      *
 536      * @return  the <code>columnModel</code> property
 537      * @see     #setColumnModel
 538      */
 539     public TableColumnModel getColumnModel() {
 540         return columnModel;
 541     }
 542 
 543 //
 544 // Implementing TableColumnModelListener interface
 545 //
 546 
 547     /**
 548      * Invoked when a column is added to the table column model.
 549      * <p>
 550      * Application code will not use these methods explicitly, they
 551      * are used internally by <code>JTable</code>.
 552      *
 553      * @param e  the event received
 554      * @see TableColumnModelListener
 555      */
 556     public void columnAdded(TableColumnModelEvent e) { resizeAndRepaint(); }
 557 
 558 
 559     /**
 560      * Invoked when a column is removed from the table column model.
 561      * <p>
 562      * Application code will not use these methods explicitly, they
 563      * are used internally by <code>JTable</code>.
 564      *
 565      * @param e  the event received
 566      * @see TableColumnModelListener
 567      */
 568     public void columnRemoved(TableColumnModelEvent e) { resizeAndRepaint(); }
 569 
 570 
 571     /**
 572      * Invoked when a column is repositioned.
 573      * <p>
 574      * Application code will not use these methods explicitly, they
 575      * are used internally by <code>JTable</code>.
 576      *
 577      * @param e the event received
 578      * @see TableColumnModelListener
 579      */
 580     public void columnMoved(TableColumnModelEvent e) { repaint(); }
 581 
 582 
 583     /**
 584      * Invoked when a column is moved due to a margin change.
 585      * <p>
 586      * Application code will not use these methods explicitly, they
 587      * are used internally by <code>JTable</code>.
 588      *
 589      * @param e the event received
 590      * @see TableColumnModelListener
 591      */
 592     public void columnMarginChanged(ChangeEvent e) { resizeAndRepaint(); }
 593 
 594 
 595     // --Redrawing the header is slow in cell selection mode.
 596     // --Since header selection is ugly and it is always clear from the
 597     // --view which columns are selected, don't redraw the header.
 598     /**
 599      * Invoked when the selection model of the <code>TableColumnModel</code>
 600      * is changed.  This method currently has no effect (the header is not
 601      * redrawn).
 602      * <p>
 603      * Application code will not use these methods explicitly, they
 604      * are used internally by <code>JTable</code>.
 605      *
 606      * @param e the event received
 607      * @see TableColumnModelListener
 608      */
 609     public void columnSelectionChanged(ListSelectionEvent e) { } // repaint(); }
 610 
 611 //
 612 //  Package Methods
 613 //
 614 
 615     /**
 616      *  Returns the default column model object which is
 617      *  a <code>DefaultTableColumnModel</code>.  A subclass can override this
 618      *  method to return a different column model object
 619      *
 620      * @return the default column model object
 621      */
 622     protected TableColumnModel createDefaultColumnModel() {
 623         return new DefaultTableColumnModel();
 624     }
 625 
 626     /**
 627      *  Returns a default renderer to be used when no header renderer
 628      *  is defined by a <code>TableColumn</code>.
 629      *
 630      *  @return the default table column renderer
 631      * @since 1.3
 632      */
 633     protected TableCellRenderer createDefaultRenderer() {
 634         return new DefaultTableCellHeaderRenderer();
 635     }
 636 
 637 
 638     /**
 639      * Initializes the local variables and properties with default values.
 640      * Used by the constructor methods.
 641      */
 642     protected void initializeLocalVars() {
 643         setOpaque(true);
 644         table = null;
 645         reorderingAllowed = true;
 646         resizingAllowed = true;
 647         draggedColumn = null;
 648         draggedDistance = 0;
 649         resizingColumn = null;
 650         updateTableInRealTime = true;
 651 
 652         // I'm registered to do tool tips so we can draw tips for the
 653         // renderers
 654         ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
 655         toolTipManager.registerComponent(this);
 656         setDefaultRenderer(createDefaultRenderer());
 657     }
 658 
 659     /**
 660      * Sizes the header and marks it as needing display.  Equivalent
 661      * to <code>revalidate</code> followed by <code>repaint</code>.
 662      */
 663     public void resizeAndRepaint() {
 664         revalidate();
 665         repaint();
 666     }
 667 
 668     /**
 669       *  Sets the header's <code>draggedColumn</code> to <code>aColumn</code>.
 670       *  <p>
 671       *  Application code will not use this method explicitly, it is used
 672       *  internally by the column dragging mechanism.
 673       *
 674       *  @param  aColumn  the column being dragged, or <code>null</code> if
 675       *                 no column is being dragged
 676       */
 677     public void setDraggedColumn(TableColumn aColumn) {
 678         draggedColumn = aColumn;
 679     }
 680 
 681     /**
 682       *  Sets the header's <code>draggedDistance</code> to <code>distance</code>.
 683       *  @param distance  the distance dragged
 684       */
 685     public void setDraggedDistance(int distance) {
 686         draggedDistance = distance;
 687     }
 688 
 689     /**
 690       *  Sets the header's <code>resizingColumn</code> to <code>aColumn</code>.
 691       *  <p>
 692       *  Application code will not use this method explicitly, it
 693       *  is used internally by the column sizing mechanism.
 694       *
 695       *  @param  aColumn  the column being resized, or <code>null</code> if
 696       *                 no column is being resized
 697       */
 698     public void setResizingColumn(TableColumn aColumn) {
 699         resizingColumn = aColumn;
 700     }
 701 
 702     /**
 703      * See <code>readObject</code> and <code>writeObject</code> in
 704      * <code>JComponent</code> for more
 705      * information about serialization in Swing.
 706      */
 707     private void writeObject(ObjectOutputStream s) throws IOException {
 708         s.defaultWriteObject();
 709         if ((ui != null) && (getUIClassID().equals(uiClassID))) {
 710             ui.installUI(this);
 711         }
 712     }
 713 
 714     private int getWidthInRightToLeft() {
 715         if ((table != null) &&
 716             (table.getAutoResizeMode() != JTable.AUTO_RESIZE_OFF)) {
 717             return table.getWidth();
 718         }
 719         return super.getWidth();
 720     }
 721 
 722     /**
 723      * Returns a string representation of this <code>JTableHeader</code>. This method
 724      * is intended to be used only for debugging purposes, and the
 725      * content and format of the returned string may vary between
 726      * implementations. The returned string may be empty but may not
 727      * be <code>null</code>.
 728      * <P>
 729      * Overriding <code>paramString</code> to provide information about the
 730      * specific new aspects of the JFC components.
 731      *
 732      * @return  a string representation of this <code>JTableHeader</code>
 733      */
 734     protected String paramString() {
 735         String reorderingAllowedString = (reorderingAllowed ?
 736                                           "true" : "false");
 737         String resizingAllowedString = (resizingAllowed ?
 738                                         "true" : "false");
 739         String updateTableInRealTimeString = (updateTableInRealTime ?
 740                                               "true" : "false");
 741 
 742         return super.paramString() +
 743         ",draggedDistance=" + draggedDistance +
 744         ",reorderingAllowed=" + reorderingAllowedString +
 745         ",resizingAllowed=" + resizingAllowedString +
 746         ",updateTableInRealTime=" + updateTableInRealTimeString;
 747     }
 748 
 749 /////////////////
 750 // Accessibility support
 751 ////////////////
 752 
 753     /**
 754      * Gets the AccessibleContext associated with this JTableHeader.
 755      * For JTableHeaders, the AccessibleContext takes the form of an
 756      * AccessibleJTableHeader.
 757      * A new AccessibleJTableHeader instance is created if necessary.
 758      *
 759      * @return an AccessibleJTableHeader that serves as the
 760      *         AccessibleContext of this JTableHeader
 761      */
 762     public AccessibleContext getAccessibleContext() {
 763         if (accessibleContext == null) {
 764             accessibleContext = new AccessibleJTableHeader();
 765         }
 766         return accessibleContext;
 767     }
 768 
 769     //
 770     // *** should also implement AccessibleSelection?
 771     // *** and what's up with keyboard navigation/manipulation?
 772     //
 773     /**
 774      * This class implements accessibility support for the
 775      * <code>JTableHeader</code> class.  It provides an implementation of the
 776      * Java Accessibility API appropriate to table header user-interface
 777      * elements.
 778      * <p>
 779      * <strong>Warning:</strong>
 780      * Serialized objects of this class will not be compatible with
 781      * future Swing releases. The current serialization support is
 782      * appropriate for short term storage or RMI between applications running
 783      * the same version of Swing.  As of 1.4, support for long term storage
 784      * of all JavaBeans&trade;
 785      * has been added to the <code>java.beans</code> package.
 786      * Please see {@link java.beans.XMLEncoder}.
 787      */
 788     protected class AccessibleJTableHeader extends AccessibleJComponent {
 789 
 790         /**
 791          * Get the role of this object.
 792          *
 793          * @return an instance of AccessibleRole describing the role of the
 794          * object
 795          * @see AccessibleRole
 796          */
 797         public AccessibleRole getAccessibleRole() {
 798             return AccessibleRole.PANEL;
 799         }
 800 
 801         /**
 802          * Returns the Accessible child, if one exists, contained at the local
 803          * coordinate Point.
 804          *
 805          * @param p The point defining the top-left corner of the Accessible,
 806          * given in the coordinate space of the object's parent.
 807          * @return the Accessible, if it exists, at the specified location;
 808          * else null
 809          */
 810         public Accessible getAccessibleAt(Point p) {
 811             int column;
 812 
 813             // Locate the renderer under the Point
 814             if ((column = JTableHeader.this.columnAtPoint(p)) != -1) {
 815                 TableColumn aColumn = JTableHeader.this.columnModel.getColumn(column);
 816                 TableCellRenderer renderer = aColumn.getHeaderRenderer();
 817                 if (renderer == null) {
 818                     if (defaultRenderer != null) {
 819                         renderer = defaultRenderer;
 820                     } else {
 821                         return null;
 822                     }
 823                 }
 824                 Component component = renderer.getTableCellRendererComponent(
 825                                   JTableHeader.this.getTable(),
 826                                   aColumn.getHeaderValue(), false, false,
 827                                   -1, column);
 828 
 829                 return new AccessibleJTableHeaderEntry(column, JTableHeader.this, JTableHeader.this.table);
 830             } else {
 831                 return null;
 832             }
 833         }
 834 
 835         /**
 836          * Returns the number of accessible children in the object.  If all
 837          * of the children of this object implement Accessible, than this
 838          * method should return the number of children of this object.
 839          *
 840          * @return the number of accessible children in the object.
 841          */
 842         public int getAccessibleChildrenCount() {
 843             return JTableHeader.this.columnModel.getColumnCount();
 844         }
 845 
 846         /**
 847          * Return the nth Accessible child of the object.
 848          *
 849          * @param i zero-based index of child
 850          * @return the nth Accessible child of the object
 851          */
 852         public Accessible getAccessibleChild(int i) {
 853             if (i < 0 || i >= getAccessibleChildrenCount()) {
 854                 return null;
 855             } else {
 856                 TableColumn aColumn = JTableHeader.this.columnModel.getColumn(i)
 857 ;
 858                 TableCellRenderer renderer = aColumn.getHeaderRenderer();
 859                 if (renderer == null) {
 860                     if (defaultRenderer != null) {
 861                         renderer = defaultRenderer;
 862                     } else {
 863                         return null;
 864                     }
 865                 }
 866                 Component component = renderer.getTableCellRendererComponent(
 867                                   JTableHeader.this.getTable(),
 868                                   aColumn.getHeaderValue(), false, false,
 869                                   -1, i);
 870 
 871                 return new AccessibleJTableHeaderEntry(i, JTableHeader.this, JTableHeader.this.table);
 872             }
 873         }
 874 
 875       /**
 876        * This class provides an implementation of the Java Accessibility
 877        * API appropriate for JTableHeader entries.
 878        */
 879         protected class AccessibleJTableHeaderEntry extends AccessibleContext
 880             implements Accessible, AccessibleComponent  {
 881 
 882             private JTableHeader parent;
 883             private int column;
 884             private JTable table;
 885 
 886             /**
 887              *  Constructs an AccessiblJTableHeaaderEntry
 888              * @since 1.4
 889              */
 890             public AccessibleJTableHeaderEntry(int c, JTableHeader p, JTable t) {
 891                 parent = p;
 892                 column = c;
 893                 table = t;
 894                 this.setAccessibleParent(parent);
 895             }
 896 
 897             /**
 898              * Get the AccessibleContext associated with this object.
 899              * In the implementation of the Java Accessibility API
 900              * for this class, returns this object, which serves as
 901              * its own AccessibleContext.
 902              *
 903              * @return this object
 904              */
 905             public AccessibleContext getAccessibleContext() {
 906                 return this;
 907             }
 908 
 909             private AccessibleContext getCurrentAccessibleContext() {
 910                 TableColumnModel tcm = table.getColumnModel();
 911                 if (tcm != null) {
 912                     // Fixes 4772355 - ArrayOutOfBoundsException in
 913                     // JTableHeader
 914                     if (column < 0 || column >= tcm.getColumnCount()) {
 915                         return null;
 916                     }
 917                     TableColumn aColumn = tcm.getColumn(column);
 918                     TableCellRenderer renderer = aColumn.getHeaderRenderer();
 919                     if (renderer == null) {
 920                         if (defaultRenderer != null) {
 921                             renderer = defaultRenderer;
 922                         } else {
 923                             return null;
 924                         }
 925                     }
 926                     Component c = renderer.getTableCellRendererComponent(
 927                                       JTableHeader.this.getTable(),
 928                                       aColumn.getHeaderValue(), false, false,
 929                                       -1, column);
 930                     if (c instanceof Accessible) {
 931                         return ((Accessible) c).getAccessibleContext();
 932                     }
 933                 }
 934                 return null;
 935             }
 936 
 937             private Component getCurrentComponent() {
 938                 TableColumnModel tcm = table.getColumnModel();
 939                 if (tcm != null) {
 940                     // Fixes 4772355 - ArrayOutOfBoundsException in
 941                     // JTableHeader
 942                     if (column < 0 || column >= tcm.getColumnCount()) {
 943                         return null;
 944                     }
 945                     TableColumn aColumn = tcm.getColumn(column);
 946                     TableCellRenderer renderer = aColumn.getHeaderRenderer();
 947                     if (renderer == null) {
 948                         if (defaultRenderer != null) {
 949                             renderer = defaultRenderer;
 950                         } else {
 951                             return null;
 952                         }
 953                     }
 954                     return renderer.getTableCellRendererComponent(
 955                                       JTableHeader.this.getTable(),
 956                                       aColumn.getHeaderValue(), false, false,
 957                                       -1, column);
 958                 } else {
 959                     return null;
 960                 }
 961             }
 962 
 963         // AccessibleContext methods
 964 
 965             public String getAccessibleName() {
 966                 AccessibleContext ac = getCurrentAccessibleContext();
 967                 if (ac != null) {
 968                     String name = ac.getAccessibleName();
 969                     if ((name != null) && (name != "")) {
 970                         // return the cell renderer's AccessibleName
 971                         return name;
 972                     }
 973                 }
 974                 if ((accessibleName != null) && (accessibleName != "")) {
 975                     return accessibleName;
 976                 } else {
 977                     // fall back to the client property
 978                     String name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
 979                     if (name != null) {
 980                         return name;
 981                     } else {
 982                         return table.getColumnName(column);
 983                     }
 984                 }
 985             }
 986 
 987             public void setAccessibleName(String s) {
 988                 AccessibleContext ac = getCurrentAccessibleContext();
 989                 if (ac != null) {
 990                     ac.setAccessibleName(s);
 991                 } else {
 992                     super.setAccessibleName(s);
 993                 }
 994             }
 995 
 996             //
 997             // *** should check toolTip text for desc. (needs MouseEvent)
 998             //
 999             public String getAccessibleDescription() {
1000                 AccessibleContext ac = getCurrentAccessibleContext();
1001                 if (ac != null) {
1002                     return ac.getAccessibleDescription();
1003                 } else {
1004                     return super.getAccessibleDescription();
1005                 }
1006             }
1007 
1008             public void setAccessibleDescription(String s) {
1009                 AccessibleContext ac = getCurrentAccessibleContext();
1010                 if (ac != null) {
1011                     ac.setAccessibleDescription(s);
1012                 } else {
1013                     super.setAccessibleDescription(s);
1014                 }
1015             }
1016 
1017             public AccessibleRole getAccessibleRole() {
1018                 AccessibleContext ac = getCurrentAccessibleContext();
1019                 if (ac != null) {
1020                     return ac.getAccessibleRole();
1021                 } else {
1022                     return AccessibleRole.COLUMN_HEADER;
1023                 }
1024             }
1025 
1026             public AccessibleStateSet getAccessibleStateSet() {
1027                 AccessibleContext ac = getCurrentAccessibleContext();
1028                 if (ac != null) {
1029                     AccessibleStateSet states = ac.getAccessibleStateSet();
1030                     if (isShowing()) {
1031                         states.add(AccessibleState.SHOWING);
1032                     }
1033                     return states;
1034                 } else {
1035                     return new AccessibleStateSet();  // must be non null?
1036                 }
1037             }
1038 
1039             public int getAccessibleIndexInParent() {
1040                 return column;
1041             }
1042 
1043             public int getAccessibleChildrenCount() {
1044                 AccessibleContext ac = getCurrentAccessibleContext();
1045                 if (ac != null) {
1046                     return ac.getAccessibleChildrenCount();
1047                 } else {
1048                     return 0;
1049                 }
1050             }
1051 
1052             public Accessible getAccessibleChild(int i) {
1053                 AccessibleContext ac = getCurrentAccessibleContext();
1054                 if (ac != null) {
1055                     Accessible accessibleChild = ac.getAccessibleChild(i);
1056                     ac.setAccessibleParent(this);
1057                     return accessibleChild;
1058                 } else {
1059                     return null;
1060                 }
1061             }
1062 
1063             public Locale getLocale() {
1064                 AccessibleContext ac = getCurrentAccessibleContext();
1065                 if (ac != null) {
1066                     return ac.getLocale();
1067                 } else {
1068                     return null;
1069                 }
1070             }
1071 
1072             public void addPropertyChangeListener(PropertyChangeListener l) {
1073                 AccessibleContext ac = getCurrentAccessibleContext();
1074                 if (ac != null) {
1075                     ac.addPropertyChangeListener(l);
1076                 } else {
1077                     super.addPropertyChangeListener(l);
1078                 }
1079             }
1080 
1081             public void removePropertyChangeListener(PropertyChangeListener l) {
1082                 AccessibleContext ac = getCurrentAccessibleContext();
1083                 if (ac != null) {
1084                     ac.removePropertyChangeListener(l);
1085                 } else {
1086                     super.removePropertyChangeListener(l);
1087                 }
1088             }
1089 
1090             public AccessibleAction getAccessibleAction() {
1091                 return getCurrentAccessibleContext().getAccessibleAction();
1092             }
1093 
1094            /**
1095             * Get the AccessibleComponent associated with this object.  In the
1096             * implementation of the Java Accessibility API for this class,
1097             * return this object, which is responsible for implementing the
1098             * AccessibleComponent interface on behalf of itself.
1099             *
1100             * @return this object
1101             */
1102             public AccessibleComponent getAccessibleComponent() {
1103                 return this; // to override getBounds()
1104             }
1105 
1106             public AccessibleSelection getAccessibleSelection() {
1107                 return getCurrentAccessibleContext().getAccessibleSelection();
1108             }
1109 
1110             public AccessibleText getAccessibleText() {
1111                 return getCurrentAccessibleContext().getAccessibleText();
1112             }
1113 
1114             public AccessibleValue getAccessibleValue() {
1115                 return getCurrentAccessibleContext().getAccessibleValue();
1116             }
1117 
1118 
1119         // AccessibleComponent methods
1120 
1121             public Color getBackground() {
1122                 AccessibleContext ac = getCurrentAccessibleContext();
1123                 if (ac instanceof AccessibleComponent) {
1124                     return ((AccessibleComponent) ac).getBackground();
1125                 } else {
1126                     Component c = getCurrentComponent();
1127                     if (c != null) {
1128                         return c.getBackground();
1129                     } else {
1130                         return null;
1131                     }
1132                 }
1133             }
1134 
1135             public void setBackground(Color c) {
1136                 AccessibleContext ac = getCurrentAccessibleContext();
1137                 if (ac instanceof AccessibleComponent) {
1138                     ((AccessibleComponent) ac).setBackground(c);
1139                 } else {
1140                     Component cp = getCurrentComponent();
1141                     if (cp != null) {
1142                         cp.setBackground(c);
1143                     }
1144                 }
1145             }
1146 
1147             public Color getForeground() {
1148                 AccessibleContext ac = getCurrentAccessibleContext();
1149                 if (ac instanceof AccessibleComponent) {
1150                     return ((AccessibleComponent) ac).getForeground();
1151                 } else {
1152                     Component c = getCurrentComponent();
1153                     if (c != null) {
1154                         return c.getForeground();
1155                     } else {
1156                         return null;
1157                     }
1158                 }
1159             }
1160 
1161             public void setForeground(Color c) {
1162                 AccessibleContext ac = getCurrentAccessibleContext();
1163                 if (ac instanceof AccessibleComponent) {
1164                     ((AccessibleComponent) ac).setForeground(c);
1165                 } else {
1166                     Component cp = getCurrentComponent();
1167                     if (cp != null) {
1168                         cp.setForeground(c);
1169                     }
1170                 }
1171             }
1172 
1173             public Cursor getCursor() {
1174                 AccessibleContext ac = getCurrentAccessibleContext();
1175                 if (ac instanceof AccessibleComponent) {
1176                     return ((AccessibleComponent) ac).getCursor();
1177                 } else {
1178                     Component c = getCurrentComponent();
1179                     if (c != null) {
1180                         return c.getCursor();
1181                     } else {
1182                         Accessible ap = getAccessibleParent();
1183                         if (ap instanceof AccessibleComponent) {
1184                             return ((AccessibleComponent) ap).getCursor();
1185                         } else {
1186                             return null;
1187                         }
1188                     }
1189                 }
1190             }
1191 
1192             public void setCursor(Cursor c) {
1193                 AccessibleContext ac = getCurrentAccessibleContext();
1194                 if (ac instanceof AccessibleComponent) {
1195                     ((AccessibleComponent) ac).setCursor(c);
1196                 } else {
1197                     Component cp = getCurrentComponent();
1198                     if (cp != null) {
1199                         cp.setCursor(c);
1200                     }
1201                 }
1202             }
1203 
1204             public Font getFont() {
1205                 AccessibleContext ac = getCurrentAccessibleContext();
1206                 if (ac instanceof AccessibleComponent) {
1207                     return ((AccessibleComponent) ac).getFont();
1208                 } else {
1209                     Component c = getCurrentComponent();
1210                     if (c != null) {
1211                         return c.getFont();
1212                     } else {
1213                         return null;
1214                     }
1215                 }
1216             }
1217 
1218             public void setFont(Font f) {
1219                 AccessibleContext ac = getCurrentAccessibleContext();
1220                 if (ac instanceof AccessibleComponent) {
1221                     ((AccessibleComponent) ac).setFont(f);
1222                 } else {
1223                     Component c = getCurrentComponent();
1224                     if (c != null) {
1225                         c.setFont(f);
1226                     }
1227                 }
1228             }
1229 
1230             public FontMetrics getFontMetrics(Font f) {
1231                 AccessibleContext ac = getCurrentAccessibleContext();
1232                 if (ac instanceof AccessibleComponent) {
1233                     return ((AccessibleComponent) ac).getFontMetrics(f);
1234                 } else {
1235                     Component c = getCurrentComponent();
1236                     if (c != null) {
1237                         return c.getFontMetrics(f);
1238                     } else {
1239                         return null;
1240                     }
1241                 }
1242             }
1243 
1244             public boolean isEnabled() {
1245                 AccessibleContext ac = getCurrentAccessibleContext();
1246                 if (ac instanceof AccessibleComponent) {
1247                     return ((AccessibleComponent) ac).isEnabled();
1248                 } else {
1249                     Component c = getCurrentComponent();
1250                     if (c != null) {
1251                         return c.isEnabled();
1252                     } else {
1253                         return false;
1254                     }
1255                 }
1256             }
1257 
1258             public void setEnabled(boolean b) {
1259                 AccessibleContext ac = getCurrentAccessibleContext();
1260                 if (ac instanceof AccessibleComponent) {
1261                     ((AccessibleComponent) ac).setEnabled(b);
1262                 } else {
1263                     Component c = getCurrentComponent();
1264                     if (c != null) {
1265                         c.setEnabled(b);
1266                     }
1267                 }
1268             }
1269 
1270             public boolean isVisible() {
1271                 AccessibleContext ac = getCurrentAccessibleContext();
1272                 if (ac instanceof AccessibleComponent) {
1273                     return ((AccessibleComponent) ac).isVisible();
1274                 } else {
1275                     Component c = getCurrentComponent();
1276                     if (c != null) {
1277                         return c.isVisible();
1278                     } else {
1279                         return false;
1280                     }
1281                 }
1282             }
1283 
1284             public void setVisible(boolean b) {
1285                 AccessibleContext ac = getCurrentAccessibleContext();
1286                 if (ac instanceof AccessibleComponent) {
1287                     ((AccessibleComponent) ac).setVisible(b);
1288                 } else {
1289                     Component c = getCurrentComponent();
1290                     if (c != null) {
1291                         c.setVisible(b);
1292                     }
1293                 }
1294             }
1295 
1296             public boolean isShowing() {
1297                 if (isVisible() && JTableHeader.this.isShowing()) {
1298                     return true;
1299                 } else {
1300                     return false;
1301                 }
1302             }
1303 
1304             public boolean contains(Point p) {
1305                 AccessibleContext ac = getCurrentAccessibleContext();
1306                 if (ac instanceof AccessibleComponent) {
1307                     Rectangle r = ((AccessibleComponent) ac).getBounds();
1308                     return r.contains(p);
1309                 } else {
1310                     Component c = getCurrentComponent();
1311                     if (c != null) {
1312                         Rectangle r = c.getBounds();
1313                         return r.contains(p);
1314                     } else {
1315                         return getBounds().contains(p);
1316                     }
1317                 }
1318             }
1319 
1320             public Point getLocationOnScreen() {
1321                 if (parent != null) {
1322                     Point parentLocation = parent.getLocationOnScreen();
1323                     Point componentLocation = getLocation();
1324                     componentLocation.translate(parentLocation.x, parentLocation.y);
1325                     return componentLocation;
1326                 } else {
1327                     return null;
1328                 }
1329             }
1330 
1331             public Point getLocation() {
1332                 AccessibleContext ac = getCurrentAccessibleContext();
1333                 if (ac instanceof AccessibleComponent) {
1334                     Rectangle r = ((AccessibleComponent) ac).getBounds();
1335                     return r.getLocation();
1336                 } else {
1337                     Component c = getCurrentComponent();
1338                     if (c != null) {
1339                         Rectangle r = c.getBounds();
1340                         return r.getLocation();
1341                     } else {
1342                         return getBounds().getLocation();
1343                     }
1344                 }
1345             }
1346 
1347             public void setLocation(Point p) {
1348 //                if ((parent != null)  && (parent.contains(p))) {
1349 //                    ensureIndexIsVisible(indexInParent);
1350 //                }
1351             }
1352 
1353             public Rectangle getBounds() {
1354                   Rectangle r = table.getCellRect(-1, column, false);
1355                   r.y = 0;
1356                   return r;
1357 
1358 //                AccessibleContext ac = getCurrentAccessibleContext();
1359 //                if (ac instanceof AccessibleComponent) {
1360 //                    return ((AccessibleComponent) ac).getBounds();
1361 //                } else {
1362 //                  Component c = getCurrentComponent();
1363 //                  if (c != null) {
1364 //                      return c.getBounds();
1365 //                  } else {
1366 //                      Rectangle r = table.getCellRect(-1, column, false);
1367 //                      r.y = 0;
1368 //                      return r;
1369 //                  }
1370 //              }
1371             }
1372 
1373             public void setBounds(Rectangle r) {
1374                 AccessibleContext ac = getCurrentAccessibleContext();
1375                 if (ac instanceof AccessibleComponent) {
1376                     ((AccessibleComponent) ac).setBounds(r);
1377                 } else {
1378                     Component c = getCurrentComponent();
1379                     if (c != null) {
1380                         c.setBounds(r);
1381                     }
1382                 }
1383             }
1384 
1385             public Dimension getSize() {
1386                 return getBounds().getSize();
1387 //                AccessibleContext ac = getCurrentAccessibleContext();
1388 //                if (ac instanceof AccessibleComponent) {
1389 //                    Rectangle r = ((AccessibleComponent) ac).getBounds();
1390 //                    return r.getSize();
1391 //                } else {
1392 //                    Component c = getCurrentComponent();
1393 //                    if (c != null) {
1394 //                        Rectangle r = c.getBounds();
1395 //                        return r.getSize();
1396 //                    } else {
1397 //                        return getBounds().getSize();
1398 //                    }
1399 //                }
1400             }
1401 
1402             public void setSize (Dimension d) {
1403                 AccessibleContext ac = getCurrentAccessibleContext();
1404                 if (ac instanceof AccessibleComponent) {
1405                     ((AccessibleComponent) ac).setSize(d);
1406                 } else {
1407                     Component c = getCurrentComponent();
1408                     if (c != null) {
1409                         c.setSize(d);
1410                     }
1411                 }
1412             }
1413 
1414             public Accessible getAccessibleAt(Point p) {
1415                 AccessibleContext ac = getCurrentAccessibleContext();
1416                 if (ac instanceof AccessibleComponent) {
1417                     return ((AccessibleComponent) ac).getAccessibleAt(p);
1418                 } else {
1419                     return null;
1420                 }
1421             }
1422 
1423             public boolean isFocusTraversable() {
1424                 AccessibleContext ac = getCurrentAccessibleContext();
1425                 if (ac instanceof AccessibleComponent) {
1426                     return ((AccessibleComponent) ac).isFocusTraversable();
1427                 } else {
1428                     Component c = getCurrentComponent();
1429                     if (c != null) {
1430                         return c.isFocusTraversable();
1431                     } else {
1432                         return false;
1433                     }
1434                 }
1435             }
1436 
1437             public void requestFocus() {
1438                 AccessibleContext ac = getCurrentAccessibleContext();
1439                 if (ac instanceof AccessibleComponent) {
1440                     ((AccessibleComponent) ac).requestFocus();
1441                 } else {
1442                     Component c = getCurrentComponent();
1443                     if (c != null) {
1444                         c.requestFocus();
1445                     }
1446                 }
1447             }
1448 
1449             public void addFocusListener(FocusListener l) {
1450                 AccessibleContext ac = getCurrentAccessibleContext();
1451                 if (ac instanceof AccessibleComponent) {
1452                     ((AccessibleComponent) ac).addFocusListener(l);
1453                 } else {
1454                     Component c = getCurrentComponent();
1455                     if (c != null) {
1456                         c.addFocusListener(l);
1457                     }
1458                 }
1459             }
1460 
1461             public void removeFocusListener(FocusListener l) {
1462                 AccessibleContext ac = getCurrentAccessibleContext();
1463                 if (ac instanceof AccessibleComponent) {
1464                     ((AccessibleComponent) ac).removeFocusListener(l);
1465                 } else {
1466                     Component c = getCurrentComponent();
1467                     if (c != null) {
1468                         c.removeFocusListener(l);
1469                     }
1470                 }
1471             }
1472 
1473         } // inner class AccessibleJTableHeaderElement
1474 
1475     }  // inner class AccessibleJTableHeader
1476 
1477 }  // End of Class JTableHeader