1 module utils;
2 
3 import core.time;
4 import std.traits;
5 import rx;
6 import dlangui.core.signals;
7 import dlangui.widgets.widget;
8 
9 ///Wrap a Signal!T as Observable
10 auto asObservable(T)(ref T signal) if (is(T == Signal!U, U) && is(U == interface))
11 {
12     static if (is(T == Signal!U, U))
13     {
14         alias return_t = ReturnType!(__traits(getMember, U, __traits(allMembers, U)[0]));
15         alias param_t = ParameterTypeTuple!(__traits(getMember, U, __traits(allMembers, U)[0]));
16         static assert(param_t.length == 1);
17     }
18 
19     static struct LocalObservable
20     {
21         alias ElementType = param_t[0];
22         this(ref T signal)
23         {
24             _subscribe = (Observer!ElementType o) {
25                 auto dg = (ElementType w) {
26                     o.put(w);
27                     static if (is(return_t == bool))
28                     {
29                         return true;
30                     }
31                 };
32 
33                 signal.connect(dg);
34 
35                 return new AnonymousDisposable({ signal.disconnect(dg); });
36             };
37         }
38 
39         auto subscribe(U)(U observer)
40         {
41             return _subscribe(observerObject!ElementType(observer));
42         }
43 
44         Disposable delegate(Observer!ElementType) _subscribe;
45     }
46 
47     return LocalObservable(signal);
48 }
49 
50 struct TimerHandler
51 {
52     CancellationToken token;
53     void delegate() action;
54 }
55 
56 class DlangUIScheduler : Widget, AsyncScheduler
57 {
58     TimerHandler[ulong] _actions;
59     Object _gate = new Object();
60     ulong _timerId;
61 
62     void start(void delegate() op)
63     {
64         auto id = setTimer(0);
65         synchronized (_gate)
66         {
67             _actions[id] = TimerHandler(null, op);
68         }
69     }
70 
71     CancellationToken schedule(void delegate() op, Duration val)
72     {
73         auto ms = val.total!"msecs";
74         auto id = setTimer(ms);
75         auto token = new CancellationToken();
76         synchronized (_gate)
77         {
78             _actions[id] = TimerHandler(token, op);
79         }
80         return token;
81     }
82 
83     override bool onTimer(ulong id)
84     {
85         CancellationToken token;
86         void delegate() action;
87 
88         synchronized (_gate)
89         {
90             auto temp = id in _actions;
91             if (temp)
92             {
93                 token = (*temp).token;
94                 action = (*temp).action;
95 
96                 _actions.remove(id);
97             }
98             else
99             {
100                 return false;
101             }
102         }
103 
104         if (token is null || !token.isCanceled)
105         {
106             action();
107             return true;
108         }
109 
110         return false;
111     }
112 }