[Editor] Improve Parameter<T> binding to backing properties
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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<*>>)
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user