fidgit 0.0.2alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/COPYING.txt +674 -0
- data/Gemfile +4 -0
- data/README.textile +138 -0
- data/Rakefile +38 -0
- data/config/default_schema.yml +180 -0
- data/examples/_all_examples.rb +9 -0
- data/examples/align_example.rb +56 -0
- data/examples/button_and_toggle_button_example.rb +27 -0
- data/examples/color_picker_example.rb +17 -0
- data/examples/color_well_example.rb +25 -0
- data/examples/combo_box_example.rb +24 -0
- data/examples/file_dialog_example.rb +42 -0
- data/examples/grid_packer_example.rb +29 -0
- data/examples/helpers/example_window.rb +17 -0
- data/examples/label_example.rb +17 -0
- data/examples/list_example.rb +23 -0
- data/examples/media/images/head_icon.png +0 -0
- data/examples/menu_pane_example.rb +27 -0
- data/examples/message_dialog_example.rb +65 -0
- data/examples/radio_button_example.rb +37 -0
- data/examples/readme_example.rb +32 -0
- data/examples/scroll_window_example.rb +49 -0
- data/examples/slider_example.rb +30 -0
- data/examples/splash_example.rb +42 -0
- data/examples/text_area_example.rb +28 -0
- data/fidgit.gemspec +28 -0
- data/lib/fidgit.rb +4 -0
- data/lib/fidgit/chingu_ext/window.rb +6 -0
- data/lib/fidgit/clipboard.rb +23 -0
- data/lib/fidgit/cursor.rb +38 -0
- data/lib/fidgit/elements/button.rb +68 -0
- data/lib/fidgit/elements/color_picker.rb +63 -0
- data/lib/fidgit/elements/color_well.rb +39 -0
- data/lib/fidgit/elements/combo_box.rb +85 -0
- data/lib/fidgit/elements/composite.rb +17 -0
- data/lib/fidgit/elements/container.rb +187 -0
- data/lib/fidgit/elements/element.rb +252 -0
- data/lib/fidgit/elements/file_browser.rb +152 -0
- data/lib/fidgit/elements/grid_packer.rb +219 -0
- data/lib/fidgit/elements/group.rb +66 -0
- data/lib/fidgit/elements/horizontal_packer.rb +12 -0
- data/lib/fidgit/elements/label.rb +77 -0
- data/lib/fidgit/elements/list.rb +47 -0
- data/lib/fidgit/elements/menu_pane.rb +149 -0
- data/lib/fidgit/elements/packer.rb +42 -0
- data/lib/fidgit/elements/radio_button.rb +86 -0
- data/lib/fidgit/elements/scroll_area.rb +75 -0
- data/lib/fidgit/elements/scroll_bar.rb +114 -0
- data/lib/fidgit/elements/scroll_window.rb +92 -0
- data/lib/fidgit/elements/slider.rb +119 -0
- data/lib/fidgit/elements/text_area.rb +351 -0
- data/lib/fidgit/elements/toggle_button.rb +67 -0
- data/lib/fidgit/elements/tool_tip.rb +35 -0
- data/lib/fidgit/elements/vertical_packer.rb +12 -0
- data/lib/fidgit/event.rb +99 -0
- data/lib/fidgit/gosu_ext/color.rb +123 -0
- data/lib/fidgit/history.rb +85 -0
- data/lib/fidgit/redirector.rb +83 -0
- data/lib/fidgit/schema.rb +123 -0
- data/lib/fidgit/selection.rb +106 -0
- data/lib/fidgit/standard_ext/hash.rb +21 -0
- data/lib/fidgit/states/dialog_state.rb +42 -0
- data/lib/fidgit/states/file_dialog.rb +24 -0
- data/lib/fidgit/states/gui_state.rb +301 -0
- data/lib/fidgit/states/message_dialog.rb +61 -0
- data/lib/fidgit/thumbnail.rb +29 -0
- data/lib/fidgit/version.rb +5 -0
- data/lib/fidgit/window.rb +19 -0
- data/media/images/arrow.png +0 -0
- data/media/images/file_directory.png +0 -0
- data/media/images/file_file.png +0 -0
- data/media/images/pixel.png +0 -0
- data/spec/fidgit/elements/helpers/helper.rb +3 -0
- data/spec/fidgit/elements/label_spec.rb +49 -0
- data/spec/fidgit/event_spec.rb +149 -0
- data/spec/fidgit/gosu_ext/color_spec.rb +130 -0
- data/spec/fidgit/gosu_ext/helpers/helper.rb +3 -0
- data/spec/fidgit/helpers/helper.rb +4 -0
- data/spec/fidgit/helpers/tex_play_helper.rb +9 -0
- data/spec/fidgit/history_spec.rb +144 -0
- data/spec/fidgit/redirector_spec.rb +78 -0
- data/spec/fidgit/schema_spec.rb +67 -0
- data/spec/fidgit/schema_test.yml +32 -0
- data/spec/fidgit/thumbnail_spec.rb +50 -0
- metadata +177 -0
@@ -0,0 +1,219 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
# A vertically aligned element packing container.
|
5
|
+
|
6
|
+
class GridPacker < Packer
|
7
|
+
# @return [Integer]
|
8
|
+
attr_reader :num_rows
|
9
|
+
# @return [Integer]
|
10
|
+
attr_reader :num_columns
|
11
|
+
|
12
|
+
# @note Currently only supports +num_columns+ mode (not +num_rows+).
|
13
|
+
#
|
14
|
+
# @param (see Packer#initialize)
|
15
|
+
#
|
16
|
+
# @option (see Packer#initialize)
|
17
|
+
# @option options [Integer] :num_columns Maximum number of columns to use (incompatible with :num_rows)
|
18
|
+
# @option options [Integer] :num_rows Maximum number of rows to use (incompatible with :num_columns)
|
19
|
+
def initialize(options = {})
|
20
|
+
options = {
|
21
|
+
cell_border_color: default(:cell_border_color),
|
22
|
+
cell_background_color: default(:cell_background_color),
|
23
|
+
cell_border_thickness: default(:cell_border_thickness),
|
24
|
+
}.merge! options
|
25
|
+
|
26
|
+
@num_columns = options[:num_columns]
|
27
|
+
@num_rows = options[:num_rows]
|
28
|
+
raise ArgumentError, "options :num_rows and :num_columns are not compatible" if @num_rows and @num_columns
|
29
|
+
|
30
|
+
@cell_border_color = options[:cell_border_color].dup
|
31
|
+
@cell_border_thickness = options[:cell_border_thickness]
|
32
|
+
@cell_background_color = options[:cell_background_color].dup
|
33
|
+
|
34
|
+
@type = @num_rows ? :fixed_rows : :fixed_columns
|
35
|
+
|
36
|
+
super options
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def layout
|
41
|
+
rearrange
|
42
|
+
repack
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
# Rearrange the cells based on changes to the number of rows/columns or adding/removing elements.
|
47
|
+
def rearrange
|
48
|
+
# Calculate the number of the dynamic dimension.
|
49
|
+
case @type
|
50
|
+
when :fixed_rows
|
51
|
+
@num_columns = (size / @num_rows.to_f).ceil
|
52
|
+
when :fixed_columns
|
53
|
+
@num_rows = (size / @num_columns.to_f).ceil
|
54
|
+
end
|
55
|
+
|
56
|
+
# Create an array containing all the rows.
|
57
|
+
@rows = case @type
|
58
|
+
when :fixed_rows
|
59
|
+
# Rearrange the list, arranged by columns, into rows.
|
60
|
+
rows = Array.new(@num_rows) { [] }
|
61
|
+
@children.each_with_index do |child, i|
|
62
|
+
rows[i % @num_rows].push child
|
63
|
+
end
|
64
|
+
rows
|
65
|
+
when :fixed_columns
|
66
|
+
@children.each_slice(@num_columns).to_a
|
67
|
+
end
|
68
|
+
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
# Repack all the elements into their positions.
|
74
|
+
def repack
|
75
|
+
@widths = Array.new(@num_columns, 0)
|
76
|
+
@heights = Array.new(@num_rows, 0)
|
77
|
+
|
78
|
+
filled_columns = []
|
79
|
+
filled_rows = []
|
80
|
+
|
81
|
+
# Calculate the maximum widths of each column and the maximum height of each row.
|
82
|
+
@rows.each_with_index do |row, row_num|
|
83
|
+
row.each_with_index do |element, column_num|
|
84
|
+
fills = (element.align_h == :fill)
|
85
|
+
@widths[column_num] = [fills ? 0 : element.outer_width, @widths[column_num] || 0].max
|
86
|
+
filled_columns.push fills
|
87
|
+
|
88
|
+
fills = (element.align_v == :fill)
|
89
|
+
@heights[row_num] = [fills ? 0 : element.outer_height, @heights[row_num] || 0].max
|
90
|
+
filled_rows.push fills
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Expand the size of each filled column to make the minimum size required.
|
95
|
+
num_filled_columns = filled_columns.select {|value| value }.count
|
96
|
+
if num_filled_columns > 0
|
97
|
+
total_width = @widths.inject(0, :+) + (padding_left + padding_right) + ((@num_columns - 1) * spacing_h)
|
98
|
+
if total_width < min_width
|
99
|
+
extra_width = total_width / num_filled_columns
|
100
|
+
filled_columns.each_with_index do |filled, i|
|
101
|
+
@widths[i] += extra_width if filled
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Expand the size of each filled row to make the minimum size required.
|
107
|
+
num_filled_rows = filled_rows.select {|value| value }.count
|
108
|
+
if num_filled_rows > 0
|
109
|
+
total_height = @heights.inject(0, :+) + (padding_left + padding_right) + ((@num_rows - 1) * spacing_v)
|
110
|
+
if total_height < min_height
|
111
|
+
extra_height = total_height / num_filled_rows
|
112
|
+
filled_rows.each_with_index do |filled, i|
|
113
|
+
@heights[i] += extra_height if filled
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Actually place all the elements into the grid positions, modified by valign and align.
|
119
|
+
current_y = y + padding_top
|
120
|
+
@rows.each_with_index do |row, row_num|
|
121
|
+
current_x = x + padding_left
|
122
|
+
|
123
|
+
row.each_with_index do |element, column_num|
|
124
|
+
element.x = current_x + element.border_thickness
|
125
|
+
|
126
|
+
case element.align_h # Take horizontal alignment into consideration.
|
127
|
+
when :fill
|
128
|
+
if element.width < @widths[column_num]
|
129
|
+
element.width = @widths[column_num]
|
130
|
+
element.send :repack if element.is_a? GridPacker
|
131
|
+
end
|
132
|
+
when :center
|
133
|
+
element.x += (@widths[column_num] - element.width) / 2
|
134
|
+
when :right
|
135
|
+
element.x += @widths[column_num] - element.width
|
136
|
+
end
|
137
|
+
|
138
|
+
current_x += @widths[column_num]
|
139
|
+
current_x += spacing_h unless column_num == @num_columns - 1
|
140
|
+
|
141
|
+
element.y = current_y + element.border_thickness
|
142
|
+
|
143
|
+
case element.align_v # Take horizontal alignment into consideration.
|
144
|
+
when :fill
|
145
|
+
if element.height < @heights[row_num]
|
146
|
+
element.height = @heights[row_num]
|
147
|
+
element.send :repack if element.is_a? GridPacker
|
148
|
+
end
|
149
|
+
when :center
|
150
|
+
element.y += (@heights[row_num] - element.height) / 2
|
151
|
+
when :bottom
|
152
|
+
element.y += @heights[row_num] - element.height
|
153
|
+
else
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
self.width = current_x - x + padding_left if row_num == 0
|
158
|
+
|
159
|
+
current_y += @heights[row_num] unless row.empty?
|
160
|
+
current_y += spacing_h unless row_num == num_rows - 1
|
161
|
+
end
|
162
|
+
|
163
|
+
self.height = current_y - y + padding_top
|
164
|
+
|
165
|
+
nil
|
166
|
+
end
|
167
|
+
|
168
|
+
protected
|
169
|
+
# @yield The rectangle of each cell within the grid.
|
170
|
+
# @yieldparam [Number] x
|
171
|
+
# @yieldparam [Number] y
|
172
|
+
# @yieldparam [Number] width
|
173
|
+
# @yieldparam [Number] height
|
174
|
+
def each_cell_rect
|
175
|
+
x = self.x + padding_left
|
176
|
+
|
177
|
+
@widths.each_with_index do |width, column_num|
|
178
|
+
y = self.y + padding_top
|
179
|
+
|
180
|
+
@heights.each_with_index do |height, row_num|
|
181
|
+
yield x, y, width, height if @rows[row_num][column_num]
|
182
|
+
y += height + spacing_v
|
183
|
+
end
|
184
|
+
|
185
|
+
x += width + spacing_h
|
186
|
+
end
|
187
|
+
|
188
|
+
nil
|
189
|
+
end
|
190
|
+
|
191
|
+
protected
|
192
|
+
def draw_background
|
193
|
+
super
|
194
|
+
|
195
|
+
# Draw the cell backgrounds.
|
196
|
+
unless @cell_background_color.transparent?
|
197
|
+
each_cell_rect do |x, y, width, height|
|
198
|
+
draw_rect x, y, width, height, z, @cell_background_color
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
nil
|
203
|
+
end
|
204
|
+
|
205
|
+
protected
|
206
|
+
def draw_border
|
207
|
+
super
|
208
|
+
|
209
|
+
# Draw the cell borders.
|
210
|
+
if @cell_border_thickness > 0 and not @cell_border_color.transparent?
|
211
|
+
each_cell_rect do |x, y, width, height|
|
212
|
+
draw_frame x, y, width, height, @cell_border_thickness, z, @cell_border_color
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
nil
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class Group < Packer
|
5
|
+
attr_reader :selected
|
6
|
+
|
7
|
+
event :changed
|
8
|
+
|
9
|
+
def value; @selected ? @selected.value : nil; end
|
10
|
+
|
11
|
+
# @example
|
12
|
+
# group do
|
13
|
+
# pack :horizontal do
|
14
|
+
# radio_button 1, text: '1', checked: true
|
15
|
+
# radio_button 2, text: '2'
|
16
|
+
# subscribe :changed do |sender, value|
|
17
|
+
# puts value
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# @param (see Packer#initialize)
|
23
|
+
#
|
24
|
+
# @option (see Packer#initialize)
|
25
|
+
def initialize(options = {}, &block)
|
26
|
+
super(options)
|
27
|
+
|
28
|
+
@selected = nil
|
29
|
+
@buttons = []
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_button(button)
|
33
|
+
@buttons.push button
|
34
|
+
self.value = button.value if button.checked?
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def remove_button(button)
|
39
|
+
self.value = nil if button == @selected
|
40
|
+
@buttons.delete button
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# @example
|
45
|
+
# @my_group = group do
|
46
|
+
# pack :horizontal do
|
47
|
+
# radio_button(1, text: '1', checked: true)
|
48
|
+
# radio_button(2, text: '2')
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# # later
|
53
|
+
# @my_group.value = 2
|
54
|
+
def value=(value)
|
55
|
+
if value != self.value
|
56
|
+
button = @buttons.find { |b| b.value == value }
|
57
|
+
@selected.uncheck if @selected and @selected.checked?
|
58
|
+
@selected = button
|
59
|
+
@selected.check if @selected and not @selected.checked?
|
60
|
+
publish :changed, self.value
|
61
|
+
end
|
62
|
+
|
63
|
+
value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class Label < Element
|
5
|
+
attr_accessor :color, :background_color, :border_color
|
6
|
+
attr_reader :text, :icon
|
7
|
+
|
8
|
+
def text=(value)
|
9
|
+
@text = value
|
10
|
+
recalc
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def icon=(value)
|
15
|
+
@icon = value
|
16
|
+
recalc
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param (see Element#initialize)
|
21
|
+
# @param [String] text The string to display in the label.
|
22
|
+
#
|
23
|
+
# @option (see Element#initialize)
|
24
|
+
# @option options [Fidgit::Thumbnail, Gosu::Image, nil] :icon (nil)
|
25
|
+
def initialize(text, options = {})
|
26
|
+
options = {
|
27
|
+
color: default(:color),
|
28
|
+
background_color: default(:background_color),
|
29
|
+
border_color: default(:border_color),
|
30
|
+
}.merge! options
|
31
|
+
|
32
|
+
@text = text.dup
|
33
|
+
@icon = options[:icon]
|
34
|
+
@color = options[:color].dup
|
35
|
+
|
36
|
+
super(options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def draw_foreground
|
40
|
+
current_x = x + padding_left
|
41
|
+
if @icon
|
42
|
+
@icon.draw(current_x, y + padding_top, z)
|
43
|
+
current_x += @icon.width + padding_left
|
44
|
+
end
|
45
|
+
|
46
|
+
unless @text.empty?
|
47
|
+
font.draw(@text, current_x, y + padding_top, z, 1, 1, @color)
|
48
|
+
end
|
49
|
+
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
def layout
|
55
|
+
if @icon
|
56
|
+
if @text.empty?
|
57
|
+
rect.width = [padding_left + @icon.width + padding_right, width].max
|
58
|
+
rect.height = [padding_top + @icon.height + padding_bottom, height].max
|
59
|
+
else
|
60
|
+
# Todo: Use padding_h inside here? Probably by making this a Composite.
|
61
|
+
rect.width = [padding_left + @icon.width + [padding_left + padding_right].max + font.text_width(@text) + padding_right, width].max
|
62
|
+
rect.height = [padding_top + [@icon.height, font_size].max + padding_bottom, height].max
|
63
|
+
end
|
64
|
+
else
|
65
|
+
if @text.empty?
|
66
|
+
rect.width = [padding_left + padding_right, width].max
|
67
|
+
rect.height = [padding_top + padding_bottom, height].max
|
68
|
+
else
|
69
|
+
rect.width = [padding_left + font.text_width(@text) + padding_right, width].max
|
70
|
+
rect.height = [padding_top + font_size + padding_bottom, height].max
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class List < Composite
|
5
|
+
class Item < RadioButton
|
6
|
+
end
|
7
|
+
|
8
|
+
event :changed
|
9
|
+
|
10
|
+
def size; @items.size; end
|
11
|
+
def clear; @items.clear; end
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
options = {
|
15
|
+
background_color: default(:background_color),
|
16
|
+
border_color: default(:border_color),
|
17
|
+
}.merge! options
|
18
|
+
|
19
|
+
super options
|
20
|
+
|
21
|
+
group do
|
22
|
+
subscribe :changed do |sender, value|
|
23
|
+
publish :changed, value
|
24
|
+
end
|
25
|
+
|
26
|
+
@items = pack :vertical, spacing: 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param [String] text
|
31
|
+
# @option options [Gosu::Image] :icon
|
32
|
+
def item(text, value, options = {}, &block)
|
33
|
+
Item.new(text, value, { parent: @items }.merge!(options), &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def layout
|
38
|
+
super
|
39
|
+
if @items
|
40
|
+
max_width = @items.each.to_a.map {|c| c.width }.max || 0
|
41
|
+
@items.each {|c| c.rect.width = max_width }
|
42
|
+
end
|
43
|
+
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class MenuPane < Composite
|
5
|
+
# An item within the menu.
|
6
|
+
class Item < Button
|
7
|
+
attr_reader :value, :shortcut
|
8
|
+
|
9
|
+
# @param (see Button#initialize)
|
10
|
+
#
|
11
|
+
# @option (see Button#initialize)
|
12
|
+
# @param [any] value Value if the user picks this item
|
13
|
+
# @option options [Boolean] :enabled (true)
|
14
|
+
# @option options [String] :shortcut ('')
|
15
|
+
def initialize(text, value, options = {})
|
16
|
+
options = {
|
17
|
+
enabled: true,
|
18
|
+
border_color: default(:border_color),
|
19
|
+
}.merge! options
|
20
|
+
|
21
|
+
@value = value
|
22
|
+
@enabled = [true, false].include?(options[:enabled]) ? options[:enabled] : true
|
23
|
+
@shortcut = options[:shortcut] || ''
|
24
|
+
|
25
|
+
super(text, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def draw_foreground
|
29
|
+
super
|
30
|
+
unless @shortcut.empty?
|
31
|
+
font.draw_rel("#{@shortcut}", rect.right - padding_right, y + ((height - font_size) / 2).floor, z, 1, 0, 1, 1, color)
|
32
|
+
end
|
33
|
+
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
def layout
|
39
|
+
super
|
40
|
+
rect.width += font.text_width(" #{@shortcut}") unless @shortcut.empty?
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Separator < Label
|
46
|
+
# @param (see Item#initialize)
|
47
|
+
#
|
48
|
+
# @option (see Item#initialize)
|
49
|
+
def initialize(options = {})
|
50
|
+
options = {
|
51
|
+
height: default(:line_height),
|
52
|
+
background_color: default(:background_color),
|
53
|
+
padding: 0,
|
54
|
+
}.merge! options
|
55
|
+
|
56
|
+
super '', options
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
event :selected
|
61
|
+
|
62
|
+
def index(value); @items.index find(value); end
|
63
|
+
def size; @items.size; end
|
64
|
+
def [](index); @items[index]; end
|
65
|
+
|
66
|
+
# @option (see Composite#initialize)
|
67
|
+
# @option options [Float] :x (cursor x, if in a GuiState)
|
68
|
+
# @option options [Float] :y (cursor y, if in a GuiState)
|
69
|
+
# @option options [Boolean] :show (true) Whether to show immediately (show later with #show).
|
70
|
+
def initialize(options = {}, &block)
|
71
|
+
options = {
|
72
|
+
background_color: default(:color),
|
73
|
+
z: Float::INFINITY,
|
74
|
+
show: true,
|
75
|
+
}.merge! options
|
76
|
+
|
77
|
+
state = $window.current_game_state
|
78
|
+
if state.is_a? GuiState
|
79
|
+
cursor = $window.current_game_state.cursor
|
80
|
+
options = {
|
81
|
+
x: cursor.x,
|
82
|
+
y: cursor.y,
|
83
|
+
}.merge! options
|
84
|
+
end
|
85
|
+
|
86
|
+
super(options)
|
87
|
+
|
88
|
+
@items = pack :vertical, spacing: 0, padding: 0
|
89
|
+
|
90
|
+
if options[:show] and state.is_a? GuiState
|
91
|
+
show
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def find(value)
|
96
|
+
@items.find {|c| c.value == value }
|
97
|
+
end
|
98
|
+
|
99
|
+
def separator(options = {})
|
100
|
+
options[:z] = z
|
101
|
+
|
102
|
+
Separator.new({ parent: @items }.merge!(options))
|
103
|
+
end
|
104
|
+
|
105
|
+
def item(text, value, options = {}, &block)
|
106
|
+
options[:z] = z
|
107
|
+
item = Item.new(text, value, { parent: @items }.merge!(options), &block)
|
108
|
+
|
109
|
+
item.subscribe :left_mouse_button, method(:item_selected)
|
110
|
+
item.subscribe :right_mouse_button, method(:item_selected)
|
111
|
+
|
112
|
+
item
|
113
|
+
end
|
114
|
+
|
115
|
+
def item_selected(sender, x, y)
|
116
|
+
publish(:selected, sender.value)
|
117
|
+
|
118
|
+
$window.game_state_manager.current_game_state.hide_menu
|
119
|
+
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
def show
|
124
|
+
$window.game_state_manager.current_game_state.show_menu self
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
|
128
|
+
protected
|
129
|
+
def layout
|
130
|
+
super
|
131
|
+
|
132
|
+
if @items
|
133
|
+
# Ensure the menu can't go over the edge of the screen. If it can't be avoided, align with left edge of screen.
|
134
|
+
rect.x = [[x, $window.width - width - padding_right].min, 0].max
|
135
|
+
rect.y = [[y, $window.height - height - padding_bottom].min, 0].max
|
136
|
+
|
137
|
+
# Move the actual list if the menu has moved to keep on the screen.
|
138
|
+
@items.x = x + padding_left
|
139
|
+
@items.y = y + padding_top
|
140
|
+
|
141
|
+
# Ensure that all items are of the same width.
|
142
|
+
max_width = @items.each.to_a.map {|c| c.width }.max || 0
|
143
|
+
@items.each {|c| c.rect.width = max_width }
|
144
|
+
end
|
145
|
+
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|