metro-ld25 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +12 -0
  6. data/Guardfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +189 -0
  9. data/Rakefile +18 -0
  10. data/bin/metro +16 -0
  11. data/changelog.md +157 -0
  12. data/lib/assets/menu-movement.wav +0 -0
  13. data/lib/assets/menu-selection.wav +0 -0
  14. data/lib/assets/missing.ogg +0 -0
  15. data/lib/assets/missing.png +0 -0
  16. data/lib/assets/missing.wav +0 -0
  17. data/lib/assets/missing_animation.png +0 -0
  18. data/lib/commands/generate_game.rb +13 -0
  19. data/lib/commands/generate_model.rb +25 -0
  20. data/lib/commands/generate_scene.rb +36 -0
  21. data/lib/commands/generate_view.rb +21 -0
  22. data/lib/commands/thor.rb +83 -0
  23. data/lib/core_ext/class.rb +14 -0
  24. data/lib/core_ext/numeric.rb +59 -0
  25. data/lib/gosu_ext/color.rb +62 -0
  26. data/lib/gosu_ext/gosu_constants.rb +53 -0
  27. data/lib/locale/en.yml +35 -0
  28. data/lib/locale/locale.rb +1 -0
  29. data/lib/metro.rb +140 -0
  30. data/lib/metro/animation.rb +135 -0
  31. data/lib/metro/animation/after_interval_factory.rb +12 -0
  32. data/lib/metro/animation/animation_factory.rb +15 -0
  33. data/lib/metro/animation/easing/ease_in.rb +15 -0
  34. data/lib/metro/animation/easing/easing.rb +51 -0
  35. data/lib/metro/animation/easing/linear.rb +15 -0
  36. data/lib/metro/animation/has_animations.rb +70 -0
  37. data/lib/metro/animation/implicit_animation.rb +100 -0
  38. data/lib/metro/animation/on_update_operation.rb +96 -0
  39. data/lib/metro/animation/scene_animation.rb +16 -0
  40. data/lib/metro/asset_path.rb +97 -0
  41. data/lib/metro/events/control_definition.rb +11 -0
  42. data/lib/metro/events/controls.rb +42 -0
  43. data/lib/metro/events/event_data.rb +60 -0
  44. data/lib/metro/events/event_dictionary.rb +52 -0
  45. data/lib/metro/events/event_factory.rb +17 -0
  46. data/lib/metro/events/event_relay.rb +300 -0
  47. data/lib/metro/events/event_state_manager.rb +63 -0
  48. data/lib/metro/events/events.rb +3 -0
  49. data/lib/metro/events/has_events.rb +108 -0
  50. data/lib/metro/events/hit_list.rb +75 -0
  51. data/lib/metro/events/unknown_sender.rb +5 -0
  52. data/lib/metro/font.rb +69 -0
  53. data/lib/metro/game.rb +102 -0
  54. data/lib/metro/game/dsl.rb +68 -0
  55. data/lib/metro/image.rb +68 -0
  56. data/lib/metro/logging.rb +33 -0
  57. data/lib/metro/missing_scene.rb +21 -0
  58. data/lib/metro/models/audio/song.rb +33 -0
  59. data/lib/metro/models/draws.rb +86 -0
  60. data/lib/metro/models/key_value_coding.rb +38 -0
  61. data/lib/metro/models/model.rb +236 -0
  62. data/lib/metro/models/model_factory.rb +32 -0
  63. data/lib/metro/models/models.rb +62 -0
  64. data/lib/metro/models/properties/animation_property.rb +115 -0
  65. data/lib/metro/models/properties/array_property.rb +24 -0
  66. data/lib/metro/models/properties/boolean_property.rb +27 -0
  67. data/lib/metro/models/properties/color_property.rb +116 -0
  68. data/lib/metro/models/properties/dimensions_property.rb +84 -0
  69. data/lib/metro/models/properties/font_property.rb +130 -0
  70. data/lib/metro/models/properties/image_property.rb +96 -0
  71. data/lib/metro/models/properties/model_property.rb +84 -0
  72. data/lib/metro/models/properties/numeric_property.rb +29 -0
  73. data/lib/metro/models/properties/options_property/no_option.rb +29 -0
  74. data/lib/metro/models/properties/options_property/options.rb +94 -0
  75. data/lib/metro/models/properties/options_property/options_property.rb +125 -0
  76. data/lib/metro/models/properties/position_property.rb +90 -0
  77. data/lib/metro/models/properties/property.rb +221 -0
  78. data/lib/metro/models/properties/property_owner.rb +137 -0
  79. data/lib/metro/models/properties/sample_property.rb +84 -0
  80. data/lib/metro/models/properties/scale_property.rb +80 -0
  81. data/lib/metro/models/properties/song_property.rb +89 -0
  82. data/lib/metro/models/properties/text_property.rb +75 -0
  83. data/lib/metro/models/ui/animated_sprite.rb +85 -0
  84. data/lib/metro/models/ui/border.rb +95 -0
  85. data/lib/metro/models/ui/fps.rb +54 -0
  86. data/lib/metro/models/ui/generic.rb +66 -0
  87. data/lib/metro/models/ui/grid_drawer.rb +74 -0
  88. data/lib/metro/models/ui/image.rb +87 -0
  89. data/lib/metro/models/ui/label.rb +175 -0
  90. data/lib/metro/models/ui/menu.rb +214 -0
  91. data/lib/metro/models/ui/model_label.rb +65 -0
  92. data/lib/metro/models/ui/model_labeler.rb +79 -0
  93. data/lib/metro/models/ui/rectangle.rb +59 -0
  94. data/lib/metro/models/ui/sprite.rb +79 -0
  95. data/lib/metro/models/ui/tile_map.rb +162 -0
  96. data/lib/metro/models/ui/ui.rb +13 -0
  97. data/lib/metro/parameters/command_line_args_parser.rb +68 -0
  98. data/lib/metro/parameters/options.rb +25 -0
  99. data/lib/metro/parameters/parameters.rb +2 -0
  100. data/lib/metro/sample.rb +40 -0
  101. data/lib/metro/scene.rb +477 -0
  102. data/lib/metro/scenes.rb +154 -0
  103. data/lib/metro/song.rb +56 -0
  104. data/lib/metro/template_message.rb +60 -0
  105. data/lib/metro/transitions/edit_transition_scene.rb +100 -0
  106. data/lib/metro/transitions/fade_transition_scene.rb +66 -0
  107. data/lib/metro/transitions/scene_transitions.rb +44 -0
  108. data/lib/metro/transitions/transition_scene.rb +19 -0
  109. data/lib/metro/units/bounds.rb +8 -0
  110. data/lib/metro/units/calculation_validations.rb +74 -0
  111. data/lib/metro/units/dimensions.rb +60 -0
  112. data/lib/metro/units/point.rb +51 -0
  113. data/lib/metro/units/rectangle_bounds.rb +85 -0
  114. data/lib/metro/units/scale.rb +46 -0
  115. data/lib/metro/units/units.rb +6 -0
  116. data/lib/metro/version.rb +32 -0
  117. data/lib/metro/views/json_view.rb +60 -0
  118. data/lib/metro/views/no_view.rb +34 -0
  119. data/lib/metro/views/parsers.rb +42 -0
  120. data/lib/metro/views/scene_view.rb +107 -0
  121. data/lib/metro/views/view.rb +133 -0
  122. data/lib/metro/views/writers.rb +43 -0
  123. data/lib/metro/views/yaml_view.rb +94 -0
  124. data/lib/metro/window.rb +94 -0
  125. data/lib/setup_handlers/exit_if_dry_run.rb +26 -0
  126. data/lib/setup_handlers/game_execution.rb +65 -0
  127. data/lib/setup_handlers/load_game_configuration.rb +65 -0
  128. data/lib/setup_handlers/load_game_files.rb +101 -0
  129. data/lib/setup_handlers/move_to_game_directory.rb +25 -0
  130. data/lib/setup_handlers/reload_game_on_game_file_changes.rb +79 -0
  131. data/lib/templates/game/README.md.tt +52 -0
  132. data/lib/templates/game/assets/brand.jpg +0 -0
  133. data/lib/templates/game/assets/hero.png +0 -0
  134. data/lib/templates/game/lib/custom_easing.rb +32 -0
  135. data/lib/templates/game/metro.tt +63 -0
  136. data/lib/templates/game/models/hero.rb +62 -0
  137. data/lib/templates/game/scenes/brand_scene.rb +19 -0
  138. data/lib/templates/game/scenes/brand_to_title_scene.rb +13 -0
  139. data/lib/templates/game/scenes/first_scene.rb +28 -0
  140. data/lib/templates/game/scenes/game_scene.rb +43 -0
  141. data/lib/templates/game/scenes/title_scene.rb +15 -0
  142. data/lib/templates/game/views/brand.yaml +4 -0
  143. data/lib/templates/game/views/brand_to_title.yaml +8 -0
  144. data/lib/templates/game/views/first.yaml +26 -0
  145. data/lib/templates/game/views/title.yaml +11 -0
  146. data/lib/templates/message.erb +23 -0
  147. data/lib/templates/model.rb.tt +111 -0
  148. data/lib/templates/scene.rb.tt +140 -0
  149. data/lib/templates/view.yaml.tt +11 -0
  150. data/lib/tmxed_ext/tile_set.rb +34 -0
  151. data/metro.gemspec +56 -0
  152. data/spec/core_ext/numeric_spec.rb +78 -0
  153. data/spec/core_ext/string_spec.rb +33 -0
  154. data/spec/gosu_ext/color_spec.rb +80 -0
  155. data/spec/metro/events/event_state_manager_spec.rb +5 -0
  156. data/spec/metro/models/key_value_coding_spec.rb +61 -0
  157. data/spec/metro/models/properties/array_property_spec.rb +60 -0
  158. data/spec/metro/models/properties/color_property_spec.rb +85 -0
  159. data/spec/metro/models/properties/dimensions_spec.rb +29 -0
  160. data/spec/metro/models/properties/font_property_spec.rb +127 -0
  161. data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
  162. data/spec/metro/models/properties/options_property/no_option_spec.rb +25 -0
  163. data/spec/metro/models/properties/options_property/options_property_spec.rb +133 -0
  164. data/spec/metro/models/properties/options_property/options_spec.rb +125 -0
  165. data/spec/metro/models/properties/position_property_spec.rb +90 -0
  166. data/spec/metro/models/ui/label_spec.rb +259 -0
  167. data/spec/metro/parameters/command_line_args_parser_spec.rb +42 -0
  168. data/spec/metro/scene_spec.rb +15 -0
  169. data/spec/metro/scene_views/json_view_spec.rb +27 -0
  170. data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
  171. data/spec/metro/scenes_spec.rb +77 -0
  172. data/spec/metro/units/point_spec.rb +132 -0
  173. data/spec/metro/views/view_spec.rb +53 -0
  174. data/spec/setup_handlers/exit_if_dry_run_spec.rb +27 -0
  175. data/spec/setup_handlers/reload_game_on_game_file_changes_spec.rb +68 -0
  176. data/spec/spec_helper.rb +20 -0
  177. metadata +374 -0
@@ -0,0 +1,130 @@
1
+ module Metro
2
+ class Model
3
+
4
+ #
5
+ # A font property maintains a Gosu::Font.
6
+ #
7
+ # A font property also defines a `font_size` property and a `font_name` property which allows a
8
+ # more direct interface. Changing these values will update the font the next time that it is drawn.
9
+ #
10
+ # A font is stored in the properties as a hash representation and is converted into
11
+ # a Gosu::Font when it is retrieved within the system. When retrieving a font the Font
12
+ # Property will attempt to use a font that already exists that meets that criteria.
13
+ #
14
+ # The fonts are cached within the font property to help performance by reducing the unncessary
15
+ # creation of similar fonts.
16
+ #
17
+ # @example Defining a font property
18
+ #
19
+ # class Scoreboard < Metro::Model
20
+ # property :font
21
+ #
22
+ # def draw
23
+ # font.draw text, x, y, z_order, x_factor, y_factor, color
24
+ # end
25
+ #
26
+ # end
27
+ #
28
+ # @example Defining a font property providing a default
29
+ #
30
+ # class Hero < Metro::Model
31
+ # property :font, default: { name: 'Comic Sans', size: 80 }
32
+ # end
33
+ #
34
+ # @example Using the `font_size` and `font_name` properties
35
+ #
36
+ # class Hero < Metro::Model
37
+ # property :font, default: { name: 'Comic Sans', size: 80 }
38
+ # property :color, default: "rgba(255,0,0,1.0)"
39
+ #
40
+ # def dignified
41
+ # self.font_size = 45
42
+ # self.font_name = 'Helvetica'
43
+ # end
44
+ # end
45
+ #
46
+ # @example Using a font property with a different property name
47
+ #
48
+ # class Hero < Metro::Model
49
+ # property :alt_font, type: :font, default: { name: 'Helvetica', size: 80 }
50
+ #
51
+ # def draw
52
+ # puts "Font: #{alt_font_name}:#{alt_font_size}"
53
+ # alt_font.draw text, x, y, z_order, x_factor, y_factor, color
54
+ # end
55
+ # end
56
+ #
57
+ class FontProperty < Property
58
+
59
+ # Define a paired property which allows the setting of the font size
60
+ define_property :size, prefix: true
61
+ # Define a paired property which allows the setting of the font name
62
+ define_property :name, type: :text, prefix: true
63
+
64
+ # Return the default font when the value is not supported.
65
+ get do
66
+ default_font
67
+ end
68
+
69
+ # Create a font from the specified hash of data.
70
+ #
71
+ # @example Format of Hash
72
+ #
73
+ # { name: 'Times New Roman', size: 33 }
74
+ #
75
+ get Hash do |value|
76
+ self.class.font_for value.merge(window: model.window)
77
+ end
78
+
79
+ # Save a hash of the default font when the value is not supported.
80
+ set do
81
+ { name: default_font_name, size: default_font_size }
82
+ end
83
+
84
+ # Save a hash representation of the font when given a font
85
+ set Metro::Font do |font|
86
+ { name: font.name, size: font.height }
87
+ end
88
+
89
+ # Save the hash provided. It is assumed to contain the correct font data.
90
+ set Hash, HashWithIndifferentAccess do |hash|
91
+ hash.to_hash
92
+ end
93
+
94
+ #
95
+ # @return the default font to use when a value has not been provided.
96
+ #
97
+ def default_font
98
+ self.class.font_for name: default_font_name,
99
+ size: default_font_size,
100
+ window: model.window
101
+ end
102
+
103
+ #
104
+ # Use the specified default font size or fall back to 40.
105
+ #
106
+ def default_font_size
107
+ (options[:default] and options[:default][:size]) ? options[:default][:size] : 40
108
+ end
109
+
110
+ #
111
+ # Use the specified default font name or fall back to Gosu's default font name.
112
+ #
113
+ def default_font_name
114
+ (options[:default] and options[:default][:name]) ? options[:default][:name] : Gosu::default_font_name
115
+ end
116
+
117
+ #
118
+ # Return a font that matches the specified criteria. Usig the name, size, and window a font will be
119
+ # generated or retrieved from the cache.
120
+ #
121
+ # @param [Hash] value the hash that contains the `name`, `size` and `window` that describe the font.
122
+ #
123
+ def self.font_for(value)
124
+ Font.find_or_create(value)
125
+ end
126
+
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,96 @@
1
+ module Metro
2
+ class Model
3
+
4
+ #
5
+ # A image property maintains a Gosu::Image.
6
+ #
7
+ # An image is stored in the properties as a string to the specified image path and is converted into
8
+ # a Gosu::Image when it is retrieved within the system. When retrieving an image the Image
9
+ # Property will attempt to use a image at that path that already meets that criteria if it has been
10
+ # loaded.
11
+ #
12
+ # @example Defining a image property
13
+ #
14
+ # class Player < Metro::Model
15
+ # property :image
16
+ #
17
+ # def draw
18
+ # image.draw x, y, z_order, x_factor, y_factor, color, :add)
19
+ # end
20
+ #
21
+ # end
22
+ #
23
+ # @example Defining an image property providing a path
24
+ #
25
+ # class Player < Metro::Model
26
+ # property :image, path: "player.png"
27
+ # end
28
+ #
29
+ # @example Using an image property with a different property name
30
+ #
31
+ # class Player < Metro::Model
32
+ # property :disconnected_image, type: :image, path: "disconnected_player.png"
33
+ #
34
+ # def draw
35
+ # disconnected_image.draw x, y, z_order, x_factor, y_factor, color, :add)
36
+ # end
37
+ # end
38
+ #
39
+ class ImageProperty < Property
40
+
41
+ # By default, getting will use the the default image.
42
+ get do
43
+ default_image
44
+ end
45
+
46
+ # Return the image at the specified path.
47
+ get String do |path|
48
+ self.class.image_for path: path, window: model.window
49
+ end
50
+
51
+ # By default, setting will use the path of the default image.
52
+ set do
53
+ default_image.path
54
+ end
55
+
56
+ # Set the image with the specified path.
57
+ set String do |path|
58
+ path
59
+ end
60
+
61
+ # Set the image with the given image. A Gosu::Image does not normally
62
+ # store it's path, however, this functionality has been monkey-patched.
63
+ set Metro::Image do |image|
64
+ image.path
65
+ end
66
+
67
+ #
68
+ # @return the default image based on the default image path specified.
69
+ #
70
+ def default_image
71
+ self.class.image_for path: default_image_path, window: model.window
72
+ end
73
+
74
+ #
75
+ # @return the path provided as the default or if one has not been specified
76
+ # the default "missing.png"
77
+ #
78
+ def default_image_path
79
+ options[:path] or "missing.png"
80
+ end
81
+
82
+ #
83
+ # Return an image for the specified path. On first request it will be loaded from
84
+ # the file-system. On subsequent requests it will be pulled from the cache.
85
+ #
86
+ # @param [Hash] options the relative `path` to the image and the window for which it
87
+ # will be displayed.
88
+ #
89
+ def self.image_for(options)
90
+ Metro::Image.find_or_create(options)
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,84 @@
1
+ module Metro
2
+ class Model
3
+
4
+ #
5
+ # A model property maintains a reference to another model. This property
6
+ # allows for an existing model to be more easily composed with other models.
7
+ #
8
+ # The model is stored as a hash which describes the model.
9
+ #
10
+ # @example Defining a model property with a block
11
+ #
12
+ # class ScoreBoard < Metro::Model
13
+ # property :position
14
+ # property :score
15
+ # property :label, type: :model do
16
+ # create "metro::ui::label", text: "", position: position
17
+ # end
18
+ # end
19
+ #
20
+ # @example Defining a model property with a hash
21
+ #
22
+ # class ScoreBoard < Metro::Model
23
+ # property :position
24
+ # property :score
25
+ # property :label, type: :model, default: { model: "metro::ui::label",
26
+ # text: "", position: position }
27
+ # end
28
+ # end
29
+ #
30
+ class ModelProperty < Property
31
+
32
+ # When retrieving a model and the type is unsupported generate the
33
+ # model instance from the default.
34
+ get do
35
+ default_model
36
+ end
37
+
38
+ # When retrieving a hash representation of the model, convert it into
39
+ # a Metro::Model instance.
40
+ get Hash do |params|
41
+ create_model params
42
+ end
43
+
44
+ # When setting the property with an unsupported type, simply save an
45
+ # empty hash. Which later, if retrieved, it will generate a generic
46
+ # model.
47
+ set do
48
+ {}
49
+ end
50
+
51
+ # When setting the property with a hash, assume that the hash is a
52
+ # valid description of a Metro::Model.
53
+ set Hash, HashWithIndifferentAccess do |hash|
54
+ hash
55
+ end
56
+
57
+ # When setting the property with a Metro::Model, convert the model into
58
+ # a hash.
59
+ set Metro::Model do |model|
60
+ model.to_hash
61
+ end
62
+
63
+ #
64
+ # Allow for a model property to be defined with a block initialization or
65
+ # a default hash.
66
+ #
67
+ def default_model
68
+ if block
69
+ model.instance_eval(&block)
70
+ else
71
+ create_model options[:default]
72
+ end
73
+ end
74
+
75
+ # @return [Metro::Model] return a model created by the current model that
76
+ # owns the property.
77
+ def create_model
78
+ model.create params[:model], params.except(:model)
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,29 @@
1
+ module Metro
2
+ class Model
3
+
4
+ #
5
+ # The numeric property will simply convert any input into a floating
6
+ # point value. This is the same both on getting and setting.
7
+ #
8
+ class NumericProperty < Property
9
+
10
+ # For all cases the value is converted to floating point when it can
11
+ # otherwise the default number is used.
12
+ get_or_set do |value|
13
+ if value.is_a?(NilClass)
14
+ default_number
15
+ elsif value.respond_to?(:to_f)
16
+ value.to_f
17
+ else
18
+ default_number
19
+ end
20
+ end
21
+
22
+ def default_number
23
+ options[:default].to_f
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Metro
2
+ class Model
3
+ class OptionsProperty
4
+
5
+ #
6
+ # When the options cannot find a selected menu option then this no option
7
+ # is returned instead of a nil value. This allows for a warning to be generated
8
+ # if any methods target this item.
9
+ #
10
+ # Also if the option will send a 'missing_menu_action' if the options were to
11
+ # ask for the selected action.
12
+ #
13
+ class NoOption
14
+ def method_missing(name,*args,&block)
15
+ log.warn warning_message
16
+ end
17
+
18
+ def warning_message
19
+ "No valid options were found in the menu"
20
+ end
21
+
22
+ def properties
23
+ { action: :missing_menu_action }
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,94 @@
1
+ module Metro
2
+ class Model
3
+ class OptionsProperty
4
+
5
+ #
6
+ # Options maintains the list of menu options that would be displayed in a menu.
7
+ # Each option is a component that can be rendered during the draw phase.
8
+ #
9
+ # Also, options maintains the currently selected item and has the ability to manage
10
+ # the changes from the previous.
11
+ #
12
+ class Options < SimpleDelegator
13
+
14
+ #
15
+ # Generate an empty set of options.
16
+ #
17
+ def self.empty
18
+ new []
19
+ end
20
+
21
+ #
22
+ # Create options with the provided array of options.
23
+ #
24
+ # @param [Array] options the array of options that this object will maintain
25
+ # as it's list of options.
26
+ #
27
+ def initialize(options)
28
+ super(options)
29
+ end
30
+
31
+ #
32
+ # @return [Fixnum] the index of the current selected option.
33
+ #
34
+ def current_selected_index
35
+ @current_selected_index ||= 0
36
+ end
37
+
38
+ #
39
+ # Set the index of the currently selected item. Values that exceed the possible
40
+ # count of options will reset to the beginning of the list of options.
41
+ # Values that proceed the start of of the list of options will fallback to the last option.
42
+ #
43
+ def current_selected_index=(value)
44
+ @current_selected_index = value || 0
45
+ @current_selected_index = 0 if @current_selected_index >= count
46
+ @current_selected_index = count - 1 if @current_selected_index <= -1
47
+ @current_selected_index
48
+ end
49
+
50
+ #
51
+ # @return [Array] a list of all the options that are currently not selected.
52
+ #
53
+ def unselected
54
+ self - [ selected ]
55
+ end
56
+
57
+ #
58
+ # @return [Object] the currently selected option.
59
+ #
60
+ def selected
61
+ at(current_selected_index) || NoOption.new
62
+ end
63
+
64
+ #
65
+ # @return [Symbol] the action name of the currently selected option. If no
66
+ # option is currently selected then the NoOption 'missing_menu_action' will be
67
+ # returned.
68
+ #
69
+ def selected_action
70
+ if selected.respond_to?(:properties) && selected.properties[:action]
71
+ selected.properties[:action]
72
+ else
73
+ selected.to_sym
74
+ end
75
+ end
76
+
77
+ #
78
+ # Move the current selected item to the next item
79
+ #
80
+ def next!
81
+ self.current_selected_index += 1
82
+ end
83
+
84
+ #
85
+ # Move the current selected item to the previous item
86
+ #
87
+ def previous!
88
+ self.current_selected_index -= 1
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end