153 lines
4.3 KiB
Kotlin
153 lines
4.3 KiB
Kotlin
package inr.numass.control
|
|
|
|
import hep.dataforge.configure
|
|
import hep.dataforge.fx.plots.PlotContainer
|
|
import hep.dataforge.meta.KMetaBuilder
|
|
import hep.dataforge.plots.PlotFrame
|
|
import hep.dataforge.plots.Plottable
|
|
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
|
import hep.dataforge.values.Value
|
|
import javafx.beans.value.ObservableValue
|
|
import javafx.event.EventTarget
|
|
import javafx.geometry.Orientation
|
|
import javafx.scene.Node
|
|
import javafx.scene.layout.BorderPane
|
|
import javafx.scene.paint.Color
|
|
import javafx.scene.paint.Paint
|
|
import javafx.scene.shape.Circle
|
|
import javafx.scene.shape.StrokeType
|
|
import org.controlsfx.control.ToggleSwitch
|
|
import tornadofx.*
|
|
|
|
|
|
/**
|
|
* A pin like indicator fx node
|
|
*/
|
|
class Indicator(radius: Double = 10.0) : Circle(radius, Color.GRAY) {
|
|
private var binding: ObservableValue<*>? = null;
|
|
|
|
init {
|
|
stroke = Color.BLACK;
|
|
strokeType = StrokeType.INSIDE;
|
|
}
|
|
|
|
/**
|
|
* bind this indicator color to given observable
|
|
*/
|
|
fun <T> bind(observable: ObservableValue<T>, transform: (T) -> Paint) {
|
|
if (binding != null) {
|
|
throw RuntimeException("Indicator already bound");
|
|
} else {
|
|
binding = observable;
|
|
fill = transform(observable.value)
|
|
observable.addListener { _, _, value ->
|
|
fill = transform(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* bind indicator to the boolean value using default colours
|
|
*/
|
|
fun bind(booleanValue: ObservableValue<Boolean?>) {
|
|
bind(booleanValue) {
|
|
when {
|
|
it == null -> Color.GRAY
|
|
it -> Color.GREEN
|
|
else -> Color.RED
|
|
}
|
|
}
|
|
}
|
|
|
|
fun unbind() {
|
|
this.binding = null;
|
|
neutralize();
|
|
}
|
|
|
|
/**
|
|
* return indicator to the neutral state but do not unbind
|
|
*/
|
|
fun neutralize() {
|
|
fill = Color.GRAY;
|
|
}
|
|
}
|
|
|
|
fun EventTarget.indicator(radius: Double = 10.0, op: (Indicator.() -> Unit) = {}): Indicator = opcr(this, Indicator(radius), op)
|
|
|
|
fun Indicator.bind(connection: DeviceDisplayFX<*>, state: String, transform: ((Value) -> Paint)? = null) {
|
|
tooltip(state)
|
|
if (transform != null) {
|
|
bind(connection.valueStateProperty(state), transform);
|
|
} else {
|
|
bind(connection.valueStateProperty(state)) {
|
|
when {
|
|
it.isNull -> Color.GRAY
|
|
it.boolean -> Color.GREEN
|
|
else -> Color.RED
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* State name + indicator
|
|
*/
|
|
fun EventTarget.deviceStateIndicator(connection: DeviceDisplayFX<*>, state: String, showName: Boolean = true, transform: ((Value) -> Paint)? = null) {
|
|
if (connection.device.stateNames.contains(state)) {
|
|
if (showName) {
|
|
text("${state.uppercase()}: ")
|
|
}
|
|
indicator {
|
|
bind(connection, state, transform);
|
|
}
|
|
separator(Orientation.VERTICAL)
|
|
} else {
|
|
throw RuntimeException("Device does not support state $state");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A togglebutton + indicator for boolean state
|
|
*/
|
|
fun Node.deviceStateToggle(connection: DeviceDisplayFX<*>, state: String, title: String = state) {
|
|
if (connection.device.stateNames.contains(state)) {
|
|
togglebutton(title) {
|
|
selectedProperty().addListener { _, oldValue, newValue ->
|
|
if (oldValue != newValue) {
|
|
connection.device.states[state] = newValue
|
|
}
|
|
}
|
|
connection.valueStateProperty(state).apply {
|
|
isSelected = value?.boolean ?: false
|
|
onChange {
|
|
runLater {
|
|
isSelected = it?.boolean ?: false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
deviceStateIndicator(connection, state, false)
|
|
} else {
|
|
throw RuntimeException("Device does not support state $state");
|
|
}
|
|
}
|
|
|
|
fun EventTarget.switch(text: String = "", op: (ToggleSwitch.() -> Unit) = {}): ToggleSwitch {
|
|
val switch = ToggleSwitch(text)
|
|
return opcr(this, switch, op)
|
|
}
|
|
|
|
/**
|
|
* Add frame
|
|
*/
|
|
fun BorderPane.plot(plottable: Plottable, metaTransform: (KMetaBuilder.() -> Unit) = {}): PlotFrame {
|
|
val frame = JFreeChartFrame().configure(metaTransform)
|
|
frame.add(plottable)
|
|
center = PlotContainer(frame).root
|
|
return frame;
|
|
}
|
|
|
|
//val ValueState.property: ObjectProperty<Value>
|
|
// get() {
|
|
// ret
|
|
// } |