8
8
import javafx .beans .value .ChangeListener ;
9
9
import javafx .beans .value .ObservableValue ;
10
10
11
- import org .codefx .libfx .nesting .Nested ;
12
11
import org .codefx .libfx .nesting .Nesting ;
13
12
import org .codefx .libfx .nesting .NestingObserver ;
14
13
import org .codefx .libfx .nesting .property .NestedProperty ;
15
14
16
15
/**
17
- * <p>
18
16
* Contains a {@link ChangeListener} which is connected to a {@link Nesting}. Simply put, the listener is always added
19
17
* to the nesting's inner observable (more precisely, it is added to the {@link ObservableValue} instance contained in
20
- * the optional value held by the nesting's {@link Nesting#innerObservableProperty() innerObservable} property).
21
- * <h2> Inner Observable's Value Changes</h2> The listener is added to the nesting's inner observable. So when that
22
- * observable's value changes, the listener is called as usual.
23
- * <h2>Inner Observable Is Replaced</h2> When the nesting's inner observable is replaced by another, the listener is
24
- * removed from the old and added to the new observable. If one of them is missing, the affected removal or add is not
25
- * performed, which means the listener might not be added to any observable.
18
+ * the optional value held by the nesting's {@link Nesting#innerObservableProperty() innerObservable} property). <h2>
19
+ * Inner Observable's Value Changes</h2> The listener is added to the nesting's inner observable. So when that
20
+ * observable's value changes, the listener is called as usual. <h2>Inner Observable Is Replaced</h2> When the nesting's
21
+ * inner observable is replaced by another, the listener is removed from the old and added to the new observable. If one
22
+ * of them is missing, the affected removal or add is not performed, which means the listener might not be added to any
23
+ * observable.
26
24
* <p>
27
25
* Note that if the observable is replaced, <b>the listener is not called</b>! If this is the desired behavior, a
28
26
* listener has to be added to a {@link NestedProperty}.
29
27
*
30
28
* @param <T>
31
29
* the type of the value wrapped by the {@link ObservableValue}
32
30
*/
33
- public class NestedChangeListener <T > implements Nested {
31
+ public class NestedChangeListenerHandle <T > implements NestedListenerHandle {
34
32
35
33
// #region PROPERTIES
36
34
35
+ private final Nesting <? extends ObservableValue <T >> nesting ;
36
+
37
37
/**
38
38
* The property indicating whether the nesting's inner observable is currently present, i.e. not null.
39
39
*/
40
40
private final BooleanProperty innerObservablePresent ;
41
41
42
+ private final ChangeListener <? super T > listener ;
43
+
44
+ private boolean attached ;
45
+
42
46
//#end PROPERTIES
43
47
44
48
// #region CONSTUCTION
45
49
46
50
/**
47
- * Creates a new {@link NestedChangeListener} which adds the specified listener to the specified nesting's inner
48
- * observable.
51
+ * Creates a new {@link NestedChangeListenerHandle} which can {@link #attach() attach} the specified listener to the
52
+ * specified nesting's inner observable.
53
+ * <p>
54
+ * The listener is initially detached.
49
55
*
50
56
* @param nesting
51
57
* the {@link Nesting} to which the listener is added
52
58
* @param listener
53
59
* the {@link ChangeListener} which is added to the nesting's {@link Nesting#innerObservableProperty()
54
60
* innerObservable}
55
61
*/
56
- NestedChangeListener (Nesting <? extends ObservableValue <T >> nesting , ChangeListener <? super T > listener ) {
62
+ NestedChangeListenerHandle (Nesting <? extends ObservableValue <T >> nesting , ChangeListener <? super T > listener ) {
57
63
Objects .requireNonNull (nesting , "The argument 'nesting' must not be null." );
58
64
Objects .requireNonNull (listener , "The argument 'listener' must not be null." );
59
65
66
+ this .nesting = nesting ;
60
67
this .innerObservablePresent = new SimpleBooleanProperty (this , "innerObservablePresent" );
68
+ this .listener = listener ;
61
69
62
70
NestingObserver
63
71
.forNesting (nesting )
64
- .withOldInnerObservable (oldInnerObservable -> oldInnerObservable . removeListener ( listener ) )
65
- .withNewInnerObservable (newInnerObservable -> newInnerObservable . addListener ( listener ) )
72
+ .withOldInnerObservable (this :: remove )
73
+ .withNewInnerObservable (this :: addIfAttached )
66
74
.whenInnerObservableChanges (
67
- (Boolean any , Boolean newInnerObservablePresent )
68
- -> innerObservablePresent .set (newInnerObservablePresent ))
75
+ (any , newInnerObservablePresent ) -> innerObservablePresent .set (newInnerObservablePresent ))
69
76
.observe ();
70
77
}
71
78
72
79
//#end CONSTUCTION
73
80
74
- // #region IMPLEMENTATION OF 'Nested'
81
+ // #region ADD & REMOVE
82
+
83
+ private void addIfAttached (ObservableValue <T > observable ) {
84
+ if (attached )
85
+ observable .addListener (listener );
86
+ }
87
+
88
+ private void remove (ObservableValue <T > observable ) {
89
+ observable .removeListener (listener );
90
+ }
91
+
92
+ // #end ADD & REMOVE
93
+
94
+ // #region IMPLEMENTATION OF 'NestedListenerHandle'
95
+
96
+ @ Override
97
+ public void attach () {
98
+ if (!attached ) {
99
+ attached = true ;
100
+ nesting .innerObservableProperty ().getValue ().ifPresent (this ::addIfAttached );
101
+ }
102
+ }
103
+
104
+ @ Override
105
+ public void detach () {
106
+ if (attached ) {
107
+ attached = false ;
108
+ nesting .innerObservableProperty ().getValue ().ifPresent (this ::remove );
109
+ }
110
+ }
75
111
76
112
@ Override
77
113
public ReadOnlyBooleanProperty innerObservablePresentProperty () {
@@ -83,6 +119,6 @@ public boolean isInnerObservablePresent() {
83
119
return innerObservablePresent .get ();
84
120
}
85
121
86
- //#end IMPLEMENTATION OF 'NestedProperty '
122
+ //#end IMPLEMENTATION OF 'NestedListenerHandle '
87
123
88
124
}
0 commit comments