Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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
@blocks = {}
end
#
# Store an association between a message of type
# _messageType_ with a callable object or a block.
#
def pconnect(messageType, callableObject, block)
if callableObject.nil?
@blocks[messageType] = block
else
@blocks[messageType] = callableObject
end
FXMAPTYPE(messageType, :onHandleMsg)
case messageType
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)
messageType = Fox.FXSELTYPE(sel)
result = @blocks[messageType].call(sender, sel, ptr)
case messageType
when SEL_TIMEOUT
@@targets_of_pending_timers.delete(self)
when SEL_CHORE
@@targets_of_pending_chores.delete(self)
end
result
end
end
end
#
# 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(messageType, callableObject=nil, &block)
unless instance_variables.include?('@pseudoTarget')
@pseudoTarget = Fox::FXPseudoTarget.new
self.target = @pseudoTarget
end
@pseudoTarget.pconnect(messageType, callableObject, block)
end
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'