1 module tinyevent; 2 3 /// Defines a regular event 4 alias Event(Args...) = void delegate(Args)[]; 5 /// Defines a cancelable event by returning false to cancel 6 alias Cancelable(Args...) = bool delegate(Args)[]; 7 8 /// Calls all functions in a regular event 9 void emit(Args...)(void delegate(Args)[] events, Args args) { 10 foreach(fn; events) 11 fn(args); 12 } 13 14 /// Calls all functions in a cancelable event 15 bool emit(Args...)(bool delegate(Args)[] events, Args args) { 16 foreach(fn; events) 17 if(!fn(args)) 18 return false; 19 return true; 20 } 21 22 /// Returns true if the type or variable is an Event!(...) 23 enum bool isEvent(T) = isEvent!(T.init); 24 /// ditto 25 enum bool isEvent(alias v) = is(typeof(v.length)) && is(typeof(v) : void delegate(Args)[], Args...); 26 /// Returns true if the type or variable is a Cancelable!(...) 27 enum bool isCancelable(T) = isCancelable!(T.init); 28 /// ditto 29 enum bool isCancelable(alias v) = is(typeof(v.length)) && is(typeof(v) : bool delegate(Args)[], Args...); 30 /// Returns true if the type or variable is an Event or Cancelable 31 enum bool isEmittable(T) = isEmittable!(T.init); 32 /// ditto 33 enum bool isEmittable(alias v) = is(typeof(v.length)) && is(typeof(v) : Ret delegate(Args)[], Ret, Args...) 34 && (is(Ret == bool) || is(Ret == void)); 35 36 /// 37 unittest { 38 Event!string onStringChange; 39 static assert (isEvent!onStringChange); 40 static assert (isEvent!(typeof(onStringChange))); 41 static assert (!isCancelable!onStringChange); 42 static assert (!isCancelable!(typeof(onStringChange))); 43 static assert (isEmittable!onStringChange); 44 static assert (isEmittable!(typeof(onStringChange))); 45 onStringChange ~= (s) { assert(s == "Foo"); }; 46 onStringChange.emit("Foo"); 47 } 48 49 /// 50 unittest { 51 Cancelable!int onIntChange; 52 static assert (!isEvent!onIntChange); 53 static assert (!isEvent!(typeof(onIntChange))); 54 static assert (isCancelable!onIntChange); 55 static assert (isCancelable!(typeof(onIntChange))); 56 static assert (isEmittable!onIntChange); 57 static assert (isEmittable!(typeof(onIntChange))); 58 int changed = 0; 59 onIntChange ~= (i) { if(i > 5) return false; changed++; return true; }; 60 onIntChange ~= (i) { if(i > 4) return false; changed++; return true; }; 61 onIntChange ~= (i) { if(i > 3) return false; changed++; return true; }; 62 assert(onIntChange.emit(2)); 63 assert(changed == 3); 64 65 changed = 0; 66 assert(!onIntChange.emit(4)); 67 assert(changed == 2); 68 } 69 70 unittest { 71 string s; 72 static assert (!isEvent!s); 73 int i; 74 static assert (!isEvent!i); 75 void fn(int i) { 76 } 77 static assert (!isEvent!fn); 78 static assert (isEvent!([&fn])); 79 void function()[] fns; 80 static assert (!isEvent!fns); 81 void delegate()[] dels; 82 static assert (isEvent!dels); 83 Event!int e; 84 static assert (isEvent!e); 85 Cancelable!int c; 86 static assert (isCancelable!c); 87 static assert (isEmittable!e && isEmittable!c); 88 Event!() en; 89 static assert (isEvent!en); 90 Cancelable!() cn; 91 static assert (isCancelable!cn); 92 Event!(Event!int, int, string, Object) em; 93 static assert (isEvent!em); 94 Cancelable!(Object, string, void function(int, string)) cm; 95 static assert (isCancelable!cm); 96 }