Skip to contentMethod: set(Object)
1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * SteelBlue: DCI User Interfaces
5: * http://tidalwave.it/projects/steelblue
6: *
7: * Copyright (C) 2015 - 2025 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.ui.core;
27:
28: import jakarta.annotation.Nonnull;
29: import java.beans.PropertyChangeSupport;
30: import it.tidalwave.ui.core.role.Changeable;
31: import it.tidalwave.ui.core.role.impl.MutableListenerSupport;
32: import lombok.AllArgsConstructor;
33: import lombok.EqualsAndHashCode;
34: import lombok.NoArgsConstructor;
35: import lombok.ToString;
36: import lombok.experimental.Delegate;
37:
38: /***************************************************************************************************************************************************************
39: *
40: * @since 2.0-ALPHA-1
41: * @author Fabrizio Giudici
42: *
43: **************************************************************************************************************************************************************/
44: // FIXME: weak listeners
45: @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode(exclude={"pcs", "mls"}) @ToString(exclude={"pcs", "mls"}) @SuppressWarnings("this-escape")
46: public class BoundProperty<T> implements ChangingSource<T>, Changeable<T>
47: {
48: @Delegate
49: private final transient PropertyChangeSupport pcs = new PropertyChangeSupport(this);
50:
51: @Delegate
52: private final transient MutableListenerSupport mls = new MutableListenerSupport(pcs);
53:
54: public static final String PROP_VALUE = "value";
55:
56: private T value;
57:
58: /***********************************************************************************************************************************************************
59: * Creates a new {@code BoundProperty} with the given initial value.
60: *
61: * @param <T> the type of the property
62: * @param value the initial value
63: * @return the property
64: * @since 3.2-ALPHA-2
65: **********************************************************************************************************************************************************/
66: @Nonnull
67: public static <T> BoundProperty<T> of (@Nonnull final T value)
68: {
69: return new BoundProperty<>(value);
70: }
71:
72: /***********************************************************************************************************************************************************
73: * {@inheritDoc}
74: * This method fires a property change event associated to {@link #PROP_VALUE}.
75: **********************************************************************************************************************************************************/
76: @Override
77: public void set (final T value)
78: {
79: final var oldValue = this.value;
80: this.value = value;
81: pcs.firePropertyChange(PROP_VALUE, oldValue, value);
82: }
83:
84: /***********************************************************************************************************************************************************
85: * {@inheritDoc}
86: **********************************************************************************************************************************************************/
87: @Override
88: public T get()
89: {
90: return value;
91: }
92:
93: /***********************************************************************************************************************************************************
94: * Binds this property to a {@link ChangingSource}. Every change in the value of the source will be synchronized to
95: * the value of this property. If the source is a {@link Changeable} binding will be bidirectional, that is the
96: * object will be set to the current value of this property and will be kept in sync.
97: *
98: * @param source the source
99: **********************************************************************************************************************************************************/
100: public void bind (@Nonnull final ChangingSource<T> source)
101: {
102: source.addPropertyChangeListener(event -> set((T)event.getNewValue()));
103:
104: if (source instanceof Changeable)
105: {
106: final var changeable = (Changeable<T>)source;
107: changeable.set(value);
108: this.addPropertyChangeListener(event -> changeable.set((T)event.getNewValue()));
109: }
110: }
111:
112: /***********************************************************************************************************************************************************
113: * {@inheritDoc}
114: **********************************************************************************************************************************************************/
115: @Override
116: public void unbindAll()
117: {
118: for (final var listener : pcs.getPropertyChangeListeners().clone())
119: {
120: pcs.removePropertyChangeListener(listener);
121: }
122:
123: mls.removeAllListeners();
124: }
125: }