API  1.0.0
CPTimer.j
Go to the documentation of this file.
1 /*
2  * CPTimer.j
3  * Foundation
4  *
5  * Created by Nick Takayama.
6  * Copyright 2008.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 #define CPTimerDefaultTimeInterval 0.1
25 
31 @implementation CPTimer : CPObject
32 {
33  CPTimeInterval _timeInterval;
34  CPInvocation _invocation;
35  Function _callback;
36 
37  BOOL _repeats;
38  BOOL _isValid;
39  CPDate _fireDate;
40  id _userInfo;
41 }
42 
46 + (CPTimer)scheduledTimerWithTimeInterval:(CPTimeInterval)seconds invocation:(CPInvocation)anInvocation repeats:(BOOL)shouldRepeat
47 {
48  var timer = [[self alloc] initWithFireDate:[CPDate dateWithTimeIntervalSinceNow:seconds] interval:seconds invocation:anInvocation repeats:shouldRepeat];
49 
50  [[CPRunLoop currentRunLoop] addTimer:timer forMode:CPDefaultRunLoopMode];
51 
52  return timer;
53 }
54 
58 + (CPTimer)scheduledTimerWithTimeInterval:(CPTimeInterval)seconds target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)shouldRepeat
59 {
60  var timer = [[self alloc] initWithFireDate:[CPDate dateWithTimeIntervalSinceNow:seconds] interval:seconds target:aTarget selector:aSelector userInfo:userInfo repeats:shouldRepeat];
61 
62  [[CPRunLoop currentRunLoop] addTimer:timer forMode:CPDefaultRunLoopMode];
63 
64  return timer;
65 }
66 
70 + (CPTimer)scheduledTimerWithTimeInterval:(CPTimeInterval)seconds callback:(Function)aFunction repeats:(BOOL)shouldRepeat
71 {
72  var timer = [[self alloc] initWithFireDate:[CPDate dateWithTimeIntervalSinceNow:seconds] interval:seconds callback:aFunction repeats:shouldRepeat];
73 
74  [[CPRunLoop currentRunLoop] addTimer:timer forMode:CPDefaultRunLoopMode];
75 
76  return timer;
77 }
78 
82 + (CPTimer)timerWithTimeInterval:(CPTimeInterval)seconds invocation:(CPInvocation)anInvocation repeats:(BOOL)shouldRepeat
83 {
84  return [[self alloc] initWithFireDate:[CPDate dateWithTimeIntervalSinceNow:seconds] interval:seconds invocation:anInvocation repeats:shouldRepeat];
85 }
86 
90 + (CPTimer)timerWithTimeInterval:(CPTimeInterval)seconds target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)shouldRepeat
91 {
92  return [[self alloc] initWithFireDate:[CPDate dateWithTimeIntervalSinceNow:seconds] interval:seconds target:aTarget selector:aSelector userInfo:userInfo repeats:shouldRepeat];
93 }
94 
98 + (CPTimer)timerWithTimeInterval:(CPTimeInterval)seconds callback:(Function)aFunction repeats:(BOOL)shouldRepeat
99 {
100  return [[self alloc] initWithFireDate:[CPDate dateWithTimeIntervalSinceNow:seconds] interval:seconds callback:aFunction repeats:shouldRepeat];
101 }
102 
106 - (id)initWithFireDate:(CPDate)aDate interval:(CPTimeInterval)seconds invocation:(CPInvocation)anInvocation repeats:(BOOL)shouldRepeat
107 {
108  self = [super init];
109 
110  if (self)
111  {
112  _timeInterval = (seconds <= 0) ? CPTimerDefaultTimeInterval : seconds;
113  _invocation = anInvocation;
114  _repeats = shouldRepeat;
115  _isValid = YES;
116  _fireDate = aDate;
117  }
118 
119  return self;
120 }
121 
125 - (id)initWithFireDate:(CPDate)aDate interval:(CPTimeInterval)seconds target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)shouldRepeat
126 {
127  var invocation = [CPInvocation invocationWithMethodSignature:1];
128 
129  [invocation setTarget:aTarget];
130  [invocation setSelector:aSelector];
131  [invocation setArgument:self atIndex:2];
132 
133  self = [self initWithFireDate:aDate interval:seconds invocation:invocation repeats:shouldRepeat];
134 
135  if (self)
136  _userInfo = userInfo;
137 
138  return self;
139 }
140 
144 - (id)initWithFireDate:(CPDate)aDate interval:(CPTimeInterval)seconds callback:(Function)aFunction repeats:(BOOL)shouldRepeat
145 {
146  self = [super init];
147 
148  if (self)
149  {
150  _timeInterval = (seconds <= 0) ? CPTimerDefaultTimeInterval : seconds;
151  _callback = aFunction;
152  _repeats = shouldRepeat;
153  _isValid = YES;
154  _fireDate = aDate;
155  }
156 
157  return self;
158 }
159 
163 - (CPTimeInterval)timeInterval
164 {
165  return _timeInterval;
166 }
167 
171 - (CPDate)fireDate
172 {
173  return _fireDate;
174 }
175 
179 - (void)setFireDate:(CPDate)aDate
180 {
181  _fireDate = aDate;
182 }
183 
187 - (void)fire
188 {
189  if (!_isValid)
190  return;
191 
192  if (_callback)
193  _callback();
194  else
195  [_invocation invoke];
196 
197  if (!_isValid)
198  return;
199 
200  if (_repeats)
201  _fireDate = [CPDate dateWithTimeIntervalSinceNow:_timeInterval];
202 
203  else
204  [self invalidate];
205 }
206 
210 - (BOOL)isValid
211 {
212  return _isValid;
213 }
214 
218 - (void)invalidate
219 {
220  _isValid = NO;
221  _userInfo = nil;
222  _invocation = nil;
223  _callback = nil;
224 }
225 
229 - (id)userInfo
230 {
231  return _userInfo;
232 }
233 
234 @end
235 
236 var CPTimersTimeoutID = 1000,
238 
239 var _CPTimerBridgeTimer = function(codeOrFunction, aDelay, shouldRepeat, functionArgs)
240 {
241  var timeoutID = CPTimersTimeoutID++,
242  theFunction = nil;
243 
244  if (typeof codeOrFunction === "string")
245  {
246  theFunction = function()
247  {
248  new Function(codeOrFunction)();
249 
250  if (!shouldRepeat)
251  CPTimersForTimeoutIDs[timeoutID] = nil;
252  }
253  }
254  else
255  {
256  if (!functionArgs)
257  functionArgs = [];
258 
259  theFunction = function()
260  {
261  codeOrFunction.apply(window, functionArgs);
262 
263  if (!shouldRepeat)
264  CPTimersForTimeoutIDs[timeoutID] = nil;
265  }
266  }
267 
268  // A call such as setTimeout(f) is technically invalid but browsers seem to treat it as setTimeout(f, 0), so so will we.
269  aDelay = aDelay | 0.0;
270 
271  CPTimersForTimeoutIDs[timeoutID] = [CPTimer scheduledTimerWithTimeInterval:aDelay / 1000 callback:theFunction repeats:shouldRepeat];
272 
273  return timeoutID;
274 };
275 
276 // Avoid "TypeError: Result of expression 'window' [undefined] is not an object" when running unit tests.
277 // We can't use a regular PLATFORM(DOM) check because that platform constant is not defined in Foundation.
278 if (typeof(window) !== 'undefined')
279 {
280  window.setTimeout = function(codeOrFunction, aDelay)
281  {
282  return _CPTimerBridgeTimer(codeOrFunction, aDelay, NO, Array.prototype.slice.apply(arguments, [2]));
283  };
284 
285  window.clearTimeout = function(aTimeoutID)
286  {
287  var timer = CPTimersForTimeoutIDs[aTimeoutID];
288 
289  if (timer)
290  [timer invalidate];
291 
292  CPTimersForTimeoutIDs[aTimeoutID] = nil;
293  };
294 
295  window.setInterval = function(codeOrFunction, aDelay, functionArgs)
296  {
297  return _CPTimerBridgeTimer(codeOrFunction, aDelay, YES, Array.prototype.slice.apply(arguments, [2]));
298  };
299 
300  window.clearInterval = function(aTimeoutID)
301  {
302  window.clearTimeout(aTimeoutID);
303  };
304 }
var CPTimersTimeoutID
Definition: CPTimer.j:236
id invocationWithMethodSignature:(CPMethodSignature aMethodSignature)
Definition: CPInvocation.j:43
A representation of a single point in time.
Definition: CPDate.h:2
The main run loop for the application.
Definition: CPRunLoop.h:2
CPTimer scheduledTimerWithTimeInterval:callback:repeats:(CPTimeInterval seconds, [callback] Function aFunction, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:70
id initWithFireDate:interval:target:selector:userInfo:repeats:(CPDate aDate, [interval] CPTimeInterval seconds, [target] id aTarget, [selector] SEL aSelector, [userInfo] id userInfo, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:125
CPRunLoop currentRunLoop()
Definition: CPRunLoop.j:232
An object representation of a message.
Definition: CPInvocation.h:2
var CPTimersForTimeoutIDs
Definition: CPTimer.j:237
A timer object that can send a message after the given time interval.
Definition: CPTimer.h:2
id init()
Definition: CPObject.j:145
id initWithFireDate:interval:invocation:repeats:(CPDate aDate, [interval] CPTimeInterval seconds, [invocation] CPInvocation anInvocation, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:106
void addTimer:forMode:(CPTimer aTimer, [forMode] CPString aMode)
Definition: CPRunLoop.j:313
CompletionHandlerAgent prototype invalidate
void invalidate()
Definition: CPTimer.j:218
id dateWithTimeIntervalSinceNow:(CPTimeInterval seconds)
Definition: CPDate.j:47
id initWithFireDate:interval:callback:repeats:(CPDate aDate, [interval] CPTimeInterval seconds, [callback] Function aFunction, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:144
CompletionHandlerAgent prototype fire
#define CPTimerDefaultTimeInterval
Definition: CPTimer.j:24
id alloc()
Definition: CPObject.j:130