diff --git a/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/IVetoablePropertyChangeListener.java b/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/IVetoablePropertyChangeListener.java new file mode 100644 index 0000000..7a05031 --- /dev/null +++ b/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/IVetoablePropertyChangeListener.java @@ -0,0 +1,8 @@ +package com.openeggbert.jdotnet.JDotNet.Properties; + +@FunctionalInterface +public interface IVetoablePropertyChangeListener { + void vetoablePropertyChanged(T oldValue, T newValue) throws PropertyVetoException; + + +} diff --git a/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/ObservablePropertyImpl.java b/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/ObservablePropertyImpl.java index f0ac158..bd87496 100644 --- a/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/ObservablePropertyImpl.java +++ b/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/ObservablePropertyImpl.java @@ -18,6 +18,7 @@ public class ObservablePropertyImpl extends PropertyImpl implements IObser private List> observers = new ArrayList<>(); private final List> changeListeners = new ArrayList<>(); + private final List> vetoableChangeListeners = new ArrayList<>(); public ObservablePropertyImpl(IReadOnlyProperty readOnlyPropertyIn, IWriteOnlyProperty writeOnlyPropertyIn) { super(readOnlyPropertyIn, writeOnlyPropertyIn); @@ -35,6 +36,15 @@ public class ObservablePropertyImpl extends PropertyImpl 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 extends PropertyImpl 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 listener : vetoableChangeListeners) { + try { + listener.vetoablePropertyChanged(oldValue, newValue); + } catch (PropertyVetoException e) { + return true; + } + } + return false; + } public void addChangeListener(IPropertyChangeListener changeListener) { changeListeners.add(changeListener); } @@ -62,6 +92,13 @@ public class ObservablePropertyImpl extends PropertyImpl implements IObser public void removeChangeListener(IPropertyChangeListener changeListener) { changeListeners.remove(changeListener); } + public void addVetoableChangeListener(IVetoablePropertyChangeListener changeListener) { + vetoableChangeListeners.add(changeListener); + } + + public void removeVetoableChangeListener(IVetoablePropertyChangeListener vetoablePropertyChangeListener) { + vetoableChangeListeners.remove(vetoablePropertyChangeListener); + } public void addObserver(Consumer listener) { @@ -73,7 +110,7 @@ public class ObservablePropertyImpl extends PropertyImpl 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 extends PropertyImpl implements IObser public boolean hasChangeListeners() { return !changeListeners.isEmpty(); } + public boolean hasVetoableChangeListeners() { + return !vetoableChangeListeners.isEmpty(); + } } diff --git a/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/PropertyVetoException.java b/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/PropertyVetoException.java new file mode 100644 index 0000000..90440c9 --- /dev/null +++ b/src/main/java/com/openeggbert/jdotnet/JDotNet/Properties/PropertyVetoException.java @@ -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); + } +}