lib/metro/events/hit_list.rb
module Metro
#
# The HitList is an object that maintains when an object is touched/clicked
# and then moved and finally released. The object attempts to work through
# the process:
#
# hit_list.hit(first_event)
# hit_list.update(next_event)
# hit_list.update(next_event)
# hit_list.release(last_event)
#
# @see EditTransitionScene
#
class HitList
def initialize(drawers)
@drawers = drawers
end
attr_reader :drawers
def hit(event)
add drawers_at(event.mouse_point)
save_event event
end
def update(event)
offset = offset_from_last_event(event)
list.each { |d| d.position = d.position + offset }
save_event event
end
def release(event)
offset = offset_from_last_event(event)
list.each { |d| d.position = d.position + offset }
save_event event
clear
end
def drawers_at(point)
hit_drawers = drawers.find_all { |drawer| drawer.bounds.contains?(point) }
# assumed that we only want one item
top_drawer = hit_drawers.inject(hit_drawers.first) {|top,drawer| drawer.z_order > top.z_order ? drawer : top }
[ top_drawer ].compact
end
def offset_from_last_event(event)
return Point.zero unless @last_event
event.mouse_point - @last_event.mouse_point
end
def save_event(event)
@first_event = event unless @first_event
@last_event = event
end
def list
@list ||= []
end
def add(hits)
Array(hits).each {|hit| list.push hit }
end
def clear
list.clear
@first_event = nil
end
end
end