Added new namespace JDotNet.Properties II

This commit is contained in:
Robert Vokac 2025-01-19 19:47:28 +01:00
parent a96c90ec35
commit 1725ce1a9c
Signed by: robertvokac
GPG Key ID: FB9CE8E20AADA55F
3 changed files with 58 additions and 1 deletions

View File

@ -0,0 +1,8 @@
package com.openeggbert.jdotnet.JDotNet.Properties;
@FunctionalInterface
public interface IVetoablePropertyChangeListener<T> {
void vetoablePropertyChanged(T oldValue, T newValue) throws PropertyVetoException;
}

View File

@ -18,6 +18,7 @@ public class ObservablePropertyImpl<T> extends PropertyImpl<T> implements IObser
private List<Consumer<T>> observers = new ArrayList<>();
private final List<IPropertyChangeListener<T>> changeListeners = new ArrayList<>();
private final List<IVetoablePropertyChangeListener<T>> vetoableChangeListeners = new ArrayList<>();
public ObservablePropertyImpl(IReadOnlyProperty<T> readOnlyPropertyIn, IWriteOnlyProperty<T> writeOnlyPropertyIn) {
super(readOnlyPropertyIn, writeOnlyPropertyIn);
@ -35,6 +36,15 @@ public class ObservablePropertyImpl<T> extends PropertyImpl<T> implements IObser
@Override
public void set(T valueIn) {
T oldValue = this.get();
boolean vetoed = false;
if(!vetoableChangeListeners.isEmpty()) {
vetoed = notifyVetoableChangeListeners(oldValue, valueIn);
}
if(vetoed) {
//nothing to do
return;
}
super.set(valueIn);
if(!observers.isEmpty()) {
notifyListeners(valueIn);
@ -55,6 +65,26 @@ public class ObservablePropertyImpl<T> extends PropertyImpl<T> implements IObser
}
}
/**
* Notifies all registered vetoable change listeners of a potential change
* from the old value to the new value. If any listener vetoes the change by
* throwing a {@code PropertyVetoException}, the method stops further notifications
* and returns {@code true}.
*
* @param oldValue the previous value before the change
* @param newValue the proposed new value
* @return {@code true} if the change was vetoed by any listener; {@code false} otherwise
*/
private boolean notifyVetoableChangeListeners(T oldValue, T newValue) {
for (IVetoablePropertyChangeListener<T> listener : vetoableChangeListeners) {
try {
listener.vetoablePropertyChanged(oldValue, newValue);
} catch (PropertyVetoException e) {
return true;
}
}
return false;
}
public void addChangeListener(IPropertyChangeListener<T> changeListener) {
changeListeners.add(changeListener);
}
@ -62,6 +92,13 @@ public class ObservablePropertyImpl<T> extends PropertyImpl<T> implements IObser
public void removeChangeListener(IPropertyChangeListener<T> changeListener) {
changeListeners.remove(changeListener);
}
public void addVetoableChangeListener(IVetoablePropertyChangeListener<T> changeListener) {
vetoableChangeListeners.add(changeListener);
}
public void removeVetoableChangeListener(IVetoablePropertyChangeListener<T> vetoablePropertyChangeListener) {
vetoableChangeListeners.remove(vetoablePropertyChangeListener);
}
public void addObserver(Consumer<T> listener) {
@ -73,7 +110,7 @@ public class ObservablePropertyImpl<T> extends PropertyImpl<T> implements IObser
}
public boolean hasListeners() {
return !observers.isEmpty() || !changeListeners.isEmpty();
return !observers.isEmpty() || !changeListeners.isEmpty() || !vetoableChangeListeners.isEmpty();
}
public boolean hasObservers() {
return !observers.isEmpty();
@ -81,5 +118,8 @@ public class ObservablePropertyImpl<T> extends PropertyImpl<T> implements IObser
public boolean hasChangeListeners() {
return !changeListeners.isEmpty();
}
public boolean hasVetoableChangeListeners() {
return !vetoableChangeListeners.isEmpty();
}
}

View File

@ -0,0 +1,9 @@
package com.openeggbert.jdotnet.JDotNet.Properties;
import com.openeggbert.jdotnet.JDotNet.JDotNetException;
public class PropertyVetoException extends JDotNetException {
public PropertyVetoException(String message) {
super(message);
}
}