/* * Copyright (c) 2012, 2016, 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 com.sun.javafx.scene.control.Properties; import javafx.css.CssMetaData; import java.util.Collections; import java.util.List; import java.util.Map; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ObservableValue; import javafx.beans.value.WritableValue; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.collections.WeakListChangeListener; import javafx.event.Event; import javafx.event.EventHandler; import javafx.event.EventTarget; import javafx.event.EventType; import javafx.scene.Node; import javafx.scene.control.skin.*; import javafx.util.Callback; import javafx.css.Styleable; /** * A {@link TreeTableView} is made up of a number of TreeTableColumn instances. Each * TreeTableColumn in a {@link TreeTableView} is responsible for displaying * (and editing) the contents of that column. As well as being responsible for * displaying and editing data for a single column, a TreeTableColumn also * contains the necessary properties to: *
{@code * firstNameCol.setCellValueFactory(new Callback* * This approach assumes that the object returned from, ObservableValue >() { * public ObservableValue call(CellDataFeatures p) { * // p.getValue() returns the TreeItem instance for a particular TreeTableView row, * // p.getValue().getValue() returns the Person instance inside the TreeItem * return p.getValue().getValue().firstNameProperty(); * } * }); * }}
p.getValue().getValue()
* has a JavaFX {@link ObservableValue} that can simply be returned. The benefit of this
* is that the TableView will internally create bindings to ensure that,
* should the returned {@link ObservableValue} change, the cell contents will be
* automatically refreshed.
*
* In situations where a TableColumn must interact with classes created before * JavaFX, or that generally do not wish to use JavaFX APIs for properties, it is * possible to wrap the returned value in a {@link ReadOnlyObjectWrapper} instance. For * example: * *
{@code * firstNameCol.setCellValueFactory(new Callback* * It is hoped that over time there will be convenience cell value factories * developed and made available to developers. As of the JavaFX 2.0 release, * there is one such convenience class: {@link javafx.scene.control.cell.TreeItemPropertyValueFactory}. * This class removes the need to write the code above, instead relying on reflection to * look up a given property from a String. Refer to the *, ObservableValue >() { * public ObservableValue call(CellDataFeatures p) { * // p.getValue() returns the TreeItem instance for a particular TreeTableView row, * // p.getValue().getValue() returns the Person instance inside the TreeItem * return new ReadOnlyObjectWrapper(p.getValue().getValue().getFirstName()); * } * }); * }}
TreeItemPropertyValueFactory
class documentation for more information
* on how to use this with a TableColumn.
*
* Finally, for more detail on how to use TableColumn, there is further documentation in
* the {@link TableView} class documentation.
*
* @param toString()
if it is not null, setting the resulting string
* inside the {@link Cell#textProperty() text} property.
*/
public static final CallbackAn example of how to set a cell value factory is: * *
{@code * firstNameCol.setCellValueFactory(new Callback* * A common approach is to want to populate cells in a TreeTableColumn using * a single value from a Java bean. To support this common scenario, there * is the {@link javafx.scene.control.cell.TreeItemPropertyValueFactory} class. * Refer to this class for more information on how to use it, but briefly * here is how the above use case could be simplified using the TreeItemPropertyValueFactory class: * *, ObservableValue >() { * public ObservableValue call(CellDataFeatures p) { * // p.getValue() returns the TreeItem instance for a particular TreeTableView row, * // p.getValue().getValue() returns the Person instance inside the TreeItem * return p.getValue().getValue().firstNameProperty(); * } * }); * }}
* firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person,String>("firstName"));
*
*
* @see javafx.scene.control.cell.TreeItemPropertyValueFactory
*/
private ObjectPropertyBy default TreeTableColumn uses a {@link #DEFAULT_CELL_FACTORY default cell * factory}, but this can be replaced with a custom implementation, for * example to show data in a different way or to support editing. There is a * lot of documentation on creating custom cell factories * elsewhere (see {@link Cell} and {@link TreeTableView} for example).
* *Finally, there are a number of pre-built cell factories available in the
* {@link javafx.scene.control.cell} package.
*
*/
private final ObjectProperty>> cellFactory =
new SimpleObjectProperty>>(
this, "cellFactory", (Callback>) ((Callback) DEFAULT_CELL_FACTORY)) {
@Override protected void invalidated() {
TreeTableView table = getTreeTableView();
if (table == null) return;
Map