149 /** 150 * Creates a cell factory for use in a TreeView control. Unlike 151 * {@link #forTreeView()}, this method does not assume that all TreeItem 152 * instances in the TreeView are {@link CheckBoxTreeItem} instances. 153 * 154 * <p>When used in a TreeView, the CheckBoxCell is rendered with a CheckBox 155 * to the right of the 'disclosure node' (i.e. the arrow). The item stored 156 * in {@link CheckBoxTreeItem#getValue()} will then have the StringConverter 157 * called on it, and this text will take all remaining horizontal space. 158 * 159 * <p>Unlike {@link #forTreeView()}, this cell factory does not handle 160 * updating the state of parent or children TreeItems - it simply toggles 161 * the {@code ObservableValue<Boolean>} that is provided, and no more. Of 162 * course, this functionality can then be implemented externally by adding 163 * observers to the {@code ObservableValue<Boolean>}, and toggling the state 164 * of other properties as necessary. 165 * 166 * @param <T> The type of the elements contained within the {@link TreeItem} 167 * instances. 168 * @param getSelectedProperty A {@link Callback} that, given an object of 169 * type TreeItem<T>, will return an {@code ObservableValue<Boolean>} 170 * that represents whether the given item is selected or not. This 171 * {@code ObservableValue<Boolean>} will be bound bidirectionally 172 * (meaning that the CheckBox in the cell will set/unset this property 173 * based on user interactions, and the CheckBox will reflect the state 174 * of the {@code ObservableValue<Boolean>}, if it changes externally). 175 * @return A {@link Callback} that will return a TreeCell that is able to 176 * work on the type of element contained within the TreeView root, and 177 * all of its children (recursively). 178 */ 179 public static <T> Callback<TreeView<T>, TreeCell<T>> forTreeView( 180 final Callback<TreeItem<T>, 181 ObservableValue<Boolean>> getSelectedProperty) { 182 return forTreeView(getSelectedProperty, CellUtils.<T>defaultTreeItemStringConverter()); 183 } 184 185 /** 186 * Creates a cell factory for use in a TreeView control. Unlike 187 * {@link #forTreeView()}, this method does not assume that all TreeItem 188 * instances in the TreeView are {@link CheckBoxTreeItem}. 189 * 190 * <p>When used in a TreeView, the CheckBoxCell is rendered with a CheckBox 191 * to the right of the 'disclosure node' (i.e. the arrow). The item stored 192 * in {@link TreeItem#getValue()} will then have the the StringConverter 193 * called on it, and this text will take all remaining horizontal space. 194 * 195 * <p>Unlike {@link #forTreeView()}, this cell factory does not handle 196 * updating the state of parent or children TreeItems - it simply toggles 197 * the {@code ObservableValue<Boolean>} that is provided, and no more. Of 198 * course, this functionality can then be implemented externally by adding 199 * observers to the {@code ObservableValue<Boolean>}, and toggling the state 200 * of other properties as necessary. 201 * 202 * @param <T> The type of the elements contained within the {@link TreeItem} 203 * instances. 204 * @param getSelectedProperty A Callback that, given an object of 205 * type TreeItem<T>, will return an {@code ObservableValue<Boolean>} 206 * that represents whether the given item is selected or not. This 207 * {@code ObservableValue<Boolean>} will be bound bidirectionally 208 * (meaning that the CheckBox in the cell will set/unset this property 209 * based on user interactions, and the CheckBox will reflect the state of 210 * the {@code ObservableValue<Boolean>}, if it changes externally). 211 * @param converter A StringConverter that, give an object of type TreeItem<T>, 212 * will return a String that can be used to represent the object 213 * visually. The default implementation in {@link #forTreeView(Callback)} 214 * is to simply call .toString() on all non-null items (and to just 215 * return an empty string in cases where the given item is null). 216 * @return A {@link Callback} that will return a TreeCell that is able to 217 * work on the type of element contained within the TreeView root, and 218 * all of its children (recursively). 219 */ 220 public static <T> Callback<TreeView<T>, TreeCell<T>> forTreeView( 221 final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedProperty, 222 final StringConverter<TreeItem<T>> converter) { 223 return tree -> new CheckBoxTreeCell<T>(getSelectedProperty, converter); 224 } 225 226 227 228 229 /*************************************************************************** 230 * * 231 * Fields * 232 * * 233 **************************************************************************/ 253 * and indeterminate state of each item in the tree. 254 */ 255 public CheckBoxTreeCell() { 256 // getSelectedProperty as anonymous inner class to deal with situation 257 // where the user is using CheckBoxTreeItem instances in their tree 258 this(item -> { 259 if (item instanceof CheckBoxTreeItem<?>) { 260 return ((CheckBoxTreeItem<?>)item).selectedProperty(); 261 } 262 return null; 263 }); 264 } 265 266 /** 267 * Creates a {@link CheckBoxTreeCell} for use in a TreeView control via a 268 * cell factory. Unlike {@link CheckBoxTreeCell#CheckBoxTreeCell()}, this 269 * method does not assume that all TreeItem instances in the TreeView are 270 * {@link CheckBoxTreeItem}. 271 * 272 * <p>To call this method, it is necessary to provide a 273 * {@link Callback} that, given an object of type TreeItem<T>, will return 274 * an {@code ObservableValue<Boolean>} that represents whether the given 275 * item is selected or not. This {@code ObservableValue<Boolean>} will be 276 * bound bidirectionally (meaning that the CheckBox in the cell will 277 * set/unset this property based on user interactions, and the CheckBox will 278 * reflect the state of the {@code ObservableValue<Boolean>}, if it changes 279 * externally). 280 * 281 * <p>If the items are not {@link CheckBoxTreeItem} instances, it becomes 282 * the developers responsibility to handle updating the state of parent and 283 * children TreeItems. This means that, given a TreeItem, this class will 284 * simply toggles the {@code ObservableValue<Boolean>} that is provided, and 285 * no more. Of course, this functionality can then be implemented externally 286 * by adding observers to the {@code ObservableValue<Boolean>}, and toggling 287 * the state of other properties as necessary. 288 * 289 * @param getSelectedProperty A {@link Callback} that will return an 290 * {@code ObservableValue<Boolean>} that represents whether the given 291 * item is selected or not. 292 */ 293 public CheckBoxTreeCell( 294 final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedProperty) { 295 this(getSelectedProperty, CellUtils.<T>defaultTreeItemStringConverter(), null); 296 } 297 298 /** 299 * Creates a {@link CheckBoxTreeCell} for use in a TreeView control via a 300 * cell factory. Unlike {@link CheckBoxTreeCell#CheckBoxTreeCell()}, this 301 * method does not assume that all TreeItem instances in the TreeView are 302 * {@link CheckBoxTreeItem}. 303 * 304 * <p>To call this method, it is necessary to provide a {@link Callback} 305 * that, given an object of type TreeItem<T>, will return an 306 * {@code ObservableValue<Boolean>} that represents whether the given item 307 * is selected or not. This {@code ObservableValue<Boolean>} will be bound 308 * bidirectionally (meaning that the CheckBox in the cell will set/unset 309 * this property based on user interactions, and the CheckBox will reflect 310 * the state of the {@code ObservableValue<Boolean>}, if it changes 311 * externally). 312 * 313 * <p>If the items are not {@link CheckBoxTreeItem} instances, it becomes 314 * the developers responsibility to handle updating the state of parent and 315 * children TreeItems. This means that, given a TreeItem, this class will 316 * simply toggles the {@code ObservableValue<Boolean>} that is provided, and 317 * no more. Of course, this functionality can then be implemented externally 318 * by adding observers to the {@code ObservableValue<Boolean>}, and toggling 319 * the state of other properties as necessary. 320 * 321 * @param getSelectedProperty A {@link Callback} that will return an 322 * {@code ObservableValue<Boolean>} that represents whether the given 323 * item is selected or not. 324 * @param converter A StringConverter that, give an object of type TreeItem<T>, will 325 * return a String that can be used to represent the object visually. 326 */ 327 public CheckBoxTreeCell( 328 final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedProperty, 329 final StringConverter<TreeItem<T>> converter) { 330 this(getSelectedProperty, converter, null); 331 } 332 333 private CheckBoxTreeCell( 334 final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedProperty, 335 final StringConverter<TreeItem<T>> converter, 336 final Callback<TreeItem<T>, ObservableValue<Boolean>> getIndeterminateProperty) { 337 this.getStyleClass().add("check-box-tree-cell"); 338 setSelectedStateCallback(getSelectedProperty); 339 setConverter(converter); 340 341 this.checkBox = new CheckBox(); 342 this.checkBox.setAllowIndeterminate(false); 343 344 // by default the graphic is null until the cell stops being empty 345 setGraphic(null); 346 } 347 348 349 350 /*************************************************************************** 351 * * 352 * Properties * 353 * * 354 **************************************************************************/ 355 356 // --- converter 357 private ObjectProperty<StringConverter<TreeItem<T>>> converter = 358 new SimpleObjectProperty<StringConverter<TreeItem<T>>>(this, "converter"); 359 360 /** 361 * The {@link StringConverter} property. 362 */ 363 public final ObjectProperty<StringConverter<TreeItem<T>>> converterProperty() { 364 return converter; 365 } 366 367 /** 368 * Sets the {@link StringConverter} to be used in this cell. 369 */ 370 public final void setConverter(StringConverter<TreeItem<T>> value) { 371 converterProperty().set(value); 372 } 373 374 /** 375 * Returns the {@link StringConverter} used in this cell. 376 */ 377 public final StringConverter<TreeItem<T>> getConverter() { 378 return converterProperty().get(); 379 } 380 381 382 383 // --- selected state callback property 384 private ObjectProperty<Callback<TreeItem<T>, ObservableValue<Boolean>>> 385 selectedStateCallback = 386 new SimpleObjectProperty<Callback<TreeItem<T>, ObservableValue<Boolean>>>( 387 this, "selectedStateCallback"); 388 389 /** 390 * Property representing the {@link Callback} that is bound to by the 391 * CheckBox shown on screen. 392 */ 393 public final ObjectProperty<Callback<TreeItem<T>, ObservableValue<Boolean>>> selectedStateCallbackProperty() { 394 return selectedStateCallback; 395 } 396 397 /** 398 * Sets the {@link Callback} that is bound to by the CheckBox shown on screen. 399 */ 400 public final void setSelectedStateCallback(Callback<TreeItem<T>, ObservableValue<Boolean>> value) { 401 selectedStateCallbackProperty().set(value); 402 } 403 404 /** 405 * Returns the {@link Callback} that is bound to by the CheckBox shown on screen. 406 */ 407 public final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedStateCallback() { 408 return selectedStateCallbackProperty().get(); 409 } 410 411 412 413 /*************************************************************************** 414 * * 415 * Public API * 416 * * 417 **************************************************************************/ 418 419 /** {@inheritDoc} */ 420 @Override public void updateItem(T item, boolean empty) { 421 super.updateItem(item, empty); 422 423 if (empty) { 424 setText(null); 425 setGraphic(null); | 149 /** 150 * Creates a cell factory for use in a TreeView control. Unlike 151 * {@link #forTreeView()}, this method does not assume that all TreeItem 152 * instances in the TreeView are {@link CheckBoxTreeItem} instances. 153 * 154 * <p>When used in a TreeView, the CheckBoxCell is rendered with a CheckBox 155 * to the right of the 'disclosure node' (i.e. the arrow). The item stored 156 * in {@link CheckBoxTreeItem#getValue()} will then have the StringConverter 157 * called on it, and this text will take all remaining horizontal space. 158 * 159 * <p>Unlike {@link #forTreeView()}, this cell factory does not handle 160 * updating the state of parent or children TreeItems - it simply toggles 161 * the {@code ObservableValue<Boolean>} that is provided, and no more. Of 162 * course, this functionality can then be implemented externally by adding 163 * observers to the {@code ObservableValue<Boolean>}, and toggling the state 164 * of other properties as necessary. 165 * 166 * @param <T> The type of the elements contained within the {@link TreeItem} 167 * instances. 168 * @param getSelectedProperty A {@link Callback} that, given an object of 169 * type {@literal TreeItem<T>}, will return an {@code ObservableValue<Boolean>} 170 * that represents whether the given item is selected or not. This 171 * {@code ObservableValue<Boolean>} will be bound bidirectionally 172 * (meaning that the CheckBox in the cell will set/unset this property 173 * based on user interactions, and the CheckBox will reflect the state 174 * of the {@code ObservableValue<Boolean>}, if it changes externally). 175 * @return A {@link Callback} that will return a TreeCell that is able to 176 * work on the type of element contained within the TreeView root, and 177 * all of its children (recursively). 178 */ 179 public static <T> Callback<TreeView<T>, TreeCell<T>> forTreeView( 180 final Callback<TreeItem<T>, 181 ObservableValue<Boolean>> getSelectedProperty) { 182 return forTreeView(getSelectedProperty, CellUtils.<T>defaultTreeItemStringConverter()); 183 } 184 185 /** 186 * Creates a cell factory for use in a TreeView control. Unlike 187 * {@link #forTreeView()}, this method does not assume that all TreeItem 188 * instances in the TreeView are {@link CheckBoxTreeItem}. 189 * 190 * <p>When used in a TreeView, the CheckBoxCell is rendered with a CheckBox 191 * to the right of the 'disclosure node' (i.e. the arrow). The item stored 192 * in {@link TreeItem#getValue()} will then have the the StringConverter 193 * called on it, and this text will take all remaining horizontal space. 194 * 195 * <p>Unlike {@link #forTreeView()}, this cell factory does not handle 196 * updating the state of parent or children TreeItems - it simply toggles 197 * the {@code ObservableValue<Boolean>} that is provided, and no more. Of 198 * course, this functionality can then be implemented externally by adding 199 * observers to the {@code ObservableValue<Boolean>}, and toggling the state 200 * of other properties as necessary. 201 * 202 * @param <T> The type of the elements contained within the {@link TreeItem} 203 * instances. 204 * @param getSelectedProperty A Callback that, given an object of 205 * type {@literal TreeItem<T>}, will return an {@code ObservableValue<Boolean>} 206 * that represents whether the given item is selected or not. This 207 * {@code ObservableValue<Boolean>} will be bound bidirectionally 208 * (meaning that the CheckBox in the cell will set/unset this property 209 * based on user interactions, and the CheckBox will reflect the state of 210 * the {@code ObservableValue<Boolean>}, if it changes externally). 211 * @param converter A StringConverter that, give an object of type 212 * {@literal TreeItem<T>}, will return a String that can be used to represent the 213 * object visually. The default implementation in {@link #forTreeView(Callback)} 214 * is to simply call .toString() on all non-null items (and to just 215 * return an empty string in cases where the given item is null). 216 * @return A {@link Callback} that will return a TreeCell that is able to 217 * work on the type of element contained within the TreeView root, and 218 * all of its children (recursively). 219 */ 220 public static <T> Callback<TreeView<T>, TreeCell<T>> forTreeView( 221 final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedProperty, 222 final StringConverter<TreeItem<T>> converter) { 223 return tree -> new CheckBoxTreeCell<T>(getSelectedProperty, converter); 224 } 225 226 227 228 229 /*************************************************************************** 230 * * 231 * Fields * 232 * * 233 **************************************************************************/ 253 * and indeterminate state of each item in the tree. 254 */ 255 public CheckBoxTreeCell() { 256 // getSelectedProperty as anonymous inner class to deal with situation 257 // where the user is using CheckBoxTreeItem instances in their tree 258 this(item -> { 259 if (item instanceof CheckBoxTreeItem<?>) { 260 return ((CheckBoxTreeItem<?>)item).selectedProperty(); 261 } 262 return null; 263 }); 264 } 265 266 /** 267 * Creates a {@link CheckBoxTreeCell} for use in a TreeView control via a 268 * cell factory. Unlike {@link CheckBoxTreeCell#CheckBoxTreeCell()}, this 269 * method does not assume that all TreeItem instances in the TreeView are 270 * {@link CheckBoxTreeItem}. 271 * 272 * <p>To call this method, it is necessary to provide a 273 * {@link Callback} that, given an object of type {@literal TreeItem<T>}, will return 274 * an {@code ObservableValue<Boolean>} that represents whether the given 275 * item is selected or not. This {@code ObservableValue<Boolean>} will be 276 * bound bidirectionally (meaning that the CheckBox in the cell will 277 * set/unset this property based on user interactions, and the CheckBox will 278 * reflect the state of the {@code ObservableValue<Boolean>}, if it changes 279 * externally). 280 * 281 * <p>If the items are not {@link CheckBoxTreeItem} instances, it becomes 282 * the developers responsibility to handle updating the state of parent and 283 * children TreeItems. This means that, given a TreeItem, this class will 284 * simply toggles the {@code ObservableValue<Boolean>} that is provided, and 285 * no more. Of course, this functionality can then be implemented externally 286 * by adding observers to the {@code ObservableValue<Boolean>}, and toggling 287 * the state of other properties as necessary. 288 * 289 * @param getSelectedProperty A {@link Callback} that will return an 290 * {@code ObservableValue<Boolean>} that represents whether the given 291 * item is selected or not. 292 */ 293 public CheckBoxTreeCell( 294 final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedProperty) { 295 this(getSelectedProperty, CellUtils.<T>defaultTreeItemStringConverter(), null); 296 } 297 298 /** 299 * Creates a {@link CheckBoxTreeCell} for use in a TreeView control via a 300 * cell factory. Unlike {@link CheckBoxTreeCell#CheckBoxTreeCell()}, this 301 * method does not assume that all TreeItem instances in the TreeView are 302 * {@link CheckBoxTreeItem}. 303 * 304 * <p>To call this method, it is necessary to provide a {@link Callback} 305 * that, given an object of type {@literal TreeItem<T>}, will return an 306 * {@code ObservableValue<Boolean>} that represents whether the given item 307 * is selected or not. This {@code ObservableValue<Boolean>} will be bound 308 * bidirectionally (meaning that the CheckBox in the cell will set/unset 309 * this property based on user interactions, and the CheckBox will reflect 310 * the state of the {@code ObservableValue<Boolean>}, if it changes 311 * externally). 312 * 313 * <p>If the items are not {@link CheckBoxTreeItem} instances, it becomes 314 * the developers responsibility to handle updating the state of parent and 315 * children TreeItems. This means that, given a TreeItem, this class will 316 * simply toggles the {@code ObservableValue<Boolean>} that is provided, and 317 * no more. Of course, this functionality can then be implemented externally 318 * by adding observers to the {@code ObservableValue<Boolean>}, and toggling 319 * the state of other properties as necessary. 320 * 321 * @param getSelectedProperty A {@link Callback} that will return an 322 * {@code ObservableValue<Boolean>} that represents whether the given 323 * item is selected or not. 324 * @param converter {@literal A StringConverter that, give an object of type 325 * TreeItem<T>, will return a String that can be used to represent the 326 * object visually.} 327 */ 328 public CheckBoxTreeCell( 329 final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedProperty, 330 final StringConverter<TreeItem<T>> converter) { 331 this(getSelectedProperty, converter, null); 332 } 333 334 private CheckBoxTreeCell( 335 final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedProperty, 336 final StringConverter<TreeItem<T>> converter, 337 final Callback<TreeItem<T>, ObservableValue<Boolean>> getIndeterminateProperty) { 338 this.getStyleClass().add("check-box-tree-cell"); 339 setSelectedStateCallback(getSelectedProperty); 340 setConverter(converter); 341 342 this.checkBox = new CheckBox(); 343 this.checkBox.setAllowIndeterminate(false); 344 345 // by default the graphic is null until the cell stops being empty 346 setGraphic(null); 347 } 348 349 350 351 /*************************************************************************** 352 * * 353 * Properties * 354 * * 355 **************************************************************************/ 356 357 // --- converter 358 private ObjectProperty<StringConverter<TreeItem<T>>> converter = 359 new SimpleObjectProperty<StringConverter<TreeItem<T>>>(this, "converter"); 360 361 /** 362 * The {@link StringConverter} property. 363 * @return the {@link StringConverter} property 364 */ 365 public final ObjectProperty<StringConverter<TreeItem<T>>> converterProperty() { 366 return converter; 367 } 368 369 /** 370 * Sets the {@link StringConverter} to be used in this cell. 371 * @param value the {@link StringConverter} to be used in this cell 372 */ 373 public final void setConverter(StringConverter<TreeItem<T>> value) { 374 converterProperty().set(value); 375 } 376 377 /** 378 * Returns the {@link StringConverter} used in this cell. 379 * @return the {@link StringConverter} used in this cell 380 */ 381 public final StringConverter<TreeItem<T>> getConverter() { 382 return converterProperty().get(); 383 } 384 385 386 387 // --- selected state callback property 388 private ObjectProperty<Callback<TreeItem<T>, ObservableValue<Boolean>>> 389 selectedStateCallback = 390 new SimpleObjectProperty<Callback<TreeItem<T>, ObservableValue<Boolean>>>( 391 this, "selectedStateCallback"); 392 393 /** 394 * Property representing the {@link Callback} that is bound to by the 395 * CheckBox shown on screen. 396 * @return the property representing the {@link Callback} that is bound to 397 * by the CheckBox shown on screen 398 */ 399 public final ObjectProperty<Callback<TreeItem<T>, ObservableValue<Boolean>>> selectedStateCallbackProperty() { 400 return selectedStateCallback; 401 } 402 403 /** 404 * Sets the {@link Callback} that is bound to by the CheckBox shown on screen. 405 * @param value the {@link Callback} that is bound to by the CheckBox shown on screen 406 */ 407 public final void setSelectedStateCallback(Callback<TreeItem<T>, ObservableValue<Boolean>> value) { 408 selectedStateCallbackProperty().set(value); 409 } 410 411 /** 412 * Returns the {@link Callback} that is bound to by the CheckBox shown on screen. 413 * @return the {@link Callback} that is bound to by the CheckBox shown on screen 414 */ 415 public final Callback<TreeItem<T>, ObservableValue<Boolean>> getSelectedStateCallback() { 416 return selectedStateCallbackProperty().get(); 417 } 418 419 420 421 /*************************************************************************** 422 * * 423 * Public API * 424 * * 425 **************************************************************************/ 426 427 /** {@inheritDoc} */ 428 @Override public void updateItem(T item, boolean empty) { 429 super.updateItem(item, empty); 430 431 if (empty) { 432 setText(null); 433 setGraphic(null); |