Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 66d49e46ac09cca81e31439c117a1aeb51bd1bab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
/*******************************************************************************
 * Copyright (c) 2006, 2009 Cerner Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Brad Reynolds - initial API and implementation
 *     Matt Carter - bug 212518 (constantObservableValue)
 *     Matthew Hall - bugs 208332, 212518, 219909, 184830, 237718, 245647,
 *         226289
 *     Marko Topolnik - bug 184830
 ******************************************************************************/

package org.eclipse.core.databinding.observable;

import java.util.List;
import java.util.Set;

import org.eclipse.core.databinding.observable.list.DecoratingObservableList;
import org.eclipse.core.databinding.observable.list.IListChangeListener;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.ObservableList;
import org.eclipse.core.databinding.observable.map.DecoratingObservableMap;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
import org.eclipse.core.databinding.observable.set.DecoratingObservableSet;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
import org.eclipse.core.databinding.observable.set.ObservableSet;
import org.eclipse.core.databinding.observable.value.DecoratingObservableValue;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.IVetoableValue;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.core.databinding.observable.value.ValueChangingEvent;
import org.eclipse.core.internal.databinding.observable.ConstantObservableValue;
import org.eclipse.core.internal.databinding.observable.DelayedObservableValue;
import org.eclipse.core.internal.databinding.observable.EmptyObservableList;
import org.eclipse.core.internal.databinding.observable.EmptyObservableSet;
import org.eclipse.core.internal.databinding.observable.MapEntryObservableValue;
import org.eclipse.core.internal.databinding.observable.StalenessObservableValue;
import org.eclipse.core.internal.databinding.observable.UnmodifiableObservableList;
import org.eclipse.core.internal.databinding.observable.UnmodifiableObservableMap;
import org.eclipse.core.internal.databinding.observable.UnmodifiableObservableSet;
import org.eclipse.core.internal.databinding.observable.UnmodifiableObservableValue;
import org.eclipse.core.runtime.Assert;

/**
 * Contains static methods to operate on or return {@link IObservable
 * Observables}.
 * 
 * @since 1.0
 */
public class Observables {
	/**
	 * Returns an observable which delays notification of value change events
	 * from <code>observable</code> until <code>delay</code> milliseconds have
	 * elapsed since the last change event. This observable helps to boost
	 * performance in situations where an observable has computationally
	 * expensive listeners or many dependencies. A common use of this observable
	 * is to delay validation of user input until the user stops typing in a UI
	 * field.
	 * <p>
	 * To notify about pending changes, the returned observable fires a stale
	 * event when the wrapped observable value fires a change event, and remains
	 * stale until the delay has elapsed and the value change is fired. A call
	 * to {@link IObservableValue#getValue() getValue()} while a value change is
	 * pending will fire the value change immediately, short-circuiting the
	 * delay.
	 * <p>
	 * <b>Note:</b>
	 * <ul>
	 * <li>Use SWTObservables.observeDelayedValue() instead when the target
	 * observable is observing a SWT Control, or
	 * ViewersObservables.observeDelayedValue() when the target observable is
	 * observing a JFace Viewer. These observables ensure that pending value
	 * changes are fired when the underlying control loses focus. (Otherwise, it
	 * is possible for pending changes to be lost if a window is closed before
	 * the delay has elapsed.)
	 * <li>This observable does not forward {@link ValueChangingEvent} events
	 * from a wrapped {@link IVetoableValue}.
	 * </ul>
	 * 
	 * @param <T>
	 * 
	 * @param delay
	 *            the delay in milliseconds
	 * @param observable
	 *            the observable being delayed
	 * @return an observable which delays notification of value change events
	 *         from <code>observable</code> until <code>delay</code>
	 *         milliseconds have elapsed since the last change event.
	 * 
	 * @since 1.2
	 */
	public static <T> IObservableValue<T> observeDelayedValue(int delay,
			IObservableValue<T> observable) {
		return new DelayedObservableValue<T>(delay, observable);
	}

	/**
	 * Returns an unmodifiable observable value backed by the given observable
	 * value.
	 * 
	 * @param <T>
	 * 
	 * @param value
	 *            the value to wrap in an unmodifiable value
	 * @return an unmodifiable observable value backed by the given observable
	 *         value
	 * @since 1.1
	 */
	public static <T> IObservableValue<T> unmodifiableObservableValue(
			IObservableValue<T> value) {
		Assert.isNotNull(value, "Argument 'value' cannot be null"); //$NON-NLS-1$
		return new UnmodifiableObservableValue<T>(value);
	}

	/**
	 * Returns an observable value with the given constant value.
	 * 
	 * @param <T>
	 * 
	 * @param realm
	 *            the observable's realm
	 * @param value
	 *            the observable's constant value
	 * @param valueType
	 *            the observable's value type
	 * @return an immutable observable value with the given constant value
	 * @since 1.1
	 */
	public static <T> IObservableValue<T> constantObservableValue(Realm realm,
			T value, Object valueType) {
		return new ConstantObservableValue<T>(realm, value, valueType);
	}

	/**
	 * Returns an observable value with the given constant value.
	 * 
	 * @param <T>
	 * 
	 * @param realm
	 *            the observable's realm
	 * @param value
	 *            the observable's constant value
	 * @return an immutable observable value with the given constant value
	 * @since 1.1
	 */
	public static <T> IObservableValue<T> constantObservableValue(Realm realm,
			T value) {
		return constantObservableValue(realm, value, null);
	}

	/**
	 * Returns an observable value with the given constant value.
	 * 
	 * @param <T>
	 * 
	 * @param value
	 *            the observable's constant value
	 * @param valueType
	 *            the observable's value type
	 * @return an immutable observable value with the given constant value
	 * @since 1.1
	 */
	public static <T> IObservableValue<T> constantObservableValue(T value,
			T valueType) {
		return constantObservableValue(Realm.getDefault(), value, valueType);
	}

	/**
	 * Returns an observable value with the given constant value.
	 * 
	 * @param <T>
	 * 
	 * @param value
	 *            the observable's constant value
	 * @return an immutable observable value with the given constant value
	 * @since 1.1
	 */
	public static <T> IObservableValue<T> constantObservableValue(T value) {
		return constantObservableValue(Realm.getDefault(), value, null);
	}

	/**
	 * Returns an unmodifiable observable list backed by the given observable
	 * list.
	 * 
	 * @param <E>
	 * 
	 * @param list
	 *            the list to wrap in an unmodifiable list
	 * @return an unmodifiable observable list backed by the given observable
	 *         list
	 */
	public static <E> IObservableList<E> unmodifiableObservableList(
			IObservableList<E> list) {
		if (list == null) {
			throw new IllegalArgumentException("List parameter cannot be null."); //$NON-NLS-1$
		}

		return new UnmodifiableObservableList<E>(list);
	}

	/**
	 * Returns an unmodifiable observable set backed by the given observable
	 * set.
	 * 
	 * @param <E>
	 * 
	 * @param set
	 *            the set to wrap in an unmodifiable set
	 * @return an unmodifiable observable set backed by the given observable set
	 * @since 1.1
	 */
	public static <E> IObservableSet<E> unmodifiableObservableSet(
			IObservableSet<E> set) {
		if (set == null) {
			throw new IllegalArgumentException("Set parameter cannot be null"); //$NON-NLS-1$
		}

		return new UnmodifiableObservableSet<E>(set);
	}

	/**
	 * Returns an unmodifiable observable map backed by the given observable
	 * map.
	 * 
	 * @param <K>
	 * @param <V>
	 * 
	 * @param map
	 *            the map to wrap in an unmodifiable map
	 * @return an unmodifiable observable map backed by the given observable
	 *         map.
	 * @since 1.2
	 */
	public static <K, V> IObservableMap<K, V> unmodifiableObservableMap(
			IObservableMap<K, V> map) {
		if (map == null) {
			throw new IllegalArgumentException("Map parameter cannot be null"); //$NON-NLS-1$
		}

		return new UnmodifiableObservableMap<K, V>(map);
	}

	/**
	 * Returns an empty observable list. The returned list continues to work
	 * after it has been disposed of and can be disposed of multiple times.
	 * 
	 * @return an empty observable list.
	 */
	public static IObservableList<Object> emptyObservableList() {
		return emptyObservableList(Realm.getDefault(), null);
	}

	/**
	 * Returns an empty observable list of the given element type. The returned
	 * list continues to work after it has been disposed of and can be disposed
	 * of multiple times.
	 * 
	 * @param elementType
	 *            the element type of the returned list
	 * @return an empty observable list
	 * @since 1.1
	 */
	public static IObservableList<Object> emptyObservableList(Object elementType) {
		return emptyObservableList(Realm.getDefault(), elementType);
	}

	/**
	 * Returns an empty observable list belonging to the given realm. The
	 * returned list continues to work after it has been disposed of and can be
	 * disposed of multiple times.
	 * 
	 * @param realm
	 *            the realm of the returned list
	 * @return an empty observable list.
	 */
	public static IObservableList<Object> emptyObservableList(Realm realm) {
		return emptyObservableList(realm, null);
	}

	/**
	 * Returns an empty observable list of the given element type and belonging
	 * to the given realm. The returned list continues to work after it has been
	 * disposed of and can be disposed of multiple times.
	 * 
	 * @param realm
	 *            the realm of the returned list
	 * @param elementType
	 *            the element type of the returned list
	 * @return an empty observable list
	 * @since 1.1
	 */
	public static IObservableList<Object> emptyObservableList(Realm realm,
			Object elementType) {
		return new EmptyObservableList<Object>(realm, elementType);
	}

	/**
	 * Returns an empty observable set. The returned set continues to work after
	 * it has been disposed of and can be disposed of multiple times.
	 * 
	 * @return an empty observable set.
	 */
	public static IObservableSet<Object> emptyObservableSet() {
		return emptyObservableSet(Realm.getDefault(), null);
	}

	/**
	 * Returns an empty observable set of the given element type. The returned
	 * set continues to work after it has been disposed of and can be disposed
	 * of multiple times.
	 * 
	 * @param elementType
	 *            the element type of the returned set
	 * @return an empty observable set
	 * @since 1.1
	 */
	public static IObservableSet<Object> emptyObservableSet(Object elementType) {
		return emptyObservableSet(Realm.getDefault(), elementType);
	}

	/**
	 * Returns an empty observable set belonging to the given realm. The
	 * returned set continues to work after it has been disposed of and can be
	 * disposed of multiple times.
	 * 
	 * @param realm
	 *            the realm of the returned set
	 * @return an empty observable set.
	 */
	public static IObservableSet<Object> emptyObservableSet(Realm realm) {
		return emptyObservableSet(realm, null);
	}

	/**
	 * Returns an empty observable set of the given element type and belonging
	 * to the given realm. The returned set continues to work after it has been
	 * disposed of and can be disposed of multiple times.
	 * 
	 * @param realm
	 *            the realm of the returned set
	 * @param elementType
	 *            the element type of the returned set
	 * @return an empty observable set
	 * @since 1.1
	 */
	public static IObservableSet<Object> emptyObservableSet(Realm realm,
			Object elementType) {
		return new EmptyObservableSet<Object>(realm, elementType);
	}

	/**
	 * Returns an observable set backed by the given set.
	 * 
	 * @param <E>
	 * 
	 * @param set
	 *            the set to wrap in an IObservableSet
	 * @return an observable set backed by the given set
	 */
	public static <E> IObservableSet<E> staticObservableSet(Set<E> set) {
		return staticObservableSet(Realm.getDefault(), set, Object.class);
	}

	/**
	 * Returns an observable set of the given element type, backed by the given
	 * set.
	 * 
	 * @param <E>
	 * 
	 * @param set
	 *            the set to wrap in an IObservableSet
	 * @param elementType
	 *            the element type of the returned set
	 * @return Returns an observable set backed by the given unchanging set
	 * @since 1.1
	 */
	public static <E> IObservableSet<E> staticObservableSet(Set<E> set,
			Object elementType) {
		return staticObservableSet(Realm.getDefault(), set, elementType);
	}

	/**
	 * Returns an observable set belonging to the given realm, backed by the
	 * given set.
	 * 
	 * @param <E>
	 * 
	 * @param realm
	 *            the realm of the returned set
	 * @param set
	 *            the set to wrap in an IObservableSet
	 * @return an observable set backed by the given unchanging set
	 */
	public static <E> IObservableSet<E> staticObservableSet(Realm realm,
			Set<E> set) {
		return staticObservableSet(realm, set, Object.class);
	}

	/**
	 * Returns an observable set of the given element type and belonging to the
	 * given realm, backed by the given set.
	 * 
	 * @param <E>
	 * 
	 * @param realm
	 *            the realm of the returned set
	 * @param set
	 *            the set to wrap in an IObservableSet
	 * @param elementType
	 *            the element type of the returned set
	 * @return an observable set backed by the given set
	 * @since 1.1
	 */
	public static <E> IObservableSet<E> staticObservableSet(Realm realm,
			Set<E> set, Object elementType) {
		return new ObservableSet<E>(realm, set, elementType) {
			public synchronized void addChangeListener(IChangeListener listener) {
			}

			public synchronized void addStaleListener(IStaleListener listener) {
			}

			public synchronized void addSetChangeListener(
					ISetChangeListener<? super E> listener) {
			}
		};
	}

	/**
	 * Returns an observable value that contains the same value as the given
	 * observable, and fires the same events as the given observable, but can be
	 * disposed of without disposing of the wrapped observable.
	 * 
	 * @param <T>
	 * 
	 * @param target
	 *            the observable value to wrap
	 * @return a disposable proxy for the given observable value.
	 * @since 1.2
	 */
	public static <T> IObservableValue<T> proxyObservableValue(
			IObservableValue<T> target) {
		return new DecoratingObservableValue<T>(target, false);
	}

	/**
	 * Returns an observable set that contains the same elements as the given
	 * set, and fires the same events as the given set, but can be disposed of
	 * without disposing of the wrapped set.
	 * 
	 * @param <E>
	 * 
	 * @param target
	 *            the set to wrap
	 * @return a disposable proxy for the given observable set
	 */
	public static <E> IObservableSet<E> proxyObservableSet(
			IObservableSet<E> target) {
		return new DecoratingObservableSet<E>(target, false);
	}

	/**
	 * Returns an observable list that contains the same elements as the given
	 * list, and fires the same events as the given list, but can be disposed of
	 * without disposing of the wrapped list.
	 * 
	 * @param <E>
	 * 
	 * @param target
	 *            the list to wrap
	 * @return a disposable proxy for the given observable list
	 * @since 1.1
	 */
	public static <E> IObservableList<E> proxyObservableList(
			IObservableList<E> target) {
		return new DecoratingObservableList<E>(target, false);
	}

	/**
	 * Returns an observable map that contains the same entries as the given
	 * map, and fires the same events as the given map, but can be disposed of
	 * without disposing of the wrapped map.
	 * 
	 * @param <K>
	 * @param <V>
	 * 
	 * @param target
	 *            the map to wrap
	 * @return a disposable proxy for the given observable map
	 * @since 1.2
	 */
	public static <K, V> IObservableMap<K, V> proxyObservableMap(
			IObservableMap<K, V> target) {
		return new DecoratingObservableMap<K, V>(target, false);
	}

	/**
	 * Returns an observable list backed by the given list.
	 * 
	 * @param <E>
	 * 
	 * @param list
	 *            the list to wrap in an IObservableList
	 * @return an observable list backed by the given unchanging list
	 */
	public static <E> IObservableList<E> staticObservableList(List<E> list) {
		return staticObservableList(Realm.getDefault(), list, Object.class);
	}

	/**
	 * Returns an observable list of the given element type, backed by the given
	 * list.
	 * 
	 * @param <E>
	 * 
	 * @param list
	 *            the list to wrap in an IObservableList
	 * @param elementType
	 *            the element type of the returned list
	 * @return an observable list backed by the given unchanging list
	 * @since 1.1
	 */
	public static <E> IObservableList<E> staticObservableList(List<E> list,
			Object elementType) {
		return staticObservableList(Realm.getDefault(), list, elementType);
	}

	/**
	 * Returns an observable list belonging to the given realm, backed by the
	 * given list.
	 * 
	 * @param <E>
	 * 
	 * @param realm
	 *            the realm of the returned list
	 * @param list
	 *            the list to wrap in an IObservableList
	 * @return an observable list backed by the given unchanging list
	 */
	public static <E> IObservableList<E> staticObservableList(Realm realm,
			List<E> list) {
		return staticObservableList(realm, list, Object.class);
	}

	/**
	 * Returns an observable list of the given element type and belonging to the
	 * given realm, backed by the given list.
	 * 
	 * @param <E>
	 * 
	 * @param realm
	 *            the realm of the returned list
	 * @param list
	 *            the list to wrap in an IObservableList
	 * @param elementType
	 *            the element type of the returned list
	 * @return an observable list backed by the given unchanging list
	 * @since 1.1
	 */
	public static <E> IObservableList<E> staticObservableList(Realm realm,
			List<E> list, Object elementType) {
		return new ObservableList<E>(realm, list, elementType) {
			public synchronized void addChangeListener(IChangeListener listener) {
			}

			public synchronized void addStaleListener(IStaleListener listener) {
			}

			public synchronized void addListChangeListener(
					IListChangeListener<E> listener) {
			}
		};
	}

	/**
	 * Returns an observable value of type <code>Boolean.TYPE</code> which
	 * tracks whether the given observable is stale.
	 * 
	 * @param observable
	 *            the observable to track
	 * @return an observable value which tracks whether the given observable is
	 *         stale
	 * 
	 * @since 1.1
	 */
	public static IObservableValue<Boolean> observeStale(IObservable observable) {
		return new StalenessObservableValue(observable);
	}

	/**
	 * Returns an observable value that tracks changes to the value of an
	 * observable map's entry specified by its key.
	 * <p>
	 * The state where the key does not exist in the map is equivalent to the
	 * state where the key exists and its value is <code>null</code>. The
	 * transition between these two states is not considered a value change and
	 * no event is fired.
	 * 
	 * @param <K>
	 * 
	 * @param <V>
	 * 
	 * @param map
	 *            the observable map whose entry will be tracked.
	 * @param key
	 *            the key identifying the map entry to track.
	 * @return an observable value that tracks the value associated with the
	 *         specified key in the given map
	 * @since 1.2
	 */
	public static <K, V> IObservableValue<V> observeMapEntry(
			IObservableMap<K, V> map, K key) {
		return observeMapEntry(map, key, map.getValueType());
	}

	/**
	 * Returns an observable value that tracks changes to the value of an
	 * observable map's entry specified by its key.
	 * <p>
	 * The state where the key does not exist in the map is equivalent to the
	 * state where the key exists and its value is <code>null</code>. The
	 * transition between these two states is not considered a value change and
	 * no event is fired.
	 * 
	 * @param <K>
	 * 
	 * @param <V>
	 * 
	 * @param map
	 *            the observable map whose entry will be tracked.
	 * @param key
	 *            the key identifying the map entry to track.
	 * @param valueType
	 *            the type of the value. May be <code>null</code>, meaning the
	 *            value is untyped.
	 * @return an observable value that tracks the value associated with the
	 *         specified key in the given map
	 * @since 1.1
	 */
	public static <K, V> IObservableValue<V> observeMapEntry(
			IObservableMap<K, V> map, K key, Object valueType) {
		if (valueType == null)
			valueType = map.getValueType();
		return new MapEntryObservableValue<K, V>(map, key, valueType);
	}

	/**
	 * Returns a factory for creating observable values tracking the value of
	 * the {@link IObservableMap observable map} entry identified by a
	 * particular key.
	 * 
	 * @param <K>
	 * @param <V>
	 * 
	 * @param map
	 *            the observable map whose entry will be tracked.
	 * @param valueType
	 *            the type of the value. May be <code>null</code>, meaning the
	 *            value is untyped.
	 * @return a factory for creating observable values tracking the value of
	 *         the observable map entry identified by a particular key object.
	 * @since 1.1
	 */
	public static <K, V> IObservableFactory<K, IObservableValue<V>> mapEntryValueFactory(
			final IObservableMap<K, V> map, final Object valueType) {
		return new IObservableFactory<K, IObservableValue<V>>() {
			public IObservableValue<V> createObservable(K key) {
				return observeMapEntry(map, key, valueType);
			}
		};
	}

	/**
	 * Helper method for <code>MasterDetailObservables.detailValue(master,
	 * mapEntryValueFactory(map, valueType), valueType)</code>.
	 * 
	 * @param <K>
	 * @param <V>
	 * 
	 * @param map
	 *            the observable map whose entry will be tracked.
	 * @param master
	 *            the observable value that identifies which map entry to track.
	 * @param valueType
	 *            the type of the value. May be <code>null</code>, meaning the
	 *            value is untyped.
	 * @return an observable value tracking the current value of the specified
	 *         key in the given map an observable value that tracks the current
	 *         value of the named property for the current value of the master
	 *         observable value
	 * @since 1.1
	 */
	public static <K, V> IObservableValue<V> observeDetailMapEntry(
			IObservableMap<K, V> map, IObservableValue<K> master,
			Object valueType) {
		return MasterDetailObservables.detailValue(master,
				mapEntryValueFactory(map, valueType), valueType);
	}

	/**
	 * Copies the current value of the source observable to the destination
	 * observable, and upon value change events fired by the source observable,
	 * updates the destination observable accordingly, until the source
	 * observable is disposed. This method assumes that both observables are on
	 * the same realm.
	 * 
	 * @param <T>
	 * 
	 * @param source
	 *            the source observable
	 * @param destination
	 *            the destination observable
	 * @since 1.2
	 */
	public static <T> void pipe(IObservableValue<T> source,
			final IObservableValue<? super T> destination) {
		destination.setValue(source.getValue());
		source.addValueChangeListener(new IValueChangeListener<T>() {
			public void handleValueChange(ValueChangeEvent<T> event) {
				destination.setValue(event.diff.getNewValue());
			}
		});
	}
}

Back to the top