Reputation: 5844
Based on the paper Deprecating the Observer Pattern with Scala.React I tried to set up a simple example from the paper, but it throwed an exception Exception in thread "main" java.lang.AssertionError: assertion failed: This method must be run on its domain scala.react.NilDebug@1502c065
A related question is Running a simple Scala.React expression.
How do I set up everything to use the great power of the scala react library?
Besides the library scala-react, I used the following example:
object MyFirstReact extends App {
object MyDomain extends scala.react.Domain {
protected val scheduler: Scheduler = new ManualScheduler
protected val engine: Engine = new Engine
}
import MyDomain._
case class MouseEvent(position: (Int, Int))
class Path(var positions: Seq[(Int, Int)]) {
def this(pos: (Int, Int)) = this(Seq(pos))
def lineTo(pos: (Int, Int)) { positions = positions :+ pos }
def close { positions = positions :+ positions.head }
}
val mouseDown: Events[MouseEvent] = Events.once(MouseEvent((0, 0)))
val mouseMove: Events[MouseEvent] = Events.once(MouseEvent((1, 1)))
val mouseUp: Events[MouseEvent] = Events.once(MouseEvent((2, 2)))
def draw(path: Path) { /* ... */ }
Reactor.loop { self =>
// step 1
val path = new Path((self await mouseDown).position)
self.loopUntil(mouseUp) { // step 2
val m = self awaitNext mouseMove
path.lineTo(m.position)
draw(path)
}
path.close // step 3
draw(path)
}
}
Upvotes: 0
Views: 1093
Reputation: 739
You got the exception because Reactor.loop must be wrapped with a schedule { ... } block. But fixing that is not enough (I got an java.lang.StackOverflowError).
Anyhow, I prepared a full working example using a scala-swing in which you can actually draw a line with the very same reactor code that you have. I put a sbt-buildable copy with scala-react included to github: https://github.com/zsoltdonca/scala-react-line-drawing
package zsd
import scala.swing._
import java.awt.event.{MouseMotionAdapter, MouseEvent, MouseAdapter}
import java.awt.{Color, Point}
import scala.react.Domain
object MyDomain extends Domain {
val scheduler = new SwingScheduler()
val engine = new Engine
}
import MyDomain._
object ScalaReactLineDrawing extends SimpleSwingApplication with Observing {
override def main(args: Array[String]) {
schedule { startup(args) }
start() // starts the scala-react engine
}
override def top: Frame = new MainFrame() {
contents = new FlowPanel() {
val mouseDown = EventSource[Point]
val mouseMove = EventSource[Point]
val mouseUp = EventSource[Point]
val mainProgramFlow = Reactor.loop {
self =>
// step 1
val path = new Path(self await mouseDown)
self.loopUntil(mouseUp) {
// step 2
val m = self awaitNext mouseMove
path.lineTo(m)
draw(path)
}
path.close() // step 3
draw(path)
}
peer.addMouseListener(new MouseAdapter {
override def mousePressed(e: MouseEvent): Unit = mouseDown << e.getPoint
override def mouseReleased(e: MouseEvent): Unit = mouseUp << e.getPoint
})
peer.addMouseMotionListener(new MouseMotionAdapter {
override def mouseDragged(e: MouseEvent): Unit = mouseMove << e.getPoint
})
class Path(var positions: Seq[Point]) {
def this(pos: Point) = this(Seq(pos))
def lineTo(pos: Point) {
positions = positions :+ pos
}
def close() {
positions = positions :+ positions.head
}
}
var pathDrawn = new Path(new Point(0, 0))
def draw(path: Path) {
pathDrawn = path
repaint()
}
override protected def paintComponent(g: swing.Graphics2D): Unit = {
super.paintComponent(g)
val xPoints = pathDrawn.positions.map(pos => pos.x).toArray
val yPoints = pathDrawn.positions.map(pos => pos.y).toArray
g.setColor(Color.BLACK)
g.drawPolyline(xPoints, yPoints, pathDrawn.positions.length)
}
}
preferredSize = new Dimension(400, 300)
pack()
}
}
Upvotes: 2