001/* JTableHeader.java --
002   Copyright (C) 2003, 2004, 2005, 2006,  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.swing.table;
040
041import java.awt.Color;
042import java.awt.Component;
043import java.awt.Cursor;
044import java.awt.Dimension;
045import java.awt.Font;
046import java.awt.FontMetrics;
047import java.awt.Point;
048import java.awt.Rectangle;
049import java.awt.event.FocusListener;
050import java.beans.PropertyChangeListener;
051import java.util.Locale;
052
053import javax.accessibility.Accessible;
054import javax.accessibility.AccessibleAction;
055import javax.accessibility.AccessibleComponent;
056import javax.accessibility.AccessibleContext;
057import javax.accessibility.AccessibleRole;
058import javax.accessibility.AccessibleSelection;
059import javax.accessibility.AccessibleStateSet;
060import javax.accessibility.AccessibleText;
061import javax.accessibility.AccessibleValue;
062import javax.swing.JComponent;
063import javax.swing.JTable;
064import javax.swing.UIManager;
065import javax.swing.event.ChangeEvent;
066import javax.swing.event.ListSelectionEvent;
067import javax.swing.event.TableColumnModelEvent;
068import javax.swing.event.TableColumnModelListener;
069import javax.swing.plaf.TableHeaderUI;
070
071/**
072 * Represents the table header. The header displays the column header values,
073 * is always visible event if the rest of the table scrolls up and down and
074 * supports column reordering and resizing with mouse.
075 */
076public class JTableHeader extends JComponent
077  implements TableColumnModelListener, Accessible
078{
079  protected class AccessibleJTableHeader extends AccessibleJComponent
080  {
081    protected class AccessibleJTableHeaderEntry extends AccessibleContext
082      implements Accessible, AccessibleComponent
083    {
084      
085      private int columnIndex;
086      
087      private JTableHeader parent;
088      
089      private JTable table;
090      
091      public AccessibleJTableHeaderEntry(int c, JTableHeader p, JTable t)
092      {
093        columnIndex = c;
094        parent = p;
095        table = t;
096      }
097      
098      /**
099       * Returns the column header renderer.
100       * 
101       * @return The column header renderer.
102       */
103      Component getColumnHeaderRenderer()
104      {
105        TableColumn tc = parent.getColumnModel().getColumn(columnIndex);
106        TableCellRenderer r = tc.getHeaderRenderer();
107        if (r == null)
108          r = parent.getDefaultRenderer();
109        return r.getTableCellRendererComponent(table, tc.headerValue, 
110            false, false, -1, columnIndex);
111      }
112      
113      /**
114       * Returns the accessible context for the column header renderer, or 
115       * <code>null</code>.
116       * 
117       * @return The accessible context.
118       */
119      AccessibleContext getAccessibleColumnHeaderRenderer()
120      {
121        Component c = getColumnHeaderRenderer();
122        if (c instanceof Accessible)
123          return c.getAccessibleContext();
124        return null;
125      }
126      
127      /**
128       * @see #removeFocusListener(FocusListener)
129       */
130      public void addFocusListener(FocusListener l)
131      {
132        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
133        AccessibleComponent c = ac.getAccessibleComponent();
134        if (c != null)
135          c.addFocusListener(l);
136      }
137      
138      /**
139       * @see #removePropertyChangeListener(PropertyChangeListener)
140       */
141      public void addPropertyChangeListener(PropertyChangeListener l)
142      {
143        // add the listener to the accessible context for the header
144        // renderer...
145        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
146        if (ac != null)
147          ac.addPropertyChangeListener(l);
148      }
149      
150      public boolean contains(Point p)
151      {
152        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
153        AccessibleComponent c = ac.getAccessibleComponent();
154        if (c != null)
155          return c.contains(p);
156        else 
157          return false;
158      }
159      
160      public AccessibleAction getAccessibleAction()
161      {
162        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
163        if (ac instanceof AccessibleAction)
164          return (AccessibleAction) ac;
165        else 
166          return null;
167      }
168      
169      public Accessible getAccessibleAt(Point p)
170      {
171        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
172        AccessibleComponent c = ac.getAccessibleComponent();
173        if (c != null)
174          return c.getAccessibleAt(p);
175        else
176          return null;
177      }
178      
179      /**
180       * Returns <code>null</code> as the header entry has no accessible
181       * children.
182       * 
183       * @return <code>null</code>.
184       */
185      public Accessible getAccessibleChild(int i)
186      {
187        return null;
188      }
189      
190      /**
191       * Returns the number of accessible children, zero in this case.
192       * 
193       * @return 0
194       */
195      public int getAccessibleChildrenCount()
196      {
197        return 0;
198      }
199      
200      /**
201       * Returns the accessible component for this header entry.
202       * 
203       * @return <code>this</code>.
204       */
205      public AccessibleComponent getAccessibleComponent()
206      {
207        return this;
208      }
209      
210      /**
211       * Returns the accessible context for this header entry.
212       * 
213       * @return <code>this</code>.
214       */
215      public AccessibleContext getAccessibleContext()
216      {
217        return this;
218      }
219      
220      /**
221       * Returns the accessible description.
222       * 
223       * @return The accessible description.
224       * 
225       * @see #setAccessibleDescription(String)
226       */
227      public String getAccessibleDescription()
228      {
229        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
230        if (ac != null)
231          return ac.getAccessibleDescription();
232        return accessibleDescription;
233      }
234      
235      /**
236       * Returns the index of this header entry.
237       * 
238       * @return The index of this header entry.
239       */
240      public int getAccessibleIndexInParent()
241      {
242        return columnIndex;
243      }
244      
245      /**
246       * Returns the accessible name.
247       * 
248       * @return The accessible name.
249       * 
250       * @see #setAccessibleName(String)
251       */
252      public String getAccessibleName()
253      {
254        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
255        if (ac != null)
256          return ac.getAccessibleName();
257        return accessibleName;
258      }
259      
260      /**
261       * Returns the accessible role for the header entry.
262       * 
263       * @return The accessible role.
264       */
265      public AccessibleRole getAccessibleRole()
266      {
267        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
268        if (ac != null)
269          return ac.getAccessibleRole();
270        else
271          return null;
272      }
273      
274      public AccessibleSelection getAccessibleSelection()
275      {
276        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
277        if (ac instanceof AccessibleValue)
278          return (AccessibleSelection) ac;
279        else 
280          return null;
281      }
282      
283      public AccessibleStateSet getAccessibleStateSet()
284      {
285        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
286        if (ac != null)
287          return ac.getAccessibleStateSet();
288        else 
289          return null;
290      }
291      
292      public AccessibleText getAccessibleText()
293      {
294        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
295        if (ac != null)
296          return ac.getAccessibleText();
297        else 
298          return null;
299      }
300      
301      public AccessibleValue getAccessibleValue()
302      {
303        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
304        if (ac instanceof AccessibleValue)
305          return (AccessibleValue) ac;
306        else 
307          return null;
308      }
309      
310      public Color getBackground()
311      {
312        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
313        AccessibleComponent c = ac.getAccessibleComponent();
314        if (c != null)
315          return c.getBackground();
316        else
317          return null;
318      }
319      
320      public Rectangle getBounds()
321      {
322        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
323        AccessibleComponent c = ac.getAccessibleComponent();
324        if (c != null)
325          return c.getBounds();
326        else
327          return null;
328      }
329      
330      public Cursor getCursor()
331      {
332        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
333        AccessibleComponent c = ac.getAccessibleComponent();
334        if (c != null)
335          return c.getCursor();
336        else
337          return null;
338      }
339      
340      public Font getFont()
341      {
342        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
343        AccessibleComponent c = ac.getAccessibleComponent();
344        if (c != null)
345          return c.getFont();
346        else
347          return null;
348      }
349      
350      public FontMetrics getFontMetrics(Font f)
351      {
352        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
353        AccessibleComponent c = ac.getAccessibleComponent();
354        if (c != null)
355          return c.getFontMetrics(f);
356        else
357          return null;
358      }
359      
360      public Color getForeground()
361      {
362        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
363        AccessibleComponent c = ac.getAccessibleComponent();
364        if (c != null)
365          return c.getForeground();
366        else
367          return null;
368      }
369      
370      public Locale getLocale()
371      {
372        Component c = getColumnHeaderRenderer();
373        if (c != null)
374          return c.getLocale();
375        return null;
376      }
377      
378      public Point getLocation()
379      {
380        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
381        AccessibleComponent c = ac.getAccessibleComponent();
382        if (c != null)
383          return c.getLocation();
384        else
385          return null;
386      }
387      
388      public Point getLocationOnScreen()
389      {
390        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
391        AccessibleComponent c = ac.getAccessibleComponent();
392        if (c != null)
393          return c.getLocationOnScreen();
394        else
395          return null;
396      }
397      
398      public Dimension getSize()
399      {
400        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
401        AccessibleComponent c = ac.getAccessibleComponent();
402        if (c != null)
403          return c.getSize();
404        else
405          return null;
406      }
407      
408      public boolean isEnabled()
409      {
410        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
411        AccessibleComponent c = ac.getAccessibleComponent();
412        if (c != null)
413          return c.isEnabled();
414        else
415          return false;
416      }
417      
418      public boolean isFocusTraversable()
419      {
420        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
421        AccessibleComponent c = ac.getAccessibleComponent();
422        if (c != null)
423          return c.isFocusTraversable();
424        else
425          return false;
426      }
427      
428      public boolean isShowing()
429      {
430        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
431        AccessibleComponent c = ac.getAccessibleComponent();
432        if (c != null)
433          return c.isShowing();
434        else
435          return false;
436      }
437      
438      public boolean isVisible()
439      {
440        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
441        AccessibleComponent c = ac.getAccessibleComponent();
442        if (c != null)
443          return c.isVisible();
444        else
445          return false;
446      }
447      
448      /**
449       * @see #addFocusListener(FocusListener)
450       */
451      public void removeFocusListener(FocusListener l)
452      {
453        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
454        AccessibleComponent c = ac.getAccessibleComponent();
455        if (c != null)
456          c.removeFocusListener(l);
457      }
458      
459      /**
460       * @see #addPropertyChangeListener(PropertyChangeListener)
461       */
462      public void removePropertyChangeListener(PropertyChangeListener l)
463      {
464        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
465        if (ac != null)
466          ac.removePropertyChangeListener(l);
467      }
468      
469      /**
470       * @see #addFocusListener(FocusListener)
471       */
472      public void requestFocus()
473      {
474        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
475        AccessibleComponent c = ac.getAccessibleComponent();
476        if (c != null)
477          c.requestFocus();
478      }
479      
480      /**
481       * @see #getAccessibleDescription()
482       */
483      public void setAccessibleDescription(String s)
484      {
485        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
486        if (ac != null)
487          ac.setAccessibleDescription(s);
488        else
489          accessibleDescription = s;
490      }
491      
492      /**
493       * @see #getAccessibleName()
494       */
495      public void setAccessibleName(String s)
496      {
497        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
498        if (ac != null)
499          ac.setAccessibleName(s);
500      }
501      
502      public void setBackground(Color c)
503      {
504        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
505        AccessibleComponent comp = ac.getAccessibleComponent();
506        if (comp != null)
507          comp.setBackground(c);
508      }
509      
510      public void setBounds(Rectangle r)
511      {
512        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
513        AccessibleComponent comp = ac.getAccessibleComponent();
514        if (comp != null)
515          comp.setBounds(r);
516      }
517      
518      public void setCursor(Cursor c)
519      {
520        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
521        AccessibleComponent comp = ac.getAccessibleComponent();
522        if (comp != null)
523          comp.setCursor(c);
524      }
525      
526      public void setEnabled(boolean b)
527      {
528        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
529        AccessibleComponent comp = ac.getAccessibleComponent();
530        if (comp != null)
531          comp.setEnabled(b);
532      }
533      
534      public void setFont(Font f)
535      {
536        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
537        AccessibleComponent comp = ac.getAccessibleComponent();
538        if (comp != null)
539          comp.setFont(f);
540      }
541      
542      public void setForeground(Color c)
543      {
544        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
545        AccessibleComponent comp = ac.getAccessibleComponent();
546        if (comp != null)
547          comp.setForeground(c);
548      }
549      
550      public void setLocation(Point p)
551      {
552        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
553        AccessibleComponent comp = ac.getAccessibleComponent();
554        if (comp != null)
555          comp.setLocation(p);
556      }
557      
558      public void setSize(Dimension d)
559      {
560        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
561        AccessibleComponent comp = ac.getAccessibleComponent();
562        if (comp != null)
563          comp.setSize(d);
564      }
565      
566      public void setVisible(boolean b)
567      {
568        AccessibleContext ac = getAccessibleColumnHeaderRenderer();
569        AccessibleComponent comp = ac.getAccessibleComponent();
570        if (comp != null)
571          comp.setVisible(b);
572      }
573    }
574    
575    public AccessibleRole getAccessibleRole()
576    {
577      return AccessibleRole.PANEL;
578    }
579    
580    public int getAccessibleChildrenCount()
581    {
582      return table.getColumnCount();
583    }
584    
585    public Accessible getAccessibleChild(int i)
586    {
587      return new AccessibleJTableHeaderEntry(i, JTableHeader.this, table);
588    }
589    
590    public Accessible getAccessibleAt(Point p)
591    {
592      return getAccessibleChild(columnAtPoint(p));
593    }
594  }
595  
596  /**
597   * Use serialVersionUid for interoperability.
598   */
599  private static final long serialVersionUID = 5144633983372967710L;
600
601  /**
602   * The columnModel property.
603   */
604  protected TableColumnModel columnModel;
605
606  /**
607   * The draggedColumn property.
608   */
609  protected TableColumn draggedColumn;
610
611  /**
612   * The draggedDistance property.
613   */
614  protected int draggedDistance;
615
616  /**
617   * The opaque property.
618   */
619  boolean opaque;
620
621  /**
622   * The reorderingAllowed property.
623   */
624  protected boolean reorderingAllowed;
625
626  /**
627   * The resizingAllowed property.
628   */
629  protected boolean resizingAllowed = true;
630
631  /**
632   * The resizingColumn property.
633   */
634  protected TableColumn resizingColumn;
635
636  /**
637   * The table property.
638   */
639  protected JTable table;
640
641  /**
642   * The updateTableInRealTime property.
643   */
644  protected boolean updateTableInRealTime;
645
646  TableCellRenderer cellRenderer; 
647
648  /**
649   * Creates a new default instance.
650   */
651  public JTableHeader()
652  {
653    this(null);
654  }
655
656  /**
657   * Creates a new header.  If <code>cm</code> is <code>null</code>, a new
658   * table column model is created by calling 
659   * {@link #createDefaultColumnModel()}.
660   * 
661   * @param cm  the table column model (<code>null</code> permitted).
662   */
663  public JTableHeader(TableColumnModel cm)
664  {
665    columnModel = cm == null ? createDefaultColumnModel() : cm; 
666    initializeLocalVars();
667    updateUI();
668  }
669
670  /**
671   * Creates a default table column model.
672   * 
673   * @return A default table column model.
674   */
675  protected TableColumnModel createDefaultColumnModel()
676  {
677    return new DefaultTableColumnModel();
678  }
679
680  /**
681   * Get the value of the {@link #accessibleContext} property.
682   *
683   * @return The current value of the property
684   */
685  public AccessibleContext getAccessibleContext()
686  {
687    return accessibleContext;
688  }
689
690  /**
691   * Get the value of the {@link #columnModel} property.
692   *
693   * @return The current value of the property
694   */
695  public TableColumnModel getColumnModel()
696  {
697    return columnModel;
698  }
699
700  /**
701   * Get the column that is currently being dragged. This is used when
702   * handling the column reordering with mouse.
703   *
704   * @return the column being dragged, null if none.
705   */
706  public TableColumn getDraggedColumn()
707  {
708    return draggedColumn;
709  }
710
711  /**
712   * Get the value of the {@link #draggedDistance} property.
713   *
714   * @return The current value of the property
715   */
716  public int getDraggedDistance()
717  {
718    return draggedDistance;
719  }
720
721  /**
722   * Check if it is possible to reorder the table columns by dragging column
723   * header with mouse. The table reordering is enabled by default, but can be
724   * disabled with {@link #setReorderingAllowed(boolean)}.
725   *
726   * @return true if reordering is allowed, false otherwise.
727   */ 
728  public boolean getReorderingAllowed()
729  {
730    return reorderingAllowed;
731  }
732
733  /**
734   * Check if it is possible to resize the table columns by dragging the column
735   * boundary in the table header with mouse. The resizing is enabled
736   * by default, but can be disabled with {@link #setResizingAllowed(boolean)}.
737   *
738   * @return true if resizing is allowed, false otherwise.
739   */ 
740  public boolean getResizingAllowed()
741  {
742    return resizingAllowed;
743  }
744
745  /**
746   * Get the column that is currently being resized. This is used when
747   * handling the column resizing with mouse.
748   *
749   * @return the column being currently resized, null if none.
750   */
751  public TableColumn getResizingColumn()
752  {
753    return resizingColumn;
754  }
755
756  /**
757   * Get the table, having this header.
758   *
759   * @return the table, having this header.
760   */
761  public JTable getTable()
762  {
763    return table;
764  }
765
766  /**
767   * Get the value of the {@link #updateTableInRealTime} property.
768   *
769   * @return The current value of the property
770   */
771  public boolean getUpdateTableInRealTime()
772  {
773    return updateTableInRealTime;
774  }
775
776  /**
777   * Get the value of the {@link #opaque} property.
778   *
779   * @return The current value of the property
780   */
781  public boolean isOpaque()
782  {
783    return opaque;
784  }
785
786  /**
787   * Set the value of the {@link #columnModel} property.
788   *
789   * @param c The new value of the property
790   */ 
791  public void setColumnModel(TableColumnModel c)
792  {
793    columnModel.removeColumnModelListener(this);
794    columnModel = c;
795    columnModel.addColumnModelListener(this);
796  }
797
798  /**
799   * Set the column that is currently being dragged. This is used when
800   * dragging the column with mouse. Setting to null will stop the 
801   * dragging session immediately.
802   *
803   * @param draggingIt the column being currently dragged, null if none.
804   */ 
805  public void setDraggedColumn(TableColumn draggingIt)
806  {
807    draggedColumn = draggingIt;
808  }
809
810  /**
811   * Set the value of the {@link #draggedDistance} property.
812   *
813   * @param d The new value of the property
814   */ 
815  public void setDraggedDistance(int d)
816  {
817    draggedDistance = d;
818  }
819
820  /**
821   * Set the value of the {@link #opaque} property.
822   *
823   * @param o The new value of the property
824   */ 
825  public void setOpaque(boolean o)
826  {
827    opaque = o;
828  }
829
830  /**
831   * Set the table ability to reorder columns by dragging column header
832   * with mouse. The table reordering is enabled by default, but can be
833   * disabled with this method.
834   *
835   * @param allowed true if reordering is allowed, false otherwise.
836   */ 
837  public void setReorderingAllowed(boolean allowed)
838  {
839    reorderingAllowed = allowed;
840  }
841
842  /**
843   * Set the table ability to resize columns by dragging the column
844   * boundary in the table header with mouse. The resizing is enabled
845   * by default, but can be disabled using this method.
846   *
847   * @param allowed true if resizing is allowed, false otherwise.
848   */ 
849  public void setResizingAllowed(boolean allowed)
850  {
851    resizingAllowed = allowed;
852  }
853
854  /**
855   * The the column that is currently being resized. This property is used
856   * when handling table resizing with mouse. Setting to null would stop
857   * the resizing session immediately.
858   *
859   * @param resizingIt the column being currently resized
860   */ 
861  public void setResizingColumn(TableColumn resizingIt)
862  {
863    resizingColumn = resizingIt;
864  }
865
866  /**
867   * Set the value of the {@link #table} property.
868   *
869   * @param t The new value of the property
870   */ 
871  public void setTable(JTable t)
872  {
873    table = t;
874  }
875
876  /**
877   * Set the value of the {@link #updateTableInRealTime} property.
878   *
879   * @param u The new value of the property
880   */ 
881  public void setUpdateTableInRealTime(boolean u)
882  {
883    updateTableInRealTime = u;
884  }
885
886  /**
887   * Creates a default renderer.
888   * 
889   * @return A default renderer.
890   */
891  protected TableCellRenderer createDefaultRenderer()
892  {
893    return new DefaultTableCellRenderer();
894  }
895  
896  /**
897   * Returns the default table cell renderer.
898   * 
899   * @return The default table cell renderer.
900   */
901  public TableCellRenderer getDefaultRenderer()
902  {
903    return cellRenderer;
904  }
905
906  /**
907   * Sets the default table cell renderer.
908   * 
909   * @param cellRenderer  the renderer.
910   */
911  public void setDefaultRenderer(TableCellRenderer cellRenderer)
912  {
913    this.cellRenderer = cellRenderer;
914  }
915  
916  /**
917   * Get the rectangle, occupied by the header of the given column.
918   * 
919   * @param column the column, for that the header area is requested.
920   * 
921   * @return the column header area.
922   */
923  public Rectangle getHeaderRect(int column)
924  {
925    Rectangle r = getTable().getCellRect(-1, column, false);
926    r.height = getHeight();
927    return r;
928  }
929
930  protected String paramString()
931  {
932    return "JTableHeader";
933  }
934
935  // UI support
936
937  public String getUIClassID()
938  {
939    return "TableHeaderUI";
940  }
941
942  public TableHeaderUI getUI()
943  {
944    return (TableHeaderUI) ui;
945  }
946
947  public void setUI(TableHeaderUI u)
948  {
949    super.setUI(u);
950  }
951
952  public void updateUI()
953  {
954    setUI((TableHeaderUI) UIManager.getUI(this));
955  }
956
957  /**
958   * Returns the index of the column at the specified point.
959   * 
960   * @param point  the point.
961   * 
962   * @return The column index, or -1.
963   */
964  public int columnAtPoint(Point point)
965  {
966    if (getBounds().contains(point))
967      return columnModel.getColumnIndexAtX(point.x);
968    
969    return -1;
970  }
971
972  /**
973   * Receives notification when a column is added to the column model.
974   *
975   * @param event the table column model event
976   */
977  public void columnAdded(TableColumnModelEvent event)
978  {
979    // TODO: What else to do here (if anything)?
980    resizeAndRepaint();
981  }
982
983  /**
984   * Receives notification when a column margin changes in the column model.
985   *
986   * @param event the table column model event
987   */
988  public void columnMarginChanged(ChangeEvent event)
989  {
990    // TODO: What else to do here (if anything)?
991    resizeAndRepaint();
992  }
993
994  /**
995   * Receives notification when a column is moved within the column model.
996   *
997   * @param event the table column model event
998   */
999  public void columnMoved(TableColumnModelEvent event)
1000  {
1001    // TODO: What else to do here (if anything)?
1002    resizeAndRepaint();
1003  }
1004
1005  /**
1006   * Receives notification when a column is removed from the column model.
1007   *
1008   * @param event the table column model event
1009   */
1010  public void columnRemoved(TableColumnModelEvent event)
1011  {
1012    // TODO: What else to do here (if anything)?
1013    resizeAndRepaint();
1014  }
1015
1016  /**
1017   * Receives notification when the column selection has changed.
1018   *
1019   * @param event the table column model event
1020   */
1021  public void columnSelectionChanged(ListSelectionEvent event)
1022  {
1023    // TODO: What else to do here (if anything)?
1024    resizeAndRepaint();
1025  }
1026
1027  /**
1028   * Validates the layout of this table header and repaints it. This is
1029   * equivalent to <code>revalidate()</code> followed by
1030   * <code>repaint()</code>.
1031   */
1032  public void resizeAndRepaint()
1033  {
1034    revalidate();
1035    repaint();
1036  }
1037
1038  /**
1039   * Initializes the fields and properties of this class with default values.
1040   * This is called by the constructors.
1041   */
1042  protected void initializeLocalVars()
1043  {
1044    accessibleContext = new AccessibleJTableHeader();
1045    draggedColumn = null;
1046    draggedDistance = 0;
1047    opaque = true;
1048    reorderingAllowed = true;
1049    resizingAllowed = true;
1050    resizingColumn = null;
1051    table = null;
1052    updateTableInRealTime = true;
1053    cellRenderer = createDefaultRenderer();
1054  }
1055}