1 /* JTableHeader.java --
2 Copyright (C) 2003, 2004, 2005, 2006, Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing.table;
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Cursor;
44 import java.awt.Dimension;
46 import java.awt.FontMetrics;
47 import java.awt.Point;
48 import java.awt.Rectangle;
49 import java.awt.event.FocusListener;
50 import java.beans.PropertyChangeListener;
51 import java.util.Locale;
53 import javax.accessibility.Accessible;
54 import javax.accessibility.AccessibleAction;
55 import javax.accessibility.AccessibleComponent;
56 import javax.accessibility.AccessibleContext;
57 import javax.accessibility.AccessibleRole;
58 import javax.accessibility.AccessibleSelection;
59 import javax.accessibility.AccessibleStateSet;
60 import javax.accessibility.AccessibleText;
61 import javax.accessibility.AccessibleValue;
62 import javax.swing.JComponent;
63 import javax.swing.JTable;
64 import javax.swing.UIManager;
65 import javax.swing.event.ChangeEvent;
66 import javax.swing.event.ListSelectionEvent;
67 import javax.swing.event.TableColumnModelEvent;
68 import javax.swing.event.TableColumnModelListener;
69 import javax.swing.plaf.TableHeaderUI;
72 * Represents the table header. The header displays the column header values,
73 * is always visible event if the rest of the table scrolls up and down and
74 * supports column reordering and resizing with mouse.
76 public class JTableHeader extends JComponent
77 implements TableColumnModelListener, Accessible
79 protected class AccessibleJTableHeader extends AccessibleJComponent
81 protected class AccessibleJTableHeaderEntry extends AccessibleContext
82 implements Accessible, AccessibleComponent
85 private int columnIndex;
87 private JTableHeader parent;
91 public AccessibleJTableHeaderEntry(int c, JTableHeader p, JTable t)
99 * Returns the column header renderer.
101 * @return The column header renderer.
103 Component getColumnHeaderRenderer()
105 TableColumn tc = parent.getColumnModel().getColumn(columnIndex);
106 TableCellRenderer r = tc.getHeaderRenderer();
108 r = parent.getDefaultRenderer();
109 return r.getTableCellRendererComponent(table, tc.headerValue,
110 false, false, -1, columnIndex);
114 * Returns the accessible context for the column header renderer, or
117 * @return The accessible context.
119 AccessibleContext getAccessibleColumnHeaderRenderer()
121 Component c = getColumnHeaderRenderer();
122 if (c instanceof Accessible)
123 return c.getAccessibleContext();
128 * @see #removeFocusListener(FocusListener)
130 public void addFocusListener(FocusListener l)
132 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
133 AccessibleComponent c = ac.getAccessibleComponent();
135 c.addFocusListener(l);
139 * @see #removePropertyChangeListener(PropertyChangeListener)
141 public void addPropertyChangeListener(PropertyChangeListener l)
143 // add the listener to the accessible context for the header
145 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
147 ac.addPropertyChangeListener(l);
150 public boolean contains(Point p)
152 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
153 AccessibleComponent c = ac.getAccessibleComponent();
155 return c.contains(p);
160 public AccessibleAction getAccessibleAction()
162 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
163 if (ac instanceof AccessibleAction)
164 return (AccessibleAction) ac;
169 public Accessible getAccessibleAt(Point p)
171 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
172 AccessibleComponent c = ac.getAccessibleComponent();
174 return c.getAccessibleAt(p);
180 * Returns <code>null</code> as the header entry has no accessible
183 * @return <code>null</code>.
185 public Accessible getAccessibleChild(int i)
191 * Returns the number of accessible children, zero in this case.
195 public int getAccessibleChildrenCount()
201 * Returns the accessible component for this header entry.
203 * @return <code>this</code>.
205 public AccessibleComponent getAccessibleComponent()
211 * Returns the accessible context for this header entry.
213 * @return <code>this</code>.
215 public AccessibleContext getAccessibleContext()
221 * Returns the accessible description.
223 * @return The accessible description.
225 * @see #setAccessibleDescription(String)
227 public String getAccessibleDescription()
229 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
231 return ac.getAccessibleDescription();
232 return accessibleDescription;
236 * Returns the index of this header entry.
238 * @return The index of this header entry.
240 public int getAccessibleIndexInParent()
246 * Returns the accessible name.
248 * @return The accessible name.
250 * @see #setAccessibleName(String)
252 public String getAccessibleName()
254 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
256 return ac.getAccessibleName();
257 return accessibleName;
261 * Returns the accessible role for the header entry.
263 * @return The accessible role.
265 public AccessibleRole getAccessibleRole()
267 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
269 return ac.getAccessibleRole();
274 public AccessibleSelection getAccessibleSelection()
276 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
277 if (ac instanceof AccessibleValue)
278 return (AccessibleSelection) ac;
283 public AccessibleStateSet getAccessibleStateSet()
285 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
287 return ac.getAccessibleStateSet();
292 public AccessibleText getAccessibleText()
294 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
296 return ac.getAccessibleText();
301 public AccessibleValue getAccessibleValue()
303 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
304 if (ac instanceof AccessibleValue)
305 return (AccessibleValue) ac;
310 public Color getBackground()
312 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
313 AccessibleComponent c = ac.getAccessibleComponent();
315 return c.getBackground();
320 public Rectangle getBounds()
322 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
323 AccessibleComponent c = ac.getAccessibleComponent();
325 return c.getBounds();
330 public Cursor getCursor()
332 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
333 AccessibleComponent c = ac.getAccessibleComponent();
335 return c.getCursor();
340 public Font getFont()
342 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
343 AccessibleComponent c = ac.getAccessibleComponent();
350 public FontMetrics getFontMetrics(Font f)
352 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
353 AccessibleComponent c = ac.getAccessibleComponent();
355 return c.getFontMetrics(f);
360 public Color getForeground()
362 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
363 AccessibleComponent c = ac.getAccessibleComponent();
365 return c.getForeground();
370 public Locale getLocale()
372 Component c = getColumnHeaderRenderer();
374 return c.getLocale();
378 public Point getLocation()
380 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
381 AccessibleComponent c = ac.getAccessibleComponent();
383 return c.getLocation();
388 public Point getLocationOnScreen()
390 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
391 AccessibleComponent c = ac.getAccessibleComponent();
393 return c.getLocationOnScreen();
398 public Dimension getSize()
400 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
401 AccessibleComponent c = ac.getAccessibleComponent();
408 public boolean isEnabled()
410 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
411 AccessibleComponent c = ac.getAccessibleComponent();
413 return c.isEnabled();
418 public boolean isFocusTraversable()
420 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
421 AccessibleComponent c = ac.getAccessibleComponent();
423 return c.isFocusTraversable();
428 public boolean isShowing()
430 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
431 AccessibleComponent c = ac.getAccessibleComponent();
433 return c.isShowing();
438 public boolean isVisible()
440 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
441 AccessibleComponent c = ac.getAccessibleComponent();
443 return c.isVisible();
449 * @see #addFocusListener(FocusListener)
451 public void removeFocusListener(FocusListener l)
453 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
454 AccessibleComponent c = ac.getAccessibleComponent();
456 c.removeFocusListener(l);
460 * @see #addPropertyChangeListener(PropertyChangeListener)
462 public void removePropertyChangeListener(PropertyChangeListener l)
464 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
466 ac.removePropertyChangeListener(l);
470 * @see #addFocusListener(FocusListener)
472 public void requestFocus()
474 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
475 AccessibleComponent c = ac.getAccessibleComponent();
481 * @see #getAccessibleDescription()
483 public void setAccessibleDescription(String s)
485 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
487 ac.setAccessibleDescription(s);
489 accessibleDescription = s;
493 * @see #getAccessibleName()
495 public void setAccessibleName(String s)
497 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
499 ac.setAccessibleName(s);
502 public void setBackground(Color c)
504 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
505 AccessibleComponent comp = ac.getAccessibleComponent();
507 comp.setBackground(c);
510 public void setBounds(Rectangle r)
512 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
513 AccessibleComponent comp = ac.getAccessibleComponent();
518 public void setCursor(Cursor c)
520 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
521 AccessibleComponent comp = ac.getAccessibleComponent();
526 public void setEnabled(boolean b)
528 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
529 AccessibleComponent comp = ac.getAccessibleComponent();
534 public void setFont(Font f)
536 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
537 AccessibleComponent comp = ac.getAccessibleComponent();
542 public void setForeground(Color c)
544 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
545 AccessibleComponent comp = ac.getAccessibleComponent();
547 comp.setForeground(c);
550 public void setLocation(Point p)
552 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
553 AccessibleComponent comp = ac.getAccessibleComponent();
558 public void setSize(Dimension d)
560 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
561 AccessibleComponent comp = ac.getAccessibleComponent();
566 public void setVisible(boolean b)
568 AccessibleContext ac = getAccessibleColumnHeaderRenderer();
569 AccessibleComponent comp = ac.getAccessibleComponent();
575 public AccessibleRole getAccessibleRole()
577 return AccessibleRole.PANEL;
580 public int getAccessibleChildrenCount()
582 return table.getColumnCount();
585 public Accessible getAccessibleChild(int i)
587 return new AccessibleJTableHeaderEntry(i, JTableHeader.this, table);
590 public Accessible getAccessibleAt(Point p)
592 return getAccessibleChild(columnAtPoint(p));
597 * Use serialVersionUid for interoperability.
599 private static final long serialVersionUID = 5144633983372967710L;
602 * The columnModel property.
604 protected TableColumnModel columnModel;
607 * The draggedColumn property.
609 protected TableColumn draggedColumn;
612 * The draggedDistance property.
614 protected int draggedDistance;
617 * The opaque property.
622 * The reorderingAllowed property.
624 protected boolean reorderingAllowed;
627 * The resizingAllowed property.
629 protected boolean resizingAllowed = true;
632 * The resizingColumn property.
634 protected TableColumn resizingColumn;
637 * The table property.
639 protected JTable table;
642 * The updateTableInRealTime property.
644 protected boolean updateTableInRealTime;
646 TableCellRenderer cellRenderer;
649 * Creates a new default instance.
651 public JTableHeader()
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()}.
661 * @param cm the table column model (<code>null</code> permitted).
663 public JTableHeader(TableColumnModel cm)
665 columnModel = cm == null ? createDefaultColumnModel() : cm;
666 initializeLocalVars();
671 * Creates a default table column model.
673 * @return A default table column model.
675 protected TableColumnModel createDefaultColumnModel()
677 return new DefaultTableColumnModel();
681 * Get the value of the {@link #accessibleContext} property.
683 * @return The current value of the property
685 public AccessibleContext getAccessibleContext()
687 return accessibleContext;
691 * Get the value of the {@link #columnModel} property.
693 * @return The current value of the property
695 public TableColumnModel getColumnModel()
701 * Get the column that is currently being dragged. This is used when
702 * handling the column reordering with mouse.
704 * @return the column being dragged, null if none.
706 public TableColumn getDraggedColumn()
708 return draggedColumn;
712 * Get the value of the {@link #draggedDistance} property.
714 * @return The current value of the property
716 public int getDraggedDistance()
718 return draggedDistance;
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)}.
726 * @return true if reordering is allowed, false otherwise.
728 public boolean getReorderingAllowed()
730 return reorderingAllowed;
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)}.
738 * @return true if resizing is allowed, false otherwise.
740 public boolean getResizingAllowed()
742 return resizingAllowed;
746 * Get the column that is currently being resized. This is used when
747 * handling the column resizing with mouse.
749 * @return the column being currently resized, null if none.
751 public TableColumn getResizingColumn()
753 return resizingColumn;
757 * Get the table, having this header.
759 * @return the table, having this header.
761 public JTable getTable()
767 * Get the value of the {@link #updateTableInRealTime} property.
769 * @return The current value of the property
771 public boolean getUpdateTableInRealTime()
773 return updateTableInRealTime;
777 * Get the value of the {@link #opaque} property.
779 * @return The current value of the property
781 public boolean isOpaque()
787 * Set the value of the {@link #columnModel} property.
789 * @param c The new value of the property
791 public void setColumnModel(TableColumnModel c)
793 columnModel.removeColumnModelListener(this);
795 columnModel.addColumnModelListener(this);
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.
803 * @param draggingIt the column being currently dragged, null if none.
805 public void setDraggedColumn(TableColumn draggingIt)
807 draggedColumn = draggingIt;
811 * Set the value of the {@link #draggedDistance} property.
813 * @param d The new value of the property
815 public void setDraggedDistance(int d)
821 * Set the value of the {@link #opaque} property.
823 * @param o The new value of the property
825 public void setOpaque(boolean o)
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.
835 * @param allowed true if reordering is allowed, false otherwise.
837 public void setReorderingAllowed(boolean allowed)
839 reorderingAllowed = allowed;
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.
847 * @param allowed true if resizing is allowed, false otherwise.
849 public void setResizingAllowed(boolean allowed)
851 resizingAllowed = allowed;
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.
859 * @param resizingIt the column being currently resized
861 public void setResizingColumn(TableColumn resizingIt)
863 resizingColumn = resizingIt;
867 * Set the value of the {@link #table} property.
869 * @param t The new value of the property
871 public void setTable(JTable t)
877 * Set the value of the {@link #updateTableInRealTime} property.
879 * @param u The new value of the property
881 public void setUpdateTableInRealTime(boolean u)
883 updateTableInRealTime = u;
887 * Creates a default renderer.
889 * @return A default renderer.
891 protected TableCellRenderer createDefaultRenderer()
893 return new DefaultTableCellRenderer();
897 * Returns the default table cell renderer.
899 * @return The default table cell renderer.
901 public TableCellRenderer getDefaultRenderer()
907 * Sets the default table cell renderer.
909 * @param cellRenderer the renderer.
911 public void setDefaultRenderer(TableCellRenderer cellRenderer)
913 this.cellRenderer = cellRenderer;
917 * Get the rectangle, occupied by the header of the given column.
919 * @param column the column, for that the header area is requested.
921 * @return the column header area.
923 public Rectangle getHeaderRect(int column)
925 Rectangle r = getTable().getCellRect(-1, column, false);
926 r.height = getHeight();
930 protected String paramString()
932 return "JTableHeader";
937 public String getUIClassID()
939 return "TableHeaderUI";
942 public TableHeaderUI getUI()
944 return (TableHeaderUI) ui;
947 public void setUI(TableHeaderUI u)
952 public void updateUI()
954 setUI((TableHeaderUI) UIManager.getUI(this));
958 * Returns the index of the column at the specified point.
960 * @param point the point.
962 * @return The column index, or -1.
964 public int columnAtPoint(Point point)
966 if (getBounds().contains(point))
967 return columnModel.getColumnIndexAtX(point.x);
973 * Receives notification when a column is added to the column model.
975 * @param event the table column model event
977 public void columnAdded(TableColumnModelEvent event)
979 // TODO: What else to do here (if anything)?
984 * Receives notification when a column margin changes in the column model.
986 * @param event the table column model event
988 public void columnMarginChanged(ChangeEvent event)
990 // TODO: What else to do here (if anything)?
995 * Receives notification when a column is moved within the column model.
997 * @param event the table column model event
999 public void columnMoved(TableColumnModelEvent event)
1001 // TODO: What else to do here (if anything)?
1006 * Receives notification when a column is removed from the column model.
1008 * @param event the table column model event
1010 public void columnRemoved(TableColumnModelEvent event)
1012 // TODO: What else to do here (if anything)?
1017 * Receives notification when the column selection has changed.
1019 * @param event the table column model event
1021 public void columnSelectionChanged(ListSelectionEvent event)
1023 // TODO: What else to do here (if anything)?
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>.
1032 public void resizeAndRepaint()
1039 * Initializes the fields and properties of this class with default values.
1040 * This is called by the constructors.
1042 protected void initializeLocalVars()
1044 accessibleContext = new AccessibleJTableHeader();
1045 draggedColumn = null;
1046 draggedDistance = 0;
1048 reorderingAllowed = true;
1049 resizingAllowed = true;
1050 resizingColumn = null;
1052 updateTableInRealTime = true;
1053 cellRenderer = createDefaultRenderer();