minigl 1.3.10 → 2.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3638cd0876552f96b482a2b5986581916a27a5f9
4
- data.tar.gz: a6e059c49297f45b360e225394b687bb2650a0a9
3
+ metadata.gz: f8b03d2bc58b9642caa459346389f4d8a9368bdf
4
+ data.tar.gz: a16bbf130daa7014e576450145ab8acd8db57aea
5
5
  SHA512:
6
- metadata.gz: 2ac542ef6d3fe0140636b591b26336c23ed4b8fe1c7188c751f89e439a7099c2e0baaaff1e7fdae65f9d1529a73757792c9c147282e2f83418ac8e00254dad13
7
- data.tar.gz: 68dbca5b83d9600c2d2b75c11b4c69aabd536a9a41722e0f1e1235af27e7bf195cad88809571770a9e91d61e025e777df13ed479dc8eb6e0f814c8e48d588530
6
+ metadata.gz: 7c5ca7adb1c4b297affa552ed1a7e1f7fc723c47e09172363e1049b0fb625247c1efd95d3961433fda7675ce9a8add42bc75c41decf930d1e6fdd01d2a892e13
7
+ data.tar.gz: 0400e96968260c4a45791ed85b9e37659f6bfcf0d267919b1fabd61e0bc222d5a1622f58395a2f6ecbb9428fb56274a47223c5a61ae5bb6a93f5a36746c27d44
data/README.md CHANGED
@@ -26,16 +26,22 @@ After installing the gosu dependencies, you can just `gem install minigl`.
26
26
  Please note:
27
27
 
28
28
  * The test package is not complete! Most of the functionality
29
- provided by the gem is difficult to test automatically, but you can check out
30
- this [working game example](https://github.com/victords/aventura-do-saber).
31
- * The RDoc documentation is now available.
29
+ provided by the gem is difficult to test automatically, but you can check the
30
+ examples provided with the gem.
31
+ * The library is 100% RDoc-documented.
32
32
  * An auxiliary, tutorial-like documentation is under construction
33
- [here](https://github.com/victords/minigl/wiki).
33
+ [here](https://github.com/victords/minigl/wiki/How-To).
34
34
 
35
- **Version 1.3.10**
35
+ **Version 2.0.0**
36
36
 
37
- * Split the `center` parameter in `Button` and `ToggleButton` constructors
38
- into `center_x` and `center_y` (see doc. for details).
37
+ MiniGL 2.0.0 is finally released!
39
38
 
40
- **P.S.** This version can cause incompatibility because of the parameter order
41
- in the constructors of `Button` and `ToggleButton`.
39
+ It brings new features, improvements to existing features and some bug fixes.
40
+ For details on what has changed, visit
41
+ [the changelog](https://github.com/victords/minigl/wiki/Changelog-(2.0.0)).
42
+
43
+ As the semantic versioning implies, **this version is incompatible with the 1.x
44
+ series**, so you'll need to adjust your code a little if you wish to upgrade.
45
+
46
+ A new tutorial has to be built, because there have been some changes even in the
47
+ basics of the usage. So please be patient while it doesn't come out!
data/lib/minigl/forms.rb CHANGED
@@ -1,9 +1,21 @@
1
1
  require_relative 'global'
2
2
 
3
- module AGL
3
+ module MiniGL
4
4
  # This class is an abstract ancestor for all form components (Button,
5
5
  # ToggleButton and TextField).
6
6
  class Component
7
+ # The horizontal coordinate of the component
8
+ attr_reader :x
9
+
10
+ # The vertical coordinate of the component
11
+ attr_reader :y
12
+
13
+ # The width of the component
14
+ attr_reader :w
15
+
16
+ # The height of the component
17
+ attr_reader :h
18
+
7
19
  # Determines whether the control is enabled, i.e., will process user input.
8
20
  attr_accessor :enabled
9
21
 
@@ -32,6 +44,12 @@ module AGL
32
44
 
33
45
  # This class represents a button.
34
46
  class Button < Component
47
+ # The current state of the button.
48
+ attr_reader :state
49
+
50
+ # The text of the button.
51
+ attr_accessor :text
52
+
35
53
  # Creates a button.
36
54
  #
37
55
  # Parameters:
@@ -49,6 +67,10 @@ module AGL
49
67
  # [text_color] Color of the button text, in hexadecimal RRGGBB format.
50
68
  # [disabled_text_color] Color of the button text, when it's disabled, in
51
69
  # hexadecimal RRGGBB format.
70
+ # [over_text_color] Color of the button text, when the cursor is over it
71
+ # (hexadecimal RRGGBB).
72
+ # [down_text_color] Color of the button text, when it is pressed
73
+ # (hexadecimal RRGGBB).
52
74
  # [center_x] Whether the button text should be horizontally centered in its
53
75
  # area (the area is defined by the image size, if an image is
54
76
  # given, or by the +width+ and +height+ parameters, otherwise).
@@ -71,9 +93,11 @@ module AGL
71
93
  # parameters.
72
94
  # [action] The block of code executed when the button is clicked (or by
73
95
  # calling the +click+ method).
74
- def initialize(x, y, font, text, img, text_color = 0, disabled_text_color = 0, center_x = true, center_y = true,
75
- margin_x = 0, margin_y = 0, width = nil, height = nil, params = nil, &action)
96
+ def initialize(x, y, font, text, img, text_color = 0, disabled_text_color = 0, over_text_color = 0, down_text_color = 0,
97
+ center_x = true, center_y = true, margin_x = 0, margin_y = 0, width = nil, height = nil, params = nil, &action)
76
98
  super x, y, font, text, text_color, disabled_text_color
99
+ @over_text_color = over_text_color
100
+ @down_text_color = down_text_color
77
101
  @img =
78
102
  if img; Res.imgs img, 1, 4, true
79
103
  else; nil; end
@@ -175,7 +199,17 @@ module AGL
175
199
  return unless @visible
176
200
 
177
201
  color = (alpha << 24) | 0xffffff
178
- text_color = (alpha << 24) | (@enabled ? @text_color : @disabled_text_color)
202
+ text_color =
203
+ if @enabled
204
+ if @state == :down
205
+ @down_text_color
206
+ else
207
+ @state == :over ? @over_text_color : @text_color
208
+ end
209
+ else
210
+ @disabled_text_color
211
+ end
212
+ text_color = (alpha << 24) | text_color
179
213
  @img[@img_index].draw @x, @y, z_index, 1, 1, color if @img
180
214
  if @text
181
215
  if @center_x or @center_y
@@ -215,9 +249,10 @@ module AGL
215
249
  # puts "button was checked" if checked
216
250
  # # do something with params
217
251
  # }
218
- def initialize(x, y, font, text, img, checked = false, text_color = 0, disabled_text_color = 0, center_x = true, center_y = true,
219
- margin_x = 0, margin_y = 0, width = nil, height = nil, params = nil, &action)
220
- super x, y, font, text, nil, text_color, disabled_text_color, center_x, center_y, margin_x, margin_y, width, height, params, &action
252
+ def initialize(x, y, font, text, img, checked = false, text_color = 0, disabled_text_color = 0, over_text_color = 0, down_text_color = 0,
253
+ center_x = true, center_y = true, margin_x = 0, margin_y = 0, width = nil, height = nil, params = nil, &action)
254
+ super x, y, font, text, nil, text_color, disabled_text_color, over_text_color, down_text_color,
255
+ center_x, center_y, margin_x, margin_y, width, height, params, &action
221
256
  @img =
222
257
  if img; Res.imgs img, 2, 4, true
223
258
  else; nil; end
@@ -271,6 +306,10 @@ module AGL
271
306
  # The current text inside the text field.
272
307
  attr_reader :text
273
308
 
309
+ # The current 'locale' used for detecting the keys. THIS FEATURE IS
310
+ # INCOMPLETE!
311
+ attr_reader :locale
312
+
274
313
  # Creates a new text field.
275
314
  #
276
315
  # Parameters:
@@ -306,6 +345,10 @@ module AGL
306
345
  # [selection_color] The color of the rectangle highlighting selected text,
307
346
  # in hexadecimal RRGGBB format. The rectangle will
308
347
  # always be drawn with 50% of opacity.
348
+ # [locale] The locale to be used when detecting keys. By now, only 'en-US'
349
+ # and 'pt-BR' are **partially** supported. Default is 'en-US'. If
350
+ # any different value is supplied, all typed characters will be
351
+ # mapped to '#'.
309
352
  # [params] An object containing any parameters you want passed to the
310
353
  # +on_text_changed+ block. When the text of the text field is
311
354
  # changed, the following is called:
@@ -317,7 +360,7 @@ module AGL
317
360
  # +text=+. The new text is passed as a first parameter
318
361
  # to this block, followed by +params+. Can be +nil+.
319
362
  def initialize(x, y, font, img, cursor_img = nil, disabled_img = nil, margin_x = 0, margin_y = 0, max_length = 100, active = false, text = '',
320
- allowed_chars = nil, text_color = 0, disabled_text_color = 0, selection_color = 0, params = nil, &on_text_changed)
363
+ allowed_chars = nil, text_color = 0, disabled_text_color = 0, selection_color = 0, locale = 'en-us', params = nil, &on_text_changed)
321
364
  super x, y, font, text, text_color, disabled_text_color
322
365
  @img = Res.img img
323
366
  @w = @img.width
@@ -348,16 +391,13 @@ module AGL
348
391
  Gosu::KbDelete, Gosu::KbLeft, Gosu::KbRight, Gosu::KbHome,
349
392
  Gosu::KbEnd, Gosu::KbLeftShift, Gosu::KbRightShift,
350
393
  Gosu::KbBacktick, Gosu::KbMinus, Gosu::KbEqual, Gosu::KbBracketLeft,
351
- Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbApostrophe,
352
- Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash
394
+ Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbSemicolon,
395
+ Gosu::KbApostrophe, Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash,
396
+ Gosu::KbNumpadAdd, Gosu::KbNumpadSubtract,
397
+ Gosu::KbNumpadMultiply, Gosu::KbNumpadDivide
353
398
  ]
354
- @chars = "abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ'-=/[]\\,.;\"_+?{}|<>:!@#$%¨&*()"
355
- @allowed_chars =
356
- if allowed_chars
357
- allowed_chars
358
- else
359
- @chars
360
- end
399
+ @user_allowed_chars = allowed_chars
400
+ self.locale = locale
361
401
 
362
402
  @on_text_changed = on_text_changed
363
403
  @params = params
@@ -430,10 +470,10 @@ module AGL
430
470
  insert_char @chars[i]
431
471
  end
432
472
  elsif i < 36
433
- if shift; insert_char @chars[i + 57]
473
+ if shift; insert_char @chars[i + 59]
434
474
  else; insert_char @chars[i]; end
435
475
  elsif shift
436
- insert_char(@chars[i + 47])
476
+ insert_char(@chars[i + 49])
437
477
  else
438
478
  insert_char(@chars[i - 10])
439
479
  end
@@ -443,15 +483,26 @@ module AGL
443
483
  end
444
484
 
445
485
  return if inserted
446
- for i in 55..64 # special
486
+ for i in 55..65 # special
447
487
  if KB.key_pressed?(@k[i]) or KB.key_held?(@k[i])
448
- if shift; insert_char @chars[i + 18]
488
+ remove_interval true if @anchor1 and @anchor2
489
+ if shift; insert_char @chars[i + 19]
449
490
  else; insert_char @chars[i + 8]; end
450
491
  inserted = true
451
492
  break
452
493
  end
453
494
  end
454
495
 
496
+ return if inserted
497
+ for i in 66..69 # numpad operators
498
+ if KB.key_pressed?(@k[i]) or KB.key_held?(@k[i])
499
+ remove_interval true if @anchor1 and @anchor2
500
+ insert_char @chars[i + 19]
501
+ inserted = true
502
+ break
503
+ end
504
+ end
505
+
455
506
  return if inserted
456
507
  if KB.key_pressed?(@k[47]) or KB.key_held?(@k[47]) # back
457
508
  if @anchor1 and @anchor2
@@ -541,6 +592,25 @@ module AGL
541
592
  @on_text_changed.call @text, @params if @on_text_changed
542
593
  end
543
594
 
595
+ # Sets the locale used by the text field to detect keys. Only 'en-us' and
596
+ # 'pt-br' are **partially** supported. If any different value is supplied,
597
+ # all typed characters will be mapped to '#'.
598
+ def locale=(value)
599
+ @locale = value.downcase
600
+ @chars =
601
+ case @locale
602
+ when 'en-us' then "abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ`-=[]\\;',./~_+{}|:\"<>?!@#$%^&*()+-*/"
603
+ when 'pt-br' then "abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ'-=/[]ç~,.;\"_+?{}Ç^<>:!@#$%¨&*()+-*/"
604
+ else '###################################################################################################'
605
+ end
606
+ @allowed_chars =
607
+ if @user_allowed_chars
608
+ @user_allowed_chars
609
+ else
610
+ @chars
611
+ end
612
+ end
613
+
544
614
  # Returns the currently selected text.
545
615
  def selected_text
546
616
  return '' if @anchor2.nil?
@@ -597,10 +667,10 @@ module AGL
597
667
 
598
668
  if @anchor1 and @anchor2
599
669
  selection_color = ((alpha / 2) << 24) | @selection_color
600
- Game.window.draw_quad @nodes[@anchor1], @text_y, selection_color,
601
- @nodes[@anchor2] + 1, @text_y, selection_color,
602
- @nodes[@anchor2] + 1, @text_y + @font.height, selection_color,
603
- @nodes[@anchor1], @text_y + @font.height, selection_color, z_index
670
+ G.window.draw_quad @nodes[@anchor1], @text_y, selection_color,
671
+ @nodes[@anchor2] + 1, @text_y, selection_color,
672
+ @nodes[@anchor2] + 1, @text_y + @font.height, selection_color,
673
+ @nodes[@anchor1], @text_y + @font.height, selection_color, z_index
604
674
  end
605
675
 
606
676
  if @cursor_visible
@@ -608,10 +678,10 @@ module AGL
608
678
  @cursor_img.draw @nodes[@cur_node] - @cursor_img.width / 2, @text_y, z_index
609
679
  else
610
680
  cursor_color = alpha << 24
611
- Game.window.draw_quad @nodes[@cur_node], @text_y, cursor_color,
612
- @nodes[@cur_node] + 1, @text_y, cursor_color,
613
- @nodes[@cur_node] + 1, @text_y + @font.height, cursor_color,
614
- @nodes[@cur_node], @text_y + @font.height, cursor_color, z_index
681
+ G.window.draw_quad @nodes[@cur_node], @text_y, cursor_color,
682
+ @nodes[@cur_node] + 1, @text_y, cursor_color,
683
+ @nodes[@cur_node] + 1, @text_y + @font.height, cursor_color,
684
+ @nodes[@cur_node], @text_y + @font.height, cursor_color, z_index
615
685
  end
616
686
  end
617
687
  end
@@ -668,7 +738,7 @@ module AGL
668
738
  interval_width += @font.text_width(@text[i])
669
739
  @nodes.delete_at min + 1
670
740
  end
671
- @text[min...max] = ""
741
+ @text[min...max] = ''
672
742
  for i in (min + 1)..(@nodes.size - 1)
673
743
  @nodes[i] -= interval_width
674
744
  end
@@ -691,4 +761,286 @@ module AGL
691
761
  @on_text_changed.call @text, @params if @on_text_changed
692
762
  end
693
763
  end
764
+
765
+ # Represents a progress bar.
766
+ class ProgressBar < Component
767
+ # The maximum value for this progress bar (when the current value equals
768
+ # the maximum, the bar is full).
769
+ attr_reader :max_value
770
+
771
+ # The current value of the progress bar (an integer greater than or equal
772
+ # to zero, and less than or equal to +max_value+).
773
+ attr_reader :value
774
+
775
+ # Creates a progress bar.
776
+ #
777
+ # Parameters:
778
+ # [x] The x-coordinate of the progress bar on the screen.
779
+ # [y] The y-coordinate of the progress bar on the screen.
780
+ # [w] Width of the progress bar, in pixels. This is the maximum space the
781
+ # bar foreground can occupy. Note that the width of the foreground image
782
+ # (+fg+) can be less than this.
783
+ # [h] Height of the progress bar. This will be the height of the bar
784
+ # foreground when +fg+ is a color (when it is an image, the height of
785
+ # the image will be kept).
786
+ # [bg] A background image (string or symbol that will be passed to
787
+ # +Res.img+) or color (in RRGGBB hexadecimal format).
788
+ # [fg] A foreground image (string or symbol that will be passed to
789
+ # +Res.img+) or color (in RRGGBB hexadecimal format). The image will
790
+ # be horizontally repeated when needed, if its width is less than +w+.
791
+ # [max_value] The maximum value the progress bar can reach (an integer).
792
+ # [value] The starting value for the progress bar.
793
+ # [fg_margin_x] Horizontal margin between the background image and the
794
+ # foreground image (when these are provided).
795
+ # [fg_margin_y] Vertical margin between the background image and the
796
+ # foreground image (when these are provided).
797
+ # [font] Font that will be used to draw a text indicating the value of the
798
+ # progress bar.
799
+ # [text_color] Color of the text.
800
+ # [format] Format to display the value. Specify '%' for a percentage and
801
+ # anything else for absolute values (current/maximum).
802
+ def initialize(x, y, w, h, bg, fg, max_value = 100, value = 100, fg_margin_x = 0, fg_margin_y = 0, #fg_left = nil, fg_right = nil,
803
+ font = nil, text_color = 0, format = nil)
804
+ super x, y, font, '', text_color, text_color
805
+ @w = w
806
+ @h = h
807
+ if bg.is_a? Integer
808
+ @bg_color = bg
809
+ else # String or Symbol
810
+ @bg = Res.img bg
811
+ end
812
+ if fg.is_a? Integer
813
+ @fg_color = fg
814
+ else # String or Symbol
815
+ @fg = Res.img fg
816
+ @fg_path = "#{Res.prefix}img/#{fg.to_s.gsub('_', '/')}.png"
817
+ puts @fg_path
818
+ end
819
+ @fg_margin_x = fg_margin_x
820
+ @fg_margin_y = fg_margin_y
821
+ # @fg_left = fg_left
822
+ # @fg_right = fg_right
823
+ @max_value = max_value
824
+ self.value = value
825
+ @format = format
826
+ end
827
+
828
+ # Increases the current value of the progress bar by the given amount.
829
+ #
830
+ # Parameters:
831
+ # [amount] (+Integer+) The amount to be added to the current value. If the
832
+ # sum surpasses +max_value+, it is set to +max_value+.
833
+ def increase(amount)
834
+ @value += amount
835
+ @value = @max_value if @value > @max_value
836
+ end
837
+
838
+ # Descreases the current value of the progress bar by the given amount.
839
+ #
840
+ # Parameters:
841
+ # [amount] (+Integer+) The amount to be subtracted from the current value.
842
+ # If the result is less than zero, it is set to zero.
843
+ def decrease(amount)
844
+ @value -= amount
845
+ @value = 0 if @value < 0
846
+ end
847
+
848
+ # Sets the value of the progress bar.
849
+ #
850
+ # Parameters:
851
+ # [val] (+Integer+) The value to be set. It will be changed as needed to be
852
+ # between zero and +max_value+.
853
+ def value=(val)
854
+ @value = val
855
+ if @value > @max_value
856
+ @value = @max_value
857
+ elsif @value < 0
858
+ @value = 0
859
+ end
860
+ end
861
+
862
+ # Sets the value of the progress bar to a given percentage of +max_value+.
863
+ #
864
+ # Parameters:
865
+ # [pct] (+Numeric+) The percentage of +max_value+ to set the current value
866
+ # to. The final result will be changed as needed to be between zero
867
+ # and +max_value+.
868
+ def percentage=(pct)
869
+ self.value = (pct * @max_value).round
870
+ end
871
+
872
+ # Draws the progress bar.
873
+ #
874
+ # Parameters:
875
+ # [alpha] (+Fixnum+) The opacity with which the progress bar will be drawn.
876
+ # Allowed values vary between 0 (fully transparent) and 255 (fully
877
+ # opaque).
878
+ # [z_index] (+Fixnum+) The z-order to draw the object. Objects with larger
879
+ # z-orders will be drawn on top of the ones with smaller z-orders.
880
+ def draw(alpha = 0xff, z_index = 0)
881
+ return unless @visible
882
+
883
+ if @bg
884
+ c = (alpha << 24) | 0xffffff
885
+ @bg.draw @x, @y, z_index, 1, 1, c
886
+ else
887
+ c = (alpha << 24) | @bg_color
888
+ G.window.draw_quad @x, @y, c,
889
+ @x + @w, @y, c,
890
+ @x + @w, @y + @h, c,
891
+ @x, @y + @h, c, z_index
892
+ end
893
+ if @fg
894
+ c = (alpha << 24) | 0xffffff
895
+ w1 = @fg.width
896
+ w2 = (@value.to_f / @max_value * @w).round
897
+ x0 = @x + @fg_margin_x
898
+ x = 0
899
+ while x <= w2 - w1
900
+ @fg.draw x0 + x, @y + @fg_margin_y, z_index, 1, 1, c
901
+ x += w1
902
+ end
903
+ if w2 - x > 0
904
+ img = Gosu::Image.new(G.window, @fg_path, true, 0, 0, w2 - x, @fg.height)
905
+ img.draw x0 + x, @y + @fg_margin_y, z_index, 1, 1, c
906
+ end
907
+ else
908
+ c = (alpha << 24) | @fg_color
909
+ rect_r = @x + (@value.to_f / @max_value * @w).round
910
+ G.window.draw_quad @x, @y, c,
911
+ rect_r, @y, c,
912
+ rect_r, @y + @h, c,
913
+ @x, @y + @h, c, z_index
914
+ end
915
+ if @font
916
+ c = (alpha << 24) | @text_color
917
+ @text = @format == '%' ? "#{(@value.to_f / @max_value * 100).round}%" : "#{@value}/#{@max_value}"
918
+ @font.draw_rel @text, @x + @fg_margin_x + @w / 2, @y + @fg_margin_y + @h / 2, 0, 0.5, 0.5, 1, 1, c
919
+ end
920
+ end
921
+ end
922
+
923
+ # This class represents a "drop-down list" form component, here composed of a
924
+ # group of +Button+ objects.
925
+ class DropDownList < Component
926
+ # The selected value in the drop-down list. This is one of the +options+.
927
+ attr_reader :value
928
+
929
+ # An array containing all the options (each of them +String+s) that can be
930
+ # selected in the drop-down list.
931
+ attr_accessor :options
932
+
933
+ # Creates a new drop-down list.
934
+ #
935
+ # Parameters:
936
+ # [x] The x-coordinate of the object.
937
+ # [y] The y-coordinate of the object.
938
+ # [font] Font to be used by the buttons that compose the drop-donwn list.
939
+ # [img] Image of the main button, i.e., the one at the top, that toggles
940
+ # visibility of the other buttons (the "option" buttons).
941
+ # [opt_img] Image for the "option" buttons, as described above.
942
+ # [options] Array of available options for this control (+String+s).
943
+ # [option] Index of the firstly selected option.
944
+ # [text_margin] Left margin of the text inside the buttons (vertically, the
945
+ # text will always be centered).
946
+ # [width] Width of the control, used when no image is provided.
947
+ # [height] Height of the control, used when no image is provided.
948
+ # [text_color] Used as the +text_color+ parameter in the constructor of the
949
+ # buttons.
950
+ # [disabled_text_color] Analogous to +text_color+.
951
+ # [over_text_color] Same as above.
952
+ # [down_text_color] Same as above.
953
+ def initialize(x, y, font, img, opt_img, options, option = 0, text_margin = 0, width = nil, height = nil,
954
+ text_color = 0, disabled_text_color = 0, over_text_color = 0, down_text_color = 0)
955
+ super x, y, font, options[option], text_color, disabled_text_color
956
+ @img = img
957
+ @opt_img = opt_img
958
+ @options = options
959
+ @value = @options[option]
960
+ @open = false
961
+ @buttons = []
962
+ @buttons.push(
963
+ Button.new(x, y, font, @value, img, text_color, disabled_text_color, over_text_color, down_text_color,
964
+ false, true, text_margin, 0, width, height) {
965
+ toggle
966
+ }
967
+ )
968
+ @w = @buttons[0].w
969
+ @h = @buttons[0].h
970
+ @options.each_with_index do |o, i|
971
+ b = Button.new(x, y + (i+1) * @h, font, o, opt_img, text_color, disabled_text_color, over_text_color, down_text_color,
972
+ false, true, text_margin, 0, @w, @h) {
973
+ @value = @buttons[0].text = o
974
+ toggle
975
+ }
976
+ b.visible = false
977
+ @buttons.push b
978
+ end
979
+ @max_h = (@options.size + 1) * @h
980
+ end
981
+
982
+ # Updates the control.
983
+ def update
984
+ return unless @enabled and @visible
985
+ if @open and Mouse.button_pressed? :left and not Mouse.over?(@x, @y, @w, @max_h)
986
+ toggle
987
+ return
988
+ end
989
+ @buttons.each { |b| b.update }
990
+ end
991
+
992
+ # Sets the currently selected value of the drop-down list. It is ignored if
993
+ # it is not among the available options.
994
+ def value=(val)
995
+ if @options.include? val
996
+ @value = @buttons[0].text = val
997
+ end
998
+ end
999
+
1000
+ def enabled=(value) # :nodoc:
1001
+ toggle if @open
1002
+ @buttons[0].enabled = value
1003
+ @enabled = value
1004
+ end
1005
+
1006
+ # Draws the drop-down list.
1007
+ #
1008
+ # Parameters:
1009
+ # [alpha] (+Fixnum+) The opacity with which the drop-down list will be
1010
+ # drawn. Allowed values vary between 0 (fully transparent) and 255
1011
+ # (fully opaque).
1012
+ # [z_index] (+Fixnum+) The z-order to draw the object. Objects with larger
1013
+ # z-orders will be drawn on top of the ones with smaller z-orders.
1014
+ def draw(alpha = 0xff, z_index = 0)
1015
+ return unless @visible
1016
+ unless @img
1017
+ bottom = @open ? @y + @max_h + 1 : @y + @h + 1
1018
+ b_color = (alpha << 24)
1019
+ G.window.draw_quad @x - 1, @y - 1, b_color,
1020
+ @x + @w + 1, @y - 1, b_color,
1021
+ @x + @w + 1, bottom, b_color,
1022
+ @x - 1, bottom, b_color, z_index
1023
+ @buttons.each do |b|
1024
+ color = (alpha << 24) | (b.state == :over ? 0xcccccc : 0xffffff)
1025
+ G.window.draw_quad b.x, b.y, color,
1026
+ b.x + b.w, b.y, color,
1027
+ b.x + b.w, b.y + b.h, color,
1028
+ b.x, b.y + b.h, color, z_index if b.visible
1029
+ end
1030
+ end
1031
+ @buttons.each { |b| b.draw alpha, z_index }
1032
+ end
1033
+
1034
+ private
1035
+
1036
+ def toggle
1037
+ if @open
1038
+ @buttons[1..-1].each { |b| b.visible = false }
1039
+ @open = false
1040
+ else
1041
+ @buttons[1..-1].each { |b| b.visible = true }
1042
+ @open = true
1043
+ end
1044
+ end
1045
+ end
694
1046
  end