fxruby icon indicating copy to clipboard operation
fxruby copied to clipboard

Responder2 does not work with custom message ID

Open jackorp opened this issue 2 years ago • 2 comments

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

jackorp avatar May 23 '23 17:05 jackorp

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

vin1antme avatar May 24 '23 21:05 vin1antme

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.

jackorp avatar May 29 '23 08:05 jackorp

I think I resolved my original issue.

jackorp avatar Mar 28 '24 17:03 jackorp