1 module nulib.events; 2 import nulib.collections.vector; 3 import nulib.collections.map; 4 import numem.core.traits; 5 import numem.core.lifetime; 6 import numem.object; 7 8 /** 9 A type for an event. 10 */ 11 alias Event(SenderType, ArgTypes...) = void function(SenderType, ArgTypes) @nogc; 12 13 /** 14 Gets whether the given type is an event callback function. 15 */ 16 enum isEvent(T) = is(T : void function(SenderType, ArgTypes) @nogc, SenderType, ArgTypes...); 17 18 /** 19 Gets the sender type of an event type $(D T). 20 */ 21 template EventSenderType(T) { 22 static if (is(T : void function(SenderType, ArgTypes), SenderType, ArgTypes...)) 23 alias EventSenderType = SenderType; 24 else 25 alias EventSenderType = void; 26 } 27 28 /** 29 Gets the argument types of an event type $(D T). 30 */ 31 template EventArgs(T) { 32 static if (is(T : void function(SenderType, ArgTypes), SenderType, ArgTypes...)) 33 alias EventArgs = ArgTypes; 34 else 35 alias EventArgs = void; 36 } 37 38 /** 39 An event handler which stores events internally. 40 */ 41 struct EventHandler(EventT) 42 if (isEvent!EventT) { 43 private: 44 @nogc: 45 vector!EventT events_; 46 47 public: 48 49 /** 50 The callbacks registered with the handler. 51 */ 52 @property EventT[] callbacks() => events_[]; 53 54 /** 55 Type of the accepted event callback functions. 56 */ 57 alias EventType = EventT; 58 59 /** 60 The type of accepted event senders. 61 */ 62 alias SenderType = EventSenderType!EventT; 63 64 /** 65 The type of accepted event arguments. 66 */ 67 alias ArgTypes = EventArgs!EventT; 68 69 /** 70 Adds an event to the handler. 71 */ 72 void opOpAssign(string op)(EventT event) 73 if (op == "~") { 74 events_ ~= event; 75 } 76 77 /** 78 Adds an event to the handler. 79 */ 80 void opOpAssign(string op)(EventT event) 81 if (op == "-") { 82 events_.remove(event); 83 } 84 85 /** 86 Calls all the events in the handler. 87 */ 88 void opCall(SenderType sender, ArgTypes args) { 89 foreach(event; events_) { 90 event(sender, args); 91 } 92 } 93 } 94 95 @("EventHandler") 96 unittest { 97 __gshared int vx; 98 99 EventHandler!(Event!(void*, int)) handler; 100 handler ~= (void* sender, int v) { 101 vx += v; 102 }; 103 104 handler(null, 42); 105 assert(vx == 42); 106 }