]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/analogclock.py
Ensure the first EVT_SIZE has happened before the first EVT_PAINT
[wxWidgets.git] / wxPython / wx / lib / analogclock.py
1 # -*- coding: iso-8859-1 -*-
2 #----------------------------------------------------------------------
3 # Name: wx.lib.analogclock
4 # Purpose: A simple analog clock window
5 #
6 # Author: several folks on wxPython-users
7 #
8 # Created: 16-April-2003
9 # RCS-ID: $Id$
10 # Copyright: (c) 2003 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------
13 # 11/30/2003 - Jeff Grimmett (grimmtooth@softhome.net)
14 #
15 # o Updated for wx namespace
16 # o Tested with updated demo and with builtin test.
17 #
18 # 15-February-2004 - E. A. Tacao
19 #
20 # o Many ehnacements
21 #
22
23
24 import math
25 import sys
26 import string
27 import time
28
29 import wx
30
31 from analogclockopts import ACCustomizationFrame
32
33
34 # self.clockStyle:
35 SHOW_QUARTERS_TICKS = 1
36 SHOW_HOURS_TICKS = 2
37 SHOW_MINUTES_TICKS = 4
38 ROTATE_TICKS = 8
39 SHOW_HOURS_HAND = 16
40 SHOW_MINUTES_HAND = 32
41 SHOW_SECONDS_HAND = 64
42 SHOW_SHADOWS = 128
43 OVERLAP_TICKS = 256
44
45 # self.tickMarkHoursStyle and self.tickMarkMinutesStyle:
46 TICKS_NONE = 1
47 TICKS_SQUARE = 2
48 TICKS_CIRCLE = 4
49 TICKS_POLY = 8
50 TICKS_DECIMAL = 16
51 TICKS_ROMAN = 32
52
53
54 class AnalogClockWindow(wx.PyWindow):
55 """An analog clock window"""
56
57 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
58 style=0, name="clock"):
59
60 # Initialize the wxWindow...
61 wx.PyWindow.__init__(self, parent, ID, pos, size, style, name)
62
63 # Initialize some variables and defaults...
64 self.clockStep = 1
65 self.prefs_open = False
66
67 self.tickShapeHours = self.tickShapeMinutes= [[0,0],
68 [1,-1],
69 [2,0],
70 [1,4]]
71 self.handHoursThickness = 5
72 self.handHoursColour = (0, 0, 0)
73
74 self.handMinutesThickness = 3
75 self.handMinutesColour = (0, 0, 0)
76
77 self.handSecondsThickness = 1
78 self.handSecondsColour = (0, 0, 0)
79
80 self.tickMarkHoursPen = wx.Pen((0, 0, 0), 1, wx.SOLID)
81 self.tickMarkHoursBrush = wx.Brush((0, 0, 0), wx.SOLID)
82 self.markSizeHour = 10
83 self.tickMarkHoursFont = wx.Font(0, wx.SWISS, wx.NORMAL, wx.BOLD)
84 self.tickMarkHoursFont.SetPointSize(self.markSizeHour)
85
86 self.tickMarkMinutesPen = wx.Pen((0, 0, 0), 1, wx.SOLID)
87 self.tickMarkMinutesBrush = wx.Brush((0, 0, 0), wx.SOLID)
88 self.markSizeMin = 6
89 self.tickMarkMinutesFont = wx.Font(self.markSizeMin, wx.SWISS, wx.NORMAL, wx.BOLD)
90
91 self.offM = 0
92
93 self.shadowPenColour = self.shadowBrushColour = (128,128,128)
94
95 self.watchPen = None
96 self.watchBrush = None
97
98 self.clockStyle = SHOW_HOURS_TICKS | SHOW_MINUTES_TICKS | SHOW_SHADOWS | ROTATE_TICKS
99 self.handsStyle = SHOW_SECONDS_HAND
100
101 self.tickMarkHoursStyle = TICKS_POLY
102 self.tickMarkMinutesStyle = TICKS_CIRCLE
103
104 self.currentTime=None
105
106 size = wx.Size(*size)
107 bestSize = self.GetBestSize()
108 size.x = max(size.x, bestSize.x)
109 size.y = max(size.y, bestSize.y)
110 self.SetSize(size)
111
112 # Make an initial bitmap for the face, it will be updated and
113 # painted at the first EVT_SIZE event.
114 W, H = size
115 self.faceBitmap = wx.EmptyBitmap(max(W,1), max(H,1))
116
117 # Set event handlers...
118 self.Bind(wx.EVT_PAINT, self.OnPaint)
119 self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
120 self.Bind(wx.EVT_SIZE, self.OnSize)
121 self.Bind(wx.EVT_TIMER, self.OnTimerExpire)
122 self.Bind(wx.EVT_WINDOW_DESTROY, self.OnQuit)
123 self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
124 self.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
125
126 # Initialize the timer that drives the update of the clock
127 # face. Update every half second to ensure that there is at
128 # least one true update during each realtime second.
129 self.timer = wx.Timer(self)
130 self.timer.Start(500)
131
132
133 def DoGetBestSize(self):
134 return wx.Size(25,25)
135
136
137 def OnPaint(self, event):
138 dc = wx.BufferedPaintDC(self)
139 if hasattr(self, 'coords'):
140 self._doDrawHands(dc, True)
141
142
143 def OnTimerExpire(self, event):
144 size = self.GetClientSize()
145 dc = wx.BufferedDC(wx.ClientDC(self), size)
146 self._doDrawHands(dc, True)
147
148
149 def OnQuit(self, event):
150 self.timer.Stop()
151 del self.timer
152
153
154 def OnRightDown(self, event):
155 self.x = event.GetX()
156 self.y = event.GetY()
157 event.Skip()
158
159
160 def OnRightClick(self, event):
161 # only do this part the first time so the events are only bound once
162 if not hasattr(self, "popupID1"):
163 self.popupID1 = wx.NewId()
164 self.popupID2 = wx.NewId()
165 self.Bind(wx.EVT_MENU, self.OnPopupOne, id=self.popupID1)
166 self.Bind(wx.EVT_MENU, self.OnPopupTwo, id=self.popupID2)
167
168 # make a menu
169 sm = wx.Menu()
170
171 sm.Append(self.popupID1, "Customize...")
172 sm.Append(self.popupID2, "About...")
173
174 # If there already a setup window open, we must not appear...
175 if not self.prefs_open:
176 # Popup the menu. If an item is selected then its handler
177 # will be called before PopupMenu returns.
178 self.PopupMenu(sm, (self.x,self.y))
179 sm.Destroy()
180
181
182 def OnPopupOne(self, event):
183 self.prefs_open=True
184 frame = ACCustomizationFrame(self, -1, "AnalogClock Preferences")
185 frame.Show(True)
186
187
188 def OnPopupTwo(self, event):
189 dlg = wx.MessageDialog(self, "AnalogClockWindow\n\nby Several folks on wxPython-users\nwith enhancements from E. A. Tacão",
190 'About', wx.OK | wx.ICON_INFORMATION)
191 dlg.ShowModal()
192 dlg.Destroy()
193
194
195 def OnSize(self, event):
196 # The faceBitmap init is done here, to make sure the buffer is always
197 # the same size as the Window
198 size = self.GetClientSize()
199 if size.x < 1 or size.y < 1:
200 return
201
202 self.faceBitmap = wx.EmptyBitmap(size.width, size.height)
203
204 # Update drawing coordinates...
205 new_dim = size.Get()
206 if not hasattr(self,"dim"):
207 self.dim = new_dim
208
209 x,y=[0,1]
210 self.scale = min([float(new_dim[x]) / self.dim[x],
211 float(new_dim[y]) / self.dim[y]])
212
213 self.centerX = self.faceBitmap.GetWidth() / 2
214 self.centerY = self.faceBitmap.GetHeight() / 2
215
216 self.shadowDistance = 2 * self.scale
217
218 self.radius_watch = min(self.centerX, self.centerY)
219
220 self._doDrawFace()
221
222
223
224 def _doDrawHands(self, drawDC, force=0):
225 currentTime = list(time.localtime(time.time())[3:6])
226
227 if not (self.handsStyle & SHOW_SECONDS_HAND):
228 currentTime[2]=-1
229
230 if not (force or currentTime != self.currentTime):
231 return
232 self.currentTime = currentTime
233 hour, minutes, seconds = currentTime
234
235 # Start by drawing the face bitmap
236 drawDC.DrawBitmap(self.faceBitmap, 0,0)
237
238
239 # NOTE: All this hand drawing code below should be refactored into a helper function.
240
241
242 # Draw hours hand shadow
243 mStep = 6 * self.clockStep
244 angle = hour * 30
245 if angle > 360:
246 angle = angle - 360
247 angle = angle + round(minutes/(mStep*2)) * mStep
248
249 x,y,f = self._getCoords("hand_hours", angle)
250
251 if f and self.clockStyle & SHOW_SHADOWS:
252 drawDC.SetPen(wx.Pen(self.shadowPenColour,
253 int(self.handHoursThickness * self.scale),
254 wx.SOLID))
255 drawDC.DrawLine(self.centerX + self.shadowDistance,
256 self.centerY + self.shadowDistance,
257 x + self.shadowDistance,
258 y + self.shadowDistance)
259
260 # Draw minutes hand shadow
261 angle = minutes * 6
262 x,y,f = self._getCoords("hand_minutes", angle)
263
264 if f and self.clockStyle & SHOW_SHADOWS:
265 drawDC.SetPen(wx.Pen(self.shadowPenColour,
266 int(self.handMinutesThickness * self.scale),
267 wx.SOLID))
268 drawDC.DrawLine(self.centerX + self.shadowDistance,
269 self.centerY + self.shadowDistance,
270 x + self.shadowDistance,
271 y + self.shadowDistance)
272
273 # Draw seconds hand shadow if required
274 if seconds >= 0:
275 angle = seconds * 6
276 x,y,f = self._getCoords("hand_seconds", angle)
277
278 if f and self.clockStyle & SHOW_SHADOWS:
279 drawDC.SetPen(wx.Pen(self.shadowPenColour,
280 int(self.handSecondsThickness * self.scale),
281 wx.SOLID))
282 drawDC.DrawLine(self.centerX + self.shadowDistance,
283 self.centerY + self.shadowDistance,
284 x + self.shadowDistance,
285 y + self.shadowDistance)
286
287
288 # Draw hours hand
289 angle = hour * 30
290 if angle > 360:
291 angle = angle - 360
292 angle = angle + round(minutes/(mStep*2)) * mStep
293
294 x,y,f = self._getCoords("hand_hours", angle)
295
296 if f:
297 drawDC.SetPen(wx.Pen(self.handHoursColour,
298 int(self.handHoursThickness * self.scale),
299 wx.SOLID))
300 drawDC.DrawLine(self.centerX, self.centerY, x, y)
301
302 # Draw minutes hand
303 angle = minutes * 6
304 x,y,f = self._getCoords("hand_minutes", angle)
305
306 if f:
307 drawDC.SetPen(wx.Pen(self.handMinutesColour,
308 int(self.handMinutesThickness * self.scale),
309 wx.SOLID))
310 drawDC.DrawLine(self.centerX, self.centerY, x, y)
311
312 # Draw seconds hand if required
313 if seconds >= 0:
314 angle = seconds * 6
315 x,y,f = self._getCoords("hand_seconds", angle)
316 if f:
317 drawDC.SetPen(wx.Pen(self.handSecondsColour,
318 int(self.handSecondsThickness * self.scale),
319 wx.SOLID))
320 drawDC.DrawLine(self.centerX, self.centerY, x, y)
321
322
323
324 def _doDrawFace(self):
325 backgroundBrush = wx.Brush(self.GetBackgroundColour(), wx.SOLID)
326 drawDC = wx.MemoryDC()
327 drawDC.SelectObject(self.faceBitmap)
328 drawDC.SetBackground(backgroundBrush)
329 drawDC.Clear()
330
331 self.handHoursLength = 0.65 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC))
332 self.handMinutesLength = 0.85 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC))
333 self.handSecondsLength = 0.85 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC))
334
335 self.radius_ticks_hours = self.radius_watch - self.shadowDistance - self._getMarkMaxSize("ticks_hours", drawDC)
336 self.radius_ticks_minutes = self.radius_ticks_hours
337
338 self._calcSteps()
339
340 # Draw the watch...
341 self._drawWatch(drawDC)
342
343 # Draw the marks for hours and minutes...
344 circle = 360
345 mStep = 6 * self.clockStep
346
347 if self.clockStyle & SHOW_SHADOWS:
348 for i in range(0, circle, mStep):
349 for t in self.coords.keys():
350 if t.find("ticks") > -1:
351 x,y,f = self._getCoords(t, i)
352 if f:
353 self._doDrawTickMark(i, drawDC, t,
354 x + self.shadowDistance,
355 y + self.shadowDistance,
356 True)
357
358 for i in range(0, circle, mStep):
359 for t in self.coords.keys():
360 if t.find("ticks") > -1:
361 x,y,f = self._getCoords(t, i)
362 if f:
363 self._doDrawTickMark(i, drawDC, t, x, y)
364
365
366
367 def _doDrawTickMark(self, angle, drawDC, tipo, x, y, is_a_shadow=None):
368 opts = {"ticks_hours": [self.tickMarkHoursPen, self.tickMarkHoursBrush, self.markSizeHour, self.tickMarkHoursStyle],
369 "ticks_quarters": [self.tickMarkHoursPen, self.tickMarkHoursBrush, self.markSizeHour, self.tickMarkHoursStyle],
370 "ticks_minutes": [self.tickMarkMinutesPen, self.tickMarkMinutesBrush, self.markSizeMin, self.tickMarkMinutesStyle]}
371
372 pen, brush, size, style = opts[tipo];
373 size = size * self.scale
374
375 if is_a_shadow:
376 drawDC.SetPen(wx.Pen(self.shadowPenColour, 1, wx.SOLID))
377 drawDC.SetBrush(wx.Brush(self.shadowBrushColour, wx.SOLID))
378 drawDC.SetTextForeground(self.shadowBrushColour)
379 else:
380 drawDC.SetPen(pen)
381 drawDC.SetBrush(brush)
382 drawDC.SetTextForeground(brush.GetColour())
383
384 if style & TICKS_CIRCLE:
385 x, y = self._center2corner(x, y, tipo)
386 drawDC.DrawEllipse(x, y, size, size)
387
388 elif style & TICKS_SQUARE:
389 x, y = self._center2corner(x, y, tipo)
390 drawDC.DrawRectangle(x, y, size, size)
391
392 elif (style & TICKS_DECIMAL) or (style & TICKS_ROMAN):
393 self._draw_rotate_text(drawDC, x, y, tipo, angle)
394
395 elif style & TICKS_POLY:
396 self._draw_rotate_polygon(drawDC, x, y, tipo, angle)
397
398
399 def _draw_rotate_text(self, drawDC, x, y, tipo, angle):
400 text = self._build_text(angle, tipo)
401 lX, lY = self._center2corner(x, y, tipo, drawDC)
402 lX = lX * len(text)
403 angle = 360 - angle
404
405 if self.clockStyle & ROTATE_TICKS:
406 radiansPerDegree = math.pi / 180
407 x = int(x -
408 ((math.cos((angle) * radiansPerDegree)*lX) +
409 (math.sin((angle) * radiansPerDegree)*lY)))
410 y = int(y -
411 ((math.cos((angle) * radiansPerDegree)*lY) -
412 (math.sin((angle) * radiansPerDegree)*lX)))
413 drawDC.DrawRotatedText(text, x,y, angle)
414
415 else:
416 x = x - lX
417 y = y - lY
418 drawDC.DrawText(text, x, y)
419
420
421 def _draw_rotate_polygon(self, drawDC, x, y, tipo, angle):
422 if tipo=="ticks_quarters":
423 tipo="ticks_hours"
424
425 # Add to empty list to prevent system-wide hard freezes under XP...
426 points = {"ticks_hours":self.tickShapeHours+[], "ticks_minutes":self.tickShapeMinutes+[]}[tipo]
427 size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo]
428
429 maxX = max(map(lambda x:x[0],points))
430 minX = min(map(lambda x:x[0],points))
431 maxY = max(map(lambda x:x[0],points))
432 minY = min(map(lambda x:x[0],points))
433
434 maxB = abs(max(maxX, maxY));
435 f = size / maxB
436
437 orgX = (maxX - minX) / 2.
438 orgY = (maxY - minY) / 2.
439
440 radiansPerDegree = math.pi / 180
441 scaledX = x
442 scaledY = y
443
444 for z in range(0, len(points)):
445 x,y = points[z]
446 x = x * f - orgX * f
447 y = y * f - orgY * f
448 if self.clockStyle & ROTATE_TICKS:
449 m,t = self._rect2pol(x,y)
450 t = t + angle
451 x,y = self._pol2rect(m,t)
452 x = x + scaledX
453 y = y + scaledY
454 points[z] = [int(x), int(y)]
455
456 drawDC.DrawPolygon(points)
457
458
459 def _pol2rect(self, r, w, deg=1): # radian if deg=0; degree if deg=1
460 if deg:
461 w = math.pi * w / 180.0
462 return r * math.cos(w), r * math.sin(w)
463
464
465 def _rect2pol(self, x, y, deg=1): # radian if deg=0; degree if deg=1
466 if deg:
467 return math.hypot(x, y), 180.0 * math.atan2(y, x) / math.pi
468 else:
469 return math.hypot(x, y), math.atan2(y, x)
470
471
472 def _center2corner(self, x, y, tipo, drawDC=None):
473 if tipo == "ticks_quarters":
474 tipo = "ticks_hours"
475
476 style = {"ticks_hours":self.tickMarkHoursStyle, "ticks_minutes":self.tickMarkMinutesStyle}[tipo]
477 size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo]
478
479 if style & TICKS_DECIMAL or style & TICKS_ROMAN:
480 font = {"ticks_hours":self.tickMarkHoursFont, "ticks_minutes":self.tickMarkMinutesFont}[tipo]
481 font.SetPointSize(int(size));
482 drawDC.SetFont(font)
483 lX = drawDC.GetCharWidth() / 2.
484 lY = drawDC.GetCharHeight() / 2.
485 x = lX
486 y = lY
487 else:
488 size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo]
489 x=x-size/2.;y=y-size/2.
490 return x, y
491
492
493 def _build_text(self, angle, tipo):
494 if tipo == "ticks_quarters":
495 tipo = "ticks_hours"
496 a = angle
497 if a <= 0:
498 a = a + 360
499 divider = {"ticks_hours":30,"ticks_minutes":6}[tipo]
500 a = int(a / divider)
501
502 style = {"ticks_hours":self.tickMarkHoursStyle," ticks_minutes":self.tickMarkMinutesStyle}[tipo]
503 if style & TICKS_ROMAN:
504 text=["I","II","III","IV","V","VI","VII","VIII","IX","X", \
505 "XI","XII","XIII","XIV","XV","XVI","XVII","XVIII","XIX","XX", \
506 "XXI","XXII","XXIII","XXIV","XXV","XXVI","XXVII","XXVIII","XXIX","XXX", \
507 "XXXI","XXXII","XXXIII","XXXIV","XXXV","XXXVI","XXXVII","XXXVIII","XXXIX","XL", \
508 "XLI","XLII","XLIII","XLIV","XLV","XLVI","XLVII","XLVIII","XLIX","L", \
509 "LI","LII","LIII","LIV","LV","LVI","LVII","LVIII","LIX","LX"][a-1]
510 else:
511 text = "%s" % a
512
513 return text
514
515
516 def _getMarkMaxSize(self, tipo, drawDC=None):
517 if tipo == "ticks_quarters":
518 tipo = "ticks_hours"
519
520 style = {"ticks_hours":self.tickMarkHoursStyle, "ticks_minutes":self.tickMarkMinutesStyle}[tipo]
521 size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo]
522
523 if style & TICKS_DECIMAL or style & TICKS_ROMAN:
524 lX = 2 * drawDC.GetCharWidth()
525 lY = drawDC.GetCharHeight()
526 size = math.sqrt(lX**2 + lY**2) * self.scale
527 else:
528 size=math.sqrt(2) * size
529
530 return size
531
532
533 def _drawWatch(self, drawDC):
534 # Draw the watch...
535 if self.watchPen or self.watchBrush:
536 if self.watchPen:
537 drawDC.SetPen(self.watchPen)
538 if self.watchBrush:
539 drawDC.SetBrush(self.watchBrush)
540 else:
541 drawDC.SetBrush(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
542 drawDC.DrawCircle(self.centerX, self.centerY, self.radius_watch)
543
544
545 def _calcSteps(self):
546 # Calcule todos os pontos para:
547 # - marcas de horas
548 # - marcas de minutos
549 # - ponteiro de horas
550 # - ponteiro de minutos
551 # - ponteiro de segundos
552
553 circle = 360
554 mStep = 6 * self.clockStep # Step in degrees...
555
556 vq = 90 * (self.clockStyle & SHOW_QUARTERS_TICKS) / SHOW_QUARTERS_TICKS
557 vh = 30 * (self.clockStyle & SHOW_HOURS_TICKS) / SHOW_HOURS_TICKS
558 vm = 1 * (self.clockStyle & SHOW_MINUTES_TICKS) / SHOW_MINUTES_TICKS
559
560 coords = {"ticks_quarters": [self.radius_ticks_hours, 60,vq,{}],
561 "ticks_hours": [self.radius_ticks_hours, 60,vh,{}],
562 "ticks_minutes": [self.radius_ticks_minutes,60,vm,{}],
563 "hand_hours": [self.handHoursLength, 60,1, {}],
564 "hand_minutes": [self.handMinutesLength, 60,1, {}],
565 "hand_seconds": [self.handSecondsLength, 60,1, {}]}
566
567 radiansPerDegree = math.pi / 180
568
569 for t in coords.keys():
570 for i in range(0, circle+mStep, mStep):
571 radius = coords[t][0]
572 if t == "ticks_minutes":
573 radius = radius - self.offM
574 step_angle = 360. / coords[t][1]
575 pre = coords[t][2]
576 x = self.centerX + radius * math.sin(i * radiansPerDegree)
577 y = self.centerY + radius * math.cos(i * radiansPerDegree)
578 f = (pre and (i/step_angle == int(i/step_angle)) and (float(i)/pre == int(i/pre)))
579 coords[t][3][i] = [x,y,f]
580
581 if not self.clockStyle & OVERLAP_TICKS:
582 for i in range(0, circle + mStep, mStep):
583 f=coords["ticks_minutes"][3][i][2]
584 if f and \
585 (coords["ticks_hours"][3].get(i,[0,0,0])[2] or coords["ticks_quarters"][3].get(i,[0,0,0])[2]):
586 f=False
587 coords["ticks_minutes"][3][i][2]=f
588
589 self.coords = coords
590
591
592 def _getCoords(self, tipo, angle):
593 # Returns coords and 'use flag' based on current angle...
594 k = 360 - (angle + 180)
595 if k <= 0:
596 k = k + 360
597 return self.coords[tipo][3][k]
598
599
600 # -----------------------------------------------------
601 #
602 def SetTickShapes(self, tsh, tsm=None):
603 """
604 tsh, tsm: [[x0,y0], [x1,y1], ... [xn,yn]]
605
606 Sets lists of lists of points to be used as polygon shapes
607 when using the TICKS_POLY style. If tsm is ommitted,
608 we'll use tsh for both shapes.
609 """
610
611 if not tsm:
612 tsm=tsh
613
614 self.tickShapeHours = tsh
615 self.tickShapeMinutes = tsm
616
617
618 def SetHandWeights(self, h=None, m=None, s=None):
619 """
620 h, m, s: value
621
622 Sets thickness of hands.
623 """
624
625 if h:
626 self.handHoursThickness = h
627 if m:
628 self.handMinutesThickness = m
629 if s:
630 self.handSecondsThickness = s
631
632
633 def SetHandColours(self, h=None, m=None, s=None):
634 """
635 h, m, s: wx.Colour
636
637 Sets colours of hands. If m and s are ommitted,
638 we'll use h for all.
639 """
640
641 if h and not m and not s:
642 m=h
643 s=h
644
645 if h:
646 self.handHoursColour = h
647 if m:
648 self.handMinutesColour = m
649 if s:
650 self.handSecondsColour = s
651
652
653 def SetTickColours(self, h=None, m=None):
654 """
655 h, m: wx.Colour
656
657 Sets colours of ticks. If m is ommitted,
658 we'll use h for both.
659 """
660
661 if not m:
662 m=h
663
664 if h:
665 self.tickMarkHoursPen = wx.Pen(h, 1, wx.SOLID)
666 self.tickMarkHoursBrush = wx.Brush(h, wx.SOLID)
667
668 if m:
669 self.tickMarkMinutesPen = wx.Pen(m, 1, wx.SOLID)
670 self.tickMarkMinutesBrush = wx.Brush(m, wx.SOLID)
671
672
673 def SetTickSizes(self, h=None, m=None):
674 """
675 h, m: value
676
677 Sizes for tick marks.
678 """
679
680 if h:
681 self.markSizeHour = h
682 if m:
683 self.markSizeMin = m
684
685
686 def SetTickFonts(self, h=None, m=None):
687 """
688 h, m: wx.Font
689
690 Fonts for tick marks when using TICKS_DECIMAL or TICKS_ROMAN style.
691 If m is ommitted, we'll use h for both.
692 """
693
694 if not m:
695 m=h
696
697 if h:
698 self.tickMarkHoursFont = h
699 self.tickMarkHoursFont.SetPointSize(self.markSizeHour)
700 if m:
701 self.tickMarkMinutesFont = m
702 self.tickMarkMinutesFont.SetPointSize(self.markSizeMin)
703
704
705 def SetMinutesOffset(self, o):
706 """
707 s = value
708
709 Sets the distance between tick marks for hours and minutes.
710 """
711 self.offM = o
712
713
714 def SetShadowColour(self, s):
715 """
716 s = wx.Colour or (r,g,b) tuple.
717
718 Sets the colour to be used to draw shadows.
719 """
720
721 self.shadowPenColour = self.shadowBrushColour = s
722
723
724 def SetWatchPenBrush(self, p=None, b=None):
725 """
726 p = wx.Pen; b = wx.Brush
727
728 Set the pen and brush for the watch.
729 """
730
731 if p:
732 self.watchPen = p
733 if b:
734 self.watchBrush = b
735
736
737 def SetClockStyle(self, style):
738 """
739 Set the clock style, acording to these options:
740
741 ==================== ================================
742 SHOW_QUARTERS_TICKS Show marks for hours 3, 6, 9, 12
743 SHOW_HOURS_TICKS Show marks for all hours
744 SHOW_MINUTES_TICKS Show marks for minutes
745
746 SHOW_HOURS_HAND Show hours hand
747 SHOW_MINUTES_HAND Show minutes hand
748 SHOW_SECONDS_HAND Show seconds hand
749
750 SHOW_SHADOWS Show hands and marks shadows
751
752 ROTATE_TICKS Align tick marks to watch
753 OVERLAP_TICKS Draw tick marks for minutes even
754 when they match the hours marks.
755 ==================== ================================
756 """
757
758 self.clockStyle = style
759
760
761 def SetTickStyles(self, h=None, m=None):
762 """
763 Set the ticks styles, acording to the options below.
764
765 ================= =====================================
766 TICKS_NONE Don't show tick marks.
767 TICKS_SQUARE Use squares as tick marks.
768 TICKS_CIRCLE Use circles as tick marks.
769 TICKS_POLY Use a polygon as tick marks. The
770 polygon must be passed using
771 SetTickShapes, otherwise the default
772 polygon will be used.
773 TICKS_DECIMAL Use decimal numbers.
774 TICKS_ROMAN Use Roman numbers.
775 ================= =====================================
776 """
777
778 if h:
779 self.tickMarkHoursStyle = h
780 if m:
781 self.tickMarkMinutesStyle = m
782 #
783 # -----------------------------------------------------
784
785
786 if __name__ == "__main__":
787 print wx.VERSION_STRING
788 class App(wx.App):
789 def OnInit(self):
790 frame = wx.Frame(None, -1, "AnalogClockWindow", size=(375,375))
791
792 clock = AnalogClockWindow(frame)
793
794 # Settings below are used by default...
795 #clock.SetClockStyle(SHOW_HOURS_TICKS|SHOW_MINUTES_TICKS|SHOW_SHADOWS|ROTATE_TICKS)
796 #clock.SetTickStyles(TICKS_POLY, TICKS_CIRCLE)
797
798 frame.Centre(wx.BOTH)
799 frame.Show(True)
800 self.SetTopWindow(frame)
801 return True
802
803 theApp = App(0)
804 theApp.MainLoop()
805
806
807 #
808 ##
809 ### eof