summaryrefslogtreecommitdiff
path: root/examples/demos/src/main/scala/advanced/Async.scala
blob: 7a7e5ff233a731f8eb4ba1b10d3f0b40ff3c6cc5 (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
package advanced

import org.scalajs.dom
import concurrent._
import async.Async._
import 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 =
      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: 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
        )
      }
    }
  }
}

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