blob: 6af01ba991ba63c21d28fdd4781aa52773605364 [file] [log] [blame]
Guido van Rossumf06ee5f1996-11-27 19:52:01 +00001#! /usr/bin/env python
Guido van Rossum453bd401992-03-30 13:18:37 +00002
3# "M Clock"
4#
5# An implementation in software of an original design by Rob Juda.
6# Clock implementation: Guido van Rossum.
7# Alarm and Gong features: Sape Mullender.
8#
9# XXX TO DO:
10# add arguments to specify initial window position and size
11# find out local time zone difference automatically
12# add a date indicator
13# allow multiple alarms
14# allow the menu to change more parameters
15
16import sys
17
18from gl import *
19from GL import *
20from DEVICE import *
21import time
22import getopt
23import string
24import os
25from math import pi
26import math
27
28FULLC = 3600 # Full circle in 1/10-ths of a degree
29MIDN = 900 # Angle of the 12 o'clock position
30R, G, B = 0, 1, 2 # Indices of colors in RGB list
31
32HOUR = 3600 # Number of seconds per hour
33MINUTE = 60 # Number of seconds per minute
34
35class struct: pass # Class to define featureless structures
36Gl = struct() # Object to hold writable global variables
37
38# Default constants (used in multiple places)
39
40SCREENBG = 127, 156, 191
41NPARTS = 9
42TITLE = 'M Clock'
Guido van Rossum05e46dd1992-12-14 13:00:14 +000043
Guido van Rossum96b608c1993-12-17 14:57:24 +000044# Set timezone, check for daylight saving time
45TZDIFF = time.timezone
46if time.localtime(time.time())[-1]:
47 TZDIFF = time.altzone
Guido van Rossum453bd401992-03-30 13:18:37 +000048
49# Default parameters
50
51Gl.foreground = 0 # If set, run in the foreground
52Gl.fullscreen = 0 # If set, run on full screen
53Gl.tzdiff = TZDIFF # Seconds west of Greenwich (winter time)
54Gl.nparts = NPARTS # Number of parts each circle is divided in (>= 2)
55Gl.debug = 0 # If set, print debug output
56Gl.doublebuffer = 1 # If set, use double buffering
57Gl.update = 0 # Update interval; seconds hand is suppressed if > 1
58Gl.colorsubset = 0 # If set, display only a subset of the colors
59Gl.cyan = 0 # If set, display cyan overlay (big hand)
60Gl.magenta = 0 # If set, display magenta overlay (little hand)
61Gl.yellow = 0 # If set, display yellow overlay (fixed background)
62Gl.black = 0 # If set, display black overlay (hands)
63Gl.colormap = 0 # If set, use colormap mode instead of RGB mode
64Gl.warnings = 0 # If set, print warnings
65Gl.title = '' # Window title (default set later)
66Gl.name = 'mclock' # Window title for resources
67Gl.border = 1 # If set, use a window border (and title)
68Gl.bg = 0, 0, 0 # Background color R, G, B value
69Gl.iconic = 0 # Set in iconic state
70Gl.fg = 255, 0, 0 # Alarm background RGB (either normal or alarm)
71Gl.ox,Gl.oy = 0,0 # Window origin
72Gl.cx,Gl.cy = 0,0 # Window size
73Gl.alarm_set = 0 # Alarm on or off
74Gl.alarm_on = 0 # Alarm is ringing
75Gl.alarm_time = 0 # Alarm time in seconds after midnight
76Gl.alarm_hours = 0 # Alarm hour setting, 24 hour clock
77Gl.alarm_minutes = 0 # Alarm minutes setting
78Gl.alarm_rgb = 0,0,0 # Alarm display RGB colors
79Gl.alarm_cmd = '' # Command to execute when alarm goes off
80Gl.mouse2down = 0 # Mouse button state
81Gl.mouse3down = 0 # Mouse button state
82Gl.gong_cmd = '' # Command to execute when chimes go off
83Gl.gong_int = 3600 # Gong interval
84Gl.indices = R, G, B # Colors (permuted when alarm is on)
85
86def main():
87 #
88 sys.stdout = sys.stderr # All output is errors/warnings etc.
89 #
90 try:
91 args = getoptions()
92 except string.atoi_error, value:
93 usage(string.atoi_error, value)
94 except getopt.error, msg:
95 usage(getopt.error, msg)
96 #
97 if args:
98 realtime = 0
99 hours = string.atoi(args[0])
100 minutes = seconds = 0
101 if args[1:]: minutes = string.atoi(args[1])
102 if args[2:]: seconds = string.atoi(args[2])
103 localtime = ((hours*60)+minutes)*60+seconds
104 else:
105 realtime = 1
106 #
107 if Gl.title == '':
108 if realtime:
109 Gl.title = TITLE
110 else:
111 title = ''
112 for arg in args: title = title + ' ' + arg
113 Gl.title = title[1:]
114 del title
115 #
116 wid = makewindow()
117 Gl.ox,Gl.oy = getorigin()
118 Gl.cx,Gl.cy = getsize()
119 initmenu()
120 clearall()
121 #
122 if not Gl.update:
123 Gl.update = 60
124 #
125 if Gl.update <= 1:
126 Gl.timernoise = 6
127 else:
128 Gl.timernoise = 60
129 noise(TIMER0, Gl.timernoise)
130 #
131 qdevice(WINSHUT)
132 qdevice(WINQUIT)
133 qdevice(ESCKEY)
134 if realtime:
135 qdevice(TIMER0)
136 qdevice(REDRAW)
137 qdevice(WINFREEZE)
138 qdevice(WINTHAW)
139 qdevice(MENUBUTTON) # MOUSE1
140 qdevice(MOUSE3) # Left button
141 qdevice(MOUSE2) # Middle button
142 unqdevice(INPUTCHANGE)
143 #
144 lasttime = 0
145 Gl.change = 1
146 while 1:
147 if realtime:
Guido van Rossum96b608c1993-12-17 14:57:24 +0000148 localtime = int(time.time() - Gl.tzdiff)
Guido van Rossum453bd401992-03-30 13:18:37 +0000149 if Gl.alarm_set:
150 if localtime%(24*HOUR) == Gl.alarm_time:
151 # Ring the alarm!
152 if Gl.debug:
153 print 'Rrrringg!'
154 Gl.alarm_on = 1
155 if Gl.alarm_cmd <> '':
156 d = os.system(Gl.alarm_cmd+' '+`Gl.alarm_time/3600`+' '+`(Gl.alarm_time/60)%60` + ' &')
157 Gl.change = 1
158 clearall()
159 if Gl.alarm_on:
160 if (localtime - Gl.alarm_time) % (24*HOUR) > 300:
161 # More than 5 minutes away from alarm
162 Gl.alarm_on = 0
163 if Gl.debug:
164 print 'Alarm turned off'
165 Gl.change = 1
166 clearall()
167 Gl.indices = R, G, B
168 else:
169 if localtime % 2 == 0:
170 # Permute color indices
171 Gl.indices = Gl.indices[2:] + Gl.indices[:2]
172 Gl.change = 1
173 if Gl.gong_cmd <> '' and localtime%Gl.gong_int == 0:
174 d = os.system(Gl.gong_cmd+' '+`(localtime/3600)%24`+' '+`(localtime/60)%60` + ' &')
175 if localtime/Gl.update <> lasttime/Gl.update:
176 if Gl.debug: print 'new time'
177 Gl.change = 1
178 if Gl.change:
179 if Gl.debug: print 'drawing'
180 doit(localtime)
181 lasttime = localtime
182 Gl.change = 0
183 dev, data = qread()
184 if Gl.debug and dev <> TIMER0:
185 print dev, data
186 if dev == TIMER0:
187 if Gl.debug > 1:
188 print dev, data
189 elif dev == MOUSE3:
190 mousex = getvaluator(MOUSEX)
191 mousey = getvaluator(MOUSEY)
192 if mouseclick(3, data, mousex, mousey):
193 Gl.change = 1
194 elif dev == MOUSE2:
195 mousex = getvaluator(MOUSEX)
196 mousey = getvaluator(MOUSEY)
197 if mouseclick(2, data, mousex, mousey):
198 Gl.change = 1
199 elif dev == MOUSEX:
200 mousex = data
201 if Gl.mouse2down:
202 mouse2track(mousex, mousey)
203 if Gl.mouse3down:
204 mouse3track(mousex, mousey)
205 elif dev == MOUSEY:
206 mousey = data
207 if Gl.mouse2down:
208 mouse2track(mousex, mousey)
209 if Gl.mouse3down:
210 mouse3track(mousex, mousey)
211 elif dev == REDRAW or dev == REDRAWICONIC:
212 if Gl.debug:
213 if dev == REDRAW: print 'REDRAW'
214 else: print 'REDRAWICONIC'
215 reshapeviewport()
216 Gl.ox,Gl.oy = getorigin()
217 Gl.cx,Gl.cy = getsize()
218 Gl.change = 1
219 clearall()
220 elif dev == MENUBUTTON:
221 if Gl.debug: print 'MENUBUTTON'
222 handlemenu()
223 elif dev == WINFREEZE:
224 if Gl.debug: print 'WINFREEZE'
225 Gl.iconic = 1
226 noise(TIMER0, 60*60) # Redraw every 60 seconds only
227 elif dev == WINTHAW:
228 if Gl.debug: print 'WINTHAW'
229 Gl.iconic = 0
230 noise(TIMER0, Gl.timernoise)
231 Gl.change = 1
232 elif dev == ESCKEY or dev == WINSHUT or dev == WINQUIT:
233 if Gl.debug: print 'Exit'
234 sys.exit(0)
235
236def getoptions():
237 optlist, args = getopt.getopt(sys.argv[1:], 'A:a:B:bc:dFfG:g:n:sT:t:u:wCMYK')
238 for optname, optarg in optlist:
239 if optname == '-A':
240 Gl.fg = eval(optarg) # Should be (r,g,b)
241 elif optname == '-a':
242 Gl.alarm_cmd = optarg
243 elif optname == '-B':
244 Gl.bg = eval(optarg) # Should be (r,g,b)
245 elif optname == '-b':
246 Gl.border = 0
247 elif optname == '-c':
248 Gl.colormap = string.atoi(optarg)
249 elif optname == '-d':
250 Gl.debug = Gl.debug + 1
251 Gl.warnings = 1
252 elif optname == '-F':
253 Gl.foreground = 1
254 elif optname == '-f':
255 Gl.fullscreen = 1
256 elif optname == '-G':
257 Gl.gong_int = 60*string.atoi(optarg)
258 elif optname == '-g':
259 Gl.gong_cmd = optarg
260 elif optname == '-n':
261 Gl.nparts = string.atoi(optarg)
262 elif optname == '-s':
263 Gl.doublebuffer = 0
264 elif optname == '-T':
265 Gl.title = Gl.name = optarg
266 elif optname == '-t':
267 Gl.tzdiff = string.atoi(optarg)
268 elif optname == '-u':
269 Gl.update = string.atoi(optarg)
270 elif optname == '-w':
271 Gl.warnings = 1
272 elif optname == '-C':
273 Gl.cyan = Gl.colorsubset = 1
274 elif optname == '-M':
275 Gl.magenta = Gl.colorsubset = 1
276 elif optname == '-Y':
277 Gl.yellow = Gl.colorsubset = 1
278 elif optname == '-K':
279 Gl.black = Gl.colorsubset = 1
280 else:
281 print 'Unsupported option', optname
282 return args
283
284def usage(exc, msg):
285 if sys.argv:
286 progname = os.path.basename(sys.argv[0])
287 else:
288 progname = 'mclock'
289 #
290 print progname + ':',
291 if exc == string.atoi_error:
292 print 'non-numeric argument:',
293 print msg
294 #
295 print 'usage:', progname, '[options] [hh [mm [ss]]]'
296 #
297 print '-A r,g,b : alarm background red,green,blue [255,0,0]'
298 print '-a cmd : shell command executed when alarm goes off'
299 print '-B r,g,b : background red,green,blue [0,0,0]'
300 print ' (-B SCREENBG uses the default screen background)'
301 print '-b : suppress window border and title'
302 print '-c cmapid : select explicit colormap'
303 print '-d : more debug output (implies -F, -w)'
304 print '-F : run in foreground'
305 print '-f : use full screen'
306 print '-G intrvl : interval between chimes in minutes [60]'
307 print '-g cmd : shell command executed when chimes go off'
308 print '-s : single buffer mode'
309 print '-w : print various warnings'
310 print '-n nparts : number of parts [' + `NPARTS` + ']'
311 print '-T title : alternate window title [\'' + TITLE + '\']'
312 print '-t tzdiff : time zone difference [' + `TZDIFF` + ']'
313 print '-u update : update interval [60]'
314 print '-CMYK : Cyan, Magenta, Yellow or blacK overlay only'
315 print 'if hh [mm [ss]] is specified, display that time statically'
Guido van Rossum96b608c1993-12-17 14:57:24 +0000316 print 'on machines with < 12 bitplanes, -s is forced on'
Guido van Rossum453bd401992-03-30 13:18:37 +0000317 #
318 sys.exit(2)
319
320def doit(localtime):
321 hands = makehands(localtime)
322 list = makelist(hands)
323 render(list, hands)
324
325def makehands(localtime):
326 localtime = localtime % (12*HOUR)
327 seconds_hand = MIDN + FULLC - (localtime*60) % FULLC
328 big_hand = (MIDN + FULLC - (localtime%HOUR)) % FULLC
329 little_hand = (MIDN + FULLC - ((localtime/12) % HOUR)) % FULLC
330 return little_hand, big_hand, seconds_hand
331
Guido van Rossum96b608c1993-12-17 14:57:24 +0000332def makelist(hands):
333 little_hand, big_hand, seconds_hand = hands
Guido van Rossum453bd401992-03-30 13:18:37 +0000334 total = []
335 if Gl.cyan or not Gl.colorsubset:
336 total = total + makesublist(big_hand, Gl.indices[0])
337 if Gl.magenta or not Gl.colorsubset:
338 total = total + makesublist(little_hand, Gl.indices[1])
339 if Gl.yellow or not Gl.colorsubset:
340 total = total + makesublist(MIDN, Gl.indices[2])
341 total.sort()
342 return total
343
344def makesublist(first, icolor):
345 list = []
346 alpha = FULLC/Gl.nparts
347 a = first - alpha/2
348 for i in range(Gl.nparts):
349 angle = (a + i*alpha + FULLC) % FULLC
350 value = 255*(Gl.nparts-1-i)/(Gl.nparts-1)
Guido van Rossum9c2c1e81998-10-08 15:24:48 +0000351 list.append((angle, icolor, value))
Guido van Rossum453bd401992-03-30 13:18:37 +0000352 list.sort()
353 a, icolor, value = list[0]
354 if a <> 0:
355 a, icolor, value = list[len(list)-1]
356 t = 0, icolor, value
357 list.insert(0, t)
358 return list
359
360def rgb_fg():
361 return Gl.fg
362 # Obsolete code:
363 if Gl.alarm_on:
364 return Gl.bg
365 else:
366 return Gl.fg
367
368def rgb_bg():
369 return Gl.bg
370 # Obsolete code:
371 if Gl.alarm_on:
372 return Gl.fg
373 else:
374 return Gl.bg
375
376def clearall():
377 Gl.c3i(rgb_bg())
378 clear()
379 if Gl.doublebuffer:
380 swapbuffers()
381 clear()
382
383def draw_alarm(color):
384 frontbuffer(TRUE)
385 Gl.c3i(color)
386 pushmatrix()
387 rotate(-((Gl.alarm_time/12)%3600), 'z')
388 bgnpolygon()
389 v2f( 0.00,1.00)
390 v2f( 0.04,1.05)
391 v2f(-0.04,1.05)
392 endpolygon()
393 popmatrix()
394 #
395 pushmatrix()
396 rotate(-((Gl.alarm_time)%3600), 'z')
397 bgnpolygon()
398 v2f( 0.00,1.05)
399 v2f( 0.07,1.10)
400 v2f(-0.07,1.10)
401 endpolygon()
402 popmatrix()
403 #
404 cmov2(-1.06, -1.06)
405 charstr(string.rjust(`Gl.alarm_time/3600`,2))
406 charstr(':')
407 charstr(string.zfill((Gl.alarm_time/60)%60,2))
408 frontbuffer(FALSE)
409
410def render(list, (little_hand, big_hand, seconds_hand)):
411 #
412 if Gl.colormap:
413 resetindex()
414 #
415 if not list:
Guido van Rossum05e46dd1992-12-14 13:00:14 +0000416 Gl.c3i((255, 255, 255)) # White
Guido van Rossum453bd401992-03-30 13:18:37 +0000417 circf(0.0, 0.0, 1.0)
418 else:
Guido van Rossum9c2c1e81998-10-08 15:24:48 +0000419 list.append((3600, 0, 255)) # Sentinel
Guido van Rossum453bd401992-03-30 13:18:37 +0000420 #
421 rgb = [255, 255, 255]
422 a_prev = 0
423 for a, icolor, value in list:
424 if a <> a_prev:
425 [r, g, b] = rgb
426 if Gl.debug > 1:
427 print rgb, a_prev, a
Guido van Rossum05e46dd1992-12-14 13:00:14 +0000428 Gl.c3i((r, g, b))
Guido van Rossum453bd401992-03-30 13:18:37 +0000429 arcf(0.0, 0.0, 1.0, a_prev, a)
430 rgb[icolor] = value
431 a_prev = a
432 #
433 if Gl.black or not Gl.colorsubset:
434 #
435 # Draw the hands -- in black
436 #
Guido van Rossum05e46dd1992-12-14 13:00:14 +0000437 Gl.c3i((0, 0, 0))
Guido van Rossum453bd401992-03-30 13:18:37 +0000438 #
439 if Gl.update == 1 and not Gl.iconic:
440 # Seconds hand is only drawn if we update every second
441 pushmatrix()
442 rotate(seconds_hand, 'z')
443 bgnline()
444 v2f(0.0, 0.0)
445 v2f(1.0, 0.0)
446 endline()
447 popmatrix()
448 #
449 pushmatrix()
450 rotate(big_hand, 'z')
451 rectf(0.0, -0.01, 0.97, 0.01)
452 circf(0.0, 0.0, 0.01)
453 circf(0.97, 0.0, 0.01)
454 popmatrix()
455 #
456 pushmatrix()
457 rotate(little_hand, 'z')
458 rectf(0.04, -0.02, 0.63, 0.02)
459 circf(0.04, 0.0, 0.02)
460 circf(0.63, 0.0, 0.02)
461 popmatrix()
462 #
463 # Draw the alarm time, if set or being set
464 #
465 if Gl.alarm_set:
466 draw_alarm(rgb_fg())
467 #
468 if Gl.doublebuffer: swapbuffers()
469
470def makewindow():
471 #
472 if Gl.debug or Gl.foreground:
473 foreground()
474 #
475 if Gl.fullscreen:
476 scrwidth, scrheight = getgdesc(GD_XPMAX), getgdesc(GD_YPMAX)
477 prefposition(0, scrwidth-1, 0, scrheight-1)
478 else:
479 keepaspect(1, 1)
Guido van Rossum96b608c1993-12-17 14:57:24 +0000480 prefsize(80, 80)
Guido van Rossum453bd401992-03-30 13:18:37 +0000481 #
482 if not Gl.border:
483 noborder()
484 wid = winopen(Gl.name)
485 wintitle(Gl.title)
486 #
487 if not Gl.fullscreen:
488 keepaspect(1, 1)
489 minsize(10, 10)
490 maxsize(2000, 2000)
491 iconsize(66, 66)
492 winconstraints()
493 #
494 nplanes = getplanes()
495 nmaps = getgdesc(GD_NMMAPS)
496 if Gl.warnings:
497 print nplanes, 'color planes,', nmaps, 'color maps'
498 #
Guido van Rossum96b608c1993-12-17 14:57:24 +0000499 if Gl.doublebuffer and not Gl.colormap and nplanes < 12:
500 if Gl.warnings: print 'forcing single buffer mode'
501 Gl.doublebuffer = 0
502 #
503 if Gl.colormap:
Guido van Rossum453bd401992-03-30 13:18:37 +0000504 if not Gl.colormap:
505 Gl.colormap = nmaps - 1
506 if Gl.warnings:
507 print 'not enough color planes available',
508 print 'for RGB mode; forcing colormap mode'
509 print 'using color map number', Gl.colormap
510 if not Gl.colorsubset:
511 needed = 3
512 else:
513 needed = Gl.cyan + Gl.magenta + Gl.yellow
514 needed = needed*Gl.nparts
515 if Gl.bg <> (0, 0, 0):
516 needed = needed+1
517 if Gl.fg <> (0, 0, 0):
518 needed = needed+1
519 if Gl.doublebuffer:
520 if needed > available(nplanes/2):
521 Gl.doublebuffer = 0
522 if Gl.warnings:
523 print 'not enough colors available',
524 print 'for double buffer mode;',
525 print 'forcing single buffer mode'
526 else:
527 nplanes = nplanes/2
528 if needed > available(nplanes):
529 # Do this warning always
530 print 'still not enough colors available;',
531 print 'parts will be left white'
532 print '(needed', needed, 'but have only',
533 print available(nplanes), 'colors available)'
534 #
535 if Gl.doublebuffer:
536 doublebuffer()
537 gconfig()
538 #
539 if Gl.colormap:
540 Gl.c3i = pseudo_c3i
541 fixcolormap()
542 else:
543 Gl.c3i = c3i
544 RGBmode()
545 gconfig()
546 #
547 if Gl.fullscreen:
548 # XXX Should find out true screen size using getgdesc()
549 ortho2(-1.1*1.280, 1.1*1.280, -1.1*1.024, 1.1*1.024)
550 else:
551 ortho2(-1.1, 1.1, -1.1, 1.1)
552 #
553 return wid
554
555def available(nplanes):
556 return pow(2, nplanes) - 1 # Reserve one pixel for black
557
558def fixcolormap():
559 multimap()
560 gconfig()
561 nplanes = getplanes()
562 if Gl.warnings:
563 print 'multimap mode has', nplanes, 'color planes'
564 imap = Gl.colormap
565 Gl.startindex = pow(2, nplanes) - 1
566 Gl.stopindex = 1
567 setmap(imap)
568 mapcolor(0, 0, 0, 0) # Fixed entry for black
569 if Gl.bg <> (0, 0, 0):
570 r, g, b = Gl.bg
571 mapcolor(1, r, g, b) # Fixed entry for Gl.bg
572 Gl.stopindex = 2
573 if Gl.fg <> (0, 0, 0):
574 r, g, b = Gl.fg
575 mapcolor(2, r, g, b) # Fixed entry for Gl.fg
576 Gl.stopindex = 3
577 Gl.overflow_seen = 0
578 resetindex()
579
580def resetindex():
581 Gl.index = Gl.startindex
582
583r0g0b0 = (0, 0, 0)
584
585def pseudo_c3i(rgb):
586 if rgb == r0g0b0:
587 index = 0
588 elif rgb == Gl.bg:
589 index = 1
590 elif rgb == Gl.fg:
591 index = 2
592 else:
593 index = definecolor(rgb)
594 color(index)
595
596def definecolor(rgb):
597 index = Gl.index
598 if index < Gl.stopindex:
599 if Gl.debug: print 'definecolor hard case', rgb
600 # First see if we already have this one...
601 for index in range(Gl.stopindex, Gl.startindex+1):
602 if rgb == getmcolor(index):
603 if Gl.debug: print 'return', index
604 return index
605 # Don't clobber reserverd colormap entries
606 if not Gl.overflow_seen:
607 # Shouldn't happen any more, hence no Gl.warnings test
608 print 'mclock: out of colormap entries'
609 Gl.overflow_seen = 1
610 return Gl.stopindex
611 r, g, b = rgb
612 if Gl.debug > 1: print 'mapcolor', (index, r, g, b)
613 mapcolor(index, r, g, b)
614 Gl.index = index - 1
615 return index
616
617# Compute n**i
618def pow(n, i):
619 x = 1
620 for j in range(i): x = x*n
621 return x
622
623def mouseclick(mouse, updown, x, y):
624 if updown == 1:
625 # mouse button came down, start tracking
626 if Gl.debug:
627 print 'mouse', mouse, 'down at', x, y
628 if mouse == 2:
629 Gl.mouse2down = 1
630 mouse2track(x, y)
631 elif mouse == 3:
632 Gl.mouse3down = 1
633 mouse3track(x, y)
634 else:
635 print 'fatal error'
636 qdevice(MOUSEX)
637 qdevice(MOUSEY)
638 return 0
639 else:
640 # mouse button came up, stop tracking
641 if Gl.debug:
642 print 'mouse', mouse, 'up at', x, y
643 unqdevice(MOUSEX)
644 unqdevice(MOUSEY)
645 if mouse == 2:
646 mouse2track(x, y)
647 Gl.mouse2down = 0
648 elif mouse == 3:
649 mouse3track(x, y)
650 Gl.mouse3down = 0
651 else:
652 print 'fatal error'
653 Gl.alarm_set = 1
654 return 1
655
656def mouse3track(x, y):
657 # first compute polar coordinates from x and y
658 cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
659 x, y = x - cx, y - cy
660 if (x, y) == (0, 0): return # would cause an exception
661 minutes = int(30.5 + 30.0*math.atan2(float(-x), float(-y))/pi)
662 if minutes == 60: minutes = 0
663 a,b = Gl.alarm_minutes/15, minutes/15
664 if (a,b) == (0,3):
665 # Moved backward through 12 o'clock:
666 Gl.alarm_hours = Gl.alarm_hours - 1
667 if Gl.alarm_hours < 0: Gl.alarm_hours = Gl.alarm_hours + 24
668 if (a,b) == (3,0):
669 # Moved forward through 12 o'clock:
670 Gl.alarm_hours = Gl.alarm_hours + 1
671 if Gl.alarm_hours >= 24: Gl.alarm_hours = Gl.alarm_hours - 24
672 Gl.alarm_minutes = minutes
673 seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
674 if seconds <> Gl.alarm_time:
675 draw_alarm(rgb_bg())
676 Gl.alarm_time = seconds
677 draw_alarm(rgb_fg())
678
679def mouse2track(x, y):
680 # first compute polar coordinates from x and y
681 cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
682 x, y = x - cx, y - cy
683 if (x, y) == (0, 0): return # would cause an exception
684 hours = int(6.5 - float(Gl.alarm_minutes)/60.0 + 6.0*math.atan2(float(-x), float(-y))/pi)
685 if hours == 12: hours = 0
686 if (Gl.alarm_hours,hours) == (0,11):
687 # Moved backward through midnight:
688 Gl.alarm_hours = 23
689 elif (Gl.alarm_hours,hours) == (12,11):
690 # Moved backward through noon:
691 Gl.alarm_hours = 11
692 elif (Gl.alarm_hours,hours) == (11,0):
693 # Moved forward through noon:
694 Gl.alarm_hours = 12
695 elif (Gl.alarm_hours,hours) == (23,0):
696 # Moved forward through midnight:
697 Gl.alarm_hours = 0
698 elif Gl.alarm_hours < 12:
699 Gl.alarm_hours = hours
700 else:
701 Gl.alarm_hours = hours + 12
702 seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
703 if seconds <> Gl.alarm_time:
704 draw_alarm(rgb_bg())
705 Gl.alarm_time = seconds
706 draw_alarm(rgb_fg())
707
708def initmenu():
709 Gl.pup = pup = newpup()
710 addtopup(pup, 'M Clock%t|Alarm On/Off|Seconds Hand On/Off|Quit', 0)
711
712def handlemenu():
713 item = dopup(Gl.pup)
714 if item == 1:
715 # Toggle alarm
716 if Gl.alarm_set:
717 Gl.alarm_set = 0
718 Gl.alarm_on = 0
719 else:
720 Gl.alarm_set = 1
721 Gl.change = 1
722 clearall()
723 elif item == 2:
724 # Toggle Seconds Hand
725 if Gl.update == 1:
726 Gl.update = 60
727 Gl.timernoise = 60
728 else:
729 Gl.update = 1
730 Gl.timernoise = 6
731 Gl.change = 1
732 elif item == 3:
733 if Gl.debug: print 'Exit'
734 sys.exit(0)
735
736main()