UIThreadAwareBindings.java
001 /*
002  * SPDX-License-Identifier: Apache-2.0
003  *
004  * Copyright 2008-2017 the original author or authors.
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 package griffon.javafx.beans.binding;
019 
020 import javafx.beans.InvalidationListener;
021 import javafx.beans.Observable;
022 import javafx.beans.binding.BooleanBinding;
023 import javafx.beans.binding.DoubleBinding;
024 import javafx.beans.binding.FloatBinding;
025 import javafx.beans.binding.IntegerBinding;
026 import javafx.beans.binding.LongBinding;
027 import javafx.beans.binding.ObjectBinding;
028 import javafx.beans.binding.StringBinding;
029 import javafx.beans.property.BooleanProperty;
030 import javafx.beans.property.DoubleProperty;
031 import javafx.beans.property.FloatProperty;
032 import javafx.beans.property.IntegerProperty;
033 import javafx.beans.property.ListProperty;
034 import javafx.beans.property.LongProperty;
035 import javafx.beans.property.MapProperty;
036 import javafx.beans.property.ObjectProperty;
037 import javafx.beans.property.Property;
038 import javafx.beans.property.SetProperty;
039 import javafx.beans.property.StringProperty;
040 import javafx.beans.value.ChangeListener;
041 import javafx.beans.value.ObservableBooleanValue;
042 import javafx.beans.value.ObservableDoubleValue;
043 import javafx.beans.value.ObservableFloatValue;
044 import javafx.beans.value.ObservableIntegerValue;
045 import javafx.beans.value.ObservableLongValue;
046 import javafx.beans.value.ObservableStringValue;
047 import javafx.beans.value.ObservableValue;
048 import javafx.collections.ListChangeListener;
049 import javafx.collections.MapChangeListener;
050 import javafx.collections.ObservableList;
051 import javafx.collections.ObservableMap;
052 import javafx.collections.ObservableSet;
053 import javafx.collections.SetChangeListener;
054 
055 import javax.annotation.Nonnull;
056 import java.util.function.Consumer;
057 
058 import static java.util.Objects.requireNonNull;
059 
060 /**
061  @author Andres Almiray
062  @since 2.9.0
063  */
064 public final class UIThreadAwareBindings {
065     private static final String ERROR_LISTENER_NULL = "Argument 'listener' must not be null";
066     private static final String ERROR_CONSUMER_NULL = "Argument 'consumer' must not be null";
067     private static final String ERROR_RUNNABLE_NULL = "Argument 'runnable' must not be null";
068     private static final String ERROR_OBSERVABLE_NULL = "Argument 'observable' must not be null";
069     private static final String ERROR_PROPERTY_NULL = "Argument 'property' must not be null";
070     private static final String ERROR_BINDING_NULL = "Argument 'binding' must not be null";
071 
072     private UIThreadAwareBindings() {
073         // prevent instantiation
074     }
075 
076     /**
077      * Registers a {@code ChangeListener} on the supplied observable that will notify the target property.
078      *
079      @param property   the property that will be notified of value changes.
080      @param observable the observable on which the listener will be registered.
081      *
082      @return the wrapped change listener.
083      */
084     public static <T> ChangeListener<T> uiThreadAwareBind(@Nonnull final Property<T> property, @Nonnull final ObservableValue<T> observable) {
085         requireNonNull(property, ERROR_PROPERTY_NULL);
086         property.setValue(observable.getValue());
087         return uiThreadAwareChangeListener(observable, (v, o, n-> property.setValue(n));
088     }
089 
090     /**
091      * Registers a {@code ChangeListener} that always handles notifications inside the UI thread.
092      *
093      @param observable the observable on which the listener will be registered.
094      @param listener   the wrapped change listener.
095      *
096      @return a {@code ChangeListener}.
097      */
098     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull final ObservableValue<T> observable, @Nonnull ChangeListener<T> listener) {
099         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
100         ChangeListener<T> uiListener = uiThreadAwareChangeListener(listener);
101         observable.addListener(uiListener);
102         return uiListener;
103     }
104 
105     /**
106      * Creates a {@code ChangeListener} that always handles notifications inside the UI thread.
107      *
108      @param listener the wrapped change listener.
109      *
110      @return a {@code ChangeListener}.
111      */
112     @Nonnull
113     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull ChangeListener<T> listener) {
114         requireNonNull(listener, ERROR_LISTENER_NULL);
115         return listener instanceof UIThreadAware ? listener : new UIThreadAwareChangeListener<>(listener);
116     }
117 
118     /**
119      * Registers a {@code ChangeListener} that always handles notifications inside the UI thread.
120      *
121      @param observable the observable on which the listener will be registered.
122      @param consumer   the consumer of the {@code newValue} argument.
123      *
124      @return a {@code ChangeListener}.
125      */
126     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull final ObservableValue<T> observable, @Nonnull final Consumer<T> consumer) {
127         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
128         ChangeListener<T> listener = uiThreadAwareChangeListener(consumer);
129         observable.addListener(listener);
130         return listener;
131     }
132 
133     /**
134      * Creates a {@code ChangeListener} that always handles notifications inside the UI thread.
135      *
136      @param consumer the consumer of the {@code newValue} argument.
137      *
138      @return a {@code ChangeListener}.
139      */
140     @Nonnull
141     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull final Consumer<T> consumer) {
142         requireNonNull(consumer, ERROR_CONSUMER_NULL);
143         return new UIThreadAwareChangeListener<>((observable, oldValue, newValue-> consumer.accept(newValue));
144     }
145 
146     /**
147      * Registers a {@code ChangeListener} that always handles notifications inside the UI thread.
148      *
149      @param observable the observable on which the listener will be registered.
150      @param runnable   the code to be executed when the listener is notified.
151      *
152      @return a {@code ChangeListener}.
153      */
154     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull final ObservableValue<T> observable, @Nonnull final Runnable runnable) {
155         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
156         ChangeListener<T> listener = uiThreadAwareChangeListener(runnable);
157         observable.addListener(listener);
158         return listener;
159     }
160 
161     /**
162      * Creates a {@code ChangeListener} that always handles notifications inside the UI thread.
163      *
164      @param runnable the code to be executed when the listener is notified.
165      *
166      @return a {@code ChangeListener}.
167      */
168     @Nonnull
169     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull final Runnable runnable) {
170         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
171         return new UIThreadAwareChangeListener<>((observable, oldValue, newValue-> runnable.run());
172     }
173 
174     /**
175      * Registers a {@code InvalidationListener} that always handles notifications inside the UI thread.
176      *
177      @param observable the observable on which the listener will be registered.
178      @param listener   the wrapped invalidation listener.
179      *
180      @return an {@code InvalidationListener}.
181      */
182     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull final Observable observable, @Nonnull InvalidationListener listener) {
183         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
184         InvalidationListener uiListener = uiThreadAwareInvalidationListener(listener);
185         observable.addListener(uiListener);
186         return uiListener;
187     }
188 
189     /**
190      * Creates a {@code InvalidationListener} that always handles notifications inside the UI thread.
191      *
192      @param listener the wrapped invalidation listener.
193      *
194      @return a {@code InvalidationListener}.
195      */
196     @Nonnull
197     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull InvalidationListener listener) {
198         requireNonNull(listener, ERROR_LISTENER_NULL);
199         return listener instanceof UIThreadAware ? listener : new UIThreadAwareInvalidationListener(listener);
200     }
201 
202     /**
203      * Registers a {@code InvalidationListener} that always handles notifications inside the UI thread.
204      *
205      @param observable the observable on which the listener will be registered.
206      @param consumer   the consumer of the {@code observable} argument.
207      *
208      @return a {@code InvalidationListener}.
209      */
210     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull final Observable observable, @Nonnull final Consumer<Observable> consumer) {
211         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
212         InvalidationListener listener = uiThreadAwareInvalidationListener(consumer);
213         observable.addListener(listener);
214         return listener;
215     }
216 
217     /**
218      * Creates a {@code InvalidationListener} that always handles notifications inside the UI thread.
219      *
220      @param consumer the consumer of the {@code observable} argument.
221      *
222      @return a {@code InvalidationListener}.
223      */
224     @Nonnull
225     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull final Consumer<Observable> consumer) {
226         requireNonNull(consumer, ERROR_CONSUMER_NULL);
227         return new UIThreadAwareInvalidationListener(consumer::accept);
228     }
229 
230     /**
231      * Registers a {@code InvalidationListener} that always handles notifications inside the UI thread.
232      *
233      @param observable the observable on which the listener will be registered.
234      @param runnable   the code to be executed when the listener is notified.
235      *
236      @return a {@code InvalidationListener}.
237      */
238     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull final Observable observable, @Nonnull final Runnable runnable) {
239         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
240         InvalidationListener listener = uiThreadAwareInvalidationListener(runnable);
241         observable.addListener(listener);
242         return listener;
243     }
244 
245     /**
246      * Creates a {@code InvalidationListener} that always handles notifications inside the UI thread.
247      *
248      @param runnable the code to be executed when the listener is notified.
249      *
250      @return a {@code InvalidationListener}.
251      */
252     @Nonnull
253     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull final Runnable runnable) {
254         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
255         return new UIThreadAwareInvalidationListener(observable -> runnable.run());
256     }
257 
258     /**
259      * Registers a {@code ListChangeListener} that always handles notifications inside the UI thread.
260      *
261      @param observable the observable on which the listener will be registered.
262      @param listener   the wrapped list change listener.
263      *
264      @return a {@code ListChangeListener}.
265      */
266     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull final ObservableList<E> observable, @Nonnull ListChangeListener<E> listener) {
267         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
268         ListChangeListener<E> uiListener = uiThreadAwareListChangeListener(listener);
269         observable.addListener(uiListener);
270         return listener;
271     }
272 
273     /**
274      * Creates a {@code ListChangeListener} that always handles notifications inside the UI thread.
275      *
276      @param listener the wrapped list change listener.
277      *
278      @return a {@code ListChangeListener}.
279      */
280     @Nonnull
281     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull ListChangeListener<E> listener) {
282         requireNonNull(listener, ERROR_LISTENER_NULL);
283         return listener instanceof UIThreadAware ? listener : new UIThreadAwareListChangeListener<>(listener);
284     }
285 
286     /**
287      * Registers a {@code ListChangeListener} that always handles notifications inside the UI thread.
288      *
289      @param observable the observable on which the listener will be registered.
290      @param consumer   the consumer of the {@code newValue} argument.
291      *
292      @return a {@code ListChangeListener}.
293      */
294     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull final ObservableList<E> observable, @Nonnull final Consumer<ListChangeListener.Change<? extends E>> consumer) {
295         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
296         ListChangeListener<E> listener = uiThreadAwareListChangeListener(consumer);
297         observable.addListener(listener);
298         return listener;
299     }
300 
301     /**
302      * Creates a {@code ListChangeListener} that always handles notifications inside the UI thread.
303      *
304      @param consumer the consumer of the {@code change} argument.
305      *
306      @return a {@code ListChangeListener}.
307      */
308     @Nonnull
309     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull final Consumer<ListChangeListener.Change<? extends E>> consumer) {
310         requireNonNull(consumer, ERROR_CONSUMER_NULL);
311         return new UIThreadAwareListChangeListener<E>(consumer::accept);
312     }
313 
314     /**
315      * Registers a {@code ListChangeListener} that always handles notifications inside the UI thread.
316      *
317      @param observable the observable on which the listener will be registered.
318      @param runnable   the code to be executed when the listener is notified.
319      *
320      @return a {@code ListChangeListener}.
321      */
322     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull final ObservableList<E> observable, @Nonnull final Runnable runnable) {
323         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
324         ListChangeListener<E> listener = uiThreadAwareListChangeListener(runnable);
325         observable.addListener(listener);
326         return listener;
327     }
328 
329     /**
330      * Creates a {@code ListChangeListener} that always handles notifications inside the UI thread.
331      *
332      @param runnable the code to be executed when the listener is notified.
333      *
334      @return a {@code ListChangeListener}.
335      */
336     @Nonnull
337     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull final Runnable runnable) {
338         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
339         return new UIThreadAwareListChangeListener<>(change -> runnable.run());
340     }
341 
342     /**
343      * Registers a {@code MapChangeListener} that always handles notifications inside the UI thread.
344      *
345      @param observable the observable on which the listener will be registered.
346      @param listener   the wrapped map change listener.
347      *
348      @return a {@code MapChangeListener}.
349      */
350     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull final ObservableMap<K, V> observable, @Nonnull MapChangeListener<K, V> listener) {
351         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
352         MapChangeListener<K, V> uiListener = uiThreadAwareMapChangeListener(listener);
353         observable.addListener(uiListener);
354         return listener;
355     }
356 
357     /**
358      * Creates a {@code MapChangeListener} that always handles notifications inside the UI thread.
359      *
360      @param listener the wrapped map change listener.
361      *
362      @return a {@code MapChangeListener}.
363      */
364     @Nonnull
365     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull MapChangeListener<K, V> listener) {
366         requireNonNull(listener, ERROR_LISTENER_NULL);
367         return listener instanceof UIThreadAware ? listener : new UIThreadAwareMapChangeListener<>(listener);
368     }
369 
370     /**
371      * Registers a {@code MapChangeListener} that always handles notifications inside the UI thread.
372      *
373      @param observable the observable on which the listener will be registered.
374      @param consumer   the consumer of the {@code newValue} argument.
375      *
376      @return a {@code MapChangeListener}.
377      */
378     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull final ObservableMap<K, V> observable, @Nonnull final Consumer<MapChangeListener.Change<? extends K, ? extends V>> consumer) {
379         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
380         MapChangeListener<K, V> listener = uiThreadAwareMapChangeListener(consumer);
381         observable.addListener(listener);
382         return listener;
383     }
384 
385     /**
386      * Creates a {@code MapChangeListener} that always handles notifications inside the UI thread.
387      *
388      @param consumer the consumer of the {@code change} argument.
389      *
390      @return a {@code MapChangeListener}.
391      */
392     @Nonnull
393     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull final Consumer<MapChangeListener.Change<? extends K, ? extends V>> consumer) {
394         requireNonNull(consumer, ERROR_CONSUMER_NULL);
395         return new UIThreadAwareMapChangeListener<K, V>(consumer::accept);
396     }
397 
398     /**
399      * Registers a {@code MapChangeListener} that always handles notifications inside the UI thread.
400      *
401      @param observable the observable on which the listener will be registered.
402      @param runnable   the code to be executed when the listener is notified.
403      *
404      @return a {@code MapChangeListener}.
405      */
406     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull final ObservableMap<K, V> observable, @Nonnull final Runnable runnable) {
407         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
408         MapChangeListener<K, V> listener = uiThreadAwareMapChangeListener(runnable);
409         observable.addListener(listener);
410         return listener;
411     }
412 
413     /**
414      * Creates a {@code MapChangeListener} that always handles notifications inside the UI thread.
415      *
416      @param runnable the code to be executed when the listener is notified.
417      *
418      @return a {@code MapChangeListener}.
419      */
420     @Nonnull
421     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull final Runnable runnable) {
422         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
423         return new UIThreadAwareMapChangeListener<>(change -> runnable.run());
424     }
425 
426     /**
427      * Registers a {@code SetChangeListener} that always handles notifications inside the UI thread.
428      *
429      @param observable the observable on which the listener will be registered.
430      @param listener   the wrapped set change listener.
431      *
432      @return a {@code SetChangeListener}.
433      */
434     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull final ObservableSet<E> observable, @Nonnull SetChangeListener<E> listener) {
435         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
436         SetChangeListener<E> uiListener = uiThreadAwareSetChangeListener(listener);
437         observable.addListener(uiListener);
438         return listener;
439     }
440 
441     /**
442      * Creates a {@code SetChangeListener} that always handles notifications inside the UI thread.
443      *
444      @param listener the wrapped set change listener.
445      *
446      @return a {@code SetChangeListener}.
447      */
448     @Nonnull
449     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull SetChangeListener<E> listener) {
450         requireNonNull(listener, ERROR_LISTENER_NULL);
451         return listener instanceof UIThreadAware ? listener : new UIThreadAwareSetChangeListener<>(listener);
452     }
453 
454     /**
455      * Registers a {@code SetChangeListener} that always handles notifications inside the UI thread.
456      *
457      @param observable the observable on which the listener will be registered.
458      @param consumer   the consumer of the {@code newValue} argument.
459      *
460      @return a {@code SetChangeListener}.
461      */
462     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull final ObservableSet<E> observable, @Nonnull final Consumer<SetChangeListener.Change<? extends E>> consumer) {
463         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
464         SetChangeListener<E> listener = uiThreadAwareSetChangeListener(consumer);
465         observable.addListener(listener);
466         return listener;
467     }
468 
469     /**
470      * Creates a {@code SetChangeListener} that always handles notifications inside the UI thread.
471      *
472      @param consumer the consumer of the {@code change} argument.
473      *
474      @return a {@code SetChangeListener}.
475      */
476     @Nonnull
477     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull final Consumer<SetChangeListener.Change<? extends E>> consumer) {
478         requireNonNull(consumer, ERROR_CONSUMER_NULL);
479         return new UIThreadAwareSetChangeListener<E>(consumer::accept);
480     }
481 
482     /**
483      * Registers a {@code SetChangeListener} that always handles notifications inside the UI thread.
484      *
485      @param observable the observable on which the listener will be registered.
486      @param runnable   the code to be executed when the listener is notified.
487      *
488      @return a {@code SetChangeListener}.
489      */
490     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull final ObservableSet<E> observable, @Nonnull final Runnable runnable) {
491         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
492         SetChangeListener<E> listener = uiThreadAwareSetChangeListener(runnable);
493         observable.addListener(listener);
494         return listener;
495     }
496 
497     /**
498      * Creates a {@code SetChangeListener} that always handles notifications inside the UI thread.
499      *
500      @param runnable the code to be executed when the listener is notified.
501      *
502      @return a {@code SetChangeListener}.
503      */
504     @Nonnull
505     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull final Runnable runnable) {
506         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
507         return new UIThreadAwareSetChangeListener<>(change -> runnable.run());
508     }
509 
510     /**
511      * Creates an observable boolean property that notifies its listeners inside the UI thread.
512      *
513      @param observable the observable boolean property to wrap.
514      *
515      @return an observable boolean property.
516      */
517     @Nonnull
518     public static BooleanProperty uiThreadAwareBooleanProperty(@Nonnull BooleanProperty observable) {
519         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
520         return observable instanceof UIThreadAware ? observable : new UIThreadAwareBooleanProperty(observable);
521     }
522 
523     /**
524      * Creates an observable integer property that notifies its listeners inside the UI thread.
525      *
526      @param observable the observable integer property to wrap.
527      *
528      @return an observable integer property.
529      */
530     @Nonnull
531     public static IntegerProperty uiThreadAwareIntegerProperty(@Nonnull IntegerProperty observable) {
532         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
533         return observable instanceof UIThreadAware ? observable : new UIThreadAwareIntegerProperty(observable);
534     }
535 
536     /**
537      * Creates an observable long property that notifies its listeners inside the UI thread.
538      *
539      @param observable the observable long property to wrap.
540      *
541      @return an observable long property.
542      */
543     @Nonnull
544     public static LongProperty uiThreadAwareLongProperty(@Nonnull LongProperty observable) {
545         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
546         return observable instanceof UIThreadAware ? observable : new UIThreadAwareLongProperty(observable);
547     }
548 
549     /**
550      * Creates an observable float property that notifies its listeners inside the UI thread.
551      *
552      @param observable the observable float property to wrap.
553      *
554      @return an observable float property.
555      */
556     @Nonnull
557     public static FloatProperty uiThreadAwareFloatProperty(@Nonnull FloatProperty observable) {
558         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
559         return observable instanceof UIThreadAware ? observable : new UIThreadAwareFloatProperty(observable);
560     }
561 
562     /**
563      * Creates an observable double property that notifies its listeners inside the UI thread.
564      *
565      @param observable the observable double property to wrap.
566      *
567      @return an observable double property.
568      */
569     @Nonnull
570     public static DoubleProperty uiThreadAwareDoubleProperty(@Nonnull DoubleProperty observable) {
571         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
572         return observable instanceof UIThreadAware ? observable : new UIThreadAwareDoubleProperty(observable);
573     }
574 
575     /**
576      * Creates an observable string property that notifies its listeners inside the UI thread.
577      *
578      @param observable the observable string property to wrap.
579      *
580      @return an observable string property.
581      */
582     @Nonnull
583     public static StringProperty uiThreadAwareStringProperty(@Nonnull StringProperty observable) {
584         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
585         return observable instanceof UIThreadAware ? observable : new UIThreadAwareStringProperty(observable);
586     }
587 
588     /**
589      * Creates an observable boolean property that notifies its listeners inside the UI thread.
590      *
591      @param observable the observable boolean property to wrap.
592      *
593      @return an observable boolean property.
594      */
595     @Nonnull
596     public static Property<Boolean> uiThreadAwarePropertyBoolean(@Nonnull Property<Boolean> observable) {
597         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
598         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyBoolean(observable);
599     }
600 
601     /**
602      * Creates an observable integer property that notifies its listeners inside the UI thread.
603      *
604      @param observable the observable integer property to wrap.
605      *
606      @return an observable integer property.
607      */
608     @Nonnull
609     public static Property<Integer> uiThreadAwarePropertyInteger(@Nonnull Property<Integer> observable) {
610         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
611         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyInteger(observable);
612     }
613 
614     /**
615      * Creates an observable long property that notifies its listeners inside the UI thread.
616      *
617      @param observable the observable long property to wrap.
618      *
619      @return an observable long property.
620      */
621     @Nonnull
622     public static Property<Long> uiThreadAwarePropertyLong(@Nonnull Property<Long> observable) {
623         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
624         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyLong(observable);
625     }
626 
627     /**
628      * Creates an observable float property that notifies its listeners inside the UI thread.
629      *
630      @param observable the observable float property to wrap.
631      *
632      @return an observable float property.
633      */
634     @Nonnull
635     public static Property<Float> uiThreadAwarePropertyFloat(@Nonnull Property<Float> observable) {
636         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
637         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyFloat(observable);
638     }
639 
640     /**
641      * Creates an observable double property that notifies its listeners inside the UI thread.
642      *
643      @param observable the observable double property to wrap.
644      *
645      @return an observable double property.
646      */
647     @Nonnull
648     public static Property<Double> uiThreadAwarePropertyDouble(@Nonnull Property<Double> observable) {
649         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
650         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyDouble(observable);
651     }
652 
653     /**
654      * Creates an observable string property that notifies its listeners inside the UI thread.
655      *
656      @param observable the observable string property to wrap.
657      *
658      @return an observable string property.
659      */
660     @Nonnull
661     public static Property<String> uiThreadAwarePropertyString(@Nonnull Property<String> observable) {
662         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
663         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyString(observable);
664     }
665 
666     /**
667      * Creates an observable object property that notifies its listeners inside the UI thread.
668      *
669      @param observable the observable object property to wrap.
670      *
671      @return an observable object property.
672      */
673     @Nonnull
674     public static <T> ObjectProperty<T> uiThreadAwareObjectProperty(@Nonnull final ObjectProperty<T> observable) {
675         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
676         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObjectProperty<>(observable);
677     }
678 
679     /**
680      * Creates an observable list property that notifies its listeners inside the UI thread.
681      *
682      @param observable the observable list property to wrap.
683      *
684      @return an observable list property.
685      */
686     @Nonnull
687     public static <E> ListProperty<E> uiThreadAwareListProperty(@Nonnull ListProperty<E> observable) {
688         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
689         return observable instanceof UIThreadAware ? observable : new UIThreadAwareListProperty<>(observable);
690     }
691 
692     /**
693      * Creates an observable set property that notifies its seteners inside the UI thread.
694      *
695      @param observable the observable set property to wrap.
696      *
697      @return an observable set property.
698      */
699     @Nonnull
700     public static <E> SetProperty<E> uiThreadAwareSetProperty(@Nonnull SetProperty<E> observable) {
701         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
702         return observable instanceof UIThreadAware ? observable : new UIThreadAwareSetProperty<>(observable);
703     }
704 
705     /**
706      * Creates an observable map property that notifies its listeners inside the UI thread.
707      *
708      @param observable the observable map property to wrap.
709      *
710      @return an observable map property.
711      */
712     @Nonnull
713     public static <K, V> MapProperty<K, V> uiThreadAwareMapProperty(@Nonnull MapProperty<K, V> observable) {
714         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
715         return observable instanceof UIThreadAware ? observable : new UIThreadAwareMapProperty<>(observable);
716     }
717 
718     /**
719      * Creates an observable value that notifies its listeners inside the UI thread.
720      *
721      @param observable the observable to wrap.
722      *
723      @return an observable value.
724      */
725     @Nonnull
726     public static <T> ObservableValue<T> uiThreadAwareObservable(@Nonnull final ObservableValue<T> observable) {
727         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
728         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableObjectValue<>(observable);
729     }
730 
731     /**
732      * Creates an observable string value that notifies its listeners inside the UI thread.
733      *
734      @param observable the observable string to wrap.
735      *
736      @return an observable string value.
737      */
738     @Nonnull
739     public static ObservableStringValue uiThreadAwareObservableString(@Nonnull final ObservableStringValue observable) {
740         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
741         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableStringValue(observable);
742     }
743 
744     /**
745      * Creates an observable boolean value that notifies its listeners inside the UI thread.
746      *
747      @param observable the observable boolean to wrap.
748      *
749      @return an observable boolean value.
750      */
751     @Nonnull
752     public static ObservableBooleanValue uiThreadAwareObservableBoolean(@Nonnull final ObservableBooleanValue observable) {
753         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
754         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableBooleanValue(observable);
755     }
756 
757     /**
758      * Creates an observable integer value that notifies its listeners inside the UI thread.
759      *
760      @param observable the observable integer to wrap.
761      *
762      @return an observable integer value.
763      */
764     @Nonnull
765     public static ObservableIntegerValue uiThreadAwareObservableInteger(@Nonnull final ObservableIntegerValue observable) {
766         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
767         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableIntegerValue(observable);
768     }
769 
770     /**
771      * Creates an observable long value that notifies its listeners inside the UI thread.
772      *
773      @param observable the observable long to wrap.
774      *
775      @return an observable long value.
776      */
777     @Nonnull
778     public static ObservableLongValue uiThreadAwareObservableLong(@Nonnull final ObservableLongValue observable) {
779         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
780         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableLongValue(observable);
781     }
782 
783     /**
784      * Creates an observable float value that notifies its listeners inside the UI thread.
785      *
786      @param observable the observable float to wrap.
787      *
788      @return an observable float value.
789      */
790     @Nonnull
791     public static ObservableFloatValue uiThreadAwareObservableFloat(@Nonnull final ObservableFloatValue observable) {
792         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
793         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableFloatValue(observable);
794     }
795 
796     /**
797      * Creates an observable double value that notifies its listeners inside the UI thread.
798      *
799      @param observable the observable double to wrap.
800      *
801      @return an observable double value.
802      */
803     @Nonnull
804     public static ObservableDoubleValue uiThreadAwareObservableDouble(@Nonnull final ObservableDoubleValue observable) {
805         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
806         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableDoubleValue(observable);
807     }
808 
809     /**
810      * Creates a boolean binding that notifies its listeners inside the UI thread.
811      *
812      @param binding the boolean binding to wrap.
813      *
814      @return a boolean binding.
815      *
816      @since 2.13.0
817      */
818     @Nonnull
819     public static BooleanBinding uiThreadAwareBooleanBinding(@Nonnull BooleanBinding binding) {
820         requireNonNull(binding, ERROR_BINDING_NULL);
821         return binding instanceof UIThreadAware ? binding : new UIThreadAwareBooleanBinding(binding);
822     }
823 
824     /**
825      * Creates an integer binding that notifies its listeners inside the UI thread.
826      *
827      @param binding the integer binding to wrap.
828      *
829      @return an integer binding.
830      *
831      @since 2.13.0
832      */
833     @Nonnull
834     public static IntegerBinding uiThreadAwareIntegerBinding(@Nonnull IntegerBinding binding) {
835         requireNonNull(binding, ERROR_BINDING_NULL);
836         return binding instanceof UIThreadAware ? binding : new UIThreadAwareIntegerBinding(binding);
837     }
838 
839     /**
840      * Creates a long binding that notifies its listeners inside the UI thread.
841      *
842      @param binding the long binding to wrap.
843      *
844      @return a long binding.
845      *
846      @since 2.13.0
847      */
848     @Nonnull
849     public static LongBinding uiThreadAwareLongBinding(@Nonnull LongBinding binding) {
850         requireNonNull(binding, ERROR_BINDING_NULL);
851         return binding instanceof UIThreadAware ? binding : new UIThreadAwareLongBinding(binding);
852     }
853 
854     /**
855      * Creates a float binding that notifies its listeners inside the UI thread.
856      *
857      @param binding the float binding to wrap.
858      *
859      @return a float binding.
860      *
861      @since 2.13.0
862      */
863     @Nonnull
864     public static FloatBinding uiThreadAwareFloatBinding(@Nonnull FloatBinding binding) {
865         requireNonNull(binding, ERROR_BINDING_NULL);
866         return binding instanceof UIThreadAware ? binding : new UIThreadAwareFloatBinding(binding);
867     }
868 
869     /**
870      * Creates a double binding that notifies its listeners inside the UI thread.
871      *
872      @param binding the double binding to wrap.
873      *
874      @return a double binding.
875      *
876      @since 2.13.0
877      */
878     @Nonnull
879     public static DoubleBinding uiThreadAwareDoubleBinding(@Nonnull DoubleBinding binding) {
880         requireNonNull(binding, ERROR_BINDING_NULL);
881         return binding instanceof UIThreadAware ? binding : new UIThreadAwareDoubleBinding(binding);
882     }
883 
884     /**
885      * Creates a string binding that notifies its listeners inside the UI thread.
886      *
887      @param binding the string binding to wrap.
888      *
889      @return a string binding.
890      *
891      @since 2.13.0
892      */
893     @Nonnull
894     public static StringBinding uiThreadAwareStringBinding(@Nonnull StringBinding binding) {
895         requireNonNull(binding, ERROR_BINDING_NULL);
896         return binding instanceof UIThreadAware ? binding : new UIThreadAwareStringBinding(binding);
897     }
898 
899     /**
900      * Creates an object binding that notifies its listeners inside the UI thread.
901      *
902      @param binding the object binding to wrap.
903      *
904      @return an object binding.
905      *
906      @since 2.13.0
907      */
908     @Nonnull
909     public static <T> ObjectBinding<T> uiThreadAwareObjectBinding(@Nonnull ObjectBinding<T> binding) {
910         requireNonNull(binding, ERROR_BINDING_NULL);
911         return binding instanceof UIThreadAware ? binding : new UIThreadAwareObjectBinding<>(binding);
912     }
913 }