From 2cae5963414c6cc9e610c3a71aeda422c3ce052d Mon Sep 17 00:00:00 2001 From: jules Ivanic Date: Thu, 5 Aug 2021 23:41:01 +0800 Subject: [PATCH] Backport (as much as possible) https://github.com/edvin/tornadofx2/pull/40 --- src/main/java/tornadofx/Component.kt | 82 +++++++++++++--------------- src/main/java/tornadofx/Lib.kt | 5 +- 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/src/main/java/tornadofx/Component.kt b/src/main/java/tornadofx/Component.kt index bc19b1f2a..c2d437191 100644 --- a/src/main/java/tornadofx/Component.kt +++ b/src/main/java/tornadofx/Component.kt @@ -529,61 +529,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() - } - } + private 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, _, 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 b9ca99bb3..7f7b25280 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) } }