diff --git a/dataforge-gui/build.gradle.kts b/dataforge-gui/build.gradle.kts index bd628c9..e101ef9 100644 --- a/dataforge-gui/build.gradle.kts +++ b/dataforge-gui/build.gradle.kts @@ -12,7 +12,9 @@ description = "A tornadofx based kotlin library" dependencies { api(project(":dataforge-plots")) api(project(":dataforge-gui:dataforge-html")) - api("no.tornado:tornadofx:1.7.20") + api("no.tornado:tornadofx:1.7.20"){ + exclude("org.jetbrains.kotlin") + } api("org.controlsfx:controlsfx:11.1.0") api("no.tornado:tornadofx-controlsfx:0.1.1") api("org.fxmisc.richtext:richtextfx:0.10.7") diff --git a/numass-viewer/build.gradle.kts b/numass-viewer/build.gradle.kts index 15cf2ff..9c6699d 100644 --- a/numass-viewer/build.gradle.kts +++ b/numass-viewer/build.gradle.kts @@ -1,6 +1,7 @@ plugins { kotlin("jvm") id("org.openjfx.javafxplugin") + id("org.beryx.runtime") version "1.12.7" application } @@ -27,16 +28,38 @@ dependencies { api(project(":dataforge-gui")) } +val addJvmArgs = listOf( + "--add-exports=javafx.graphics/com.sun.glass.ui=ALL-UNNAMED", + "--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED", + "--add-opens=javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED", + "--add-opens=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED", + "--add-opens=javafx.graphics/javafx.scene=ALL-UNNAMED", + "--add-opens=javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED", + "--add-opens=javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED", + "--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED", + "--add-exports=javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED", +) + application { - applicationDefaultJvmArgs = listOf( - "--add-exports=javafx.graphics/com.sun.glass.ui=ALL-UNNAMED", - "--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED", - "--add-opens=javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED", - "--add-opens=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED", - "--add-opens=javafx.graphics/javafx.scene=ALL-UNNAMED", - "--add-opens=javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED", - "--add-opens=javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED", - "--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED", - "--add-exports=javafx.controls/com.sun.javafx.scene.control.inputmap=ALL-UNNAMED", + applicationDefaultJvmArgs = addJvmArgs +} + +runtime { + addOptions("--strip-debug", "--compress", "2", "--no-header-files", "--no-man-pages") + addModules( + "java.desktop", + "jdk.unsupported", + "java.scripting", + "java.logging", + "java.xml", + "javafx.graphics", + "javafx.controls" ) + jpackage { + jvmArgs = addJvmArgs + imageOptions = listOf("--linux-deb-maintainer nozik.aa@mipt.ru", "--linux-menu-group Science") + } + launcher { + jvmArgs = addJvmArgs + } } \ No newline at end of file diff --git a/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt b/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt index bddfce3..b63c2ee 100644 --- a/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt +++ b/numass-viewer/src/main/kotlin/inr/numass/viewer/StorageView.kt @@ -2,6 +2,7 @@ package inr.numass.viewer import hep.dataforge.fx.dfIconView import hep.dataforge.fx.meta.MetaViewer +import hep.dataforge.io.envelopes.Envelope import hep.dataforge.meta.Meta import hep.dataforge.meta.Metoid import hep.dataforge.names.AlphanumComparator @@ -9,6 +10,8 @@ import hep.dataforge.storage.Storage import hep.dataforge.storage.files.FileStorage import hep.dataforge.storage.files.FileTableLoader import hep.dataforge.storage.tables.TableLoader +import inr.numass.data.NumassDataUtils +import inr.numass.data.NumassEnvelopeType import inr.numass.data.api.NumassPoint import inr.numass.data.api.NumassSet import inr.numass.data.storage.NumassDataLoader @@ -17,7 +20,14 @@ import javafx.beans.property.SimpleObjectProperty import javafx.collections.ObservableList import javafx.scene.control.ContextMenu import javafx.scene.control.TreeItem +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch import tornadofx.* +import java.nio.file.Path +import java.nio.file.StandardWatchEventKinds.ENTRY_CREATE +import java.nio.file.WatchKey import java.nio.file.WatchService @@ -58,6 +68,8 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { } } + val watchedProperty = SimpleBooleanProperty(false) + init { checkedProperty.onChange { selected -> when (content) { @@ -88,50 +100,61 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { } } } + + watchedProperty.onChange { + toggleWatch(it) + } } - fun getChildren(): ObservableList? = when (content) { - is Storage -> content.getChildren().map { - buildContainer(it, this) - }.sortedWith(Comparator.comparing({ it.id }, AlphanumComparator)).asObservable() - is NumassSet -> content.points - .sortedBy { it.index } - .map { buildContainer(it, this) } - .asObservable() - else -> null + val children: ObservableList? by lazy { + when (content) { + is Storage -> content.getChildren().map { + buildContainer(it, this) + }.sortedWith(Comparator.comparing({ it.id }, AlphanumComparator)).asObservable() + is NumassSet -> content.points + .sortedBy { it.index } + .map { buildContainer(it, this) } + .asObservable() + else -> null + } } - /* - is NumassDataLoader -> { - val res = content.points.sortedBy { it.index }.map { buildContainer(it, this) }.toObservable() - watchJob = app.context.launch(Dispatchers.IO) { - val key: WatchKey = content.path.register(watcher!!, ENTRY_CREATE) - coroutineContext[Job]?.invokeOnCompletion { - key.cancel() - } - while (watcher != null && isActive) { - try { - key.pollEvents().forEach { event -> - if (event.kind() == ENTRY_CREATE) { - val path: Path = event.context() as Path - if (path.fileName.toString().startsWith(NumassDataLoader.POINT_FRAGMENT_NAME)) { - val envelope: Envelope = NumassEnvelopeType.infer(path)?.reader?.read(path) - ?: kotlin.error("Can't read point file") - val point = NumassDataUtils.read(envelope) - res.add(buildContainer(point, this@Container)) + + val hasChildren: Boolean = (content is Storage) || (content is NumassSet) + + private var watchJob: Job? = null + + private fun toggleWatch(watch: Boolean) { + if (watch) { + if (watchJob != null && content is NumassDataLoader) { + watchJob = app.context.launch(Dispatchers.IO) { + val key: WatchKey = content.path.register(watcher!!, ENTRY_CREATE) + coroutineContext[Job]?.invokeOnCompletion { + key.cancel() + } + while (watcher != null && isActive) { + try { + key.pollEvents().forEach { event -> + if (event.kind() == ENTRY_CREATE) { + val path: Path = event.context() as Path + if (path.fileName.toString().startsWith(NumassDataLoader.POINT_FRAGMENT_NAME)) { + val envelope: Envelope = NumassEnvelopeType.infer(path)?.reader?.read(path) + ?: kotlin.error("Can't read point file") + val point = NumassDataUtils.read(envelope) + children!!.add(buildContainer(point, this@Container)) + } } } + } catch (x: Throwable) { + app.context.logger.error("Error during dynamic point read", x) } - } catch (x: Throwable) { - app.context.logger.error("Error during dynamic point read", x) } } } - res + } else { + watchJob?.cancel() + watchJob = null } - */ - - - val hasChildren: Boolean = (content is Storage) || (content is NumassSet) + } } @@ -146,7 +169,7 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { lazyPopulate(leafCheck = { !it.value.hasChildren }) { - it.value.getChildren() + it.value.children } watcher?.close() watcher = if (storage is FileStorage) { @@ -196,6 +219,11 @@ class StorageView : View(title = "Numass storage", icon = dfIconView) { value.infoView.openModal(escapeClosesWindow = true) } } + if(value.content is NumassDataLoader) { + checkmenuitem("Watch") { + selectedProperty().bindBidirectional(value.watchedProperty) + } + } } } }