Skip to content

Commit f2d8c68

Browse files
committed
Add nested support for CompositeBinding
1 parent 308e9b6 commit f2d8c68

File tree

1 file changed

+86
-15
lines changed

1 file changed

+86
-15
lines changed

src/main/java/rx/subscriptions/CompositeBinding.java

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
/**
1111
* A group of of Bindings that are disposed together.
1212
* <p>
13-
* All methods of this class are thread-safe.
13+
* All methods of this class must be called on JavaFX Thread
1414
*/
1515
public final class CompositeBinding {
1616

1717
private Set<Binding> bindings;
18+
private Set<CompositeBinding> compBindings;
1819
private boolean disposedInd;
1920

2021
public CompositeBinding() {}
@@ -24,16 +25,40 @@ public CompositeBinding(final Binding... bindings) {
2425
}
2526

2627
public void invalidate() {
27-
bindings.forEach(Binding::invalidate);
28+
if (bindings != null) {
29+
bindings.forEach(Binding::invalidate);
30+
}
31+
if (compBindings != null) {
32+
compBindings.forEach(CompositeBinding::invalidate);
33+
}
2834
}
2935
public boolean isDisposed() {
3036
return disposedInd;
3137
}
3238

39+
/**
40+
* Adds a new {@link CompositeBinding} to this {@code CompositeBinding} if the
41+
* {@code CompositeBinding} is not yet disposed. If the {@code CompositeBinding} <em>is</em>
42+
* disposed, {@code add} will indicate this by explicitly disposing the new {@code CompositeBinding} as
43+
* well.
44+
*
45+
* @param b the {@link Subscription} to add
46+
*/
47+
public void add(final CompositeBinding b) {
48+
if (!disposedInd) {
49+
if (compBindings == null) {
50+
compBindings = new HashSet<>(4);
51+
}
52+
compBindings.add(b);
53+
return;
54+
}
55+
b.dispose();
56+
}
57+
3358
/**
3459
* Adds a new {@link Binding} to this {@code CompositeBinding} if the
3560
* {@code CompositeBinding} is not yet disposedInd. If the {@code CompositeBinding} <em>is</em>
36-
* disposed, {@code add} will indicate this by explicitly unsubscribing the new {@code Subscription} as
61+
* disposed, {@code add} will indicate this by explicitly disposing the new {@code Binding} as
3762
* well.
3863
*
3964
* @param b the {@link Subscription} to add
@@ -49,6 +74,26 @@ public void add(final Binding b) {
4974
b.dispose();
5075
}
5176

77+
/**
78+
* Removes a {@link CompositeBinding} from this {@code CompositeBinding}, and disposes the
79+
* {@link CompositeBinding}.
80+
*
81+
* @param b the {@link CompositeBinding} to remove
82+
*/
83+
public void remove(final CompositeBinding b) {
84+
if (!disposedInd) {
85+
boolean unsubscribe = false;
86+
if (compBindings == null) {
87+
return;
88+
}
89+
unsubscribe = compBindings.remove(b);
90+
if (unsubscribe) {
91+
// if we removed successfully we then need to call dispose on it
92+
b.dispose();
93+
}
94+
}
95+
}
96+
5297
/**
5398
* Removes a {@link Binding} from this {@code CompositeBinding}, and disposes the
5499
* {@link Binding}.
@@ -69,21 +114,29 @@ public void remove(final Binding b) {
69114
}
70115
}
71116

117+
72118
/**
73119
* Disposes any bindings that are currently part of this {@code CompositeBinding} and remove
74120
* them from the {@code CompositeBinding} so that the {@code CompositeBinding} is empty and
75121
* able to manage new bindings.
76122
*/
77123
public void clear() {
78124
if (!disposedInd) {
79-
Collection<Binding> unsubscribe = null;
80-
if (bindings == null) {
125+
Collection<Binding> unsubscribe1 = null;
126+
Collection<CompositeBinding> unsubscribe2 = null;
127+
if (bindings == null && compBindings == null) {
81128
return;
82-
} else {
83-
unsubscribe = bindings;
129+
}
130+
if (bindings != null) {
131+
unsubscribe1 = bindings;
84132
bindings = null;
133+
unsubscribeFromAll(unsubscribe1);
134+
}
135+
if (compBindings != null) {
136+
unsubscribe2 = compBindings;
137+
compBindings = null;
138+
unsubscribeFromAllComposite(unsubscribe2);
85139
}
86-
unsubscribeFromAll(unsubscribe);
87140
}
88141
}
89142

@@ -95,15 +148,36 @@ public void clear() {
95148
*/
96149
public void dispose() {
97150
if (!disposedInd) {
98-
Collection<Binding> unsubscribe = null;
151+
Collection<Binding> unsubscribe1 = null;
152+
Collection<CompositeBinding> unsubscribe2 = null;
99153
disposedInd = true;
100-
unsubscribe = bindings;
154+
unsubscribe1 = bindings;
155+
unsubscribe2 = compBindings;
101156
bindings = null;
157+
compBindings = null;
102158
// we will only get here once
103-
unsubscribeFromAll(unsubscribe);
159+
unsubscribeFromAll(unsubscribe1);
160+
unsubscribeFromAllComposite(unsubscribe2);
104161
}
105162
}
106163

164+
private static void unsubscribeFromAllComposite(Collection<CompositeBinding> bindings) {
165+
if (bindings == null) {
166+
return;
167+
}
168+
List<Throwable> es = null;
169+
for (CompositeBinding b : bindings) {
170+
try {
171+
b.dispose();
172+
} catch (Throwable e) {
173+
if (es == null) {
174+
es = new ArrayList<>();
175+
}
176+
es.add(e);
177+
}
178+
}
179+
Exceptions.throwIfAny(es);
180+
}
107181
private static void unsubscribeFromAll(Collection<Binding> bindings) {
108182
if (bindings == null) {
109183
return;
@@ -129,10 +203,7 @@ private static void unsubscribeFromAll(Collection<Binding> bindings) {
129203
* @since 1.0.7
130204
*/
131205
public boolean hasSubscriptions() {
132-
if (!disposedInd) {
133-
return bindings != null && !bindings.isEmpty();
134-
}
135-
return false;
206+
return !disposedInd && ((bindings != null && !bindings.isEmpty()) || (compBindings != null && !compBindings.isEmpty()));
136207
}
137208
}
138209

0 commit comments

Comments
 (0)