diff options
Diffstat (limited to 'vfd-frontend/src/main/scala/vfd/frontend/ui')
-rw-r--r-- | vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala | 67 | ||||
-rw-r--r-- | vfd-frontend/src/main/scala/vfd/frontend/ui/Panels.scala | 116 |
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 |