Numass control room global update

This commit is contained in:
Alexander Nozik 2017-05-27 11:50:11 +03:00
parent c7e460d43d
commit ad958f8f9c
7 changed files with 107 additions and 69 deletions

View File

@ -13,14 +13,11 @@ import javafx.beans.property.SimpleObjectProperty
import javafx.collections.FXCollections import javafx.collections.FXCollections
import javafx.collections.ObservableList import javafx.collections.ObservableList
import tornadofx.* import tornadofx.*
import java.util.*
/** /**
* Created by darksnake on 12-May-17. * Created by darksnake on 12-May-17.
*/ */
class BoardController() : Controller() { class BoardController() : Controller() {
private val serviceLoader = ServiceLoader.load(DeviceViewFactory::class.java);
val devices: ObservableList<DeviceViewConnection<*>> = FXCollections.observableArrayList<DeviceViewConnection<*>>(); val devices: ObservableList<DeviceViewConnection<*>> = FXCollections.observableArrayList<DeviceViewConnection<*>>();
val storageProperty = SimpleObjectProperty<Storage>() val storageProperty = SimpleObjectProperty<Storage>()
@ -41,7 +38,7 @@ class BoardController() : Controller() {
} }
} }
if(meta.hasMeta("storage")){ if (meta.hasMeta("storage")) {
storage = buildStorage(context, meta); storage = buildStorage(context, meta);
val storageConnection = StorageConnection(storage); val storageConnection = StorageConnection(storage);
devices.forEach { devices.forEach {
@ -61,12 +58,13 @@ class BoardController() : Controller() {
private fun buildDeviceView(context: Context, deviceMeta: Meta): DeviceViewConnection<*> { private fun buildDeviceView(context: Context, deviceMeta: Meta): DeviceViewConnection<*> {
context.logger.info("Building device with meta: {}", deviceMeta) context.logger.info("Building device with meta: {}", deviceMeta)
val factory = serviceLoader.find { val factory = context.serviceStream(DeviceViewFactory::class.java)
it.type == deviceMeta.getString("type") .filter { it.type == deviceMeta.getString("type") }
}; .findFirst();
if (factory != null) {
val device = factory.build(context, deviceMeta); if (factory.isPresent) {
val view = factory.buildView(device); val device = factory.get().build(context, deviceMeta);
val view = factory.get().buildView(device);
device.connect(view, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE) device.connect(view, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE)
device.init(); device.init();
return view; return view;
@ -76,7 +74,10 @@ class BoardController() : Controller() {
} }
private fun buildStorage(context: Context, meta: Meta): Storage { private fun buildStorage(context: Context, meta: Meta): Storage {
val storageMeta = meta.getMeta("storage"); val storageMeta = meta.getMeta("storage").builder
.putValue("readOnly", false)
.putValue("monitor", true)
context.logger.info("Creating storage for server with meta {}", storageMeta) context.logger.info("Creating storage for server with meta {}", storageMeta)
var storage = StorageFactory.buildStorage(context, storageMeta); var storage = StorageFactory.buildStorage(context, storageMeta);

View File

@ -1,8 +1,10 @@
package inr.numass.control package inr.numass.control
import hep.dataforge.control.devices.Device import hep.dataforge.control.devices.Device
import hep.dataforge.control.devices.PortSensor
import hep.dataforge.fx.fragments.FXFragment import hep.dataforge.fx.fragments.FXFragment
import hep.dataforge.fx.fragments.FragmentWindow import hep.dataforge.fx.fragments.FragmentWindow
import hep.dataforge.storage.filestorage.FileStorage
import inr.numass.control.NumassControlUtils.getDFIcon import inr.numass.control.NumassControlUtils.getDFIcon
import javafx.geometry.Orientation import javafx.geometry.Orientation
import javafx.geometry.Pos import javafx.geometry.Pos
@ -22,63 +24,80 @@ class BoardView : View("Numass control board", ImageView(getDFIcon())) {
prefWidth = 200.0 prefWidth = 200.0
center { center {
vbox { vbox {
hbox { //Server pane
alignment = Pos.CENTER titledpane(title = "Server", collapsible = false) {
vgrow = Priority.ALWAYS; vgrow = Priority.ALWAYS;
prefHeight = 40.0 hbox {
text("Server") // TODO add fancy style here alignment = Pos.CENTER_LEFT
separator(Orientation.VERTICAL) prefHeight = 40.0
var serverLabel: Hyperlink by singleAssign(); var serverLabel: Hyperlink by singleAssign();
togglebutton("Start") { togglebutton("Start") {
isSelected = false isSelected = false
disableProperty().bind(controller.serverManagerProperty.isNull) disableProperty().bind(controller.serverManagerProperty.isNull)
action { action {
if (isSelected) { if (isSelected) {
text = "Stop" text = "Stop"
controller.serverManager.startServer() controller.serverManager.startServer()
serverLabel.text = controller.serverManager.link; serverLabel.text = controller.serverManager.link;
} else {
text = "Start"
controller.serverManager.stopServer()
serverLabel.text = ""
}
}
}
text("Started: ") {
paddingHorizontal = 5
}
indicator {
bind(controller.serverManager.isStarted)
}
separator(Orientation.VERTICAL)
text("Address: ")
serverLabel = hyperlink {
action {
hostServices.showDocument(controller.serverManager.link);
}
}
}
}
titledpane(title = "Storage", collapsible = true) {
vgrow = Priority.ALWAYS;
hbox {
alignment = Pos.CENTER_LEFT
prefHeight = 40.0
label(stringBinding(controller.storage) {
val storage = controller.storage
if (storage is FileStorage) {
"Path: " + storage.dataDir;
} else { } else {
text = "Start" "Name: " + controller.storage.fullPath
controller.serverManager.stopServer()
serverLabel.text = ""
} }
} })
}
indicator {
bind(controller.serverManager.isStarted)
}
serverLabel = hyperlink {
action {
hostServices.showDocument(controller.serverManager.link);
}
} }
} }
separator(Orientation.HORIZONTAL) separator(Orientation.HORIZONTAL)
hbox { scrollpane(fitToWidth = true, fitToHeight = true) {
alignment = Pos.CENTER
vgrow = Priority.ALWAYS; vgrow = Priority.ALWAYS;
prefHeight = 40.0 vbox {
text("Storage") prefHeight = 40.0
separator(Orientation.VERTICAL) bindChildren(controller.devices) { connection ->
label(stringBinding(controller.storage) { titledpane(title = "Device: " + connection.device.name, collapsible = true) {
controller.storage.fullPath hbox {
}) alignment = Pos.CENTER_LEFT
} vgrow = Priority.ALWAYS;
separator(Orientation.HORIZONTAL) deviceStateIndicator(connection,Device.INITIALIZED_STATE)
vbox { deviceStateIndicator(connection, PortSensor.CONNECTED_STATE)
vgrow = Priority.ALWAYS; deviceStateIndicator(connection, "storing")
prefHeight = 40.0 pane {
bindChildren(controller.devices) { connection -> hgrow = Priority.ALWAYS
hbox { }
alignment = Pos.CENTER togglebutton("View") {
vgrow = Priority.ALWAYS; isSelected = false
text("Device: " + connection.device.name) FragmentWindow(FXFragment.buildFromNode(connection.device.name) { connection.fxNode }).bindTo(this)
separator(Orientation.VERTICAL) }
indicator { }
bind(connection, Device.INITIALIZED_STATE)
} }
val viewButton = togglebutton("View")
FragmentWindow(FXFragment.buildFromNode(connection.device.name) { connection.fxNode }).bindTo(viewButton)
} }
} }
} }

View File

@ -3,6 +3,7 @@ package inr.numass.control
import hep.dataforge.values.Value import hep.dataforge.values.Value
import javafx.beans.value.ObservableValue import javafx.beans.value.ObservableValue
import javafx.event.EventTarget import javafx.event.EventTarget
import javafx.geometry.Orientation
import javafx.scene.paint.Color import javafx.scene.paint.Color
import javafx.scene.paint.Paint import javafx.scene.paint.Paint
import javafx.scene.shape.Circle import javafx.scene.shape.Circle
@ -19,7 +20,6 @@ class Indicator(radius: Double = 10.0) : Circle(radius, Color.GRAY) {
init { init {
stroke = Color.BLACK; stroke = Color.BLACK;
strokeType = StrokeType.INSIDE; strokeType = StrokeType.INSIDE;
tooltip { }
} }
/** /**
@ -30,9 +30,10 @@ class Indicator(radius: Double = 10.0) : Circle(radius, Color.GRAY) {
throw RuntimeException("Indicator already bound"); throw RuntimeException("Indicator already bound");
} else { } else {
binding = observable; binding = observable;
} fill = transform(observable.value)
observable.addListener { _, _, value -> observable.addListener { _, _, value ->
fill = transform(value); fill = transform(value);
}
} }
} }
@ -79,4 +80,17 @@ fun Indicator.bind(connection: DeviceViewConnection<*>, state: String, transform
} }
} }
} }
}
/**
* 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)
}
} }

View File

@ -1,9 +1,9 @@
package inr.numass.control package inr.numass.control
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.context.Global
import javafx.stage.Stage import javafx.stage.Stage
import tornadofx.* import tornadofx.*
import java.io.File
/** /**
* Created by darksnake on 19-May-17. * Created by darksnake on 19-May-17.
@ -14,7 +14,11 @@ class ServerApp : App(BoardView::class) {
override fun start(stage: Stage) { override fun start(stage: Stage) {
NumassControlUtils.getConfig(this).ifPresent { NumassControlUtils.getConfig(this).ifPresent {
context = Global.getContext("NUMASS-SERVER"); val libPath = parameters.named.getOrDefault("libPath","../lib");
context = Context
.builder("NUMASS-SERVER")
.classPath(File(libPath).toURI().toURL())
.build()
controller.load(context, it); controller.load(context, it);
} }
super.start(stage) super.start(stage)

View File

@ -36,7 +36,7 @@ public class MspApp extends NumassControlApplication<MspDevice> {
} }
@Override @Override
protected DeviceFactory<MspDevice> getDeviceFactory() { protected DeviceFactory getDeviceFactory() {
return new MspDeviceFactory(); return new MspDeviceFactory();
} }

View File

@ -25,7 +25,7 @@ public class ReadVac extends NumassControlApplication<VacCollectorDevice> {
} }
@Override @Override
protected DeviceFactory<VacCollectorDevice> getDeviceFactory() { protected DeviceFactory getDeviceFactory() {
return new VacDeviceFactory(); return new VacDeviceFactory();
} }

View File

@ -27,7 +27,7 @@ dependencies {
compile 'org.controlsfx:controlsfx:8.40.12' compile 'org.controlsfx:controlsfx:8.40.12'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:'1.1.2-3" compile "org.jetbrains.kotlin:kotlin-stdlib-jre8"
compile "no.tornado:tornadofx:1.7.4" compile "no.tornado:tornadofx:1.7.4"
} }