From 04607d4591dc423668f88f651ef6770e6ba69886 Mon Sep 17 00:00:00 2001 From: jules Ivanic Date: Thu, 5 Aug 2021 21:26:45 +0800 Subject: [PATCH] Backport https://github.com/edvin/tornadofx/pull/1319 to Tornado2 --- src/main/java/tornadofx/Component.kt | 82 +++++++++++++--------------- src/main/java/tornadofx/Lib.kt | 5 +- src/main/java/tornadofx/Workspace.kt | 2 +- 3 files changed, 41 insertions(+), 48 deletions(-) diff --git a/src/main/java/tornadofx/Component.kt b/src/main/java/tornadofx/Component.kt index 30e3ace..48b7863 100644 --- a/src/main/java/tornadofx/Component.kt +++ b/src/main/java/tornadofx/Component.kt @@ -542,61 +542,53 @@ abstract class UIComponent(viewTitle: String? = "", icon: Node? = null) : Compon properties["tornadofx.closeable"] = SimpleBooleanProperty(false) } - private val rootParentChangeListener: ChangeListener - get() { - val key = "tornadofx.rootParentChangeListener" - if (properties[key] == null) { - properties[key] = ChangeListener { _, oldParent, newParent -> - if (modalStage != null) return@ChangeListener - if (newParent == null && oldParent != null && isDocked) callOnUndock() - if (newParent != null && newParent != oldParent && !isDocked) { - callOnDock() - // Call `onTabSelected` if/when we are connected to a Tab and it's selected - // Note that this only works for builder constructed tabpanes - owningTab?.let { - it.selectedProperty()?.onChange { if (it) onTabSelected() } - if (it.isSelected) onTabSelected() - } - } + internal val rootParentChangeListener: ChangeListener by lazy { + ChangeListener { _, oldParent, newParent -> + if (modalStage != null) return@ChangeListener + if (newParent == null && oldParent != null && isDocked) callOnUndock() + if (newParent != null && newParent != oldParent && !isDocked) { + callOnDock() + // Call `onTabSelected` if/when we are connected to a Tab and it's selected + // Note that this only works for builder constructed tabpanes + owningTab?.let { + it.selectedProperty()?.onChange { if (it) onTabSelected() } + if (it.isSelected) onTabSelected() } } - return properties[key] as ChangeListener } + } - private val rootSceneChangeListener: ChangeListener - get() { - val key = "tornadofx.rootSceneChangeListener" - if (properties[key] == null) { - properties[key] = ChangeListener { _, oldParent, newParent -> - if (modalStage != null || root.parent != null) return@ChangeListener - if (newParent == null && oldParent != null && isDocked) callOnUndock() - if (newParent != null && newParent != oldParent && !isDocked) { - // Calls dock or undock when window opens or closes - newParent.windowProperty().onChangeOnce { - it?.showingProperty()?.addListener(rootSceneWindowShowingPropertyChangeListener) - } - callOnDock() - } + private val rootSceneChangeListener: ChangeListener by lazy { + ChangeListener { _, oldParent, newParent -> + val key = "tornadofx.rootSceneWindowPropertyChangeListener" + + if (modalStage != null || root.parent != null) return@ChangeListener + if (newParent == null && oldParent != null && isDocked) { + (properties[key] as? ChangeListener)?.run { + oldParent.windowProperty().removeListener(this) } + callOnUndock() + } + if (newParent != null && newParent != oldParent && !isDocked) { + // Calls dock or undock when window opens or closes + properties[key] = newParent.windowProperty().onChangeOnce { + it?.showingProperty()?.addListener(rootSceneWindowShowingPropertyChangeListener) + } + callOnDock() } - return properties[key] as ChangeListener } + } - private val rootSceneWindowShowingPropertyChangeListener: ChangeListener - get() { - val key = "tornadofx.rootSceneWindowShowingPropertyChangeListener" - if (properties[key] == null) { - properties[key] = ChangeListener { property, oldValue, newValue -> - if (!isInitialized) { - property.removeListener(rootSceneWindowShowingPropertyChangeListener) - return@ChangeListener - } - if (!newValue && isDocked) callOnUndock() - if (newValue && !isDocked) callOnDock() - } + private val rootSceneWindowShowingPropertyChangeListener: ChangeListener by lazy { + ChangeListener { property, oldValue, newValue -> + if (!isInitialized) { + property.removeListener(rootSceneWindowShowingPropertyChangeListener) + return@ChangeListener } - return properties[key] as ChangeListener + if (!newValue && isDocked) callOnUndock() + if (newValue && !isDocked) callOnDock() } + } internal fun init() { if (isInitialized) return diff --git a/src/main/java/tornadofx/Lib.kt b/src/main/java/tornadofx/Lib.kt index b9ca99b..7f7b252 100644 --- a/src/main/java/tornadofx/Lib.kt +++ b/src/main/java/tornadofx/Lib.kt @@ -233,7 +233,7 @@ inline fun ChangeListener(crossinline listener: (observable: ObservableValue * Listen for changes to this observable. Optionally only listen x times. * The lambda receives the changed value when the change occurs, which may be null, */ -fun ObservableValue.onChangeTimes(times: Int, op: (T?) -> Unit) { +fun ObservableValue.onChangeTimes(times: Int, op: (T?) -> Unit): ChangeListener { var counter = 0 val listener = object : ChangeListener { override fun changed(observable: ObservableValue?, oldValue: T, newValue: T) { @@ -244,9 +244,10 @@ fun ObservableValue.onChangeTimes(times: Int, op: (T?) -> Unit) { } } addListener(listener) + return listener } -fun ObservableValue.onChangeOnce(op: (T?) -> Unit) = onChangeTimes(1, op) +fun ObservableValue.onChangeOnce(op: (T?) -> Unit): ChangeListener = onChangeTimes(1, op) fun ObservableValue.onChange(op: (T?) -> Unit) = apply { addListener { _, _, newValue -> op(newValue) } } fun ObservableBooleanValue.onChange(op: (Boolean) -> Unit) = apply { addListener { _, _, new -> op(new ?: false) } } diff --git a/src/main/java/tornadofx/Workspace.kt b/src/main/java/tornadofx/Workspace.kt index 6a28155..75db2a0 100644 --- a/src/main/java/tornadofx/Workspace.kt +++ b/src/main/java/tornadofx/Workspace.kt @@ -312,7 +312,7 @@ open class Workspace(title: String = "Workspace", navigationMode: NavigationMode dockedComponent?.also { dockedComponentProperty.value = null if (oldMode == Stack && newMode == Tabs) { - val listener = it.properties["tornadofx.rootParentChangeListener"] as ChangeListener + val listener = it.rootParentChangeListener it.root.parentProperty().removeListener(listener) it.callOnUndock() dock(it, true)