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
|
object Geom {
trait Shape
case class Point(x: Int, y: Int) extends Shape
case class Rectangle(ll: Point, ur: Point) extends Shape {
def inset(delta: Int) =
Rectangle(Point(ll.x - delta, ll.y - delta), Point(ur.x + delta, ur.y + delta));
}
}
object Color {
type Color = Int
val black = 0x000000
val grey = 0x808080
}
trait Screen {
type Color = Int
def drawRect(r: Geom.Rectangle, c: Color): Unit
def fillRect(r: Geom.Rectangle, c: Color): Unit
}
object DummyScreen extends Screen {
def drawRect(r: Geom.Rectangle, c: Color) {
Console.println("draw " + r + " with " + c)
}
def fillRect(r: Geom.Rectangle, c: Color) {
Console.println("fill " + r + " with " + c)
}
}
object GUI {
object Controller {
def addMouseCtl(c: MouseCtl) = ()
}
trait Glyph {
def getRect: Geom.Rectangle
def setLoc(p: Geom.Point): Unit
def draw() { Console.println("draw " + this) }
}
class Label(scr: Screen, p: Geom.Point, name: String) extends Glyph {
private var origin = p
def getRect = Geom.Rectangle(origin, origin).inset(10);
def setLoc(p: Geom.Point) = { origin = p }
}
trait Ctl {
def getGlyph: Glyph
def enable(b: Boolean): this.type
}
trait MouseCtl extends Ctl {
def mouseDown(p: Geom.Point): Unit
}
abstract class Button(scr: Screen, p: Geom.Point, name: String)
extends Glyph with MouseCtl {
var enabled: Boolean = false
val label = new Label(scr, p, name)
/* Glyph methods */
override def draw() {
if (enabled) scr.drawRect(getRect, Color.black)
else scr.fillRect(getRect, Color.grey);
label.draw();
}
def setLoc(p: Geom.Point) = label.setLoc(p);
def getRect = label.getRect.inset(-2);
/* Ctl methods */
def enable(b: Boolean): this.type = { enabled = b; draw(); this }
def getGlyph = label
final def mouseDown(p: Geom.Point) {
if (enabled) doit() else Console.println("button is disabled");
}
/* deferred method to be specified by client */
def doit(): Unit
}
}
object GUIClient {
class App {
def quit() { Console.println("application exited") }
}
class QuitButton (scr: Screen, p: Geom.Point, name: String, a: App)
extends GUI.Button(scr, p, name) {
def doit() { a.quit() }
}
def main(args: Array[String]) {
val b = new QuitButton(
DummyScreen, Geom.Point(1, 1), "quit", new App);
b.draw();
b.enable(true).mouseDown(Geom.Point(1, 2));
}
}
|