All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dankito.utils.javafx.util.LazyLoadingObservableList.kt Maven / Gradle / Ivy

There is a newer version: 1.0.9
Show newest version
package net.dankito.utils.javafx.util

import javafx.collections.ObservableList
import javafx.collections.ObservableListBase
import org.slf4j.LoggerFactory
import java.util.*


class LazyLoadingObservableList : ObservableListBase, ObservableList {

    companion object {
        private val log = LoggerFactory.getLogger(LazyLoadingObservableList::class.java)
    }


    private var underlyingCollection: MutableCollection? = null


    constructor() {
        setUnderlyingCollection(ArrayList())
    }

    constructor(collection: MutableCollection) {
        setUnderlyingCollection(collection)
    }


    override val size: Int
        get() {
            underlyingCollection?.let { underlyingCollection ->
                return underlyingCollection.size
            }

            return 0
        }

    override fun iterator(): MutableIterator {
        return underlyingCollection!!.iterator()
    }

    override fun listIterator(index: Int): MutableListIterator {
        if(underlyingCollection is List<*>) {
            return (underlyingCollection as List<*>).listIterator(index) as MutableListIterator
        }

        return super.listIterator(index)
    }

    override fun get(index: Int): T? {
        return getItemFromCollection(index, underlyingCollection)
    }

    private fun getItemFromCollection(index: Int, collection: Collection?): T? {
        if (collection is List<*>) {
            return (collection as List)[index]
        }

        collection?.let { collection ->
            var i = 0
            val iterator = collection.iterator()

            while(iterator.hasNext()) {
                if (i == index) {
                    return iterator.next()
                }

                iterator.next()
                i++
            }
        }

        return null
    }


    /**
     * Note that even thought Java method declaration says "Collection" you have to provide a MutableCollection, otherwise method will fail
     */
    override fun setAll(collection: Collection?): Boolean {
        if(collection is MutableCollection) {
            setUnderlyingCollection(collection)
            return true
        }
        else { // should actually never be the case
            return false
        }
    }

    fun setUnderlyingCollection(underlyingCollection: MutableCollection?) {
        // simply make sure that collection is set (or better: endChange() ) is called on UI Thread (otherwise a IllegalStateException would be thrown)
        FXUtils.runOnUiThread { setUnderlyingCollectionOnUiThread(underlyingCollection) }
    }

    private fun setUnderlyingCollectionOnUiThread(underlyingCollection: MutableCollection?) {
        beginChange()
        // this only makes removed items getting loaded from Database. And as ObservableList is also working without why implementing it?
        //    if(this.underlyingCollection instanceof List)
        //      nextRemove(0, (List)this.underlyingCollection);
        //    else if(this.underlyingCollection != null) { // TODO: test
        //      int i = 0;
        //      for(T item : this.underlyingCollection) {
        //        nextRemove(i, item);
        //        i++;
        //      }
        //    }

        this.underlyingCollection = underlyingCollection

        try {
            if (size > 0) {
                nextAdd(0, size)
            } else {
                nextAdd(0, 0)
            }

            endChange()
        } catch (ex: Exception) {
            log.error("Could not set underlying collection", ex)
        }

    }

    override fun clear() {
        setUnderlyingCollection(ArrayList())
    }

    override fun add(index: Int, element: T) {
        beginChange()

        if (underlyingCollection is MutableList<*>) {
            (underlyingCollection as MutableList).add(index, element)
        }
        else {
            underlyingCollection?.let { it.add(element) }
        }

        nextAdd(index - 1, index)
        endChange()
    }

    override fun remove(element: T): Boolean {
        var result = false
        beginChange()

        try {
            underlyingCollection?.let { underlyingCollection ->
                result = underlyingCollection.remove(element as T)
            }

            //      nextRemove(index, element);
        } catch (ex: Exception) {

        } finally {
            endChange()
        }

        return result
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy