home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Demo / stdwin / clock.py next >
Text File  |  1993-01-13  |  5KB  |  205 lines

  1. #! /usr/local/bin/python
  2.  
  3. # 'clock' -- A simple alarm clock
  4.  
  5. # The alarm can be set at 5 minute intervals on a 12 hour basis.
  6. # It is controlled with the mouse:
  7. # - Click and drag around the circle to set the alarm.
  8. # - Click far outside the circle to clear the alarm.
  9. # - Click near the center to set the alarm at the last time set.
  10. # The alarm time is indicated by a small triangle just outside the circle,
  11. # and also by a digital time at the bottom.
  12. # The indicators disappear when the alarm is not set.
  13. # When the alarm goes off, it beeps every minute for five minutes,
  14. # and the clock turns into inverse video.
  15. # Click or activate the window to turn the ringing off.
  16.  
  17. import stdwin
  18. from stdwinevents import WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP, \
  19.     WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE
  20. import mainloop
  21. import time
  22. from math import sin, cos, atan2, pi, sqrt
  23.  
  24. DEFWIDTH, DEFHEIGHT = 200, 200
  25.  
  26. MOUSE_EVENTS = (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP)
  27. ORIGIN = 0, 0
  28. FARAWAY = 2000, 2000
  29. EVERYWHERE = ORIGIN, FARAWAY
  30.  
  31. # TZDIFF = 5*3600    # THINK C 3.0 returns UCT if local time is EST
  32. TZDIFF = 0        # THINK C 4.0 always returns local time
  33.  
  34.  
  35. def main():
  36.     win = makewindow()
  37.     del win
  38.     mainloop.mainloop()
  39.  
  40. def makewindow():
  41.     stdwin.setdefwinsize(DEFWIDTH, DEFHEIGHT + stdwin.lineheight())
  42.     win = stdwin.open('clock')
  43.     setdimensions(win)
  44.     win.set = 1        # True when alarm is set
  45.     win.time = 11*60 + 40    # Time when alarm must go off
  46.     win.ring = 0        # True when alarm is ringing
  47.     win.dispatch = cdispatch
  48.     mainloop.register(win)
  49.     settimer(win)
  50.     return win
  51.  
  52. def cdispatch(event):
  53.     type, win, detail = event
  54.     if type == WE_DRAW:
  55.         drawproc(win, detail)
  56.     elif type == WE_TIMER:
  57.         settimer(win)
  58.         drawproc(win, EVERYWHERE)
  59.     elif type in MOUSE_EVENTS:
  60.         mouseclick(win, type, detail)
  61.     elif type == WE_ACTIVATE:
  62.         if win.ring:
  63.             # Turn the ringing off
  64.             win.ring = 0
  65.             win.begindrawing().invert(win.mainarea)
  66.     elif type == WE_SIZE:
  67.         win.change(EVERYWHERE)
  68.         setdimensions(win)
  69.     elif type == WE_CLOSE:
  70.         mainloop.unregister(win)
  71.         win.close()
  72.  
  73. def setdimensions(win):
  74.     width, height = win.getwinsize()
  75.     height = height - stdwin.lineheight()
  76.     if width < height: size = width
  77.     else: size = height
  78.     halfwidth = width/2
  79.     halfheight = height/2
  80.     win.center = halfwidth, halfheight
  81.     win.radius = size*45/100
  82.     win.width = width
  83.     win.height = height
  84.     win.corner = width, height
  85.     win.mainarea = ORIGIN, win.corner
  86.     win.lineheight = stdwin.lineheight()
  87.     win.farcorner = width, height + win.lineheight
  88.     win.statusarea = (0, height), win.farcorner
  89.     win.fullarea = ORIGIN, win.farcorner
  90.  
  91. def settimer(win):
  92.     now = getlocaltime()
  93.     win.times = calctime(now)
  94.     delay = 61 - now % 60
  95.     win.settimer(10 * delay)
  96.     minutes = (now/60) % 720
  97.     if win.ring:
  98.         # Is it time to stop the alarm ringing?
  99.         since = (minutes - win.time + 720) % 720
  100.         if since >= 5:
  101.             # Stop it now
  102.             win.ring = 0
  103.         else:
  104.             # Ring again, once every minute
  105.             stdwin.fleep()
  106.     elif win.set and minutes == win.time:
  107.         # Start the alarm ringing
  108.         win.ring = 1
  109.         stdwin.fleep()
  110.  
  111. def drawproc(win, area):
  112.     hours, minutes, seconds = win.times
  113.     d = win.begindrawing()
  114.     d.cliprect(area)
  115.     d.erase(EVERYWHERE)
  116.     d.circle(win.center, win.radius)
  117.     d.line(win.center, calcpoint(win, hours*30 + minutes/2, 0.6))
  118.     d.line(win.center, calcpoint(win, minutes*6, 1.0))
  119.     str = dd(hours) + ':' + dd(minutes)
  120.     p = (win.width - d.textwidth(str))/2, win.height * 3 / 4
  121.     d.text(p, str)
  122.     if win.set:
  123.         drawalarm(win, d)
  124.         drawalarmtime(win, d)
  125.     if win.ring:
  126.         d.invert(win.mainarea)
  127.  
  128. def mouseclick(win, type, detail):
  129.     d = win.begindrawing()
  130.     if win.ring:
  131.         # First turn the ringing off
  132.         win.ring = 0
  133.         d.invert(win.mainarea)
  134.     h, v = detail[0]
  135.     ch, cv = win.center
  136.     x, y = h-ch, cv-v
  137.     dist = sqrt(x*x + y*y) / float(win.radius)
  138.     if dist > 1.2:
  139.         if win.set:
  140.             drawalarm(win, d)
  141.             erasealarmtime(win, d)
  142.             win.set = 0
  143.     elif dist < 0.8:
  144.         if not win.set:
  145.             win.set = 1
  146.             drawalarm(win, d)
  147.             drawalarmtime(win, d)
  148.     else:
  149.         # Convert to half-degrees (range 0..720)
  150.         alpha = atan2(y, x)
  151.         hdeg = alpha*360.0/pi
  152.         hdeg = 180.0 - hdeg
  153.         hdeg = (hdeg + 720.0) % 720.0
  154.         atime = 5*int(hdeg/5.0 + 0.5)
  155.         if atime <> win.time or not win.set:
  156.             if win.set:
  157.                 drawalarm(win, d)
  158.                 erasealarmtime(win, d)
  159.             win.set = 1
  160.             win.time = atime
  161.             drawalarm(win, d)
  162.             drawalarmtime(win, d)
  163.  
  164. def drawalarm(win, d):
  165.     p1 = calcpoint(win, float(win.time)/2.0, 1.02)
  166.     p2 = calcpoint(win, float(win.time)/2.0 - 4.0, 1.1)
  167.     p3 = calcpoint(win, float(win.time)/2.0 + 4.0, 1.1)
  168.     d.xorline(p1, p2)
  169.     d.xorline(p2, p3)
  170.     d.xorline(p3, p1)
  171.  
  172. def erasealarmtime(win, d):
  173.     d.erase(win.statusarea)
  174.  
  175. def drawalarmtime(win, d):
  176.     # win.time is in the range 0..720 with origin at 12 o'clock
  177.     # Convert to hours (0..12) and minutes (12*(0..60))
  178.     hh = win.time/60
  179.     mm = win.time%60
  180.     str = 'Alarm@' + dd(hh) + ':' + dd(mm)
  181.     p1 = (win.width - d.textwidth(str))/2, win.height
  182.     d.text(p1, str)
  183.  
  184. def calcpoint(win, degrees, size):
  185.     alpha = pi/2.0 - float(degrees) * pi/180.0
  186.     x, y = cos(alpha), sin(alpha)
  187.     h, v = win.center
  188.     r = float(win.radius)
  189.     return h + int(x*size*r), v - int(y*size*r)
  190.  
  191. def calctime(now):
  192.     seconds = now % 60
  193.     minutes = (now/60) % 60
  194.     hours = (now/3600) % 12
  195.     return hours, minutes, seconds
  196.  
  197. def dd(n):
  198.     s = `n`
  199.     return '0'*(2-len(s)) + s
  200.  
  201. def getlocaltime():
  202.     return int(time.time() - TZDIFF)
  203.  
  204. main()
  205.