3 # 'clock' -- A simple alarm clock
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.
18 from stdwinevents
import WE_MOUSE_DOWN
, WE_MOUSE_MOVE
, WE_MOUSE_UP
, \
19 WE_TIMER
, WE_DRAW
, WE_SIZE
, WE_CLOSE
, WE_ACTIVATE
22 from math
import sin
, cos
, atan2
, pi
, sqrt
24 DEFWIDTH
, DEFHEIGHT
= 200, 200
26 MOUSE_EVENTS
= (WE_MOUSE_DOWN
, WE_MOUSE_MOVE
, WE_MOUSE_UP
)
29 EVERYWHERE
= ORIGIN
, FARAWAY
38 stdwin
.setdefwinsize(DEFWIDTH
, DEFHEIGHT
+ stdwin
.lineheight())
39 win
= stdwin
.open('clock')
41 win
.set = 1 # True when alarm is set
42 win
.time
= 11*60 + 40 # Time when alarm must go off
43 win
.ring
= 0 # True when alarm is ringing
44 win
.dispatch
= cdispatch
45 mainloop
.register(win
)
50 type, win
, detail
= event
53 elif type == WE_TIMER
:
55 drawproc(win
, EVERYWHERE
)
56 elif type in MOUSE_EVENTS
:
57 mouseclick(win
, type, detail
)
58 elif type == WE_ACTIVATE
:
60 # Turn the ringing off
62 win
.begindrawing().invert(win
.mainarea
)
64 win
.change(EVERYWHERE
)
66 elif type == WE_CLOSE
:
67 mainloop
.unregister(win
)
70 def setdimensions(win
):
71 width
, height
= win
.getwinsize()
72 height
= height
- stdwin
.lineheight()
73 if width
< height
: size
= width
77 win
.center
= halfwidth
, halfheight
78 win
.radius
= size
*45/100
81 win
.corner
= width
, height
82 win
.mainarea
= ORIGIN
, win
.corner
83 win
.lineheight
= stdwin
.lineheight()
84 win
.farcorner
= width
, height
+ win
.lineheight
85 win
.statusarea
= (0, height
), win
.farcorner
86 win
.fullarea
= ORIGIN
, win
.farcorner
90 hours
, minutes
, seconds
= win
.times
= calctime(now
)
92 win
.settimer(10 * delay
)
93 minutes
= minutes
+ hours
*60
95 # Is it time to stop the alarm ringing?
96 since
= (minutes
- win
.time
+ 720) % 720
101 # Ring again, once every minute
103 elif win
.set and minutes
== win
.time
:
104 # Start the alarm ringing
108 def drawproc(win
, area
):
109 hours
, minutes
, seconds
= win
.times
110 d
= win
.begindrawing()
113 d
.circle(win
.center
, win
.radius
)
114 d
.line(win
.center
, calcpoint(win
, hours
*30 + minutes
/2, 0.6))
115 d
.line(win
.center
, calcpoint(win
, minutes
*6, 1.0))
116 str = "%02d:%02d" % (hours
, minutes
)
117 p
= (win
.width
- d
.textwidth(str))/2, win
.height
* 3 / 4
121 drawalarmtime(win
, d
)
123 d
.invert(win
.mainarea
)
125 def mouseclick(win
, type, detail
):
126 d
= win
.begindrawing()
128 # First turn the ringing off
130 d
.invert(win
.mainarea
)
134 dist
= sqrt(x
*x
+ y
*y
) / float(win
.radius
)
138 erasealarmtime(win
, d
)
144 drawalarmtime(win
, d
)
146 # Convert to half-degrees (range 0..720)
148 hdeg
= alpha
*360.0/pi
150 hdeg
= (hdeg
+ 720.0) % 720.0
151 atime
= 5*int(hdeg
/5.0 + 0.5)
152 if atime
<> win
.time
or not win
.set:
155 erasealarmtime(win
, d
)
159 drawalarmtime(win
, d
)
161 def drawalarm(win
, d
):
162 p1
= calcpoint(win
, float(win
.time
)/2.0, 1.02)
163 p2
= calcpoint(win
, float(win
.time
)/2.0 - 4.0, 1.1)
164 p3
= calcpoint(win
, float(win
.time
)/2.0 + 4.0, 1.1)
169 def erasealarmtime(win
, d
):
170 d
.erase(win
.statusarea
)
172 def drawalarmtime(win
, d
):
173 # win.time is in the range 0..720 with origin at 12 o'clock
174 # Convert to hours (0..12) and minutes (12*(0..60))
177 str = 'Alarm@%02d:%02d' % (hh
, mm
)
178 p1
= (win
.width
- d
.textwidth(str))/2, win
.height
181 def calcpoint(win
, degrees
, size
):
182 alpha
= pi
/2.0 - float(degrees
) * pi
/180.0
183 x
, y
= cos(alpha
), sin(alpha
)
185 r
= float(win
.radius
)
186 return h
+ int(x
*size
*r
), v
- int(y
*size
*r
)
189 hours
, minutes
, seconds
= time
.localtime(now
)[3:6]
191 return hours
, minutes
, seconds