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 */ TableColumn()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 */ TableColumn(int modelIndex)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 */ TableColumn(int modelIndex, int width)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 */ TableColumn(int modelIndex, int width, TableCellRenderer cellRenderer, TableCellEditor cellEditor)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 */ setModelIndex(int modelIndex)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 */ getModelIndex()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 */ setIdentifier(Object identifier)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 */ getIdentifier()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 */ setHeaderValue(Object headerValue)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 */ getHeaderValue()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 */ setHeaderRenderer(TableCellRenderer renderer)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 */ getHeaderRenderer()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 */ setCellRenderer(TableCellRenderer renderer)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 */ getCellRenderer()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 */ setCellEditor(TableCellEditor cellEditor)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 */ getCellEditor()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 */ setWidth(int newWidth)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 */ getWidth()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 */ setPreferredWidth(int preferredWidth)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 */ getPreferredWidth()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 */ setMinWidth(int minWidth)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 */ getMinWidth()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 */ setMaxWidth(int maxWidth)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 */ getMaxWidth()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 */ setResizable(boolean isResizable)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 */ getResizable()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 */ sizeWidthToFit()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 */ disableResizedPosting()612 public void disableResizedPosting() 613 { 614 // Does nothing 615 } 616 617 /** 618 * This method is empty, unused and deprecated. 619 * @deprecated 1.3 620 */ enableResizedPosting()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 */ addPropertyChangeListener( PropertyChangeListener listener)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 */ removePropertyChangeListener( PropertyChangeListener listener)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 */ getPropertyChangeListeners()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 */ createDefaultHeaderRenderer()689 protected TableCellRenderer createDefaultHeaderRenderer() 690 { 691 return new DefaultTableCellRenderer(); 692 } 693 } 694