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 }