From 7ca2e125c17bd541340bce55623bd40cf88ce64f Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Thu, 20 Nov 2014 02:07:02 -0800 Subject: Scala-async chapter works --- examples/demos/src/main/scala/advanced/Async.scala | 120 +++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 examples/demos/src/main/scala/advanced/Async.scala (limited to 'examples/demos/src/main/scala/advanced/Async.scala') diff --git a/examples/demos/src/main/scala/advanced/Async.scala b/examples/demos/src/main/scala/advanced/Async.scala new file mode 100644 index 0000000..481e80e --- /dev/null +++ b/examples/demos/src/main/scala/advanced/Async.scala @@ -0,0 +1,120 @@ +package advanced + +import org.scalajs.dom +import concurrent._ +import async.Async._ +import scala.scalajs.js.annotation.JSExport +import scalajs.concurrent.JSExecutionContext.Implicits.queue + +@JSExport +object Async { + def init(canvas: dom.HTMLCanvasElement) = { + val renderer = canvas.getContext("2d") + .asInstanceOf[dom.CanvasRenderingContext2D] + + canvas.style.backgroundColor = "#f8f8f8" + canvas.height = canvas.parentElement.clientHeight + canvas.width = canvas.parentElement.clientWidth + + renderer.lineWidth = 5 + renderer.strokeStyle = "red" + renderer.fillStyle = "cyan" + renderer + } + @JSExport + def main(canvas: dom.HTMLCanvasElement) = { + val renderer = init(canvas) + // async + def rect = canvas.getBoundingClientRect() + + type ME = dom.MouseEvent + val mousemove = + Channel[ME](canvas.onmousemove = _) + val mouseup = + Channel[ME](canvas.onmouseup = _) + val mousedown = + Channel[ME](canvas.onmousedown = _) + + async{ + while(true){ + val start = await(mousedown()) + renderer.beginPath() + renderer.moveTo( + start.clientX - rect.left, + start.clientY - rect.top + ) + + var res = await(mousemove | mouseup) + while(res.`type` == "mousemove"){ + renderer.lineTo( + res.clientX - rect.left, + res.clientY - rect.top + ) + renderer.stroke() + res = await(mousemove | mouseup) + } + + renderer.fill() + await(mouseup()) + renderer.clearRect(0, 0, 1000, 1000) + } + } + } + @JSExport + def main0(canvas: dom.HTMLCanvasElement) = { + val renderer = init(canvas) + // traditional + def rect = canvas.getBoundingClientRect() + + var dragState = 0 + + canvas.onmousemove ={(e: dom.MouseEvent) => + if (dragState == 1) { + renderer.lineTo( + e.clientX - rect.left, + e.clientY - rect.top + ) + renderer.stroke() + } + } + canvas.onmouseup = {(e: dom.MouseEvent) => + if(dragState == 1) { + renderer.fill() + dragState = 2 + }else if (dragState == 2){ + renderer.clearRect(0, 0, 1000, 1000) + dragState = 0 + } + } + canvas.onmousedown ={(e: dom.MouseEvent) => + if (dragState == 0) { + dragState = 1 + renderer.beginPath() + renderer.moveTo( + e.clientX - rect.left, + e.clientY - rect.top + ) + } + } + } +} + +case class Channel[T](init: (T => Unit) => Unit){ + init(update) + private[this] var value: Promise[T] = null + def apply(): Future[T] = { + value = Promise[T]() + value.future + } + def update(t: T): Unit = { + if (value != null && !value.isCompleted) value.success(t) + } + def |(other: Channel[T]): Future[T] = { + val p = Promise[T]() + for{ + f <- Seq(other(), this()) + t <- f + } p.trySuccess(t) + p.future + } +} \ No newline at end of file -- cgit v1.2.3