192 * @see TreeItem 193 * @see TreeCell 194 * @param <T> The type of the item contained within the {@link TreeItem} value 195 * property for all tree items in this TreeView. 196 * @since JavaFX 2.0 197 */ 198 @DefaultProperty("root") 199 public class TreeView<T> extends Control { 200 201 /*************************************************************************** 202 * * 203 * Static properties and methods * 204 * * 205 **************************************************************************/ 206 207 /** 208 * An EventType that indicates some edit event has occurred. It is the parent 209 * type of all other edit events: {@link #editStartEvent}, 210 * {@link #editCommitEvent} and {@link #editCancelEvent}. 211 * 212 * @return An EventType that indicates some edit event has occurred. 213 */ 214 @SuppressWarnings("unchecked") 215 public static <T> EventType<EditEvent<T>> editAnyEvent() { 216 return (EventType<EditEvent<T>>) EDIT_ANY_EVENT; 217 } 218 private static final EventType<?> EDIT_ANY_EVENT = 219 new EventType<>(Event.ANY, "TREE_VIEW_EDIT"); 220 221 /** 222 * An EventType used to indicate that an edit event has started within the 223 * TreeView upon which the event was fired. 224 * 225 * @return An EventType used to indicate that an edit event has started. 226 */ 227 @SuppressWarnings("unchecked") 228 public static <T> EventType<EditEvent<T>> editStartEvent() { 229 return (EventType<EditEvent<T>>) EDIT_START_EVENT; 230 } 231 private static final EventType<?> EDIT_START_EVENT = 232 new EventType<>(editAnyEvent(), "EDIT_START"); 233 234 /** 235 * An EventType used to indicate that an edit event has just been canceled 236 * within the TreeView upon which the event was fired. 237 * 238 * @return An EventType used to indicate that an edit event has just been 239 * canceled. 240 */ 241 @SuppressWarnings("unchecked") 242 public static <T> EventType<EditEvent<T>> editCancelEvent() { 243 return (EventType<EditEvent<T>>) EDIT_CANCEL_EVENT; 244 } 245 private static final EventType<?> EDIT_CANCEL_EVENT = 246 new EventType<>(editAnyEvent(), "EDIT_CANCEL"); 247 248 /** 249 * An EventType that is used to indicate that an edit in a TreeView has been 250 * committed. This means that user has made changes to the data of a 251 * TreeItem, and that the UI should be updated. 252 * 253 * @return An EventType that is used to indicate that an edit in a TreeView 254 * has been committed. 255 */ 256 @SuppressWarnings("unchecked") 257 public static <T> EventType<EditEvent<T>> editCommitEvent() { 258 return (EventType<EditEvent<T>>) EDIT_COMMIT_EVENT; 259 } 260 private static final EventType<?> EDIT_COMMIT_EVENT = 261 new EventType<>(editAnyEvent(), "EDIT_COMMIT"); 262 263 /** 264 * Returns the number of levels of 'indentation' of the given TreeItem, 265 * based on how many times {@link javafx.scene.control.TreeItem#getParent()} 266 * can be recursively called. If the TreeItem does not have any parent set, 267 * the returned value will be zero. For each time getParent() is recursively 268 * called, the returned value is incremented by one. 269 * 270 * <p><strong>Important note: </strong>This method is deprecated as it does 271 * not consider the root node. This means that this method will iterate 272 * past the root node of the TreeView control, if the root node has a parent. 399 * which are used to represent items in the 400 * TreeView. The factory works identically to the cellFactory in ListView 401 * and other complex composite controls. It is called to create a new 402 * TreeCell only when the system has determined that it doesn't have enough 403 * cells to represent the currently visible items. The TreeCell is reused 404 * by the system to represent different items in the tree when possible. 405 * 406 * <p>Refer to the {@link Cell} class documentation for more details. 407 * 408 * @param value The {@link Callback} to use for generating TreeCell instances, 409 * or null if the default cell factory should be used. 410 */ 411 public final void setCellFactory(Callback<TreeView<T>, TreeCell<T>> value) { 412 cellFactoryProperty().set(value); 413 } 414 415 /** 416 * <p>Returns the cell factory that will be used for creating TreeCells, 417 * which are used to represent items in the TreeView, or null if no custom 418 * cell factory has been set. 419 */ 420 public final Callback<TreeView<T>, TreeCell<T>> getCellFactory() { 421 return cellFactory == null ? null : cellFactory.get(); 422 } 423 424 /** 425 * Represents the cell factory that will be used for creating TreeCells, 426 * which are used to represent items in the TreeView. 427 */ 428 public final ObjectProperty<Callback<TreeView<T>, TreeCell<T>>> cellFactoryProperty() { 429 if (cellFactory == null) { 430 cellFactory = new SimpleObjectProperty<Callback<TreeView<T>, TreeCell<T>>>(this, "cellFactory"); 431 } 432 return cellFactory; 433 } 434 435 436 // --- Root 437 private ObjectProperty<TreeItem<T>> root = new SimpleObjectProperty<TreeItem<T>>(this, "root") { 438 private WeakReference<TreeItem<T>> weakOldItem; 439 440 @Override protected void invalidated() { 441 TreeItem<T> oldTreeItem = weakOldItem == null ? null : weakOldItem.get(); 442 if (oldTreeItem != null && weakRootEventListener != null) { 443 oldTreeItem.removeEventHandler(TreeItem.<T>treeNotificationEvent(), weakRootEventListener); 444 } 445 446 TreeItem<T> root = getRoot(); 463 * documentation for more details. 464 * 465 * @param value The {@link TreeItem} that will be placed at the root of the 466 * TreeView. 467 */ 468 public final void setRoot(TreeItem<T> value) { 469 rootProperty().set(value); 470 } 471 472 /** 473 * Returns the current root node of this TreeView, or null if no root node 474 * is specified. 475 * @return The current root node, or null if no root node exists. 476 */ 477 public final TreeItem<T> getRoot() { 478 return root == null ? null : root.get(); 479 } 480 481 /** 482 * Property representing the root node of the TreeView. 483 */ 484 public final ObjectProperty<TreeItem<T>> rootProperty() { 485 return root; 486 } 487 488 489 490 // --- Show Root 491 private BooleanProperty showRoot; 492 493 /** 494 * Specifies whether the root {@code TreeItem} should be shown within this 495 * TreeView. 496 * 497 * @param value If true, the root TreeItem will be shown, and if false it 498 * will be hidden. 499 */ 500 public final void setShowRoot(boolean value) { 501 showRootProperty().set(value); 502 } 503 504 /** 505 * Returns true if the root of the TreeView should be shown, and false if 506 * it should not. By default, the root TreeItem is visible in the TreeView. 507 */ 508 public final boolean isShowRoot() { 509 return showRoot == null ? true : showRoot.get(); 510 } 511 512 /** 513 * Property that represents whether or not the TreeView root node is visible. 514 */ 515 public final BooleanProperty showRootProperty() { 516 if (showRoot == null) { 517 showRoot = new SimpleBooleanProperty(this, "showRoot", true) { 518 @Override protected void invalidated() { 519 updateRootExpanded(); 520 updateExpandedItemCount(getRoot()); 521 } 522 }; 523 } 524 return showRoot; 525 } 526 527 528 // --- Selection Model 529 private ObjectProperty<MultipleSelectionModel<TreeItem<T>>> selectionModel; 530 531 /** 532 * Sets the {@link MultipleSelectionModel} to be used in the TreeView. 533 * Despite a TreeView requiring a <code><b>Multiple</b>SelectionModel</code>, 534 * it is possible to configure it to only allow single selection (see 535 * {@link MultipleSelectionModel#setSelectionMode(javafx.scene.control.SelectionMode)} 536 * for more information). 537 */ 538 public final void setSelectionModel(MultipleSelectionModel<TreeItem<T>> value) { 539 selectionModelProperty().set(value); 540 } 541 542 /** 543 * Returns the currently installed selection model. 544 */ 545 public final MultipleSelectionModel<TreeItem<T>> getSelectionModel() { 546 return selectionModel == null ? null : selectionModel.get(); 547 } 548 549 /** 550 * The SelectionModel provides the API through which it is possible 551 * to select single or multiple items within a TreeView, as well as inspect 552 * which rows have been selected by the user. Note that it has a generic 553 * type that must match the type of the TreeView itself. 554 */ 555 public final ObjectProperty<MultipleSelectionModel<TreeItem<T>>> selectionModelProperty() { 556 if (selectionModel == null) { 557 selectionModel = new SimpleObjectProperty<MultipleSelectionModel<TreeItem<T>>>(this, "selectionModel"); 558 } 559 return selectionModel; 560 } 561 562 563 // --- Focus Model 564 private ObjectProperty<FocusModel<TreeItem<T>>> focusModel; 565 566 /** 567 * Sets the {@link FocusModel} to be used in the TreeView. 568 */ 569 public final void setFocusModel(FocusModel<TreeItem<T>> value) { 570 focusModelProperty().set(value); 571 } 572 573 /** 574 * Returns the currently installed {@link FocusModel}. 575 */ 576 public final FocusModel<TreeItem<T>> getFocusModel() { 577 return focusModel == null ? null : focusModel.get(); 578 } 579 580 /** 581 * The FocusModel provides the API through which it is possible 582 * to control focus on zero or one rows of the TreeView. Generally the 583 * default implementation should be more than sufficient. 584 */ 585 public final ObjectProperty<FocusModel<TreeItem<T>>> focusModelProperty() { 586 if (focusModel == null) { 587 focusModel = new SimpleObjectProperty<FocusModel<TreeItem<T>>>(this, "focusModel"); 588 } 589 return focusModel; 590 } 591 592 593 // --- Expanded node count 594 /** 595 * <p>Represents the number of tree nodes presently able to be visible in the 596 * TreeView. This is essentially the count of all expanded tree items, and 597 * their children. 598 * 599 * <p>For example, if just the root node is visible, the expandedItemCount will 600 * be one. If the root had three children and the root was expanded, the value 601 * will be four. 602 * @since JavaFX 8.0 603 */ 647 } 648 /** 649 * Specifies whether this control has cells that are a fixed height (of the 650 * specified value). If this value is less than or equal to zero, 651 * then all cells are individually sized and positioned. This is a slow 652 * operation. Therefore, when performance matters and developers are not 653 * dependent on variable cell sizes it is a good idea to set the fixed cell 654 * size value. Generally cells are around 24px, so setting a fixed cell size 655 * of 24 is likely to result in very little difference in visuals, but a 656 * improvement to performance. 657 * 658 * <p>To set this property via CSS, use the -fx-fixed-cell-size property. 659 * This should not be confused with the -fx-cell-size property. The difference 660 * between these two CSS properties is that -fx-cell-size will size all 661 * cells to the specified size, but it will not enforce that this is the 662 * only size (thus allowing for variable cell sizes, and preventing the 663 * performance gains from being possible). Therefore, when performance matters 664 * use -fx-fixed-cell-size, instead of -fx-cell-size. If both properties are 665 * specified in CSS, -fx-fixed-cell-size takes precedence.</p> 666 * 667 * @since JavaFX 8.0 668 */ 669 public final DoubleProperty fixedCellSizeProperty() { 670 if (fixedCellSize == null) { 671 fixedCellSize = new StyleableDoubleProperty(Region.USE_COMPUTED_SIZE) { 672 @Override public CssMetaData<TreeView<?>,Number> getCssMetaData() { 673 return StyleableProperties.FIXED_CELL_SIZE; 674 } 675 676 @Override public Object getBean() { 677 return TreeView.this; 678 } 679 680 @Override public String getName() { 681 return "fixedCellSize"; 682 } 683 }; 684 } 685 return fixedCellSize; 686 } 687 688 689 // --- Editable 690 private BooleanProperty editable; 691 public final void setEditable(boolean value) { 692 editableProperty().set(value); 693 } 694 public final boolean isEditable() { 695 return editable == null ? false : editable.get(); 696 } 697 /** 698 * Specifies whether this TreeView is editable - only if the TreeView and 699 * the TreeCells within it are both editable will a TreeCell be able to go 700 * into their editing state. 701 */ 702 public final BooleanProperty editableProperty() { 703 if (editable == null) { 704 editable = new SimpleBooleanProperty(this, "editable", false); 705 } 706 return editable; 707 } 708 709 710 // --- Editing Item 711 private ReadOnlyObjectWrapper<TreeItem<T>> editingItem; 712 713 private void setEditingItem(TreeItem<T> value) { 714 editingItemPropertyImpl().set(value); 715 } 716 717 /** 718 * Returns the TreeItem that is currently being edited in the TreeView, 719 * or null if no item is being edited. 720 */ 721 public final TreeItem<T> getEditingItem() { 722 return editingItem == null ? null : editingItem.get(); 723 } 724 725 /** 726 * <p>A property used to represent the TreeItem currently being edited 727 * in the TreeView, if editing is taking place, or null if no item is being edited. 728 * 729 * <p>It is not possible to set the editing item, instead it is required that 730 * you call {@link #edit(javafx.scene.control.TreeItem)}. 731 */ 732 public final ReadOnlyObjectProperty<TreeItem<T>> editingItemProperty() { 733 return editingItemPropertyImpl().getReadOnlyProperty(); 734 } 735 736 private ReadOnlyObjectWrapper<TreeItem<T>> editingItemPropertyImpl() { 737 if (editingItem == null) { 738 editingItem = new ReadOnlyObjectWrapper<TreeItem<T>>(this, "editingItem"); 739 } 740 return editingItem; 741 } 742 743 744 // --- On Edit Start 745 private ObjectProperty<EventHandler<EditEvent<T>>> onEditStart; 746 747 /** 748 * Sets the {@link EventHandler} that will be called when the user begins 749 * an edit. 750 */ 751 public final void setOnEditStart(EventHandler<EditEvent<T>> value) { 752 onEditStartProperty().set(value); 753 } 754 755 /** 756 * Returns the {@link EventHandler} that will be called when the user begins 757 * an edit. 758 */ 759 public final EventHandler<EditEvent<T>> getOnEditStart() { 760 return onEditStart == null ? null : onEditStart.get(); 761 } 762 763 /** 764 * This event handler will be fired when the user successfully initiates 765 * editing. 766 */ 767 public final ObjectProperty<EventHandler<EditEvent<T>>> onEditStartProperty() { 768 if (onEditStart == null) { 769 onEditStart = new SimpleObjectProperty<EventHandler<EditEvent<T>>>(this, "onEditStart") { 770 @Override protected void invalidated() { 771 setEventHandler(TreeView.<T>editStartEvent(), get()); 772 } 773 }; 774 } 775 return onEditStart; 776 } 777 778 779 // --- On Edit Commit 780 private ObjectProperty<EventHandler<EditEvent<T>>> onEditCommit; 781 782 /** 783 * Sets the {@link EventHandler} that will be called when the user commits 784 * an edit. 785 */ 786 public final void setOnEditCommit(EventHandler<EditEvent<T>> value) { 787 onEditCommitProperty().set(value); 788 } 789 790 /** 791 * Returns the {@link EventHandler} that will be called when the user commits 792 * an edit. 793 */ 794 public final EventHandler<EditEvent<T>> getOnEditCommit() { 795 return onEditCommit == null ? null : onEditCommit.get(); 796 } 797 798 /** 799 * <p>This property is used when the user performs an action that should 800 * result in their editing input being persisted.</p> 801 * 802 * <p>The EventHandler in this property should not be called directly - 803 * instead call {@link TreeCell#commitEdit(java.lang.Object)} from within 804 * your custom TreeCell. This will handle firing this event, updating the 805 * view, and switching out of the editing state.</p> 806 */ 807 public final ObjectProperty<EventHandler<EditEvent<T>>> onEditCommitProperty() { 808 if (onEditCommit == null) { 809 onEditCommit = new SimpleObjectProperty<EventHandler<EditEvent<T>>>(this, "onEditCommit") { 810 @Override protected void invalidated() { 811 setEventHandler(TreeView.<T>editCommitEvent(), get()); 812 } 813 }; 814 } 815 return onEditCommit; 816 } 817 818 819 // --- On Edit Cancel 820 private ObjectProperty<EventHandler<EditEvent<T>>> onEditCancel; 821 822 /** 823 * Sets the {@link EventHandler} that will be called when the user cancels 824 * an edit. 825 */ 826 public final void setOnEditCancel(EventHandler<EditEvent<T>> value) { 827 onEditCancelProperty().set(value); 828 } 829 830 /** 831 * Returns the {@link EventHandler} that will be called when the user cancels 832 * an edit. 833 */ 834 public final EventHandler<EditEvent<T>> getOnEditCancel() { 835 return onEditCancel == null ? null : onEditCancel.get(); 836 } 837 838 /** 839 * This event handler will be fired when the user cancels editing a cell. 840 */ 841 public final ObjectProperty<EventHandler<EditEvent<T>>> onEditCancelProperty() { 842 if (onEditCancel == null) { 843 onEditCancel = new SimpleObjectProperty<EventHandler<EditEvent<T>>>(this, "onEditCancel") { 844 @Override protected void invalidated() { 845 setEventHandler(TreeView.<T>editCancelEvent(), get()); 846 } 847 }; 848 } 849 return onEditCancel; 850 } 851 852 853 854 /*************************************************************************** 855 * * 856 * Public API * 857 * * 858 **************************************************************************/ 859 1161 * @since JavaFX 2.0 1162 */ 1163 public static class EditEvent<T> extends Event { 1164 private static final long serialVersionUID = -4437033058917528976L; 1165 1166 /** 1167 * Common supertype for all edit event types. 1168 * @since JavaFX 8.0 1169 */ 1170 public static final EventType<?> ANY = EDIT_ANY_EVENT; 1171 1172 private final TreeView<T> source; 1173 private final T oldValue; 1174 private final T newValue; 1175 private transient final TreeItem<T> treeItem; 1176 1177 /** 1178 * Creates a new EditEvent instance to represent an edit event. This 1179 * event is used for {@link #EDIT_START_EVENT}, 1180 * {@link #EDIT_COMMIT_EVENT} and {@link #EDIT_CANCEL_EVENT} types. 1181 */ 1182 public EditEvent(TreeView<T> source, 1183 EventType<? extends EditEvent> eventType, 1184 TreeItem<T> treeItem, T oldValue, T newValue) { 1185 super(source, Event.NULL_SOURCE_TARGET, eventType); 1186 this.source = source; 1187 this.oldValue = oldValue; 1188 this.newValue = newValue; 1189 this.treeItem = treeItem; 1190 } 1191 1192 /** 1193 * Returns the TreeView upon which the edit took place. 1194 */ 1195 @Override public TreeView<T> getSource() { 1196 return source; 1197 } 1198 1199 /** 1200 * Returns the {@link TreeItem} upon which the edit took place. 1201 */ 1202 public TreeItem<T> getTreeItem() { 1203 return treeItem; 1204 } 1205 1206 /** 1207 * Returns the new value input into the TreeItem by the end user. 1208 */ 1209 public T getNewValue() { 1210 return newValue; 1211 } 1212 1213 /** 1214 * Returns the old value that existed in the TreeItem prior to the current 1215 * edit event. 1216 */ 1217 public T getOldValue() { 1218 return oldValue; 1219 } 1220 } 1221 1222 1223 1224 1225 1226 1227 1228 // package for testing 1229 static class TreeViewBitSetSelectionModel<T> extends MultipleSelectionModelBase<TreeItem<T>> { 1230 1231 /*********************************************************************** 1232 * * 1233 * Internal fields * 1234 * * 1235 **********************************************************************/ | 192 * @see TreeItem 193 * @see TreeCell 194 * @param <T> The type of the item contained within the {@link TreeItem} value 195 * property for all tree items in this TreeView. 196 * @since JavaFX 2.0 197 */ 198 @DefaultProperty("root") 199 public class TreeView<T> extends Control { 200 201 /*************************************************************************** 202 * * 203 * Static properties and methods * 204 * * 205 **************************************************************************/ 206 207 /** 208 * An EventType that indicates some edit event has occurred. It is the parent 209 * type of all other edit events: {@link #editStartEvent}, 210 * {@link #editCommitEvent} and {@link #editCancelEvent}. 211 * 212 * @param <T> the type of edit event 213 * @return An EventType that indicates some edit event has occurred. 214 */ 215 @SuppressWarnings("unchecked") 216 public static <T> EventType<EditEvent<T>> editAnyEvent() { 217 return (EventType<EditEvent<T>>) EDIT_ANY_EVENT; 218 } 219 private static final EventType<?> EDIT_ANY_EVENT = 220 new EventType<>(Event.ANY, "TREE_VIEW_EDIT"); 221 222 /** 223 * An EventType used to indicate that an edit event has started within the 224 * TreeView upon which the event was fired. 225 * 226 * @param <T> the type of edit event 227 * @return An EventType used to indicate that an edit event has started. 228 */ 229 @SuppressWarnings("unchecked") 230 public static <T> EventType<EditEvent<T>> editStartEvent() { 231 return (EventType<EditEvent<T>>) EDIT_START_EVENT; 232 } 233 private static final EventType<?> EDIT_START_EVENT = 234 new EventType<>(editAnyEvent(), "EDIT_START"); 235 236 /** 237 * An EventType used to indicate that an edit event has just been canceled 238 * within the TreeView upon which the event was fired. 239 * 240 * @param <T> the type of edit event 241 * @return An EventType used to indicate that an edit event has just been 242 * canceled. 243 */ 244 @SuppressWarnings("unchecked") 245 public static <T> EventType<EditEvent<T>> editCancelEvent() { 246 return (EventType<EditEvent<T>>) EDIT_CANCEL_EVENT; 247 } 248 private static final EventType<?> EDIT_CANCEL_EVENT = 249 new EventType<>(editAnyEvent(), "EDIT_CANCEL"); 250 251 /** 252 * An EventType that is used to indicate that an edit in a TreeView has been 253 * committed. This means that user has made changes to the data of a 254 * TreeItem, and that the UI should be updated. 255 * 256 * @param <T> the type of edit event 257 * @return An EventType that is used to indicate that an edit in a TreeView 258 * has been committed. 259 */ 260 @SuppressWarnings("unchecked") 261 public static <T> EventType<EditEvent<T>> editCommitEvent() { 262 return (EventType<EditEvent<T>>) EDIT_COMMIT_EVENT; 263 } 264 private static final EventType<?> EDIT_COMMIT_EVENT = 265 new EventType<>(editAnyEvent(), "EDIT_COMMIT"); 266 267 /** 268 * Returns the number of levels of 'indentation' of the given TreeItem, 269 * based on how many times {@link javafx.scene.control.TreeItem#getParent()} 270 * can be recursively called. If the TreeItem does not have any parent set, 271 * the returned value will be zero. For each time getParent() is recursively 272 * called, the returned value is incremented by one. 273 * 274 * <p><strong>Important note: </strong>This method is deprecated as it does 275 * not consider the root node. This means that this method will iterate 276 * past the root node of the TreeView control, if the root node has a parent. 403 * which are used to represent items in the 404 * TreeView. The factory works identically to the cellFactory in ListView 405 * and other complex composite controls. It is called to create a new 406 * TreeCell only when the system has determined that it doesn't have enough 407 * cells to represent the currently visible items. The TreeCell is reused 408 * by the system to represent different items in the tree when possible. 409 * 410 * <p>Refer to the {@link Cell} class documentation for more details. 411 * 412 * @param value The {@link Callback} to use for generating TreeCell instances, 413 * or null if the default cell factory should be used. 414 */ 415 public final void setCellFactory(Callback<TreeView<T>, TreeCell<T>> value) { 416 cellFactoryProperty().set(value); 417 } 418 419 /** 420 * <p>Returns the cell factory that will be used for creating TreeCells, 421 * which are used to represent items in the TreeView, or null if no custom 422 * cell factory has been set. 423 * @return the cell factory 424 */ 425 public final Callback<TreeView<T>, TreeCell<T>> getCellFactory() { 426 return cellFactory == null ? null : cellFactory.get(); 427 } 428 429 /** 430 * Represents the cell factory that will be used for creating TreeCells, 431 * which are used to represent items in the TreeView. 432 * @return the cell factory property 433 */ 434 public final ObjectProperty<Callback<TreeView<T>, TreeCell<T>>> cellFactoryProperty() { 435 if (cellFactory == null) { 436 cellFactory = new SimpleObjectProperty<Callback<TreeView<T>, TreeCell<T>>>(this, "cellFactory"); 437 } 438 return cellFactory; 439 } 440 441 442 // --- Root 443 private ObjectProperty<TreeItem<T>> root = new SimpleObjectProperty<TreeItem<T>>(this, "root") { 444 private WeakReference<TreeItem<T>> weakOldItem; 445 446 @Override protected void invalidated() { 447 TreeItem<T> oldTreeItem = weakOldItem == null ? null : weakOldItem.get(); 448 if (oldTreeItem != null && weakRootEventListener != null) { 449 oldTreeItem.removeEventHandler(TreeItem.<T>treeNotificationEvent(), weakRootEventListener); 450 } 451 452 TreeItem<T> root = getRoot(); 469 * documentation for more details. 470 * 471 * @param value The {@link TreeItem} that will be placed at the root of the 472 * TreeView. 473 */ 474 public final void setRoot(TreeItem<T> value) { 475 rootProperty().set(value); 476 } 477 478 /** 479 * Returns the current root node of this TreeView, or null if no root node 480 * is specified. 481 * @return The current root node, or null if no root node exists. 482 */ 483 public final TreeItem<T> getRoot() { 484 return root == null ? null : root.get(); 485 } 486 487 /** 488 * Property representing the root node of the TreeView. 489 * @return the root node property 490 */ 491 public final ObjectProperty<TreeItem<T>> rootProperty() { 492 return root; 493 } 494 495 496 497 // --- Show Root 498 private BooleanProperty showRoot; 499 500 /** 501 * Specifies whether the root {@code TreeItem} should be shown within this 502 * TreeView. 503 * 504 * @param value If true, the root TreeItem will be shown, and if false it 505 * will be hidden. 506 */ 507 public final void setShowRoot(boolean value) { 508 showRootProperty().set(value); 509 } 510 511 /** 512 * Returns true if the root of the TreeView should be shown, and false if 513 * it should not. By default, the root TreeItem is visible in the TreeView. 514 * @return true if the root of the TreeView should be shown 515 */ 516 public final boolean isShowRoot() { 517 return showRoot == null ? true : showRoot.get(); 518 } 519 520 /** 521 * Property that represents whether or not the TreeView root node is visible. 522 * @return the show root property 523 */ 524 public final BooleanProperty showRootProperty() { 525 if (showRoot == null) { 526 showRoot = new SimpleBooleanProperty(this, "showRoot", true) { 527 @Override protected void invalidated() { 528 updateRootExpanded(); 529 updateExpandedItemCount(getRoot()); 530 } 531 }; 532 } 533 return showRoot; 534 } 535 536 537 // --- Selection Model 538 private ObjectProperty<MultipleSelectionModel<TreeItem<T>>> selectionModel; 539 540 /** 541 * Sets the {@link MultipleSelectionModel} to be used in the TreeView. 542 * Despite a TreeView requiring a <code><b>Multiple</b>SelectionModel</code>, 543 * it is possible to configure it to only allow single selection (see 544 * {@link MultipleSelectionModel#setSelectionMode(javafx.scene.control.SelectionMode)} 545 * for more information). 546 * @param value the {@link MultipleSelectionModel} to be used 547 */ 548 public final void setSelectionModel(MultipleSelectionModel<TreeItem<T>> value) { 549 selectionModelProperty().set(value); 550 } 551 552 /** 553 * Returns the currently installed selection model. 554 * @return the currently installed selection model 555 */ 556 public final MultipleSelectionModel<TreeItem<T>> getSelectionModel() { 557 return selectionModel == null ? null : selectionModel.get(); 558 } 559 560 /** 561 * The SelectionModel provides the API through which it is possible 562 * to select single or multiple items within a TreeView, as well as inspect 563 * which rows have been selected by the user. Note that it has a generic 564 * type that must match the type of the TreeView itself. 565 * @return the selection model property 566 */ 567 public final ObjectProperty<MultipleSelectionModel<TreeItem<T>>> selectionModelProperty() { 568 if (selectionModel == null) { 569 selectionModel = new SimpleObjectProperty<MultipleSelectionModel<TreeItem<T>>>(this, "selectionModel"); 570 } 571 return selectionModel; 572 } 573 574 575 // --- Focus Model 576 private ObjectProperty<FocusModel<TreeItem<T>>> focusModel; 577 578 /** 579 * Sets the {@link FocusModel} to be used in the TreeView. 580 * @param value the {@link FocusModel} to be used 581 */ 582 public final void setFocusModel(FocusModel<TreeItem<T>> value) { 583 focusModelProperty().set(value); 584 } 585 586 /** 587 * Returns the currently installed {@link FocusModel}. 588 * @return the currently installed {@link FocusModel} 589 */ 590 public final FocusModel<TreeItem<T>> getFocusModel() { 591 return focusModel == null ? null : focusModel.get(); 592 } 593 594 /** 595 * The FocusModel provides the API through which it is possible 596 * to control focus on zero or one rows of the TreeView. Generally the 597 * default implementation should be more than sufficient. 598 * @return the focus model property 599 */ 600 public final ObjectProperty<FocusModel<TreeItem<T>>> focusModelProperty() { 601 if (focusModel == null) { 602 focusModel = new SimpleObjectProperty<FocusModel<TreeItem<T>>>(this, "focusModel"); 603 } 604 return focusModel; 605 } 606 607 608 // --- Expanded node count 609 /** 610 * <p>Represents the number of tree nodes presently able to be visible in the 611 * TreeView. This is essentially the count of all expanded tree items, and 612 * their children. 613 * 614 * <p>For example, if just the root node is visible, the expandedItemCount will 615 * be one. If the root had three children and the root was expanded, the value 616 * will be four. 617 * @since JavaFX 8.0 618 */ 662 } 663 /** 664 * Specifies whether this control has cells that are a fixed height (of the 665 * specified value). If this value is less than or equal to zero, 666 * then all cells are individually sized and positioned. This is a slow 667 * operation. Therefore, when performance matters and developers are not 668 * dependent on variable cell sizes it is a good idea to set the fixed cell 669 * size value. Generally cells are around 24px, so setting a fixed cell size 670 * of 24 is likely to result in very little difference in visuals, but a 671 * improvement to performance. 672 * 673 * <p>To set this property via CSS, use the -fx-fixed-cell-size property. 674 * This should not be confused with the -fx-cell-size property. The difference 675 * between these two CSS properties is that -fx-cell-size will size all 676 * cells to the specified size, but it will not enforce that this is the 677 * only size (thus allowing for variable cell sizes, and preventing the 678 * performance gains from being possible). Therefore, when performance matters 679 * use -fx-fixed-cell-size, instead of -fx-cell-size. If both properties are 680 * specified in CSS, -fx-fixed-cell-size takes precedence.</p> 681 * 682 * @return the fixed cell size property 683 * @since JavaFX 8.0 684 */ 685 public final DoubleProperty fixedCellSizeProperty() { 686 if (fixedCellSize == null) { 687 fixedCellSize = new StyleableDoubleProperty(Region.USE_COMPUTED_SIZE) { 688 @Override public CssMetaData<TreeView<?>,Number> getCssMetaData() { 689 return StyleableProperties.FIXED_CELL_SIZE; 690 } 691 692 @Override public Object getBean() { 693 return TreeView.this; 694 } 695 696 @Override public String getName() { 697 return "fixedCellSize"; 698 } 699 }; 700 } 701 return fixedCellSize; 702 } 703 704 705 // --- Editable 706 private BooleanProperty editable; 707 public final void setEditable(boolean value) { 708 editableProperty().set(value); 709 } 710 public final boolean isEditable() { 711 return editable == null ? false : editable.get(); 712 } 713 /** 714 * Specifies whether this TreeView is editable - only if the TreeView and 715 * the TreeCells within it are both editable will a TreeCell be able to go 716 * into their editing state. 717 * @return the editable property 718 */ 719 public final BooleanProperty editableProperty() { 720 if (editable == null) { 721 editable = new SimpleBooleanProperty(this, "editable", false); 722 } 723 return editable; 724 } 725 726 727 // --- Editing Item 728 private ReadOnlyObjectWrapper<TreeItem<T>> editingItem; 729 730 private void setEditingItem(TreeItem<T> value) { 731 editingItemPropertyImpl().set(value); 732 } 733 734 /** 735 * Returns the TreeItem that is currently being edited in the TreeView, 736 * or null if no item is being edited. 737 * @return the TreeItem that is currently being edited in the TreeView 738 */ 739 public final TreeItem<T> getEditingItem() { 740 return editingItem == null ? null : editingItem.get(); 741 } 742 743 /** 744 * <p>A property used to represent the TreeItem currently being edited 745 * in the TreeView, if editing is taking place, or null if no item is being edited. 746 * 747 * <p>It is not possible to set the editing item, instead it is required that 748 * you call {@link #edit(javafx.scene.control.TreeItem)}. 749 * @return the editing item property 750 */ 751 public final ReadOnlyObjectProperty<TreeItem<T>> editingItemProperty() { 752 return editingItemPropertyImpl().getReadOnlyProperty(); 753 } 754 755 private ReadOnlyObjectWrapper<TreeItem<T>> editingItemPropertyImpl() { 756 if (editingItem == null) { 757 editingItem = new ReadOnlyObjectWrapper<TreeItem<T>>(this, "editingItem"); 758 } 759 return editingItem; 760 } 761 762 763 // --- On Edit Start 764 private ObjectProperty<EventHandler<EditEvent<T>>> onEditStart; 765 766 /** 767 * Sets the {@link EventHandler} that will be called when the user begins 768 * an edit. 769 * @param value the {@link EventHandler} that will be called when the user 770 * begins an edit 771 */ 772 public final void setOnEditStart(EventHandler<EditEvent<T>> value) { 773 onEditStartProperty().set(value); 774 } 775 776 /** 777 * Returns the {@link EventHandler} that will be called when the user begins 778 * an edit. 779 * @return the {@link EventHandler} when the user begins an edit 780 */ 781 public final EventHandler<EditEvent<T>> getOnEditStart() { 782 return onEditStart == null ? null : onEditStart.get(); 783 } 784 785 /** 786 * This event handler will be fired when the user successfully initiates 787 * editing. 788 * @return the event handler when the user successfully initiates editing 789 */ 790 public final ObjectProperty<EventHandler<EditEvent<T>>> onEditStartProperty() { 791 if (onEditStart == null) { 792 onEditStart = new SimpleObjectProperty<EventHandler<EditEvent<T>>>(this, "onEditStart") { 793 @Override protected void invalidated() { 794 setEventHandler(TreeView.<T>editStartEvent(), get()); 795 } 796 }; 797 } 798 return onEditStart; 799 } 800 801 802 // --- On Edit Commit 803 private ObjectProperty<EventHandler<EditEvent<T>>> onEditCommit; 804 805 /** 806 * Sets the {@link EventHandler} that will be called when the user commits 807 * an edit. 808 * @param value the {@link EventHandler} that will be called when the user 809 * commits an edit 810 */ 811 public final void setOnEditCommit(EventHandler<EditEvent<T>> value) { 812 onEditCommitProperty().set(value); 813 } 814 815 /** 816 * Returns the {@link EventHandler} that will be called when the user commits 817 * an edit. 818 * @return the {@link EventHandler} that will be called when the user commits 819 * an edit 820 */ 821 public final EventHandler<EditEvent<T>> getOnEditCommit() { 822 return onEditCommit == null ? null : onEditCommit.get(); 823 } 824 825 /** 826 * <p>This property is used when the user performs an action that should 827 * result in their editing input being persisted.</p> 828 * 829 * <p>The EventHandler in this property should not be called directly - 830 * instead call {@link TreeCell#commitEdit(java.lang.Object)} from within 831 * your custom TreeCell. This will handle firing this event, updating the 832 * view, and switching out of the editing state.</p> 833 * @return the event handler when the user performs an action that result in 834 * their editing input being persisted 835 */ 836 public final ObjectProperty<EventHandler<EditEvent<T>>> onEditCommitProperty() { 837 if (onEditCommit == null) { 838 onEditCommit = new SimpleObjectProperty<EventHandler<EditEvent<T>>>(this, "onEditCommit") { 839 @Override protected void invalidated() { 840 setEventHandler(TreeView.<T>editCommitEvent(), get()); 841 } 842 }; 843 } 844 return onEditCommit; 845 } 846 847 848 // --- On Edit Cancel 849 private ObjectProperty<EventHandler<EditEvent<T>>> onEditCancel; 850 851 /** 852 * Sets the {@link EventHandler} that will be called when the user cancels 853 * an edit. 854 * @param value the {@link EventHandler} that will be called when the user 855 * cancels an edit 856 */ 857 public final void setOnEditCancel(EventHandler<EditEvent<T>> value) { 858 onEditCancelProperty().set(value); 859 } 860 861 /** 862 * Returns the {@link EventHandler} that will be called when the user cancels 863 * an edit. 864 * @return the {@link EventHandler} that will be called when the user cancels 865 * an edit 866 */ 867 public final EventHandler<EditEvent<T>> getOnEditCancel() { 868 return onEditCancel == null ? null : onEditCancel.get(); 869 } 870 871 /** 872 * This event handler will be fired when the user cancels editing a cell. 873 * @return the event handler will be fired when the user cancels editing a 874 * cell 875 */ 876 public final ObjectProperty<EventHandler<EditEvent<T>>> onEditCancelProperty() { 877 if (onEditCancel == null) { 878 onEditCancel = new SimpleObjectProperty<EventHandler<EditEvent<T>>>(this, "onEditCancel") { 879 @Override protected void invalidated() { 880 setEventHandler(TreeView.<T>editCancelEvent(), get()); 881 } 882 }; 883 } 884 return onEditCancel; 885 } 886 887 888 889 /*************************************************************************** 890 * * 891 * Public API * 892 * * 893 **************************************************************************/ 894 1196 * @since JavaFX 2.0 1197 */ 1198 public static class EditEvent<T> extends Event { 1199 private static final long serialVersionUID = -4437033058917528976L; 1200 1201 /** 1202 * Common supertype for all edit event types. 1203 * @since JavaFX 8.0 1204 */ 1205 public static final EventType<?> ANY = EDIT_ANY_EVENT; 1206 1207 private final TreeView<T> source; 1208 private final T oldValue; 1209 private final T newValue; 1210 private transient final TreeItem<T> treeItem; 1211 1212 /** 1213 * Creates a new EditEvent instance to represent an edit event. This 1214 * event is used for {@link #EDIT_START_EVENT}, 1215 * {@link #EDIT_COMMIT_EVENT} and {@link #EDIT_CANCEL_EVENT} types. 1216 * @param source the source 1217 * @param eventType the eventType 1218 * @param treeItem the treeItem 1219 * @param oldValue the oldValue 1220 * @param newValue the newValue 1221 */ 1222 public EditEvent(TreeView<T> source, 1223 EventType<? extends EditEvent> eventType, 1224 TreeItem<T> treeItem, T oldValue, T newValue) { 1225 super(source, Event.NULL_SOURCE_TARGET, eventType); 1226 this.source = source; 1227 this.oldValue = oldValue; 1228 this.newValue = newValue; 1229 this.treeItem = treeItem; 1230 } 1231 1232 /** 1233 * Returns the TreeView upon which the edit took place. 1234 */ 1235 @Override public TreeView<T> getSource() { 1236 return source; 1237 } 1238 1239 /** 1240 * Returns the {@link TreeItem} upon which the edit took place. 1241 * @return the {@link TreeItem} upon which the edit took place 1242 */ 1243 public TreeItem<T> getTreeItem() { 1244 return treeItem; 1245 } 1246 1247 /** 1248 * Returns the new value input into the TreeItem by the end user. 1249 * @return the new value input into the TreeItem by the end user 1250 */ 1251 public T getNewValue() { 1252 return newValue; 1253 } 1254 1255 /** 1256 * Returns the old value that existed in the TreeItem prior to the current 1257 * edit event. 1258 * @return the old value that existed in the TreeItem prior to the current 1259 * edit event 1260 */ 1261 public T getOldValue() { 1262 return oldValue; 1263 } 1264 } 1265 1266 1267 1268 1269 1270 1271 1272 // package for testing 1273 static class TreeViewBitSetSelectionModel<T> extends MultipleSelectionModelBase<TreeItem<T>> { 1274 1275 /*********************************************************************** 1276 * * 1277 * Internal fields * 1278 * * 1279 **********************************************************************/ |