diff --git a/KotlinCore/src/de/steamwar/kotlin/ui/Observer.kt b/KotlinCore/src/de/steamwar/kotlin/ui/Observer.kt index 8ecb1295..6990e14a 100644 --- a/KotlinCore/src/de/steamwar/kotlin/ui/Observer.kt +++ b/KotlinCore/src/de/steamwar/kotlin/ui/Observer.kt @@ -24,9 +24,9 @@ import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty abstract class Observable { - private val listeners = mutableSetOf() + internal val listeners = mutableSetOf() - fun removeListener(render: ObserverListener) { + open fun removeListener(render: ObserverListener) { listeners.remove(render) } @@ -46,15 +46,34 @@ abstract class Observable { override fun update() = callback(get()) } listeners.add(listener) + callback(get()) return { removeListener(listener) } } abstract fun get(): T - fun map(mapper: (T) -> R): ReadOnlyProperty = Delegate(mapper(get())) + fun map(mapper: (T) -> R): Observable = Delegate(mapper, this) - class Delegate(val value: T): ReadOnlyProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): T = value + class Delegate(val mapper: (T) -> R, val parent: Observable): Observable(), ReadOnlyProperty { + var value: R? = null + var unsubParent = parent.listen { + val old = value + value = mapper(it) + if (old != value) { + notifyListeners() + } + } + + override fun removeListener(render: ObserverListener) { + super.removeListener(render) + if (listeners.isEmpty()) { + unsubParent() + } + } + + override fun get(): R = value!! + + override fun getValue(thisRef: Any?, property: KProperty<*>): R = value!! } }