summaryrefslogtreecommitdiff
path: root/examples/demos/src/main/scala/advanced/Async.scala
blob: 3d70f274458bf90d61af11b4e9b508635ddb8848 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package advanced

import org.scalajs.dom
import dom.html
import concurrent._
import async.Async._
import scalajs.js.annotation.JSExport
import scalajs.concurrent.JSExecutionContext.Implicits.queue

@JSExport
object Async {
  def init(canvas: html.Canvas) = {
    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: html.Canvas) = {
    val renderer = init(canvas)
    // async
    def rect = canvas.getBoundingClientRect()

    type ME = dom.MouseEvent
    val mousemove =
      new Channel[ME](canvas.onmousemove = _)
    val mouseup =
      new Channel[ME](canvas.onmouseup = _)
    val mousedown =
      new Channel[ME](canvas.onmousedown = _)

    // Disabled due to scala-js#1469
    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: html.Canvas) = {
    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
        )
      }
    }
  }
}

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
  }
}