[GroovyとProcessing]キーボードとマウスからの入力

キーボードからスペース入力で終了、'c'で箱を追加する
マウスの左クリックで箱の選択、ドラッグで箱の移動、右クリックで選択解除、ホイールの回転で箱の色を変更する

動画リスト：[LWJGLのチュートリアル](http://www.youtube.com/playlist?list=PL19F2453814E0E315)
動画は[ココ](http://www.youtube.com/watch?v=EjbOjio_pC4)

```groovy:DisplayTest.groovy
package episode004

import groovy.swing.SwingBuilder
import processing.core.PApplet

import javax.swing.*
import java.awt.event.MouseWheelListener

class DisplayTest extends PApplet {

    def shapes = []
    def somethingIsSelected = false
    def volatile randomColorCooldown = false

    def void setup() {
        frameRate(60)

        addMouseWheelListener({ mwe ->
            mouseWheel(mwe.wheelRotation)
        } as MouseWheelListener)

        shapes << new Box(this, 15, 15)
        shapes << new Box(this, 100, 150)
    }

    def void draw() {
        background(0, 0, 0)

        shapes.each { box ->
            if (box.selected) {
                box.update(mouseX - pmouseX, mouseY - pmouseY)
            }
            box.draw()
        }
    }

    def void keyPressed() {
        switch (key) {
            case ' ':
                System.exit(0)
                break
            case 'c':
                shapes << new Box(this, 15, 15)
                break
        }
    }

    def void mouseClicked() {
        shapes.each { box ->
            selectedBoxUpdate(box)
        }
    }

    def void mouseDragged() {
        shapes.each { box ->
            selectedBoxUpdate(box)
        }
    }

    def mouseWheel(delta) {
        shapes.each { box ->
            if (box.inBounds(mouseX, mouseY) && !somethingIsSelected) {
                box.randomizeColors()
                randomColorCooldown = true
                new Thread({
                    Thread.sleep(200)
                    randomColorCooldown = false
                } as Runnable).run()
            }
        }
    }

    def selectedBoxUpdate(box) {
        switch (mouseButton) {
            case LEFT:
                if (box.inBounds(mouseX, mouseY) && !somethingIsSelected) {
                    somethingIsSelected = true
                    box.selected = true
                }
                break
            case RIGHT:
                somethingIsSelected = false
                box.selected = false
                break
        }
    }

    def static void main(args) {
        def display = new DisplayTest()
        new SwingBuilder().frame(
                title: 'Episode 4',
                defaultCloseOperation: JFrame.EXIT_ON_CLOSE,
                size: [640, 480], show: true) {
            widget(display)
        }
        display.init()
    }
}

class Box {
    def x, y
    def selected = false
    def colorRed,  colorBlue, colorGreen
    def display

    def Box(display, x, y) {
        this.display = display
        this.x = x
        this.y = y

        def randomGenerator = new Random()
        colorRed = randomGenerator.nextInt(256)
        colorBlue = randomGenerator.nextInt(256)
        colorGreen = randomGenerator.nextInt(256)
    }

    def inBounds(mouseX, mouseY) {
        mouseX > x && mouseX < x + 50 && mouseY > y && mouseY < y + 50
    }

    def update(dx, dy) {
        x += dx
        y += dy
    }

    def randomizeColors() {
        def randomGenerator = new Random()
        colorRed = randomGenerator.nextInt(256)
        colorBlue = randomGenerator.nextInt(256)
        colorGreen = randomGenerator.nextInt(256)
    }

    def draw() {
        display.with {
            noStroke()
            fill(colorRed, colorGreen, colorBlue)
            rect(this.x, this.y, 50, 50)
        }
    }
}
```

![grocessingGL004.png](https://qiita-image-store.s3.amazonaws.com/0/17179/03e2c920-0ebc-8acd-f734-7e64a0fefcdf.png)