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 
061     private UIThreadAwareBindings() {
062         // prevent instantiation
063     }
064 
065     /**
066      * Registers a {@code ChangeListener} that always handles notifications inside the UI thread.
067      *
068      @param observable the observable on which the listener will be registered.
069      @param listener   the wrapped change listener.
070      */
071     public static <T> void uiThreadAwareChangeListener(@Nonnull final ObservableValue<T> observable, @Nonnull ChangeListener<T> listener) {
072         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
073         observable.addListener(uiThreadAwareChangeListener(listener));
074     }
075 
076     /**
077      * Creates a {@code ChangeListener} that always handles notifications inside the UI thread.
078      *
079      @param listener the wrapped change listener.
080      *
081      @return a {@code ChangeListener}.
082      */
083     @Nonnull
084     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull ChangeListener<T> listener) {
085         requireNonNull(listener, ERROR_LISTENER_NULL);
086         return listener instanceof UIThreadAware ? listener : new UIThreadAwareChangeListener<T>(listener);
087     }
088 
089     /**
090      * Registers a {@code ChangeListener} that always handles notifications inside the UI thread.
091      *
092      @param observable the observable on which the listener will be registered.
093      @param consumer   the consumer of the {@code newValue} argument.
094      */
095     public static <T> void uiThreadAwareChangeListener(@Nonnull final ObservableValue<T> observable, @Nonnull final Consumer<T> consumer) {
096         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
097         observable.addListener(uiThreadAwareChangeListener(consumer));
098     }
099 
100     /**
101      * Creates a {@code ChangeListener} that always handles notifications inside the UI thread.
102      *
103      @param consumer the consumer of the {@code newValue} argument.
104      *
105      @return a {@code ChangeListener}.
106      */
107     @Nonnull
108     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull final Consumer<T> consumer) {
109         requireNonNull(consumer, ERROR_CONSUMER_NULL);
110         return new UIThreadAwareChangeListener<>((observable, oldValue, newValue-> consumer.accept(newValue));
111     }
112 
113     /**
114      * Registers a {@code ChangeListener} that always handles notifications inside the UI thread.
115      *
116      @param observable the observable on which the listener will be registered.
117      @param runnable   the code to be executed when the listener is notified.
118      */
119     public static <T> void uiThreadAwareChangeListener(@Nonnull final ObservableValue<T> observable, @Nonnull final Runnable runnable) {
120         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
121         observable.addListener(uiThreadAwareChangeListener(runnable));
122     }
123 
124     /**
125      * Creates a {@code ChangeListener} that always handles notifications inside the UI thread.
126      *
127      @param runnable the code to be executed when the listener is notified.
128      *
129      @return a {@code ChangeListener}.
130      */
131     @Nonnull
132     public static <T> ChangeListener<T> uiThreadAwareChangeListener(@Nonnull final Runnable runnable) {
133         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
134         return new UIThreadAwareChangeListener<>((observable, oldValue, newValue-> runnable.run());
135     }
136 
137     /**
138      * Registers a {@code InvalidationListener} that always handles notifications inside the UI thread.
139      *
140      @param observable the observable on which the listener will be registered.
141      @param listener   the wrapped invalidation listener.
142      */
143     public static void uiThreadAwareInvalidationListener(@Nonnull final Observable observable, @Nonnull InvalidationListener listener) {
144         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
145         observable.addListener(uiThreadAwareInvalidationListener(listener));
146     }
147 
148     /**
149      * Creates a {@code InvalidationListener} that always handles notifications inside the UI thread.
150      *
151      @param listener the wrapped invalidation listener.
152      *
153      @return a {@code InvalidationListener}.
154      */
155     @Nonnull
156     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull InvalidationListener listener) {
157         requireNonNull(listener, ERROR_LISTENER_NULL);
158         return listener instanceof UIThreadAware ? listener : new UIThreadAwareInvalidationListener(listener);
159     }
160 
161     /**
162      * Registers a {@code InvalidationListener} that always handles notifications inside the UI thread.
163      *
164      @param observable the observable on which the listener will be registered.
165      @param consumer   the consumer of the {@code observable} argument.
166      */
167     public static void uiThreadAwareInvalidationListener(@Nonnull final Observable observable, @Nonnull final Consumer<Observable> consumer) {
168         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
169         observable.addListener(uiThreadAwareInvalidationListener(consumer));
170     }
171 
172     /**
173      * Creates a {@code InvalidationListener} that always handles notifications inside the UI thread.
174      *
175      @param consumer the consumer of the {@code observable} argument.
176      *
177      @return a {@code InvalidationListener}.
178      */
179     @Nonnull
180     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull final Consumer<Observable> consumer) {
181         requireNonNull(consumer, ERROR_CONSUMER_NULL);
182         return new UIThreadAwareInvalidationListener(consumer::accept);
183     }
184 
185     /**
186      * Registers a {@code InvalidationListener} that always handles notifications inside the UI thread.
187      *
188      @param observable the observable on which the listener will be registered.
189      @param runnable   the code to be executed when the listener is notified.
190      */
191     public static void uiThreadAwareInvalidationListener(@Nonnull final Observable observable, @Nonnull final Runnable runnable) {
192         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
193         observable.addListener(uiThreadAwareInvalidationListener(runnable));
194     }
195 
196     /**
197      * Creates a {@code InvalidationListener} that always handles notifications inside the UI thread.
198      *
199      @param runnable the code to be executed when the listener is notified.
200      *
201      @return a {@code InvalidationListener}.
202      */
203     @Nonnull
204     public static InvalidationListener uiThreadAwareInvalidationListener(@Nonnull final Runnable runnable) {
205         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
206         return new UIThreadAwareInvalidationListener(observable -> runnable.run());
207     }
208 
209     /**
210      * Registers a {@code ListChangeListener} that always handles notifications inside the UI thread.
211      *
212      @param observable the observable on which the listener will be registered.
213      @param listener   the wrapped list change listener.
214      */
215     public static <E> void uiThreadAwareListChangeListener(@Nonnull final ObservableList<E> observable, @Nonnull ListChangeListener<E> listener) {
216         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
217         observable.addListener(uiThreadAwareListChangeListener(listener));
218     }
219 
220     /**
221      * Creates a {@code ListChangeListener} that always handles notifications inside the UI thread.
222      *
223      @param listener the wrapped list change listener.
224      *
225      @return a {@code ListChangeListener}.
226      */
227     @Nonnull
228     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull ListChangeListener<E> listener) {
229         requireNonNull(listener, ERROR_LISTENER_NULL);
230         return listener instanceof UIThreadAware ? listener : new UIThreadAwareListChangeListener<E>(listener);
231     }
232 
233     /**
234      * Registers a {@code ListChangeListener} that always handles notifications inside the UI thread.
235      *
236      @param observable the observable on which the listener will be registered.
237      @param consumer   the consumer of the {@code newValue} argument.
238      */
239     public static <E> void uiThreadAwareListChangeListener(@Nonnull final ObservableList<E> observable, @Nonnull final Consumer<ListChangeListener.Change<? extends E>> consumer) {
240         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
241         observable.addListener(uiThreadAwareListChangeListener(consumer));
242     }
243 
244     /**
245      * Creates a {@code ListChangeListener} that always handles notifications inside the UI thread.
246      *
247      @param consumer the consumer of the {@code change} argument.
248      *
249      @return a {@code ListChangeListener}.
250      */
251     @Nonnull
252     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull final Consumer<ListChangeListener.Change<? extends E>> consumer) {
253         requireNonNull(consumer, ERROR_CONSUMER_NULL);
254         return new UIThreadAwareListChangeListener<E>(consumer::accept);
255     }
256 
257     /**
258      * Registers a {@code ListChangeListener} that always handles notifications inside the UI thread.
259      *
260      @param observable the observable on which the listener will be registered.
261      @param runnable   the code to be executed when the listener is notified.
262      */
263     public static <E> void uiThreadAwareListChangeListener(@Nonnull final ObservableList<E> observable, @Nonnull final Runnable runnable) {
264         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
265         observable.addListener(uiThreadAwareListChangeListener(runnable));
266     }
267 
268     /**
269      * Creates a {@code ListChangeListener} that always handles notifications inside the UI thread.
270      *
271      @param runnable the code to be executed when the listener is notified.
272      *
273      @return a {@code ListChangeListener}.
274      */
275     @Nonnull
276     public static <E> ListChangeListener<E> uiThreadAwareListChangeListener(@Nonnull final Runnable runnable) {
277         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
278         return new UIThreadAwareListChangeListener<>(change -> runnable.run());
279     }
280 
281     /**
282      * Registers a {@code MapChangeListener} that always handles notifications inside the UI thread.
283      *
284      @param observable the observable on which the listener will be registered.
285      @param listener   the wrapped map change listener.
286      */
287     public static <K, V> void uiThreadAwareMapChangeListener(@Nonnull final ObservableMap<K, V> observable, @Nonnull MapChangeListener<K, V> listener) {
288         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
289         observable.addListener(uiThreadAwareMapChangeListener(listener));
290     }
291 
292     /**
293      * Creates a {@code MapChangeListener} that always handles notifications inside the UI thread.
294      *
295      @param listener the wrapped map change listener.
296      *
297      @return a {@code MapChangeListener}.
298      */
299     @Nonnull
300     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull MapChangeListener<K, V> listener) {
301         requireNonNull(listener, ERROR_LISTENER_NULL);
302         return listener instanceof UIThreadAware ? listener : new UIThreadAwareMapChangeListener<K, V>(listener);
303     }
304 
305     /**
306      * Registers a {@code MapChangeListener} that always handles notifications inside the UI thread.
307      *
308      @param observable the observable on which the listener will be registered.
309      @param consumer   the consumer of the {@code newValue} argument.
310      */
311     public static <K, V> void uiThreadAwareMapChangeListener(@Nonnull final ObservableMap<K, V> observable, @Nonnull final Consumer<MapChangeListener.Change<? extends K, ? extends V>> consumer) {
312         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
313         observable.addListener(uiThreadAwareMapChangeListener(consumer));
314     }
315 
316     /**
317      * Creates a {@code MapChangeListener} that always handles notifications inside the UI thread.
318      *
319      @param consumer the consumer of the {@code change} argument.
320      *
321      @return a {@code MapChangeListener}.
322      */
323     @Nonnull
324     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull final Consumer<MapChangeListener.Change<? extends K, ? extends V>> consumer) {
325         requireNonNull(consumer, ERROR_CONSUMER_NULL);
326         return new UIThreadAwareMapChangeListener<K, V>(consumer::accept);
327     }
328 
329     /**
330      * Registers a {@code MapChangeListener} that always handles notifications inside the UI thread.
331      *
332      @param observable the observable on which the listener will be registered.
333      @param runnable   the code to be executed when the listener is notified.
334      */
335     public static <K, V> void uiThreadAwareMapChangeListener(@Nonnull final ObservableMap<K, V> observable, @Nonnull final Runnable runnable) {
336         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
337         observable.addListener(uiThreadAwareMapChangeListener(runnable));
338     }
339 
340     /**
341      * Creates a {@code MapChangeListener} that always handles notifications inside the UI thread.
342      *
343      @param runnable the code to be executed when the listener is notified.
344      *
345      @return a {@code MapChangeListener}.
346      */
347     @Nonnull
348     public static <K, V> MapChangeListener<K, V> uiThreadAwareMapChangeListener(@Nonnull final Runnable runnable) {
349         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
350         return new UIThreadAwareMapChangeListener<>(change -> runnable.run());
351     }
352 
353     /**
354      * Registers a {@code SetChangeListener} that always handles notifications inside the UI thread.
355      *
356      @param observable the observable on which the listener will be registered.
357      @param listener   the wrapped set change listener.
358      */
359     public static <E> void uiThreadAwareSetChangeListener(@Nonnull final ObservableSet<E> observable, @Nonnull SetChangeListener<E> listener) {
360         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
361         observable.addListener(uiThreadAwareSetChangeListener(listener));
362     }
363 
364     /**
365      * Creates a {@code SetChangeListener} that always handles notifications inside the UI thread.
366      *
367      @param listener the wrapped set change listener.
368      *
369      @return a {@code SetChangeListener}.
370      */
371     @Nonnull
372     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull SetChangeListener<E> listener) {
373         requireNonNull(listener, ERROR_LISTENER_NULL);
374         return listener instanceof UIThreadAware ? listener : new UIThreadAwareSetChangeListener<E>(listener);
375     }
376 
377     /**
378      * Registers a {@code SetChangeListener} that always handles notifications inside the UI thread.
379      *
380      @param observable the observable on which the listener will be registered.
381      @param consumer   the consumer of the {@code newValue} argument.
382      */
383     public static <E> void uiThreadAwareSetChangeListener(@Nonnull final ObservableSet<E> observable, @Nonnull final Consumer<SetChangeListener.Change<? extends E>> consumer) {
384         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
385         observable.addListener(uiThreadAwareSetChangeListener(consumer));
386     }
387 
388     /**
389      * Creates a {@code SetChangeListener} that always handles notifications inside the UI thread.
390      *
391      @param consumer the consumer of the {@code change} argument.
392      *
393      @return a {@code SetChangeListener}.
394      */
395     @Nonnull
396     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull final Consumer<SetChangeListener.Change<? extends E>> consumer) {
397         requireNonNull(consumer, ERROR_CONSUMER_NULL);
398         return new UIThreadAwareSetChangeListener<E>(consumer::accept);
399     }
400 
401     /**
402      * Registers a {@code SetChangeListener} that always handles notifications inside the UI thread.
403      *
404      @param observable the observable on which the listener will be registered.
405      @param runnable   the code to be executed when the listener is notified.
406      */
407     public static <E> void uiThreadAwareSetChangeListener(@Nonnull final ObservableSet<E> observable, @Nonnull final Runnable runnable) {
408         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
409         observable.addListener(uiThreadAwareSetChangeListener(runnable));
410     }
411 
412     /**
413      * Creates a {@code SetChangeListener} that always handles notifications inside the UI thread.
414      *
415      @param runnable the code to be executed when the listener is notified.
416      *
417      @return a {@code SetChangeListener}.
418      */
419     @Nonnull
420     public static <E> SetChangeListener<E> uiThreadAwareSetChangeListener(@Nonnull final Runnable runnable) {
421         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
422         return new UIThreadAwareSetChangeListener<>(change -> runnable.run());
423     }
424 
425     /**
426      * Creates an observable boolean property that notifies its listeners inside the UI thread.
427      *
428      @param observable the observable boolean property to wrap.
429      *
430      @return an observable boolean property.
431      */
432     @Nonnull
433     public static BooleanProperty uiThreadAwareBooleanProperty(@Nonnull BooleanProperty observable) {
434         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
435         return observable instanceof UIThreadAware ? observable : new UIThreadAwareBooleanProperty(observable);
436     }
437 
438     /**
439      * Creates an observable integer property that notifies its listeners inside the UI thread.
440      *
441      @param observable the observable integer property to wrap.
442      *
443      @return an observable integer property.
444      */
445     @Nonnull
446     public static IntegerProperty uiThreadAwareIntegerProperty(@Nonnull IntegerProperty observable) {
447         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
448         return observable instanceof UIThreadAware ? observable : new UIThreadAwareIntegerProperty(observable);
449     }
450 
451     /**
452      * Creates an observable long property that notifies its listeners inside the UI thread.
453      *
454      @param observable the observable long property to wrap.
455      *
456      @return an observable long property.
457      */
458     @Nonnull
459     public static LongProperty uiThreadAwareLongProperty(@Nonnull LongProperty observable) {
460         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
461         return observable instanceof UIThreadAware ? observable : new UIThreadAwareLongProperty(observable);
462     }
463 
464     /**
465      * Creates an observable float property that notifies its listeners inside the UI thread.
466      *
467      @param observable the observable float property to wrap.
468      *
469      @return an observable float property.
470      */
471     @Nonnull
472     public static FloatProperty uiThreadAwareFloatProperty(@Nonnull FloatProperty observable) {
473         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
474         return observable instanceof UIThreadAware ? observable : new UIThreadAwareFloatProperty(observable);
475     }
476 
477     /**
478      * Creates an observable double property that notifies its listeners inside the UI thread.
479      *
480      @param observable the observable double property to wrap.
481      *
482      @return an observable double property.
483      */
484     @Nonnull
485     public static DoubleProperty uiThreadAwareDoubleProperty(@Nonnull DoubleProperty observable) {
486         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
487         return observable instanceof UIThreadAware ? observable : new UIThreadAwareDoubleProperty(observable);
488     }
489 
490     /**
491      * Creates an observable string property that notifies its listeners inside the UI thread.
492      *
493      @param observable the observable string property to wrap.
494      *
495      @return an observable string property.
496      */
497     @Nonnull
498     public static StringProperty uiThreadAwareStringProperty(@Nonnull StringProperty observable) {
499         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
500         return observable instanceof UIThreadAware ? observable : new UIThreadAwareStringProperty(observable);
501     }
502 
503     /**
504      * Creates an observable boolean property that notifies its listeners inside the UI thread.
505      *
506      @param observable the observable boolean property to wrap.
507      *
508      @return an observable boolean property.
509      */
510     @Nonnull
511     public static Property<Boolean> uiThreadAwarePropertyBoolean(@Nonnull Property<Boolean> observable) {
512         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
513         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyBoolean(observable);
514     }
515 
516     /**
517      * Creates an observable integer property that notifies its listeners inside the UI thread.
518      *
519      @param observable the observable integer property to wrap.
520      *
521      @return an observable integer property.
522      */
523     @Nonnull
524     public static Property<Integer> uiThreadAwarePropertyInteger(@Nonnull Property<Integer> observable) {
525         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
526         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyInteger(observable);
527     }
528 
529     /**
530      * Creates an observable long property that notifies its listeners inside the UI thread.
531      *
532      @param observable the observable long property to wrap.
533      *
534      @return an observable long property.
535      */
536     @Nonnull
537     public static Property<Long> uiThreadAwarePropertyLong(@Nonnull Property<Long> observable) {
538         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
539         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyLong(observable);
540     }
541 
542     /**
543      * Creates an observable float property that notifies its listeners inside the UI thread.
544      *
545      @param observable the observable float property to wrap.
546      *
547      @return an observable float property.
548      */
549     @Nonnull
550     public static Property<Float> uiThreadAwarePropertyFloat(@Nonnull Property<Float> observable) {
551         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
552         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyFloat(observable);
553     }
554 
555     /**
556      * Creates an observable double property that notifies its listeners inside the UI thread.
557      *
558      @param observable the observable double property to wrap.
559      *
560      @return an observable double property.
561      */
562     @Nonnull
563     public static Property<Double> uiThreadAwarePropertyDouble(@Nonnull Property<Double> observable) {
564         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
565         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyDouble(observable);
566     }
567 
568     /**
569      * Creates an observable string property that notifies its listeners inside the UI thread.
570      *
571      @param observable the observable string property to wrap.
572      *
573      @return an observable string property.
574      */
575     @Nonnull
576     public static Property<String> uiThreadAwarePropertyString(@Nonnull Property<String> observable) {
577         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
578         return observable instanceof UIThreadAware ? observable : new UIThreadAwarePropertyString(observable);
579     }
580 
581     /**
582      * Creates an observable object property that notifies its listeners inside the UI thread.
583      *
584      @param observable the observable object property to wrap.
585      *
586      @return an observable object property.
587      */
588     @Nonnull
589     public static <T> ObjectProperty<T> uiThreadAwareObjectProperty(@Nonnull final ObjectProperty<T> observable) {
590         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
591         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObjectProperty<>(observable);
592     }
593 
594     /**
595      * Creates an observable list property that notifies its listeners inside the UI thread.
596      *
597      @param observable the observable list property to wrap.
598      *
599      @return an observable list property.
600      */
601     @Nonnull
602     public static <E> ListProperty<E> uiThreadAwareListProperty(@Nonnull ListProperty<E> observable) {
603         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
604         return observable instanceof UIThreadAware ? observable : new UIThreadAwareListProperty<>(observable);
605     }
606 
607     /**
608      * Creates an observable set property that notifies its seteners inside the UI thread.
609      *
610      @param observable the observable set property to wrap.
611      *
612      @return an observable set property.
613      */
614     @Nonnull
615     public static <E> SetProperty<E> uiThreadAwareSetProperty(@Nonnull SetProperty<E> observable) {
616         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
617         return observable instanceof UIThreadAware ? observable : new UIThreadAwareSetProperty<>(observable);
618     }
619 
620     /**
621      * Creates an observable map property that notifies its listeners inside the UI thread.
622      *
623      @param observable the observable map property to wrap.
624      *
625      @return an observable map property.
626      */
627     @Nonnull
628     public static <K, V> MapProperty<K, V> uiThreadAwareMapProperty(@Nonnull MapProperty<K, V> observable) {
629         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
630         return observable instanceof UIThreadAware ? observable : new UIThreadAwareMapProperty<>(observable);
631     }
632 
633     /**
634      * Creates an observable value that notifies its listeners inside the UI thread.
635      *
636      @param observable the observable to wrap.
637      *
638      @return an observable value.
639      */
640     @Nonnull
641     public static <T> ObservableValue<T> uiThreadAwareObservable(@Nonnull final ObservableValue<T> observable) {
642         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
643         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableValue<>(observable);
644     }
645 
646     /**
647      * Creates an observable string value that notifies its listeners inside the UI thread.
648      *
649      @param observable the observable string to wrap.
650      *
651      @return an observable string value.
652      */
653     @Nonnull
654     public static ObservableStringValue uiThreadAwareObservableString(@Nonnull final ObservableStringValue observable) {
655         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
656         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableStringValue(observable);
657     }
658 
659     /**
660      * Creates an observable boolean value that notifies its listeners inside the UI thread.
661      *
662      @param observable the observable boolean to wrap.
663      *
664      @return an observable boolean value.
665      */
666     @Nonnull
667     public static ObservableBooleanValue uiThreadAwareObservableBoolean(@Nonnull final ObservableBooleanValue observable) {
668         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
669         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableBooleanValue(observable);
670     }
671 
672     /**
673      * Creates an observable integer value that notifies its listeners inside the UI thread.
674      *
675      @param observable the observable integer to wrap.
676      *
677      @return an observable integer value.
678      */
679     @Nonnull
680     public static ObservableIntegerValue uiThreadAwareObservableInteger(@Nonnull final ObservableIntegerValue observable) {
681         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
682         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableIntegerValue(observable);
683     }
684 
685     /**
686      * Creates an observable long value that notifies its listeners inside the UI thread.
687      *
688      @param observable the observable long to wrap.
689      *
690      @return an observable long value.
691      */
692     @Nonnull
693     public static ObservableLongValue uiThreadAwareObservableLong(@Nonnull final ObservableLongValue observable) {
694         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
695         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableLongValue(observable);
696     }
697 
698     /**
699      * Creates an observable float value that notifies its listeners inside the UI thread.
700      *
701      @param observable the observable float to wrap.
702      *
703      @return an observable float value.
704      */
705     @Nonnull
706     public static ObservableFloatValue uiThreadAwareObservableFloat(@Nonnull final ObservableFloatValue observable) {
707         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
708         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableFloatValue(observable);
709     }
710 
711     /**
712      * Creates an observable double value that notifies its listeners inside the UI thread.
713      *
714      @param observable the observable double to wrap.
715      *
716      @return an observable double value.
717      */
718     @Nonnull
719     public static ObservableDoubleValue uiThreadAwareObservableDouble(@Nonnull final ObservableDoubleValue observable) {
720         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
721         return observable instanceof UIThreadAware ? observable : new UIThreadAwareObservableDoubleValue(observable);
722     }
723 }