[Editor] Improve Parameter<T> binding to backing properties

This commit is contained in:
2021-02-20 11:36:04 +01:00
parent 53c24c9b99
commit 878d6de678
5 changed files with 51 additions and 42 deletions

View File

@@ -12,17 +12,31 @@ abstract class Parameter<T>(
private val autocommit: Boolean = false,
private val onCommit: (oldValue: T, newValue: T, submit: () -> Unit) -> Unit = { _, _, submit -> submit() }
) {
private var other: Property<T>? = null
val keyProperty = ReadOnlyStringWrapper(key)
val key by keyProperty
val editableProperty: BooleanProperty = SimpleBooleanProperty(editable)
var editable by editableProperty
var editable by editableProperty
val valueProperty: ObjectProperty<T> = SimpleObjectProperty(initialValue)
var value by valueProperty
fun commit() = onCommit(value, editorValueProperty.value, if (autocommit) NOOP else this::submit)
fun bindBidirectional(other: Property<T>) {
unbindBidirectional()
this.value = other.value
this.other = other.apply { bindBidirectional(valueProperty) }
}
fun unbindBidirectional() {
this.other?.unbindBidirectional(valueProperty)
this.other = null
}
private fun submit() {
value = editorValueProperty.value
}
@@ -30,7 +44,17 @@ abstract class Parameter<T>(
protected fun init() {
if (autocommit) {
editorValueProperty.bindBidirectional(valueProperty)
valueProperty.addListener { _, oldValue, newValue -> onCommit(oldValue, newValue, NOOP) }
valueProperty.addListener { _, oldValue, newValue ->
// Disclaimer:
// This ugly hack enforces the onCommit() listener to be fired, when
// `other` Property has been updated with current value.
// Without that hack, even if `other` is bidirectionally bound to `valueProperty`,
// it is updated right after the onCommit() listener, which is not very useful.
other?.value = newValue
onCommit(oldValue, newValue, NOOP)
}
} else {
editorValueProperty.value = value
valueProperty.addListener { _, _, v -> editorValueProperty.value = v }

View File

@@ -9,10 +9,6 @@ import org.springframework.stereotype.Component
@Component
class ColorLayerParametersBinder : LayerParametersBinder<ColorLayer> {
private var red: IntegerParameter? = null
private var green: IntegerParameter? = null
private var blue: IntegerParameter? = null
private var alpha: IntegerParameter? = null
override fun bind(
layer: ColorLayer,
@@ -21,24 +17,15 @@ class ColorLayerParametersBinder : LayerParametersBinder<ColorLayer> {
onCommit: () -> Unit
) {
val red = IntegerParameter("red", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() }
.apply { valueProperty.bindBidirectional(layer.redProperty) }
val green = IntegerParameter("green", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() }
.apply { valueProperty.bindBidirectional(layer.greenProperty) }
val blue = IntegerParameter("blue", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() }
.apply { valueProperty.bindBidirectional(layer.blueProperty) }
val alpha = IntegerParameter("alpha", 100, 0, 100, autocommit = true) { _, _, _ -> onCommit() }
.apply { valueProperty.bindBidirectional(layer.alphaProperty) }
red.bindBidirectional(layer.redProperty)
green.bindBidirectional(layer.greenProperty)
blue.bindBidirectional(layer.blueProperty)
alpha.bindBidirectional(layer.alphaProperty)
parameters.addAll(red, green, blue, alpha)
}
override fun unbind(layer: ColorLayer, parameters: ObservableList<Parameter<*>>) {
red?.valueProperty?.unbindBidirectional(layer.redProperty)
green?.valueProperty?.unbindBidirectional(layer.greenProperty)
blue?.valueProperty?.unbindBidirectional(layer.blueProperty)
alpha?.valueProperty?.unbindBidirectional(layer.alphaProperty)
}
}

View File

@@ -3,7 +3,6 @@ package com.bartlomiejpluta.base.editor.map.parameter.layer
import com.bartlomiejpluta.base.editor.common.parameter.model.GraphicAssetParameter
import com.bartlomiejpluta.base.editor.common.parameter.model.IntegerParameter
import com.bartlomiejpluta.base.editor.common.parameter.model.Parameter
import com.bartlomiejpluta.base.editor.image.asset.ImageAsset
import com.bartlomiejpluta.base.editor.map.model.layer.ImageLayer
import com.bartlomiejpluta.base.editor.project.model.Project
import javafx.collections.ObservableList
@@ -11,8 +10,6 @@ import org.springframework.stereotype.Component
@Component
class ImageLayerParametersBinder : LayerParametersBinder<ImageLayer> {
private var image: GraphicAssetParameter<ImageAsset>? = null
private var opacity: IntegerParameter? = null
override fun bind(
layer: ImageLayer,
@@ -20,20 +17,18 @@ class ImageLayerParametersBinder : LayerParametersBinder<ImageLayer> {
project: Project,
onCommit: () -> Unit
) {
image = GraphicAssetParameter("image", layer.imageAsset, true, project.images) { _, _, submit ->
val image = GraphicAssetParameter("image", layer.imageAsset, true, project.images) { _, _, submit ->
onCommit()
submit()
}.apply { valueProperty.bindBidirectional(layer.imageAssetProperty) }
}
opacity = IntegerParameter("opacity", 100, 0, 100, autocommit = true) { _, _, _ ->
val opacity = IntegerParameter("opacity", 100, 0, 100, autocommit = true) { _, _, _ ->
onCommit()
}.apply { valueProperty.bindBidirectional(layer.opacityProperty) }
}
image.bindBidirectional(layer.imageAssetProperty)
opacity.bindBidirectional(layer.opacityProperty)
parameters.addAll(image, opacity)
}
override fun unbind(layer: ImageLayer, parameters: ObservableList<Parameter<*>>) {
image?.valueProperty?.unbindBidirectional(layer.imageAssetProperty)
opacity?.valueProperty?.unbindBidirectional(layer.opacityProperty)
}
}

View File

@@ -7,5 +7,4 @@ import javafx.collections.ObservableList
interface LayerParametersBinder<T : Layer> {
fun bind(layer: T, parameters: ObservableList<Parameter<*>>, project: Project, onCommit: () -> Unit)
fun unbind(layer: T, parameters: ObservableList<Parameter<*>>)
}

View File

@@ -24,17 +24,21 @@ class MapLayerParameters : View() {
private val parameters = observableListOf<Parameter<*>>()
init {
editorStateVM.selectedLayerProperty.addListener { _, previousLayer, layer ->
when (previousLayer) {
is ColorLayer -> colorLayerParametersBinder.unbind(previousLayer, parameters)
is ImageLayer -> imageLayerParametersBinder.unbind(previousLayer, parameters)
}
editorStateVM.selectedLayerProperty.addListener { _, _, layer ->
parameters.forEach(Parameter<*>::unbindBidirectional)
parameters.clear()
when (layer) {
is ColorLayer -> colorLayerParametersBinder.bind(layer, parameters, projectContext.project!!) { fire(RedrawMapRequestEvent) }
is ImageLayer -> imageLayerParametersBinder.bind(layer, parameters, projectContext.project!!) { fire(RedrawMapRequestEvent) }
is ColorLayer -> colorLayerParametersBinder.bind(layer, parameters, projectContext.project!!) {
fire(
RedrawMapRequestEvent
)
}
is ImageLayer -> imageLayerParametersBinder.bind(layer, parameters, projectContext.project!!) {
fire(
RedrawMapRequestEvent
)
}
}
}
}