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 }