1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 from pyjamas import Window
16 from __pyjamas__ import JS, get_main_frame
17 import pyjd
18 from traceback import print_exc
19
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
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
94 self.__tid = None
95 self.__onTimer = lambda: self.run()
96 Window.addWindowCloseListener(Timer.__WindowCloseListener())
97
98
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
106
107
108
109
110 self.__impl_init_hook()
111
112
113 if delayMillis != 0:
114 self.schedule(delayMillis)
115
118
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
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
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
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
172 - def __fire(self, *args, **kwds):
173
174 if not self.__is_repeating:
175 Timer.__timers.discard(self)
176 self.__onTimer()
177
178
179
180
181
183 return get_main_frame().window.setTimeout(self.__fire, delayMillis)
184
186 return get_main_frame().window.clearTimeout(tid)
187
189 return get_main_frame().window.setInterval(self.__fire, periodMillis)
190
192 return get_main_frame().window.clearInterval(tid)
193