fidgit 0.0.2alpha
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.
- 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,106 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class Selection
|
5
|
+
MIN_DRAG_DISTANCE = 2
|
6
|
+
|
7
|
+
def size; @items.size; end
|
8
|
+
def empty?; @items.empty?; end
|
9
|
+
def [](index); @items[index]; end
|
10
|
+
def each(&block); @items.each(&block); end
|
11
|
+
def to_a; @items.dup; end
|
12
|
+
def include?(object); @items.include? object; end
|
13
|
+
|
14
|
+
# Current being dragged?
|
15
|
+
def dragging?; @dragging; end
|
16
|
+
|
17
|
+
# Actually moved during a dragging operation?
|
18
|
+
def moved?; @moved; end
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@items = []
|
22
|
+
@moved = false
|
23
|
+
@dragging = false
|
24
|
+
end
|
25
|
+
|
26
|
+
def add(object)
|
27
|
+
object.selected = true
|
28
|
+
@items.push(object)
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove(object)
|
34
|
+
@items.delete(object)
|
35
|
+
object.selected = false
|
36
|
+
object.dragging = false
|
37
|
+
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def clear
|
42
|
+
end_drag if dragging?
|
43
|
+
@items.each { |o| o.selected = false; o.dragging = false }
|
44
|
+
@items.clear
|
45
|
+
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def begin_drag(x, y)
|
50
|
+
@initial_x, @initial_y = x, y
|
51
|
+
@last_x, @last_y = x, y
|
52
|
+
@dragging = true
|
53
|
+
@moved = false
|
54
|
+
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def end_drag
|
59
|
+
@items.each do |object|
|
60
|
+
object.x, object.y = object.x.round, object.y.round
|
61
|
+
object.dragging = false
|
62
|
+
end
|
63
|
+
@dragging = false
|
64
|
+
@moved = false
|
65
|
+
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Move all dragged object back to original positions.
|
70
|
+
def reset_drag
|
71
|
+
if moved?
|
72
|
+
@items.each do |o|
|
73
|
+
o.x += @initial_x - @last_x
|
74
|
+
o.y += @initial_y - @last_y
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
self.end_drag
|
79
|
+
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
def update_drag(x, y)
|
84
|
+
x, y = x.round, y.round
|
85
|
+
|
86
|
+
# If the mouse has been dragged far enough from the initial click position, then 'pick up' the objects and drag.
|
87
|
+
unless moved?
|
88
|
+
if distance(@initial_x, @initial_y, x, y) > MIN_DRAG_DISTANCE
|
89
|
+
@items.each { |o| o.dragging = true }
|
90
|
+
@moved = true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
if moved?
|
95
|
+
@items.each do |o|
|
96
|
+
o.x += x - @last_x
|
97
|
+
o.y += y - @last_y
|
98
|
+
end
|
99
|
+
|
100
|
+
@last_x, @last_y = x, y
|
101
|
+
end
|
102
|
+
|
103
|
+
self
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Hash
|
2
|
+
# Merge not only the hashes, but all nested hashes as well.
|
3
|
+
# Written by Stefan Rusterholz (apeiros) from http://www.ruby-forum.com/topic/142809
|
4
|
+
def deep_merge!(other)
|
5
|
+
merger = lambda do |key, a, b|
|
6
|
+
(a.is_a?(Hash) && b.is_a?(Hash)) ? a.merge!(b, &merger) : b
|
7
|
+
end
|
8
|
+
|
9
|
+
merge!(other, &merger)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Merge not only the hashes, but all nested hashes as well.
|
13
|
+
# Written by Stefan Rusterholz (apeiros) from http://www.ruby-forum.com/topic/142809
|
14
|
+
def deep_merge(other)
|
15
|
+
merger = lambda do |key, a, b|
|
16
|
+
(a.is_a?(Hash) && b.is_a?(Hash)) ? a.merge(b, &merger) : b
|
17
|
+
end
|
18
|
+
|
19
|
+
merge(other, &merger)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Fidgit
|
2
|
+
# A modal dialog.
|
3
|
+
# @abstract
|
4
|
+
class DialogState < GuiState
|
5
|
+
DEFAULT_BACKGROUND_COLOR = Gosu::Color.rgb(75, 75, 75)
|
6
|
+
DEFAULT_BORDER_COLOR = Gosu::Color.rgb(255, 255, 255)
|
7
|
+
|
8
|
+
DEFAULT_SHADOW_COLOR = Gosu::Color.rgba(0, 0, 0, 100)
|
9
|
+
DEFAULT_SHADOW_OFFSET = 8
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
# @option options [Gosu::Color] :shadow_color (transparent black) Color of the shadow.
|
13
|
+
# @option options [Gosu::Color] :shadow_offset (8) Distance shadow is offset to bottom and left.
|
14
|
+
# @option options [Gosu::Color] :shadow_full (false) Shadow fills whole screen. Ignores :shadow_offset option if true.
|
15
|
+
options = {
|
16
|
+
shadow_color: DEFAULT_SHADOW_COLOR,
|
17
|
+
shadow_offset: DEFAULT_SHADOW_OFFSET,
|
18
|
+
shadow_full: false,
|
19
|
+
}.merge! options
|
20
|
+
|
21
|
+
@shadow_color = options[:shadow_color].dup
|
22
|
+
@shadow_offset = options[:shadow_offset]
|
23
|
+
@shadow_full = options[:shadow_full]
|
24
|
+
|
25
|
+
super()
|
26
|
+
end
|
27
|
+
|
28
|
+
def draw
|
29
|
+
$window.game_state_manager.previous_game_state.draw # Keep the underlying state being shown.
|
30
|
+
$window.flush
|
31
|
+
|
32
|
+
if @shadow_full
|
33
|
+
draw_rect 0, 0, $window.width, $window.height, -Float::INFINITY, @shadow_color
|
34
|
+
elsif @shadow_offset > 0
|
35
|
+
dialog = container[0]
|
36
|
+
draw_rect dialog.x + @shadow_offset, dialog.y + @shadow_offset, dialog.width, dialog.height, -Float::INFINITY, @shadow_color
|
37
|
+
end
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Fidgit
|
2
|
+
# A simple dialog that manages a message with a set of buttons beneath it.
|
3
|
+
class FileDialog < DialogState
|
4
|
+
def initialize(type, options = {}, &block)
|
5
|
+
options = {
|
6
|
+
show: true,
|
7
|
+
background_color: DEFAULT_BACKGROUND_COLOR,
|
8
|
+
border_color: DEFAULT_BORDER_COLOR,
|
9
|
+
}.merge! options
|
10
|
+
|
11
|
+
super(options)
|
12
|
+
|
13
|
+
pack :vertical, align: :center, padding: 0 do |packer|
|
14
|
+
FileBrowser.new(type, { parent: packer }.merge!(options)) do |sender, result, file_name|
|
15
|
+
hide
|
16
|
+
block.call result, file_name if block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
show if options[:show]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,301 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Fidgit
|
4
|
+
class GuiState < Chingu::GameState
|
5
|
+
# A 1x1 white pixel used for drawing.
|
6
|
+
PIXEL_IMAGE = 'pixel.png'
|
7
|
+
|
8
|
+
# The Container that contains all the elements for this GuiState.
|
9
|
+
# @return [Packer]
|
10
|
+
attr_reader :container
|
11
|
+
|
12
|
+
# The element with focus.
|
13
|
+
# @return [Element]
|
14
|
+
attr_reader :focus
|
15
|
+
|
16
|
+
# The Cursor.
|
17
|
+
# @return [Cursor]
|
18
|
+
def cursor; @@cursor; end
|
19
|
+
|
20
|
+
# Sets the focus to a particular element.
|
21
|
+
def focus=(element)
|
22
|
+
@focus.publish :blur if @focus and element
|
23
|
+
@focus = element
|
24
|
+
end
|
25
|
+
|
26
|
+
# Delay, in ms, before a tool-tip will appear.
|
27
|
+
def tool_tip_delay
|
28
|
+
500 # TODO: configure this.
|
29
|
+
end
|
30
|
+
|
31
|
+
# Show a file_dialog.
|
32
|
+
# (see FileDialog#initialize)
|
33
|
+
def file_dialog(type, options = {}, &block)
|
34
|
+
FileDialog.new(type, options, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
# (see MenuPane#initialize)
|
38
|
+
def menu(options = {}, &block); MenuPane.new(options, &block); end
|
39
|
+
|
40
|
+
# (see MessageDialog#initialize)
|
41
|
+
def message(text, options = {}, &block); MessageDialog.new(text, options, &block); end
|
42
|
+
|
43
|
+
# (see Container#pack)
|
44
|
+
def pack(*args, &block); @container.pack *args, █ end
|
45
|
+
|
46
|
+
# (see Container#clear)
|
47
|
+
def clear(*args, &block); @container.clear *args, █ end
|
48
|
+
|
49
|
+
def initialize
|
50
|
+
# The container is where the user puts their content.
|
51
|
+
@container = VerticalPacker.new(padding: 0, width: $window.width, height: $window.height)
|
52
|
+
|
53
|
+
unless defined? @@draw_pixel
|
54
|
+
media_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'media'))
|
55
|
+
Gosu::Image.autoload_dirs << File.join(media_dir, 'images')
|
56
|
+
Gosu::Sample.autoload_dirs << File.join(media_dir, 'sounds')
|
57
|
+
|
58
|
+
@@draw_pixel = Gosu::Image.new($window, File.join(media_dir, 'images', PIXEL_IMAGE), true) # Must be tileable or it will blur.
|
59
|
+
@@cursor = Cursor.new
|
60
|
+
end
|
61
|
+
|
62
|
+
@min_drag_distance = 0
|
63
|
+
|
64
|
+
super()
|
65
|
+
|
66
|
+
add_inputs(
|
67
|
+
left_mouse_button: ->{ redirect_mouse_button(:left) },
|
68
|
+
holding_left_mouse_button: ->{ redirect_holding_mouse_button(:left) },
|
69
|
+
released_left_mouse_button: ->{ redirect_released_mouse_button(:left) },
|
70
|
+
|
71
|
+
middle_mouse_button: ->{ redirect_mouse_button(:middle) },
|
72
|
+
holding_middle_mouse_button: ->{ redirect_holding_mouse_button(:middle) },
|
73
|
+
released_middle_mouse_button: ->{ redirect_released_mouse_button(:middle) },
|
74
|
+
|
75
|
+
right_mouse_button: ->{ redirect_mouse_button(:right) },
|
76
|
+
holding_right_mouse_button: ->{ redirect_holding_mouse_button(:right) },
|
77
|
+
released_right_mouse_button: ->{ redirect_released_mouse_button(:right) },
|
78
|
+
|
79
|
+
mouse_wheel_up: :redirect_mouse_wheel_up,
|
80
|
+
mouse_wheel_down: :redirect_mouse_wheel_down
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Internationalisation helper.
|
85
|
+
def t(*args); I18n.t(*args); end
|
86
|
+
|
87
|
+
# Clear the data which is specific to the current $window.
|
88
|
+
def self.clear
|
89
|
+
remove_class_variable '@@cursor' if defined? @@cursor
|
90
|
+
remove_class_variable '@@draw_pixel' if defined? @@draw_pixel
|
91
|
+
end
|
92
|
+
|
93
|
+
def update
|
94
|
+
cursor.update
|
95
|
+
@tool_tip.update if @tool_tip
|
96
|
+
@menu.update if @menu
|
97
|
+
@container.update
|
98
|
+
|
99
|
+
# Check menu first, then other elements.
|
100
|
+
new_mouse_over = @menu.hit_element(cursor.x, cursor.y) if @menu
|
101
|
+
new_mouse_over = @container.hit_element(cursor.x, cursor.y) unless new_mouse_over
|
102
|
+
|
103
|
+
if new_mouse_over
|
104
|
+
new_mouse_over.publish :enter if new_mouse_over != @mouse_over
|
105
|
+
new_mouse_over.publish :hover, cursor.x, cursor.y
|
106
|
+
end
|
107
|
+
|
108
|
+
@mouse_over.publish :leave if @mouse_over and new_mouse_over != @mouse_over
|
109
|
+
|
110
|
+
@mouse_over = new_mouse_over
|
111
|
+
|
112
|
+
# Check if the mouse has moved, and no menu is shown, so we can show a tooltip.
|
113
|
+
if [cursor.x, cursor.y] == @last_cursor_pos and (not @menu)
|
114
|
+
if @mouse_over and (Gosu::milliseconds - @mouse_moved_at) > tool_tip_delay
|
115
|
+
if text = @mouse_over.tip and not text.empty?
|
116
|
+
@tool_tip ||= ToolTip.new
|
117
|
+
@tool_tip.text = text
|
118
|
+
@tool_tip.x = cursor.x
|
119
|
+
@tool_tip.y = cursor.y + cursor.height # Place the tip beneath the cursor.
|
120
|
+
else
|
121
|
+
@tool_tip = nil
|
122
|
+
@mouse_moved_at = Gosu::milliseconds
|
123
|
+
end
|
124
|
+
end
|
125
|
+
else
|
126
|
+
@tool_tip = nil
|
127
|
+
@mouse_moved_at = Gosu::milliseconds
|
128
|
+
end
|
129
|
+
|
130
|
+
# The element that grabs input.
|
131
|
+
@active_element = @dragging_element || @focus || @mouse_over
|
132
|
+
|
133
|
+
@last_cursor_pos = [cursor.x, cursor.y]
|
134
|
+
|
135
|
+
super
|
136
|
+
end
|
137
|
+
|
138
|
+
def draw
|
139
|
+
@container.draw
|
140
|
+
@menu.draw if @menu
|
141
|
+
@tool_tip.draw if @tool_tip
|
142
|
+
cursor.draw
|
143
|
+
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
|
147
|
+
def setup
|
148
|
+
super
|
149
|
+
|
150
|
+
@tool_tip = nil
|
151
|
+
@mouse_over = nil # Element the mouse is hovering over.
|
152
|
+
@mouse_down_on = Hash.new # Element that each button was pressed over.
|
153
|
+
@mouse_down_pos = Hash.new # Position that each button was pressed down at.
|
154
|
+
@drag_button = nil
|
155
|
+
@dragging_element = nil
|
156
|
+
@focus = nil
|
157
|
+
@mouse_moved_at = Gosu::milliseconds
|
158
|
+
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
|
162
|
+
def finalize
|
163
|
+
@tool_tip = nil
|
164
|
+
|
165
|
+
nil
|
166
|
+
end
|
167
|
+
|
168
|
+
# Set the menu pane to be displayed.
|
169
|
+
#
|
170
|
+
# @param [MenuPane] menu Menu to display.
|
171
|
+
# @return nil
|
172
|
+
def show_menu(menu)
|
173
|
+
hide_menu if @menu
|
174
|
+
@menu = menu
|
175
|
+
|
176
|
+
nil
|
177
|
+
end
|
178
|
+
|
179
|
+
# Hides the currently shown menu, if any.
|
180
|
+
# @return nil
|
181
|
+
def hide_menu
|
182
|
+
@menu = nil
|
183
|
+
|
184
|
+
nil
|
185
|
+
end
|
186
|
+
|
187
|
+
# Flush all pending drawing to the screen.
|
188
|
+
def flush
|
189
|
+
$window.flush
|
190
|
+
end
|
191
|
+
|
192
|
+
# Draw a filled rectangle.
|
193
|
+
def draw_rect(x, y, width, height, z, color, mode = :default)
|
194
|
+
@@draw_pixel.draw x, y, z, width, height, color, mode
|
195
|
+
|
196
|
+
nil
|
197
|
+
end
|
198
|
+
|
199
|
+
# Draw an unfilled rectangle.
|
200
|
+
def draw_frame(x, y, width, height, thickness, z, color, mode = :default)
|
201
|
+
draw_rect(x - thickness, y, thickness, height, z, color, mode) # left
|
202
|
+
draw_rect(x - thickness, y - thickness, width + thickness * 2, thickness, z, color, mode) # top (full)
|
203
|
+
draw_rect(x + width, y, thickness, height, z, color, mode) # right
|
204
|
+
draw_rect(x - thickness, y + height, width + thickness * 2, thickness, z, color, mode) # bottom (full)
|
205
|
+
|
206
|
+
nil
|
207
|
+
end
|
208
|
+
|
209
|
+
def distance(x1, y1, x2, y2)
|
210
|
+
Gosu.distance(x1, y1, x2, y2)
|
211
|
+
end
|
212
|
+
|
213
|
+
def show
|
214
|
+
$window.game_state_manager.push self unless $window.game_state_manager.game_states.include? self
|
215
|
+
nil
|
216
|
+
end
|
217
|
+
|
218
|
+
def hide
|
219
|
+
$window.game_state_manager.pop if $window.game_state_manager.current == self
|
220
|
+
nil
|
221
|
+
end
|
222
|
+
|
223
|
+
protected
|
224
|
+
def redirect_mouse_button(button)
|
225
|
+
# Ensure that if the user clicks away from a menu, it is automatically closed.
|
226
|
+
hide_menu unless @menu and @menu == @mouse_over
|
227
|
+
|
228
|
+
# Blur if clicking outside the focused element.
|
229
|
+
if @focus and @mouse_over != @focus
|
230
|
+
@focus.publish :blur
|
231
|
+
@focus = nil
|
232
|
+
end
|
233
|
+
|
234
|
+
# Publish :left_mouse_button for the element that is clicked.
|
235
|
+
if @mouse_over
|
236
|
+
@mouse_down_pos[button] = [cursor.x, cursor.y]
|
237
|
+
@mouse_down_on[button] = @mouse_over
|
238
|
+
@mouse_over.publish :"#{button}_mouse_button", *@mouse_down_pos[button]
|
239
|
+
else
|
240
|
+
@mouse_down_pos[button] = nil
|
241
|
+
@mouse_down_on[button] = nil
|
242
|
+
end
|
243
|
+
|
244
|
+
nil
|
245
|
+
end
|
246
|
+
|
247
|
+
protected
|
248
|
+
def redirect_released_mouse_button(button)
|
249
|
+
# Ensure that if the user clicks away from a menu, it is automatically closed.
|
250
|
+
hide_menu if @menu and @mouse_over != @menu
|
251
|
+
|
252
|
+
if @mouse_over
|
253
|
+
@mouse_over.publish :"released_#{button}_mouse_button", cursor.x, cursor.y
|
254
|
+
@mouse_over.publish :"clicked_#{button}_mouse_button", cursor.x, cursor.y if @mouse_over == @mouse_down_on[button]
|
255
|
+
end
|
256
|
+
|
257
|
+
if @dragging_element and @drag_button == button
|
258
|
+
@dragging_element.publish :end_drag, cursor.x, cursor.y, @drag_button, @mouse_over
|
259
|
+
@dragging_element = nil
|
260
|
+
@drag_button = nil
|
261
|
+
end
|
262
|
+
|
263
|
+
@mouse_down_on[button] = nil
|
264
|
+
@mouse_down_pos[button] = nil
|
265
|
+
|
266
|
+
nil
|
267
|
+
end
|
268
|
+
|
269
|
+
protected
|
270
|
+
def redirect_holding_mouse_button(button)
|
271
|
+
if not @dragging_element and @mouse_down_on[button] and @mouse_down_on[button].drag?(button) and
|
272
|
+
distance(*@mouse_down_pos[button], cursor.x, cursor.y) > @min_drag_distance
|
273
|
+
@drag_button = button
|
274
|
+
@dragging_element = @mouse_down_on[button]
|
275
|
+
@dragging_element.publish :begin_drag, *@mouse_down_pos[button], :left
|
276
|
+
end
|
277
|
+
|
278
|
+
if @dragging_element
|
279
|
+
if @drag_button == button
|
280
|
+
@dragging_element.publish :update_drag, cursor.x, cursor.y
|
281
|
+
end
|
282
|
+
else
|
283
|
+
@mouse_over.publish :"holding_#{button}_mouse_button", cursor.x, cursor.y if @mouse_over
|
284
|
+
end
|
285
|
+
|
286
|
+
nil
|
287
|
+
end
|
288
|
+
|
289
|
+
protected
|
290
|
+
def redirect_mouse_wheel_up
|
291
|
+
@active_element.publish :mouse_wheel_up, cursor.x, cursor.y if @active_element
|
292
|
+
nil
|
293
|
+
end
|
294
|
+
|
295
|
+
protected
|
296
|
+
def redirect_mouse_wheel_down
|
297
|
+
@active_element.publish :mouse_wheel_down, cursor.x, cursor.y if @active_element
|
298
|
+
nil
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|