-
Notifications
You must be signed in to change notification settings - Fork 0
/
graphics.rb
148 lines (130 loc) · 2.84 KB
/
graphics.rb
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
extend Gems
def init
@tree = nil
@background = Color.new 255, 190, 220, 250
@black = Color.new 255, 30, 28, 26
@red = Color.new 255, 200, 32, 38
@orange = Color.new 255, 250, 140, 20
@yellow = Color.new 255, 240, 220, 10
@grey = Color.new 255, 130
@brush = Brush.new
@grade = 1
@deepest = 0
@nodelist = []
@zoom = 1.0
@offset = [0.0, 0.0]
@buttons = [[],[]]
redraw
end
def event i, v
if i == "source"
@tree = Fork.new 0,0,true
@tree.me = v
@tree.value = @tree.calc
@deepest = @tree.last
@nodelist = @tree.flatten
@nodelist.flatten!
watch @deepest
redraw
end
end
def draw v
@brush.setColor @background
v.drawRectangle @brush, [0, 0, v.width, v.height]
return if @tree == nil or @nodelist.length == 0
return if @tree.me == ""
radius = 5 * @zoom
center = v.width * 0.5 + @offset[0]
height = radius * 3
line_width = radius * 0.125
@nodelist.each do |node|
interval = 2**(@deepest - node.layer + 1)
offset = 0
if node.layer == 0
interval = 0
offset = 0
else
1.upto(node.layer) do |n|
offset += 2**(@deepest - n)
end
offset *= radius * -1
end
node.x, node.y = center + offset + node.id * (interval * radius), @offset[1] + radius + 0.125 + node.layer * height
if node.from != nil
dx = node.from.x - node.x
dy = node.from.y - node.y
angle = Math.atan2(dy, dx)
x1, y1 = node.x + Math.cos(angle) * radius, node.y + Math.sin(angle) * radius
dx = node.x - node.from.x
dy = node.y - node.from.y
angle = Math.atan2(dy, dx)
x2, y2 = node.from.x + Math.cos(angle) * radius, node.from.y + Math.sin(angle) * radius
pen = Pen.new @grey, line_width
pen.setStartCap "roundanchor"
pen.setEndCap "round"
pen.setLineJoin "round"
#v.drawLine pen, [x2, y2], [x1, y1]
v.drawLine pen, [node.x, node.y - radius * 1.25], [x2, y2]
end
p = method("g" + node.value.to_s).call([node.x, node.y], [0.1875, radius].max)
@brush.setColor case node.me
when "b"
@black
when "o", "m"
@orange
when "r"
@red
when "y", "k"
@yellow
else
@grey
end
v.drawPath @brush, p
end
end
def distance a, b
dx = b[0] - a[0]
dy = b[1] - a[1]
return Math.sqrt(dx**2 + dy**2)
end
def isInMousePoint x, y
true
end
def mouseLDouble
@offset[0, 1] = 0.0, 0.0
redraw
end
def mouseRDouble
@zoom = 1
redraw
end
def mouseLDown x, y
@buttons[0][0] = true
@buttons[0][1, 2] = x, y
captureMouse
end
def mouseRDown x, y
@buttons[1][0] = true
@buttons[1][1] = y
captureMouse
end
def mouseMoveCaptured x, y
if @buttons[1][0]
@zoom += ((y - @buttons[1][1]) * 0.05) * @zoom
@buttons[1][1] = y
redraw
elsif @buttons[0][0]
@offset[0] += (x - @buttons[0][1]) * 0.95
@offset[1] += (y - @buttons[0][2]) * 0.95
@buttons[0][1, 2] = x, y
redraw
end
end
def mouseLUp x, y
@buttons[0][0] = false
releaseMouse
end
def mouseRUp x, y
@buttons[1][0] = false
releaseMouse
end