/*
* Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javafx.scene.control;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.BooleanPropertyBase;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ObjectPropertyBase;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.event.EventDispatchChain;
import javafx.event.EventHandler;
import javafx.event.EventTarget;
import javafx.event.EventType;
import javafx.scene.Node;
import com.sun.javafx.event.EventHandlerManager;
import java.util.Comparator;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import static javafx.scene.control.TreeSortMode.*;
The model for a single node supplying a hierarchy of values to a control such as TreeView
. The model may be implemented such that values may be loaded in memory as they are needed.
The model allows registration of listeners which will be notified as the
number of items changes, their position or if the values themselves change.
Note however that a TreeItem is not a Node, and therefore no visual events will be fired on the TreeItem. To get these events, it is necessary to add relevant observers to the TreeCell instances (via a custom cell factory - see the Cell
class documentation for more details).
In the simplest case, TreeItem instances may be created in memory as such:
TreeItem<String> root = new TreeItem<String>("Root Node");
root.setExpanded(true);
root.getChildren().addAll(
new TreeItem<String>("Item 1"),
new TreeItem<String>("Item 2"),
new TreeItem<String>("Item 3")
);
TreeView<String> treeView = new TreeView<String>(root);
This approach works well for simple tree structures, or when the data is not
excessive (so that it can easily fit in memory). In situations where the size
of the tree structure is unknown (and therefore potentially huge), there is
the option of creating TreeItem instances on-demand in a memory-efficient way.
To demonstrate this, the code below creates a file system browser:
private TreeView buildFileSystemBrowser() {
TreeItem<File> root = createNode(new File("/"));
return new TreeView<File>(root);
}
// This method creates a TreeItem to represent the given File. It does this
// by overriding the TreeItem.getChildren() and TreeItem.isLeaf() methods
// anonymously, but this could be better abstracted by creating a
// 'FileTreeItem' subclass of TreeItem. However, this is left as an exercise
// for the reader.
private TreeItem<File> createNode(final File f) {
return new TreeItem<File>(f) {
// We cache whether the File is a leaf or not. A File is a leaf if
// it is not a directory and does not have any files contained within
// it. We cache this as isLeaf() is called often, and doing the
// actual check on File is expensive.
private boolean isLeaf;
// We do the children and leaf testing only once, and then set these
// booleans to false so that we do not check again during this
// run. A more complete implementation may need to handle more
// dynamic file system situations (such as where a folder has files
// added after the TreeView is shown). Again, this is left as an
// exercise for the reader.
private boolean isFirstTimeChildren = true;
private boolean isFirstTimeLeaf = true;
@Override public ObservableList<TreeItem<File>> getChildren() {
if (isFirstTimeChildren) {
isFirstTimeChildren = false;
// First getChildren() call, so we actually go off and
// determine the children of the File contained in this TreeItem.
super.getChildren().setAll(buildChildren(this));
}
return super.getChildren();
}
@Override public boolean isLeaf() {
if (isFirstTimeLeaf) {
isFirstTimeLeaf = false;
File f = (File) getValue();
isLeaf = f.isFile();
}
return isLeaf;
}
private ObservableList<TreeItem<File>> buildChildren(TreeItem<File> TreeItem) {
File f = TreeItem.getValue();
if (f != null && f.isDirectory()) {
File[] files = f.listFiles();
if (files != null) {
ObservableList<TreeItem<File>> children = FXCollections.observableArrayList();
for (File childFile : files) {
children.add(createNode(childFile));
}
return children;
}
}
return FXCollections.emptyObservableList();
}
};
}
TreeItem Events
TreeItem supports the same event bubbling concept as elsewhere in the scenegraph. This means that it is not necessary to listen for events on all TreeItems (and this is certainly not encouraged!). A better, and far more low cost solution is to instead attach event listeners to the TreeView root
item. As long as there is a path between where the event occurs and the root TreeItem, the event will be bubbled to the root item.
It is important to note however that a TreeItem is not a Node, which means that only the event types defined in TreeItem will be delivered. To listen to general events (for example mouse interactions), it is necessary to add the necessary listeners to the cells
contained within the TreeView (by providing a
cell factory
).
The TreeItem class defines a number of events, with a defined hierarchy. These
are shown below (follow the links to learn more about each event type):
The indentation shown above signifies the relationship between event types. For example, all TreeItem event types have treeNotificationEvent()
as their parent event type, and the branch expand
/ collapse
event types are both treeNotificationEvent()
. For performance reasons, it is encouraged to listen to only the events you need to listen to. This means that it is encouraged that it is better to listen to, for example, TreeItem.valueChangedEvent()
, rather than TreeItem.treeNotificationEvent()
.
Type parameters: See Also: Since: JavaFX 2.0
/**
* The model for a single node supplying a hierarchy of values to a control such
* as {@link TreeView}. The model may be implemented such that values may be loaded in
* memory as they are needed.
* <p>
* The model allows registration of listeners which will be notified as the
* number of items changes, their position or if the values themselves change.
* Note however that a TreeItem is <b>not</b> a Node, and therefore no visual
* events will be fired on the TreeItem. To get these events, it is necessary to
* add relevant observers to the TreeCell instances (via a custom cell factory -
* see the {@link Cell} class documentation for more details).
*
* <p>In the simplest case, TreeItem instances may be created in memory as such:
* <pre><code>
* TreeItem<String> root = new TreeItem<String>("Root Node");
* root.setExpanded(true);
* root.getChildren().addAll(
* new TreeItem<String>("Item 1"),
* new TreeItem<String>("Item 2"),
* new TreeItem<String>("Item 3")
* );
* TreeView<String> treeView = new TreeView<String>(root);
* </code></pre>
*
* This approach works well for simple tree structures, or when the data is not
* excessive (so that it can easily fit in memory). In situations where the size
* of the tree structure is unknown (and therefore potentially huge), there is
* the option of creating TreeItem instances on-demand in a memory-efficient way.
* To demonstrate this, the code below creates a file system browser:
*
* <pre><code>
* private TreeView buildFileSystemBrowser() {
* TreeItem<File> root = createNode(new File("/"));
* return new TreeView<File>(root);
* }
*
* // This method creates a TreeItem to represent the given File. It does this
* // by overriding the TreeItem.getChildren() and TreeItem.isLeaf() methods
* // anonymously, but this could be better abstracted by creating a
* // 'FileTreeItem' subclass of TreeItem. However, this is left as an exercise
* // for the reader.
* private TreeItem<File> createNode(final File f) {
* return new TreeItem<File>(f) {
* // We cache whether the File is a leaf or not. A File is a leaf if
* // it is not a directory and does not have any files contained within
* // it. We cache this as isLeaf() is called often, and doing the
* // actual check on File is expensive.
* private boolean isLeaf;
*
* // We do the children and leaf testing only once, and then set these
* // booleans to false so that we do not check again during this
* // run. A more complete implementation may need to handle more
* // dynamic file system situations (such as where a folder has files
* // added after the TreeView is shown). Again, this is left as an
* // exercise for the reader.
* private boolean isFirstTimeChildren = true;
* private boolean isFirstTimeLeaf = true;
*
* @Override public ObservableList<TreeItem<File>> getChildren() {
* if (isFirstTimeChildren) {
* isFirstTimeChildren = false;
*
* // First getChildren() call, so we actually go off and
* // determine the children of the File contained in this TreeItem.
* super.getChildren().setAll(buildChildren(this));
* }
* return super.getChildren();
* }
*
* @Override public boolean isLeaf() {
* if (isFirstTimeLeaf) {
* isFirstTimeLeaf = false;
* File f = (File) getValue();
* isLeaf = f.isFile();
* }
*
* return isLeaf;
* }
*
* private ObservableList<TreeItem<File>> buildChildren(TreeItem<File> TreeItem) {
* File f = TreeItem.getValue();
* if (f != null && f.isDirectory()) {
* File[] files = f.listFiles();
* if (files != null) {
* ObservableList<TreeItem<File>> children = FXCollections.observableArrayList();
*
* for (File childFile : files) {
* children.add(createNode(childFile));
* }
*
* return children;
* }
* }
*
* return FXCollections.emptyObservableList();
* }
* };
* }</code></pre>
*
* <strong>TreeItem Events</strong>
* <p>TreeItem supports the same event bubbling concept as elsewhere in the
* scenegraph. This means that it is not necessary to listen for events on all
* TreeItems (and this is certainly not encouraged!). A better, and far more low
* cost solution is to instead attach event listeners to the TreeView
* {@link TreeView#rootProperty() root} item. As long as there is a path between
* where the event occurs and the root TreeItem, the event will be bubbled to the
* root item.
*
* <p>It is important to note however that a TreeItem is <strong>not</strong> a
* Node, which means that only the event types defined in TreeItem will be
* delivered. To listen to general events (for example mouse interactions), it is
* necessary to add the necessary listeners to the {@link Cell cells} contained
* within the TreeView (by providing a {@link TreeView#cellFactoryProperty()
* cell factory}).
*
* <p>The TreeItem class defines a number of events, with a defined hierarchy. These
* are shown below (follow the links to learn more about each event type):
*
* <ul>
* <li>{@link TreeItem#treeNotificationEvent() TreeItem.treeNotificationEvent()}
* <ul>
* <li>{@link TreeItem#valueChangedEvent() TreeItem.valueChangedEvent()}</li>
* <li>{@link TreeItem#graphicChangedEvent() TreeItem.graphicChangedEvent()}</li>
* <li>{@link TreeItem#expandedItemCountChangeEvent() TreeItem.expandedItemCountChangeEvent()}
* <ul>
* <li>{@link TreeItem#branchExpandedEvent() TreeItem.branchExpandedEvent()}</li>
* <li>{@link TreeItem#branchCollapsedEvent() TreeItem.branchCollapsedEvent()}</li>
* <li>{@link TreeItem#childrenModificationEvent() TreeItem.childrenModificationEvent()}</li>
* </ul>
* </li>
* </ul>
* </li>
* </ul>
*
* <p>The indentation shown above signifies the relationship between event types.
* For example, all TreeItem event types have
* {@link TreeItem#treeNotificationEvent() treeNotificationEvent()} as their
* parent event type, and the branch
* {@link TreeItem#branchExpandedEvent() expand} /
* {@link TreeItem#branchCollapsedEvent() collapse} event types are both
* {@link TreeItem#treeNotificationEvent() treeNotificationEvent()}. For
* performance reasons, it is encouraged to listen
* to only the events you need to listen to. This means that it is encouraged
* that it is better to listen to, for example,
* {@link TreeItem#valueChangedEvent() TreeItem.valueChangedEvent()},
* rather than {@link TreeItem#treeNotificationEvent() TreeItem.treeNotificationEvent()}.
*
* @param <T> The type of the {@link #getValue() value} property within TreeItem.
* @since JavaFX 2.0
* @see TreeView
*/
public class TreeItem<T> implements EventTarget { //, Comparable<TreeItem<T>> {
/***************************************************************************
* *
* Static properties and methods *
* *
**************************************************************************/
The base EventType used to indicate that an event has occurred within a
TreeItem. When an event occurs in a TreeItem, the event is fired to any
listeners on the TreeItem that the event occurs, before it 'bubbles' up the
TreeItem chain by following the TreeItem parent property. This repeats
until a TreeItem whose parent TreeItem is null is reached At this point
the event stops 'bubbling' and goes no further. This means that events
that occur on a TreeItem can be relatively cheap, as a listener needs only
be installed on the TreeView root node to be alerted of events happening
at any point in the tree.
Type parameters: - <T> – The type of the value contained within the TreeItem.
Returns: the base EventType when an event has occurred within a TreeItem
/**
* The base EventType used to indicate that an event has occurred within a
* TreeItem. When an event occurs in a TreeItem, the event is fired to any
* listeners on the TreeItem that the event occurs, before it 'bubbles' up the
* TreeItem chain by following the TreeItem parent property. This repeats
* until a TreeItem whose parent TreeItem is null is reached At this point
* the event stops 'bubbling' and goes no further. This means that events
* that occur on a TreeItem can be relatively cheap, as a listener needs only
* be installed on the TreeView root node to be alerted of events happening
* at any point in the tree.
*
* @param <T> The type of the value contained within the TreeItem.
* @return the base EventType when an event has occurred within a TreeItem
*/
@SuppressWarnings("unchecked")
public static <T> EventType<TreeModificationEvent<T>> treeNotificationEvent() {
return (EventType<TreeModificationEvent<T>>) TREE_NOTIFICATION_EVENT;
}
private static final EventType<?> TREE_NOTIFICATION_EVENT
= new EventType<>(Event.ANY, "TreeNotificationEvent");
The general EventType used when the TreeItem receives a modification that results in the number of children being visible changes. This is normally achieved via one of the sub-types of this EventType (see branchExpandedEvent()
, branchCollapsedEvent()
and childrenModificationEvent()
for the three sub-types). Type parameters: - <T> – The type of the value contained within the TreeItem.
Returns: The general EventType when the TreeItem receives a modification Since: JavaFX 8.0
/**
* The general EventType used when the TreeItem receives a modification that
* results in the number of children being visible changes.
* This is normally achieved via one of the sub-types of this
* EventType (see {@link #branchExpandedEvent()},
* {@link #branchCollapsedEvent()} and {@link #childrenModificationEvent()}
* for the three sub-types).
*
* @param <T> The type of the value contained within the TreeItem.
* @return The general EventType when the TreeItem receives a modification
* @since JavaFX 8.0
*/
@SuppressWarnings("unchecked")
public static <T> EventType<TreeModificationEvent<T>> expandedItemCountChangeEvent() {
return (EventType<TreeModificationEvent<T>>) EXPANDED_ITEM_COUNT_CHANGE_EVENT;
}
private static final EventType<?> EXPANDED_ITEM_COUNT_CHANGE_EVENT
= new EventType<>(treeNotificationEvent(), "ExpandedItemCountChangeEvent");
An EventType used when the TreeItem receives a modification to its
expanded property, such that the TreeItem is now in the expanded state.
Type parameters: - <T> – The type of the value contained within the TreeItem.
Returns: The EventType used when the TreeItem receives a modification
/**
* An EventType used when the TreeItem receives a modification to its
* expanded property, such that the TreeItem is now in the expanded state.
*
* @param <T> The type of the value contained within the TreeItem.
* @return The EventType used when the TreeItem receives a modification
*/
@SuppressWarnings("unchecked")
public static <T> EventType<TreeModificationEvent<T>> branchExpandedEvent() {
return (EventType<TreeModificationEvent<T>>) BRANCH_EXPANDED_EVENT;
}
private static final EventType<?> BRANCH_EXPANDED_EVENT
= new EventType<>(expandedItemCountChangeEvent(), "BranchExpandedEvent");
An EventType used when the TreeItem receives a modification to its
expanded property, such that the TreeItem is now in the collapsed state.
Type parameters: - <T> – The type of the value contained within the TreeItem.
Returns: The EventType when the TreeItem receives a modification
/**
* An EventType used when the TreeItem receives a modification to its
* expanded property, such that the TreeItem is now in the collapsed state.
*
* @param <T> The type of the value contained within the TreeItem.
* @return The EventType when the TreeItem receives a modification
*/
@SuppressWarnings("unchecked")
public static <T> EventType<TreeModificationEvent<T>> branchCollapsedEvent() {
return (EventType<TreeModificationEvent<T>>) BRANCH_COLLAPSED_EVENT;
}
private static final EventType<?> BRANCH_COLLAPSED_EVENT
= new EventType<>(expandedItemCountChangeEvent(), "BranchCollapsedEvent");
An EventType used when the TreeItem receives a direct modification to its
children list.
Type parameters: - <T> – The type of the value contained within the TreeItem.
Returns: The EventType when the TreeItem receives a direct modification to
its children list
/**
* An EventType used when the TreeItem receives a direct modification to its
* children list.
*
* @param <T> The type of the value contained within the TreeItem.
* @return The EventType when the TreeItem receives a direct modification to
* its children list
*/
@SuppressWarnings("unchecked")
public static <T> EventType<TreeModificationEvent<T>> childrenModificationEvent() {
return (EventType<TreeModificationEvent<T>>) CHILDREN_MODIFICATION_EVENT;
}
private static final EventType<?> CHILDREN_MODIFICATION_EVENT
= new EventType<>(expandedItemCountChangeEvent(), "ChildrenModificationEvent");
An EventType used when the TreeItem receives a modification to its
value property.
Type parameters: - <T> – The type of the value contained within the TreeItem.
Returns: The EventType when the TreeItem receives a modification to its
value property
/**
* An EventType used when the TreeItem receives a modification to its
* value property.
*
* @param <T> The type of the value contained within the TreeItem.
* @return The EventType when the TreeItem receives a modification to its
* value property
*/
@SuppressWarnings("unchecked")
public static <T> EventType<TreeModificationEvent<T>> valueChangedEvent() {
return (EventType<TreeModificationEvent<T>>) VALUE_CHANGED_EVENT;
}
private static final EventType<?> VALUE_CHANGED_EVENT
= new EventType<>(treeNotificationEvent(), "ValueChangedEvent");
An EventType used when the TreeItem receives a modification to its
graphic property.
Type parameters: - <T> – The type of the value contained within the TreeItem.
Returns: The EventType when the TreeItem receives a modification to its
graphic property
/**
* An EventType used when the TreeItem receives a modification to its
* graphic property.
*
* @param <T> The type of the value contained within the TreeItem.
* @return The EventType when the TreeItem receives a modification to its
* graphic property
*/
@SuppressWarnings("unchecked")
public static <T> EventType<TreeModificationEvent<T>> graphicChangedEvent() {
return (EventType<TreeModificationEvent<T>>) GRAPHIC_CHANGED_EVENT;
}
private static final EventType<?> GRAPHIC_CHANGED_EVENT
= new EventType<>(treeNotificationEvent(), "GraphicChangedEvent");
/***************************************************************************
* *
* Constructors *
* *
**************************************************************************/
Creates an empty TreeItem.
/**
* Creates an empty TreeItem.
*/
public TreeItem() {
this(null);
}
Creates a TreeItem with the value property set to the provided object.
Params: - value – The object to be stored as the value of this TreeItem.
/**
* Creates a TreeItem with the value property set to the provided object.
*
* @param value The object to be stored as the value of this TreeItem.
*/
public TreeItem(final T value) {
this(value, (Node)null);
}
Creates a TreeItem with the value property set to the provided object, and
the graphic set to the provided Node.
Params: - value – The object to be stored as the value of this TreeItem.
- graphic – The Node to show in the TreeView next to this TreeItem.
/**
* Creates a TreeItem with the value property set to the provided object, and
* the graphic set to the provided Node.
*
* @param value The object to be stored as the value of this TreeItem.
* @param graphic The Node to show in the TreeView next to this TreeItem.
*/
public TreeItem(final T value, final Node graphic) {
setValue(value);
setGraphic(graphic);
addEventHandler(TreeItem.<Object>expandedItemCountChangeEvent(), itemListener);
}
private final EventHandler<TreeModificationEvent<Object>> itemListener =
new EventHandler<TreeModificationEvent<Object>>() {
@Override public void handle(TreeModificationEvent<Object> event) {
expandedDescendentCountDirty = true;
}
};
*
Instance Variables *
*
/***************************************************************************
* *
* Instance Variables *
* *
**************************************************************************/
private boolean ignoreSortUpdate = false;
private boolean expandedDescendentCountDirty = true;
// The ObservableList containing all children belonging to this TreeItem.
// It is important that interactions with this list go directly into the
// children property, rather than via getChildren(), as this may be
// a very expensive call.
ObservableList<TreeItem<T>> children;
// Made static based on findings of RT-18344 - EventHandlerManager is an
// expensive class and should be reused amongst classes if at all possible.
private final EventHandlerManager eventHandlerManager =
new EventHandlerManager(this);
// Rather than have the TreeView need to (pretty well) constantly determine
// the expanded descendent count of a TreeItem, we instead cache it locally
// based on tree item modification events.
private int expandedDescendentCount = 1;
// we record the previous value also, so that we can easily determine how
// many items just disappeared on a TreeItem collapse event. Note that the
// actual number of items that disappeared is one less than this value,
// because we obviously are also counting this node, which hasn't disappeared
// when all children are collapsed.
int previousExpandedDescendentCount = 1;
Comparator<TreeItem<T>> lastComparator = null;
TreeSortMode lastSortMode = null;
// Refer to the TreeItem.updateChildrenParent method below for more context
// and a description of this field
private int parentLinkCount = 0;
*
Callbacks and events *
*
/***************************************************************************
* *
* Callbacks and events *
* *
**************************************************************************/
// called whenever the contents of the children sequence changes
private ListChangeListener<TreeItem<T>> childrenListener = c -> {
expandedDescendentCountDirty = true;
updateChildren(c);
};
*
Properties *
*
/***************************************************************************
* *
* Properties *
* *
**************************************************************************/
// --- Value
private ObjectProperty<T> value;
Sets the application-specific data represented by this TreeItem.
Params: - value – the application-specific data
/**
* Sets the application-specific data represented by this TreeItem.
* @param value the application-specific data
*/
public final void setValue(T value) { valueProperty().setValue(value); }
Returns the application-specific data represented by this TreeItem.
Returns: the data represented by this TreeItem
/**
* Returns the application-specific data represented by this TreeItem.
* @return the data represented by this TreeItem
*/
public final T getValue() { return value == null ? null : value.getValue(); }
A property representing the application-specific data contained within
this TreeItem.
Returns: the property representing the application-specific data contained
within this TreeItem
/**
* A property representing the application-specific data contained within
* this TreeItem.
* @return the property representing the application-specific data contained
* within this TreeItem
*/
public final ObjectProperty<T> valueProperty() {
if (value == null) {
value = new ObjectPropertyBase<T>() {
@Override protected void invalidated() {
fireEvent(new TreeModificationEvent<T>(VALUE_CHANGED_EVENT, TreeItem.this, get()));
}
@Override public Object getBean() {
return TreeItem.this;
}
@Override public String getName() {
return "value";
}
};
}
return value;
}
// --- Graphic
private ObjectProperty<Node> graphic;
Sets the node that is generally shown to the left of the value property.
For best effect, this tends to be a 16x16 image.
Params: - value – The graphic node that will be displayed to the user.
/**
* Sets the node that is generally shown to the left of the value property.
* For best effect, this tends to be a 16x16 image.
*
* @param value The graphic node that will be displayed to the user.
*/
public final void setGraphic(Node value) { graphicProperty().setValue(value); }
Returns the node that is generally shown to the left of the value property.
For best effect, this tends to be a 16x16 image.
Returns: The graphic node that will be displayed to the user.
/**
* Returns the node that is generally shown to the left of the value property.
* For best effect, this tends to be a 16x16 image.
*
* @return The graphic node that will be displayed to the user.
*/
public final Node getGraphic() { return graphic == null ? null : graphic.getValue(); }
The node that is generally shown to the left of the value property. For
best effect, this tends to be a 16x16 image.
Returns: The node that is generally shown to the left of the value property
/**
* The node that is generally shown to the left of the value property. For
* best effect, this tends to be a 16x16 image.
* @return The node that is generally shown to the left of the value property
*/
public final ObjectProperty<Node> graphicProperty() {
if (graphic == null) {
graphic = new ObjectPropertyBase<Node>() {
@Override protected void invalidated() {
fireEvent(new TreeModificationEvent<T>(GRAPHIC_CHANGED_EVENT, TreeItem.this));
}
@Override
public Object getBean() {
return TreeItem.this;
}
@Override
public String getName() {
return "graphic";
}
};
}
return graphic;
}
// --- Expanded
private BooleanProperty expanded;
Sets the expanded state of this TreeItem. This has no effect on a TreeItem
with no children. On a TreeItem with children however, the result of
toggling this property is that visually the children will either become
visible or hidden, based on whether expanded is set to true or false.
Params: - value – If this TreeItem has children, calling setExpanded with
true
will result in the children becoming visible.
Calling setExpanded with false
will hide any children
belonging to the TreeItem.
/**
* Sets the expanded state of this TreeItem. This has no effect on a TreeItem
* with no children. On a TreeItem with children however, the result of
* toggling this property is that visually the children will either become
* visible or hidden, based on whether expanded is set to true or false.
*
* @param value If this TreeItem has children, calling setExpanded with
* <code>true</code> will result in the children becoming visible.
* Calling setExpanded with <code>false</code> will hide any children
* belonging to the TreeItem.
*/
public final void setExpanded(boolean value) {
if (! value && expanded == null) return;
expandedProperty().setValue(value);
}
Returns the expanded state of this TreeItem.
Returns: Returns the expanded state of this TreeItem.
/**
* Returns the expanded state of this TreeItem.
*
* @return Returns the expanded state of this TreeItem.
*/
public final boolean isExpanded() { return expanded == null ? false : expanded.getValue(); }
The expanded state of this TreeItem.
Returns: The expanded state property of this TreeItem
/**
* The expanded state of this TreeItem.
* @return The expanded state property of this TreeItem
*/
public final BooleanProperty expandedProperty() {
if (expanded == null) {
expanded = new BooleanPropertyBase() {
@Override protected void invalidated() {
// We don't fire expanded events for leaf nodes (RT-32620)
if (isLeaf()) return;
EventType<?> evtType = isExpanded() ?
BRANCH_EXPANDED_EVENT : BRANCH_COLLAPSED_EVENT;
fireEvent(new TreeModificationEvent<T>(evtType, TreeItem.this, isExpanded()));
}
@Override
public Object getBean() {
return TreeItem.this;
}
@Override
public String getName() {
return "expanded";
}
};
}
return expanded;
}
// --- Leaf
private ReadOnlyBooleanWrapper leaf;
private void setLeaf(boolean value) {
if (value && leaf == null) {
return;
} else if (leaf == null) {
leaf = new ReadOnlyBooleanWrapper(this, "leaf", true);
}
leaf.setValue(value);
}
A TreeItem is a leaf if it has no children. The isLeaf method may of
course be overridden by subclasses to support alternate means of defining
how a TreeItem may be a leaf, but the general premise is the same: a
leaf can not be expanded by the user, and as such will not show a
disclosure node or respond to expansion requests.
Returns: true if this TreeItem has no children
/**
* A TreeItem is a leaf if it has no children. The isLeaf method may of
* course be overridden by subclasses to support alternate means of defining
* how a TreeItem may be a leaf, but the general premise is the same: a
* leaf can not be expanded by the user, and as such will not show a
* disclosure node or respond to expansion requests.
* @return true if this TreeItem has no children
*/
public boolean isLeaf() { return leaf == null ? true : leaf.getValue(); }
Represents the TreeItem leaf property, which is true if the TreeItem has no children.
Returns: the TreeItem leaf property
/**
* Represents the TreeItem leaf property, which is true if the TreeItem has no children.
* @return the TreeItem leaf property
*/
public final ReadOnlyBooleanProperty leafProperty() {
if (leaf == null) {
leaf = new ReadOnlyBooleanWrapper(this, "leaf", true);
}
return leaf.getReadOnlyProperty();
}
// --- Parent
private ReadOnlyObjectWrapper<TreeItem<T>> parent = new ReadOnlyObjectWrapper<TreeItem<T>>(this, "parent");
private void setParent(TreeItem<T> value) { parent.setValue(value); }
The parent of this TreeItem. Each TreeItem can have no more than one
parent. If a TreeItem has no parent, it represents a root in the tree model.
Returns: The parent of this TreeItem, or null if the TreeItem has no parent.
/**
* The parent of this TreeItem. Each TreeItem can have no more than one
* parent. If a TreeItem has no parent, it represents a root in the tree model.
*
* @return The parent of this TreeItem, or null if the TreeItem has no parent.
*/
public final TreeItem<T> getParent() { return parent == null ? null : parent.getValue(); }
A property that represents the parent of this TreeItem.
Returns: the parent property of this TreeItem
/**
* A property that represents the parent of this TreeItem.
* @return the parent property of this TreeItem
*/
public final ReadOnlyObjectProperty<TreeItem<T>> parentProperty() { return parent.getReadOnlyProperty(); }
/***********************************************************************
* *
* TreeItem API *
* *
**********************************************************************/
The children of this TreeItem. This method is called frequently, and
it is therefore recommended that the returned list be cached by
any TreeItem implementations.
Returns: a list that contains the child TreeItems belonging to the TreeItem.
/**
* The children of this TreeItem. This method is called frequently, and
* it is therefore recommended that the returned list be cached by
* any TreeItem implementations.
*
* @return a list that contains the child TreeItems belonging to the TreeItem.
*/
public ObservableList<TreeItem<T>> getChildren() {
if (children == null) {
children = FXCollections.observableArrayList();
children.addListener(childrenListener);
}
// we need to check if this TreeItem needs to have its children sorted.
// There are two different ways that this could be possible.
if (children.isEmpty()) return children;
// checkSortState should in almost all instances be called, but there
// are situations where checking the sort state will result in
// unwanted permutation events being fired (if a sort is applied). To
// avoid this (which resolves RT-37593), we set the ignoreSortUpdate
// to true (and of course, we're careful to set it back to false again)
if (!ignoreSortUpdate) {
checkSortState();
}
return children;
}
/***************************************************************************
* *
* Public API *
* *
**************************************************************************/
Returns the previous sibling of the TreeItem. Ordering is based on the
position of the TreeItem relative to its siblings in the children
list belonging to the parent of the TreeItem.
Returns: A TreeItem that is the previous sibling of the current TreeItem,
or null if no such sibling can be found.
/**
* Returns the previous sibling of the TreeItem. Ordering is based on the
* position of the TreeItem relative to its siblings in the children
* list belonging to the parent of the TreeItem.
*
* @return A TreeItem that is the previous sibling of the current TreeItem,
* or null if no such sibling can be found.
*/
public TreeItem<T> previousSibling() {
return previousSibling(this);
}
Returns the previous sibling after the given node. Ordering is based on the
position of the given TreeItem relative to its siblings in the children
list belonging to the parent of the TreeItem.
Params: - beforeNode – The TreeItem for which the previous sibling is being
sought.
Returns: A TreeItem that is the previous sibling of the given TreeItem,
or null if no such sibling can be found.
/**
* Returns the previous sibling after the given node. Ordering is based on the
* position of the given TreeItem relative to its siblings in the children
* list belonging to the parent of the TreeItem.
*
* @param beforeNode The TreeItem for which the previous sibling is being
* sought.
* @return A TreeItem that is the previous sibling of the given TreeItem,
* or null if no such sibling can be found.
*/
public TreeItem<T> previousSibling(final TreeItem<T> beforeNode) {
if (getParent() == null || beforeNode == null) {
return null;
}
List<TreeItem<T>> parentChildren = getParent().getChildren();
final int childCount = parentChildren.size();
int pos = -1;
for (int i = 0; i < childCount; i++) {
if (beforeNode.equals(parentChildren.get(i))) {
pos = i - 1;
return pos < 0 ? null : parentChildren.get(pos);
}
}
return null;
}
Returns the next sibling of the TreeItem. Ordering is based on the
position of the TreeItem relative to its siblings in the children
list belonging to the parent of the TreeItem.
Returns: A TreeItem that is the next sibling of the current TreeItem,
or null if no such sibling can be found.
/**
* Returns the next sibling of the TreeItem. Ordering is based on the
* position of the TreeItem relative to its siblings in the children
* list belonging to the parent of the TreeItem.
*
* @return A TreeItem that is the next sibling of the current TreeItem,
* or null if no such sibling can be found.
*/
public TreeItem<T> nextSibling() {
return nextSibling(this);
}
Returns the next sibling after the given node. Ordering is based on the
position of the given TreeItem relative to its siblings in the children
list belonging to the parent of the TreeItem.
Params: - afterNode – The TreeItem for which the next sibling is being
sought.
Returns: A TreeItem that is the next sibling of the given TreeItem,
or null if no such sibling can be found.
/**
* Returns the next sibling after the given node. Ordering is based on the
* position of the given TreeItem relative to its siblings in the children
* list belonging to the parent of the TreeItem.
*
* @param afterNode The TreeItem for which the next sibling is being
* sought.
* @return A TreeItem that is the next sibling of the given TreeItem,
* or null if no such sibling can be found.
*/
public TreeItem<T> nextSibling(final TreeItem<T> afterNode) {
if (getParent() == null || afterNode == null) {
return null;
}
List<TreeItem<T>> parentChildren = getParent().getChildren();
final int childCount = parentChildren.size();
int pos = -1;
for (int i = 0; i < childCount; i++) {
if (afterNode.equals(parentChildren.get(i))) {
pos = i + 1;
return pos >= childCount ? null : parentChildren.get(pos);
}
}
return null;
}
Returns a string representation of this TreeItem
object. Returns: a string representation of this TreeItem
object.
/**
* Returns a string representation of this {@code TreeItem} object.
* @return a string representation of this {@code TreeItem} object.
*/
@Override public String toString() {
return "TreeItem [ value: " + getValue() + " ]";
}
private void fireEvent(TreeModificationEvent<T> evt) {
Event.fireEvent(this, evt);
}
/***************************************************************************
* *
* Event Target Implementation / API *
* *
**************************************************************************/
{@inheritDoc} /** {@inheritDoc} */
@Override public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) {
// To allow for a TreeView (and its skin) to be notified of changes in the
// tree, this method recursively calls up to the root node, at which point
// it fires a ROOT_NOTIFICATION_EVENT, which the TreeView may be watching for.
if (getParent() != null) {
getParent().buildEventDispatchChain(tail);
}
return tail.append(eventHandlerManager);
}
Registers an event handler to this TreeItem. The TreeItem class allows
registration of listeners which will be notified as the
number of items changes, their position or if the values themselves change.
Note however that a TreeItem is not a Node, and therefore no visual events will be fired on the TreeItem. To get these events, it is necessary to add relevant observers to the TreeCell instances (via a custom cell factory - see the Cell
class documentation for more details). Params: - eventType – the type of the events to receive by the handler
- eventHandler – the handler to register
Type parameters: - <E> – The event
Throws: - NullPointerException – if the event type or handler is null
/**
* Registers an event handler to this TreeItem. The TreeItem class allows
* registration of listeners which will be notified as the
* number of items changes, their position or if the values themselves change.
* Note however that a TreeItem is <b>not</b> a Node, and therefore no visual
* events will be fired on the TreeItem. To get these events, it is necessary to
* add relevant observers to the TreeCell instances (via a custom cell factory -
* see the {@link Cell} class documentation for more details).
*
* @param <E> The event
* @param eventType the type of the events to receive by the handler
* @param eventHandler the handler to register
* @throws NullPointerException if the event type or handler is null
*/
public <E extends Event> void addEventHandler(EventType<E> eventType, EventHandler<E> eventHandler) {
eventHandlerManager.addEventHandler(eventType, eventHandler);
}
Unregisters a previously registered event handler from this TreeItem. One
handler might have been registered for different event types, so the
caller needs to specify the particular event type from which to
unregister the handler.
Params: - eventType – the event type from which to unregister
- eventHandler – the handler to unregister
Type parameters: - <E> – The event
Throws: - NullPointerException – if the event type or handler is null
/**
* Unregisters a previously registered event handler from this TreeItem. One
* handler might have been registered for different event types, so the
* caller needs to specify the particular event type from which to
* unregister the handler.
*
* @param <E> The event
* @param eventType the event type from which to unregister
* @param eventHandler the handler to unregister
* @throws NullPointerException if the event type or handler is null
*/
public <E extends Event> void removeEventHandler(EventType<E> eventType, EventHandler<E> eventHandler) {
eventHandlerManager.removeEventHandler(eventType, eventHandler);
}
*
private methods *
*
/***************************************************************************
* *
* private methods *
* *
**************************************************************************/
void sort() {
sort(children, lastComparator, lastSortMode);
}
private void sort(final ObservableList<TreeItem<T>> children,
final Comparator<TreeItem<T>> comparator,
final TreeSortMode sortMode) {
if (comparator == null) return;
runSort(children, comparator, sortMode);
// if we're at the root node, we'll fire an event so that the control
// can update its display
if (getParent() == null) {
TreeModificationEvent<T> e = new TreeModificationEvent<T>(TreeItem.childrenModificationEvent(), this);
e.wasPermutated = true;
fireEvent(e);
}
}
private void checkSortState() {
TreeItem<T> rootNode = getRoot();
TreeSortMode sortMode = rootNode.lastSortMode;
Comparator<TreeItem<T>> comparator = rootNode.lastComparator;
if (comparator != null && comparator != lastComparator) {
lastComparator = comparator;
runSort(children, comparator, sortMode);
}
}
private void runSort(ObservableList<TreeItem<T>> children, Comparator<TreeItem<T>> comparator, TreeSortMode sortMode) {
if (sortMode == ALL_DESCENDANTS) {
doSort(children, comparator);
} else if (sortMode == ONLY_FIRST_LEVEL) {
// if we are here we presume that the current node is the root node
// (but we can test to see if getParent() returns null to be sure).
// We also know that ONLY_FIRST_LEVEL only applies to the children
// of the root, so we return straight after we sort these children.
if (getParent() == null) {
doSort(children, comparator);
}
// } else if (sortMode == ONLY_LEAVES) {
// if (isLeaf()) {
// // sort the parent once
// }
// } else if (sortMode == ALL_BUT_LEAVES) {
//
} else {
// Unknown sort mode
}
}
private TreeItem<T> getRoot() {
TreeItem<T> parent = getParent();
if (parent == null) return this;
while (true) {
TreeItem<T> newParent = parent.getParent();
if (newParent == null) return parent;
parent = newParent;
}
}
private void doSort(ObservableList<TreeItem<T>> children, final Comparator<TreeItem<T>> comparator) {
if (!isLeaf() && isExpanded()) {
FXCollections.sort(children, comparator);
}
}
// This value is package accessible so that it may be retrieved from TreeView.
int getExpandedDescendentCount(boolean reset) {
if (reset || expandedDescendentCountDirty) {
updateExpandedDescendentCount(reset);
expandedDescendentCountDirty = false;
}
return expandedDescendentCount;
}
private void updateExpandedDescendentCount(boolean reset) {
previousExpandedDescendentCount = expandedDescendentCount;
expandedDescendentCount = 1;
ignoreSortUpdate = true;
if (!isLeaf() && isExpanded()) {
for (TreeItem<T> child : getChildren()) {
if (child == null) continue;
expandedDescendentCount += child.isExpanded() ? child.getExpandedDescendentCount(reset) : 1;
}
}
ignoreSortUpdate = false;
}
private void updateChildren(ListChangeListener.Change<? extends TreeItem<T>> c) {
setLeaf(children.isEmpty());
final List<TreeItem<T>> added = new ArrayList<>();
final List<TreeItem<T>> removed = new ArrayList<>();
while (c.next()) {
added.addAll(c.getAddedSubList());
removed.addAll(c.getRemoved());
}
// update the relationships such that all added children point to
// this node as the parent (and all removed children point to null)
updateChildrenParent(removed, null);
updateChildrenParent(added, this);
c.reset();
// fire an event up the parent hierarchy such that any listening
// TreeViews (which only listen to their root node) can redraw
fireEvent(new TreeModificationEvent<T>(
CHILDREN_MODIFICATION_EVENT, this, added, removed, c));
}
// Convenience method to set the parent of all children in the given list to
// the given parent TreeItem
private static <T> void updateChildrenParent(List<? extends TreeItem<T>> treeItems, final TreeItem<T> newParent) {
if (treeItems == null) return;
for (final TreeItem<T> treeItem : treeItems) {
if (treeItem == null) continue;
TreeItem<T> currentParent = treeItem.getParent();
// We only replace the parent if the parentLinkCount of the given
// TreeItem is zero (which indicates that this TreeItem has not been
// 'linked' to its parent multiple times). This can happen in
// situations such as what is shown in RT-28668 (and tested for in
// TreeViewTest.test_rt28556()). Specifically, when a sort is applied
// to the children of a TreeItem, it is possible for them to be
// sorted in such a way that the element is considered to be
// added in multiple places in the child list and then removed from
// one of those places subsequently. In doing this final removal,
// the parent of that TreeItem is set to null when it should in fact
// remain with the parent that it belongs to.
if (treeItem.parentLinkCount == 0) {
treeItem.setParent(newParent);
}
boolean parentMatch = currentParent != null && currentParent.equals(newParent);
if (parentMatch) {
if (newParent == null) {
treeItem.parentLinkCount--;
} else {
treeItem.parentLinkCount++;
}
}
}
}
An Event
that contains relevant information for all forms of TreeItem modifications. Type parameters: - <T> – The TreeModificationEvent
Since: JavaFX 2.0
/**
* An {@link Event} that contains relevant information for all forms of
* TreeItem modifications.
* @param <T> The TreeModificationEvent
* @since JavaFX 2.0
*/
public static class TreeModificationEvent<T> extends Event {
private static final long serialVersionUID = 4741889985221719579L;
Common supertype for all tree modification event types.
Since: JavaFX 8.0
/**
* Common supertype for all tree modification event types.
* @since JavaFX 8.0
*/
public static final EventType<?> ANY = TREE_NOTIFICATION_EVENT;
private transient final TreeItem<T> treeItem;
private final T newValue;
private final List<? extends TreeItem<T>> added;
private final List<? extends TreeItem<T>> removed;
private final ListChangeListener.Change<? extends TreeItem<T>> change;
private final boolean wasExpanded;
private final boolean wasCollapsed;
private boolean wasPermutated;
Constructs a basic TreeModificationEvent - this is useful in situations
where the tree item has not received a new value, has not changed
between expanded/collapsed states, and whose children has not changed.
An example of when this constructor is used is when the TreeItem
graphic property changes.
Params: - eventType – The type of the event that has occurred.
- treeItem – The TreeItem on which this event occurred.
/**
* Constructs a basic TreeModificationEvent - this is useful in situations
* where the tree item has not received a new value, has not changed
* between expanded/collapsed states, and whose children has not changed.
* An example of when this constructor is used is when the TreeItem
* graphic property changes.
*
* @param eventType The type of the event that has occurred.
* @param treeItem The TreeItem on which this event occurred.
*/
public TreeModificationEvent(EventType<? extends Event> eventType, TreeItem<T> treeItem) {
this (eventType, treeItem, null);
}
Constructs a TreeModificationEvent for when the TreeItem has had its TreeItem.valueProperty()
changed. Params: - eventType – The type of the event that has occurred.
- treeItem – The TreeItem on which this event occurred.
- newValue – The new value that has been put into the
TreeItem.valueProperty()
.
/**
* Constructs a TreeModificationEvent for when the TreeItem has had its
* {@link TreeItem#valueProperty()} changed.
*
* @param eventType The type of the event that has occurred.
* @param treeItem The TreeItem on which this event occurred.
* @param newValue The new value that has been put into the
* {@link TreeItem#valueProperty()}.
*/
public TreeModificationEvent(EventType<? extends Event> eventType,
TreeItem<T> treeItem, T newValue) {
super(eventType);
this.treeItem = treeItem;
this.newValue = newValue;
this.added = null;
this.removed = null;
this.change = null;
this.wasExpanded = false;
this.wasCollapsed = false;
}
Constructs a TreeModificationEvent for when the TreeItem has had its TreeItem.expandedProperty()
changed. Params: - eventType – The type of the event that has occurred.
- treeItem – The TreeItem on which this event occurred.
- expanded – A boolean to represent the current expanded
state of the TreeItem.
/**
* Constructs a TreeModificationEvent for when the TreeItem has had its
* {@link TreeItem#expandedProperty()} changed.
*
* @param eventType The type of the event that has occurred.
* @param treeItem The TreeItem on which this event occurred.
* @param expanded A boolean to represent the current expanded
* state of the TreeItem.
*/
public TreeModificationEvent(EventType<? extends Event> eventType,
TreeItem<T> treeItem, boolean expanded) {
super(eventType);
this.treeItem = treeItem;
this.newValue = null;
this.added = null;
this.removed = null;
this.change = null;
this.wasExpanded = expanded;
this.wasCollapsed = ! expanded;
}
Constructs a TreeModificationEvent for when the TreeItem has had its
children list changed.
Params: - eventType – The type of the event that has occurred.
- treeItem – The TreeItem on which this event occurred.
- added – A list of the items added to the children list of the
given TreeItem.
- removed – A list of the items removed from the children list of
the given TreeItem.
/**
* Constructs a TreeModificationEvent for when the TreeItem has had its
* children list changed.
*
* @param eventType The type of the event that has occurred.
* @param treeItem The TreeItem on which this event occurred.
* @param added A list of the items added to the children list of the
* given TreeItem.
* @param removed A list of the items removed from the children list of
* the given TreeItem.
*/
public TreeModificationEvent(EventType<? extends Event> eventType,
TreeItem<T> treeItem,
List<? extends TreeItem<T>> added,
List<? extends TreeItem<T>> removed) {
this(eventType, treeItem, added, removed, null);
}
Constructs a TreeModificationEvent for when the TreeItem has had its children list changed, including the Change
that has taken place. Params: - eventType – The type of the event that has occurred.
- treeItem – The TreeItem on which this event occurred.
- added – A list of the items added to the children list of the
given TreeItem.
- removed – A list of the items removed from the children list of
the given TreeItem.
- change – The actual change that has taken place on the children list.
/**
* Constructs a TreeModificationEvent for when the TreeItem has had its
* children list changed, including the
* {@link javafx.collections.ListChangeListener.Change} that has taken place.
*
* @param eventType The type of the event that has occurred.
* @param treeItem The TreeItem on which this event occurred.
* @param added A list of the items added to the children list of the
* given TreeItem.
* @param removed A list of the items removed from the children list of
* the given TreeItem.
* @param change The actual change that has taken place on the children list.
*/
private TreeModificationEvent(EventType<? extends Event> eventType,
TreeItem<T> treeItem,
List<? extends TreeItem<T>> added,
List<? extends TreeItem<T>> removed,
ListChangeListener.Change<? extends TreeItem<T>> change) {
super(eventType);
this.treeItem = treeItem;
this.newValue = null;
this.added = added;
this.removed = removed;
this.change = change;
this.wasExpanded = false;
this.wasCollapsed = false;
this.wasPermutated = added != null && removed != null &&
added.size() == removed.size() &&
added.containsAll(removed);
}
Returns the TreeItem upon which this event occurred.
Since: JavaFX 2.1
/**
* Returns the TreeItem upon which this event occurred.
* @since JavaFX 2.1
*/
@Override public TreeItem<T> getSource() {
return this.treeItem;
}
Returns the TreeItem that this event occurred upon.
Returns: The TreeItem that this event occurred upon.
/**
* Returns the TreeItem that this event occurred upon.
* @return The TreeItem that this event occurred upon.
*/
public TreeItem<T> getTreeItem() {
return treeItem;
}
If the value of the TreeItem changed, this method will return the new
value. If it did not change, this method will return null.
Returns: The new value of the TreeItem if it changed, null otherwise.
/**
* If the value of the TreeItem changed, this method will return the new
* value. If it did not change, this method will return null.
* @return The new value of the TreeItem if it changed, null otherwise.
*/
public T getNewValue() {
return newValue;
}
Returns the children added to the TreeItem in this event, or an empty
list if no children were added.
Returns: The newly added children, or an empty list if no children
were added.
/**
* Returns the children added to the TreeItem in this event, or an empty
* list if no children were added.
* @return The newly added children, or an empty list if no children
* were added.
*/
public List<? extends TreeItem<T>> getAddedChildren() {
return added == null ? Collections.<TreeItem<T>>emptyList() : added;
}
Returns the children removed from the TreeItem in this event, or an
empty list if no children were added.
Returns: The removed children, or an empty list if no children
were removed.
/**
* Returns the children removed from the TreeItem in this event, or an
* empty list if no children were added.
* @return The removed children, or an empty list if no children
* were removed.
*/
public List<? extends TreeItem<T>> getRemovedChildren() {
return removed == null ? Collections.<TreeItem<T>>emptyList() : removed;
}
Returns the number of children items that were removed in this event,
or zero if no children were removed.
Returns: The number of removed children items, or zero if no children
were removed.
/**
* Returns the number of children items that were removed in this event,
* or zero if no children were removed.
* @return The number of removed children items, or zero if no children
* were removed.
*/
public int getRemovedSize() {
return getRemovedChildren().size();
}
Returns the number of children items that were added in this event,
or zero if no children were added.
Returns: The number of added children items, or zero if no children
were added.
/**
* Returns the number of children items that were added in this event,
* or zero if no children were added.
* @return The number of added children items, or zero if no children
* were added.
*/
public int getAddedSize() {
return getAddedChildren().size();
}
Returns true if this event represents a TreeItem expansion event,
and false if the TreeItem was not expanded.
Returns: true if this event represents a TreeItem expansion event,
and false if the TreeItem was not expanded
/**
* Returns true if this event represents a TreeItem expansion event,
* and false if the TreeItem was not expanded.
* @return true if this event represents a TreeItem expansion event,
* and false if the TreeItem was not expanded
*/
public boolean wasExpanded() { return wasExpanded; }
Returns true if this event represents a TreeItem collapse event,
and false if the TreeItem was not collapsed.
Returns: true if this event represents a TreeItem collapse event,
and false if the TreeItem was not collapsed
/**
* Returns true if this event represents a TreeItem collapse event,
* and false if the TreeItem was not collapsed.
* @return true if this event represents a TreeItem collapse event,
* and false if the TreeItem was not collapsed
*/
public boolean wasCollapsed() { return wasCollapsed; }
Returns true if this event represents a TreeItem event where children
TreeItems were added.
Returns: true if this event represents a TreeItem event where children
TreeItems were added
/**
* Returns true if this event represents a TreeItem event where children
* TreeItems were added.
* @return true if this event represents a TreeItem event where children
* TreeItems were added
*/
public boolean wasAdded() { return getAddedSize() > 0; }
Returns true if this event represents a TreeItem event where children
TreeItems were removed.
Returns: true if this event represents a TreeItem event where children
TreeItems were removed
/**
* Returns true if this event represents a TreeItem event where children
* TreeItems were removed.
* @return true if this event represents a TreeItem event where children
* TreeItems were removed
*/
public boolean wasRemoved() { return getRemovedSize() > 0; }
Returns true if the order of the TreeItem children list has changed,
but that there have been no additions or removals.
Returns: true if the order of the TreeItem children list has changed,
but that there have been no additions or removals
/**
* Returns true if the order of the TreeItem children list has changed,
* but that there have been no additions or removals.
* @return true if the order of the TreeItem children list has changed,
* but that there have been no additions or removals
*/
public boolean wasPermutated() { return wasPermutated; }
int getFrom() { return change == null ? -1 : change.getFrom(); }
int getTo() { return change == null ? -1 : change.getTo(); }
ListChangeListener.Change<? extends TreeItem<T>> getChange() { return change; }
}
}