minigl 1.3.10 → 2.0.0

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