Skip to content

Instantly share code, notes, and snippets.

@abesto
Created May 28, 2011 22:05
Show Gist options
  • Save abesto/997280 to your computer and use it in GitHub Desktop.
Save abesto/997280 to your computer and use it in GitHub Desktop.
Slots and signals for CoffeeScript
##
# Slots and signals implementation for classes
# (Porting to using simple functions should be almost trivial
##
class Connection
constructor: (@sender, @signal, @receiver, @slot) ->
connections = [] # List of connections
strict = true
# Internal function that calls all the slots connected to signal with params
send = (sender, signal, params...) ->
for c in connections
if c.sender == sender && c.signal == signal
c.receiver[ c.slot ](params...)
# CREATE a function with name `name` on the class with arbitrary parameters
# Calling this function will fire the event
# Mark the function as a signal
signal = (clazz, name) ->
clazz.prototype[name] = (params...) ->
send(this, name, params...)
clazz.prototype[name].__sigslot_signal = true
# MARK function as a slot
slot = (clazz, name) -> clazz.prototype[name].__sigslot_slot = true
# Connect the signal to the slot, ensuring that one signal is connected to a slot once at most
connect = (sender, signal, receiver, slot) ->
# Check for valid parameters if strict flag is set
if strict
throw "Signal parameter '" + signal + "' to connect is not a signal" if not sender[signal].__sigslot_signal
throw "Slot parameter '" + slot + "' to connect is not a slot" if not receiver[slot].__sigslot_slot
# Craete connection, add to connection list if needed
cn = new Connection(sender, signal, receiver, slot)
for c in connections
if c.sender == cn.sender && c.signal == cn.signal && c.receiver == cn.receiver && c.slot == cn.slot
return
connections.push cn
# Throw exception if trying to use non-signal function as signal, or non-slot function as slot?
# Note: there's no guarantee that a function not created with `signal` used as a signal will actually fire the signal
# A function not marked as a slot will work just fine, but strict mode won't accept it
setStrict = (val) -> strict = val
###########
## Usage ##
###########
class Sender
constructor: (@prefix) ->
run: (x) -> @test @prefix + x
s1 = new Sender '<- s1: '
s2 = new Sender '<- s2: '
class Receiver
constructor: (@prefix) ->
log: (x) -> console.log @prefix + x
r1 = new Receiver 'r1 '
r2 = new Receiver 'r2 '
signal Sender, 'test'
slot Receiver, 'log'
connect s1, 'test', r1, 'log'
connect s2, 'test', r1, 'log'
connect s2, 'test', r2, 'log'
connect s2, 'test', r2, 'log'
connect s2, 'test', r2, 'log'
connect s2, 'test', r2, 'log'
s1.run "Signals and slots!"
s2.run "Another signal!"
@abesto
Copy link
Author

abesto commented May 28, 2011

This is my first anything with CoffeeScript, so nitpick please.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment