#
# dispatch.rb
#
#   Copyright (c) 1999,2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
#
#   This program is free software.
#   You can distribute/modify this program under the terms of
#   the GNU General Public License version 2 or later.
#


module Dispatchable

  def Dispatchable.append_features( mod )

    super   # don't forget

    def mod.event_handler( sym )
      name = sym.id2name
      str = %-
        def #{name}( &block )
          unless block then
            raise ArgumentError, 'event_handler() called without block'
          end
          push_event( :#{name}, block )
        end
      -
      module_eval str
    end
  end


  def push_event( sym, block )
    @dispatch_table = {} unless defined? @dispatch_table
    unless arr = @dispatch_table[ sym ] then
      @dispatch_table[ sym ] = arr = []
    end
    arr.push block
  end


  def pop_event( sym )
    if tbl = @dispatch_table then
      if arr = tbl[ sym ] then
        arr.pop
      end
    end
  end


  def dispatch( sym, *args )
    return unless defined? @dispatch_table
    if arr = @dispatch_table[ sym ] then
      arr.each {|block| block.call( self, *args ) }
    end
  end

end
