wads 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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