fidgit 0.0.2alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +2 -0
  3. data/COPYING.txt +674 -0
  4. data/Gemfile +4 -0
  5. data/README.textile +138 -0
  6. data/Rakefile +38 -0
  7. data/config/default_schema.yml +180 -0
  8. data/examples/_all_examples.rb +9 -0
  9. data/examples/align_example.rb +56 -0
  10. data/examples/button_and_toggle_button_example.rb +27 -0
  11. data/examples/color_picker_example.rb +17 -0
  12. data/examples/color_well_example.rb +25 -0
  13. data/examples/combo_box_example.rb +24 -0
  14. data/examples/file_dialog_example.rb +42 -0
  15. data/examples/grid_packer_example.rb +29 -0
  16. data/examples/helpers/example_window.rb +17 -0
  17. data/examples/label_example.rb +17 -0
  18. data/examples/list_example.rb +23 -0
  19. data/examples/media/images/head_icon.png +0 -0
  20. data/examples/menu_pane_example.rb +27 -0
  21. data/examples/message_dialog_example.rb +65 -0
  22. data/examples/radio_button_example.rb +37 -0
  23. data/examples/readme_example.rb +32 -0
  24. data/examples/scroll_window_example.rb +49 -0
  25. data/examples/slider_example.rb +30 -0
  26. data/examples/splash_example.rb +42 -0
  27. data/examples/text_area_example.rb +28 -0
  28. data/fidgit.gemspec +28 -0
  29. data/lib/fidgit.rb +4 -0
  30. data/lib/fidgit/chingu_ext/window.rb +6 -0
  31. data/lib/fidgit/clipboard.rb +23 -0
  32. data/lib/fidgit/cursor.rb +38 -0
  33. data/lib/fidgit/elements/button.rb +68 -0
  34. data/lib/fidgit/elements/color_picker.rb +63 -0
  35. data/lib/fidgit/elements/color_well.rb +39 -0
  36. data/lib/fidgit/elements/combo_box.rb +85 -0
  37. data/lib/fidgit/elements/composite.rb +17 -0
  38. data/lib/fidgit/elements/container.rb +187 -0
  39. data/lib/fidgit/elements/element.rb +252 -0
  40. data/lib/fidgit/elements/file_browser.rb +152 -0
  41. data/lib/fidgit/elements/grid_packer.rb +219 -0
  42. data/lib/fidgit/elements/group.rb +66 -0
  43. data/lib/fidgit/elements/horizontal_packer.rb +12 -0
  44. data/lib/fidgit/elements/label.rb +77 -0
  45. data/lib/fidgit/elements/list.rb +47 -0
  46. data/lib/fidgit/elements/menu_pane.rb +149 -0
  47. data/lib/fidgit/elements/packer.rb +42 -0
  48. data/lib/fidgit/elements/radio_button.rb +86 -0
  49. data/lib/fidgit/elements/scroll_area.rb +75 -0
  50. data/lib/fidgit/elements/scroll_bar.rb +114 -0
  51. data/lib/fidgit/elements/scroll_window.rb +92 -0
  52. data/lib/fidgit/elements/slider.rb +119 -0
  53. data/lib/fidgit/elements/text_area.rb +351 -0
  54. data/lib/fidgit/elements/toggle_button.rb +67 -0
  55. data/lib/fidgit/elements/tool_tip.rb +35 -0
  56. data/lib/fidgit/elements/vertical_packer.rb +12 -0
  57. data/lib/fidgit/event.rb +99 -0
  58. data/lib/fidgit/gosu_ext/color.rb +123 -0
  59. data/lib/fidgit/history.rb +85 -0
  60. data/lib/fidgit/redirector.rb +83 -0
  61. data/lib/fidgit/schema.rb +123 -0
  62. data/lib/fidgit/selection.rb +106 -0
  63. data/lib/fidgit/standard_ext/hash.rb +21 -0
  64. data/lib/fidgit/states/dialog_state.rb +42 -0
  65. data/lib/fidgit/states/file_dialog.rb +24 -0
  66. data/lib/fidgit/states/gui_state.rb +301 -0
  67. data/lib/fidgit/states/message_dialog.rb +61 -0
  68. data/lib/fidgit/thumbnail.rb +29 -0
  69. data/lib/fidgit/version.rb +5 -0
  70. data/lib/fidgit/window.rb +19 -0
  71. data/media/images/arrow.png +0 -0
  72. data/media/images/file_directory.png +0 -0
  73. data/media/images/file_file.png +0 -0
  74. data/media/images/pixel.png +0 -0
  75. data/spec/fidgit/elements/helpers/helper.rb +3 -0
  76. data/spec/fidgit/elements/label_spec.rb +49 -0
  77. data/spec/fidgit/event_spec.rb +149 -0
  78. data/spec/fidgit/gosu_ext/color_spec.rb +130 -0
  79. data/spec/fidgit/gosu_ext/helpers/helper.rb +3 -0
  80. data/spec/fidgit/helpers/helper.rb +4 -0
  81. data/spec/fidgit/helpers/tex_play_helper.rb +9 -0
  82. data/spec/fidgit/history_spec.rb +144 -0
  83. data/spec/fidgit/redirector_spec.rb +78 -0
  84. data/spec/fidgit/schema_spec.rb +67 -0
  85. data/spec/fidgit/schema_test.yml +32 -0
  86. data/spec/fidgit/thumbnail_spec.rb +50 -0
  87. metadata +177 -0
@@ -0,0 +1,187 @@
1
+ # encoding: utf-8
2
+
3
+ module Fidgit
4
+ # A container that contains Elements.
5
+ # @abstract
6
+ class Container < Element
7
+ def size; @children.size; end
8
+ def each(&block); @children.each &block; end
9
+ def find(&block); @children.find &block; end
10
+ def index(value); @children.index value; end
11
+ def [](index); @children[index]; end
12
+
13
+ def x=(value)
14
+ each {|c| c.x += value - x }
15
+ super(value)
16
+ end
17
+
18
+ def y=(value)
19
+ each {|c| c.y += value - y }
20
+ super(value)
21
+ end
22
+
23
+ # @param (see Element#initialize)
24
+ #
25
+ # @option (see Element#initialize)
26
+ def initialize(options = {})
27
+ options[:border_color] = default(:debug, :border_color) if Fidgit.debug_mode?
28
+
29
+ @children = []
30
+
31
+ super(options)
32
+ end
33
+
34
+ def add(element)
35
+ element.send :parent=, self
36
+ @children.push element
37
+
38
+ recalc
39
+ nil
40
+ end
41
+
42
+ def remove(element)
43
+ @children.delete element
44
+ element.send :parent=, nil
45
+
46
+ recalc
47
+ nil
48
+ end
49
+
50
+ def insert(position, element)
51
+ @children.insert position, element
52
+ element.send :parent=, self
53
+
54
+ recalc
55
+ nil
56
+ end
57
+
58
+ # Create a button within the container.
59
+ def button(text, options = {}, &block)
60
+ Button.new(text, {parent: self}.merge!(options), &block)
61
+ end
62
+
63
+ # Create a color picker within the container.
64
+ def color_picker(options = {}, &block)
65
+ ColorPicker.new({parent: self}.merge!(options), &block)
66
+ end
67
+
68
+ # Create a color well within the container.
69
+ def color_well(options = {}, &block)
70
+ ColorWell.new({parent: self}.merge!(options), &block)
71
+ end
72
+
73
+ def combo_box(options = {}, &block)
74
+ ComboBox.new({parent: self}.merge!(options), &block)
75
+ end
76
+
77
+ def file_browser(type, options = {}, &block)
78
+ FileBrowser.new(type, {parent: self}.merge!(options), &block)
79
+ end
80
+
81
+ def group(options = {}, &block)
82
+ Group.new({parent: self}.merge!(options), &block)
83
+ end
84
+
85
+ # Create a label within the container.
86
+ def label(text, options = {})
87
+ Label.new(text, {parent: self}.merge!(options))
88
+ end
89
+
90
+ def list(options = {}, &block)
91
+ List.new({parent: self}.merge!(options), &block)
92
+ end
93
+
94
+ def pack(arrangement, options = {}, &block)
95
+ klass = case arrangement
96
+ when :horizontal
97
+ HorizontalPacker
98
+ when :vertical
99
+ VerticalPacker
100
+ when :grid
101
+ GridPacker
102
+ else
103
+ raise ArgumentError, "packing arrangement must be one of :horizontal, :vertical or :grid"
104
+ end
105
+
106
+ klass.new({parent: self}.merge!(options), &block)
107
+ end
108
+
109
+ def radio_button(text, value, options = {}, &block)
110
+ RadioButton.new(text, value, {parent: self}.merge!(options), &block)
111
+ end
112
+
113
+ def scroll_area(options = {}, &block)
114
+ ScrollArea.new({parent: self}.merge!(options), &block)
115
+ end
116
+
117
+ def scroll_window(options = {}, &block)
118
+ ScrollWindow.new({parent: self}.merge!(options), &block)
119
+ end
120
+
121
+ def slider(options = {}, &block)
122
+ Slider.new({parent: self}.merge!(options), &block)
123
+ end
124
+
125
+ def text_area(options = {}, &block)
126
+ TextArea.new({parent: self}.merge!(options), &block)
127
+ end
128
+
129
+ def toggle_button(text, options = {}, &block)
130
+ ToggleButton.new(text, {parent: self}.merge!(options), &block)
131
+ end
132
+
133
+ def clear
134
+ @children.each {|child| child.send :parent=, nil }
135
+ @children.clear
136
+
137
+ recalc
138
+
139
+ nil
140
+ end
141
+
142
+ def update
143
+ each { |c| c.update }
144
+
145
+ nil
146
+ end
147
+
148
+ # Returns the element within this container that was hit,
149
+ # @return [Element, nil] The element hit, otherwise nil.
150
+ def hit_element(x, y)
151
+ @children.reverse_each do |child|
152
+ case child
153
+ when Container, Composite
154
+ if element = child.hit_element(x, y)
155
+ return element
156
+ end
157
+ else
158
+ return child if child.hit?(x, y)
159
+ end
160
+ end
161
+
162
+ self if hit?(x, y)
163
+ end
164
+
165
+ protected
166
+ def draw_foreground
167
+ each { |c| c.draw }
168
+
169
+ font.draw self.class.name, x, y, z if Fidgit.debug_mode?
170
+
171
+ nil
172
+ end
173
+
174
+ protected
175
+ # Any container passed a block will allow you access to its methods.
176
+ def post_init_block(&block)
177
+ case block.arity
178
+ when 1
179
+ yield self
180
+ when 0
181
+ instance_methods_eval &block
182
+ else
183
+ raise "block arity must be 0 or 1"
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,252 @@
1
+ # encoding: utf-8
2
+
3
+ # The Fidgit GUI framework for Gosu.
4
+ module Fidgit
5
+ class << self
6
+ attr_accessor :debug_mode
7
+ end
8
+
9
+ self.debug_mode = false
10
+
11
+ def self.debug_mode?; debug_mode; end
12
+
13
+ # An element within the GUI environment.
14
+ # @abstract
15
+ class Element
16
+ include Event
17
+
18
+ event :left_mouse_button
19
+ event :holding_left_mouse_button
20
+ event :released_left_mouse_button
21
+ event :clicked_left_mouse_button
22
+
23
+ event :right_mouse_button
24
+ event :holding_right_mouse_button
25
+ event :released_right_mouse_button
26
+ event :clicked_right_mouse_button
27
+
28
+ event :mouse_wheel_up
29
+ event :mouse_wheel_down
30
+
31
+ event :enter
32
+ event :hover
33
+ event :leave
34
+
35
+ DEFAULT_SCHEMA_FILE = File.expand_path(File.join(__FILE__, '..', '..', '..', '..', 'config', 'default_schema.yml'))
36
+
37
+ VALID_ALIGN_H = [:left, :center, :right, :fill]
38
+ VALID_ALIGN_V = [:top, :center, :bottom, :fill]
39
+
40
+ attr_reader :z, :tip, :font_size, :padding_top, :padding_right, :padding_bottom, :padding_left, :align_h, :align_v, :parent, :border_thickness
41
+
42
+ attr_accessor :background_color
43
+
44
+ def x; rect.x; end
45
+ def x=(value); rect.x = value; end
46
+
47
+ def y; rect.y; end
48
+ def y=(value); rect.y = value; end
49
+
50
+ # Width not including border.
51
+ def width; rect.width; end
52
+ def width=(value); rect.width = [[value, @width_range.max].min, @width_range.min].max; end
53
+ def min_width; @width_range.min; end
54
+ def max_width; @width_range.max; end
55
+ # Width including border thickness.
56
+ def outer_width; rect.width + @border_thickness * 2; end
57
+
58
+ # Height not including border.
59
+ def height; rect.height; end
60
+ def height=(value); rect.height = [[value, @height_range.max].min, @height_range.min].max; end
61
+ def min_height; @height_range.min; end
62
+ def max_height; @height_range.max; end
63
+ # Height including border thickness.
64
+ def outer_height; rect.height + @border_thickness * 2; end
65
+
66
+ # Can the object be dragged?
67
+ def drag?(button); false; end
68
+
69
+ def enabled?; @enabled; end
70
+ def enabled=(value); @enabled = value; end
71
+
72
+ def font; @font ||= Gosu::Font[@font_name, @font_size]; end
73
+
74
+ def rect; @rect; end; protected :rect
75
+
76
+ def self.schema; @@schema ||= Schema.new(YAML.load(File.read(DEFAULT_SCHEMA_FILE)));; end
77
+
78
+ class << self
79
+ alias_method :original_new, :new
80
+
81
+ def new(*args, &block)
82
+ obj = original_new(*args) # Block should be ignored.
83
+ obj.send :post_init
84
+ obj.send :post_init_block, &block if block_given?
85
+ obj
86
+ end
87
+ end
88
+
89
+ # Get the default value from the schema.
90
+ #
91
+ # @param [Symbol, Array<Symbol>] names
92
+ def default(*names)
93
+ self.class.schema.default(self.class, names)
94
+ end
95
+
96
+ # @param [Element, nil] parent
97
+ #
98
+ # @option options [Number] :x (0)
99
+ # @option options [Number] :y (0)
100
+ # @option options [Number] :z (0)
101
+ #
102
+ # @option options [Number] :width (auto)
103
+ # @option options [Number] :min_width (value of :width option)
104
+ # @option options [Number] :max_width (value of :width option)
105
+ #
106
+ # @option options [Number] :height (auto)
107
+ # @option options [Number] :min_height (value of :height option)
108
+ # @option options [Number] :max_height (value of :height option)
109
+ #
110
+ # @option options [String] :tip ('') Tool-tip text
111
+ # @option options [String] :font_name ('')
112
+ # @option options [String] :font_size (30)
113
+ #
114
+ # @option options [Gosu::Color] :background_color (transparent)
115
+ # @option options [Gosu::Color] :border_color (transparent)
116
+ #
117
+ # @option options [Boolean] :enabled (true)
118
+ #
119
+ # @option options [Number] :padding (4)
120
+ # @option options [Number] :padding_h (:padding option)
121
+ # @option options [Number] :padding_v (:padding option)
122
+ # @option options [Number] :padding_top (:padding_v option)
123
+ # @option options [Number] :padding_right (:padding_h option)
124
+ # @option options [Number] :padding_bottom (:padding_v option)
125
+ # @option options [Number] :padding_left (:padding_h option)
126
+ #
127
+ # @option options [Symbol] :align Align both horizontally and vertically. One of :center, :fill or [<align_v>, <align_h>] such as [:top, :right].
128
+ # @option options [Symbol] :align_h (value or :align else :left) One of :left, :center, :right :fill
129
+ # @option options [Symbol] :align_v (value of :align else :top) One of :top, :center, :bottom, :fill
130
+
131
+ # @yield instance_methods_eval with respect to self.
132
+ def initialize(options = {}, &block)
133
+ options = {
134
+ x: 0,
135
+ y: 0,
136
+ z: 0,
137
+ tip: '',
138
+ font_name: default(:font_name),
139
+ font_size: default(:font_size),
140
+ background_color: default(:background_color),
141
+ border_color: default(:border_color),
142
+ border_thickness: default(:border_thickness),
143
+ enabled: true,
144
+ }.merge! options
145
+
146
+ @enabled = options[:enabled]
147
+
148
+ # Alignment and min/max dimensions.
149
+ @align_h = options[:align_h] || Array(options[:align]).last || default(:align_h)
150
+ raise ArgumentError, "Invalid align_h: #{@align_h}" unless VALID_ALIGN_H.include? @align_h
151
+
152
+ min_width = (options[:min_width] || options[:width] || 0)
153
+ max_width = (options[:max_width] || options[:width] || Float::INFINITY)
154
+ @width_range = min_width..max_width
155
+
156
+ @align_v = options[:align_v] || Array(options[:align]).first || default(:align_v)
157
+ raise ArgumentError, "Invalid align_v: #{@align_v}" unless VALID_ALIGN_V.include? @align_v
158
+
159
+ min_height = (options[:min_height] || options[:height] || 0)
160
+ max_height = (options[:max_height] || options[:height] || Float::INFINITY)
161
+ @height_range = min_height..max_height
162
+
163
+ @background_color = options[:background_color].dup
164
+ @border_color = options[:border_color].dup
165
+ @border_thickness = options[:border_thickness]
166
+
167
+ @padding_top = options[:padding_top] || options[:padding_v] || options[:padding] || default(:padding_top)
168
+ @padding_right = options[:padding_right] || options[:padding_h] || options[:padding] || default(:padding_right)
169
+ @padding_bottom = options[:padding_bottom] || options[:padding_v] || options[:padding] || default(:padding_bottom)
170
+ @padding_left = options[:padding_left] || options[:padding_h] || options[:padding] || default(:padding_left)
171
+ self.parent = options[:parent]
172
+
173
+ @z = options[:z]
174
+ @tip = options[:tip].dup
175
+ @font_name = options[:font_name].dup
176
+ @font_size = options[:font_size]
177
+
178
+ @rect = Chingu::Rect.new(options[:x], options[:y], options[:width] || 0, options[:height] || 0)
179
+ end
180
+
181
+ def recalc
182
+ old_width, old_height = width, height
183
+ layout
184
+ parent.recalc if parent and (width != old_width or height != old_height)
185
+
186
+ nil
187
+ end
188
+
189
+ # Check if a point (screen coordinates) is over the element.
190
+ def hit?(x, y)
191
+ @rect.collide_point?(x, y)
192
+ end
193
+
194
+ # Redraw the element.
195
+ def draw
196
+ draw_background
197
+ draw_border
198
+ draw_foreground
199
+ nil
200
+ end
201
+
202
+ # Update the element.
203
+ def update
204
+ nil
205
+ end
206
+
207
+ def draw_rect(*args)
208
+ $window.current_game_state.draw_rect(*args)
209
+ end
210
+
211
+ def draw_frame(*args)
212
+ $window.current_game_state.draw_frame(*args)
213
+ end
214
+
215
+ protected
216
+ def parent=(parent); @parent = parent; end
217
+
218
+ protected
219
+ def draw_background
220
+ draw_rect(x, y, width, height, z, @background_color) unless @background_color.transparent?
221
+ end
222
+
223
+ protected
224
+ def draw_border
225
+ draw_frame(x, y, width, height, @border_thickness, z, @border_color) if @border_thickness > 0 and not @border_color.transparent?
226
+ end
227
+
228
+ protected
229
+ def draw_foreground
230
+ nil
231
+ end
232
+
233
+ protected
234
+ # Should be overridden in children to recalculate the width and height of the element and, if a container
235
+ # manage the positions of its children.
236
+ def layout
237
+ nil
238
+ end
239
+
240
+ protected
241
+ def post_init
242
+ recalc
243
+ @parent.send :add, self if @parent
244
+ end
245
+
246
+ protected
247
+ # By default, elements do not accept block arguments.
248
+ def post_init_block(&block)
249
+ raise ArgumentError, "does not accept a block"
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,152 @@
1
+ # encoding: utf-8
2
+
3
+ module Fidgit
4
+ class FileBrowser < Composite
5
+ VALID_TYPES = [:open, :save]
6
+
7
+ event :selected
8
+
9
+ attr_reader :pattern, :base_directory
10
+
11
+ def show_extension?; @show_extension; end
12
+ def directory
13
+ dir = File.join(*@directories)
14
+ dir = File.join(@base_directory, dir) unless @base_directory.empty?
15
+ dir
16
+ end
17
+ def file_name; @file_name_text.text; end
18
+ def file_path; File.join(directory, file_name); end
19
+
20
+ # @param [Symbol] type One of :open, :save
21
+ # @option options [String] :base_directory ('') Outermost directory that the browser will see.
22
+ # @option options [String] :directory (current working directory).
23
+ # @option options [String] :file_name ('') Initially selected file in the directory.
24
+ # @option options [String] :pattern ('*.*')
25
+ # @option options [Boolean] :show_extension (true)
26
+ def initialize(type, options = {})
27
+ options = {
28
+ base_directory: '',
29
+ directory: Dir.pwd,
30
+ file_name: '',
31
+ pattern: default(:pattern),
32
+ show_extension: default(:show_extension),
33
+ width: 400,
34
+ save_text: "Save",
35
+ open_text: "Open",
36
+ cancel_text: "Cancel",
37
+ }.merge! options
38
+
39
+ @type = type
40
+ raise ArgumentError, "type must be one of #{VALID_TYPES}, not #{@type}" unless VALID_TYPES.include? @type
41
+
42
+ @pattern = options[:pattern]
43
+ @show_extension = options[:show_extension]
44
+ @base_directory = options[:base_directory].chomp File::SEPARATOR
45
+
46
+ @directories = options[:directory].sub(/^#{@base_directory}/, '').split(File::SEPARATOR)
47
+ if @directories.first == ''
48
+ @directories[0] = File::SEPARATOR
49
+ end
50
+
51
+ super options
52
+
53
+ pack :vertical do
54
+ @nav_buttons = pack :horizontal, padding: 0, spacing: 2
55
+
56
+ @scroll_window = scroll_window(height: 250, width: options[:width]) do
57
+ @files_list = list(width: options[:width]) do
58
+ subscribe :changed do |sender, file_path|
59
+ if file_path
60
+ file_name = File.basename file_path
61
+ if File.directory? file_path
62
+ @directories.push file_name
63
+ create_nav_buttons
64
+ update_files_list
65
+ else
66
+ @file_name_text.text = file_name
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ @file_name_text = text_area(text: options[:file_name], max_height: font_size * 1.5, width: options[:width], border_thickness: 1)
74
+
75
+ create_nav_buttons
76
+
77
+ pack :horizontal, align: :center, padding: 0 do
78
+ @action_button = button(options[:"#{type}_text"]) do
79
+ publish :selected, @type, file_path
80
+ end
81
+
82
+ button(options[:cancel_text]) do
83
+ publish :selected, :cancel, file_path
84
+ end
85
+ end
86
+
87
+ # Ensure that the open/save button is enabled only when the path is sensible.
88
+ @file_name_text.subscribe :changed do |sender, text|
89
+ @action_button.enabled = case @type
90
+ when :open
91
+ File.exists? file_path and not File.directory? file_path
92
+ when :save
93
+ not text.empty?
94
+ end
95
+ end
96
+
97
+ update_files_list
98
+ end
99
+ end
100
+
101
+ protected
102
+ def create_nav_buttons(size = @directories.size)
103
+ @nav_buttons.clear
104
+
105
+ @directories = @directories[0..size]
106
+
107
+ @directories.each_with_index do |dir, i|
108
+ if i < @directories.size - 1
109
+ @nav_buttons.button(dir) do
110
+ create_nav_buttons(i)
111
+ end
112
+ else
113
+ @nav_buttons.label dir, border_color: @@schema.default(Button, :border_color), border_thickness: @@schema.default(Button, :border_thickness)
114
+ end
115
+ end
116
+
117
+ update_files_list
118
+ end
119
+
120
+ protected
121
+ def update_files_list
122
+ @files_list.clear
123
+ @file_name_text.text = ''
124
+ @scroll_window.offset_x = @scroll_window.offset_y = 0
125
+
126
+ # Add folders.
127
+ Dir.glob(File.join(directory, "*")).each do |file_path|
128
+ if File.directory? file_path
129
+ @files_list.item File.basename(file_path), file_path, icon: Gosu::Image["file_directory.png"]
130
+ end
131
+ end
132
+
133
+ # Add files that match the pattern.
134
+ Dir.glob(File.join(directory, pattern)).each do |file_path|
135
+ unless File.directory? file_path
136
+ file_name = if @show_extension
137
+ File.basename(file_path)
138
+ else
139
+ File.basename(file_path, File.extname(file_path))
140
+ end
141
+
142
+ @files_list.item file_name, file_path, icon: Gosu::Image["file_file.png"]
143
+ end
144
+ end
145
+ end
146
+
147
+ protected
148
+ def post_init_block(&block)
149
+ subscribe :selected, &block
150
+ end
151
+ end
152
+ end