37 import com.sun.javafx.scene.control.Logging; 38 import sun.util.logging.PlatformLogger; 39 import sun.util.logging.PlatformLogger.Level; 40 41 42 /** 43 * A convenience implementation of the Callback interface, designed specifically 44 * for use within the {@link TreeTableColumn} 45 * {@link TreeTableColumn#cellValueFactoryProperty() cell value factory}. An example 46 * of how to use this class is: 47 * 48 * <pre><code> 49 * TreeTableColumn<Person,String> firstNameCol = new TreeTableColumn<Person,String>("First Name"); 50 * firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person,String>("firstName")); 51 * </code></pre> 52 * 53 * In this example, the "firstName" string is used as a reference to an assumed 54 * <code>firstNameProperty()</code> method in the <code>Person</code> class type 55 * (which is the class type of the TreeTableView). Additionally, this method must 56 * return a {@link Property} instance. If a method meeting these requirements 57 * is found, then the {@link javafx.scene.control.TreeTableCell} is populated with this ObservableValue<T>. 58 * In addition, the TreeTableView will automatically add an observer to the 59 * returned value, such that any changes fired will be observed by the TreeTableView, 60 * resulting in the cell immediately updating. 61 * 62 * <p>If no method matching this pattern exists, there is fall-through support 63 * for attempting to call get<property>() or is<property>() (that is, 64 * <code>getFirstName()</code> or <code>isFirstName()</code> in the example 65 * above). If a method matching this pattern exists, the value returned from this method 66 * is wrapped in a {@link ReadOnlyObjectWrapper} and returned to the TreeTableCell. 67 * However, in this situation, this means that the TreeTableCell will not be able 68 * to observe the ObservableValue for changes (as is the case in the first 69 * approach above). 70 * 71 * <p>For reference (and as noted in the TreeTableColumn 72 * {@link TreeTableColumn#cellValueFactory cell value factory} documentation), the 73 * long form of the code above would be the following: 74 * 75 * <pre><code> 76 * TreeTableColumn<Person,String> firstNameCol = new TreeTableColumn<Person,String>("First Name"); 77 * firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() { 78 * public ObservableValue<String> call(CellDataFeatures<Person, String> p) { 79 * // p.getValue() returns the TreeItem<Person> instance for a particular 80 * // TreeTableView row, and the second getValue() call returns the 81 * // Person instance contained within the TreeItem. 82 * return p.getValue().getValue().firstNameProperty(); 83 * } 84 * }); 85 * } 86 * </code></pre> 87 * 88 * @see TreeTableColumn 89 * @see javafx.scene.control.TreeTableView 90 * @see javafx.scene.control.TreeTableCell 91 * @see PropertyValueFactory 92 * @see MapValueFactory 93 * @since JavaFX 8.0 94 */ 95 public class TreeItemPropertyValueFactory<S,T> implements Callback<TreeTableColumn.CellDataFeatures<S,T>, ObservableValue<T>> { 96 97 private final String property; 98 99 private Class<?> columnClass; 100 private String previousProperty; 101 private PropertyReference<T> propertyRef; 102 103 /** 104 * Creates a default PropertyValueFactory to extract the value from a given 105 * TableView row item reflectively, using the given property name. 106 * 107 * @param property The name of the property with which to attempt to 108 * reflectively extract a corresponding value for in a given object. 109 */ 110 public TreeItemPropertyValueFactory(@NamedArg("property") String property) { 111 this.property = property; 112 } 113 114 /** {@inheritDoc} */ 115 @Override public ObservableValue<T> call(CellDataFeatures<S, T> param) { 116 TreeItem<S> treeItem = param.getValue(); 117 return getCellDataReflectively(treeItem.getValue()); 118 } 119 120 /** 121 * Returns the property name provided in the constructor. 122 */ 123 public final String getProperty() { return property; } 124 125 private ObservableValue<T> getCellDataReflectively(S rowData) { 126 if (getProperty() == null || getProperty().isEmpty() || rowData == null) return null; 127 128 try { 129 // we attempt to cache the property reference here, as otherwise 130 // performance suffers when working in large data models. For 131 // a bit of reference, refer to RT-13937. 132 if (columnClass == null || previousProperty == null || 133 ! columnClass.equals(rowData.getClass()) || 134 ! previousProperty.equals(getProperty())) { 135 136 // create a new PropertyReference 137 this.columnClass = rowData.getClass(); 138 this.previousProperty = getProperty(); 139 this.propertyRef = new PropertyReference<T>(rowData.getClass(), getProperty()); 140 } 141 | 37 import com.sun.javafx.scene.control.Logging; 38 import sun.util.logging.PlatformLogger; 39 import sun.util.logging.PlatformLogger.Level; 40 41 42 /** 43 * A convenience implementation of the Callback interface, designed specifically 44 * for use within the {@link TreeTableColumn} 45 * {@link TreeTableColumn#cellValueFactoryProperty() cell value factory}. An example 46 * of how to use this class is: 47 * 48 * <pre><code> 49 * TreeTableColumn<Person,String> firstNameCol = new TreeTableColumn<Person,String>("First Name"); 50 * firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person,String>("firstName")); 51 * </code></pre> 52 * 53 * In this example, the "firstName" string is used as a reference to an assumed 54 * <code>firstNameProperty()</code> method in the <code>Person</code> class type 55 * (which is the class type of the TreeTableView). Additionally, this method must 56 * return a {@link Property} instance. If a method meeting these requirements 57 * is found, then the {@link javafx.scene.control.TreeTableCell} is populated 58 * with this {@literal ObservableValue<T>}. 59 * In addition, the TreeTableView will automatically add an observer to the 60 * returned value, such that any changes fired will be observed by the TreeTableView, 61 * resulting in the cell immediately updating. 62 * 63 * <p>If no method matching this pattern exists, there is fall-through support 64 * for attempting to call get<property>() or is<property>() (that is, 65 * <code>getFirstName()</code> or <code>isFirstName()</code> in the example 66 * above). If a method matching this pattern exists, the value returned from this method 67 * is wrapped in a {@link ReadOnlyObjectWrapper} and returned to the TreeTableCell. 68 * However, in this situation, this means that the TreeTableCell will not be able 69 * to observe the ObservableValue for changes (as is the case in the first 70 * approach above). 71 * 72 * <p>For reference (and as noted in the TreeTableColumn 73 * {@link TreeTableColumn#cellValueFactory cell value factory} documentation), the 74 * long form of the code above would be the following: 75 * 76 * <pre><code> 77 * TreeTableColumn<Person,String> firstNameCol = new TreeTableColumn<Person,String>("First Name"); 78 * {@literal 79 * firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() { 80 * public ObservableValue<String> call(CellDataFeatures<Person, String> p) { 81 * // p.getValue() returns the TreeItem<Person> instance for a particular 82 * // TreeTableView row, and the second getValue() call returns the 83 * // Person instance contained within the TreeItem. 84 * return p.getValue().getValue().firstNameProperty(); 85 * } 86 * }); 87 * } 88 * } 89 * </code></pre> 90 * 91 * @see TreeTableColumn 92 * @see javafx.scene.control.TreeTableView 93 * @see javafx.scene.control.TreeTableCell 94 * @see PropertyValueFactory 95 * @see MapValueFactory 96 * @since JavaFX 8.0 97 */ 98 public class TreeItemPropertyValueFactory<S,T> implements Callback<TreeTableColumn.CellDataFeatures<S,T>, ObservableValue<T>> { 99 100 private final String property; 101 102 private Class<?> columnClass; 103 private String previousProperty; 104 private PropertyReference<T> propertyRef; 105 106 /** 107 * Creates a default PropertyValueFactory to extract the value from a given 108 * TableView row item reflectively, using the given property name. 109 * 110 * @param property The name of the property with which to attempt to 111 * reflectively extract a corresponding value for in a given object. 112 */ 113 public TreeItemPropertyValueFactory(@NamedArg("property") String property) { 114 this.property = property; 115 } 116 117 /** {@inheritDoc} */ 118 @Override public ObservableValue<T> call(CellDataFeatures<S, T> param) { 119 TreeItem<S> treeItem = param.getValue(); 120 return getCellDataReflectively(treeItem.getValue()); 121 } 122 123 /** 124 * Returns the property name provided in the constructor. 125 * @return the property name provided in the constructor 126 */ 127 public final String getProperty() { return property; } 128 129 private ObservableValue<T> getCellDataReflectively(S rowData) { 130 if (getProperty() == null || getProperty().isEmpty() || rowData == null) return null; 131 132 try { 133 // we attempt to cache the property reference here, as otherwise 134 // performance suffers when working in large data models. For 135 // a bit of reference, refer to RT-13937. 136 if (columnClass == null || previousProperty == null || 137 ! columnClass.equals(rowData.getClass()) || 138 ! previousProperty.equals(getProperty())) { 139 140 // create a new PropertyReference 141 this.columnClass = rowData.getClass(); 142 this.previousProperty = getProperty(); 143 this.propertyRef = new PropertyReference<T>(rowData.getClass(), getProperty()); 144 } 145 |