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 }
|