diff --git a/libraries/stdlib/samples/test/samples/properties/delegates.kt b/libraries/stdlib/samples/test/samples/properties/delegates.kt index 44433be6a5a1f..17dbc1e3a7550 100644 --- a/libraries/stdlib/samples/test/samples/properties/delegates.kt +++ b/libraries/stdlib/samples/test/samples/properties/delegates.kt @@ -76,4 +76,23 @@ class Delegates { assertPrints(max, "10") assertTrue(observed) } + + @Sample + fun distinctObservableDelegate() { + var observed = false + var max: Int by Delegates.distinctObservable(0) { property, oldValue, newValue -> + observed = true + } + + assertPrints(max, "0") + assertFalse(observed) + + max = 0 + assertPrints(max, "0") + assertFalse(observed) + + max = 10 + assertPrints(max, "10") + assertTrue(observed) + } } \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/properties/Delegates.kt b/libraries/stdlib/src/kotlin/properties/Delegates.kt index e38e6cb5073cd..806a5f44baa9c 100644 --- a/libraries/stdlib/src/kotlin/properties/Delegates.kt +++ b/libraries/stdlib/src/kotlin/properties/Delegates.kt @@ -34,6 +34,23 @@ public object Delegates { override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue) } + /** + * Returns a property delegate for a read/write property that calls a specified callback function when changed, + * but only if the new value is different from the old value. + * @param initialValue the initial value of the property. + * @param onChange the callback which is called after the change of the property is made. The value of the property + * has already been changed when this callback is invoked. + * + * @sample samples.properties.Delegates.distinctObservableDelegate + */ + public inline fun distinctObservable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit): + ReadWriteProperty = + object : ObservableProperty(initialValue) { + override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T) = oldValue != newValue + + override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue) + } + /** * Returns a property delegate for a read/write property that calls a specified callback function when changed, * allowing the callback to veto the modification.