35 import javafx.scene.control.TreeTableColumn.CellDataFeatures;
36 import javafx.scene.control.TreeTableView;
37 import javafx.util.Callback;
38 import com.sun.javafx.property.PropertyReference;
39 import com.sun.javafx.scene.control.Logging;
40 import sun.util.logging.PlatformLogger;
41 import sun.util.logging.PlatformLogger.Level;
42
43
44 /**
45 * A convenience implementation of the Callback interface, designed specifically
46 * for use within the {@link TreeTableColumn}
47 * {@link TreeTableColumn#cellValueFactoryProperty() cell value factory}. An example
48 * of how to use this class is:
49 *
50 * <pre><code>
51 * TreeTableColumn<Person,String> firstNameCol = new TreeTableColumn<Person,String>("First Name");
52 * firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person,String>("firstName"));
53 * </code></pre>
54 *
55 *
56 * <p>
57 * In this example, {@code Person} is the class type of the {@link TreeItem}
58 * instances used in the {@link TreeTableView}.
59 * {@code TreeItemPropertyValueFactory} uses the constructor argument,
60 * {@code "firstName"}, to assume that {@code Person} has a method
61 * {@code firstNameProperty} with no formal parameters and a return type of
62 * {@code ObservableValue<String>}.
63 * </p>
64 * <p>
65 * If such a method exists, then it is invoked, and additionally assumed
66 * to return an instance of {@code Property<String>}. The return value is used
67 * to populate the {@link TreeTableCell}. In addition, the {@code TreeTableView}
68 * adds an observer to the return value, such that any changes fired will be
69 * observed by the {@code TreeTableView}, resulting in the cell immediately
70 * updating.
71 * </p>
72 * <p>
73 * If no such method exists, then {@code TreeItemPropertyValueFactory}
74 * assumes that {@code Person} has a method {@code getFirstName} or
75 * {@code isFirstName} with no formal parameters and a return type of
76 * {@code String}. If such a method exists, then it is invoked, and its return
77 * value is wrapped in a {@link ReadOnlyObjectWrapper}
78 * and returned to the {@code TreeTableCell}. In this situation,
79 * the {@code TreeTableCell} will not be able to observe changes to the property,
80 * unlike in the first approach above.
81 * </p>
82 * <p>
83 * The class {@code Person} must be declared public. If that class is in a named
84 * module, then the module must {@link Module#isOpen(String,Module) open}
85 * the containing package to at least the {@code javafx.base} module
86 * (or {@link Module#isExported(String) export} the containing package
87 * unconditionally).
88 * Otherwise the {@link #call call(TreeTableColumn.CellDataFeatures)} method
89 * will log a warning and return {@code null}.
90 * </p>
91 *
92 * <p>For reference (and as noted in the TreeTableColumn
93 * {@link TreeTableColumn#cellValueFactory cell value factory} documentation), the
94 * long form of the code above would be the following:
95 * </p>
96 *
97 * <pre><code>
98 * TreeTableColumn<Person,String> firstNameCol = new TreeTableColumn<Person,String>("First Name");
99 * {@literal
100 * firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
101 * public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
102 * // p.getValue() returns the TreeItem<Person> instance for a particular
103 * // TreeTableView row, and the second getValue() call returns the
104 * // Person instance contained within the TreeItem.
105 * return p.getValue().getValue().firstNameProperty();
106 * }
107 * });
108 * }
109 * }
110 * </code></pre>
111 *
112 * @see TreeTableColumn
113 * @see TreeTableView
114 * @see TreeTableCell
115 * @see PropertyValueFactory
116 * @see MapValueFactory
117 * @since JavaFX 8.0
118 */
119 public class TreeItemPropertyValueFactory<S,T> implements Callback<TreeTableColumn.CellDataFeatures<S,T>, ObservableValue<T>> {
120
121 private final String property;
122
123 private Class<?> columnClass;
124 private String previousProperty;
125 private PropertyReference<T> propertyRef;
126
127 /**
128 * Creates a default PropertyValueFactory to extract the value from a given
129 * TableView row item reflectively, using the given property name.
130 *
|
35 import javafx.scene.control.TreeTableColumn.CellDataFeatures;
36 import javafx.scene.control.TreeTableView;
37 import javafx.util.Callback;
38 import com.sun.javafx.property.PropertyReference;
39 import com.sun.javafx.scene.control.Logging;
40 import sun.util.logging.PlatformLogger;
41 import sun.util.logging.PlatformLogger.Level;
42
43
44 /**
45 * A convenience implementation of the Callback interface, designed specifically
46 * for use within the {@link TreeTableColumn}
47 * {@link TreeTableColumn#cellValueFactoryProperty() cell value factory}. An example
48 * of how to use this class is:
49 *
50 * <pre><code>
51 * TreeTableColumn<Person,String> firstNameCol = new TreeTableColumn<Person,String>("First Name");
52 * firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person,String>("firstName"));
53 * </code></pre>
54 *
55 * <p>
56 * In this example, {@code Person} is the class type of the {@link TreeItem}
57 * instances used in the {@link TreeTableView}.
58 * The class {@code Person} must be declared public.
59 * {@code TreeItemPropertyValueFactory} uses the constructor argument,
60 * {@code "firstName"}, to assume that {@code Person} has a public method
61 * {@code firstNameProperty} with no formal parameters and a return type of
62 * {@code ObservableValue<String>}.
63 * </p>
64 * <p>
65 * If such a method exists, then it is invoked, and additionally assumed
66 * to return an instance of {@code Property<String>}. The return value is used
67 * to populate the {@link TreeTableCell}. In addition, the {@code TreeTableView}
68 * adds an observer to the return value, such that any changes fired will be
69 * observed by the {@code TreeTableView}, resulting in the cell immediately
70 * updating.
71 * </p>
72 * <p>
73 * If no such method exists, then {@code TreeItemPropertyValueFactory}
74 * assumes that {@code Person} has a public method {@code getFirstName} or
75 * {@code isFirstName} with no formal parameters and a return type of
76 * {@code String}. If such a method exists, then it is invoked, and its return
77 * value is wrapped in a {@link ReadOnlyObjectWrapper}
78 * and returned to the {@code TreeTableCell}. In this situation,
79 * the {@code TreeTableCell} will not be able to observe changes to the property,
80 * unlike in the first approach above.
81 * </p>
82 *
83 * <p>For reference (and as noted in the TreeTableColumn
84 * {@link TreeTableColumn#cellValueFactory cell value factory} documentation), the
85 * long form of the code above would be the following:
86 * </p>
87 *
88 * <pre><code>
89 * TreeTableColumn<Person,String> firstNameCol = new TreeTableColumn<Person,String>("First Name");
90 * {@literal
91 * firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
92 * public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
93 * // p.getValue() returns the TreeItem<Person> instance for a particular
94 * // TreeTableView row, and the second getValue() call returns the
95 * // Person instance contained within the TreeItem.
96 * return p.getValue().getValue().firstNameProperty();
97 * }
98 * });
99 * }
100 * }
101 * </code></pre>
102 *
103 * <p><b>Deploying an Application as a Module</b></p>
104 * <p>
105 * If the referenced class is in a named module, then it must be reflectively
106 * accessible to the {@code javafx.base} module.
107 * A class is reflectively accessible if the module
108 * {@link Module#isOpen(String,Module) opens} the containing package to at
109 * least the {@code javafx.base} module.
110 * Otherwise the {@link #call call(TreeTableColumn.CellDataFeatures)} method
111 * will log a warning and return {@code null}.
112 * </p>
113 * <p>
114 * For example, if the {@code Person} class is in the {@code com.foo} package
115 * in the {@code foo.app} module, the {@code module-info.java} might
116 * look like this:
117 * </p>
118 *
119 <pre>{@code module foo.app {
120 opens com.foo to javafx.base;
121 }}</pre>
122 *
123 * <p>
124 * Alternatively, a class is reflectively accessible if the module
125 * {@link Module#isExported(String) exports} the containing package
126 * unconditionally.
127 * </p>
128 *
129 * @see TreeTableColumn
130 * @see TreeTableView
131 * @see TreeTableCell
132 * @see PropertyValueFactory
133 * @see MapValueFactory
134 * @since JavaFX 8.0
135 */
136 public class TreeItemPropertyValueFactory<S,T> implements Callback<TreeTableColumn.CellDataFeatures<S,T>, ObservableValue<T>> {
137
138 private final String property;
139
140 private Class<?> columnClass;
141 private String previousProperty;
142 private PropertyReference<T> propertyRef;
143
144 /**
145 * Creates a default PropertyValueFactory to extract the value from a given
146 * TableView row item reflectively, using the given property name.
147 *
|