1 module events.event; 2 import events.eventargs; 3 4 /** 5 An easy alias for the EventHandler signature. 6 */ 7 //alias EventHandler = void delegate(void* sender, EventArgs data); 8 9 /** 10 An event. 11 To add event handlers to the event use ~= or += followed by your event delegate. 12 (use EventHandler for an easy signature for the delegate) 13 14 The delegate should take an void* sender and EventArgs argument. 15 16 Use -= to remove an event handler delegate from the event. 17 */ 18 public class Event(EventData) { 19 private: 20 alias EventHandler = void delegate(void* sender, EventData data); 21 EventHandler[] handlers; 22 23 public: 24 25 /** 26 Gets the amount of handlers that are bound to this event 27 */ 28 size_t count() { 29 return handlers.length; 30 } 31 32 /** 33 Clears all handlers from the event 34 */ 35 void clear() { 36 handlers.length = 0; 37 } 38 39 /** 40 Call all event handlers bound to this event 41 */ 42 void opCall(void* sender, EventData data) { 43 foreach(EventHandler handler; handlers) { 44 handler(sender, data); 45 } 46 } 47 48 /** 49 Call all event handlers bound to this event 50 */ 51 void opCall(void* sender) { 52 foreach(EventHandler handler; handlers) { 53 handler(sender, EventData.init); 54 } 55 } 56 57 /** 58 Add a new handler 59 */ 60 deprecated("C# style event adding is deprecated, please use ~= instead.") 61 Event opOpAssign(string op : "+")(EventHandler handler) { 62 handlers.length++; 63 handlers[$-1] = handler; 64 return this; 65 } 66 67 /** 68 Add a new handler 69 */ 70 Event opOpAssign(string op : "~")(EventHandler handler) { 71 handlers.length++; 72 handlers[$-1] = handler; 73 return this; 74 } 75 76 /** 77 Deletes a handler 78 */ 79 Event opOpAssign(string op : "-")(EventHandler handler) { 80 int remove = 0; 81 for (int i = 0; i < handlers.length; i++) { 82 if (handlers[i] == handler) { 83 handlers[i] = null; 84 remove++; 85 } 86 87 if (remove == handlers.length) break; 88 89 if (handlers[i-1] is null) { 90 handlers[i-1] = handlers[i]; 91 handlers[i] = null; 92 } 93 } 94 handlers.length -= remove; 95 return this; 96 } 97 } 98 99 /** 100 Test the creation and execution of an event 101 */ 102 unittest { 103 104 struct TestEventData { string name; } 105 bool wasRun; 106 107 // Test creation 108 auto eventHandler = (void* sender, TestEventData args) { 109 assert(args.name == "test", "Expected value of event args to be \"Test\""); 110 wasRun = true; 111 }; 112 113 Event!TestEventData testEvent = new Event!TestEventData; 114 testEvent ~= eventHandler; 115 116 // Test execution 117 testEvent(null, TestEventData("test")); 118 assert(wasRun, "Expected event to be executed!"); 119 120 // Test deletion of event handler 121 testEvent -= eventHandler; 122 assert(testEvent.count == 0, "Expected event to have no handlers!"); 123 } 124 125 /** 126 A basic event that takes an EventArgs as arguments 127 */ 128 public class BasicEvent : Event!EventArgs { } 129 130 /** 131 Test the creation and execution of a basic event 132 */ 133 unittest { 134 class TestEventArgs : EventArgs { 135 string name; 136 137 this(string name) { 138 this.name = name; 139 } 140 } 141 bool wasRun; 142 143 // Test creation 144 auto eventHandler = (void* sender, EventArgs args) { 145 TestEventArgs testArgs = cast(TestEventArgs)args; 146 assert(testArgs.name == "test", "Expected value of event args to be \"Test\""); 147 wasRun = true; 148 }; 149 150 BasicEvent testEvent = new BasicEvent; 151 testEvent ~= eventHandler; 152 153 // Test execution 154 testEvent(null, new TestEventArgs("test")); 155 assert(wasRun, "Expected event to be executed!"); 156 157 // Test deletion of event handler 158 testEvent -= eventHandler; 159 assert(testEvent.count == 0, "Expected event to have no handlers!"); 160 }