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