1 module sbylib.event.eventcontext; 2 3 import std; 4 import sbylib.event; 5 6 private alias BindCallback = void delegate(); 7 private struct BindNotification { EventContext context; bool bind; } 8 9 class EventContext { 10 11 package static EventContext[] currentContext; 12 13 private Array!BindCallback bindCallbackList; 14 private Array!BindCallback unbindCallbackList; 15 package Array!IEvent eventList; 16 private bool _bound = false; 17 18 private static int seed = 0; 19 20 ~this() { 21 if (this.isBound) { 22 this.unbind(); 23 } 24 foreach (e; eventList) { 25 e.kill(); 26 } 27 } 28 29 void bind() { 30 _bound = true; 31 foreach (cb; bindCallbackList) cb(); 32 } 33 34 void unbind() { 35 foreach (cb; unbindCallbackList) cb(); 36 _bound = false; 37 } 38 39 bool isBound() { 40 return _bound; 41 } 42 43 ContextRegister opCall() { 44 currentContext ~= this; 45 return ContextRegister(); 46 } 47 48 BindNotification bound() { 49 return BindNotification(this, true); 50 } 51 52 BindNotification unbound() { 53 return BindNotification(this, false); 54 } 55 56 private BindCallback add(BindCallback callback, bool bind) { 57 if (callback) { 58 if (bind) bindCallbackList ~= callback; 59 else unbindCallbackList ~= callback; 60 } 61 return callback; 62 } 63 64 private void remove(BindCallback callback, bool bind) { 65 if (bind) { 66 bindCallbackList.linearRemove(bindCallbackList[].find(callback).take(1)); 67 } else { 68 unbindCallbackList.linearRemove(unbindCallbackList[].find(callback).take(1)); 69 } 70 } 71 } 72 73 VoidEvent when(BindNotification condition) { 74 import sbylib.event : when; 75 76 auto event = new VoidEvent; 77 auto cb = condition.context.add({ event.fire(); }, condition.bind); 78 when(event.finish).then({ 79 condition.context.remove(cb, condition.bind); 80 }); 81 return event; 82 } 83 84 private struct ContextRegister { 85 86 ~this() { 87 EventContext.currentContext.popBack; 88 } 89 }