1 // Written by Christopher E. Miller 2 // See the included license.txt for copyright and license details. 3 4 5 /// 6 module dfl.timer; 7 8 private import dfl.internal.winapi, dfl.event, dfl.base, dfl.application, 9 dfl.internal.dlib; 10 11 12 /// 13 class Timer // docmain 14 { 15 //EventHandler tick; 16 Event!(Timer, EventArgs) tick; /// 17 18 19 /// 20 @property void enabled(bool on) // setter 21 { 22 if(on) 23 start(); 24 else 25 stop(); 26 } 27 28 /// ditto 29 @property bool enabled() // getter 30 { 31 return timerId != 0; 32 } 33 34 35 /// 36 final @property void interval(size_t timeout) // setter 37 { 38 if(!timeout) 39 throw new DflException("Invalid timer interval"); 40 41 if(this._timeout != timeout) 42 { 43 this._timeout = timeout; 44 45 if(timerId) 46 { 47 // I don't know if this is the correct behavior. 48 // Reset the timer for the new timeout... 49 stop(); 50 start(); 51 } 52 } 53 } 54 55 /// ditto 56 final @property size_t interval() // getter 57 { 58 return _timeout; 59 } 60 61 62 /// 63 final void start() 64 { 65 if(timerId) 66 return; 67 68 assert(_timeout > 0); 69 70 timerId = SetTimer(null, 0, _timeout, &timerProc); 71 if(!timerId) 72 throw new DflException("Unable to start timer"); 73 allTimers[timerId] = this; 74 } 75 76 /// ditto 77 final void stop() 78 { 79 if(timerId) 80 { 81 //delete allTimers[timerId]; 82 allTimers.remove(timerId); 83 KillTimer(null, timerId); 84 timerId = 0; 85 } 86 } 87 88 89 /// 90 this() 91 { 92 } 93 94 /// ditto 95 this(void delegate(Timer) dg) 96 { 97 this(); 98 if(dg) 99 { 100 this._dg = dg; 101 tick ~= &_dgcall; 102 } 103 } 104 105 /// ditto 106 this(void delegate(Object, EventArgs) dg) 107 { 108 assert(dg !is null); 109 110 this(); 111 tick ~= dg; 112 } 113 114 /// ditto 115 this(void delegate(Timer, EventArgs) dg) 116 { 117 assert(dg !is null); 118 119 this(); 120 tick ~= dg; 121 } 122 123 124 ~this() 125 { 126 dispose(); 127 } 128 129 130 protected: 131 132 void dispose() 133 { 134 stop(); 135 } 136 137 138 /// 139 void onTick(EventArgs ea) 140 { 141 tick(this, ea); 142 } 143 144 145 private: 146 DWORD _timeout = 100; 147 UINT timerId = 0; 148 void delegate(Timer) _dg; 149 150 151 void _dgcall(Object sender, EventArgs ea) 152 { 153 assert(_dg !is null); 154 _dg(this); 155 } 156 } 157 158 159 private: 160 161 Timer[UINT] allTimers; 162 163 164 extern(Windows) void timerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) nothrow 165 { 166 try 167 { 168 if(idEvent in allTimers) 169 { 170 allTimers[idEvent].onTick(EventArgs.empty); 171 } 172 else 173 { 174 debug(APP_PRINT) 175 cprintf("Unknown timer 0x%X.\n", idEvent); 176 } 177 } 178 catch(DThrowable e) 179 { 180 Application.onThreadException(e); 181 } 182 } 183