Responder2 does not work with custom message ID
I am playing around with Responder2 and FXDialogBox.
I am unable to get a FXDialogBox subclass to respond to a custom value via the Responder2 API, only via the Responder route. I got no idea why isn't it working, but Responder2 seems to be only a "syntax sugar" (so to speak) for Responder.
I created a kind of message delegation to play around with when a dialog box's "Save" button gets clicked.
I care about getting message from the ID_FOOBAR passed and have ideally the onSmth method called. (I would pass it as method(:onSmth), but here we want to see different behavior).
However, I cannot get it to work with just using the self.connect route
I have a fairly simple test app, single button, you click that, you get a dialog box, you click the dialog box's button, you get a few messages printed in the console.
Using Responder, I see the following:
From command
"From method"
2162750
nil
1
"sent ID_FOOBAR"
1
"sent ID_ACCEPT"
All targets received their messages, great.
But, using Responder2 (uncomment self.connect in EditDialog class, comment out FXMAPFUNC):
From command
0
"sent ID_FOOBAR"
1
"sent ID_ACCEPT"
I'd expect probably something like:
From command
"From connect"
1
"sent ID_FOOBAR"
1
"sent ID_ACCEPT"
Responder2 looks awesome but I am not sure if it was built for this kind of custom message IDs?
I'd note that even if I instrument the onHandleMsg in Responder2 to print out callable_object, I cannot see the correct one ever getting near the method :/
require 'fox16'
require 'fox16/colors'
include Fox
module Component
class EditDialog < Fox::FXDialogBox
include Responder
ID_FOOBAR = enum(Fox::FXDialogBox::ID_LAST, 1)[0]
def initialize(parent)
super parent, "Example"
@name = FXDataTarget.new('')
@class_id = FXDataTarget.new('')
@name.connect(SEL_CHANGED) { |a, b,c| p a,b,c, "#{FXDataTarget::ID_VALUE},#{a == FXDataTarget::ID_VALUE}, #{b == FXDataTarget::ID_VALUE}, #{c == FXDataTarget::ID_VALUE}" }
@class_id.connect(SEL_CHANGED) { |a, b,c| puts a,b,c }
@frame = Fox::FXVerticalFrame.new(self, LAYOUT_SIDE_BOTTOM|FRAME_NONE|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH, :padLeft => 20, :padRight => 20, :padTop => 10, :padBottom => 10)
# self.connect(SEL_COMMAND) do |a, b, c|
# p "From connect"
# end
FXMAPFUNC(SEL_COMMAND, ID_FOOBAR, :onSmth)
Fox::FXText.new(@frame, @name, FXDataTarget::ID_VALUE, width: 400, height: 64, opts: LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT)
Fox::FXText.new(@frame, @class_id, FXDataTarget::ID_VALUE, width: 400, height: 64, opts: LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT)
save_button
end
def onSmth sender, sel, data
p "From method"
p sel, data
return 1
end
def save_button()
Fox::FXButton.new(
@frame, "&Save Changes",
nil, self,
ID_FOOBAR,
height: 40,
opts: LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT|FRAME_RAISED|FRAME_THICK|JUSTIFY_NORMAL
) do |obj|
obj.connect(SEL_COMMAND) do |sender, sel, data|
puts "From command"
p self.handle(self, FXSEL(SEL_COMMAND,ID_FOOBAR), nil)
p "sent ID_FOOBAR"
# p self.handle(self, MKUINT(ID_ACCEPT, SEL_COMMAND), nil) == equivalent to FXSEL
p self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil)
p "sent ID_ACCEPT"
end
end
end
end
end
class MainApp < FXMainWindow
def initialize(app)
super(app, 'FX Task Manager', opts: DECOR_ALL)
self.backColor = FXColor::WhiteSmoke
vert = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y)
Fox::FXButton.new(vert, "&Edit Dialog",
opts: LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED|FRAME_THICK|JUSTIFY_NORMAL) do |obj|
p obj
obj.connect(SEL_COMMAND) do
dialog = Component::EditDialog.new(self)
dialog.show
dialog.execute
end
end
end
def create
super
show(PLACEMENT_SCREEN)
end
end
window = FXApp.new('FXTaskManager', 'FXTaskManager')
MainApp.new window
window.create
window.run
Hello,
There is one more way to receive messages with custom identifiers from button via similar api - using FXPseudoTarget. Here is example:
require "fox16"
require "fox16/colors"
include Fox
module Component
class EditDialog < Fox::FXDialogBox
include Responder
ID_FOOBAR = enum(Fox::FXDialogBox::ID_LAST, 1)[0]
def initialize(parent)
super parent, "Example"
@frame = Fox::FXVerticalFrame.new(self, LAYOUT_SIDE_BOTTOM | FRAME_NONE | LAYOUT_FILL_X | PACK_UNIFORM_WIDTH, :padLeft => 20, :padRight => 20, :padTop => 10, :padBottom => 10)
@pseudo_target = FXPseudoTarget.new
@pseudo_target.pconnect(SEL_COMMAND, proc { |sender, sel, data|
p "Hello from pseudo target pconnect"
p sender.class.name
message_id = FXSELID(sel)
p "ID_FOOBAR? ---> #{message_id == ID_FOOBAR}"
self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil)
})
Fox::FXText.new(@frame)
Fox::FXText.new(@frame)
save_button = Fox::FXButton.new(@frame, "&Save Changes", nil, :target => @pseudo_target, :selector => ID_FOOBAR)
end
end
end
class MainApp < FXMainWindow
def initialize(app)
super(app, "FX Task Manager", opts: DECOR_ALL)
self.backColor = FXColor::WhiteSmoke
vert = FXVerticalFrame.new(self, LAYOUT_FILL_X | LAYOUT_FILL_Y)
Fox::FXButton.new(vert, "&Edit Dialog",
opts: LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_RAISED | FRAME_THICK | JUSTIFY_NORMAL) do |obj|
obj.connect(SEL_COMMAND) do
dialog = Component::EditDialog.new(self)
dialog.execute
end
end
end
def create
super
show(PLACEMENT_SCREEN)
end
end
window = FXApp.new("FXTaskManager", "FXTaskManager")
MainApp.new window
window.create
window.run
Oh! Thank you, I was confused as when I inspected the object, there was a FXPseudoTarget already, binded with what seemed like the correct method I passed it.
There isn't any example in the examples/ folder that I draw inspiration for this. Most, if not all of them, are using the Responder module for custom IDs.
I think I resolved my original issue.