1 /++
2 Object module for tracking some global events like timers,
3 global event handlers, etc.
4 
5 Macros:
6     LREF = <a href="#$1">$1</a>
7     HREF = <a href="$1">$2</a>
8 
9 Authors: $(HREF https://github.com/TodNaz,TodNaz)
10 Copyright: Copyright (c) 2020 - 2021, TodNaz.
11 License: $(HREF https://github.com/TodNaz/Tida/blob/master/LICENSE,MIT)
12 +/
13 module tida.listener;
14 
15 public import std.datetime;
16 import tida.event;
17 
18 private struct Event
19 {
20 public:
21     void delegate(EventHandler) @safe event;
22 }
23 
24 /// Timer structure.
25 struct Timer
26 {
27 public:
28     MonoTime start; /// Timer start time
29     Duration duration; /// Timer duration
30     void delegate() @safe onEnd; /// Timer callback
31     bool isRepeat = false; /// Is repeat?
32 
33 @safe:
34     bool tick()
35     {
36         if (!isActual)
37         {
38             if (onEnd !is null) onEnd();
39 
40             if (isRepeat)
41             {
42                 start = MonoTime.currTime;
43                 return false;
44             }else
45                 return true;
46         }else
47             return false;
48     }
49 
50     /// Indicates whether the timer is in effect.
51     bool isActual()
52     {
53         return MonoTime.currTime - start < duration;
54     }
55 
56     /// Shows the remaining time.
57     Duration remainder()
58     {
59         return MonoTime.currTime - start;
60     }
61 }
62 
63 /++
64 Object module for tracking some global events like timers,
65 global event handlers, etc.
66 +/
67 class Listener
68 {
69     import std.algorithm : remove;
70 
71 private:
72     Event[] events;
73     Timer[] timers;
74 
75 public @safe:
76     void clearTimers()
77     {
78         timers = [];
79     }
80 
81     /++
82     Stop the timer if there is such an instance.
83 
84     Params:
85         tm = Timer.
86     +/
87     void timerStop(Timer* tm)
88     {
89         foreach (i; 0 .. timers.length)
90         {
91             if (timers[i] == *tm)
92             {
93                 timers = timers.remove(i);
94                 return;
95             }
96         }
97     }
98 
99     /++
100     Start a timer.
101 
102     Params:
103         func = The function to call when the timer expires.
104         duration = Timer duration.
105         isRepeat = Whether to repeat the timer.
106 
107     Example:
108     ---
109     listener.timer({
110         writeln("3 seconds!");
111     },dur!"msecs"(3000),true);
112     ---
113 
114     Returns: A pointer to a timer.
115     +/
116     Timer* timer(void delegate() @safe func, Duration duration, bool isRepeat = false) @trusted
117     {
118         timers ~= Timer(MonoTime.currTime, duration, func, isRepeat);
119 
120         return &timers[$-1];
121     }
122 
123     /++
124     Supply a function to handle events, no matter what the scene.
125 
126     Params:
127         func = Function for handler.
128     +/
129     void globalEvent(void delegate(EventHandler) @safe func) @trusted
130     {
131         events ~= Event(func);
132     }
133 
134     void eventHandle(EventHandler event) @trusted
135     {
136         foreach(ev; events)
137         {
138             ev.event(event);
139         }
140     }
141 
142     void timerHandle() @safe
143     {
144         foreach(i; 0 .. timers.length)
145         {
146             if(timers[i].tick()) {
147                 timers = timers.remove(i);
148                 return;
149             }
150         }
151     }
152 }