Package library :: Package pyjamas :: Module Timer
[hide private]
[frames] | no frames]

Source Code for Module library.pyjamas.Timer

  1  # Copyright (C) 2010, Daniel Popowich <danielpopowich@gmail.com> 
  2  # 
  3  # Licensed under the Apache License, Version 2.0 (the "License"); 
  4  # you may not use this file except in compliance with the License. 
  5  # You may obtain a copy of the License at 
  6  # 
  7  #     http://www.apache.org/licenses/LICENSE-2.0 
  8  # 
  9  # Unless required by applicable law or agreed to in writing, software 
 10  # distributed under the License is distributed on an "AS IS" BASIS, 
 11  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 12  # See the License for the specific language governing permissions and 
 13  # limitations under the License. 
 14   
 15  from pyjamas import Window 
 16  from __pyjamas__ import JS, get_main_frame 
 17  import pyjd 
 18  from traceback import print_exc # used in Timer.pywebkitgtknew.py for debugging 
 19   
20 -class Timer(object):
21 22 ''' 23 Timer() a re-implementation of GWT's Timer class. This class has 24 the same interface as GWT's with two minor enhancements in the 25 constructor which changes what gets fired when the timer goes off. 26 ''' 27 28 __timers = set() 29
31 ## window closing events 32 # cancel all the timers when window is closed
33 - def onWindowClosed(self):
34 for timer in list(Timer.__timers): 35 timer.cancel()
36
37 - def onWindowClosing(self):
38 pass
39
40 - def __init__(self, delayMillis=0, notify=None):
41 42 '''Called with no arguments, create a timer that will call its 43 run() method when it is scheduled and fired. This usage 44 requires subclassing to implement the run() method. This is 45 GWT's interface and behaviour. 46 47 There are two enhancements to pyjamas' implementation when 48 specified with special keyword arguments, one of which 49 obviates the need for subclassing:: 50 51 timer = Timer(delayMillis=ms) 52 53 is identical to:: 54 55 timer = Timer() 56 timer.schedule(ms) 57 58 and:: 59 60 timer = Timer(notify=object_or_func) 61 62 is the same as:: 63 64 timer = Timer() 65 run = getattr(object_or_func, 'onTimer', object_or_func) 66 if not callable(run): raise ValueError, msg 67 68 i.e., the value passed to notify is checked to see if it has 69 an onTimer attribute; if so, it is used as the callable, if 70 not, the object itself is used as the callable. 71 72 NOTE: when notify is specified, the function or method will be 73 called with one argument: the instance of the timer. So, this 74 would be proper usage:: 75 76 def timer_cb(timer): 77 ... 78 79 timer = Timer(notify=timer_cb) 80 81 or:: 82 83 class myclass: 84 85 def __init__(self): 86 ... 87 self.timer = Timer(notify=self) 88 89 def onTimer(self, timer): 90 ... 91 ''' 92 93 # initialize a few house keeping vars 94 self.__tid = None 95 self.__onTimer = lambda: self.run() 96 Window.addWindowCloseListener(Timer.__WindowCloseListener()) 97 98 # check notify 99 if notify is not None: 100 run = getattr(notify, 'onTimer', notify) 101 if not callable(run): 102 raise ValueError, 'Programming error: notify must be callable' 103 self.__onTimer = lambda: run(self) 104 105 # ugly, ugly, ugly, but there's no other way to get 106 # implementation-specific initialization (without subclassing, 107 # which the override system doesn't do). The default is a 108 # no-op. We do it here, so the instance can be init'd before 109 # the possible scheduling of the timer. 110 self.__impl_init_hook() 111 112 # schedule? 113 if delayMillis != 0: 114 self.schedule(delayMillis)
115
116 - def __impl_init_hook(self):
117 pass
118
119 - def cancel(self):
120 'Cancel the timer.' 121 122 if self.__tid is None: 123 return 124 125 if self.__is_repeating: 126 self.__clearInterval(self.__tid) 127 else: 128 self.__clearTimeout(self.__tid) 129 130 self.__tid = None 131 Timer.__timers.discard(self)
132
133 - def run(self):
134 """ 135 The method that gets fired when the timer goes off. 136 The base class raises a NotImplementedError if it is not 137 overridden by a subclass or if Timer isn't instantiated with 138 the notify keyword arguement. 139 """ 140 raise NotImplementedError, ('''Timer.run() must be overridden or Timer 141 must be instantiated with notify keyword 142 argument''')
143
144 - def schedule(self, delayMillis):
145 '''Schedule this timer to fire in delayMillis milliseconds. 146 Calling this method cancels (for this instance only) any 147 previously scheduled timer.''' 148 149 if delayMillis <= 0: 150 raise ValueError, 'delay must be positive' 151 152 self.cancel() 153 self.__is_repeating = False 154 self.__tid = self.__setTimeout(delayMillis) 155 Timer.__timers.add(self)
156 157
158 - def scheduleRepeating(self, periodMillis):
159 '''Schedule this timer to fire forever (or until cancelled) 160 every periodMillis milliseconds. Calling this method cancels 161 (for this instance only) any previously scheduled timer.''' 162 163 if periodMillis <= 0: 164 raise ValueError, 'period must be positive' 165 166 self.cancel() 167 self.__is_repeating = True 168 self.__tid = self.__setInterval(periodMillis) 169 Timer.__timers.add(self)
170 171 # fire the timer
172 - def __fire(self, *args, **kwds):
173 # if not repeating, remove it from the list of active timers 174 if not self.__is_repeating: 175 Timer.__timers.discard(self) 176 self.__onTimer()
177 178 ###################################################################### 179 # Platforms may need to implement the following four methods 180 ###################################################################### 181
182 - def __setTimeout(self, delayMillis):
183 return get_main_frame().window.setTimeout(self.__fire, delayMillis)
184
185 - def __clearTimeout(self,tid):
186 return get_main_frame().window.clearTimeout(tid)
187
188 - def __setInterval(self, periodMillis):
189 return get_main_frame().window.setInterval(self.__fire, periodMillis)
190
191 - def __clearInterval(self, tid):
192 return get_main_frame().window.clearInterval(tid)
193