Skip to content

Commit 317c73a

Browse files
author
nicolaiparlog
committed
Adapted nested listener to implement 'ListenerHandle' (undocumented).
1 parent da246c7 commit 317c73a

21 files changed

+548
-215
lines changed

src/main/java/org/codefx/libfx/nesting/AbstractNestingBuilderOnObservable.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import javafx.beans.Observable;
1010
import javafx.beans.value.ObservableValue;
1111

12-
import org.codefx.libfx.nesting.listener.NestedInvalidationListener;
12+
import org.codefx.libfx.nesting.listener.NestedInvalidationListenerHandle;
1313
import org.codefx.libfx.nesting.listener.NestedInvalidationListenerBuilder;
1414

1515
/**
@@ -170,9 +170,9 @@ private void fillNestingConstructionKit(NestingConstructionKit kit) {
170170
*
171171
* @param listener
172172
* the added {@link InvalidationListener}
173-
* @return the {@link NestedInvalidationListener} which can be used to check the nesting's state
173+
* @return the {@link NestedInvalidationListenerHandle} which can be used to check the nesting's state
174174
*/
175-
public NestedInvalidationListener addListener(InvalidationListener listener) {
175+
public NestedInvalidationListenerHandle addListener(InvalidationListener listener) {
176176
Nesting<O> nesting = buildNesting();
177177
return NestedInvalidationListenerBuilder
178178
.forNesting(nesting)

src/main/java/org/codefx/libfx/nesting/AbstractNestingBuilderOnObservableValue.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import javafx.beans.value.ChangeListener;
55
import javafx.beans.value.ObservableValue;
66

7-
import org.codefx.libfx.nesting.listener.NestedChangeListener;
7+
import org.codefx.libfx.nesting.listener.NestedChangeListenerHandle;
88
import org.codefx.libfx.nesting.listener.NestedChangeListenerBuilder;
99

1010
/**
@@ -55,9 +55,9 @@ protected <P> AbstractNestingBuilderOnObservableValue(
5555
*
5656
* @param listener
5757
* the added {@link ChangeListener}
58-
* @return the {@link NestedChangeListener} which can be used to check the nesting's state
58+
* @return the {@link NestedChangeListenerHandle} which can be used to check the nesting's state
5959
*/
60-
public NestedChangeListener<T> addListener(ChangeListener<? super T> listener) {
60+
public NestedChangeListenerHandle<T> addListener(ChangeListener<? super T> listener) {
6161
Nesting<O> nesting = buildNesting();
6262
return NestedChangeListenerBuilder
6363
.forNesting(nesting)

src/main/java/org/codefx/libfx/nesting/NestingObserver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,9 @@ public NestingObserverBuilder<O> whenInnerObservableChanges(BiConsumer<Boolean,
213213
/**
214214
* Builds a observer from this builder's settings.
215215
*/
216-
@SuppressWarnings("unused")
217216
public void observe() {
218-
new NestingObserver<O>(this);
217+
@SuppressWarnings("unused")
218+
NestingObserver<O> observer = new NestingObserver<O>(this);
219219
}
220220

221221
}

src/main/java/org/codefx/libfx/nesting/Nestings.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import javafx.beans.value.ChangeListener;
77
import javafx.beans.value.ObservableValue;
88

9-
import org.codefx.libfx.nesting.listener.NestedChangeListener;
10-
import org.codefx.libfx.nesting.listener.NestedInvalidationListener;
9+
import org.codefx.libfx.nesting.listener.NestedChangeListenerHandle;
10+
import org.codefx.libfx.nesting.listener.NestedInvalidationListenerHandle;
1111
import org.codefx.libfx.nesting.property.NestedDoubleProperty;
1212
import org.codefx.libfx.nesting.property.NestedProperty;
1313

@@ -51,8 +51,8 @@
5151
*
5252
* @see Nesting
5353
* @see NestedProperty
54-
* @see NestedChangeListener
55-
* @see NestedInvalidationListener
54+
* @see NestedChangeListenerHandle
55+
* @see NestedInvalidationListenerHandle
5656
*/
5757
public class Nestings {
5858

src/main/java/org/codefx/libfx/nesting/listener/NestedChangeListenerBuilder.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import org.codefx.libfx.nesting.Nesting;
99

1010
/**
11-
* A builder for a {@link NestedChangeListener}.
11+
* A builder for a {@link NestedChangeListenerHandle}.
1212
*
1313
* @param <T>
1414
* the type of the value wrapped by the {@link ObservableValue}
@@ -113,17 +113,39 @@ private Buildable(NestedChangeListenerBuilder<T, O> builder) {
113113
}
114114

115115
/**
116-
* Builds a nested change listener. This method can only be called once as the same {@link ChangeListener}
117-
* should not be added more than once to the same {@link Nesting}.
116+
* Builds and {@link NestedChangeListenerHandle#attach() attaches} a nested change listener and returns the
117+
* handle for it.
118+
* <p>
119+
* This method can only be called once as the same {@link ChangeListener} should not be added more than once to
120+
* the same {@link Nesting}.
118121
*
119-
* @return a new instance of {@link NestedChangeListener}
122+
* @return a new instance of {@link NestedChangeListenerHandle}
123+
* @see NestedChangeListenerHandle#attach()
120124
*/
121-
public NestedChangeListener<T> build() {
125+
public NestedChangeListenerHandle<T> build() {
126+
NestedChangeListenerHandle<T> listenerHandle = buildDetached();
127+
listenerHandle.attach();
128+
return listenerHandle;
129+
}
130+
131+
/**
132+
* Builds a nested change listener and returns the handle for it.
133+
* <p>
134+
* Note that the listener is not yet {@link NestedChangeListenerHandle#attach() attached}!
135+
* <p>
136+
* This method can only be called once as the same {@link ChangeListener} should not be added more than once to
137+
* the same {@link Nesting}.
138+
*
139+
* @return a new instance of {@link NestedChangeListenerHandle}
140+
* @see #build()
141+
* @see NestedChangeListenerHandle#attach()
142+
*/
143+
public NestedChangeListenerHandle<T> buildDetached() {
122144
if (built)
123-
throw new IllegalStateException("This builder can only build one 'NestedChangeListener'.");
145+
throw new IllegalStateException("This builder can only build one 'NestedChangeListenerHandle'.");
124146

125147
built = true;
126-
return new NestedChangeListener<T>(nesting, listener);
148+
return new NestedChangeListenerHandle<T>(nesting, listener);
127149
}
128150

129151
}

src/main/java/org/codefx/libfx/nesting/listener/NestedChangeListener.java renamed to src/main/java/org/codefx/libfx/nesting/listener/NestedChangeListenerHandle.java

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,70 +8,106 @@
88
import javafx.beans.value.ChangeListener;
99
import javafx.beans.value.ObservableValue;
1010

11-
import org.codefx.libfx.nesting.Nested;
1211
import org.codefx.libfx.nesting.Nesting;
1312
import org.codefx.libfx.nesting.NestingObserver;
1413
import org.codefx.libfx.nesting.property.NestedProperty;
1514

1615
/**
17-
* <p>
1816
* Contains a {@link ChangeListener} which is connected to a {@link Nesting}. Simply put, the listener is always added
1917
* 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.
2624
* <p>
2725
* Note that if the observable is replaced, <b>the listener is not called</b>! If this is the desired behavior, a
2826
* listener has to be added to a {@link NestedProperty}.
2927
*
3028
* @param <T>
3129
* the type of the value wrapped by the {@link ObservableValue}
3230
*/
33-
public class NestedChangeListener<T> implements Nested {
31+
public class NestedChangeListenerHandle<T> implements NestedListenerHandle {
3432

3533
// #region PROPERTIES
3634

35+
private final Nesting<? extends ObservableValue<T>> nesting;
36+
3737
/**
3838
* The property indicating whether the nesting's inner observable is currently present, i.e. not null.
3939
*/
4040
private final BooleanProperty innerObservablePresent;
4141

42+
private final ChangeListener<? super T> listener;
43+
44+
private boolean attached;
45+
4246
//#end PROPERTIES
4347

4448
// #region CONSTUCTION
4549

4650
/**
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.
4955
*
5056
* @param nesting
5157
* the {@link Nesting} to which the listener is added
5258
* @param listener
5359
* the {@link ChangeListener} which is added to the nesting's {@link Nesting#innerObservableProperty()
5460
* innerObservable}
5561
*/
56-
NestedChangeListener(Nesting<? extends ObservableValue<T>> nesting, ChangeListener<? super T> listener) {
62+
NestedChangeListenerHandle(Nesting<? extends ObservableValue<T>> nesting, ChangeListener<? super T> listener) {
5763
Objects.requireNonNull(nesting, "The argument 'nesting' must not be null.");
5864
Objects.requireNonNull(listener, "The argument 'listener' must not be null.");
5965

66+
this.nesting = nesting;
6067
this.innerObservablePresent = new SimpleBooleanProperty(this, "innerObservablePresent");
68+
this.listener = listener;
6169

6270
NestingObserver
6371
.forNesting(nesting)
64-
.withOldInnerObservable(oldInnerObservable -> oldInnerObservable.removeListener(listener))
65-
.withNewInnerObservable(newInnerObservable -> newInnerObservable.addListener(listener))
72+
.withOldInnerObservable(this::remove)
73+
.withNewInnerObservable(this::addIfAttached)
6674
.whenInnerObservableChanges(
67-
(Boolean any, Boolean newInnerObservablePresent)
68-
-> innerObservablePresent.set(newInnerObservablePresent))
75+
(any, newInnerObservablePresent) -> innerObservablePresent.set(newInnerObservablePresent))
6976
.observe();
7077
}
7178

7279
//#end CONSTUCTION
7380

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

76112
@Override
77113
public ReadOnlyBooleanProperty innerObservablePresentProperty() {
@@ -83,6 +119,6 @@ public boolean isInnerObservablePresent() {
83119
return innerObservablePresent.get();
84120
}
85121

86-
//#end IMPLEMENTATION OF 'NestedProperty'
122+
//#end IMPLEMENTATION OF 'NestedListenerHandle'
87123

88124
}

src/main/java/org/codefx/libfx/nesting/listener/NestedInvalidationListenerBuilder.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import org.codefx.libfx.nesting.Nesting;
88

99
/**
10-
* A builder for a {@link NestedInvalidationListener}.
10+
* A builder for a {@link NestedInvalidationListenerHandle}.
1111
*/
1212
public class NestedInvalidationListenerBuilder {
1313

@@ -105,17 +105,39 @@ private Buildable(NestedInvalidationListenerBuilder builder) {
105105
}
106106

107107
/**
108-
* Builds a nested invalidation listener. This method can only be called once as the same
109-
* {@link InvalidationListener} should not be added more than once to the same {@link Nesting}.
108+
* Builds and {@link NestedInvalidationListenerHandle#attach() attaches} a nested invalidation listener and
109+
* returns the handle for it.
110+
* <p>
111+
* This method can only be called once as the same {@link InvalidationListener} should not be added more than
112+
* once to the same {@link Nesting}.
110113
*
111-
* @return a new instance of {@link NestedChangeListener}
114+
* @return a new instance of {@link NestedInvalidationListenerHandle}
115+
* @see NestedInvalidationListenerHandle#attach()
112116
*/
113-
public NestedInvalidationListener build() {
117+
public NestedInvalidationListenerHandle build() {
118+
NestedInvalidationListenerHandle listenerHandle = buildDetached();
119+
listenerHandle.attach();
120+
return listenerHandle;
121+
}
122+
123+
/**
124+
* Builds a nested invalidation listener and returns the handle for it.
125+
* <p>
126+
* Note that the listener is not yet {@link NestedInvalidationListenerHandle#attach() attached}!
127+
* <p>
128+
* This method can only be called once as the same {@link InvalidationListener} should not be added more than
129+
* once to the same {@link Nesting}.
130+
*
131+
* @return a new instance of {@link NestedInvalidationListenerHandle}
132+
* @see #build()
133+
* @see NestedInvalidationListenerHandle#attach()
134+
*/
135+
public NestedInvalidationListenerHandle buildDetached() {
114136
if (built)
115-
throw new IllegalStateException("This builder can only build one 'NestedInvalidationListener'.");
137+
throw new IllegalStateException("This builder can only build one 'NestedInvalidationListenerHandle'.");
116138

117139
built = true;
118-
return new NestedInvalidationListener(nesting, listener);
140+
return new NestedInvalidationListenerHandle(nesting, listener);
119141
}
120142

121143
}

0 commit comments

Comments
 (0)