Does `find` look up into the scope of the parent o...
# tornadofx
m
Does
find
look up into the scope of the parent objects? Is there scope inheritance?
It doesn't and it can't: scopes are component-based and components are not part of the visual hierarchy or any hierarchy so there is no parent of a component, even if some components have a visual root which is usually placed in the scene visual hierarchy.
❤️ 1
I could chain the scopes and implement inheritance with this code:
Copy code
package com.aeyeonmovement.tornadofx

import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.KClass

import tornadofx.Component
import tornadofx.Scope
import tornadofx.find

class InheritingScope(val parent: Scope? = null) : Scope() {
    companion object {
        fun from(vararg instances : Any) =
            InheritingScope().apply { put(*instances) }
    }

    private val map = mutableMapOf<KClass<*>, Any>()

    fun put(type: KClass<*>, instance: Any) {
        map[type] = instance
    }
    inline fun <reified T : Any> put(instance: T) =
        put(T::class, instance)

    fun put(vararg instances: Any) =
        instances.forEach { put(it::class, it) }

    @Suppress("UNCHECKED_CAST")
    fun tryGetLocally0(type: KClass<*>) : Any? =
        map[type]

    @Suppress("UNCHECKED_CAST")
    fun <T : Any> tryGetLocally(type: KClass<T>) : T? =
        tryGetLocally0(type) as? T

    fun tryGetInParent(type: KClass<*>) =
        if (parent is InheritingScope) {
            parent.tryGet(type)
        } else {
            null
        }

    @Suppress("UNCHECKED_CAST")
    fun <T: Component> tryGetComponentInParent(type: KClass<T>) : T? =
        if (parent is InheritingScope) {
            parent.tryGet(type) as? T
        } else if (parent != null) {
            find(type, parent)
        } else {
            null
        }

    fun tryGet(type: KClass<*>) : Any? =
        tryGetLocally(type) ?: tryGetInParent(type)

    inline fun <reified T: Component> tryGetComponent(type: KClass<T>) : T? =
        tryGetLocally(type) ?: tryGetComponentInParent(type)

    inline fun <reified T : Any> tryGet() = tryGet(T::class) as? T

    inline fun <reified T : Component> tryGetComponent() = tryGetComponent(T::class)

    fun subscope() =
        InheritingScope(this)

    fun subscope(vararg instances : Any) =
        subscope().apply { put(*instances) }
}

val Component.inheritingScope get() = scope as InheritingScope

inline fun <reified T : Any> inheritingInjection() =
    object : ReadOnlyProperty<Component, T> {
        override fun getValue(thisRef: Component, property: KProperty<*>): T =
            thisRef.inheritingScope.tryGet<T>() ?: throw Exception("Value not set for type ${T::class.java}")
    }

inline fun <reified T : Component> inheritingComponentInjection()=
    object : ReadOnlyProperty<Component, T> {
        override fun getValue(thisRef: Component, property: KProperty<*>): T =
            thisRef.inheritingScope.tryGetComponent<T>() ?: throw Exception("Value not set for type ${T::class.java}")
    }

fun Scope.inheritingScope(vararg instances: Any) =
    InheritingScope(this).apply { put(*instances) }