require 'fox'
require 'fox/responder'

include Fox

# Instances of this class act as the message target for any widgets who
# elect to use the new 'connect' method to map certain message types to
# blocks.
#
class FXPseudoTarget < FXObject

  include Responder

  def initialize
    super
    @blocks = {}
  end

  def connect(sig, meth, block)
    if meth != nil
      @blocks[sig] = meth.to_proc
    else
      @blocks[sig] = block
    end
    FXMAPTYPE(sig, 'onHandleMsg')
  end

  def onHandleMsg(sender, sel, ptr)
    @blocks[SELTYPE(sel)].call(sender, sel, ptr)
  end
end

module Responder2
  def connect(sig, meth=nil, &block)
    if instance_variables.include?('@pseudoTarget') == false
      @pseudoTarget = FXPseudoTarget.new
      setTarget(@pseudoTarget)
    end
    @pseudoTarget.connect(sig, meth, block)
  end
end

module Fox
  class FXApp
    # Accepted forms are:
    #   addTimeout(ms, target, selector)
    #   addTimeout(ms, method(:onTimeout))
    #   addTimeout(ms) { |sender, sel, ptr| block }

    alias addTimeoutOrig addTimeout

    def addTimeout(ms, *args, &block)
      if args.length > 0
        if args[0].kind_of? Method
          tgt = FXPseudoTarget.new
	  tgt.connect(SEL_TIMEOUT, args[0], block)
	  addTimeoutOrig(ms, tgt, 0)
        else # it's an object
          tgt = args[0]
          sel = args[1]
          addTimeoutOrig(ms, tgt, sel)
        end
      else
        tgt = FXPseudoTarget.new
	tgt.connect(SEL_TIMEOUT, nil, block)
	addTimeoutOrig(ms, tgt, 0)
      end
    end

    # Accepted forms are:
    #   addChore(target, selector)
    #   addChore(method(:onTimeout))
    #   addChore() { |sender, sel, ptr| block }

    alias addChoreOrig addChore

    def addChore(*args, &block)
      if args.length > 0
        if args[0].kind_of? Method
          tgt = FXPseudoTarget.new
	  tgt.connect(SEL_CHORE, args[0], block)
	  addChoreOrig(tgt, 0)
        else
          addChoreOrig(args[0], args[1])
        end
      else
        tgt = FXPseudoTarget.new
	tgt.connect(SEL_CHORE, nil, block)
	addChoreOrig(tgt, 0)
      end
    end

    # Accepted forms are:
    #   addSignal(sig, target, selector, immediate=false, flags=0)
    #   addSignal(sig, method(:onTimeout), immediate=false, flags=0)
    #   addSignal(sig, immediate=false, flags=0) { |sender, sel, ptr| block }

    alias addSignalOrig addSignal

    def addSignal(sig, *args, &block)
      if args.length > 0
        if args[0].kind_of? Method
          tgt = FXPseudoTarget.new
          tgt.connect(SEL_SIGNAL, args[0], block)
          immediate = (args.length > 1) ? args[1] : false
          flags = (args.length > 2) ? args[2] : 0
          addSignalOrig(sig, tgt, 0, immediate, flags)
        elsif (args[0].kind_of? TrueClass) || (args[0].kind_of? FalseClass)
          tgt = FXPseudoTarget.new
          tgt.connect(SEL_SIGNAL, nil, block)
          immediate = args[0]
          flags = (args.length > 1) ? args[1] : 0
          addSignalOrig(sig, tgt, 0, immediate, flags)
        else # it's an object
          tgt = args[0]
          sel = (args.length > 1) ? args[1] : 0
          immediate = (args.length > 2) ? args[2] : false
          flags = (args.length > 3) ? args[3] : 0
          addSignalOrig(sig, tgt, sel, immediate, flags)
        end
      else
        tgt = FXPseudoTarget.new
        tgt.connect(SEL_SIGNAL, nil, block)
        addSignalOrig(sig, tgt, 0, false, 0)
      end
    end

    # Accepted forms are:
    #   addInput(fd, mode, target, selector)
    #   addInput(fd, mode, method(:onTimeout))
    #   addInput(fd, mode) { |sender, sel, ptr| block }

    alias addInputOrig addInput

    def addInput(fd, mode, *args, &block)
      if args.length > 0
        if args[0].kind_of? Method
          tgt = FXPseudoTarget.new
	  tgt.connect(SEL_IO_READ, args[0], block)
	  tgt.connect(SEL_IO_WRITE, args[0], block)
	  tgt.connect(SEL_IO_EXCEPT, args[0], block)
	  addTimeoutOrig(fd, mode, tgt, 0)
        else # it's an object
          tgt = args[0]
          sel = args[1]
          addInputOrig(fd, mode, tgt, sel)
        end
      else
        tgt = FXPseudoTarget.new
	tgt.connect(SEL_IO_READ, nil, block)
	tgt.connect(SEL_IO_WRITE, nil, block)
	tgt.connect(SEL_IO_EXCEPT, nil, block)
	addInputOrig(fd, mode, tgt, 0)
      end
    end
  end

  class FX4Splitter
    include Responder2
  end
  class FXAccelTable
    include Responder2
  end
  class FXApp
    include Responder2
  end
  class FXArrowButton
    include Responder2
  end
  class FXBMPIcon
    include Responder2
  end
  class FXBMPImage
    include Responder2
  end
  class FXBitmap
    include Responder2
  end
  class FXButton
    include Responder2
  end
  class FXCanvas
    include Responder2
  end
  class FXCheckButton
    include Responder2
  end
  class FXColorBar
    include Responder2
  end
  class FXColorDialog
    include Responder2
  end
  class FXColorSelector
    include Responder2
  end
  class FXColorWell
    include Responder2
  end
  class FXColorWheel
    include Responder2
  end
  class FXComboBox
    include Responder2
  end
  class FXComposite
    include Responder2
  end
  class FXCursor
    include Responder2
  end
  class FXDataTarget
    include Responder2
  end
  class FXDebugTarget
    include Responder2
  end
  class FXDelegator
    include Responder2
  end
  class FXDial
    include Responder2
  end
  class FXDialogBox
    include Responder2
  end
  class FXDirBox
    include Responder2
  end
  class FXDirDialog
    include Responder2
  end
  class FXDirItem
    include Responder2
  end
  class FXDirList
    include Responder2
  end
  class FXDirSelector
    include Responder2
  end
  class FXDocument
    include Responder2
  end
  class FXDragCorner
    include Responder2
  end
  class FXDrawable
    include Responder2
  end
  class FXDriveBox
    include Responder2
  end
  class FXFileDialog
    include Responder2
  end
  class FXFileItem
    include Responder2
  end
  class FXFileList
    include Responder2
  end
  class FXFileSelector
    include Responder2
  end
  class FXFont
    include Responder2
  end
  class FXFontDialog
    include Responder2
  end
  class FXFontSelector
    include Responder2
  end
  class FXFrame
    include Responder2
  end
  class FXGIFCursor
    include Responder2
  end
  class FXGIFIcon
    include Responder2
  end
  class FXGIFImage
    include Responder2
  end
  class FXGLCanvas
    include Responder2
  end
  class FXGLContext
    include Responder2
  end
  class FXGLGroup
    include Responder2
  end
  class FXGLObject
    include Responder2
  end
  class FXGLShape
    include Responder2
  end
  class FXGLViewer
    include Responder2
  end
  class FXGLVisual
    include Responder2
  end
  class FXGroupBox
    include Responder2
  end
  class FXHeader
    include Responder2
  end
  class FXHeaderItem
    include Responder2
  end
  class FXHorizontalFrame
    include Responder2
  end
  class FXHorizontalSeparator
    include Responder2
  end
  class FXICOIcon
    include Responder2
  end
  class FXICOImage
    include Responder2
  end
  class FXIcon
    include Responder2
  end
  class FXIconItem
    include Responder2
  end
  class FXIconList
    include Responder2
  end
  class FXId
    include Responder2
  end
  class FXImage
    include Responder2
  end
  class FXImageView
    include Responder2
  end
  class FXInputDialog
    include Responder2
  end
  class FXJPGIcon
    include Responder2
  end
  class FXJPGImage
    include Responder2
  end
  class FXLabel
    include Responder2
  end
  class FXList
    include Responder2
  end
  class FXListBox
    include Responder2
  end
  class FXListItem
    include Responder2
  end
  class FXMDIChild
    include Responder2
  end
  class FXMDIClient
    include Responder2
  end
  class FXMDIDeleteButton
    include Responder2
  end
  class FXMDIMaximizeButton
    include Responder2
  end
  class FXMDIMenu
    include Responder2
  end
  class FXMDIMinimizeButton
    include Responder2
  end
  class FXMDIRestoreButton
    include Responder2
  end
  class FXMDIWindowButton
    include Responder2
  end
  class FXMainWindow
    include Responder2
  end
  class FXMatrix
    include Responder2
  end
  class FXMenuButton
    include Responder2
  end
  class FXMenuCaption
    include Responder2
  end
  class FXMenuCascade
    include Responder2
  end
  class FXMenuCommand
    include Responder2
  end
  class FXMenuPane
    include Responder2
  end
  class FXMenuSeparator
    include Responder2
  end
  class FXMenuTitle
    include Responder2
  end
  class FXMenubar
    include Responder2
  end
  class FXMessageBox
    include Responder2
  end
  class FXObject
    include Responder2
  end
  class FXOption
    include Responder2
  end
  class FXOptionMenu
    include Responder2
  end
  class FXPacker
    include Responder2
  end
  class FXPCXIcon
    include Responder2
  end
  class FXPCXImage
    include Responder2
  end
  class FXPicker
    include Responder2
  end
  class FXPNGIcon
    include Responder2
  end
  class FXPNGImage
    include Responder2
  end
  class FXPopup
    include Responder2
  end
  class FXPrintDialog
    include Responder2
  end
  class FXProgressBar
    include Responder2
  end
  class FXProgressDialog
    include Responder2
  end
  class FXRadioButton
    include Responder2
  end
  class FXRecentFiles
    include Responder2
  end
  class FXReplaceDialog
    include Responder2
  end
  class FXRootWindow
    include Responder2
  end
  class FXScintilla
    include Responder2
  end
  class FXScrollArea
    include Responder2
  end
  class FXScrollCorner
    include Responder2
  end
  class FXScrollWindow
    include Responder2
  end
  class FXScrollbar
    include Responder2
  end
  class FXSearchDialog
    include Responder2
  end
  class FXShell
    include Responder2
  end
  class FXShutter
    include Responder2
  end
  class FXShutterItem
    include Responder2
  end
  class FXSlider
    include Responder2
  end
  class FXSpinner
    include Responder2
  end
  class FXSplitter
    include Responder2
  end
  class FXStatusbar
    include Responder2
  end
  class FXStatusline
    include Responder2
  end
  class FXSwitcher
    include Responder2
  end
  class FXTabBar
    include Responder2
  end
  class FXTabBook
    include Responder2
  end
  class FXTabItem
    include Responder2
  end
  class FXTable
    include Responder2
  end
  class FXTableItem
    include Responder2
  end
  class FXText
    include Responder2
  end
  class FXTextField
    include Responder2
  end
  class FXTGAIcon
    include Responder2
  end
  class FXTGAImage
    include Responder2
  end
  class FXTGAIcon
    include Responder2
  end
  class FXTGAImage
    include Responder2
  end
  class FXToggleButton
    include Responder2
  end
  class FXToolbar
    include Responder2
  end
  class FXToolbarGrip
    include Responder2
  end
  class FXToolbarShell
    include Responder2
  end
  class FXToolbarTab
    include Responder2
  end
  class FXTooltip
    include Responder2
  end
  class FXTopWindow
    include Responder2
  end
  class FXTreeItem
    include Responder2
  end
  class FXTreeList
    include Responder2
  end
  class FXTreeListBox
    include Responder2
  end
  class FXVerticalFrame
    include Responder2
  end
  class FXVerticalSeparator
    include Responder2
  end
  class FXVisual
    include Responder2
  end
  class FXWindow
    include Responder2
  end
  class FXXPMIcon
    include Responder2
  end
  class FXXPMImage
    include Responder2
  end
end
