[orx-file-watcher, orx-property-watchers] Add events and documentation
This commit is contained in:
@@ -3,9 +3,7 @@ package org.openrndr.extra.filewatcher
|
||||
import com.sun.nio.file.SensitivityWatchEventModifier
|
||||
import kotlinx.coroutines.*
|
||||
import mu.KotlinLogging
|
||||
import org.openrndr.Program
|
||||
import org.openrndr.events.Event
|
||||
import org.openrndr.launch
|
||||
import java.io.File
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Path
|
||||
@@ -13,7 +11,6 @@ import java.nio.file.StandardWatchEventKinds
|
||||
import java.nio.file.WatchKey
|
||||
import java.util.WeakHashMap
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
@@ -52,15 +49,19 @@ private val watchThread by lazy {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @property file
|
||||
* @property fileChangedEvent
|
||||
* @param requestStopEvent
|
||||
*/
|
||||
class FileWatcher(
|
||||
val file: File,
|
||||
private val file: File,
|
||||
private val fileChangedEvent: Event<File>,
|
||||
requestStopEvent: Event<Unit>? = null
|
||||
) {
|
||||
val path = file.absoluteFile.toPath()
|
||||
val parent = path.parent
|
||||
val key = pathKeys.getOrPut(parent) {
|
||||
private val path = file.absoluteFile.toPath()
|
||||
private val parent = path.parent
|
||||
private val key = pathKeys.getOrPut(parent) {
|
||||
parent.register(
|
||||
watchService, arrayOf(StandardWatchEventKinds.ENTRY_MODIFY),
|
||||
SensitivityWatchEventModifier.HIGH
|
||||
@@ -78,6 +79,7 @@ class FileWatcher(
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
fun stop() {
|
||||
synchronized(watching) {
|
||||
logger.info { "stopping, watcher stop requested" }
|
||||
@@ -90,34 +92,36 @@ class FileWatcher(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun <T> watchFile(
|
||||
/**
|
||||
* Watch a file for changes
|
||||
* @param file the file to watch
|
||||
* @param valueChangedEvent the event that is triggered when the value (after transforming) has changed
|
||||
* @param requestStopEvent an event that can be triggered to request the watcher to stop
|
||||
* @param transducer a function that transforms a [File] into a value of type [R]
|
||||
*/
|
||||
fun <R> watchFile(
|
||||
file: File,
|
||||
contentsChangedEvent: Event<T>? = null,
|
||||
valueChangedEvent: Event<R>? = null,
|
||||
requestStopEvent: Event<Unit>? = null,
|
||||
transducer: (File) -> T
|
||||
): () -> T {
|
||||
transducer: (File) -> R
|
||||
): () -> R {
|
||||
var result = transducer(file)
|
||||
val fileChangedEvent = Event<File>()
|
||||
val watcher = FileWatcher(file, fileChangedEvent, requestStopEvent)
|
||||
|
||||
@Suppress("UNUSED_VARIABLE") val watcher = FileWatcher(file, fileChangedEvent, requestStopEvent)
|
||||
|
||||
fileChangedEvent.listen {
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
try {
|
||||
result = transducer(file)
|
||||
contentsChangedEvent?.trigger(result)
|
||||
valueChangedEvent?.trigger(result)
|
||||
} catch (e: Throwable) {
|
||||
logger.error(e) {
|
||||
"""exception while transducing file"""
|
||||
"""exception while transforming file ${file.absolutePath}"""
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//@JvmName("programWatchFile")
|
||||
//fun <T> Program.watchFile(file: File, onChange: Event<T>? = null, transducer: (File) -> T): () -> T =
|
||||
// watchFile(this, file, onChange, transducer = transducer)
|
||||
}
|
||||
@@ -1,11 +1,21 @@
|
||||
package org.openrndr.extra.filewatcher
|
||||
|
||||
import kotlinx.coroutines.yield
|
||||
import org.openrndr.Program
|
||||
import org.openrndr.events.Event
|
||||
import org.openrndr.extra.filewatcher.watchFile
|
||||
import org.openrndr.launch
|
||||
import java.io.File
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* Property delegator that watches a file. Changes are propagated right before the [Program] updates its extensions
|
||||
* @param program the program to synchronise updates with
|
||||
* @param file the file to watch
|
||||
* @param valueChangedEvent the event that is triggered when the value (after transformation) has changed
|
||||
* @param requestStopEvent an event that can be triggered to request the watcher to stop
|
||||
* @since 0.4.3
|
||||
* @see watchingFile
|
||||
*/
|
||||
class FileWatcherDelegate<T>(
|
||||
program: Program,
|
||||
file: File,
|
||||
@@ -13,10 +23,11 @@ class FileWatcherDelegate<T>(
|
||||
requestStopEvent: Event<Unit>? = null,
|
||||
transducer: (File) -> T
|
||||
) {
|
||||
val watchValue = watchFile(file, valueChangedEvent, requestStopEvent, transducer)
|
||||
var value = watchValue()
|
||||
private val watchValue = watchFile(file, valueChangedEvent, requestStopEvent, transducer)
|
||||
private var value = watchValue()
|
||||
|
||||
init {
|
||||
// make sure that `value` is updated at the beginning of a draw cycle and not mid-cycle.
|
||||
program.launch {
|
||||
while (true) {
|
||||
value = watchValue()
|
||||
@@ -25,11 +36,23 @@ class FileWatcherDelegate<T>(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return transformed value
|
||||
*/
|
||||
operator fun getValue(any: Any?, property: KProperty<*>): T {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate value to a file watcher
|
||||
* @param file the file to watch
|
||||
* @param valueChangedEvent the event that is triggered when the value (after transformation) has changed
|
||||
* @param requestStopEvent an event that can be triggered to request the watcher to stop
|
||||
* @param transducer a function that transforms a [File] into a value of type [R]
|
||||
* @since 0.4.3
|
||||
* @see FileWatcherDelegate
|
||||
*/
|
||||
fun <R> Program.watchingFile(
|
||||
file: File,
|
||||
valueChangedEvent: Event<R>? = null,
|
||||
|
||||
Reference in New Issue
Block a user