History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/table/JTableHeader.java (1 of 18352 files). Show all

Unified · Split

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