/* * @(#)TableColumn.java 1.60 04/05/18 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package javax.swing.table; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.SwingPropertyChangeSupport; import java.lang.Integer; import java.awt.Color; import java.awt.Component; import java.io.Serializable; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** * A TableColumn represents all the attributes of a column in a * JTable, such as width, resizibility, minimum and maximum width. * In addition, the TableColumn provides slots for a renderer and * an editor that can be used to display and edit the values in this column. *

* It is also possible to specify renderers and editors on a per type basis * rather than a per column basis - see the * setDefaultRenderer method in the JTable class. * This default mechanism is only used when the renderer (or * editor) in the TableColumn is null. *

* The TableColumn stores the link between the columns in the * JTable and the columns in the TableModel. * The modelIndex is the column in the * TableModel, which will be queried for the data values for the * cells in this column. As the column moves around in the view this * modelIndex does not change. *

* Note: Some implementations may assume that all * TableColumnModels are unique, therefore we would * recommend that the same TableColumn instance * not be added more than once to a TableColumnModel. * To show TableColumns with the same column of * data from the model, create a new instance with the same * modelIndex. *

* Warning: * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeansTM * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. * * @version 1.60 05/18/04 * @author Alan Chung * @author Philip Milne * @see javax.swing.table.TableColumnModel * * @see javax.swing.table.DefaultTableColumnModel * @see javax.swing.table.JTableHeader#getDefaultRenderer() * @see JTable#getDefaultRenderer(Class) * @see JTable#getDefaultEditor(Class) * @see JTable#getCellRenderer(int, int) * @see JTable#getCellEditor(int, int) */ public class TableColumn extends Object implements Serializable { /** * Obsolete as of Java 2 platform v1.3. Please use string literals to identify * properties. */ /* * Warning: The value of this constant, "columWidth" is wrong as the * name of the property is "columnWidth". */ public final static String COLUMN_WIDTH_PROPERTY = "columWidth"; /** * Obsolete as of Java 2 platform v1.3. Please use string literals to identify * properties. */ public final static String HEADER_VALUE_PROPERTY = "headerValue"; /** * Obsolete as of Java 2 platform v1.3. Please use string literals to identify * properties. */ public final static String HEADER_RENDERER_PROPERTY = "headerRenderer"; /** * Obsolete as of Java 2 platform v1.3. Please use string literals to identify * properties. */ public final static String CELL_RENDERER_PROPERTY = "cellRenderer"; // // Instance Variables // /** * The index of the column in the model which is to be displayed by * this TableColumn. As columns are moved around in the * view modelIndex remains constant. */ protected int modelIndex; /** * This object is not used internally by the drawing machinery of * the JTable; identifiers may be set in the * TableColumn as as an * optional way to tag and locate table columns. The table package does * not modify or invoke any methods in these identifier objects other * than the equals method which is used in the * getColumnIndex() method in the * DefaultTableColumnModel. */ protected Object identifier; /** The width of the column. */ protected int width; /** The minimum width of the column. */ protected int minWidth; /** The preferred width of the column. */ private int preferredWidth; /** The maximum width of the column. */ protected int maxWidth; /** The renderer used to draw the header of the column. */ protected TableCellRenderer headerRenderer; /** The header value of the column. */ protected Object headerValue; /** The renderer used to draw the data cells of the column. */ protected TableCellRenderer cellRenderer; /** The editor used to edit the data cells of the column. */ protected TableCellEditor cellEditor; /** If true, the user is allowed to resize the column; the default is true. */ protected boolean isResizable; /** * This field was not used in previous releases and there are * currently no plans to support it in the future. * * @deprecated as of Java 2 platform v1.3 */ /* * Counter used to disable posting of resizing notifications until the * end of the resize. */ @Deprecated transient protected int resizedPostingDisableCount; /** * If any PropertyChangeListeners have been registered, the * changeSupport field describes them. */ private SwingPropertyChangeSupport changeSupport; // // Constructors // /** * Cover method, using a default model index of 0, * default width of 75, a null renderer and a * null editor. * This method is intended for serialization. * @see #TableColumn(int, int, TableCellRenderer, TableCellEditor) */ public TableColumn() { this(0); } /** * Cover method, using a default width of 75, a null * renderer and a null editor. * @see #TableColumn(int, int, TableCellRenderer, TableCellEditor) */ public TableColumn(int modelIndex) { this(modelIndex, 75, null, null); } /** * Cover method, using a null renderer and a * null editor. * @see #TableColumn(int, int, TableCellRenderer, TableCellEditor) */ public TableColumn(int modelIndex, int width) { this(modelIndex, width, null, null); } /** * Creates and initializes an instance of * TableColumn with modelIndex. * All TableColumn constructors delegate to this one. * The modelIndex is the index of the column * in the model which will supply the data for this column in the table. * The modelIndex does not change as the columns are reordered * in the view. The width parameter is used to set both the * preferredWidth for this * column and the initial width. The renderer and editor are the objects * used respectively to render and edit values in this column. When * these are null, default values, provided by the * getDefaultRenderer * and getDefaultEditor methods in the * JTable class are used to * provide defaults based on the type of the data in this column. * This column-centric rendering strategy can be circumvented by overriding * the getCellRenderer methods in the JTable. *

* * @see JTable#getDefaultRenderer(Class) * @see JTable#getDefaultEditor(Class) * @see JTable#getCellRenderer(int, int) * @see JTable#getCellEditor(int, int) */ public TableColumn(int modelIndex, int width, TableCellRenderer cellRenderer, TableCellEditor cellEditor) { super(); this.modelIndex = modelIndex; this.width = width; this.preferredWidth = width; this.cellRenderer = cellRenderer; this.cellEditor = cellEditor; // Set other instance variables to default values. minWidth = 15; maxWidth = Integer.MAX_VALUE; isResizable = true; resizedPostingDisableCount = 0; headerValue = null; } // // Modifying and Querying attributes // private void firePropertyChange(String propertyName, Object oldValue, Object newValue) { if (changeSupport != null) { changeSupport.firePropertyChange(propertyName, oldValue, newValue); } } private void firePropertyChange(String propertyName, int oldValue, int newValue) { if (oldValue != newValue) { firePropertyChange(propertyName, new Integer(oldValue), new Integer(newValue)); } } private void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { if (oldValue != newValue) { firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); } } /** * Sets the model index for this column. The model index is the * index of the column in the model that will be displayed by this * TableColumn. As the TableColumn * is moved around in the view the model index remains constant. * @param modelIndex the new modelIndex * @beaninfo * bound: true * description: The model index. */ public void setModelIndex(int modelIndex) { int old = this.modelIndex; this.modelIndex = modelIndex; firePropertyChange("modelIndex", old, modelIndex); } /** * Returns the model index for this column. * @return the modelIndex property */ public int getModelIndex() { return modelIndex; } /** * Sets the TableColumn's identifier to * anIdentifier.

* Note: identifiers are not used by the JTable, * they are purely a * convenience for the external tagging and location of columns. * * @param identifier an identifier for this column * @see #getIdentifier * @beaninfo * bound: true * description: A unique identifier for this column. */ public void setIdentifier(Object identifier) { Object old = this.identifier; this.identifier = identifier; firePropertyChange("identifier", old, identifier); } /** * Returns the identifier object for this column. * Note identifiers are not used by JTable, * they are purely a convenience for external use. * If the identifier is null, * getIdentifier() returns getHeaderValue * as a default. * * @return the identifier property * @see #setIdentifier */ public Object getIdentifier() { return (identifier != null) ? identifier : getHeaderValue(); } /** * Sets the Object whose string representation will be * used as the value for the headerRenderer. When the * TableColumn is created, the default headerValue * is null. * @param headerValue the new headerValue * @see #getHeaderValue * @beaninfo * bound: true * description: The text to be used by the header renderer. */ public void setHeaderValue(Object headerValue) { Object old = this.headerValue; this.headerValue = headerValue; firePropertyChange("headerValue", old, headerValue); } /** * Returns the Object used as the value for the header * renderer. * * @return the headerValue property * @see #setHeaderValue */ public Object getHeaderValue() { return headerValue; } // // Renderers and Editors // /** * Sets the TableCellRenderer used to draw the * TableColumn's header to headerRenderer. * * @param headerRenderer the new headerRenderer * * @see #getHeaderRenderer * @beaninfo * bound: true * description: The header renderer. */ public void setHeaderRenderer(TableCellRenderer headerRenderer) { TableCellRenderer old = this.headerRenderer; this.headerRenderer = headerRenderer; firePropertyChange("headerRenderer", old, headerRenderer); } /** * Returns the TableCellRenderer used to draw the header of the * TableColumn. When the headerRenderer is * null, the JTableHeader * uses its defaultRenderer. The default value for a * headerRenderer is null. * * @return the headerRenderer property * @see #setHeaderRenderer * @see #setHeaderValue * @see javax.swing.table.JTableHeader#getDefaultRenderer() */ public TableCellRenderer getHeaderRenderer() { return headerRenderer; } /** * Sets the TableCellRenderer used by JTable * to draw individual values for this column. * * @param cellRenderer the new cellRenderer * @see #getCellRenderer * @beaninfo * bound: true * description: The renderer to use for cell values. */ public void setCellRenderer(TableCellRenderer cellRenderer) { TableCellRenderer old = this.cellRenderer; this.cellRenderer = cellRenderer; firePropertyChange("cellRenderer", old, cellRenderer); } /** * Returns the TableCellRenderer used by the * JTable to draw * values for this column. The cellRenderer of the column * not only controls the visual look for the column, but is also used to * interpret the value object supplied by the TableModel. * When the cellRenderer is null, * the JTable uses a default renderer based on the * class of the cells in that column. The default value for a * cellRenderer is null. * * @return the cellRenderer property * @see #setCellRenderer * @see JTable#setDefaultRenderer */ public TableCellRenderer getCellRenderer() { return cellRenderer; } /** * Sets the editor to used by when a cell in this column is edited. * * @param cellEditor the new cellEditor * @see #getCellEditor * @beaninfo * bound: true * description: The editor to use for cell values. */ public void setCellEditor(TableCellEditor cellEditor){ TableCellEditor old = this.cellEditor; this.cellEditor = cellEditor; firePropertyChange("cellEditor", old, cellEditor); } /** * Returns the TableCellEditor used by the * JTable to edit values for this column. When the * cellEditor is null, the JTable * uses a default editor based on the * class of the cells in that column. The default value for a * cellEditor is null. * * @return the cellEditor property * @see #setCellEditor * @see JTable#setDefaultEditor */ public TableCellEditor getCellEditor() { return cellEditor; } /** * This method should not be used to set the widths of columns in the * JTable, use setPreferredWidth instead. * Like a layout manager in the * AWT, the JTable adjusts a column's width automatically * whenever the * table itself changes size, or a column's preferred width is changed. * Setting widths programmatically therefore has no long term effect. *

* This method sets this column's width to width. * If width exceeds the minimum or maximum width, * it is adjusted to the appropriate limiting value. *

* @param width the new width * @see #getWidth * @see #setMinWidth * @see #setMaxWidth * @see #setPreferredWidth * @see JTable#sizeColumnsToFit(int) * @beaninfo * bound: true * description: The width of the column. */ public void setWidth(int width) { int old = this.width; this.width = Math.min(Math.max(width, minWidth), maxWidth); firePropertyChange("width", old, this.width); } /** * Returns the width of the TableColumn. The default width is * 75. * * @return the width property * @see #setWidth */ public int getWidth() { return width; } /** * Sets this column's preferred width to preferredWidth. * If preferredWidth exceeds the minimum or maximum width, * it is adjusted to the appropriate limiting value. *

* For details on how the widths of columns in the JTable * (and JTableHeader) are calculated from the * preferredWidth, * see the doLayout method in JTable. * * @param preferredWidth the new preferred width * @see #getPreferredWidth * @see JTable#doLayout() * @beaninfo * bound: true * description: The preferred width of the column. */ public void setPreferredWidth(int preferredWidth) { int old = this.preferredWidth; this.preferredWidth = Math.min(Math.max(preferredWidth, minWidth), maxWidth); firePropertyChange("preferredWidth", old, this.preferredWidth); } /** * Returns the preferred width of the TableColumn. * The default preferred width is 75. * * @return the preferredWidth property * @see #setPreferredWidth */ public int getPreferredWidth() { return preferredWidth; } /** * Sets the TableColumn's minimum width to * minWidth; also adjusts the current width * and preferred width if they are less than this value. * * @param minWidth the new minimum width * @see #getMinWidth * @see #setPreferredWidth * @see #setMaxWidth * @beaninfo * bound: true * description: The minimum width of the column. */ public void setMinWidth(int minWidth) { int old = this.minWidth; this.minWidth = Math.max(minWidth, 0); if (width < minWidth) { setWidth(minWidth); } if (preferredWidth < minWidth) { setPreferredWidth(minWidth); } firePropertyChange("minWidth", old, this.minWidth); } /** * Returns the minimum width for the TableColumn. The * TableColumn's width can't be made less than this either * by the user or programmatically. The default minWidth is 15. * * @return the minWidth property * @see #setMinWidth */ public int getMinWidth() { return minWidth; } /** * Sets the TableColumn's maximum width to * maxWidth; also adjusts the width and preferred * width if they are greater than this value. * * @param maxWidth the new maximum width * @see #getMaxWidth * @see #setPreferredWidth * @see #setMinWidth * @beaninfo * bound: true * description: The maximum width of the column. */ public void setMaxWidth(int maxWidth) { int old = this.maxWidth; this.maxWidth = Math.max(minWidth, maxWidth); if (width > maxWidth) { setWidth(maxWidth); } if (preferredWidth > maxWidth) { setPreferredWidth(maxWidth); } firePropertyChange("maxWidth", old, this.maxWidth); } /** * Returns the maximum width for the TableColumn. The * TableColumn's width can't be made larger than this * either by the user or programmatically. The default maxWidth * is Integer.MAX_VALUE. * * @return the maxWidth property * @see #setMaxWidth */ public int getMaxWidth() { return maxWidth; } /** * Sets whether this column can be resized. * * @param isResizable if true, resizing is allowed; otherwise false * @see #getResizable * @beaninfo * bound: true * description: Whether or not this column can be resized. */ public void setResizable(boolean isResizable) { boolean old = this.isResizable; this.isResizable = isResizable; firePropertyChange("isResizable", old, this.isResizable); } /** * Returns true if the user is allowed to resize the * TableColumn's * width, false otherwise. You can change the width programmatically * regardless of this setting. The default is true. * * @return the isResizable property * @see #setResizable */ public boolean getResizable() { return isResizable; } /** * Resizes the TableColumn to fit the width of its header cell. * This method does nothing if the header renderer is null * (the default case). Otherwise, it sets the minimum, maximum and preferred * widths of this column to the widths of the minimum, maximum and preferred * sizes of the Component delivered by the header renderer. * The transient "width" property of this TableColumn is also set to the * preferred width. Note this method is not used internally by the table * package. * * @see #setPreferredWidth */ public void sizeWidthToFit() { if (headerRenderer == null) { return; } Component c = headerRenderer.getTableCellRendererComponent(null, getHeaderValue(), false, false, 0, 0); setMinWidth(c.getMinimumSize().width); setMaxWidth(c.getMaximumSize().width); setPreferredWidth(c.getPreferredSize().width); setWidth(getPreferredWidth()); } /** * This field was not used in previous releases and there are * currently no plans to support it in the future. * * @deprecated as of Java 2 platform v1.3 */ @Deprecated public void disableResizedPosting() { resizedPostingDisableCount++; } /** * This field was not used in previous releases and there are * currently no plans to support it in the future. * * @deprecated as of Java 2 platform v1.3 */ @Deprecated public void enableResizedPosting() { resizedPostingDisableCount--; } // // Property Change Support // /** * Adds a PropertyChangeListener to the listener list. * The listener is registered for all properties. *

* A PropertyChangeEvent will get fired in response to an * explicit call to setFont, setBackground, * or setForeground on the * current component. Note that if the current component is * inheriting its foreground, background, or font from its * container, then no event will be fired in response to a * change in the inherited property. * * @param listener the listener to be added * */ public synchronized void addPropertyChangeListener( PropertyChangeListener listener) { if (changeSupport == null) { changeSupport = new SwingPropertyChangeSupport(this); } changeSupport.addPropertyChangeListener(listener); } /** * Removes a PropertyChangeListener from the listener list. * The PropertyChangeListener to be removed was registered * for all properties. * * @param listener the listener to be removed * */ public synchronized void removePropertyChangeListener( PropertyChangeListener listener) { if (changeSupport != null) { changeSupport.removePropertyChangeListener(listener); } } /** * Returns an array of all the PropertyChangeListeners added * to this TableColumn with addPropertyChangeListener(). * * @return all of the PropertyChangeListeners added or an empty * array if no listeners have been added * @since 1.4 */ public synchronized PropertyChangeListener[] getPropertyChangeListeners() { if (changeSupport == null) { return new PropertyChangeListener[0]; } return changeSupport.getPropertyChangeListeners(); } // // Protected Methods // /** * As of Java 2 platform v1.3, this method is not called by the TableColumn * constructor. Previously this method was used by the * TableColumn to create a default header renderer. * As of Java 2 platform v1.3, the default header renderer is null. * JTableHeader now provides its own shared default * renderer, just as the JTable does for its cell renderers. * * @return the default header renderer * @see javax.swing.table.JTableHeader#createDefaultRenderer() */ protected TableCellRenderer createDefaultHeaderRenderer() { DefaultTableCellRenderer label = new DefaultTableCellRenderer() { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (table != null) { JTableHeader header = table.getTableHeader(); if (header != null) { setForeground(header.getForeground()); setBackground(header.getBackground()); setFont(header.getFont()); } } setText((value == null) ? "" : value.toString()); setBorder(UIManager.getBorder("TableHeader.cellBorder")); return this; } }; label.setHorizontalAlignment(JLabel.CENTER); return label; } } // End of class TableColumn