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