Package: PropertyAdapter
PropertyAdapter
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
PropertyAdapter(Executor, BoundProperty) |
|
|
|
|
|
||||||||||||||||||||
addListener(ChangeListener) |
|
|
|
|
|
||||||||||||||||||||
addListener(InvalidationListener) |
|
|
|
|
|
||||||||||||||||||||
bind(ObservableValue) |
|
|
|
|
|
||||||||||||||||||||
bindBidirectional(Property) |
|
|
|
|
|
||||||||||||||||||||
getBean() |
|
|
|
|
|
||||||||||||||||||||
getName() |
|
|
|
|
|
||||||||||||||||||||
getValue() |
|
|
|
|
|
||||||||||||||||||||
isBound() |
|
|
|
|
|
||||||||||||||||||||
lambda$new$0(InvalidationListener) |
|
|
|
|
|
||||||||||||||||||||
lambda$new$1(PropertyChangeEvent, ChangeListener) |
|
|
|
|
|
||||||||||||||||||||
lambda$new$2(PropertyChangeEvent) |
|
|
|
|
|
||||||||||||||||||||
lambda$new$3(PropertyChangeEvent) |
|
|
|
|
|
||||||||||||||||||||
lambda$setValue$4(Object) |
|
|
|
|
|
||||||||||||||||||||
removeListener(ChangeListener) |
|
|
|
|
|
||||||||||||||||||||
removeListener(InvalidationListener) |
|
|
|
|
|
||||||||||||||||||||
setValue(Object) |
|
|
|
|
|
||||||||||||||||||||
static {...} |
|
|
|
|
|
||||||||||||||||||||
unbind() |
|
|
|
|
|
||||||||||||||||||||
unbindBidirectional(Property) |
|
|
|
|
|
Coverage
1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * SteelBlue: DCI User Interfaces
5: * http://tidalwave.it/projects/steelblue
6: *
7: * Copyright (C) 2015 - 2024 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/steelblue-src
22: * git clone https://github.com/tidalwave-it/steelblue-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.role.ui.javafx.impl.common;
27:
28: import javax.annotation.Nonnull;
29: import java.beans.PropertyChangeListener;
30: import java.util.ArrayList;
31: import java.util.List;
32: import java.util.Objects;
33: import java.util.concurrent.Executor;
34: import javafx.beans.InvalidationListener;
35: import javafx.beans.property.Property;
36: import javafx.beans.value.ChangeListener;
37: import javafx.beans.value.ObservableValue;
38: import javafx.application.Platform;
39: import it.tidalwave.role.ui.BoundProperty;
40: import lombok.extern.slf4j.Slf4j;
41:
42: /***************************************************************************************************************************************************************
43: *
44: * Adapts a {@link BoundProperty} to a JavaFX {@link Property}. It also takes care of threaring issues, making sure that
45: * the JavaFX {@code Property} is updated in the JavaFX UI thread. Conversely, updates on the JavaFX
46: * {@code BoundProperty} are executed in a separated thread provided by an {@link Executor}.
47: *
48: * TODO: javafx.beans.binding.BooleanExpression.booleanExpression(source)? Does it do threading?
49: *
50: * @author Fabrizio Giudici
51: *
52: **************************************************************************************************************************************************************/
53: @Slf4j
54: public class PropertyAdapter<T> implements Property<T>
55: {
56: @Nonnull
57: private final Executor executor;
58:
59: @Nonnull
60: private final BoundProperty<T> delegate;
61:
62: // FIXME: WEAK LISTENER!!
63: private final List<ChangeListener<? super T>> changeListeners = new ArrayList<>();
64:
65: // FIXME: WEAK LISTENER!!
66: private final List<InvalidationListener> invalidationListeners = new ArrayList<>();
67:
68: private T boundValue;
69:
70: private final PropertyChangeListener propertyChangeListener = (event) ->
71: {
72: log.trace("propertyChange({}) - bound value: {}", event, boundValue);
73:
74:• if (!Objects.equals(boundValue, event.getNewValue()))
75: {
76: boundValue = (T)event.getNewValue();
77: Platform.runLater(() ->
78: {
79: new ArrayList<>(invalidationListeners)
80: .forEach(listener -> listener.invalidated(this));
81: new ArrayList<>(changeListeners)
82: .forEach(listener -> listener.changed(this,
83: (T)event.getOldValue(), (T)event.getNewValue()));
84: });
85: }
86: };
87:
88: public PropertyAdapter (@Nonnull final Executor executor, @Nonnull final BoundProperty<T> delegate)
89: {
90: this.executor = executor;
91: this.delegate = delegate;
92: this.boundValue = delegate.get();
93: delegate.addPropertyChangeListener(propertyChangeListener);
94: }
95:
96: @Override
97: public T getValue()
98: {
99: return delegate.get();
100: }
101:
102: @Override
103: public void setValue (final T value)
104: {
105: log.debug("setValue({})", value);
106: boundValue = value;
107:
108:• if (!Objects.equals(value, delegate.get()))
109: {
110: executor.execute(() -> delegate.set(value));
111: }
112: }
113:
114: @Override
115: public void addListener (@Nonnull final ChangeListener<? super T> listener)
116: {
117: changeListeners.add(listener);
118: }
119:
120: @Override
121: public void removeListener (@Nonnull final ChangeListener<? super T> listener)
122: {
123: changeListeners.remove(listener);
124: }
125:
126: @Override
127: public void addListener (@Nonnull final InvalidationListener listener)
128: {
129: invalidationListeners.add(listener);
130: }
131:
132: @Override
133: public void removeListener (@Nonnull final InvalidationListener listener)
134: {
135: invalidationListeners.remove(listener);
136: }
137:
138: @Override
139: public void bind (final ObservableValue<? extends T> observable)
140: {
141: log.warn("bind({})", observable);
142: throw new UnsupportedOperationException("Not supported yet.");
143: }
144:
145: @Override
146: public void unbind()
147: {
148: log.warn("unbind()");
149: throw new UnsupportedOperationException("Not supported yet.");
150: }
151:
152: @Override
153: public boolean isBound()
154: {
155: log.warn("isBound()");
156: throw new UnsupportedOperationException("Not supported yet.");
157: }
158:
159: @Override
160: public void bindBidirectional (final Property<T> other)
161: {
162: log.warn("bindBidirectional({})", other);
163: throw new UnsupportedOperationException("Not supported yet.");
164: }
165:
166: @Override
167: public void unbindBidirectional (final Property<T> other)
168: {
169: log.warn("unbindBidirectional({})", other);
170: throw new UnsupportedOperationException("Not supported yet.");
171: }
172:
173: @Override
174: public Object getBean()
175: {
176: log.warn("getBean()");
177: throw new UnsupportedOperationException("Not supported yet.");
178: }
179:
180: @Override
181: public String getName()
182: {
183: log.warn("getName()");
184: throw new UnsupportedOperationException("Not supported yet.");
185: }
186: }