2017-05-26 22:33:56 +03:00
|
|
|
package inr.numass.control
|
|
|
|
|
2017-05-31 16:53:51 +03:00
|
|
|
import hep.dataforge.fx.fragments.FXFragment
|
|
|
|
import hep.dataforge.fx.fragments.FragmentWindow
|
2017-05-26 22:33:56 +03:00
|
|
|
import hep.dataforge.values.Value
|
|
|
|
import javafx.beans.value.ObservableValue
|
|
|
|
import javafx.event.EventTarget
|
2017-05-27 11:50:11 +03:00
|
|
|
import javafx.geometry.Orientation
|
2017-05-31 16:53:51 +03:00
|
|
|
import javafx.scene.control.ToggleButton
|
2017-05-26 22:33:56 +03:00
|
|
|
import javafx.scene.paint.Color
|
|
|
|
import javafx.scene.paint.Paint
|
|
|
|
import javafx.scene.shape.Circle
|
|
|
|
import javafx.scene.shape.StrokeType
|
|
|
|
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;
|
2017-05-27 11:50:11 +03:00
|
|
|
fill = transform(observable.value)
|
|
|
|
observable.addListener { _, _, value ->
|
|
|
|
fill = transform(value);
|
|
|
|
}
|
2017-05-26 22:33:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* bind indicator to the boolean value using default colours
|
|
|
|
*/
|
2017-05-28 16:47:11 +03:00
|
|
|
fun bind(booleanValue: ObservableValue<Boolean?>) {
|
2017-05-26 22:33:56 +03:00
|
|
|
bind(booleanValue) {
|
2017-05-28 16:47:11 +03:00
|
|
|
if (it == null) {
|
|
|
|
Color.GRAY
|
|
|
|
} else if (it) {
|
2017-05-26 22:33:56 +03:00
|
|
|
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)? = null) = opcr(this, Indicator(radius), op)
|
|
|
|
|
|
|
|
fun Indicator.bind(connection: DeviceViewConnection<*>, state: String, transform: ((Value) -> Paint)? = null) {
|
|
|
|
tooltip(state)
|
|
|
|
if (transform != null) {
|
|
|
|
bind(connection.getStateBinding(state), transform);
|
|
|
|
} else {
|
|
|
|
bind(connection.getStateBinding(state)) {
|
|
|
|
if (it.isNull) {
|
|
|
|
Color.GRAY
|
|
|
|
} else if (it.booleanValue()) {
|
|
|
|
Color.GREEN;
|
|
|
|
} else {
|
|
|
|
Color.RED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-27 11:50:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* State name + indicator
|
|
|
|
*/
|
|
|
|
fun EventTarget.deviceStateIndicator(connection: DeviceViewConnection<*>, state: String, transform: ((Value) -> Paint)? = null) {
|
|
|
|
if (connection.device.hasState(state)) {
|
|
|
|
text("${state.toUpperCase()}: ")
|
|
|
|
indicator {
|
|
|
|
bind(connection, state, transform);
|
|
|
|
}
|
|
|
|
separator(Orientation.VERTICAL)
|
|
|
|
}
|
2017-05-31 16:53:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fun ToggleButton.bindView(view: View) {
|
|
|
|
//TODO use view instead of FXFragment
|
|
|
|
FragmentWindow(FXFragment.buildFromNode(view.title) { view.root }).bindTo(this)
|
|
|
|
}
|
|
|
|
|