From: Niklas Frykholm Date: 2002-02-01T23:54:49+09:00 Subject: [GUI] Signal/slot pattern in ruby I have been thinking a bit of how I would want message passing to work in an ideal ruby GUI. I think the signal/slot mechanism in Qt is the most elegant basic mechanism. (The other options are AFAIK: callbacks, observers and subclassing.) In a ruby GUI, signals and slots should be ordinary ruby functions. It should also be possible to use Proc's as slots. Like this: class Test include Connect; extend Signal attr_reader :x signal :new_value def initialize(x); @x = x; end def x=(x) @x = x new_value(x) end end a = Test.new(3) b = Test.new(7) a.connect(:new_value) {|i| puts "a value set to #{i}"} b.connect(:new_value) {|i| puts "b value set to #{i}"} a.connect(:new_value, b, :x=) a.x = 5 a.disconnect(:new_value, b, :x=) a.x = 10 This would produce the output: a value set to 5 b value set to 5 a value set to 10 Here is my implementation of the Connect and Signal modules that make this happen: module Connect def connect(signal, *args, &pr) @_signals = Hash.new([]) unless @_signals @_signals[signal] += if pr then [pr] else [args] end end def disconnect(signal, *args) return unless @_signals @_signals[signal].delete(args) end def activate_signal(signal, *args, &pr) return unless @_signals @_signals[signal].each {|obj, method| if method == nil obj.call(*args, &pr) else obj.send(method, *args, &pr) end } end end module Signal def signal(*args) args.each {|a| module_eval %Q{def #{a.to_s}(*args, &pr) activate_signal(#{a.inspect}, *args, &pr) end} } end end What do you think of all this? Is there some other message passing mechanism that you would rather see in a ruby GUI? // Niklas