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.
@@ -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, 50)
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, 50)
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, 50)
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
@@ -1,3 +1,3 @@
1
1
  module Wads
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
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
- Z_ORDER_WIDGET_BORDER = 3
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
- Z_ORDER_OVERLAY_BACKGROUND = 7
37
- Z_ORDER_OVERLAY_ELEMENTS = 8
38
- Z_ORDER_TEXT = 10
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(z_order = Z_ORDER_BACKGROUND)
119
- Gosu::draw_rect(@x + 1, @y + 1, @width - 3, @height - 3, @background_color, z_order)
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, z_order = Z_ORDER_WIDGET_BORDER)
123
- Gosu::draw_line @x - 1, @y - 1, color, right_edge - 1, @y - 1, color, z_order
124
- Gosu::draw_line @x - 1, @y - 1, color, @x - 1, bottom_edge - 1, color, z_order
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 render
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, zorder
142
- Gosu::draw_line @x, @y, color, @x, bottom_edge, color, zorder
143
- Gosu::draw_line @x,bottom_edge, color, right_edge, bottom_edge, color, zorder
144
- Gosu::draw_line right_edge, @y, color, right_edge, bottom_edge, color, zorder
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 update_count, mouse_x, mouse_y
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 button_down id, mouse_x, mouse_y
368
+ def handle_key_press id, mouse_x, mouse_y
156
369
  # empty base implementation
157
370
  end
158
371
 
159
- def button_up id, mouse_x, mouse_y
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, Z_ORDER_TEXT, 1, 1, @color)
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
- @half_size = @data_point_size / 2
194
- Gosu::draw_rect(@x - @half_size, @y - @half_size,
195
- @data_point_size, @data_point_size,
196
- @color, Z_ORDER_PLOT_POINTS)
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, Z_ORDER_TEXT, 1, 1, @text_color)
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, Z_ORDER_TEXT, 1, 1, COLOR_WHITE)
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
- @title = title
266
- add_child(Text.new(title, x + 5, y + 5, Gosu::Font.new(32)))
267
- add_child(Document.new(content, x + 5, y + 52, width, height, font))
268
- @ok_button = Button.new("OK", center_x - 50, bottom_edge - 26, @font, 100, COLOR_FORM_BUTTON)
269
- add_child(@ok_button)
270
- set_background(COLOR_GRAY)
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 button_down id, mouse_x, mouse_y
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
- WidgetResult.new(false)
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(0xff566573 )
589
+ set_background(COLOR_OFF_GRAY)
294
590
  set_border(COLOR_WHITE)
591
+ @base_z = 10
295
592
  @error_message = nil
296
593
 
297
- add_child(Text.new(title, x + 5, y + 5, @font))
594
+ add_text(title, 5, 5)
298
595
  # Forms automatically have some explanatory content
299
- add_child(Document.new(content, x, y + 56, width, height, font))
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
- @ok_button = Button.new("OK", center_x - 100, bottom_edge - 26, @font, 100, COLOR_FORM_BUTTON, COLOR_WHITE)
307
- @cancel_button = Button.new("Cancel", center_x + 50, bottom_edge - 26, @font, 100, COLOR_FORM_BUTTON, COLOR_WHITE)
308
- add_child(@ok_button)
309
- add_child(@cancel_button)
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 text_input_updated(text)
355
- # empty implementation of text being updated
356
- # in text widget
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 button_down id, mouse_x, mouse_y
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, Z_ORDER_GRAPHIC_ELEMENTS
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, Z_ORDER_GRAPHIC_ELEMENTS
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, Z_ORDER_TEXT, 1, 1, @color)
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, Z_ORDER_GRAPHIC_ELEMENTS
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, Z_ORDER_TEXT, 1, 1, @color)
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, Z_ORDER_TEXT, 1, 1, @row_colors[count])
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
- Gosu::draw_rect(@x + 20, y, @width - 3, 28, @selection_color, Z_ORDER_SELECTION_BACKGROUND)
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
- @data_set_hash = {}
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 = COLOR_BLUE
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 increase_data_point_size
668
- @data_set_hash.keys.each do |key|
669
- data_set = @data_set_hash[key]
670
- data_set.rendered_points.each do |point|
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
- @data_set_hash.keys.each do |key|
678
- data_set = @data_set_hash[key]
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.1
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.1
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.x >= @visible_range.left_x and point.x <= @visible_range.right_x and point.y >= @visible_range.bottom_y and point.y <= @visible_range.top_y
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(data_set)
1108
+ def add_data_set(data_set_name, rendered_points)
732
1109
  if range_set?
733
- @data_set_hash[data_set.name] = data_set
734
- data_set.clear_rendered_points
735
- data_set.derive_values(@visible_range, @data_set_hash)
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
- @data_set_hash.keys.each do |key|
774
- data_set = @data_set_hash[key]
775
- if data_set.visible
776
- data_set.rendered_points.each do |point|
777
- point.draw
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(data_set.rendered_points)
1152
+ display_lines_for_point_set(data_set_points)
781
1153
  end
782
1154
  end
783
- end
784
- if @display_grid and range_set?
785
- display_grid_lines
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
- Gosu::draw_line last.x, last.y, last.color,
793
- the_next.x, the_next.y, last.color, Z_ORDER_GRAPHIC_ELEMENTS
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
- grid_x = @visible_range.left_x
805
- grid_y = @visible_range.bottom_y + 1
806
- while grid_y < @visible_range.top_y
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 grid_y == 0 and grid_y != @visible_range.bottom_y.to_i
812
- color = @zero_line_color
813
- end
814
- grid_widgets << Line.new(dx, dy, last_x, dy, color)
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
- grid_x = @visible_range.left_x + 1
818
- grid_y = @visible_range.bottom_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 grid_x == 0 and grid_x != @visible_range.left_x.to_i
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(dx, dy, dx, last_y, color)
828
- grid_x = grid_x + 1
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(Z_ORDER_OVERLAY_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 update update_count, mouse_x, mouse_y
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 button_down id, mouse_x, mouse_y
899
- if id == Gosu::MsLeft
900
- # check to see if any node was selected
901
- if @rendered_nodes
902
- @rendered_nodes.values.each do |rn|
903
- if rn.contains_click(mouse_x, mouse_y)
904
- @selected_node = rn
905
- @selected_node_x_offset = mouse_x - rn.x
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 button_up id, mouse_x, mouse_y
915
- if id == Gosu::MsLeft
916
- if @selected_node
917
- @selected_node = nil
918
- end
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 set_display(center_node, max_depth)
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
- @depth = depth
925
- @visible_data_nodes = @graph.fan_out(center_node, max_depth)
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
- center_node.get_tag("color"), center_node.get_tag("color"))
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
- if node_name == center_node.name
941
- # skip, we already got this one
942
- else
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.get_tag("color"),
967
- data_node.get_tag("color"))
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