Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 308 lines (250 sloc) 10.739 kb
41078c9 @dpopowich copyright notices
dpopowich authored
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
1b69d84 @dpopowich New interface of Timer class with implementations for all browsers
dpopowich authored
15 # for desktop
16 import pyjd
17 # ui imports
18 from pyjamas.ui.HTML import HTML
19 from pyjamas.ui.RootPanel import RootPanel
20 from pyjamas.ui.Button import Button
21 from pyjamas.ui.DialogBox import DialogBox
22 from pyjamas.ui.Grid import Grid
23 from pyjamas.ui.HorizontalSlider import HorizontalSlider
24 from pyjamas.ui.Label import Label
25 from pyjamas.ui.HorizontalPanel import HorizontalPanel
26 from pyjamas.ui.SimplePanel import SimplePanel
27 from pyjamas.ui.CaptionPanel import CaptionPanel
28
29 # other pyjamas imports
30 from pyjamas import DOM
31
32 # pyjamas client-side library
33 from random import random
34 from datetime import datetime
35
38c37b5 @dpopowich Tweaked text.
dpopowich authored
36 # Timer class
1b69d84 @dpopowich New interface of Timer class with implementations for all browsers
dpopowich authored
37 from pyjamas.Timer import Timer
38
39 ######################################################################
40 # The next three classes demonstrate three ways to create/use timers
41 ######################################################################
42
43 class Clock:
44
45 # pyjamas doesn't generate __doc__
46 __doc__ = '''This demonstrates using Timer instantiated with the
47 notify keyword, as in:<pre> timer = Timer(notify=func) </pre>When
48 the timer fires it will call func() with no arguments (or
49 <code>self</code> if it is a bound method as in this example).
50 This timer is scheduled with the <code>scheduleRepeating()</code>
51 method, so after func() is called, it is automatically rescheduled
52 to fire again after the specified period. The timer can be
53 cancelled by calling the <code>cancel()</code> method; this
54 happens when you click on the button.
55 '''
56
57
58 start_txt = 'Click to start the clock'
59 stop_txt = 'Click to stop the clock'
60
61 def __init__(self):
62
63 # the button
64 self.button = Button(listener=self)
65 # set an attr on the button to keep track of its state
66 self.button.stop = False
67 # date label
68 self.datelabel = Label(StyleName='clock')
69 # the timer
70 self.timer = Timer(notify=self.updateclock)
71 # kick start
72 self.onClick(self.button)
73
74 def onClick(self, button):
75 if self.button.stop:
76 # we're stopping the clock
77 self.button.stop = False
78 self.timer.cancel()
79 self.button.setText(self.start_txt)
80 else:
81 # we're starting the clock
82 self.button.stop = True
83 self.timer.scheduleRepeating(1000)
84 self.button.setText(self.stop_txt)
85
727548a @dpopowich Restored the interface to the callable passed to the notify keyword
dpopowich authored
86 def updateclock(self, timer):
1b69d84 @dpopowich New interface of Timer class with implementations for all browsers
dpopowich authored
87
88 # the callable attached to the timer with notify
89 dt = datetime.now().replace(microsecond=0)
90 self.datelabel.setText(dt.isoformat(' '))
91
92 class PopupTimerButton(Timer, Button):
93
94 __doc__ = '''The timer in this demo is a subclass of Timer which
95 implements the <code>run()</code> method. Worth noting in this
96 example is the use of the method <code>schedule()</code> at the
97 end of <code>run()</code> (contrast this to the use of
98 <code>scheduleRepeating()</code> in the previous example). In this
99 demo when the timer counts down to zero it creates a popup which
100 will appear in the box to the left. The timer can be cancelled by
101 clicking the button before it reaches zero.
102 '''
103
104 def __init__(self, countdown):
105 # It's a Timer, no it's a Button, WAIT! It's BOTH!!
106 Timer.__init__(self)
107 Button.__init__(self)
108
109 # save the countdown value
110 self.countdown_save = countdown
111 # this instance handles the clicks
112 self.addClickListener(self)
113 # the box the popups go into
114 self.box = SimplePanel(StyleName='popupbox')
115 # kickstart
116 self.reset()
117
118 def run(self):
119
120 # When subclassing, we just implement the run method
121
122 # update the countdown
123 self.setHTML('Popup in <b>%d</b> seconds! (Click to cancel)'
124 % self.countdown)
125 # reschdule if we're not to zero else create the popup
126 self.countdown -= 1
127 if self.countdown >= 0:
128 self.schedule(1000)
129 else:
130 self.create_popup()
131 self.reset()
132
133 def reset(self):
134 # reset to starting state
135 self.setHTML('Click for countdown popup')
136 self.countdown = self.countdown_save
137 self.start = True
138
139 def onClick(self, *arg):
140
141 # handle button clicks
142
143 # are we cancelling?
144 if not self.start:
145 self.cancel()
146 self.reset()
147 return
148
149 # no we're starting
150 self.start = False
151 self.schedule(1)
152
153 def create_popup(self):
154
155 # create the popup in the middle box
156 popup = DialogBox(False, False)
157 popup.onClick = lambda w: popup.hide()
158 popup.setHTML('<b>Hello!</b>')
159 popup.setWidget(Button('Close', popup))
160 x = self.box.getAbsoluteLeft() + random()*100
161 y = self.box.getAbsoluteTop() + random()*100
162 popup.setPopupPosition(x, y)
163 popup.show()
164
165 class RandomColor:
166
167 __doc__ = '''This last example demonstrates what most pyjamas
168 programmers currently do with timers: create a Timer instance
169 specifying <code>notify</code> with an object that has an
170 <code>onTimer</code> attribute that is callable. The slider on
171 the left will adjust how often the middle panel changes color; it
172 is either OFF or a value of seconds from 1 to 5. Changing the
173 slider immediately cancels the current timer and starts a new
174 timer to change the color in the newly specified time. Like the
175 previous example, this timer reschedules itself (if it wasn't
176 turned off) at the end of the call to <code>onTimer()</code>.
177 '''
178
179 def __init__(self):
180
181 # create the label and slider
182 self.__label = Label('OFF')
183 self.slider = slider = HorizontalSlider(0, 5, step=1,
184 StyleName="slider")
185 slider.setDragable(True)
186 slider.addControlValueListener(self)
187
188 # put them in a hpanel
189 self.hpanel = hpanel = HorizontalPanel(Spacing=10)
190 hpanel.add(slider)
191 hpanel.add(self.__label)
192
193 # create the color panel and give it color
194 self.colorpanel = CaptionPanel('Color:',
195 SimplePanel(StyleName='colorpanel'))
196 self.randomcolor()
197
198 # we're initially off
199 self.value = 0
200 # create our timer
201 self.timer = Timer(notify=self)
202
203 def initialize(self):
204
205 # this method solves an apparent bug with the slider: the
206 # slider doesn't draw its handle if the position is set before
207 # showing, so instead of doing this in __init__ (where I
208 # originally had it), this method gets called after it is
209 # shown on the root panel. See below when it gets called.
210 self.slider.setValue(self.value)
211 self.slider.setControlPos(self.value)
212
727548a @dpopowich Restored the interface to the callable passed to the notify keyword
dpopowich authored
213 def onTimer(self, timer):
1b69d84 @dpopowich New interface of Timer class with implementations for all browsers
dpopowich authored
214
215 # when the timer fires we randomize the color and (maybe)
216 # reschedule ourselves.
217 self.randomcolor()
218 v = self.value * 1000
219 if v:
220 self.timer.schedule(v)
221
222 def onControlValueChanged(self, sender, old, new):
223
224 # event handler for when the slider is moved.
225 if new == self.value:
226 return
227 self.value = new
228
229 # is it being turned off?
230 if new == 0:
231 self.__label.setText('OFF')
232 self.timer.cancel()
233 else:
234 # no it's being reset
235 self.__label.setText(str(new) + ' sec')
727548a @dpopowich Restored the interface to the callable passed to the notify keyword
dpopowich authored
236 self.onTimer(self.timer)
1b69d84 @dpopowich New interface of Timer class with implementations for all browsers
dpopowich authored
237
238 def randomcolor(self):
239
240 # randomize the color and set the panel accordingly
241 r = random()*256
242 g = random()*256
243 b = random()*256
244 e = self.colorpanel.getWidget().getElement()
245 color = '#%02x%02x%02x' % (r, g, b)
246 self.colorpanel.setCaption('Color: %s' % color)
247 DOM.setStyleAttribute(e, "background", color)
248
249
250 ######################################################################
251 # The app
252 ######################################################################
253 class timerdemo:
254
255 def __init__(self):
256
257 # layed out in a grid with odd rows a different color for
258 # visual separation
259 grid = Grid(4,3,CellPadding=50,CellSpacing=0)
260 rf = grid.getRowFormatter()
261 rf.setStyleName(1, 'oddrow')
262 rf.setStyleName(3, 'oddrow')
263
264 # the clock
265 clock = Clock()
266 grid.setWidget(0, 0, CaptionPanel('Using notify()', clock.button, StyleName='left'))
267 grid.setWidget(0, 1, clock.datelabel)
268 grid.setWidget(0, 2, HTML(Clock.__doc__, StyleName='desc'))
269
270 # popup timer buttons
271 ptb = PopupTimerButton(5)
272 grid.setWidget(1, 0, CaptionPanel('Subclassing Timer()', ptb, StyleName='left'))
273 grid.setWidget(1, 1, ptb.box)
274 grid.setWidget(1, 2, HTML(PopupTimerButton.__doc__, StyleName='desc'))
275
276 # the second instance
277 ptb = PopupTimerButton(15)
278 grid.setWidget(2, 0, CaptionPanel('Subclassing Timer()&nbsp;&nbsp;(<em>again</em>)',
279 ptb, StyleName='left'))
280 grid.setWidget(2, 1, ptb.box)
281 grid.setWidget(2, 2, HTML('''This is the same as the previous
282 example and is here to demonstrate
283 creating multiple timers (each with
284 their own state) which is difficult
285 to do without sublcassing''', StyleName='desc'))
286
287 # random color
288 randomcolor = RandomColor()
289 grid.setWidget(3, 0, CaptionPanel('Using onTimer()', randomcolor.hpanel, StyleName='left'))
290 grid.setWidget(3, 1, randomcolor.colorpanel)
291 grid.setWidget(3, 2, HTML(RandomColor.__doc__, StyleName='desc'))
292
293 # add it all to the root panel
294 RootPanel().add(grid)
295
296 # kickstart the slider handle (see above concerning a
297 # potential bug)
298 randomcolor.initialize()
299
300 def onModuleLoad():
301 timerdemo()
302
303 if __name__ == '__main__':
304
305 pyjd.setup("public/timerdemo.html")
306 onModuleLoad()
307 pyjd.run()
Something went wrong with that request. Please try again.