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