diff options
Diffstat (limited to 'mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments')
10 files changed, 256 insertions, 0 deletions
diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Altimeter.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Altimeter.scala new file mode 100644 index 0000000..b65b374 --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Altimeter.scala @@ -0,0 +1,18 @@ +package vfd.dashboard.ui.instruments + +import org.scalajs.dom.html +import rx._ +import vfd.dashboard.Environment + +class Altimeter(val value: Rx[Double])(implicit env: Environment) extends SvgInstrument[Double] { + import SvgInstrument._ + + lazy val element = svgObject("altimeter") + lazy val hand = part("hand") + lazy val moveable = Seq(hand) + + // 1m === 36deg = 2Pi / 10 ~= 0.62832 + protected def update(altitude: Double) = { + rotate(hand, (altitude * 0.62832).toInt) + } +}
\ No newline at end of file diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Bar.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Bar.scala new file mode 100644 index 0000000..9f9f81c --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Bar.scala @@ -0,0 +1,18 @@ +package vfd.dashboard.ui.instruments + +import org.scalajs.dom.html +import rx._ +import vfd.dashboard.Environment + +class Bar(val value: Rx[Double])(implicit env: Environment) extends SvgInstrument[Double] { + import SvgInstrument._ + + lazy val element = svgObject("bar") + lazy val level = part("level") + lazy val moveable = Seq(level) + + protected def update(value: Double) = { + translate(level, 0, (97 * (1 - value / 100)).toInt) + } + +}
\ No newline at end of file diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Clock.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Clock.scala new file mode 100644 index 0000000..a5bfc03 --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Clock.scala @@ -0,0 +1,23 @@ +package vfd.dashboard.ui.instruments + +import org.scalajs.dom +import rx._ +import scala.scalajs.js.Date +import scalatags.JsDom.all._ + +class Clock extends Instrument[Date] { + + def format(date: Date) = date.toLocaleTimeString() + + val value = Var(new Date) + + val element = span(format(value())).render + + protected def update(value: Date) = { + element.innerHTML = format(value) + } + + dom.setInterval(() => {value() = new Date}, 1000) + ready() + +}
\ No newline at end of file diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Compass.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Compass.scala new file mode 100644 index 0000000..9f1ae4a --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Compass.scala @@ -0,0 +1,17 @@ +package vfd.dashboard.ui.instruments + +import org.scalajs.dom.html +import rx._ +import vfd.dashboard.Environment + +class Compass(val value: Rx[Double])(implicit env: Environment) extends SvgInstrument[Double] { + import SvgInstrument._ + + lazy val element = svgObject("compass") + lazy val plate = part("heading") + lazy val moveable = Seq(plate) + + protected def update(heading: Double) = { + rotate(plate, heading) + } +}
\ No newline at end of file diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Distribution.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Distribution.scala new file mode 100644 index 0000000..f750bab --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Distribution.scala @@ -0,0 +1,25 @@ +package vfd.dashboard.ui.instruments + +import org.scalajs.dom.html +import rx._ +import vfd.dashboard.Environment + +class Distribution(val value: Rx[(Double, Double, Double, Double)])(implicit env: Environment) extends SvgInstrument[(Double, Double, Double, Double)] { + import SvgInstrument._ + + lazy val element = svgObject("distribution") + lazy val position = part("position") + lazy val moveable = Seq(position) + + private final val Radius = 50 //px + + protected def update(value: (Double, Double, Double, Double)) = { + val sum = value._1 + value._2 + value._3 + value._4 + val i = (value._1 - value._3) / sum + val j = (value._2 - value._4) / sum + val x = math.sqrt(2) / 2 * (i - j) + val y = math.sqrt(2) / 2 * (-i - j) + translate(position, (x * Radius).toInt, (y * Radius).toInt) + } + +}
\ No newline at end of file diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Generic.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Generic.scala new file mode 100644 index 0000000..86c27e1 --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Generic.scala @@ -0,0 +1,40 @@ +package vfd.dashboard.ui.instruments + +import org.scalajs.dom +import org.scalajs.dom.html +import rx._ +import vfd.dashboard.Environment + +class Generic( + min: Double, + med: Double, + max: Double, + unit: String, + val value: Rx[Double]) + (implicit env: Environment) + extends SvgInstrument[Double] { + + import SvgInstrument._ + + lazy val element = svgObject("generic") + lazy val handElement = part("hand") + lazy val unitElement = element.contentDocument.getElementById("unit") + lazy val valueElement = element.contentDocument.getElementById("value") + lazy val minElement = element.contentDocument.getElementById("min") + lazy val medElement = element.contentDocument.getElementById("med") + lazy val maxElement = element.contentDocument.getElementById("max") + lazy val moveable = Seq(handElement) + + override protected def load(e: dom.Event) = { + unitElement.textContent = unit + minElement.textContent = min.toString + medElement.textContent = med.toString + maxElement.textContent = max.toString + super.load(e) + } + + protected def update(value: Double) = { + rotate(handElement, value / (max - min) * math.Pi * 3 / 2) + valueElement.textContent = value.toString + } +}
\ No newline at end of file diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Horizon.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Horizon.scala new file mode 100644 index 0000000..bbfe8cf --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Horizon.scala @@ -0,0 +1,19 @@ +package vfd.dashboard.ui.instruments + +import org.scalajs.dom.html +import rx._ +import vfd.dashboard.Environment + +class Horizon(val value: Rx[(Double, Double)])(implicit env: Environment) extends SvgInstrument[(Double, Double)] { + import SvgInstrument._ + + lazy val element = svgObject("horizon") + lazy val pitch = part("pitch") + lazy val roll = part("roll") + lazy val moveable = Seq(pitch, roll) + + protected def update(pitchRoll: (Double, Double)) = { + translate(pitch, 0, (pitchRoll._1 * 180 / math.Pi).toInt) // 1deg === 1px + rotate(roll, pitchRoll._2) + } +} diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Instrument.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Instrument.scala new file mode 100644 index 0000000..bf5c9ca --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Instrument.scala @@ -0,0 +1,25 @@ +package vfd.dashboard.ui.instruments + +import rx._ +import org.scalajs.dom.html + +/** Common trait to all flight instruments. */ +trait Instrument[A] { + + /** Current value that is displayed in the instrument. */ + val value: Rx[A] + + /** HTML element that contains the rendered instrument */ + val element: html.Element + + /** Performs the actual UI update of this instrument. */ + protected def update(newValue: A): Unit + + /** Call when instrument has finished setting up its UI. */ + protected def ready() = { + Obs(value, skipInitial = true) { + update(value()) + } + } + +}
\ No newline at end of file diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Led.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Led.scala new file mode 100644 index 0000000..f5259b5 --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/Led.scala @@ -0,0 +1,17 @@ +package vfd.dashboard.ui.instruments + +import rx._ +import scalatags.JsDom.all._ +import vfd.dashboard.Environment + +class Led(val value: Rx[String])(implicit env: Environment) extends SvgInstrument[String] { + + lazy val element = `object`(`type` := "image/svg+xml", "data".attr := env.asset("images/leds/led.svg"), width := 100.pct)( + "Error loading led.").render + protected def moveable = Seq() + + protected def update(color: String) = { + part("light").setAttribute("fill", color) + } + +}
\ No newline at end of file diff --git a/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/SvgInstrument.scala b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/SvgInstrument.scala new file mode 100644 index 0000000..fe6c58a --- /dev/null +++ b/mavigator-dashboard/src/main/scala/mavigator/dashboard/ui/instruments/SvgInstrument.scala @@ -0,0 +1,54 @@ +package vfd.dashboard.ui.instruments + + +import org.scalajs.dom +import org.scalajs.dom.html + +import scalatags.JsDom.all._ + +import vfd.dashboard.Environment + +/** An instrument backed by an SVG image. */ +trait SvgInstrument[A] extends Instrument[A] { + + /** SVG object element that contains the rendered instrument */ + val element: html.Object + + /** Retrieves an element of the underlying SVG document by ID. */ + protected def part(id: String) = element.contentDocument.getElementById(id).asInstanceOf[html.Element] + + /** Movable parts of the instrument */ + protected def moveable: Seq[html.Element] + + /** Called when element has been loaded. */ + protected def load(event: dom.Event): Unit = { + for (part <- moveable) { + part.style.transition = "transform 50ms ease-out" + } + ready() + } + + element.addEventListener("load", (e: dom.Event) => load(e)) +} + +/** Contains helpers for SVG instruments. */ +object SvgInstrument { + + /** Retrieves an SVG object element by its instrument's name. */ + def svgObject(name: String)(implicit app: Environment): html.Object = { + val path = app.asset("images/instruments/" + name + ".svg") + `object`(`type` := "image/svg+xml", "data".attr := path, width := 100.pct)( + "Error loading instrument " + name).render + } + + /** Applies translation styling to an element. */ + def translate(elem: html.Element, x: Int, y: Int): Unit = { + elem.style.transform = "translate(" + x + "px, " + y + "px)"; + } + + /** Applies rotation styling to an element. */ + def rotate(elem: html.Element, rad: Double): Unit = { + elem.style.transform = "rotateZ(" + rad + "rad)"; + } + +}
\ No newline at end of file |