Created
May 28, 2011 22:05
-
-
Save abesto/997280 to your computer and use it in GitHub Desktop.
Slots and signals for CoffeeScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# 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!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is my first anything with CoffeeScript, so nitpick please.