[fxruby-users] Data Targets and message handlers [was: Default double-click in FXTable?]
Philippe Lang
philippe.lang at attiksystem.ch
Sat Oct 7 11:26:03 EDT 2006
I wrote:
> Hi,
>
> I have read that message handlers can return a value, either
> true or false, depending on if the handler actually did
> something, or not. In the latter case, the message is
> forwarded to the default message handler.
>
> I have tried this, and found something strange: in this code,
> decommenting:
>
> @data_widget.connect(SEL_KEYPRESS) do |sender, selector, data|
> puts d.code false
> end
>
> ... breaks the update of the textfield. The handler returns
> false in every case, it should have no effect at all, no?
>
> I'm I missing something maybe?
>
> Philippe
>
>
> ----------------------------
> #!/usr/bin/ruby
>
> require 'fox16'
>
> include Fox
>
> class MyWindow < FXMainWindow
>
> def initialize(app)
>
> super(app, "Window", nil, nil, DECOR_ALL, 0, 0, 200, 100)
>
> # Menu bar stretched along the top of the main window
> menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
>
> # File menu
> filemenu = FXMenuPane.new(self)
> FXMenuTitle.new(menubar, "&File", nil, filemenu)
> FXMenuCommand.new(filemenu, "&Quit\tCtl-Q\tQuit the application",
> nil, app, FXApp::ID_QUIT)
>
> # Frames
> frame = FXMatrix.new(self, 4,
> LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED)
>
> # Data target
> @data_target = FXDataTarget.new()
>
> # Widget
> @data_widget = FXTextField.new(frame, 5, @data_target,
> FXDataTarget::ID_VALUE)
>
> # We put some data into the data target
> @data_target.value = 123
>
> # We add a message handler
> #@data_widget.connect(SEL_KEYPRESS) do |sender, selector, data|
> # puts d.code # false
> #end
>
> end
>
> def create
> super
> show(PLACEMENT_SCREEN)
> end
>
> end
>
> if __FILE__ == $0
> application = FXApp.new("Attik System", "FXRuby Test")
> MyWindow.new(application) application.create
> application.run
> end
Hi again,
I understand more or less what happens here. The link between the data target and the widget works here:
----------------------------------------
#!/usr/bin/ruby
require 'fox16'
include Fox
class MyWindow < FXMainWindow
def initialize(app)
super(app, "Window", nil, nil, DECOR_ALL, 0, 0, 200, 100)
# Menu bar stretched along the top of the main window
menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
# File menu
filemenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&File", nil, filemenu)
FXMenuCommand.new(filemenu, "&Quit\tCtl-Q\tQuit the application",
nil, app, FXApp::ID_QUIT)
# Frames
frame = FXMatrix.new(self, 4,
LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED)
# Data target
@data_target = FXDataTarget.new()
# Widget
#@data_widget = FXTextField.new(frame, 5, @data_target, FXDataTarget::ID_VALUE)
@data_widget = FXTextField.new(frame, 5)
# We put some data into the data target
@data_target.value = 123
# We add a message handler
@data_widget.connect(SEL_KEYPRESS) do |sender, selector, data|
puts data.code
0
end
# We connect the data target to the widget
@data_widget.target = @data_target
@data_widget.selector = FXDataTarget::ID_VALUE
end
def create
super
show(PLACEMENT_SCREEN)
end
end
if __FILE__ == $0
application = FXApp.new("Attik System", "FXRuby Test")
MyWindow.new(application)
application.create
application.run
end
----------------------------------------
But here it does not:
----------------------------------------
#!/usr/bin/ruby
require 'fox16'
include Fox
class MyWindow < FXMainWindow
def initialize(app)
super(app, "Window", nil, nil, DECOR_ALL, 0, 0, 200, 100)
# Menu bar stretched along the top of the main window
menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
# File menu
filemenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&File", nil, filemenu)
FXMenuCommand.new(filemenu, "&Quit\tCtl-Q\tQuit the application",
nil, app, FXApp::ID_QUIT)
# Frames
frame = FXMatrix.new(self, 4,
LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED)
# Data target
@data_target = FXDataTarget.new()
# Widget
#@data_widget = FXTextField.new(frame, 5, @data_target, FXDataTarget::ID_VALUE)
@data_widget = FXTextField.new(frame, 5)
# We put some data into the data target
@data_target.value = 123
# We connect the data target to the widget
@data_widget.target = @data_target
@data_widget.selector = FXDataTarget::ID_VALUE
# We add a message handler
@data_widget.connect(SEL_KEYPRESS) do |sender, selector, data|
puts data.code
0
end
end
def create
super
show(PLACEMENT_SCREEN)
end
end
if __FILE__ == $0
application = FXApp.new("Attik System", "FXRuby Test")
MyWindow.new(application)
application.create
application.run
end
----------------------------------------
To say things briefly, we have to connect the data target to it's widget AFTER we have added our first handler. Otherwise the link between the data target and the widget gets deleted:
The problem comes from here:
----------------------------------------
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
----------------------------------------
When calling
@data_widget.connect(SEL_KEYPRESS) do |sender, selector, data|
puts data.code
0
end
... A pseudoTarget is being created, and the target starts pointing at it.
I don't know how to handle that. For now, I have just added an exception, like this:
----------------------------------------
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')
# We check if another target is already registered.
# This might be true for a widget already linked to an
# FXDataTarget object.
if self.target
raise "A target is already registered for this object."
end
@pseudoTarget = Fox::FXPseudoTarget.new
self.target = @pseudoTarget
end
@pseudoTarget.pconnect(messageType, callableObject, block)
end
End
----------------------------------------
Cheers,
---------------
Philippe Lang
Attik System
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 3125 bytes
Desc: not available
Url : http://rubyforge.org/pipermail/fxruby-users/attachments/20061007/1909ede3/attachment.bin
More information about the fxruby-users
mailing list