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

com.github.weisj.swingdsl.components.BreadcrumbModel.kt Maven / Gradle / Ivy

/*
 * MIT License
 *
 * Copyright (c) 2021 Jannis Weis
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
package com.github.weisj.swingdsl.components

import java.util.*
import javax.swing.JTree
import javax.swing.event.TreeModelEvent
import javax.swing.event.TreeModelListener
import javax.swing.event.TreeSelectionEvent
import javax.swing.event.TreeSelectionListener
import javax.swing.tree.TreeModel
import javax.swing.tree.TreeNode
import javax.swing.tree.TreeSelectionModel

interface BreadcrumbModel {
    val breadcrumbs: List

    fun getChildren(node: NodeType): Sequence
    fun getChildCount(node: NodeType): Int

    fun getValue(node: NodeType): T

    fun addBreadCrumbModelListener(listener: BreadCrumbModelListener)
    fun removeBreadCrumbModelListener(listener: BreadCrumbModelListener)
}

interface BreadCrumbModelListener {
    fun nodesChanged()
}

class ListBreadcrumbModel : BreadcrumbModel {
    private val listeners = mutableListOf()
    var nodes: List = Collections.emptyList()
        set(value) {
            field = value
            listeners.forEach { it.nodesChanged() }
        }

    override val breadcrumbs: List
        get() = nodes.indices.toList()

    override fun getChildCount(node: Int): Int {
        return if (node != nodes.size - 1) 1 else 0
    }

    override fun getChildren(node: Int): Sequence {
        return if (node != nodes.size - 1) sequenceOf(node + 1) else emptySequence()
    }

    override fun getValue(node: Int): T = nodes[node]

    override fun addBreadCrumbModelListener(listener: BreadCrumbModelListener) {
        listeners.add(listener)
    }

    override fun removeBreadCrumbModelListener(listener: BreadCrumbModelListener) {
        listeners.remove(listener)
    }
}

@Suppress("UNCHECKED_CAST")
class TreeBreadCrumbModel(
    private val treeModel: TreeModel,
    private val treeSelectionModel: TreeSelectionModel,
    private val showRootNode: Boolean = true,
    private val nodeAccessor: (NodeType) -> T
) : BreadcrumbModel {

    constructor(tree: JTree, nodeAccessor: (NodeType) -> T) :
        this(tree.model, tree.selectionModel, tree.isRootVisible, nodeAccessor)

    override val breadcrumbs: List
        get() {
            val crumbs = treeSelectionModel.leadSelectionPath?.run {
                path.asSequence().toList() as List
            } ?: emptyList()
            return if (!showRootNode) crumbs.drop(1) else crumbs
        }

    override fun getChildren(node: NodeType): Sequence {
        return node.children().asSequence() as Sequence
    }

    override fun getChildCount(node: NodeType): Int {
        return treeModel.getChildCount(node)
    }

    override fun getValue(node: NodeType): T {
        return nodeAccessor(node)
    }

    override fun addBreadCrumbModelListener(listener: BreadCrumbModelListener) {
        treeSelectionModel.addTreeSelectionListener(TreeSelectionListenerWrapper(listener))
        treeModel.addTreeModelListener(TreeModelListenerWrapper(listener))
    }

    override fun removeBreadCrumbModelListener(listener: BreadCrumbModelListener) {
        treeSelectionModel.removeTreeSelectionListener(TreeSelectionListenerWrapper(listener))
        treeModel.removeTreeModelListener(TreeModelListenerWrapper(listener))
    }

    private data class TreeSelectionListenerWrapper(private val listener: BreadCrumbModelListener) :
        TreeSelectionListener {
        override fun valueChanged(e: TreeSelectionEvent?) {
            listener.nodesChanged()
        }
    }

    private data class TreeModelListenerWrapper(private val listener: BreadCrumbModelListener) :
        TreeModelListener {
        override fun treeNodesChanged(e: TreeModelEvent?) = listener.nodesChanged()
        override fun treeNodesInserted(e: TreeModelEvent?) = listener.nodesChanged()
        override fun treeNodesRemoved(e: TreeModelEvent?) = listener.nodesChanged()
        override fun treeStructureChanged(e: TreeModelEvent?) = listener.nodesChanged()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy