Newer
Older
require 'fox16/responder'
module Fox
#
# FXPseudoTarget instances act as the message target for any widgets that
# elect to use the #connect method to map certain message types to
# blocks.
#
class FXPseudoTarget < FXObject
include Responder
@@targets_of_pending_timers = {}
@@targets_of_pending_chores = {}
@@targets_of_pending_signals = {}
@@targets_of_pending_inputs = {}
#
# Returns an initialized FXPseudoTarget object.
#
def initialize
super
end
#
# Store an association between a message of type
# _message_type_ with a callable object.
def pconnect(message_type, callable_object, params={})
@context[message_type] = { :callable => callable_object, :params => params }
FXMAPTYPE(message_type, :onHandleMsg)
case message_type
when SEL_TIMEOUT
@@targets_of_pending_timers[self] = self
when SEL_CHORE
@@targets_of_pending_chores[self] = self
when SEL_SIGNAL
@@targets_of_pending_signals[self] = self
when SEL_IO_READ, SEL_IO_WRITE, SEL_IO_EXCEPT
@@targets_of_pending_inputs[self] = self
end
end
#
# Handle a message from _sender_, with selector _sel_ and
# message data _ptr_.
#
def onHandleMsg(sender, sel, ptr)
message_type = Fox.FXSELTYPE(sel)
ctx = @context[message_type]
callable_object = ctx[:callable]
params = ctx[:params]
result = callable_object.call(sender, sel, ptr)
case message_type
when SEL_TIMEOUT
if params[:repeat]
FXApp.instance.addTimeout(params[:delay], callable_object, params)
else
@@targets_of_pending_timers.delete(self)
end
when SEL_CHORE
if params[:repeat]
FXApp.instance.addChore(callable_object, params)
else
@@targets_of_pending_chores.delete(self)
end
end # class FXPseudoTarget
end # module Fox
#
# The Responder2 module provides the #connect method,
# which is mixed-in to all classes that have a message
# target (i.e. Fox::FXDataTarget, Fox::FXRecentFiles
# and Fox::FXWindow).
#
module Responder2
#
# Assign a "handler" for all FOX messages of type _messageType_
# sent from this widget. When called with only one argument,
# a block is expected, e.g.
#
# aButton.connect(SEL_COMMAND) { |sender, selector, data|
# ... code to handle this event ...
# }
#
# The arguments passed into the block are the _sender_ of the
# message (i.e. the widget), the _selector_ for the message, and
# any message-specific _data_.
#
# When #connect is called with two arguments, the second argument
# should be some callable object such as a Method or Proc instance, e.g.
#
# aButton.connect(SEL_COMMAND, method(:onCommand))
#
# As with the one-argument form of #connect, the callable object
# will be "called" with three arguments (the sender, selector and
# message data).
#
def connect(message_type, callable_object=nil, &block)
unless instance_variables.include?('@pseudoTarget') || instance_variables.include?(:@pseudoTarget)
@pseudoTarget = Fox::FXPseudoTarget.new
self.target = @pseudoTarget
end
@pseudoTarget.pconnect(message_type, callable_object ? callable_object : block)
end
module Fox
class FXDataTarget
include Responder2
end
class FXRecentFiles
include Responder2
end
class FXWindow
include Responder2
end
end
require 'fox16/timeout'
require 'fox16/chore'
require 'fox16/signal'
require 'fox16/input'
require 'fox16/accel_table'