Frames | No Frames |
1: /* TableColumn.java -- 2: Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 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) 9: any later version. 10: 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. 15: 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 19: 02110-1301 USA. 20: 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 24: combination. 25: 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. */ 37: 38: 39: package javax.swing.table; 40: 41: import java.awt.Component; 42: import java.awt.Dimension; 43: import java.beans.PropertyChangeEvent; 44: import java.beans.PropertyChangeListener; 45: import java.io.Serializable; 46: 47: import javax.swing.event.SwingPropertyChangeSupport; 48: 49: /** 50: * Represents the attributes of a column in a table, including the column index, 51: * width, minimum width, preferred width and maximum width. 52: * 53: * @author Andrew Selkirk 54: */ 55: public class TableColumn 56: implements Serializable 57: { 58: static final long serialVersionUID = -6113660025878112608L; 59: 60: /** 61: * The name for the <code>columnWidth</code> property (this field is 62: * obsolete and no longer used). Note also that the typo in the value 63: * string is deliberate, to match the specification. 64: */ 65: public static final String COLUMN_WIDTH_PROPERTY = "columWidth"; 66: 67: /** 68: * The name for the <code>headerValue</code> property. 69: */ 70: public static final String HEADER_VALUE_PROPERTY = "headerValue"; 71: 72: /** 73: * The name for the <code>headerRenderer</code> property. 74: */ 75: public static final String HEADER_RENDERER_PROPERTY = "headerRenderer"; 76: 77: /** 78: * The name for the <code>cellRenderer</code> property. 79: */ 80: public static final String CELL_RENDERER_PROPERTY = "cellRenderer"; 81: 82: /** 83: * The index of the corresponding column in the table model. 84: */ 85: protected int modelIndex; 86: 87: /** 88: * The identifier for the column. 89: */ 90: protected Object identifier; 91: 92: /** 93: * The current width for the column. 94: */ 95: protected int width; 96: 97: /** 98: * The minimum width for the column. 99: */ 100: protected int minWidth = 15; 101: 102: /** 103: * The preferred width for the column. 104: */ 105: private int preferredWidth; 106: 107: /** 108: * The maximum width for the column. 109: */ 110: protected int maxWidth = Integer.MAX_VALUE; 111: 112: /** 113: * The renderer for the column header. 114: */ 115: protected TableCellRenderer headerRenderer; 116: 117: /** 118: * The value for the column header. 119: */ 120: protected Object headerValue; 121: 122: /** 123: * The renderer for the regular cells in this column. 124: */ 125: protected TableCellRenderer cellRenderer; 126: 127: /** 128: * An editor for the regular cells in this column. 129: */ 130: protected TableCellEditor cellEditor; 131: 132: /** 133: * A flag that determines whether or not the column is resizable (the default 134: * is <code>true</code>). 135: */ 136: protected boolean isResizable = true; 137: 138: /** 139: * resizedPostingDisableCount 140: * 141: * @deprecated 1.3 142: */ 143: protected transient int resizedPostingDisableCount; 144: 145: /** 146: * A storage and notification mechanism for property change listeners. 147: */ 148: private SwingPropertyChangeSupport changeSupport = 149: new SwingPropertyChangeSupport(this); 150: 151: /** 152: * Creates a new <code>TableColumn</code> that maps to column 0 in the 153: * related table model. The default width is <code>75</code> units. 154: */ 155: public TableColumn() 156: { 157: this(0, 75, null, null); 158: } 159: 160: /** 161: * Creates a new <code>TableColumn</code> that maps to the specified column 162: * in the related table model. The default width is <code>75</code> units. 163: * 164: * @param modelIndex the index of the column in the model 165: */ 166: public TableColumn(int modelIndex) 167: { 168: this(modelIndex, 75, null, null); 169: } 170: 171: /** 172: * Creates a new <code>TableColumn</code> that maps to the specified column 173: * in the related table model, and has the specified <code>width</code>. 174: * 175: * @param modelIndex the index of the column in the model 176: * @param width the width 177: */ 178: public TableColumn(int modelIndex, int width) 179: { 180: this(modelIndex, width, null, null); 181: } 182: 183: /** 184: * Creates a new <code>TableColumn</code> that maps to the specified column 185: * in the related table model, and has the specified <code>width</code>, 186: * <code>cellRenderer</code> and <code>cellEditor</code>. 187: * 188: * @param modelIndex the index of the column in the model 189: * @param width the width 190: * @param cellRenderer the cell renderer (<code>null</code> permitted). 191: * @param cellEditor the cell editor (<code>null</code> permitted). 192: */ 193: public TableColumn(int modelIndex, int width, 194: TableCellRenderer cellRenderer, TableCellEditor cellEditor) 195: { 196: this.modelIndex = modelIndex; 197: this.width = width; 198: this.preferredWidth = width; 199: this.cellRenderer = cellRenderer; 200: this.cellEditor = cellEditor; 201: this.headerValue = null; 202: this.identifier = null; 203: } 204: 205: /** 206: * Sets the index of the column in the related {@link TableModel} that this 207: * <code>TableColumn</code> maps to, and sends a {@link PropertyChangeEvent} 208: * (with the property name 'modelIndex') to all registered listeners. 209: * 210: * @param modelIndex the column index in the model. 211: * 212: * @see #getModelIndex() 213: */ 214: public void setModelIndex(int modelIndex) 215: { 216: if (this.modelIndex != modelIndex) 217: { 218: int oldValue = this.modelIndex; 219: this.modelIndex = modelIndex; 220: changeSupport.firePropertyChange("modelIndex", oldValue, modelIndex); 221: } 222: } 223: 224: /** 225: * Returns the index of the column in the related {@link TableModel} that 226: * this <code>TableColumn</code> maps to. 227: * 228: * @return the model index. 229: * 230: * @see #setModelIndex(int) 231: */ 232: public int getModelIndex() 233: { 234: return modelIndex; 235: } 236: 237: /** 238: * Sets the identifier for the column and sends a {@link PropertyChangeEvent} 239: * (with the property name 'identifier') to all registered listeners. 240: * 241: * @param identifier the identifier (<code>null</code> permitted). 242: * 243: * @see #getIdentifier() 244: */ 245: public void setIdentifier(Object identifier) 246: { 247: if (this.identifier != identifier) 248: { 249: Object oldValue = this.identifier; 250: this.identifier = identifier; 251: changeSupport.firePropertyChange("identifier", oldValue, identifier); 252: } 253: } 254: 255: /** 256: * Returns the identifier for the column, or {@link #getHeaderValue()} if the 257: * identifier is <code>null</code>. 258: * 259: * @return The identifier (or {@link #getHeaderValue()} if the identifier is 260: * <code>null</code>). 261: */ 262: public Object getIdentifier() 263: { 264: if (identifier == null) 265: return getHeaderValue(); 266: return identifier; 267: } 268: 269: /** 270: * Sets the header value and sends a {@link PropertyChangeEvent} (with the 271: * property name {@link #HEADER_VALUE_PROPERTY}) to all registered listeners. 272: * 273: * @param headerValue the value of the header (<code>null</code> permitted). 274: * 275: * @see #getHeaderValue() 276: */ 277: public void setHeaderValue(Object headerValue) 278: { 279: if (this.headerValue == headerValue) 280: return; 281: 282: Object oldValue = this.headerValue; 283: this.headerValue = headerValue; 284: changeSupport.firePropertyChange(HEADER_VALUE_PROPERTY, oldValue, 285: headerValue); 286: } 287: 288: /** 289: * Returns the header value. 290: * 291: * @return the value of the header. 292: * 293: * @see #getHeaderValue() 294: */ 295: public Object getHeaderValue() 296: { 297: return headerValue; 298: } 299: 300: /** 301: * Sets the renderer for the column header and sends a 302: * {@link PropertyChangeEvent} (with the property name 303: * {@link #HEADER_RENDERER_PROPERTY}) to all registered listeners. 304: * 305: * @param renderer the header renderer (<code>null</code> permitted). 306: * 307: * @see #getHeaderRenderer() 308: */ 309: public void setHeaderRenderer(TableCellRenderer renderer) 310: { 311: if (headerRenderer == renderer) 312: return; 313: 314: TableCellRenderer oldRenderer = headerRenderer; 315: headerRenderer = renderer; 316: changeSupport.firePropertyChange(HEADER_RENDERER_PROPERTY, oldRenderer, 317: headerRenderer); 318: } 319: 320: /** 321: * Returns the renderer for the column header. 322: * 323: * @return The renderer for the column header (possibly <code>null</code>). 324: * 325: * @see #setHeaderRenderer(TableCellRenderer) 326: */ 327: public TableCellRenderer getHeaderRenderer() 328: { 329: return headerRenderer; 330: } 331: 332: /** 333: * Sets the renderer for cells in this column and sends a 334: * {@link PropertyChangeEvent} (with the property name 335: * {@link #CELL_RENDERER_PROPERTY}) to all registered listeners. 336: * 337: * @param renderer the cell renderer (<code>null</code> permitted). 338: * 339: * @see #getCellRenderer() 340: */ 341: public void setCellRenderer(TableCellRenderer renderer) 342: { 343: if (cellRenderer == renderer) 344: return; 345: 346: TableCellRenderer oldRenderer = cellRenderer; 347: cellRenderer = renderer; 348: changeSupport.firePropertyChange(CELL_RENDERER_PROPERTY, oldRenderer, 349: cellRenderer); 350: } 351: 352: /** 353: * Returns the renderer for the table cells in this column. 354: * 355: * @return The cell renderer (possibly <code>null</code>). 356: * 357: * @see #setCellRenderer(TableCellRenderer) 358: */ 359: public TableCellRenderer getCellRenderer() 360: { 361: return cellRenderer; 362: } 363: 364: /** 365: * Sets the cell editor for the column and sends a {@link PropertyChangeEvent} 366: * (with the property name 'cellEditor') to all registered listeners. 367: * 368: * @param cellEditor the cell editor (<code>null</code> permitted). 369: * 370: * @see #getCellEditor() 371: */ 372: public void setCellEditor(TableCellEditor cellEditor) 373: { 374: if (this.cellEditor != cellEditor) 375: { 376: TableCellEditor oldValue = this.cellEditor; 377: this.cellEditor = cellEditor; 378: changeSupport.firePropertyChange("cellEditor", oldValue, cellEditor); 379: } 380: } 381: 382: /** 383: * Returns the cell editor for the column (the default value is 384: * <code>null</code>). 385: * 386: * @return The cell editor (possibly <code>null</code>). 387: * 388: * @see #setCellEditor(TableCellEditor) 389: */ 390: public TableCellEditor getCellEditor() 391: { 392: return cellEditor; 393: } 394: 395: /** 396: * Sets the width for the column and sends a {@link PropertyChangeEvent} 397: * (with the property name 'width') to all registered listeners. If the new 398: * width falls outside the range getMinWidth() to getMaxWidth() it is 399: * adjusted to the appropriate boundary value. 400: * 401: * @param newWidth the width. 402: * 403: * @see #getWidth() 404: */ 405: public void setWidth(int newWidth) 406: { 407: int oldWidth = width; 408: 409: if (newWidth < minWidth) 410: width = minWidth; 411: else if (newWidth > maxWidth) 412: width = maxWidth; 413: else 414: width = newWidth; 415: 416: if (width == oldWidth) 417: return; 418: 419: // We do have a constant field COLUMN_WIDTH_PROPERTY, 420: // however, tests show that the actual fired property name is 'width' 421: // and even Sun's API docs say that this constant field is obsolete and 422: // not used. 423: changeSupport.firePropertyChange("width", oldWidth, width); 424: } 425: 426: /** 427: * Returns the width for the column (the default value is <code>75</code>). 428: * 429: * @return The width. 430: * 431: * @see #setWidth(int) 432: */ 433: public int getWidth() 434: { 435: return width; 436: } 437: 438: /** 439: * Sets the preferred width for the column and sends a 440: * {@link PropertyChangeEvent} (with the property name 'preferredWidth') to 441: * all registered listeners. If necessary, the supplied value will be 442: * adjusted to fit in the range {@link #getMinWidth()} to 443: * {@link #getMaxWidth()}. 444: * 445: * @param preferredWidth the preferred width. 446: * 447: * @see #getPreferredWidth() 448: */ 449: public void setPreferredWidth(int preferredWidth) 450: { 451: int oldPrefWidth = this.preferredWidth; 452: 453: if (preferredWidth < minWidth) 454: this.preferredWidth = minWidth; 455: else if (preferredWidth > maxWidth) 456: this.preferredWidth = maxWidth; 457: else 458: this.preferredWidth = preferredWidth; 459: 460: changeSupport.firePropertyChange("preferredWidth", oldPrefWidth, 461: this.preferredWidth); 462: } 463: 464: /** 465: * Returns the preferred width for the column (the default value is 466: * <code>75</code>). 467: * 468: * @return The preferred width. 469: * 470: * @see #setPreferredWidth(int) 471: */ 472: public int getPreferredWidth() 473: { 474: return preferredWidth; 475: } 476: 477: /** 478: * Sets the minimum width for the column and sends a 479: * {@link PropertyChangeEvent} (with the property name 'minWidth') to all 480: * registered listeners. If the current <code>width</code> and/or 481: * <code>preferredWidth</code> are less than the new minimum width, they are 482: * adjusted accordingly. 483: * 484: * @param minWidth the minimum width (negative values are treated as 0). 485: * 486: * @see #getMinWidth() 487: */ 488: public void setMinWidth(int minWidth) 489: { 490: if (minWidth < 0) 491: minWidth = 0; 492: if (this.minWidth != minWidth) 493: { 494: if (width < minWidth) 495: setWidth(minWidth); 496: if (preferredWidth < minWidth) 497: setPreferredWidth(minWidth); 498: int oldValue = this.minWidth; 499: this.minWidth = minWidth; 500: changeSupport.firePropertyChange("minWidth", oldValue, minWidth); 501: } 502: } 503: 504: /** 505: * Returns the <code>TableColumn</code>'s minimum width (the default value 506: * is <code>15</code>). 507: * 508: * @return The minimum width. 509: * 510: * @see #setMinWidth(int) 511: */ 512: public int getMinWidth() 513: { 514: return minWidth; 515: } 516: 517: /** 518: * Sets the maximum width for the column and sends a 519: * {@link PropertyChangeEvent} (with the property name 'maxWidth') to all 520: * registered listeners. If the current <code>width</code> and/or 521: * <code>preferredWidth</code> are greater than the new maximum width, they 522: * are adjusted accordingly. 523: * 524: * @param maxWidth the maximum width. 525: * 526: * @see #getMaxWidth() 527: */ 528: public void setMaxWidth(int maxWidth) 529: { 530: if (this.maxWidth != maxWidth) 531: { 532: if (width > maxWidth) 533: setWidth(maxWidth); 534: if (preferredWidth > maxWidth) 535: setPreferredWidth(maxWidth); 536: int oldValue = this.maxWidth; 537: this.maxWidth = maxWidth; 538: changeSupport.firePropertyChange("maxWidth", oldValue, maxWidth); 539: } 540: } 541: 542: /** 543: * Returns the maximum width for the column (the default value is 544: * {@link Integer#MAX_VALUE}). 545: * 546: * @return The maximum width for the column. 547: * 548: * @see #setMaxWidth(int) 549: */ 550: public int getMaxWidth() 551: { 552: return maxWidth; 553: } 554: 555: /** 556: * Sets the flag that controls whether or not the column is resizable, and 557: * sends a {@link PropertyChangeEvent} (with the property name 'isResizable') 558: * to all registered listeners. 559: * 560: * @param isResizable <code>true</code> if this column is resizable, 561: * <code>false</code> otherwise. 562: * 563: * @see #getResizable() 564: */ 565: public void setResizable(boolean isResizable) 566: { 567: if (this.isResizable != isResizable) 568: { 569: this.isResizable = isResizable; 570: changeSupport.firePropertyChange("isResizable", !this.isResizable, 571: isResizable); 572: } 573: } 574: 575: /** 576: * Returns the flag that controls whether or not the column is resizable. 577: * 578: * @return <code>true</code> if this column is resizable, 579: * <code>false</code> otherwise. 580: * 581: * @see #setResizable(boolean) 582: */ 583: public boolean getResizable() 584: { 585: return isResizable; 586: } 587: 588: /** 589: * Sets the minimum, maximum, preferred and current width to match the 590: * minimum, maximum and preferred width of the header renderer component. 591: * If there is no header renderer component, this method does nothing. 592: */ 593: public void sizeWidthToFit() 594: { 595: if (headerRenderer == null) 596: return; 597: Component c = headerRenderer.getTableCellRendererComponent(null, 598: getHeaderValue(), false, false, 0, 0); 599: Dimension min = c.getMinimumSize(); 600: Dimension max = c.getMaximumSize(); 601: Dimension pref = c.getPreferredSize(); 602: setMinWidth(min.width); 603: setMaxWidth(max.width); 604: setPreferredWidth(pref.width); 605: setWidth(pref.width); 606: } 607: 608: /** 609: * This method is empty, unused and deprecated. 610: * @deprecated 1.3 611: */ 612: public void disableResizedPosting() 613: { 614: // Does nothing 615: } 616: 617: /** 618: * This method is empty, unused and deprecated. 619: * @deprecated 1.3 620: */ 621: public void enableResizedPosting() 622: { 623: // Does nothing 624: } 625: 626: /** 627: * Adds a listener so that it receives {@link PropertyChangeEvent} 628: * notifications from this column. The properties defined by the column are: 629: * <ul> 630: * <li><code>width</code> - see {@link #setWidth(int)};</li> 631: * <li><code>preferredWidth</code> - see {@link #setPreferredWidth(int)};</li> 632: * <li><code>minWidth</code> - see {@link #setMinWidth(int)};</li> 633: * <li><code>maxWidth</code> - see {@link #setMaxWidth(int)};</li> 634: * <li><code>modelIndex</code> - see {@link #setModelIndex(int)};</li> 635: * <li><code>isResizable</code> - see {@link #setResizable(boolean)};</li> 636: * <li><code>cellRenderer</code> - see 637: * {@link #setCellRenderer(TableCellRenderer)};</li> 638: * <li><code>cellEditor</code> - see 639: * {@link #setCellEditor(TableCellEditor)};</li> 640: * <li><code>headerRenderer</code> - see 641: * {@link #setHeaderRenderer(TableCellRenderer)};</li> 642: * <li><code>headerValue</code> - see {@link #setHeaderValue(Object)};</li> 643: * <li><code>identifier</code> - see {@link #setIdentifier(Object)}.</li> 644: * </ul> 645: * 646: * @param listener the listener to add (<code>null</code> is ignored). 647: * 648: * @see #removePropertyChangeListener(PropertyChangeListener) 649: */ 650: public synchronized void addPropertyChangeListener( 651: PropertyChangeListener listener) 652: { 653: changeSupport.addPropertyChangeListener(listener); 654: } 655: 656: /** 657: * Removes a listener so that it no longer receives 658: * {@link PropertyChangeEvent} notifications from this column. If 659: * <code>listener</code> is not registered with the column, or is 660: * <code>null</code>, this method does nothing. 661: * 662: * @param listener the listener to remove (<code>null</code> is ignored). 663: */ 664: public synchronized void removePropertyChangeListener( 665: PropertyChangeListener listener) 666: { 667: changeSupport.removePropertyChangeListener(listener); 668: } 669: 670: /** 671: * Returns the property change listeners for this <code>TableColumn</code>. 672: * An empty array is returned if there are currently no listeners registered. 673: * 674: * @return The property change listeners registered with this column. 675: * 676: * @since 1.4 677: */ 678: public PropertyChangeListener[] getPropertyChangeListeners() 679: { 680: return changeSupport.getPropertyChangeListeners(); 681: } 682: 683: /** 684: * Creates and returns a default renderer for the column header (in this case, 685: * a new instance of {@link DefaultTableCellRenderer}). 686: * 687: * @return A default renderer for the column header. 688: */ 689: protected TableCellRenderer createDefaultHeaderRenderer() 690: { 691: return new DefaultTableCellRenderer(); 692: } 693: }