Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.control; 027 028import java.text.Collator; 029import java.util.Collections; 030import java.util.Comparator; 031 032import javafx.beans.property.BooleanProperty; 033import javafx.beans.property.DoubleProperty; 034import javafx.beans.property.ObjectProperty; 035import javafx.beans.property.SimpleBooleanProperty; 036import javafx.beans.property.SimpleObjectProperty; 037import javafx.beans.property.SimpleStringProperty; 038import javafx.beans.property.StringProperty; 039import javafx.collections.FXCollections; 040import javafx.collections.ObservableList; 041import javafx.collections.ObservableSet; 042import javafx.css.PseudoClass; 043import javafx.css.Styleable; 044import javafx.event.Event; 045import javafx.event.EventDispatchChain; 046import javafx.event.EventHandler; 047import javafx.event.EventTarget; 048import javafx.event.EventType; 049import javafx.scene.Node; 050 051import com.sun.javafx.scene.control.skin.Utils; 052import com.sun.javafx.event.EventHandlerManager; 053import java.util.HashMap; 054 055import javafx.beans.property.ReadOnlyDoubleProperty; 056import javafx.beans.property.ReadOnlyDoubleWrapper; 057import javafx.beans.property.ReadOnlyObjectProperty; 058import javafx.beans.property.ReadOnlyObjectWrapper; 059import javafx.beans.property.SimpleDoubleProperty; 060import javafx.beans.value.ObservableValue; 061import javafx.collections.ObservableMap; 062 063/** 064 * Table-like controls (such as {@link TableView} and {@link TreeTableView}) are 065 * made up of zero or more instances of a concrete TableColumnBase subclass 066 * ({@link TableColumn} and {@link TreeTableColumn}, respectively). Each 067 * table column in a table is responsible for displaying (and editing) the contents 068 * of that column. As well as being responsible for displaying and editing data 069 * for a single column, a table column also contains the necessary properties to: 070 * <ul> 071 * <li>Be resized (using {@link #minWidthProperty() minWidth}/{@link #prefWidthProperty() prefWidth}/{@link #maxWidthProperty() maxWidth} 072 * and {@link #widthProperty() width} properties) 073 * <li>Have its {@link #visibleProperty() visibility} toggled 074 * <li>Display {@link #textProperty() header text} 075 * <li>Display any {@link #getColumns() nested columns} it may contain 076 * <li>Have a {@link #contextMenuProperty() context menu} when the user 077 * right-clicks the column header area 078 * <li>Have the contents of the table be sorted (using 079 * {@link #comparatorProperty() comparator}, {@link #sortable sortable} and 080 * {@link #sortTypeProperty() sortType}) 081 * </ul> 082 * </p> 083 * 084 * When instantiating a concrete subclass of TableColumnBase, perhaps the two 085 * most important properties to set are the column {@link #textProperty() text} 086 * (what to show in the column header area), and the column 087 * {@code cell value factory} (which is used to populate individual cells in the 088 * column). Refer to the class documentation for {@link TableColumn} and 089 * {@link TreeTableColumn} for more information. 090 * 091 * @param <S> The type of the UI control (e.g. the type of the 'row'). 092 * @param <T> The type of the content in all cells in this table column. 093 * @see TableColumn 094 * @see TreeTableColumn 095 * @see TablePositionBase 096 */ 097public abstract class TableColumnBase<S,T> implements EventTarget, Styleable { 098 099 /*************************************************************************** 100 * * 101 * Static properties and methods * 102 * * 103 **************************************************************************/ 104 105 // NOTE: If these numbers change, update the copy of this value in TableColumnHeader 106 static final double DEFAULT_WIDTH = 80.0F; 107 static final double DEFAULT_MIN_WIDTH = 10.0F; 108 static final double DEFAULT_MAX_WIDTH = 5000.0F; 109 110 /** 111 * By default all columns will use this comparator to perform sorting. This 112 * comparator simply performs null checks, and checks if the object is 113 * {@link Comparable}. If it is, the {@link Comparable#compareTo(java.lang.Object)} 114 * method is called, otherwise this method will defer to 115 * {@link Collator#compare(java.lang.String, java.lang.String)}. 116 */ 117 public static final Comparator DEFAULT_COMPARATOR = new Comparator() { 118 @Override public int compare(Object obj1, Object obj2) { 119 if (obj1 == null && obj2 == null) return 0; 120 if (obj1 == null) return -1; 121 if (obj2 == null) return 1; 122 123 if (obj1 instanceof Comparable && (obj1.getClass() == obj2.getClass() || obj1.getClass().isAssignableFrom(obj2.getClass()))) { 124 return ((Comparable)obj1).compareTo(obj2); 125 } 126 127 return Collator.getInstance().compare(obj1.toString(), obj2.toString()); 128 } 129 }; 130 131 132 133 /*************************************************************************** 134 * * 135 * Constructors * 136 * * 137 **************************************************************************/ 138 139 /** 140 * Creates a default TableColumn with default cell factory, comparator, and 141 * onEditCommit implementation. 142 */ 143 protected TableColumnBase() { 144 this(""); 145 } 146 147 /** 148 * Creates a TableColumn with the text set to the provided string, with 149 * default cell factory, comparator, and onEditCommit implementation. 150 * @param text The string to show when the TableColumn is placed within the TableView. 151 */ 152 protected TableColumnBase(String text) { 153 setText(text); 154 } 155 156 157 158 /*************************************************************************** 159 * * 160 * Listeners * 161 * * 162 **************************************************************************/ 163 164 165 166 /*************************************************************************** 167 * * 168 * Instance Variables * 169 * * 170 **************************************************************************/ 171 172 final EventHandlerManager eventHandlerManager = new EventHandlerManager(this); 173 174 175 176 /*************************************************************************** 177 * * 178 * Properties * 179 * * 180 **************************************************************************/ 181 182 183 // --- Text 184 /** 185 * This is the text to show in the header for this column. 186 */ 187 private StringProperty text = new SimpleStringProperty(this, "text", ""); 188 public final StringProperty textProperty() { return text; } 189 public final void setText(String value) { text.set(value); } 190 public final String getText() { return text.get(); } 191 192 193 // --- Visible 194 /** 195 * Toggling this will immediately toggle the visibility of this column, 196 * and all children columns. 197 */ 198 private BooleanProperty visible = new SimpleBooleanProperty(this, "visible", true) { 199 @Override protected void invalidated() { 200 // set all children columns to be the same visibility. This isn't ideal, 201 // for example if a child column is hidden, then the parent hidden and 202 // shown, all columns will be visible again. 203 // 204 // TODO It may make sense for us to cache the visibility so that we may 205 // return to exactly the same state. 206 // set all children columns to be the same visibility. This isn't ideal, 207 // for example if a child column is hidden, then the parent hidden and 208 // shown, all columns will be visible again. 209 // 210 // TODO It may make sense for us to cache the visibility so that we may 211 // return to exactly the same state. 212 for (TableColumnBase<S,?> col : getColumns()) { 213 col.setVisible(isVisible()); 214 } 215 } 216 }; 217 public final void setVisible(boolean value) { visibleProperty().set(value); } 218 public final boolean isVisible() { return visible.get(); } 219 public final BooleanProperty visibleProperty() { return visible; } 220 221 222 // --- Parent Column 223 /** 224 * This read-only property will always refer to the parent of this column, 225 * in the situation where nested columns are being used. To create a nested 226 * column is simply a matter of placing TableColumnBase instances inside the 227 * {@link #columns} ObservableList of a TableColumnBase. 228 */ 229 private ReadOnlyObjectWrapper<TableColumnBase<S,?>> parentColumn; 230 void setParentColumn(TableColumnBase<S,?> value) { parentColumnPropertyImpl().set(value); } 231 public final TableColumnBase<S,?> getParentColumn() { 232 return parentColumn == null ? null : parentColumn.get(); 233 } 234 235 public final ReadOnlyObjectProperty<TableColumnBase<S,?>> parentColumnProperty() { 236 return parentColumnPropertyImpl().getReadOnlyProperty(); 237 } 238 239 private ReadOnlyObjectWrapper<TableColumnBase<S,?>> parentColumnPropertyImpl() { 240 if (parentColumn == null) { 241 parentColumn = new ReadOnlyObjectWrapper<TableColumnBase<S,?>>(this, "parentColumn"); 242 } 243 return parentColumn; 244 } 245 246 247 // --- Menu 248 /** 249 * This menu will be shown whenever the user right clicks within the header 250 * area of this TableColumnBase. 251 */ 252 private ObjectProperty<ContextMenu> contextMenu; 253 public final void setContextMenu(ContextMenu value) { contextMenuProperty().set(value); } 254 public final ContextMenu getContextMenu() { return contextMenu == null ? null : contextMenu.get(); } 255 public final ObjectProperty<ContextMenu> contextMenuProperty() { 256 if (contextMenu == null) { 257 contextMenu = new SimpleObjectProperty<ContextMenu>(this, "contextMenu"); 258 } 259 return contextMenu; 260 } 261 262 263 // --- Id 264 /** 265 * The id of this TableColumnBase. This simple string identifier is useful 266 * for finding a specific TableColumnBase within a UI control that uses 267 * TableColumnBase instances. The default value is {@code null}. 268 * @since 2.2 269 */ 270 private StringProperty id; 271 public final void setId(String value) { idProperty().set(value); } 272 @Override public final String getId() { return id == null ? null : id.get(); } 273 public final StringProperty idProperty() { 274 if (id == null) { 275 id = new SimpleStringProperty(this, "id"); 276 } 277 return id; 278 } 279 280 281 // --- style 282 /** 283 * A string representation of the CSS style associated with this 284 * TableColumnBase instance. This is analogous to the "style" attribute of an 285 * HTML element. Note that, like the HTML style attribute, this 286 * variable contains style properties and values and not the 287 * selector portion of a style rule. 288 * <p> 289 * Parsing this style might not be supported on some limited 290 * platforms. It is recommended to use a standalone CSS file instead. 291 * @since 2.2 292 */ 293 private StringProperty style; 294 public final void setStyle(String value) { styleProperty().set(value); } 295 @Override public final String getStyle() { return style == null ? null : style.get(); } 296 public final StringProperty styleProperty() { 297 if (style == null) { 298 style = new SimpleStringProperty(this, "style"); 299 } 300 return style; 301 } 302 303 304 // --- Style class 305 private final ObservableList<String> styleClass = FXCollections.observableArrayList(); 306 /** 307 * A list of String identifiers which can be used to logically group 308 * Nodes, specifically for an external style engine. This variable is 309 * analogous to the "class" attribute on an HTML element and, as such, 310 * each element of the list is a style class to which this Node belongs. 311 * 312 * @see <a href="http://www.w3.org/TR/css3-selectors/#class-html">CSS3 class selectors</a> 313 * @since 2.2 314 */ 315 @Override public ObservableList<String> getStyleClass() { 316 return styleClass; 317 } 318 319 320 // --- Graphic 321 /** 322 * <p>The graphic to show in the table column to allow the user to 323 * indicate graphically what is in the column. </p> 324 * @since 2.2 325 */ 326 private ObjectProperty<Node> graphic; 327 public final void setGraphic(Node value) { 328 graphicProperty().set(value); 329 } 330 public final Node getGraphic() { 331 return graphic == null ? null : graphic.get(); 332 } 333 public final ObjectProperty<Node> graphicProperty() { 334 if (graphic == null) { 335 graphic = new SimpleObjectProperty<Node>(this, "graphic"); 336 } 337 return graphic; 338 } 339 340 341 // --- Sort node 342 /** 343 * <p>The node to use as the "sort arrow", shown to the user in situations where 344 * the table column is part of the sort order. It may be the only item in 345 * the sort order, or it may be a secondary, tertiary, or latter sort item, 346 * and the node should reflect this visually. This is only used in the case of 347 * the table column being in the sort order (refer to, for example, 348 * {@link TableView#getSortOrder()} and {@link TreeTableView#getSortOrder()}). 349 * If not specified, the table column skin implementation is responsible for 350 * providing a default sort node. 351 * 352 * <p>The sort node is commonly seen represented as a triangle that rotates 353 * on screen to indicate whether the table column is part of the sort order, 354 * and if so, whether the sort is ascending or descending, and what position in 355 * the sort order it is in. 356 * 357 * @since 2.2 358 */ 359 private ObjectProperty<Node> sortNode = new SimpleObjectProperty<Node>(this, "sortNode"); 360 public final void setSortNode(Node value) { sortNodeProperty().set(value); } 361 public final Node getSortNode() { return sortNode.get(); } 362 public final ObjectProperty<Node> sortNodeProperty() { return sortNode; } 363 364 365 // --- Width 366 /** 367 * The width of this column. Modifying this will result in the column width 368 * adjusting visually. It is recommended to not bind this property to an 369 * external property, as that will result in the column width not being 370 * adjustable by the user through dragging the left and right borders of 371 * column headers. 372 */ 373 public final ReadOnlyDoubleProperty widthProperty() { return width.getReadOnlyProperty(); } 374 public final double getWidth() { return width.get(); } 375 void setWidth(double value) { width.set(value); } 376 private ReadOnlyDoubleWrapper width = new ReadOnlyDoubleWrapper(this, "width", DEFAULT_WIDTH); 377 378 379 // --- Minimum Width 380 /** 381 * The minimum width the table column is permitted to be resized to. 382 */ 383 private DoubleProperty minWidth; 384 public final void setMinWidth(double value) { minWidthProperty().set(value); } 385 public final double getMinWidth() { return minWidth == null ? DEFAULT_MIN_WIDTH : minWidth.get(); } 386 public final DoubleProperty minWidthProperty() { 387 if (minWidth == null) { 388 minWidth = new SimpleDoubleProperty(this, "minWidth", DEFAULT_MIN_WIDTH) { 389 @Override protected void invalidated() { 390 if (getMinWidth() < 0) { 391 setMinWidth(0.0F); 392 } 393 394 impl_setWidth(getWidth()); 395 } 396 }; 397 } 398 return minWidth; 399 } 400 401 402 // --- Preferred Width 403 /** 404 * The preferred width of the TableColumn. 405 */ 406 public final DoubleProperty prefWidthProperty() { return prefWidth; } 407 public final void setPrefWidth(double value) { prefWidthProperty().set(value); } 408 public final double getPrefWidth() { return prefWidth.get(); } 409 private final DoubleProperty prefWidth = new SimpleDoubleProperty(this, "prefWidth", DEFAULT_WIDTH) { 410 @Override protected void invalidated() { 411 impl_setWidth(getPrefWidth()); 412 } 413 }; 414 415 416 // --- Maximum Width 417 // The table does not resize properly if this is set to Number.MAX_VALUE, 418 // so I've arbitrarily chosen a better, smaller number. 419 /** 420 * The maximum width the table column is permitted to be resized to. 421 */ 422 public final DoubleProperty maxWidthProperty() { return maxWidth; } 423 public final void setMaxWidth(double value) { maxWidthProperty().set(value); } 424 public final double getMaxWidth() { return maxWidth.get(); } 425 private DoubleProperty maxWidth = new SimpleDoubleProperty(this, "maxWidth", DEFAULT_MAX_WIDTH) { 426 @Override protected void invalidated() { 427 impl_setWidth(getWidth()); 428 } 429 }; 430 431 432 // --- Resizable 433 /** 434 * Used to indicate whether the width of this column can change. It is up 435 * to the resizing policy to enforce this however. 436 */ 437 private BooleanProperty resizable; 438 public final BooleanProperty resizableProperty() { 439 if (resizable == null) { 440 resizable = new SimpleBooleanProperty(this, "resizable", true); 441 } 442 return resizable; 443 } 444 public final void setResizable(boolean value) { 445 resizableProperty().set(value); 446 } 447 public final boolean isResizable() { 448 return resizable == null ? true : resizable.get(); 449 } 450 451 452 453 // --- Sortable 454 /** 455 * <p>A boolean property to toggle on and off the 'sortability' of this column. 456 * When this property is true, this column can be included in sort 457 * operations. If this property is false, it will not be included in sort 458 * operations, even if it is contained within the sort order list of the 459 * underlying UI control (e.g. {@link TableView#getSortOrder()} or 460 * {@link TreeTableView#getSortOrder()}).</p> 461 * 462 * <p>For example, iIf a TableColumn instance is contained within the TableView sortOrder 463 * ObservableList, and its sortable property toggles state, it will force the 464 * TableView to perform a sort, as it is likely the view will need updating.</p> 465 */ 466 private BooleanProperty sortable; 467 public final BooleanProperty sortableProperty() { 468 if (sortable == null) { 469 sortable = new SimpleBooleanProperty(this, "sortable", true); 470 } 471 return sortable; 472 } 473 public final void setSortable(boolean value) { 474 sortableProperty().set(value); 475 } 476 public final boolean isSortable() { 477 return sortable == null ? true : sortable.get(); 478 } 479 480 481 482 // --- Reorderable 483 private BooleanProperty reorderable; 484 /** 485 * @treatAsPrivate implementation detail 486 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 487 */ 488 @Deprecated 489 public final BooleanProperty impl_reorderableProperty() { 490 if (reorderable == null) { 491 reorderable = new SimpleBooleanProperty(this, "reorderable", true); 492 } 493 return reorderable; 494 } 495 /** 496 * @treatAsPrivate implementation detail 497 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 498 */ 499 @Deprecated 500 public final void impl_setReorderable(boolean value) { 501 impl_reorderableProperty().set(value); 502 } 503 /** 504 * @treatAsPrivate implementation detail 505 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 506 */ 507 @Deprecated 508 public final boolean impl_isReorderable() { 509 return reorderable == null ? false : reorderable.get(); 510 } 511 512 513 514 // --- Comparator 515 /** 516 * Comparator function used when sorting this table column. The two Objects 517 * given as arguments are the cell data for two individual cells in this 518 * column. 519 */ 520 private ObjectProperty<Comparator<T>> comparator; 521 public final ObjectProperty<Comparator<T>> comparatorProperty() { 522 if (comparator == null) { 523 comparator = new SimpleObjectProperty<Comparator<T>>(this, "comparator", DEFAULT_COMPARATOR); 524 } 525 return comparator; 526 } 527 public final void setComparator(Comparator<T> value) { 528 comparatorProperty().set(value); 529 } 530 public final Comparator<T> getComparator() { 531 return comparator == null ? DEFAULT_COMPARATOR : comparator.get(); 532 } 533 534 535 // --- Editable 536 /** 537 * Specifies whether this table column allows editing. This, unlike 538 * {@link TableView#editableProperty()} and 539 * {@link TreeTableView#editableProperty()}, is true by default. 540 */ 541 private BooleanProperty editable; 542 public final void setEditable(boolean value) { 543 editableProperty().set(value); 544 } 545 public final boolean isEditable() { 546 return editable == null ? true : editable.get(); 547 } 548 public final BooleanProperty editableProperty() { 549 if (editable == null) { 550 editable = new SimpleBooleanProperty(this, "editable", true); 551 } 552 return editable; 553 } 554 555 556 // --- Properties 557 private static final Object USER_DATA_KEY = new Object(); 558 559 // A map containing a set of properties for this TableColumn 560 private ObservableMap<Object, Object> properties; 561 562 /** 563 * Returns an observable map of properties on this table column for use 564 * primarily by application developers. 565 * 566 * @return an observable map of properties on this table column for use 567 * primarily by application developers 568 * @since 2.2 569 */ 570 public final ObservableMap<Object, Object> getProperties() { 571 if (properties == null) { 572 properties = FXCollections.observableMap(new HashMap<Object, Object>()); 573 } 574 return properties; 575 } 576 577 /** 578 * Tests if this table column has properties. 579 * @return true if node has properties. 580 * @since 2.2 581 */ 582 public boolean hasProperties() { 583 return properties != null && ! properties.isEmpty(); 584 } 585 586 587 // --- UserData 588 /** 589 * Convenience method for setting a single Object property that can be 590 * retrieved at a later date. This is functionally equivalent to calling 591 * the getProperties().put(Object key, Object value) method. This can later 592 * be retrieved by calling {@link TableColumnBase#getUserData()}. 593 * 594 * @param value The value to be stored - this can later be retrieved by calling 595 * {@link TableColumnBase#getUserData()}. 596 * @since 2.2 597 */ 598 public void setUserData(Object value) { 599 getProperties().put(USER_DATA_KEY, value); 600 } 601 602 /** 603 * Returns a previously set Object property, or null if no such property 604 * has been set using the {@link TableColumnBase#setUserData(java.lang.Object)} method. 605 * 606 * @return The Object that was previously set, or null if no property 607 * has been set or if null was set. 608 * @since 2.2 609 */ 610 public Object getUserData() { 611 return getProperties().get(USER_DATA_KEY); 612 } 613 614 615 /*************************************************************************** 616 * * 617 * Public API * 618 * * 619 **************************************************************************/ 620 621 /** 622 * This enables support for nested columns, which can be useful to group 623 * together related data. For example, we may have a 'Name' column with 624 * two nested columns for 'First' and 'Last' names. 625 * 626 * <p>This has no impact on the table as such - all column indices point to the 627 * leaf columns only, and it isn't possible to sort using the parent column, 628 * just the leaf columns. In other words, this is purely a visual feature.</p> 629 * 630 * @return An ObservableList containing TableColumnBase instances (or subclasses) 631 * that are the children of this TableColumnBase. If these children 632 * TableColumnBase instances are set as visible, they will appear 633 * beneath this table column. 634 */ 635 public abstract ObservableList<? extends TableColumnBase<S,?>> getColumns(); 636 637 /** 638 * Returns the actual value for a cell at a given row index (and which 639 * belongs to this table column). 640 * 641 * @param index The row index for which the data is required. 642 * @return The data that belongs to the cell at the intersection of the given 643 * row index and the table column that this method is called on. 644 */ 645 public final T getCellData(final int index) { 646 ObservableValue<T> result = getCellObservableValue(index); 647 return result == null ? null : result.getValue(); 648 } 649 650 /** 651 * Returns the actual value for a cell from the given item. 652 * 653 * @param item The item from which a value of type T should be extracted. 654 * @return The data that should be used in a specific cell in this 655 * column, based on the item passed in as an argument. 656 */ 657 public final T getCellData(final S item) { 658 ObservableValue<T> result = getCellObservableValue(item); 659 return result == null ? null : result.getValue(); 660 } 661 662 /** 663 * Attempts to return an ObservableValue<T> for the item in the given 664 * index (which is of type S). In other words, this method expects to receive 665 * an integer value that is greater than or equal to zero, and less than the 666 * size of the underlying data model. If the index is 667 * valid, this method will return an ObservableValue<T> for this 668 * specific column. 669 * 670 * <p>This is achieved by calling the {@code cell value factory}, and 671 * returning whatever it returns when passed a {@code CellDataFeatures} (see, 672 * for example, the CellDataFeatures classes belonging to 673 * {@link TableColumn.CellDataFeatures TableColumn} and 674 * {@link TreeTableColumn.CellDataFeatures TreeTableColumn} for more 675 * information). 676 * 677 * @param index The index of the item (of type S) for which an 678 * ObservableValue<T> is sought. 679 * @return An ObservableValue<T> for this specific table column. 680 */ 681 public abstract ObservableValue<T> getCellObservableValue(int index); 682 683 /** 684 * Attempts to return an ObservableValue<T> for the given item (which 685 * is of type S). In other words, this method expects to receive an object from 686 * the underlying data model for the entire 'row' in the table, and it must 687 * return an ObservableValue<T> for the value in this specific column. 688 * 689 * <p>This is achieved by calling the {@code cell value factory}, and 690 * returning whatever it returns when passed a {@code CellDataFeatures} (see, 691 * for example, the CellDataFeatures classes belonging to 692 * {@link TableColumn.CellDataFeatures TableColumn} and 693 * {@link TreeTableColumn.CellDataFeatures TreeTableColumn} for more 694 * information). 695 * 696 * @param item The item (of type S) for which an ObservableValue<T> is 697 * sought. 698 * @return An ObservableValue<T> for this specific table column. 699 */ 700 public abstract ObservableValue<T> getCellObservableValue(S item); 701 702 /** {@inheritDoc} */ 703 @Override public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) { 704 return tail.prepend(eventHandlerManager); 705 } 706 707 /** 708 * Registers an event handler to this table column. The TableColumnBase class allows 709 * registration of listeners which will be notified when editing occurs. 710 * Note however that TableColumnBase is <b>not</b> a Node, and therefore no visual 711 * events will be fired on it. 712 * 713 * @param eventType the type of the events to receive by the handler 714 * @param eventHandler the handler to register 715 * @throws NullPointerException if the event type or handler is null 716 */ 717 public <E extends Event> void addEventHandler(EventType<E> eventType, EventHandler<E> eventHandler) { 718 eventHandlerManager.addEventHandler(eventType, eventHandler); 719 } 720 721 /** 722 * Unregisters a previously registered event handler from this table column. One 723 * handler might have been registered for different event types, so the 724 * caller needs to specify the particular event type from which to 725 * unregister the handler. 726 * 727 * @param eventType the event type from which to unregister 728 * @param eventHandler the handler to unregister 729 * @throws NullPointerException if the event type or handler is null 730 */ 731 public <E extends Event> void removeEventHandler(EventType<E> eventType, EventHandler<E> eventHandler) { 732 eventHandlerManager.removeEventHandler(eventType, eventHandler); 733 } 734 735 736 737 /*************************************************************************** 738 * * 739 * Private Implementation * 740 * * 741 **************************************************************************/ 742 743 /** 744 * @treatAsPrivate implementation detail 745 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 746 */ 747 @Deprecated 748 public void impl_setWidth(double width) { 749 setWidth(Utils.boundedSize(width, getMinWidth(), getMaxWidth())); 750 } 751 752 void updateColumnWidths() { 753 if (! getColumns().isEmpty()) { 754 // zero out the width and min width values, and iterate to 755 // ensure the new value is equal to the sum of all children 756 // columns 757 double _minWidth = 0.0f; 758 double _prefWidth = 0.0f; 759 double _maxWidth = 0.0f; 760 761 for (TableColumnBase col : getColumns()) { 762 col.setParentColumn(this); 763 764 _minWidth += col.getMinWidth(); 765 _prefWidth += col.getPrefWidth(); 766 _maxWidth += col.getMaxWidth(); 767 } 768 769 setMinWidth(_minWidth); 770 setPrefWidth(_prefWidth); 771 setMaxWidth(_maxWidth); 772 } 773 } 774 775 776 /*************************************************************************** 777 * * 778 * Stylesheet Handling * 779 * * 780 **************************************************************************/ 781 782 /** 783 * {@inheritDoc} 784 */ 785 public final ObservableSet<PseudoClass> getPseudoClassStates() { 786 return FXCollections.emptyObservableSet(); 787 } 788 789 790 791 /*************************************************************************** 792 * * 793 * Support Interfaces * 794 * * 795 **************************************************************************/ 796 797}