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