![JAR search and dependency download from the Maven repository](/logo.png)
org.hyperscala.ui.module.Monitor.scala Maven / Gradle / Ivy
package org.hyperscala.ui.module
import org.hyperscala.module.Module
import org.powerscala.json.TypedSupport
import org.powerscala.log.Logging
import org.powerscala.{Unique, Version}
import org.hyperscala.realtime.{RealtimePage, Realtime}
import org.hyperscala.web.{Webpage, Website}
import org.hyperscala.html._
import org.powerscala.property.Property
import org.hyperscala.PropertyAttribute
import org.hyperscala.persistence.ValuePersistence
import org.hyperscala.css.StyleSheetAttribute
import org.hyperscala.javascript.dsl._
import com.outr.net.http.session.Session
/**
* Monitor allows arbitrary JavaScript to be monitored for a changing result at a specific interval and to send that data
* back to the server when it changes. This utilizes batch sends to avoid extraneous information but causes some
* intermediate data to be potentially lost.
*
* @author Matt Hicks
*/
object Monitor extends Module with Logging {
TypedSupport.register("monitor", classOf[MonitorEvent])
val name = "monitor"
val version = Version(1)
override def dependencies = List(Realtime)
override def init(website: Website) = {
website.register("/js/monitor.js", "monitor.js")
}
override def load(webpage: Webpage) = {
webpage.head.contents += new tag.Script(mimeType = "text/javascript", src = "/js/monitor.js")
apply(webpage)
}
private def apply(webpage: Webpage) = {
webpage.store.getOrSet("monitor", new MonitoredPage(webpage))
}
def create[T, S <: Session](webpage: Webpage, frequency: Double, evaluator: JSFunction0[T])
(implicit manifest: Manifest[T], converter: ValuePersistence[T]) = {
apply(webpage).create[T](frequency, evaluator)
}
def remove[T, S <: Session](webpage: Webpage, monitor: Monitor[T]) = {
apply(webpage).remove[T](monitor)
}
def sync[T, S <: Session](webpage: Webpage, attribute: PropertyAttribute[T], frequency: Double) = {
val function = attribute match {
case ssa: StyleSheetAttribute[T] => {
val t = ssa.ss.hierarchicalParent.asInstanceOf[HTMLTag]
onCSS(t, ssa)
}
case _ => {
val t = attribute.parent.asInstanceOf[HTMLTag]
onAttribute(t, attribute)
}
}
val monitor = create[T, S](webpage, frequency, function)(attribute.manifest, attribute.persister)
val property = monitor.property
property.change.on {
case evt => RealtimePage.ignoringChange(attribute, property())
}
monitor
}
private class MonitoredPage(webpage: Webpage) {
private var map = Map.empty[String, Monitor[_]]
webpage.jsonEvent.partial(Unit) {
case evt: MonitorEvent => map.get(evt.monitorId) match {
case Some(monitor) => monitor.receive(evt)
case None => warn(s"Monitor ${evt.monitorId} doesn't exist!")
}
}
def create[T](frequency: Double, evaluator: JSFunction0[T])
(implicit manifest: Manifest[T], converter: ValuePersistence[T]) = {
val id = Unique()
val monitor = new Monitor[T](id, frequency, evaluator)
synchronized {
map += id -> monitor
}
val f = math.round(frequency * 1000.0)
webpage.eval(s"window.monitor.createMonitor('$id', $f, ${evaluator.content});")
monitor
}
def remove[T](monitor: Monitor[T]) = synchronized {
val id = monitor.id
webpage.eval(s"window.monitor.removeMonitor('$id');")
map -= id
}
}
}
case class MonitorEvent(monitorId: String, value: String)
class Monitor[T] private(val id: String, val frequency: Double, val evaluator: JSFunction0[T])
(implicit manifest: Manifest[T], converter: ValuePersistence[T]) {
val property = Property[T](default = None)
def receive(evt: MonitorEvent) = {
property := converter.fromString(evt.value, null, manifest.runtimeClass)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy