wads 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +9 -3
- data/lib/wads/app.rb +91 -66
- data/lib/wads/data_structures.rb +281 -12
- data/lib/wads/textinput.rb +49 -4
- data/lib/wads/version.rb +1 -1
- data/lib/wads/widgets.rb +656 -207
- data/media/WadsScreenshot.png +0 -0
- data/sample_app.rb +9 -3
- metadata +3 -2
data/lib/wads/textinput.rb
CHANGED
@@ -9,13 +9,17 @@ class TextField < Gosu::TextInput
|
|
9
9
|
PADDING = 5
|
10
10
|
|
11
11
|
attr_reader :x, :y
|
12
|
+
attr_accessor :base_z
|
13
|
+
attr_accessor :old_value
|
12
14
|
|
13
15
|
def initialize(window, font, x, y, original_text, default_width)
|
14
16
|
super()
|
15
17
|
|
16
18
|
@window, @font, @x, @y = window, font, x, y
|
17
19
|
@default_width = default_width
|
20
|
+
@base_z = 0
|
18
21
|
self.text = original_text
|
22
|
+
@old_value = self.text
|
19
23
|
end
|
20
24
|
|
21
25
|
def draw
|
@@ -29,7 +33,7 @@ class TextField < Gosu::TextInput
|
|
29
33
|
@window.draw_quad(x - PADDING, y - PADDING, background_color,
|
30
34
|
x + width + PADDING, y - PADDING, background_color,
|
31
35
|
x - PADDING, y + height + PADDING, background_color,
|
32
|
-
x + width + PADDING, y + height + PADDING, background_color, 9)
|
36
|
+
x + width + PADDING, y + height + PADDING, background_color, @base_z + 9)
|
33
37
|
|
34
38
|
# Calculate the position of the caret and the selection start.
|
35
39
|
pos_x = x + @font.text_width(self.text[0...self.caret_pos])
|
@@ -40,16 +44,16 @@ class TextField < Gosu::TextInput
|
|
40
44
|
@window.draw_quad(sel_x, y, SELECTION_COLOR,
|
41
45
|
pos_x, y, SELECTION_COLOR,
|
42
46
|
sel_x, y + height, SELECTION_COLOR,
|
43
|
-
pos_x, y + height, SELECTION_COLOR,
|
47
|
+
pos_x, y + height, SELECTION_COLOR, @base_z + 10)
|
44
48
|
|
45
49
|
# Draw the caret; again, only if this is the currently selected field.
|
46
50
|
if @window.text_input == self then
|
47
51
|
@window.draw_line(pos_x, y, CARET_COLOR,
|
48
|
-
pos_x, y + height, CARET_COLOR,
|
52
|
+
pos_x, y + height, CARET_COLOR, @base_z + 10)
|
49
53
|
end
|
50
54
|
|
51
55
|
# Finally, draw the text itself!
|
52
|
-
@font.draw_text(self.text, x, y,
|
56
|
+
@font.draw_text(self.text, x, y, @base_z + 10)
|
53
57
|
end
|
54
58
|
|
55
59
|
# This text field grows with the text that's being entered.
|
@@ -71,6 +75,10 @@ class TextField < Gosu::TextInput
|
|
71
75
|
mouse_x > x - PADDING and mouse_x < x + width + PADDING and
|
72
76
|
mouse_y > y - PADDING and mouse_y < y + height + PADDING
|
73
77
|
end
|
78
|
+
|
79
|
+
def contains_click(mouse_x, mouse_y)
|
80
|
+
under_point?(mouse_x, mouse_y)
|
81
|
+
end
|
74
82
|
|
75
83
|
# Tries to move the caret to the position specifies by mouse_x
|
76
84
|
def move_caret(mouse_x)
|
@@ -84,4 +92,41 @@ class TextField < Gosu::TextInput
|
|
84
92
|
# Default case: user must have clicked the right edge
|
85
93
|
self.caret_pos = self.selection_start = self.text.length
|
86
94
|
end
|
95
|
+
|
96
|
+
def button_down(id, mouse_x, mouse_y)
|
97
|
+
if id == Gosu::MsLeft
|
98
|
+
move_caret(mouse_x)
|
99
|
+
else
|
100
|
+
if @old_value == self.text
|
101
|
+
# nothing to do
|
102
|
+
else
|
103
|
+
@old_value = self.text
|
104
|
+
return WidgetResult.new(false, EVENT_TEXT_INPUT, [self.text])
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def button_up(id, mouse_x, mouse_y)
|
110
|
+
# empty base implementation
|
111
|
+
end
|
112
|
+
|
113
|
+
def update(update_count, mouse_x, mouse_y)
|
114
|
+
# empty base implementation
|
115
|
+
end
|
116
|
+
|
117
|
+
def handle_mouse_down mouse_x, mouse_y
|
118
|
+
# empty base implementation
|
119
|
+
end
|
120
|
+
|
121
|
+
def handle_mouse_up mouse_x, mouse_y
|
122
|
+
# empty base implementation
|
123
|
+
end
|
124
|
+
|
125
|
+
def handle_key_press id, mouse_x, mouse_y
|
126
|
+
# empty base implementation
|
127
|
+
end
|
128
|
+
|
129
|
+
def handle_update update_count, mouse_x, mouse_y
|
130
|
+
# empty base implementation
|
131
|
+
end
|
87
132
|
end
|
data/lib/wads/version.rb
CHANGED
data/lib/wads/widgets.rb
CHANGED
@@ -29,25 +29,33 @@ module Wads
|
|
29
29
|
COLOR_ERROR_CODE_RED = Gosu::Color.argb(0xffe6b0aa)
|
30
30
|
|
31
31
|
Z_ORDER_BACKGROUND = 2
|
32
|
-
|
32
|
+
Z_ORDER_BORDER = 3
|
33
33
|
Z_ORDER_SELECTION_BACKGROUND = 4
|
34
34
|
Z_ORDER_GRAPHIC_ELEMENTS = 5
|
35
35
|
Z_ORDER_PLOT_POINTS = 6
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
Z_ORDER_FOCAL_ELEMENTS = 8
|
37
|
+
Z_ORDER_TEXT = 9
|
38
|
+
|
39
|
+
EVENT_OK = "ok"
|
40
|
+
EVENT_TEXT_INPUT = "textinput"
|
41
|
+
EVENT_TABLE_SELECT = "tableselect"
|
42
|
+
EVENT_TABLE_UNSELECT = "tableunselect"
|
43
|
+
EVENT_TABLE_ROW_DELETE = "tablerowdelete"
|
39
44
|
|
40
45
|
class Widget
|
41
46
|
attr_accessor :x
|
42
47
|
attr_accessor :y
|
48
|
+
attr_accessor :base_z
|
43
49
|
attr_accessor :color
|
50
|
+
attr_accessor :background_color
|
51
|
+
attr_accessor :border_color
|
44
52
|
attr_accessor :width
|
45
53
|
attr_accessor :height
|
46
54
|
attr_accessor :visible
|
47
|
-
attr_accessor :children
|
48
|
-
attr_accessor :background_color
|
49
|
-
attr_accessor :border_color
|
50
55
|
attr_accessor :font
|
56
|
+
attr_accessor :children
|
57
|
+
attr_accessor :overlay_widget
|
58
|
+
attr_accessor :debug_off
|
51
59
|
|
52
60
|
def initialize(x, y, color = COLOR_CYAN)
|
53
61
|
@x = x
|
@@ -57,12 +65,26 @@ module Wads
|
|
57
65
|
@height = 1
|
58
66
|
@visible = true
|
59
67
|
@children = []
|
68
|
+
@base_z = 0
|
69
|
+
@debug_off = true
|
70
|
+
end
|
71
|
+
|
72
|
+
def z_order
|
73
|
+
@base_z + widget_z
|
74
|
+
end
|
75
|
+
|
76
|
+
def relative_z_order(relative_order)
|
77
|
+
@base_z + relative_order
|
60
78
|
end
|
61
79
|
|
62
80
|
def add_child(child)
|
63
81
|
@children << child
|
64
82
|
end
|
65
83
|
|
84
|
+
def remove_child(child)
|
85
|
+
@children.delete(child)
|
86
|
+
end
|
87
|
+
|
66
88
|
def clear_children
|
67
89
|
@children = []
|
68
90
|
end
|
@@ -79,6 +101,10 @@ module Wads
|
|
79
101
|
@font = font
|
80
102
|
end
|
81
103
|
|
104
|
+
def set_color(color)
|
105
|
+
@color = color
|
106
|
+
end
|
107
|
+
|
82
108
|
def set_dimensions(width, height)
|
83
109
|
@width = width
|
84
110
|
@height = height
|
@@ -115,22 +141,21 @@ module Wads
|
|
115
141
|
end
|
116
142
|
end
|
117
143
|
|
118
|
-
def draw_background(
|
119
|
-
|
144
|
+
def draw_background(z_override = nil)
|
145
|
+
if z_override
|
146
|
+
z = relative_z_order(z_override)
|
147
|
+
else
|
148
|
+
z = relative_z_order(Z_ORDER_BACKGROUND)
|
149
|
+
end
|
150
|
+
Gosu::draw_rect(@x + 1, @y + 1, @width - 3, @height - 3, @background_color, z)
|
120
151
|
end
|
121
152
|
|
122
|
-
def draw_shadow(color
|
123
|
-
Gosu::draw_line @x - 1, @y - 1, color, right_edge - 1, @y - 1, color,
|
124
|
-
Gosu::draw_line @x - 1, @y - 1, color, @x - 1, bottom_edge - 1, color,
|
153
|
+
def draw_shadow(color)
|
154
|
+
Gosu::draw_line @x - 1, @y - 1, color, right_edge - 1, @y - 1, color, relative_z_order(Z_ORDER_BORDER)
|
155
|
+
Gosu::draw_line @x - 1, @y - 1, color, @x - 1, bottom_edge - 1, color, relative_z_order(Z_ORDER_BORDER)
|
125
156
|
end
|
126
157
|
|
127
|
-
def
|
128
|
-
# Base implementation is empty
|
129
|
-
# Note that the draw method invoked by clients stills renders any added children
|
130
|
-
# render is for specific drawing done by the widget
|
131
|
-
end
|
132
|
-
|
133
|
-
def draw_border(color = nil, zorder = Z_ORDER_WIDGET_BORDER)
|
158
|
+
def draw_border(color = nil)
|
134
159
|
if color.nil?
|
135
160
|
if @border_color
|
136
161
|
color = @border_color
|
@@ -138,27 +163,234 @@ module Wads
|
|
138
163
|
color = @color
|
139
164
|
end
|
140
165
|
end
|
141
|
-
Gosu::draw_line @x, @y, color, right_edge, @y, color,
|
142
|
-
Gosu::draw_line @x, @y, color, @x, bottom_edge, color,
|
143
|
-
Gosu::draw_line @x,bottom_edge, color, right_edge, bottom_edge, color,
|
144
|
-
Gosu::draw_line right_edge, @y, color, right_edge, bottom_edge, color,
|
166
|
+
Gosu::draw_line @x, @y, color, right_edge, @y, color, relative_z_order(Z_ORDER_BORDER)
|
167
|
+
Gosu::draw_line @x, @y, color, @x, bottom_edge, color, relative_z_order(Z_ORDER_BORDER)
|
168
|
+
Gosu::draw_line @x,bottom_edge, color, right_edge, bottom_edge, color, relative_z_order(Z_ORDER_BORDER)
|
169
|
+
Gosu::draw_line right_edge, @y, color, right_edge, bottom_edge, color, relative_z_order(Z_ORDER_BORDER)
|
145
170
|
end
|
146
171
|
|
147
172
|
def contains_click(mouse_x, mouse_y)
|
148
173
|
mouse_x >= @x and mouse_x <= right_edge and mouse_y >= @y and mouse_y <= bottom_edge
|
149
174
|
end
|
150
175
|
|
151
|
-
def update
|
176
|
+
def update(update_count, mouse_x, mouse_y)
|
177
|
+
if @overlay_widget
|
178
|
+
@overlay_widget.update(update_count, mouse_x, mouse_y)
|
179
|
+
end
|
180
|
+
handle_update(update_count, mouse_x, mouse_y)
|
181
|
+
@children.each do |child|
|
182
|
+
child.update(update_count, mouse_x, mouse_y)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def button_down(id, mouse_x, mouse_y)
|
187
|
+
puts "Base widget #{self.class.name} button down #{id}." unless @debug_off
|
188
|
+
if @overlay_widget
|
189
|
+
result = @overlay_widget.button_down(id, mouse_x, mouse_y)
|
190
|
+
if not result.nil? and result.is_a? WidgetResult
|
191
|
+
intercept_widget_event(result)
|
192
|
+
if result.close_widget
|
193
|
+
# remove the overlay widget frmo children, set to null
|
194
|
+
# hopefully this closes and gets us back to normal
|
195
|
+
remove_child(@overlay_widget)
|
196
|
+
@overlay_widget = nil
|
197
|
+
end
|
198
|
+
end
|
199
|
+
return
|
200
|
+
end
|
201
|
+
|
202
|
+
if id == Gosu::MsLeft
|
203
|
+
result = handle_mouse_down mouse_x, mouse_y
|
204
|
+
elsif id == Gosu::MsRight
|
205
|
+
result = handle_right_mouse mouse_x, mouse_y
|
206
|
+
else
|
207
|
+
result = handle_key_press id, mouse_x, mouse_y
|
208
|
+
end
|
209
|
+
|
210
|
+
if not result.nil? and result.is_a? WidgetResult
|
211
|
+
puts "Base widget #{self.class.name} returning own #{result}" unless @debug_off
|
212
|
+
return result
|
213
|
+
end
|
214
|
+
|
215
|
+
@children.each do |child|
|
216
|
+
if id == Gosu::MsLeft
|
217
|
+
if child.contains_click(mouse_x, mouse_y)
|
218
|
+
result = child.button_down id, mouse_x, mouse_y
|
219
|
+
if not result.nil? and result.is_a? WidgetResult
|
220
|
+
intercept_widget_event(result)
|
221
|
+
puts "Base widget #{self.class.name} returning child #{result}" unless @debug_off
|
222
|
+
return result
|
223
|
+
end
|
224
|
+
end
|
225
|
+
else
|
226
|
+
result = child.button_down id, mouse_x, mouse_y
|
227
|
+
if not result.nil? and result.is_a? WidgetResult
|
228
|
+
intercept_widget_event(result)
|
229
|
+
puts "Base widget #{self.class.name} returning child #{result}" unless @debug_off
|
230
|
+
return result
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def button_up(id, mouse_x, mouse_y)
|
237
|
+
if @overlay_widget
|
238
|
+
return @overlay_widget.button_up(id, mouse_x, mouse_y)
|
239
|
+
end
|
240
|
+
|
241
|
+
if id == Gosu::MsLeft
|
242
|
+
result = handle_mouse_up mouse_x, mouse_y
|
243
|
+
if not result.nil? and result.is_a? WidgetResult
|
244
|
+
return result
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
@children.each do |child|
|
249
|
+
if id == Gosu::MsLeft
|
250
|
+
if child.contains_click(mouse_x, mouse_y)
|
251
|
+
result = child.handle_mouse_up mouse_x, mouse_y
|
252
|
+
if not result.nil? and result.is_a? WidgetResult
|
253
|
+
return result
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def x_pixel_to_screen(x)
|
261
|
+
@x + x
|
262
|
+
end
|
263
|
+
|
264
|
+
def y_pixel_to_screen(y)
|
265
|
+
@y + y
|
266
|
+
end
|
267
|
+
|
268
|
+
def add_text(message, rel_x, rel_y)
|
269
|
+
new_text = Text.new(message, x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y), @font)
|
270
|
+
new_text.base_z = @base_z
|
271
|
+
add_child(new_text)
|
272
|
+
new_text
|
273
|
+
end
|
274
|
+
|
275
|
+
def add_document(content, rel_x, rel_y, width, height)
|
276
|
+
new_doc = Document.new(content, x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y), width, height, @font)
|
277
|
+
new_doc.base_z = @base_z
|
278
|
+
add_child(new_doc)
|
279
|
+
new_doc
|
280
|
+
end
|
281
|
+
|
282
|
+
def add_button(label, rel_x, rel_y, width = nil, &block)
|
283
|
+
new_button = Button.new(label, x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y), @font)
|
284
|
+
if width.nil?
|
285
|
+
width = 60
|
286
|
+
end
|
287
|
+
new_button.width = width
|
288
|
+
new_button.set_action(&block)
|
289
|
+
new_button.base_z = @base_z
|
290
|
+
add_child(new_button)
|
291
|
+
new_button
|
292
|
+
end
|
293
|
+
|
294
|
+
def add_delete_button(rel_x, rel_y, &block)
|
295
|
+
new_delete_button = DeleteButton.new(x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y))
|
296
|
+
new_delete_button.set_action(&block)
|
297
|
+
new_delete_button.base_z = @base_z
|
298
|
+
add_child(new_delete_button)
|
299
|
+
new_delete_button
|
300
|
+
end
|
301
|
+
|
302
|
+
def add_table(rel_x, rel_y, width, height, column_headers, color = COLOR_WHITE, max_visible_rows = 10)
|
303
|
+
new_table = Table.new(x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y),
|
304
|
+
width, height, column_headers, @font, color, max_visible_rows)
|
305
|
+
new_table.base_z = @base_z
|
306
|
+
add_child(new_table)
|
307
|
+
new_table
|
308
|
+
end
|
309
|
+
|
310
|
+
def add_single_select_table(rel_x, rel_y, width, height, column_headers, color = COLOR_WHITE, max_visible_rows = 10)
|
311
|
+
new_table = SingleSelectTable.new(x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y),
|
312
|
+
width, height, column_headers, @font, color, max_visible_rows)
|
313
|
+
new_table.base_z = @base_z
|
314
|
+
add_child(new_table)
|
315
|
+
new_table
|
316
|
+
end
|
317
|
+
|
318
|
+
def add_multi_select_table(rel_x, rel_y, width, height, column_headers, color = COLOR_WHITE, max_visible_rows = 10)
|
319
|
+
new_table = MultiSelectTable.new(x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y),
|
320
|
+
width, height, column_headers, @font, color, max_visible_rows)
|
321
|
+
new_table.base_z = @base_z
|
322
|
+
add_child(new_table)
|
323
|
+
new_table
|
324
|
+
end
|
325
|
+
|
326
|
+
def add_graph_display(rel_x, rel_y, width, height, graph)
|
327
|
+
new_graph = GraphWidget.new(x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y), width, height, @font, @color, graph)
|
328
|
+
new_graph.base_z = @base_z
|
329
|
+
add_child(new_graph)
|
330
|
+
new_graph
|
331
|
+
end
|
332
|
+
|
333
|
+
def add_plot(rel_x, rel_y, width, height)
|
334
|
+
new_plot = Plot.new(x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y), width, height, @font)
|
335
|
+
new_plot.base_z = @base_z
|
336
|
+
add_child(new_plot)
|
337
|
+
new_plot
|
338
|
+
end
|
339
|
+
|
340
|
+
def add_axis_lines(rel_x, rel_y, width, height, color)
|
341
|
+
new_axis_lines = AxisLines.new(x_pixel_to_screen(rel_x), y_pixel_to_screen(rel_y), width, height, color)
|
342
|
+
new_axis_lines.base_z = @base_z
|
343
|
+
add_child(new_axis_lines)
|
344
|
+
new_axis_lines
|
345
|
+
end
|
346
|
+
|
347
|
+
def add_overlay(overlay)
|
348
|
+
overlay.base_z = @base_z + 10
|
349
|
+
add_child(overlay)
|
350
|
+
@overlay_widget = overlay
|
351
|
+
end
|
352
|
+
|
353
|
+
#
|
354
|
+
# Callbacks for subclasses to override
|
355
|
+
#
|
356
|
+
def handle_mouse_down mouse_x, mouse_y
|
357
|
+
# empty base implementation
|
358
|
+
end
|
359
|
+
|
360
|
+
def handle_mouse_up mouse_x, mouse_y
|
361
|
+
# empty base implementation
|
362
|
+
end
|
363
|
+
|
364
|
+
def handle_right_mouse mouse_x, mouse_y
|
152
365
|
# empty base implementation
|
153
366
|
end
|
154
367
|
|
155
|
-
def
|
368
|
+
def handle_key_press id, mouse_x, mouse_y
|
156
369
|
# empty base implementation
|
157
370
|
end
|
158
371
|
|
159
|
-
def
|
372
|
+
def handle_update update_count, mouse_x, mouse_y
|
160
373
|
# empty base implementation
|
161
374
|
end
|
375
|
+
|
376
|
+
def render
|
377
|
+
# Base implementation is empty
|
378
|
+
# Note that the draw method invoked by clients stills renders any added children
|
379
|
+
# render is for specific drawing done by the widget
|
380
|
+
end
|
381
|
+
|
382
|
+
def widget_z
|
383
|
+
# The relative z order compared to other widgets
|
384
|
+
# The absolute z order is the base plus this value.
|
385
|
+
# Its calculated relative so that overlay widgets can be
|
386
|
+
# on top of base displays.
|
387
|
+
0
|
388
|
+
end
|
389
|
+
|
390
|
+
def intercept_widget_event(result)
|
391
|
+
# Base implementation just relays the event
|
392
|
+
result
|
393
|
+
end
|
162
394
|
end
|
163
395
|
|
164
396
|
class Text < Widget
|
@@ -169,7 +401,10 @@ module Wads
|
|
169
401
|
@str = str
|
170
402
|
end
|
171
403
|
def render
|
172
|
-
@font.draw_text(@str, @x, @y,
|
404
|
+
@font.draw_text(@str, @x, @y, z_order, 1, 1, @color)
|
405
|
+
end
|
406
|
+
def widget_z
|
407
|
+
Z_ORDER_TEXT
|
173
408
|
end
|
174
409
|
end
|
175
410
|
|
@@ -182,20 +417,32 @@ module Wads
|
|
182
417
|
end
|
183
418
|
|
184
419
|
class PlotPoint < Widget
|
420
|
+
attr_accessor :data_x
|
421
|
+
attr_accessor :data_y
|
185
422
|
attr_accessor :data_point_size
|
186
423
|
|
187
|
-
def initialize(x, y, color = COLOR_MAROON, size = 4)
|
188
|
-
super(x, y, color)
|
424
|
+
def initialize(x, y, data_x, data_y, color = COLOR_MAROON, size = 4)
|
425
|
+
super(x, y, color)
|
426
|
+
@data_x = data_x
|
427
|
+
@data_y = data_y
|
189
428
|
@data_point_size = size
|
190
429
|
end
|
191
430
|
|
192
|
-
def render
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
431
|
+
def render(override_size = nil)
|
432
|
+
size_to_draw = @data_point_size
|
433
|
+
if override_size
|
434
|
+
size_to_draw = override_size
|
435
|
+
end
|
436
|
+
half_size = size_to_draw / 2
|
437
|
+
Gosu::draw_rect(@x - half_size, @y - half_size,
|
438
|
+
size_to_draw, size_to_draw,
|
439
|
+
@color, z_order)
|
197
440
|
end
|
198
441
|
|
442
|
+
def widget_z
|
443
|
+
Z_ORDER_PLOT_POINTS
|
444
|
+
end
|
445
|
+
|
199
446
|
def to_display
|
200
447
|
"#{@x}, #{@y}"
|
201
448
|
end
|
@@ -213,7 +460,9 @@ module Wads
|
|
213
460
|
|
214
461
|
class Button < Widget
|
215
462
|
attr_accessor :label
|
463
|
+
attr_accessor :text_color
|
216
464
|
attr_accessor :is_pressed
|
465
|
+
attr_accessor :action_code
|
217
466
|
|
218
467
|
def initialize(label, x, y, font, width = nil, color = COLOR_DARK_GRAY, text_color = COLOR_HEADER_BRIGHT_BLUE)
|
219
468
|
super(x, y, color)
|
@@ -226,14 +475,59 @@ module Wads
|
|
226
475
|
@width = width
|
227
476
|
end
|
228
477
|
@height = 26
|
229
|
-
@is_pressed = false
|
230
478
|
@text_color = text_color
|
479
|
+
@is_pressed = false
|
480
|
+
@is_pressed_update_count = -100
|
231
481
|
end
|
232
482
|
|
233
483
|
def render
|
234
484
|
draw_border(@color)
|
235
485
|
text_x = center_x - (@text_pixel_width / 2)
|
236
|
-
@font.draw_text(@label, text_x, @y,
|
486
|
+
@font.draw_text(@label, text_x, @y, z_order, 1, 1, @text_color)
|
487
|
+
end
|
488
|
+
|
489
|
+
def widget_z
|
490
|
+
Z_ORDER_TEXT
|
491
|
+
end
|
492
|
+
|
493
|
+
def set_action(&block)
|
494
|
+
@action_code = block
|
495
|
+
end
|
496
|
+
|
497
|
+
def handle_mouse_down mouse_x, mouse_y
|
498
|
+
@is_pressed = true
|
499
|
+
if @action_code
|
500
|
+
@action_code.call
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
def handle_update update_count, mouse_x, mouse_y
|
505
|
+
if @is_pressed
|
506
|
+
@is_pressed_update_count = update_count
|
507
|
+
@is_pressed = false
|
508
|
+
end
|
509
|
+
|
510
|
+
if update_count < @is_pressed_update_count + 15
|
511
|
+
set_background(nil)
|
512
|
+
elsif contains_click(mouse_x, mouse_y)
|
513
|
+
set_background(COLOR_LIGHT_GRAY)
|
514
|
+
else
|
515
|
+
set_background(nil)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
class DeleteButton < Button
|
521
|
+
def initialize(x, y)
|
522
|
+
super("ignore", x, y, Gosu::Font.new(22), 50, COLOR_GRAY)
|
523
|
+
set_dimensions(14, 14)
|
524
|
+
add_child(Line.new(@x, @y, right_edge, bottom_edge, COLOR_ERROR_CODE_RED))
|
525
|
+
add_child(Line.new(@x, bottom_edge, right_edge, @y, COLOR_ERROR_CODE_RED))
|
526
|
+
set_border(@color)
|
527
|
+
end
|
528
|
+
|
529
|
+
def render
|
530
|
+
# do nothing, just override the parent so we don't draw a label
|
237
531
|
end
|
238
532
|
end
|
239
533
|
|
@@ -250,10 +544,14 @@ module Wads
|
|
250
544
|
def render
|
251
545
|
y = @y + 4
|
252
546
|
@lines.each do |line|
|
253
|
-
@font.draw_text(line, @x + 5, y,
|
547
|
+
@font.draw_text(line, @x + 5, y, z_order, 1, 1, COLOR_WHITE)
|
254
548
|
y = y + 26
|
255
549
|
end
|
256
550
|
end
|
551
|
+
|
552
|
+
def widget_z
|
553
|
+
Z_ORDER_TEXT
|
554
|
+
end
|
257
555
|
end
|
258
556
|
|
259
557
|
class InfoBox < Widget
|
@@ -262,24 +560,22 @@ module Wads
|
|
262
560
|
set_font(font)
|
263
561
|
set_dimensions(width, height)
|
264
562
|
set_border(COLOR_WHITE)
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
563
|
+
set_background(COLOR_OFF_GRAY)
|
564
|
+
@base_z = 10
|
565
|
+
add_text(title, 5, 5)
|
566
|
+
add_document(content, 5, 52, width, height - 52)
|
567
|
+
ok_button = add_button("OK", (@width / 2) - 50, height - 26) do
|
568
|
+
WidgetResult.new(true)
|
569
|
+
end
|
570
|
+
ok_button.text_color = COLOR_WHITE
|
571
|
+
ok_button.width = 100
|
271
572
|
end
|
272
573
|
|
273
|
-
def
|
574
|
+
def handle_key_press id, mouse_x, mouse_y
|
274
575
|
if id == Gosu::KbEscape
|
275
576
|
return WidgetResult.new(true)
|
276
|
-
elsif id == Gosu::MsLeft
|
277
|
-
if @ok_button.contains_click(mouse_x, mouse_y)
|
278
|
-
return WidgetResult.new(true)
|
279
|
-
end
|
280
577
|
end
|
281
|
-
|
282
|
-
end
|
578
|
+
end
|
283
579
|
end
|
284
580
|
|
285
581
|
class Dialog < Widget
|
@@ -290,23 +586,34 @@ module Wads
|
|
290
586
|
@window = window
|
291
587
|
set_font(font)
|
292
588
|
set_dimensions(width, height)
|
293
|
-
set_background(
|
589
|
+
set_background(COLOR_OFF_GRAY)
|
294
590
|
set_border(COLOR_WHITE)
|
591
|
+
@base_z = 10
|
295
592
|
@error_message = nil
|
296
593
|
|
297
|
-
|
594
|
+
add_text(title, 5, 5)
|
298
595
|
# Forms automatically have some explanatory content
|
299
|
-
|
596
|
+
add_document(content, 0, 56, width, height)
|
300
597
|
|
301
598
|
# Forms automatically get a text input widget
|
302
599
|
@textinput = TextField.new(@window, @font, x + 10, bottom_edge - 80, text_input_default, 600)
|
600
|
+
@textinput.base_z = 10
|
303
601
|
add_child(@textinput)
|
304
602
|
|
305
603
|
# Forms automatically get OK and Cancel buttons
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
604
|
+
ok_button = add_button("OK", (@width / 2) - 100, height - 32) do
|
605
|
+
handle_ok
|
606
|
+
end
|
607
|
+
ok_button.color = COLOR_FORM_BUTTON
|
608
|
+
ok_button.text_color = COLOR_WHITE
|
609
|
+
ok_button.width = 100
|
610
|
+
|
611
|
+
cancel_button = add_button("Cancel", (@width / 2) + 50, height - 32) do
|
612
|
+
WidgetResult.new(true)
|
613
|
+
end
|
614
|
+
cancel_button.color = COLOR_FORM_BUTTON
|
615
|
+
cancel_button.text_color = COLOR_WHITE
|
616
|
+
cancel_button.width = 100
|
310
617
|
end
|
311
618
|
|
312
619
|
def content
|
@@ -318,6 +625,7 @@ module Wads
|
|
318
625
|
|
319
626
|
def add_error_message(msg)
|
320
627
|
@error_message = ErrorMessage.new(msg, x + 10, bottom_edge - 120, @font)
|
628
|
+
@error_message.base_z = @base_z
|
321
629
|
end
|
322
630
|
|
323
631
|
def render
|
@@ -329,21 +637,7 @@ module Wads
|
|
329
637
|
def handle_ok
|
330
638
|
# Default behavior is to do nothing except tell the caller to
|
331
639
|
# close the dialog
|
332
|
-
return WidgetResult.new(true)
|
333
|
-
end
|
334
|
-
|
335
|
-
def handle_cancel
|
336
|
-
# Default behavior is to do nothing except tell the caller to
|
337
|
-
# close the dialog
|
338
|
-
return WidgetResult.new(true)
|
339
|
-
end
|
340
|
-
|
341
|
-
def handle_up(mouse_x, mouse_y)
|
342
|
-
# empty implementation of up arrow
|
343
|
-
end
|
344
|
-
|
345
|
-
def handle_down(mouse_x, mouse_y)
|
346
|
-
# empty implementation of down arrow
|
640
|
+
return WidgetResult.new(true, EVENT_OK)
|
347
641
|
end
|
348
642
|
|
349
643
|
def handle_mouse_click(mouse_x, mouse_y)
|
@@ -351,37 +645,19 @@ module Wads
|
|
351
645
|
# of standard form elements in this dialog
|
352
646
|
end
|
353
647
|
|
354
|
-
def
|
355
|
-
#
|
356
|
-
|
648
|
+
def handle_mouse_down mouse_x, mouse_y
|
649
|
+
# Mouse click: Select text field based on mouse position.
|
650
|
+
@window.text_input = [@textinput].find { |tf| tf.under_point?(mouse_x, mouse_y) }
|
651
|
+
# Advanced: Move caret to clicked position
|
652
|
+
@window.text_input.move_caret(mouse_x) unless @window.text_input.nil?
|
653
|
+
|
654
|
+
handle_mouse_click(mouse_x, mouse_y)
|
357
655
|
end
|
358
656
|
|
359
|
-
def
|
657
|
+
def handle_key_press id, mouse_x, mouse_y
|
360
658
|
if id == Gosu::KbEscape
|
361
659
|
return WidgetResult.new(true)
|
362
|
-
elsif id == Gosu::KbUp
|
363
|
-
handle_up(mouse_x, mouse_y)
|
364
|
-
elsif id == Gosu::KbDown
|
365
|
-
handle_down(mouse_x, mouse_y)
|
366
|
-
elsif id == Gosu::MsLeft
|
367
|
-
if @ok_button.contains_click(mouse_x, mouse_y)
|
368
|
-
return handle_ok
|
369
|
-
elsif @cancel_button.contains_click(mouse_x, mouse_y)
|
370
|
-
return handle_cancel
|
371
|
-
else
|
372
|
-
# Mouse click: Select text field based on mouse position.
|
373
|
-
@window.text_input = [@textinput].find { |tf| tf.under_point?(mouse_x, mouse_y) }
|
374
|
-
# Advanced: Move caret to clicked position
|
375
|
-
@window.text_input.move_caret(mouse_x) unless @window.text_input.nil?
|
376
|
-
|
377
|
-
handle_mouse_click(mouse_x, mouse_y)
|
378
|
-
end
|
379
|
-
else
|
380
|
-
if @window.text_input
|
381
|
-
text_input_updated(@textinput.text)
|
382
|
-
end
|
383
660
|
end
|
384
|
-
WidgetResult.new(false)
|
385
661
|
end
|
386
662
|
end
|
387
663
|
|
@@ -408,7 +684,11 @@ module Wads
|
|
408
684
|
end
|
409
685
|
|
410
686
|
def render
|
411
|
-
Gosu::draw_line x, y, @color, x2, y2, @color,
|
687
|
+
Gosu::draw_line x, y, @color, x2, y2, @color, z_order
|
688
|
+
end
|
689
|
+
|
690
|
+
def widget_z
|
691
|
+
Z_ORDER_GRAPHIC_ELEMENTS
|
412
692
|
end
|
413
693
|
end
|
414
694
|
|
@@ -437,10 +717,14 @@ module Wads
|
|
437
717
|
def render
|
438
718
|
text_pixel_width = @font.text_width(@label)
|
439
719
|
Gosu::draw_line @x - 20, @y, @color,
|
440
|
-
@x, @y, @color,
|
720
|
+
@x, @y, @color, z_order
|
441
721
|
|
442
722
|
@font.draw_text(@label, @x - text_pixel_width - 28, @y - 12, 1, 1, 1, @color)
|
443
723
|
end
|
724
|
+
|
725
|
+
def widget_z
|
726
|
+
Z_ORDER_GRAPHIC_ELEMENTS
|
727
|
+
end
|
444
728
|
end
|
445
729
|
|
446
730
|
class HorizontalAxisLabel < Widget
|
@@ -455,7 +739,11 @@ module Wads
|
|
455
739
|
def render
|
456
740
|
text_pixel_width = @font.text_width(@label)
|
457
741
|
Gosu::draw_line @x, @y, @color, @x, @y + 20, @color
|
458
|
-
@font.draw_text(@label, @x - (text_pixel_width / 2), @y + 26,
|
742
|
+
@font.draw_text(@label, @x - (text_pixel_width / 2), @y + 26, z_order, 1, 1, @color)
|
743
|
+
end
|
744
|
+
|
745
|
+
def widget_z
|
746
|
+
Z_ORDER_TEXT
|
459
747
|
end
|
460
748
|
end
|
461
749
|
|
@@ -465,6 +753,7 @@ module Wads
|
|
465
753
|
attr_accessor :headers
|
466
754
|
attr_accessor :max_visible_rows
|
467
755
|
attr_accessor :current_row
|
756
|
+
attr_accessor :can_delete_rows
|
468
757
|
|
469
758
|
def initialize(x, y, width, height, headers, font, color = COLOR_GRAY, max_visible_rows = 10)
|
470
759
|
super(x, y, color)
|
@@ -473,7 +762,10 @@ module Wads
|
|
473
762
|
@headers = headers
|
474
763
|
@current_row = 0
|
475
764
|
@max_visible_rows = max_visible_rows
|
476
|
-
clear_rows
|
765
|
+
clear_rows
|
766
|
+
@can_delete_rows = false
|
767
|
+
@delete_buttons = []
|
768
|
+
@next_delete_button_y = 38
|
477
769
|
end
|
478
770
|
|
479
771
|
def scroll_up
|
@@ -498,6 +790,45 @@ module Wads
|
|
498
790
|
@row_colors << color
|
499
791
|
end
|
500
792
|
|
793
|
+
def add_table_delete_button
|
794
|
+
if @delete_buttons.size < @max_visible_rows
|
795
|
+
new_button = add_delete_button(@width - 18, @next_delete_button_y) do
|
796
|
+
# nothing to do here, handled in parent widget by event
|
797
|
+
end
|
798
|
+
@delete_buttons << new_button
|
799
|
+
@next_delete_button_y = @next_delete_button_y + 30
|
800
|
+
end
|
801
|
+
end
|
802
|
+
|
803
|
+
def remove_table_delete_button
|
804
|
+
if not @delete_buttons.empty?
|
805
|
+
@delete_buttons.pop
|
806
|
+
@children.pop
|
807
|
+
@next_delete_button_y = @next_delete_button_y - 30
|
808
|
+
end
|
809
|
+
end
|
810
|
+
|
811
|
+
def handle_update update_count, mouse_x, mouse_y
|
812
|
+
# How many visible data rows are there
|
813
|
+
if @can_delete_rows
|
814
|
+
number_of_visible_rows = @data_rows.size - @current_row
|
815
|
+
if number_of_visible_rows > @max_visible_rows
|
816
|
+
number_of_visible_rows = @max_visible_rows
|
817
|
+
end
|
818
|
+
if number_of_visible_rows > @delete_buttons.size
|
819
|
+
number_to_add = number_of_visible_rows - @delete_buttons.size
|
820
|
+
number_to_add.times do
|
821
|
+
add_table_delete_button
|
822
|
+
end
|
823
|
+
elsif number_of_visible_rows < @delete_buttons.size
|
824
|
+
number_to_remove = @delete_buttons.size - number_of_visible_rows
|
825
|
+
number_to_remove.times do
|
826
|
+
remove_table_delete_button
|
827
|
+
end
|
828
|
+
end
|
829
|
+
end
|
830
|
+
end
|
831
|
+
|
501
832
|
def number_of_rows
|
502
833
|
@data_rows.size
|
503
834
|
end
|
@@ -523,14 +854,14 @@ module Wads
|
|
523
854
|
if number_of_columns > 1
|
524
855
|
(0..number_of_columns-2).each do |c|
|
525
856
|
x = x + column_widths[c] + 20
|
526
|
-
Gosu::draw_line x, @y, @color, x, @y + @height, @color,
|
857
|
+
Gosu::draw_line x, @y, @color, x, @y + @height, @color, z_order
|
527
858
|
end
|
528
859
|
end
|
529
860
|
|
530
861
|
y = @y
|
531
862
|
x = @x + 20
|
532
863
|
(0..number_of_columns-1).each do |c|
|
533
|
-
@font.draw_text(@headers[c], x, y,
|
864
|
+
@font.draw_text(@headers[c], x, y, z_order, 1, 1, @color)
|
534
865
|
x = x + column_widths[c] + 20
|
535
866
|
end
|
536
867
|
y = y + 30
|
@@ -542,7 +873,7 @@ module Wads
|
|
542
873
|
elsif count < @current_row + @max_visible_rows
|
543
874
|
x = @x + 20
|
544
875
|
(0..number_of_columns-1).each do |c|
|
545
|
-
@font.draw_text(row[c], x, y + 2,
|
876
|
+
@font.draw_text(row[c], x, y + 2, z_order, 1, 1, @row_colors[count])
|
546
877
|
x = x + column_widths[c] + 20
|
547
878
|
end
|
548
879
|
y = y + 30
|
@@ -559,6 +890,10 @@ module Wads
|
|
559
890
|
end
|
560
891
|
row_number
|
561
892
|
end
|
893
|
+
|
894
|
+
def widget_z
|
895
|
+
Z_ORDER_TEXT
|
896
|
+
end
|
562
897
|
end
|
563
898
|
|
564
899
|
class SingleSelectTable < Table
|
@@ -589,10 +924,14 @@ module Wads
|
|
589
924
|
if @selected_row
|
590
925
|
if @selected_row >= @current_row and @selected_row < @current_row + @max_visible_rows
|
591
926
|
y = @y + 30 + ((@selected_row - @current_row) * 30)
|
592
|
-
Gosu::draw_rect(@x + 20, y, @width - 30, 28, @selected_color, Z_ORDER_SELECTION_BACKGROUND)
|
927
|
+
Gosu::draw_rect(@x + 20, y, @width - 30, 28, @selected_color, relative_z_order(Z_ORDER_SELECTION_BACKGROUND))
|
593
928
|
end
|
594
929
|
end
|
595
930
|
end
|
931
|
+
|
932
|
+
def widget_z
|
933
|
+
Z_ORDER_TEXT
|
934
|
+
end
|
596
935
|
end
|
597
936
|
|
598
937
|
class MultiSelectTable < Table
|
@@ -635,13 +974,52 @@ module Wads
|
|
635
974
|
y = @y + 30
|
636
975
|
row_count = @current_row
|
637
976
|
while row_count < @data_rows.size
|
638
|
-
if @selected_rows.include? row_count
|
639
|
-
|
977
|
+
if @selected_rows.include? row_count
|
978
|
+
width_of_selection_background = @width - 30
|
979
|
+
if @can_delete_rows
|
980
|
+
width_of_selection_background = width_of_selection_background - 20
|
981
|
+
end
|
982
|
+
Gosu::draw_rect(@x + 20, y, width_of_selection_background, 28,
|
983
|
+
@selection_color,
|
984
|
+
relative_z_order(Z_ORDER_SELECTION_BACKGROUND))
|
640
985
|
end
|
641
986
|
y = y + 30
|
642
987
|
row_count = row_count + 1
|
643
988
|
end
|
644
989
|
end
|
990
|
+
|
991
|
+
def widget_z
|
992
|
+
Z_ORDER_TEXT
|
993
|
+
end
|
994
|
+
|
995
|
+
def handle_mouse_down mouse_x, mouse_y
|
996
|
+
if contains_click(mouse_x, mouse_y)
|
997
|
+
row_number = determine_row_number(mouse_y)
|
998
|
+
# First check if its the delete button that got this
|
999
|
+
delete_this_row = false
|
1000
|
+
@delete_buttons.each do |db|
|
1001
|
+
if db.contains_click(mouse_x, mouse_y)
|
1002
|
+
delete_this_row = true
|
1003
|
+
end
|
1004
|
+
end
|
1005
|
+
if delete_this_row
|
1006
|
+
if not row_number.nil?
|
1007
|
+
data_set_row_to_delete = @current_row + row_number
|
1008
|
+
data_set_name_to_delete = @data_rows[data_set_row_to_delete][1]
|
1009
|
+
@data_rows.delete_at(data_set_row_to_delete)
|
1010
|
+
return WidgetResult.new(false, EVENT_TABLE_ROW_DELETE, [data_set_name_to_delete])
|
1011
|
+
end
|
1012
|
+
else
|
1013
|
+
if is_row_selected(mouse_y)
|
1014
|
+
unset_selected_row(mouse_y, 0)
|
1015
|
+
return WidgetResult.new(false, EVENT_TABLE_UNSELECT, @data_rows[row_number])
|
1016
|
+
else
|
1017
|
+
set_selected_row(mouse_y, 0)
|
1018
|
+
return WidgetResult.new(false, EVENT_TABLE_SELECT, @data_rows[row_number])
|
1019
|
+
end
|
1020
|
+
end
|
1021
|
+
end
|
1022
|
+
end
|
645
1023
|
end
|
646
1024
|
|
647
1025
|
class Plot < Widget
|
@@ -650,6 +1028,7 @@ module Wads
|
|
650
1028
|
attr_accessor :display_grid
|
651
1029
|
attr_accessor :display_lines
|
652
1030
|
attr_accessor :zoom_level
|
1031
|
+
attr_accessor :visibility_map
|
653
1032
|
|
654
1033
|
def initialize(x, y, width, height, font)
|
655
1034
|
super x, y, color
|
@@ -657,39 +1036,42 @@ module Wads
|
|
657
1036
|
set_dimensions(width, height)
|
658
1037
|
@display_grid = false
|
659
1038
|
@display_lines = true
|
660
|
-
@
|
661
|
-
@grid_line_color = COLOR_CYAN
|
1039
|
+
@grid_line_color = COLOR_LIGHT_GRAY
|
662
1040
|
@cursor_line_color = COLOR_DARK_GRAY
|
663
|
-
@zero_line_color =
|
1041
|
+
@zero_line_color = COLOR_HEADER_BRIGHT_BLUE
|
664
1042
|
@zoom_level = 1
|
1043
|
+
@data_point_size = 4
|
1044
|
+
# Hash of rendered points keyed by data set name, so we can toggle visibility
|
1045
|
+
@points_by_data_set_name = {}
|
1046
|
+
@visibility_map = {}
|
665
1047
|
end
|
666
1048
|
|
667
|
-
def
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
point.increase_size
|
672
|
-
end
|
1049
|
+
def toggle_visibility(data_set_name)
|
1050
|
+
is_visible = @visibility_map[data_set_name]
|
1051
|
+
if is_visible.nil?
|
1052
|
+
return
|
673
1053
|
end
|
1054
|
+
@visibility_map[data_set_name] = !is_visible
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
def increase_data_point_size
|
1058
|
+
@data_point_size = @data_point_size + 2
|
674
1059
|
end
|
675
1060
|
|
676
1061
|
def decrease_data_point_size
|
677
|
-
@
|
678
|
-
|
679
|
-
data_set.rendered_points.each do |point|
|
680
|
-
point.decrease_size
|
681
|
-
end
|
1062
|
+
if @data_point_size > 2
|
1063
|
+
@data_point_size = @data_point_size - 2
|
682
1064
|
end
|
683
1065
|
end
|
684
1066
|
|
685
1067
|
def zoom_out
|
686
|
-
@zoom_level = @zoom_level + 0.
|
1068
|
+
@zoom_level = @zoom_level + 0.15
|
687
1069
|
visible_range.scale(@zoom_level)
|
688
1070
|
end
|
689
1071
|
|
690
1072
|
def zoom_in
|
691
1073
|
if @zoom_level > 0.11
|
692
|
-
@zoom_level = @zoom_level - 0.
|
1074
|
+
@zoom_level = @zoom_level - 0.15
|
693
1075
|
end
|
694
1076
|
visible_range.scale(@zoom_level)
|
695
1077
|
end
|
@@ -713,11 +1095,6 @@ module Wads
|
|
713
1095
|
def define_range(range)
|
714
1096
|
@visible_range = range
|
715
1097
|
@zoom_level = 1
|
716
|
-
@data_set_hash.keys.each do |key|
|
717
|
-
data_set = @data_set_hash[key]
|
718
|
-
puts "Calling derive values on #{key}"
|
719
|
-
data_set.derive_values(range, @data_set_hash)
|
720
|
-
end
|
721
1098
|
end
|
722
1099
|
|
723
1100
|
def range_set?
|
@@ -725,24 +1102,25 @@ module Wads
|
|
725
1102
|
end
|
726
1103
|
|
727
1104
|
def is_on_screen(point)
|
728
|
-
point.
|
1105
|
+
point.data_x >= @visible_range.left_x and point.data_x <= @visible_range.right_x and point.data_y >= @visible_range.bottom_y and point.data_y <= @visible_range.top_y
|
729
1106
|
end
|
730
1107
|
|
731
|
-
def add_data_set(
|
1108
|
+
def add_data_set(data_set_name, rendered_points)
|
732
1109
|
if range_set?
|
733
|
-
@
|
734
|
-
|
735
|
-
|
736
|
-
data_set.data_points.each do |point|
|
737
|
-
if is_on_screen(point)
|
738
|
-
data_set.add_rendered_point PlotPoint.new(draw_x(point.x), draw_y(point.y), data_set.color, data_set.data_point_size)
|
739
|
-
end
|
1110
|
+
@points_by_data_set_name[data_set_name] = rendered_points
|
1111
|
+
if @visibility_map[data_set_name].nil?
|
1112
|
+
@visibility_map[data_set_name] = true
|
740
1113
|
end
|
741
1114
|
else
|
742
1115
|
puts "ERROR: range not set, cannot add data"
|
743
1116
|
end
|
744
1117
|
end
|
745
1118
|
|
1119
|
+
def remove_data_set(data_set_name)
|
1120
|
+
@points_by_data_set_name.delete(data_set_name)
|
1121
|
+
@visibility_map.delete(data_set_name)
|
1122
|
+
end
|
1123
|
+
|
746
1124
|
def x_val_to_pixel(val)
|
747
1125
|
x_pct = (@visible_range.right_x - val).to_f / @visible_range.x_range
|
748
1126
|
@width - (@width.to_f * x_pct).round
|
@@ -753,14 +1131,6 @@ module Wads
|
|
753
1131
|
(@height.to_f * y_pct).round
|
754
1132
|
end
|
755
1133
|
|
756
|
-
def x_pixel_to_screen(x)
|
757
|
-
@x + x
|
758
|
-
end
|
759
|
-
|
760
|
-
def y_pixel_to_screen(y)
|
761
|
-
@y + y
|
762
|
-
end
|
763
|
-
|
764
1134
|
def draw_x(x)
|
765
1135
|
x_pixel_to_screen(x_val_to_pixel(x))
|
766
1136
|
end
|
@@ -770,63 +1140,63 @@ module Wads
|
|
770
1140
|
end
|
771
1141
|
|
772
1142
|
def render
|
773
|
-
@
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
point
|
1143
|
+
@points_by_data_set_name.keys.each do |key|
|
1144
|
+
if @visibility_map[key]
|
1145
|
+
data_set_points = @points_by_data_set_name[key]
|
1146
|
+
data_set_points.each do |point|
|
1147
|
+
if is_on_screen(point)
|
1148
|
+
point.render(@data_point_size)
|
1149
|
+
end
|
778
1150
|
end
|
779
1151
|
if @display_lines
|
780
|
-
display_lines_for_point_set(
|
1152
|
+
display_lines_for_point_set(data_set_points)
|
781
1153
|
end
|
782
1154
|
end
|
783
|
-
|
784
|
-
|
785
|
-
|
1155
|
+
if @display_grid and range_set?
|
1156
|
+
display_grid_lines
|
1157
|
+
end
|
786
1158
|
end
|
787
1159
|
end
|
788
1160
|
|
789
1161
|
def display_lines_for_point_set(points)
|
790
1162
|
if points.length > 1
|
791
1163
|
points.inject(points[0]) do |last, the_next|
|
792
|
-
|
793
|
-
|
1164
|
+
if last.x < the_next.x
|
1165
|
+
Gosu::draw_line last.x, last.y, last.color,
|
1166
|
+
the_next.x, the_next.y, last.color, relative_z_order(Z_ORDER_GRAPHIC_ELEMENTS)
|
1167
|
+
end
|
794
1168
|
the_next
|
795
1169
|
end
|
796
1170
|
end
|
797
1171
|
end
|
798
1172
|
|
799
1173
|
def display_grid_lines
|
800
|
-
# TODO this is bnot working well for large ranges with the given increment of 1
|
801
|
-
# We don't want to draw hundreds of grid lines
|
802
1174
|
grid_widgets = []
|
803
1175
|
|
804
|
-
|
805
|
-
|
806
|
-
|
1176
|
+
x_lines = @visible_range.grid_line_x_values
|
1177
|
+
y_lines = @visible_range.grid_line_y_values
|
1178
|
+
first_x = draw_x(@visible_range.left_x)
|
1179
|
+
last_x = draw_x(@visible_range.right_x)
|
1180
|
+
first_y = draw_y(@visible_range.bottom_y)
|
1181
|
+
last_y = draw_y(@visible_range.top_y)
|
1182
|
+
|
1183
|
+
x_lines.each do |grid_x|
|
807
1184
|
dx = draw_x(grid_x)
|
808
|
-
dy = draw_y(grid_y)
|
809
|
-
last_x = draw_x(@visible_range.right_x)
|
810
1185
|
color = @grid_line_color
|
811
|
-
if
|
812
|
-
color = @zero_line_color
|
813
|
-
end
|
814
|
-
grid_widgets << Line.new(dx,
|
815
|
-
grid_y = grid_y + 1
|
1186
|
+
if grid_x == 0 and grid_x != @visible_range.left_x.to_i
|
1187
|
+
color = @zero_line_color
|
1188
|
+
end
|
1189
|
+
grid_widgets << Line.new(dx, first_y, dx, last_y, color)
|
816
1190
|
end
|
817
|
-
|
818
|
-
grid_y
|
819
|
-
while grid_x < @visible_range.right_x
|
820
|
-
dx = draw_x(grid_x)
|
1191
|
+
|
1192
|
+
y_lines.each do |grid_y|
|
821
1193
|
dy = draw_y(grid_y)
|
822
|
-
last_y = draw_y(@visible_range.top_y)
|
823
1194
|
color = @grid_line_color
|
824
|
-
if
|
825
|
-
color = @zero_line_color
|
1195
|
+
if grid_y == 0 and grid_y != @visible_range.bottom_y.to_i
|
1196
|
+
color = @zero_line_color
|
826
1197
|
end
|
827
|
-
grid_widgets << Line.new(
|
828
|
-
|
829
|
-
end
|
1198
|
+
grid_widgets << Line.new(first_x, dy, last_x, dy, color)
|
1199
|
+
end
|
830
1200
|
|
831
1201
|
grid_widgets.each do |gw|
|
832
1202
|
gw.draw
|
@@ -867,15 +1237,18 @@ module Wads
|
|
867
1237
|
|
868
1238
|
def render
|
869
1239
|
super
|
870
|
-
draw_background(
|
1240
|
+
draw_background(Z_ORDER_FOCAL_ELEMENTS)
|
871
1241
|
draw_shadow(COLOR_GRAY)
|
872
1242
|
end
|
1243
|
+
|
1244
|
+
def widget_z
|
1245
|
+
Z_ORDER_TEXT
|
1246
|
+
end
|
873
1247
|
end
|
874
1248
|
|
875
1249
|
class GraphWidget < Widget
|
876
1250
|
attr_accessor :graph
|
877
1251
|
attr_accessor :center_node
|
878
|
-
attr_accessor :depth
|
879
1252
|
attr_accessor :selected_node
|
880
1253
|
attr_accessor :selected_node_x_offset
|
881
1254
|
attr_accessor :selected_node_y_offset
|
@@ -886,50 +1259,119 @@ module Wads
|
|
886
1259
|
set_dimensions(width, height)
|
887
1260
|
set_border(color)
|
888
1261
|
@graph = graph
|
1262
|
+
set_all_nodes_for_display
|
889
1263
|
end
|
890
1264
|
|
891
|
-
def
|
1265
|
+
def handle_update update_count, mouse_x, mouse_y
|
892
1266
|
if contains_click(mouse_x, mouse_y) and @selected_node
|
893
1267
|
@selected_node.x = mouse_x - @selected_node_x_offset
|
894
1268
|
@selected_node.y = mouse_y - @selected_node_y_offset
|
895
1269
|
end
|
896
1270
|
end
|
897
1271
|
|
898
|
-
def
|
899
|
-
if
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
@selected_node_y_offset = mouse_y - rn.y
|
907
|
-
end
|
1272
|
+
def handle_mouse_down mouse_x, mouse_y
|
1273
|
+
# check to see if any node was selected
|
1274
|
+
if @rendered_nodes
|
1275
|
+
@rendered_nodes.values.each do |rn|
|
1276
|
+
if rn.contains_click(mouse_x, mouse_y)
|
1277
|
+
@selected_node = rn
|
1278
|
+
@selected_node_x_offset = mouse_x - rn.x
|
1279
|
+
@selected_node_y_offset = mouse_y - rn.y
|
908
1280
|
end
|
909
1281
|
end
|
910
1282
|
end
|
911
1283
|
WidgetResult.new(false)
|
912
1284
|
end
|
913
1285
|
|
914
|
-
def
|
915
|
-
if
|
916
|
-
|
917
|
-
|
918
|
-
|
1286
|
+
def handle_mouse_up mouse_x, mouse_y
|
1287
|
+
if @selected_node
|
1288
|
+
@selected_node = nil
|
1289
|
+
end
|
1290
|
+
end
|
1291
|
+
|
1292
|
+
def set_tree_display(max_depth = -1)
|
1293
|
+
@graph.reset_visited
|
1294
|
+
@visible_data_nodes = @graph.node_map
|
1295
|
+
@rendered_nodes = {}
|
1296
|
+
|
1297
|
+
root_nodes = @graph.root_nodes
|
1298
|
+
number_of_root_nodes = root_nodes.size
|
1299
|
+
width_for_each_root_tree = @width / number_of_root_nodes
|
1300
|
+
|
1301
|
+
start_x = 0
|
1302
|
+
y_level = 10
|
1303
|
+
root_nodes.each do |root|
|
1304
|
+
set_tree_recursive(root, start_x, start_x + width_for_each_root_tree - 1, y_level)
|
1305
|
+
start_x = start_x + width_for_each_root_tree
|
1306
|
+
y_level = y_level + 40
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
@rendered_nodes.values.each do |rn|
|
1310
|
+
rn.base_z = @base_z
|
1311
|
+
end
|
1312
|
+
end
|
1313
|
+
|
1314
|
+
def set_tree_recursive(current_node, start_x, end_x, y_level)
|
1315
|
+
# Draw the current node, and then recursively divide up
|
1316
|
+
# and call again for each of the children
|
1317
|
+
if current_node.visited
|
1318
|
+
return
|
1319
|
+
end
|
1320
|
+
current_node.visited = true
|
1321
|
+
|
1322
|
+
@rendered_nodes[current_node.name] = NodeWidget.new(
|
1323
|
+
current_node,
|
1324
|
+
x_pixel_to_screen(start_x + ((end_x - start_x) / 2)),
|
1325
|
+
y_pixel_to_screen(y_level),
|
1326
|
+
@font,
|
1327
|
+
get_node_color(current_node),
|
1328
|
+
get_node_color(current_node))
|
1329
|
+
|
1330
|
+
number_of_child_nodes = current_node.outputs.size
|
1331
|
+
if number_of_child_nodes == 0
|
1332
|
+
return
|
1333
|
+
end
|
1334
|
+
width_for_each_child_tree = (end_x - start_x) / number_of_child_nodes
|
1335
|
+
start_child_x = start_x + 5
|
1336
|
+
|
1337
|
+
current_node.outputs.each do |child|
|
1338
|
+
if child.is_a? Edge
|
1339
|
+
child = child.destination
|
1340
|
+
end
|
1341
|
+
set_tree_recursive(child, start_child_x, start_child_x + width_for_each_child_tree - 1, y_level + 40)
|
1342
|
+
start_child_x = start_child_x + width_for_each_child_tree
|
919
1343
|
end
|
920
1344
|
end
|
921
1345
|
|
922
|
-
def
|
1346
|
+
def set_all_nodes_for_display
|
1347
|
+
@visible_data_nodes = @graph.node_map
|
1348
|
+
@rendered_nodes = {}
|
1349
|
+
populate_rendered_nodes
|
1350
|
+
end
|
1351
|
+
|
1352
|
+
def get_node_color(node)
|
1353
|
+
color_tag = node.get_tag("color")
|
1354
|
+
if color_tag.nil?
|
1355
|
+
return @color
|
1356
|
+
end
|
1357
|
+
color_tag
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
def set_center_node(center_node, max_depth = -1)
|
923
1361
|
# Determine the list of nodes to draw
|
924
|
-
@
|
925
|
-
@visible_data_nodes = @graph.
|
1362
|
+
@graph.reset_visited
|
1363
|
+
@visible_data_nodes = @graph.traverse_and_collect_nodes(center_node, max_depth)
|
926
1364
|
|
927
1365
|
# Convert the data nodes to rendered nodes
|
928
1366
|
# Start by putting the center node in the center, then draw others around it
|
929
1367
|
@rendered_nodes = {}
|
930
1368
|
@rendered_nodes[center_node.name] = NodeWidget.new(center_node, center_x, center_y, @font,
|
931
|
-
|
1369
|
+
get_node_color(center_node), get_node_color(center_node))
|
1370
|
+
|
1371
|
+
populate_rendered_nodes(center_node)
|
1372
|
+
end
|
932
1373
|
|
1374
|
+
def populate_rendered_nodes(center_node = nil)
|
933
1375
|
# Spread out the other nodes around the center node
|
934
1376
|
# going in a circle
|
935
1377
|
number_of_visible_nodes = @visible_data_nodes.size
|
@@ -937,9 +1379,13 @@ module Wads
|
|
937
1379
|
current_radians = 0.05
|
938
1380
|
|
939
1381
|
@visible_data_nodes.each do |node_name, data_node|
|
940
|
-
|
941
|
-
|
942
|
-
|
1382
|
+
process_this_node = true
|
1383
|
+
if center_node
|
1384
|
+
if node_name == center_node.name
|
1385
|
+
process_this_node = false
|
1386
|
+
end
|
1387
|
+
end
|
1388
|
+
if process_this_node
|
943
1389
|
# Use radians to spread the other nodes around the center node
|
944
1390
|
# For now, we will randomly place them
|
945
1391
|
node_x = center_x + ((80 + rand(200)) * Math.cos(current_radians))
|
@@ -963,10 +1409,13 @@ module Wads
|
|
963
1409
|
node_x,
|
964
1410
|
node_y,
|
965
1411
|
@font,
|
966
|
-
data_node
|
967
|
-
data_node
|
1412
|
+
get_node_color(data_node),
|
1413
|
+
get_node_color(data_node))
|
968
1414
|
end
|
969
1415
|
end
|
1416
|
+
@rendered_nodes.values.each do |rn|
|
1417
|
+
rn.base_z = @base_z
|
1418
|
+
end
|
970
1419
|
end
|
971
1420
|
|
972
1421
|
def render
|
@@ -987,7 +1436,7 @@ module Wads
|
|
987
1436
|
else
|
988
1437
|
Gosu::draw_line rendered_node.center_x, rendered_node.center_y, rendered_node.color,
|
989
1438
|
connected_rendered_node.center_x, connected_rendered_node.center_y, connected_rendered_node.color,
|
990
|
-
Z_ORDER_GRAPHIC_ELEMENTS
|
1439
|
+
relative_z_order(Z_ORDER_GRAPHIC_ELEMENTS)
|
991
1440
|
end
|
992
1441
|
end
|
993
1442
|
end
|