298
299 @Override
300 public void dispose() {
301 super.unbind(dependencies);
302 }
303
304 @Override
305 public ObservableList<?> getDependencies() {
306 return ((dependencies == null) || (dependencies.length == 0))?
307 FXCollections.emptyObservableList()
308 : (dependencies.length == 1)?
309 FXCollections.singletonObservableList(dependencies[0])
310 : new ImmutableObservableList<Observable>(dependencies);
311 }
312 };
313 }
314
315 /**
316 * Helper function to create a custom {@link ObjectBinding}.
317 *
318 * @param func The function that calculates the value of this binding
319 * @param dependencies The dependencies of this binding
320 * @return The generated binding
321 * @since JavaFX 2.1
322 */
323 public static <T> ObjectBinding<T> createObjectBinding(final Callable<T> func, final Observable... dependencies) {
324 return new ObjectBinding<T>() {
325 {
326 bind(dependencies);
327 }
328
329 @Override
330 protected T computeValue() {
331 try {
332 return func.call();
333 } catch (Exception e) {
334 Logging.getLogger().warning("Exception while evaluating binding", e);
335 return null;
336 }
337 }
389 FXCollections.singletonObservableList(dependencies[0])
390 : new ImmutableObservableList<Observable>(dependencies);
391 }
392 };
393 }
394
395
396 // =================================================================================================================
397 // Select Bindings
398
399 /**
400 * Creates a binding used to get a member, such as {@code a.b.c}. The value
401 * of the binding will be {@code c}, or {@code null} if {@code c} could not
402 * be reached (due to {@code b} not having a {@code c} property,
403 * {@code b} being {@code null}, or {@code c} not being the right type etc.).
404 * <p>
405 * All classes and properties used in a select-binding have to be public.
406 *
407 * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
408 *
409 * @param root
410 * The root {@link javafx.beans.value.ObservableValue}
411 * @param steps
412 * The property names to reach the final property
413 * @return the created {@link ObjectBinding}
414 */
415 public static <T> ObjectBinding<T> select(ObservableValue<?> root, String... steps) {
416 return new SelectBinding.AsObject<T>(root, steps);
417 }
418
419 /**
420 * Creates a binding used to get a member, such as {@code a.b.c}. The value
421 * of the binding will be {@code c}, or {@code 0.0} if {@code c} could not
422 * be reached (due to {@code b} not having a {@code c} property,
423 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
424 * <p>
425 * All classes and properties used in a select-binding have to be public.
426 *
427 * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
428 *
527 * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
528 *
529 * @param root
530 * The root {@link javafx.beans.value.ObservableValue}
531 * @param steps
532 * The property names to reach the final property
533 * @return the created {@link ObjectBinding}
534 */
535 public static StringBinding selectString(ObservableValue<?> root, String... steps) {
536 return new SelectBinding.AsString(root, steps);
537 }
538
539 /**
540 * Creates a binding used to get a member, such as {@code a.b.c}. The value
541 * of the binding will be {@code c}, or {@code null} if {@code c} could not
542 * be reached (due to {@code b} not having a {@code c} property,
543 * {@code b} being {@code null}, or {@code c} not being the right type etc.).
544 * <p>
545 * All classes and properties used in a select-binding have to be public.
546 *
547 * If root has JavaFX properties, this call is equivalent to {@link #select(javafx.beans.value.ObservableValue, java.lang.String[]),
548 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
549 *
550 * @param root
551 * The root bean.
552 * @param steps
553 * The property names to reach the final property. The first step
554 * must be specified as it marks the property of the root bean.
555 * @return the created {@link ObjectBinding}
556 * @since JavaFX 8.0
557 */
558 public static <T> ObjectBinding<T> select(Object root, String... steps) {
559 return new SelectBinding.AsObject<T>(root, steps);
560 }
561
562 /**
563 * Creates a binding used to get a member, such as {@code a.b.c}. The value
564 * of the binding will be {@code c}, or {@code 0.0} if {@code c} could not
565 * be reached (due to {@code b} not having a {@code c} property,
566 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
567 * <p>
568 * All classes and properties used in a select-binding have to be public.
569 *
570 * If root has JavaFX properties, this call is equivalent to {@link #selectDouble(javafx.beans.value.ObservableValue, java.lang.String[]),
571 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
572 *
573 * @param root
574 * The root bean.
575 * @param steps
576 * The property names to reach the final property. The first step
577 * must be specified as it marks the property of the root bean.
578 * @return the created {@link DoubleBinding}
579 * @since JavaFX 8.0
580 */
581 public static DoubleBinding selectDouble(Object root, String... steps) {
582 return new SelectBinding.AsDouble(root, steps);
583 }
584
585 /**
586 * Creates a binding used to get a member, such as {@code a.b.c}. The value
587 * of the binding will be {@code c}, or {@code 0.0f} if {@code c} could not
588 * be reached (due to {@code b} not having a {@code c} property,
589 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
590 * <p>
591 * All classes and properties used in a select-binding have to be public.
592 *
593 * If root has JavaFX properties, this call is equivalent to {@link #selectFloat(javafx.beans.value.ObservableValue, java.lang.String[]),
594 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
595 *
596 * @param root
597 * The root bean.
598 * @param steps
599 * The property names to reach the final property. The first step
600 * must be specified as it marks the property of the root bean.
601 * @return the created {@link FloatBinding}
602 * @since JavaFX 8.0
603 */
604 public static FloatBinding selectFloat(Object root, String... steps) {
605 return new SelectBinding.AsFloat(root, steps);
606 }
607
608 /**
609 * Creates a binding used to get a member, such as {@code a.b.c}. The value
610 * of the binding will be {@code c}, or {@code 0} if {@code c} could not
611 * be reached (due to {@code b} not having a {@code c} property,
612 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
613 * <p>
614 * All classes and properties used in a select-binding have to be public.
615 *
616 * If root has JavaFX properties, this call is equivalent to {@link #selectInteger(javafx.beans.value.ObservableValue, java.lang.String[]),
617 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
618 *
619 * @param root
620 * The root bean.
621 * @param steps
622 * The property names to reach the final property. The first step
623 * must be specified as it marks the property of the root bean.
624 * @return the created {@link IntegerBinding}
625 * @since JavaFX 8.0
626 */
627 public static IntegerBinding selectInteger(Object root, String... steps) {
628 return new SelectBinding.AsInteger(root, steps);
629 }
630
631 /**
632 * Creates a binding used to get a member, such as {@code a.b.c}. The value
633 * of the binding will be {@code c}, or {@code 0L} if {@code c} could not
634 * be reached (due to {@code b} not having a {@code c} property,
635 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
636 * <p>
637 * All classes and properties used in a select-binding have to be public.
638 *
639 * If root has JavaFX properties, this call is equivalent to {@link #selectLong(javafx.beans.value.ObservableValue, java.lang.String[]),
640 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
641 *
642 * @param root
643 * The root bean.
644 * @param steps
645 * The property names to reach the final property. The first step
646 * must be specified as it marks the property of the root bean.
647 * @return the created {@link LongBinding}
648 * @since JavaFX 8.0
649 */
650 public static LongBinding selectLong(Object root, String... steps) {
651 return new SelectBinding.AsLong(root, steps);
652 }
653
654 /**
655 * Creates a binding used to get a member, such as {@code a.b.c}. The value
656 * of the binding will be {@code c}, or {@code false} if {@code c} could not
657 * be reached (due to {@code b} not having a {@code c} property,
658 * {@code b} being {@code null}, or {@code c} not being a {@code boolean} etc.).
659 * <p>
660 * All classes and properties used in a select-binding have to be public.
661 *
662 * If root has JavaFX properties, this call is equivalent to {@link #selectBoolean(javafx.beans.value.ObservableValue, java.lang.String[]),
663 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
664 *
665 * @param root
666 * The root bean.
667 * @param steps
668 * The property names to reach the final property. The first step
669 * must be specified as it marks the property of the root bean.
670 * @return the created {@link ObjectBinding}
671 * @since JavaFX 8.0
672 */
673 public static BooleanBinding selectBoolean(Object root, String... steps) {
674 return new SelectBinding.AsBoolean(root, steps);
675 }
676
677 /**
678 * Creates a binding used to get a member, such as {@code a.b.c}. The value
679 * of the binding will be {@code c}, or {@code ""} if {@code c} could not
680 * be reached (due to {@code b} not having a {@code c} property,
681 * {@code b} being {@code null}, or {@code c} not being a {@code String} etc.).
682 * <p>
683 * All classes and properties used in a select-binding have to be public.
684 *
685 * If root has JavaFX properties, this call is equivalent to {@link #selectString(javafx.beans.value.ObservableValue, java.lang.String[]),
686 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
687 *
688 * @param root
689 * The root bean.
690 * @param steps
691 * The property names to reach the final property. The first step
692 * must be specified as it marks the property of the root bean.
693 * @return the created {@link ObjectBinding}
694 * @since JavaFX 8.0
695 */
696 public static StringBinding selectString(Object root, String... steps) {
697 return new SelectBinding.AsString(root, steps);
698 }
699
700 /**
701 * Creates a binding that calculates the result of a ternary expression. See
702 * the description of class {@link When} for details.
703 *
704 * @see When
705 *
828 * Generates a bidirectional binding (or "bind with inverse") between a
829 * {@code String}-{@link javafx.beans.property.Property} and another {@code Property}
830 * using the specified {@link javafx.util.StringConverter} for conversion.
831 * <p>
832 * A bidirectional binding is a binding that works in both directions. If
833 * two properties {@code a} and {@code b} are linked with a bidirectional
834 * binding and the value of {@code a} changes, {@code b} is set to the same
835 * value automatically. And vice versa, if {@code b} changes, {@code a} is
836 * set to the same value.
837 * <p>
838 * A bidirectional binding can be removed with
839 * {@link #unbindBidirectional(Object, Object)}.
840 * <p>
841 * Note: this implementation of a bidirectional binding behaves differently
842 * from all other bindings here in two important aspects. A property that is
843 * linked to another property with a bidirectional binding can still be set
844 * (usually bindings would throw an exception). Secondly bidirectional
845 * bindings are calculated eagerly, i.e. a bound property is updated
846 * immediately.
847 *
848 * @param stringProperty
849 * the {@code String} {@code Property}
850 * @param otherProperty
851 * the other (non-{@code String}) {@code Property}
852 * @param converter
853 * the {@code StringConverter} used to convert between the properties
854 * @throws NullPointerException
855 * if one of the properties or the {@code converter} is {@code null}
856 * @throws IllegalArgumentException
857 * if both properties are equal
858 * @since JavaFX 2.1
859 */
860 public static <T> void bindBidirectional(Property<String> stringProperty, Property<T> otherProperty, StringConverter<T> converter) {
861 BidirectionalBinding.bind(stringProperty, otherProperty, converter);
862 }
863
864 /**
865 * Generates a bidirectional binding (or "bind with inverse") between two
866 * instances of {@link javafx.collections.ObservableList}.
867 * <p>
5986 return !op.isEmpty();
5987 }
5988
5989 @Override
5990 public ObservableList<?> getDependencies() {
5991 return FXCollections.singletonObservableList(op);
5992 }
5993 };
5994 }
5995
5996 /**
5997 * Creates a new {@link javafx.beans.binding.ObjectBinding} that contains the element
5998 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code ObjectBinding}
5999 * will contain {@code null}, if the {@code index} points behind the {@code ObservableList}.
6000 *
6001 * @param op the {@code ObservableList}
6002 * @param index the position in the {@code List}
6003 * @param <E> the type of the {@code List} elements
6004 * @return the new {@code ObjectBinding}
6005 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6006 * @throws IllegalArgumentException if (@code index < 0}
6007 * @since JavaFX 2.1
6008 */
6009 public static <E> ObjectBinding<E> valueAt(final ObservableList<E> op, final int index) {
6010 if (op == null) {
6011 throw new NullPointerException("List cannot be null.");
6012 }
6013 if (index < 0) {
6014 throw new IllegalArgumentException("Index cannot be negative");
6015 }
6016
6017 return new ObjectBinding<E>() {
6018 {
6019 super.bind(op);
6020 }
6021
6022 @Override
6023 public void dispose() {
6024 super.unbind(op);
6025 }
6026
6093 }
6094 return null;
6095 }
6096
6097 @Override
6098 public ObservableList<?> getDependencies() {
6099 return new ImmutableObservableList<Observable>(op, index);
6100 }
6101 };
6102 }
6103
6104 /**
6105 * Creates a new {@link javafx.beans.binding.BooleanBinding} that contains the element
6106 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code BooleanBinding}
6107 * will hold {@code false}, if the {@code index} points behind the {@code ObservableList}.
6108 *
6109 * @param op the {@code ObservableList}
6110 * @param index the position in the {@code List}
6111 * @return the new {@code BooleanBinding}
6112 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6113 * @throws IllegalArgumentException if (@code index < 0}
6114 * @since JavaFX 2.1
6115 */
6116 public static BooleanBinding booleanValueAt(final ObservableList<Boolean> op, final int index) {
6117 if (op == null) {
6118 throw new NullPointerException("List cannot be null.");
6119 }
6120 if (index < 0) {
6121 throw new IllegalArgumentException("Index cannot be negative");
6122 }
6123
6124 return new BooleanBinding() {
6125 {
6126 super.bind(op);
6127 }
6128
6129 @Override
6130 public void dispose() {
6131 super.unbind(op);
6132 }
6133
6208 }
6209 return false;
6210 }
6211
6212 @Override
6213 public ObservableList<?> getDependencies() {
6214 return new ImmutableObservableList<Observable>(op, index);
6215 }
6216 };
6217 }
6218
6219 /**
6220 * Creates a new {@link javafx.beans.binding.DoubleBinding} that contains the element
6221 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code DoubleBinding}
6222 * will hold {@code 0.0}, if the {@code index} points behind the {@code ObservableList}.
6223 *
6224 * @param op the {@code ObservableList}
6225 * @param index the position in the {@code List}
6226 * @return the new {@code DoubleBinding}
6227 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6228 * @throws IllegalArgumentException if (@code index < 0}
6229 * @since JavaFX 2.1
6230 */
6231 public static DoubleBinding doubleValueAt(final ObservableList<? extends Number> op, final int index) {
6232 if (op == null) {
6233 throw new NullPointerException("List cannot be null.");
6234 }
6235 if (index < 0) {
6236 throw new IllegalArgumentException("Index cannot be negative");
6237 }
6238
6239 return new DoubleBinding() {
6240 {
6241 super.bind(op);
6242 }
6243
6244 @Override
6245 public void dispose() {
6246 super.unbind(op);
6247 }
6248
6323 }
6324 return 0.0;
6325 }
6326
6327 @Override
6328 public ObservableList<?> getDependencies() {
6329 return new ImmutableObservableList<Observable>(op, index);
6330 }
6331 };
6332 }
6333
6334 /**
6335 * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6336 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code FloatBinding}
6337 * will hold {@code 0.0f}, if the {@code index} points behind the {@code ObservableList}.
6338 *
6339 * @param op the {@code ObservableList}
6340 * @param index the position in the {@code List}
6341 * @return the new {@code FloatBinding}
6342 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6343 * @throws IllegalArgumentException if (@code index < 0}
6344 * @since JavaFX 2.1
6345 */
6346 public static FloatBinding floatValueAt(final ObservableList<? extends Number> op, final int index) {
6347 if (op == null) {
6348 throw new NullPointerException("List cannot be null.");
6349 }
6350 if (index < 0) {
6351 throw new IllegalArgumentException("Index cannot be negative");
6352 }
6353
6354 return new FloatBinding() {
6355 {
6356 super.bind(op);
6357 }
6358
6359 @Override
6360 public void dispose() {
6361 super.unbind(op);
6362 }
6363
6438 }
6439 return 0.0f;
6440 }
6441
6442 @Override
6443 public ObservableList<?> getDependencies() {
6444 return new ImmutableObservableList<Observable>(op, index);
6445 }
6446 };
6447 }
6448
6449 /**
6450 * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
6451 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code IntegerBinding}
6452 * will hold {@code 0}, if the {@code index} points behind the {@code ObservableList}.
6453 *
6454 * @param op the {@code ObservableList}
6455 * @param index the position in the {@code List}
6456 * @return the new {@code IntegerBinding}
6457 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6458 * @throws IllegalArgumentException if (@code index < 0}
6459 * @since JavaFX 2.1
6460 */
6461 public static IntegerBinding integerValueAt(final ObservableList<? extends Number> op, final int index) {
6462 if (op == null) {
6463 throw new NullPointerException("List cannot be null.");
6464 }
6465 if (index < 0) {
6466 throw new IllegalArgumentException("Index cannot be negative");
6467 }
6468
6469 return new IntegerBinding() {
6470 {
6471 super.bind(op);
6472 }
6473
6474 @Override
6475 public void dispose() {
6476 super.unbind(op);
6477 }
6478
6553 }
6554 return 0;
6555 }
6556
6557 @Override
6558 public ObservableList<?> getDependencies() {
6559 return new ImmutableObservableList<Observable>(op, index);
6560 }
6561 };
6562 }
6563
6564 /**
6565 * Creates a new {@link javafx.beans.binding.LongBinding} that contains the element
6566 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code LongBinding}
6567 * will hold {@code 0L}, if the {@code index} points behind the {@code ObservableList}.
6568 *
6569 * @param op the {@code ObservableList}
6570 * @param index the position in the {@code List}
6571 * @return the new {@code LongBinding}
6572 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6573 * @throws IllegalArgumentException if (@code index < 0}
6574 * @since JavaFX 2.1
6575 */
6576 public static LongBinding longValueAt(final ObservableList<? extends Number> op, final int index) {
6577 if (op == null) {
6578 throw new NullPointerException("List cannot be null.");
6579 }
6580 if (index < 0) {
6581 throw new IllegalArgumentException("Index cannot be negative");
6582 }
6583
6584 return new LongBinding() {
6585 {
6586 super.bind(op);
6587 }
6588
6589 @Override
6590 public void dispose() {
6591 super.unbind(op);
6592 }
6593
6668 }
6669 return 0L;
6670 }
6671
6672 @Override
6673 public ObservableList<?> getDependencies() {
6674 return new ImmutableObservableList<Observable>(op, index);
6675 }
6676 };
6677 }
6678
6679 /**
6680 * Creates a new {@link javafx.beans.binding.StringBinding} that contains the element
6681 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code StringBinding}
6682 * will hold {@code null}, if the {@code index} points behind the {@code ObservableList}.
6683 *
6684 * @param op the {@code ObservableList}
6685 * @param index the position in the {@code List}
6686 * @return the new {@code StringBinding}
6687 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6688 * @throws IllegalArgumentException if (@code index < 0}
6689 * @since JavaFX 2.1
6690 */
6691 public static StringBinding stringValueAt(final ObservableList<String> op, final int index) {
6692 if (op == null) {
6693 throw new NullPointerException("List cannot be null.");
6694 }
6695 if (index < 0) {
6696 throw new IllegalArgumentException("Index cannot be negative");
6697 }
6698
6699 return new StringBinding() {
6700 {
6701 super.bind(op);
6702 }
6703
6704 @Override
6705 public void dispose() {
6706 super.unbind(op);
6707 }
6708
6933 protected int computeValue() {
6934 return op.size();
6935 }
6936
6937 @Override
6938 public ObservableList<?> getDependencies() {
6939 return FXCollections.singletonObservableList(op);
6940 }
6941 };
6942 }
6943
6944 /**
6945 * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6946 * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code FloatBinding}
6947 * will hold {@code 0.0f}, if the {@code index} points behind the {@code ObservableArray}.
6948 *
6949 * @param op the {@code ObservableArray}
6950 * @param index the position in the {@code ObservableArray}
6951 * @return the new {@code FloatBinding}
6952 * @throws NullPointerException if the {@code ObservableArray} is {@code null}
6953 * @throws IllegalArgumentException if (@code index < 0}
6954 * @since JavaFX 8.0
6955 */
6956 public static FloatBinding floatValueAt(final ObservableFloatArray op, final int index) {
6957 if (op == null) {
6958 throw new NullPointerException("Array cannot be null.");
6959 }
6960 if (index < 0) {
6961 throw new IllegalArgumentException("Index cannot be negative");
6962 }
6963
6964 return new FloatBinding() {
6965 {
6966 super.bind(op);
6967 }
6968
6969 @Override
6970 public void dispose() {
6971 super.unbind(op);
6972 }
6973
7038 }
7039 return 0.0f;
7040 }
7041
7042 @Override
7043 public ObservableList<?> getDependencies() {
7044 return new ImmutableObservableList<>(op, index);
7045 }
7046 };
7047 }
7048
7049 /**
7050 * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
7051 * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code IntegerBinding}
7052 * will hold {@code 0}, if the {@code index} points behind the {@code ObservableArray}.
7053 *
7054 * @param op the {@code ObservableArray}
7055 * @param index the position in the {@code ObservableArray}
7056 * @return the new {@code IntegerBinding}
7057 * @throws NullPointerException if the {@code ObservableArray} is {@code null}
7058 * @throws IllegalArgumentException if (@code index < 0}
7059 * @since JavaFX 8.0
7060 */
7061 public static IntegerBinding integerValueAt(final ObservableIntegerArray op, final int index) {
7062 if (op == null) {
7063 throw new NullPointerException("Array cannot be null.");
7064 }
7065 if (index < 0) {
7066 throw new IllegalArgumentException("Index cannot be negative");
7067 }
7068
7069 return new IntegerBinding() {
7070 {
7071 super.bind(op);
7072 }
7073
7074 @Override
7075 public void dispose() {
7076 super.unbind(op);
7077 }
7078
|
298
299 @Override
300 public void dispose() {
301 super.unbind(dependencies);
302 }
303
304 @Override
305 public ObservableList<?> getDependencies() {
306 return ((dependencies == null) || (dependencies.length == 0))?
307 FXCollections.emptyObservableList()
308 : (dependencies.length == 1)?
309 FXCollections.singletonObservableList(dependencies[0])
310 : new ImmutableObservableList<Observable>(dependencies);
311 }
312 };
313 }
314
315 /**
316 * Helper function to create a custom {@link ObjectBinding}.
317 *
318 * @param <T> the type of the wrapped {@code Object}
319 * @param func The function that calculates the value of this binding
320 * @param dependencies The dependencies of this binding
321 * @return The generated binding
322 * @since JavaFX 2.1
323 */
324 public static <T> ObjectBinding<T> createObjectBinding(final Callable<T> func, final Observable... dependencies) {
325 return new ObjectBinding<T>() {
326 {
327 bind(dependencies);
328 }
329
330 @Override
331 protected T computeValue() {
332 try {
333 return func.call();
334 } catch (Exception e) {
335 Logging.getLogger().warning("Exception while evaluating binding", e);
336 return null;
337 }
338 }
390 FXCollections.singletonObservableList(dependencies[0])
391 : new ImmutableObservableList<Observable>(dependencies);
392 }
393 };
394 }
395
396
397 // =================================================================================================================
398 // Select Bindings
399
400 /**
401 * Creates a binding used to get a member, such as {@code a.b.c}. The value
402 * of the binding will be {@code c}, or {@code null} if {@code c} could not
403 * be reached (due to {@code b} not having a {@code c} property,
404 * {@code b} being {@code null}, or {@code c} not being the right type etc.).
405 * <p>
406 * All classes and properties used in a select-binding have to be public.
407 *
408 * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
409 *
410 * @param <T> the type of the wrapped {@code Object}
411 * @param root
412 * The root {@link javafx.beans.value.ObservableValue}
413 * @param steps
414 * The property names to reach the final property
415 * @return the created {@link ObjectBinding}
416 */
417 public static <T> ObjectBinding<T> select(ObservableValue<?> root, String... steps) {
418 return new SelectBinding.AsObject<T>(root, steps);
419 }
420
421 /**
422 * Creates a binding used to get a member, such as {@code a.b.c}. The value
423 * of the binding will be {@code c}, or {@code 0.0} if {@code c} could not
424 * be reached (due to {@code b} not having a {@code c} property,
425 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
426 * <p>
427 * All classes and properties used in a select-binding have to be public.
428 *
429 * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
430 *
529 * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
530 *
531 * @param root
532 * The root {@link javafx.beans.value.ObservableValue}
533 * @param steps
534 * The property names to reach the final property
535 * @return the created {@link ObjectBinding}
536 */
537 public static StringBinding selectString(ObservableValue<?> root, String... steps) {
538 return new SelectBinding.AsString(root, steps);
539 }
540
541 /**
542 * Creates a binding used to get a member, such as {@code a.b.c}. The value
543 * of the binding will be {@code c}, or {@code null} if {@code c} could not
544 * be reached (due to {@code b} not having a {@code c} property,
545 * {@code b} being {@code null}, or {@code c} not being the right type etc.).
546 * <p>
547 * All classes and properties used in a select-binding have to be public.
548 *
549 * If root has JavaFX properties, this call is equivalent to {@link #select(javafx.beans.value.ObservableValue, java.lang.String[])},
550 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
551 *
552 * @param <T> the type of the wrapped {@code Object}
553 * @param root
554 * The root bean.
555 * @param steps
556 * The property names to reach the final property. The first step
557 * must be specified as it marks the property of the root bean.
558 * @return the created {@link ObjectBinding}
559 * @since JavaFX 8.0
560 */
561 public static <T> ObjectBinding<T> select(Object root, String... steps) {
562 return new SelectBinding.AsObject<T>(root, steps);
563 }
564
565 /**
566 * Creates a binding used to get a member, such as {@code a.b.c}. The value
567 * of the binding will be {@code c}, or {@code 0.0} if {@code c} could not
568 * be reached (due to {@code b} not having a {@code c} property,
569 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
570 * <p>
571 * All classes and properties used in a select-binding have to be public.
572 *
573 * If root has JavaFX properties, this call is equivalent to {@link #selectDouble(javafx.beans.value.ObservableValue, java.lang.String[])},
574 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
575 *
576 * @param root
577 * The root bean.
578 * @param steps
579 * The property names to reach the final property. The first step
580 * must be specified as it marks the property of the root bean.
581 * @return the created {@link DoubleBinding}
582 * @since JavaFX 8.0
583 */
584 public static DoubleBinding selectDouble(Object root, String... steps) {
585 return new SelectBinding.AsDouble(root, steps);
586 }
587
588 /**
589 * Creates a binding used to get a member, such as {@code a.b.c}. The value
590 * of the binding will be {@code c}, or {@code 0.0f} if {@code c} could not
591 * be reached (due to {@code b} not having a {@code c} property,
592 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
593 * <p>
594 * All classes and properties used in a select-binding have to be public.
595 *
596 * If root has JavaFX properties, this call is equivalent to {@link #selectFloat(javafx.beans.value.ObservableValue, java.lang.String[])},
597 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
598 *
599 * @param root
600 * The root bean.
601 * @param steps
602 * The property names to reach the final property. The first step
603 * must be specified as it marks the property of the root bean.
604 * @return the created {@link FloatBinding}
605 * @since JavaFX 8.0
606 */
607 public static FloatBinding selectFloat(Object root, String... steps) {
608 return new SelectBinding.AsFloat(root, steps);
609 }
610
611 /**
612 * Creates a binding used to get a member, such as {@code a.b.c}. The value
613 * of the binding will be {@code c}, or {@code 0} if {@code c} could not
614 * be reached (due to {@code b} not having a {@code c} property,
615 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
616 * <p>
617 * All classes and properties used in a select-binding have to be public.
618 *
619 * If root has JavaFX properties, this call is equivalent to {@link #selectInteger(javafx.beans.value.ObservableValue, java.lang.String[])},
620 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
621 *
622 * @param root
623 * The root bean.
624 * @param steps
625 * The property names to reach the final property. The first step
626 * must be specified as it marks the property of the root bean.
627 * @return the created {@link IntegerBinding}
628 * @since JavaFX 8.0
629 */
630 public static IntegerBinding selectInteger(Object root, String... steps) {
631 return new SelectBinding.AsInteger(root, steps);
632 }
633
634 /**
635 * Creates a binding used to get a member, such as {@code a.b.c}. The value
636 * of the binding will be {@code c}, or {@code 0L} if {@code c} could not
637 * be reached (due to {@code b} not having a {@code c} property,
638 * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
639 * <p>
640 * All classes and properties used in a select-binding have to be public.
641 *
642 * If root has JavaFX properties, this call is equivalent to {@link #selectLong(javafx.beans.value.ObservableValue, java.lang.String[])},
643 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
644 *
645 * @param root
646 * The root bean.
647 * @param steps
648 * The property names to reach the final property. The first step
649 * must be specified as it marks the property of the root bean.
650 * @return the created {@link LongBinding}
651 * @since JavaFX 8.0
652 */
653 public static LongBinding selectLong(Object root, String... steps) {
654 return new SelectBinding.AsLong(root, steps);
655 }
656
657 /**
658 * Creates a binding used to get a member, such as {@code a.b.c}. The value
659 * of the binding will be {@code c}, or {@code false} if {@code c} could not
660 * be reached (due to {@code b} not having a {@code c} property,
661 * {@code b} being {@code null}, or {@code c} not being a {@code boolean} etc.).
662 * <p>
663 * All classes and properties used in a select-binding have to be public.
664 *
665 * If root has JavaFX properties, this call is equivalent to {@link #selectBoolean(javafx.beans.value.ObservableValue, java.lang.String[])},
666 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
667 *
668 * @param root
669 * The root bean.
670 * @param steps
671 * The property names to reach the final property. The first step
672 * must be specified as it marks the property of the root bean.
673 * @return the created {@link ObjectBinding}
674 * @since JavaFX 8.0
675 */
676 public static BooleanBinding selectBoolean(Object root, String... steps) {
677 return new SelectBinding.AsBoolean(root, steps);
678 }
679
680 /**
681 * Creates a binding used to get a member, such as {@code a.b.c}. The value
682 * of the binding will be {@code c}, or {@code ""} if {@code c} could not
683 * be reached (due to {@code b} not having a {@code c} property,
684 * {@code b} being {@code null}, or {@code c} not being a {@code String} etc.).
685 * <p>
686 * All classes and properties used in a select-binding have to be public.
687 *
688 * If root has JavaFX properties, this call is equivalent to {@link #selectString(javafx.beans.value.ObservableValue, java.lang.String[])},
689 * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
690 *
691 * @param root
692 * The root bean.
693 * @param steps
694 * The property names to reach the final property. The first step
695 * must be specified as it marks the property of the root bean.
696 * @return the created {@link ObjectBinding}
697 * @since JavaFX 8.0
698 */
699 public static StringBinding selectString(Object root, String... steps) {
700 return new SelectBinding.AsString(root, steps);
701 }
702
703 /**
704 * Creates a binding that calculates the result of a ternary expression. See
705 * the description of class {@link When} for details.
706 *
707 * @see When
708 *
831 * Generates a bidirectional binding (or "bind with inverse") between a
832 * {@code String}-{@link javafx.beans.property.Property} and another {@code Property}
833 * using the specified {@link javafx.util.StringConverter} for conversion.
834 * <p>
835 * A bidirectional binding is a binding that works in both directions. If
836 * two properties {@code a} and {@code b} are linked with a bidirectional
837 * binding and the value of {@code a} changes, {@code b} is set to the same
838 * value automatically. And vice versa, if {@code b} changes, {@code a} is
839 * set to the same value.
840 * <p>
841 * A bidirectional binding can be removed with
842 * {@link #unbindBidirectional(Object, Object)}.
843 * <p>
844 * Note: this implementation of a bidirectional binding behaves differently
845 * from all other bindings here in two important aspects. A property that is
846 * linked to another property with a bidirectional binding can still be set
847 * (usually bindings would throw an exception). Secondly bidirectional
848 * bindings are calculated eagerly, i.e. a bound property is updated
849 * immediately.
850 *
851 * @param <T> the type of the wrapped {@code Object}
852 * @param stringProperty
853 * the {@code String} {@code Property}
854 * @param otherProperty
855 * the other (non-{@code String}) {@code Property}
856 * @param converter
857 * the {@code StringConverter} used to convert between the properties
858 * @throws NullPointerException
859 * if one of the properties or the {@code converter} is {@code null}
860 * @throws IllegalArgumentException
861 * if both properties are equal
862 * @since JavaFX 2.1
863 */
864 public static <T> void bindBidirectional(Property<String> stringProperty, Property<T> otherProperty, StringConverter<T> converter) {
865 BidirectionalBinding.bind(stringProperty, otherProperty, converter);
866 }
867
868 /**
869 * Generates a bidirectional binding (or "bind with inverse") between two
870 * instances of {@link javafx.collections.ObservableList}.
871 * <p>
5990 return !op.isEmpty();
5991 }
5992
5993 @Override
5994 public ObservableList<?> getDependencies() {
5995 return FXCollections.singletonObservableList(op);
5996 }
5997 };
5998 }
5999
6000 /**
6001 * Creates a new {@link javafx.beans.binding.ObjectBinding} that contains the element
6002 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code ObjectBinding}
6003 * will contain {@code null}, if the {@code index} points behind the {@code ObservableList}.
6004 *
6005 * @param op the {@code ObservableList}
6006 * @param index the position in the {@code List}
6007 * @param <E> the type of the {@code List} elements
6008 * @return the new {@code ObjectBinding}
6009 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6010 * @throws IllegalArgumentException if (@code index < 0}
6011 * @since JavaFX 2.1
6012 */
6013 public static <E> ObjectBinding<E> valueAt(final ObservableList<E> op, final int index) {
6014 if (op == null) {
6015 throw new NullPointerException("List cannot be null.");
6016 }
6017 if (index < 0) {
6018 throw new IllegalArgumentException("Index cannot be negative");
6019 }
6020
6021 return new ObjectBinding<E>() {
6022 {
6023 super.bind(op);
6024 }
6025
6026 @Override
6027 public void dispose() {
6028 super.unbind(op);
6029 }
6030
6097 }
6098 return null;
6099 }
6100
6101 @Override
6102 public ObservableList<?> getDependencies() {
6103 return new ImmutableObservableList<Observable>(op, index);
6104 }
6105 };
6106 }
6107
6108 /**
6109 * Creates a new {@link javafx.beans.binding.BooleanBinding} that contains the element
6110 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code BooleanBinding}
6111 * will hold {@code false}, if the {@code index} points behind the {@code ObservableList}.
6112 *
6113 * @param op the {@code ObservableList}
6114 * @param index the position in the {@code List}
6115 * @return the new {@code BooleanBinding}
6116 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6117 * @throws IllegalArgumentException if (@code index < 0}
6118 * @since JavaFX 2.1
6119 */
6120 public static BooleanBinding booleanValueAt(final ObservableList<Boolean> op, final int index) {
6121 if (op == null) {
6122 throw new NullPointerException("List cannot be null.");
6123 }
6124 if (index < 0) {
6125 throw new IllegalArgumentException("Index cannot be negative");
6126 }
6127
6128 return new BooleanBinding() {
6129 {
6130 super.bind(op);
6131 }
6132
6133 @Override
6134 public void dispose() {
6135 super.unbind(op);
6136 }
6137
6212 }
6213 return false;
6214 }
6215
6216 @Override
6217 public ObservableList<?> getDependencies() {
6218 return new ImmutableObservableList<Observable>(op, index);
6219 }
6220 };
6221 }
6222
6223 /**
6224 * Creates a new {@link javafx.beans.binding.DoubleBinding} that contains the element
6225 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code DoubleBinding}
6226 * will hold {@code 0.0}, if the {@code index} points behind the {@code ObservableList}.
6227 *
6228 * @param op the {@code ObservableList}
6229 * @param index the position in the {@code List}
6230 * @return the new {@code DoubleBinding}
6231 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6232 * @throws IllegalArgumentException if (@code index < 0}
6233 * @since JavaFX 2.1
6234 */
6235 public static DoubleBinding doubleValueAt(final ObservableList<? extends Number> op, final int index) {
6236 if (op == null) {
6237 throw new NullPointerException("List cannot be null.");
6238 }
6239 if (index < 0) {
6240 throw new IllegalArgumentException("Index cannot be negative");
6241 }
6242
6243 return new DoubleBinding() {
6244 {
6245 super.bind(op);
6246 }
6247
6248 @Override
6249 public void dispose() {
6250 super.unbind(op);
6251 }
6252
6327 }
6328 return 0.0;
6329 }
6330
6331 @Override
6332 public ObservableList<?> getDependencies() {
6333 return new ImmutableObservableList<Observable>(op, index);
6334 }
6335 };
6336 }
6337
6338 /**
6339 * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6340 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code FloatBinding}
6341 * will hold {@code 0.0f}, if the {@code index} points behind the {@code ObservableList}.
6342 *
6343 * @param op the {@code ObservableList}
6344 * @param index the position in the {@code List}
6345 * @return the new {@code FloatBinding}
6346 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6347 * @throws IllegalArgumentException if (@code index < 0}
6348 * @since JavaFX 2.1
6349 */
6350 public static FloatBinding floatValueAt(final ObservableList<? extends Number> op, final int index) {
6351 if (op == null) {
6352 throw new NullPointerException("List cannot be null.");
6353 }
6354 if (index < 0) {
6355 throw new IllegalArgumentException("Index cannot be negative");
6356 }
6357
6358 return new FloatBinding() {
6359 {
6360 super.bind(op);
6361 }
6362
6363 @Override
6364 public void dispose() {
6365 super.unbind(op);
6366 }
6367
6442 }
6443 return 0.0f;
6444 }
6445
6446 @Override
6447 public ObservableList<?> getDependencies() {
6448 return new ImmutableObservableList<Observable>(op, index);
6449 }
6450 };
6451 }
6452
6453 /**
6454 * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
6455 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code IntegerBinding}
6456 * will hold {@code 0}, if the {@code index} points behind the {@code ObservableList}.
6457 *
6458 * @param op the {@code ObservableList}
6459 * @param index the position in the {@code List}
6460 * @return the new {@code IntegerBinding}
6461 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6462 * @throws IllegalArgumentException if (@code index < 0}
6463 * @since JavaFX 2.1
6464 */
6465 public static IntegerBinding integerValueAt(final ObservableList<? extends Number> op, final int index) {
6466 if (op == null) {
6467 throw new NullPointerException("List cannot be null.");
6468 }
6469 if (index < 0) {
6470 throw new IllegalArgumentException("Index cannot be negative");
6471 }
6472
6473 return new IntegerBinding() {
6474 {
6475 super.bind(op);
6476 }
6477
6478 @Override
6479 public void dispose() {
6480 super.unbind(op);
6481 }
6482
6557 }
6558 return 0;
6559 }
6560
6561 @Override
6562 public ObservableList<?> getDependencies() {
6563 return new ImmutableObservableList<Observable>(op, index);
6564 }
6565 };
6566 }
6567
6568 /**
6569 * Creates a new {@link javafx.beans.binding.LongBinding} that contains the element
6570 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code LongBinding}
6571 * will hold {@code 0L}, if the {@code index} points behind the {@code ObservableList}.
6572 *
6573 * @param op the {@code ObservableList}
6574 * @param index the position in the {@code List}
6575 * @return the new {@code LongBinding}
6576 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6577 * @throws IllegalArgumentException if (@code index < 0}
6578 * @since JavaFX 2.1
6579 */
6580 public static LongBinding longValueAt(final ObservableList<? extends Number> op, final int index) {
6581 if (op == null) {
6582 throw new NullPointerException("List cannot be null.");
6583 }
6584 if (index < 0) {
6585 throw new IllegalArgumentException("Index cannot be negative");
6586 }
6587
6588 return new LongBinding() {
6589 {
6590 super.bind(op);
6591 }
6592
6593 @Override
6594 public void dispose() {
6595 super.unbind(op);
6596 }
6597
6672 }
6673 return 0L;
6674 }
6675
6676 @Override
6677 public ObservableList<?> getDependencies() {
6678 return new ImmutableObservableList<Observable>(op, index);
6679 }
6680 };
6681 }
6682
6683 /**
6684 * Creates a new {@link javafx.beans.binding.StringBinding} that contains the element
6685 * of an {@link javafx.collections.ObservableList} at the specified position. The {@code StringBinding}
6686 * will hold {@code null}, if the {@code index} points behind the {@code ObservableList}.
6687 *
6688 * @param op the {@code ObservableList}
6689 * @param index the position in the {@code List}
6690 * @return the new {@code StringBinding}
6691 * @throws NullPointerException if the {@code ObservableList} is {@code null}
6692 * @throws IllegalArgumentException if (@code index < 0}
6693 * @since JavaFX 2.1
6694 */
6695 public static StringBinding stringValueAt(final ObservableList<String> op, final int index) {
6696 if (op == null) {
6697 throw new NullPointerException("List cannot be null.");
6698 }
6699 if (index < 0) {
6700 throw new IllegalArgumentException("Index cannot be negative");
6701 }
6702
6703 return new StringBinding() {
6704 {
6705 super.bind(op);
6706 }
6707
6708 @Override
6709 public void dispose() {
6710 super.unbind(op);
6711 }
6712
6937 protected int computeValue() {
6938 return op.size();
6939 }
6940
6941 @Override
6942 public ObservableList<?> getDependencies() {
6943 return FXCollections.singletonObservableList(op);
6944 }
6945 };
6946 }
6947
6948 /**
6949 * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6950 * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code FloatBinding}
6951 * will hold {@code 0.0f}, if the {@code index} points behind the {@code ObservableArray}.
6952 *
6953 * @param op the {@code ObservableArray}
6954 * @param index the position in the {@code ObservableArray}
6955 * @return the new {@code FloatBinding}
6956 * @throws NullPointerException if the {@code ObservableArray} is {@code null}
6957 * @throws IllegalArgumentException if (@code index < 0}
6958 * @since JavaFX 8.0
6959 */
6960 public static FloatBinding floatValueAt(final ObservableFloatArray op, final int index) {
6961 if (op == null) {
6962 throw new NullPointerException("Array cannot be null.");
6963 }
6964 if (index < 0) {
6965 throw new IllegalArgumentException("Index cannot be negative");
6966 }
6967
6968 return new FloatBinding() {
6969 {
6970 super.bind(op);
6971 }
6972
6973 @Override
6974 public void dispose() {
6975 super.unbind(op);
6976 }
6977
7042 }
7043 return 0.0f;
7044 }
7045
7046 @Override
7047 public ObservableList<?> getDependencies() {
7048 return new ImmutableObservableList<>(op, index);
7049 }
7050 };
7051 }
7052
7053 /**
7054 * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
7055 * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code IntegerBinding}
7056 * will hold {@code 0}, if the {@code index} points behind the {@code ObservableArray}.
7057 *
7058 * @param op the {@code ObservableArray}
7059 * @param index the position in the {@code ObservableArray}
7060 * @return the new {@code IntegerBinding}
7061 * @throws NullPointerException if the {@code ObservableArray} is {@code null}
7062 * @throws IllegalArgumentException if (@code index < 0}
7063 * @since JavaFX 8.0
7064 */
7065 public static IntegerBinding integerValueAt(final ObservableIntegerArray op, final int index) {
7066 if (op == null) {
7067 throw new NullPointerException("Array cannot be null.");
7068 }
7069 if (index < 0) {
7070 throw new IllegalArgumentException("Index cannot be negative");
7071 }
7072
7073 return new IntegerBinding() {
7074 {
7075 super.bind(op);
7076 }
7077
7078 @Override
7079 public void dispose() {
7080 super.unbind(op);
7081 }
7082
|