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 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
45
46
47
48
49
50
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
63 private final List<ChangeListener<? super T>> changeListeners = new ArrayList<>();
64
65
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 }