aboutsummaryrefslogtreecommitdiff
path: root/vfd-frontend/src/main/scala/vfd/frontend/ui
diff options
context:
space:
mode:
Diffstat (limited to 'vfd-frontend/src/main/scala/vfd/frontend/ui')
-rw-r--r--vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala67
-rw-r--r--vfd-frontend/src/main/scala/vfd/frontend/ui/Panels.scala116
2 files changed, 183 insertions, 0 deletions
diff --git a/vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala b/vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala
new file mode 100644
index 0000000..959ca8a
--- /dev/null
+++ b/vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala
@@ -0,0 +1,67 @@
+package vfd.frontend.ui
+
+import rx._
+import scalatags.JsDom.all._
+import vfd.frontend.util.Application
+import org.scalajs.dom.HTMLElement
+
+object Components {
+
+ def led(color: Rx[String], size: String)(implicit app: Application) = {
+ val elem = `object`(`type` := "image/svg+xml", "data".attr := app.asset("leds/led.svg"), width := size)(
+ "Error loading image."
+ ).render
+
+ Obs(color, skipInitial = true) {
+ val svg = elem.contentDocument
+ svg.getElementById("light").setAttribute("fill", color())
+ }
+ elem
+ }
+
+ private def instrument(name: String)(implicit app: Application) = {
+ val path = app.asset("images/instruments/" + name + ".svg")
+ `object`(`type` := "image/svg+xml", "data".attr := path, width := "100%")(
+ "Error loading image " + name
+ ).render
+ }
+
+ private def frame(elem: HTMLElement, size: String) = {
+ div(style := s"width: $size; height: $size; display: inline-block;" )(
+ elem
+ )
+ }
+
+ def attitude(pitchRoll: Rx[(Double, Double)], size: String)(implicit app: Application) = {
+ val inst = instrument("attitude")
+ Obs(pitchRoll, skipInitial = true){
+ val svg = inst.contentDocument
+ val pitch = svg.getElementById("pitch")
+ val roll = svg.getElementById("roll")
+ pitch.setAttribute("transform", "translate(0, " + pitchRoll()._1 / math.Pi * 180 + ")");
+ roll.setAttribute("transform", "rotate(" + pitchRoll()._2 / math.Pi * 180 + ")");
+ }
+ frame(inst, size)
+ }
+
+ def altitude(value: Rx[Double], size: String)(implicit app: Application) = {
+ val inst = instrument("altitude")
+ Obs(value, skipInitial = true){
+ val svg = inst.contentDocument
+ // 36deg === 1m
+ svg.getElementById("hand").setAttribute("transform", "rotate(" + value() * 36 + ")");
+ }
+ frame(inst, size)
+ }
+
+ def heading(value: Rx[Double], size: String)(implicit app: Application) = {
+ val inst = instrument("heading")
+ Obs(value, skipInitial = true){
+ val svg = inst.contentDocument
+ // 1deg === 1deg
+ svg.getElementById("heading").setAttribute("transform", "rotate(" + value() / math.Pi * 180 + ")");
+ }
+ frame(inst, size)
+ }
+
+} \ No newline at end of file
diff --git a/vfd-frontend/src/main/scala/vfd/frontend/ui/Panels.scala b/vfd-frontend/src/main/scala/vfd/frontend/ui/Panels.scala
new file mode 100644
index 0000000..8c5e38d
--- /dev/null
+++ b/vfd-frontend/src/main/scala/vfd/frontend/ui/Panels.scala
@@ -0,0 +1,116 @@
+package vfd.frontend.ui
+
+import rx._
+import rx.ops._
+import scalatags.JsDom.all._
+import vfd.uav.DataFrame
+import vfd.frontend.util.Application
+import vfd.frontend.util.Framework._
+
+
+object Panels {
+
+ def primary(input: Rx[DataFrame])(implicit app: Application) = div(
+ Components.heading(input map (_.heading), "33%"),
+ Components.attitude(input map (i => (i.pitch, i.roll)), "33%"),
+ Components.altitude(input map (_.altitude), "33%")
+ )
+
+ def secondary(input: Rx[DataFrame])(implicit app: Application) = div(
+ iframe(
+ width:="100%",
+ height:="350px",
+ "frameborder".attr:="0",
+ "scrolling".attr:="no",
+ "marginheight".attr:="0",
+ "marginwidth".attr:="0",
+ src:="http://www.openstreetmap.org/export/embed.html?bbox=6.5611016750335684%2C46.51718501017836%2C6.570038795471191%2C46.520577350893525&layer=mapnik"
+ ),
+ table(`class`:="table")(
+ tr(
+ td("UAV Position"),
+ td("N13.1234 E1234.23465")
+ ),
+ tr(
+ td("Base Position"),
+ td("N13.1234 E1234.23465")
+ ),
+ tr(
+ td("Distance to UAV"),
+ td("200 m")
+ ),
+ tr(
+ td("Total flight distance"),
+ td("12.3 km")
+ ),
+ tr(
+ td("Groundspeed"),
+ td("23 km/h")
+ ),
+ tr(
+ td("---"),
+ td("")
+ ),
+ tr(
+ td("Below"),
+ td("180 cm")
+ )
+ )
+ )
+
+ def eicas()(implicit app: Application) = {
+ table(`class`:="table")(
+ tr(
+ td("Link Server"),
+ td("3"),
+ td("ms"),
+ td(img(src:="/assets/images/leds/red-off.svg",width:="16px"))
+ ),
+ tr(
+ td("Link UAV"),
+ td("-80"),
+ td("dB(m)"),
+ td(img(src:="/assets/images/leds/red-on.svg",width:="16px"))
+ ),
+ tr(
+ td("---"),
+ td(""),
+ td(""),
+ td("")
+ ),
+ tr(
+ td("Charge"),
+ td("4.800"),
+ td("Ah"),
+ td(img(src:="/assets/images/leds/red-off.svg",width:="16px"))
+ ),
+ tr(
+ td("Current"),
+ td("80"),
+ td("A"),
+ td(img(src:="/assets/images/leds/yellow-on.svg",width:="16px"))
+ ),
+ tr(
+ td("Endurance"),
+ td("14"),
+ td("min"),
+ td(img(src:="/assets/images/leds/none.svg",width:="16px"))
+ ),
+ tr(
+ td("GPS"),
+ td("5"),
+ td("satellites"),
+ td(img(src:="/assets/images/leds/none.svg",width:="16px"))
+ )
+ )
+ }
+
+ def autopilot = div(`class` := "btn-group")(
+ button(`type`:="button", `class`:="btn btn-default")("Auto"),
+ button(`type`:="button", `class`:="btn btn-default")("Position"),
+ button(`type`:="button", `class`:="btn btn-default")("Attitude"),
+ button(`type`:="button", `class`:="btn btn-default")(
+ span(`class`:="label label-default")("Manual")
+ )
+ )
+} \ No newline at end of file