]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/analogclock/analogclock.py
no need to use a throw-away bitmap, just use th eone built-in to the
[wxWidgets.git] / wxPython / wx / lib / analogclock / analogclock.py
1 # AnalogClock's main class
2 # E. A. Tacao <e.a.tacao |at| estadao.com.br>
3 # http://j.domaindlx.com/elements28/wxpython/
4 # 15 Fev 2006, 22:00 GMT-03:00
5 # Distributed under the wxWidgets license.
6 #
7 # For more info please see the __init__.py file.
8
9 import wx
10
11 from styles import *
12 from helpers import Dyer, Face, Hand, HandSet, TickSet, Box
13 from setup import Setup
14
15 #----------------------------------------------------------------------
16
17 class AnalogClock(wx.PyWindow):
18 """An analog clock."""
19
20 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
21 size=wx.DefaultSize, style=wx.NO_BORDER, name="AnalogClock",
22 clockStyle=DEFAULT_CLOCK_STYLE,
23 minutesStyle=TICKS_CIRCLE, hoursStyle=TICKS_POLY):
24
25 wx.PyWindow.__init__(self, parent, id, pos, size, style, name)
26
27 # Base size for scale calc purposes.
28 self.basesize = wx.Size(348, 348)
29
30 # Store some references.
31 self.clockStyle = clockStyle
32 self.minutesStyle = minutesStyle
33 self.hoursStyle = hoursStyle
34
35 self.DrawHands = self._drawHands
36 self.DrawBox = self._drawBox
37 self.RecalcCoords = self._recalcCoords
38
39 self.shadowOffset = 3
40
41 self.allHandStyles = [SHOW_HOURS_HAND,
42 SHOW_MINUTES_HAND,
43 SHOW_SECONDS_HAND]
44
45 # Initialize clock face.
46 #
47 # By default we don't use colours or borders on the clock face.
48 bg = self.GetBackgroundColour()
49 face = Face(dyer=Dyer(bg, 0, bg))
50
51 # Initialize tick marks.
52 #
53 # TickSet is a set of tick marks; there's always two TickSets defined
54 # regardless whether they're being shown or not.
55 ticksM = TickSet(self, style=minutesStyle, size=5, kind="minutes")
56 ticksH = TickSet(self, style=hoursStyle, size=25, kind="hours",
57 rotate=clockStyle&ROTATE_TICKS)
58
59 # Box holds the clock face and tick marks.
60 self.Box = Box(self, face, ticksM, ticksH)
61
62 # Initialize hands.
63 #
64 # HandSet is the set of hands; there's always one HandSet defined
65 # regardless whether hands are being shown or not.
66 #
67 # A 'lenfac = 0.95', e.g., means that the lenght of that hand will
68 # be 95% of the maximum allowed hand lenght ('nice' maximum lenght).
69 handH = Hand(size=7, lenfac=0.7)
70 handM = Hand(size=5, lenfac=0.95)
71 handS = Hand(size=1, lenfac=0.95)
72 self.Hands = HandSet(self, handH, handM, handS)
73
74 # Create the customization dialog.
75 self.Setup = None
76
77 # Make a context menu.
78 popup1 = wx.NewId()
79 popup2 = wx.NewId()
80 cm = self.cm = wx.Menu()
81 cm.Append(popup1, "Customize...")
82 cm.Append(popup2, "About...")
83
84 # Set event handlers.
85 self.Bind(wx.EVT_SIZE, self._OnSize)
86 self.Bind(wx.EVT_PAINT, self._OnPaint)
87 self.Bind(wx.EVT_ERASE_BACKGROUND, lambda evt: None)
88 self.Bind(wx.EVT_TIMER, self._OnTimer)
89 self.Bind(wx.EVT_WINDOW_DESTROY, self._OnDestroyWindow)
90 self.Bind(wx.EVT_CONTEXT_MENU, self._OnContextMenu)
91 self.Bind(wx.EVT_MENU, self._OnShowSetup, id=popup1)
92 self.Bind(wx.EVT_MENU, self._OnShowAbout, id=popup2)
93
94 # Set initial size based on given size, or best size
95 self.SetInitialSize(size)
96
97 # Do initial drawing (in case there is not an initial size event)
98 self.RecalcCoords(self.GetSize())
99 self.DrawBox()
100
101 # Initialize the timer that drives the update of the clock face.
102 # Update every half second to ensure that there is at least one true
103 # update during each realtime second.
104 self.timer = wx.Timer(self)
105 self.timer.Start(500)
106
107
108 def DoGetBestSize(self):
109 # Just pull a number out of the air. If there is a way to
110 # calculate this then it should be done...
111 size = wx.Size(50,50)
112 self.CacheBestSize(size)
113 return size
114
115
116 def _OnSize(self, evt):
117 size = self.GetClientSize()
118 if size.x < 1 or size.y < 1:
119 return
120
121 self.RecalcCoords(size)
122 self.DrawBox()
123
124
125 def _OnPaint(self, evt):
126 dc = wx.BufferedPaintDC(self)
127 self.DrawHands(dc)
128
129
130 def _OnTimer(self, evt):
131 self.Refresh(False)
132 self.Update()
133
134
135 def _OnDestroyWindow(self, evt):
136 self.timer.Stop()
137 del self.timer
138
139
140 def _OnContextMenu(self, evt):
141 self.PopupMenu(self.cm)
142
143
144 def _OnShowSetup(self, evt):
145 if self.Setup is None:
146 self.Setup = Setup(self)
147 self.Setup.Show()
148 self.Setup.Raise()
149
150
151 def _OnShowAbout(self, evt):
152 msg = "AnalogClock\n\n" \
153 "by Several folks on wxPython-users\n" \
154 "with enhancements from E. A. Tacao."
155 title = "About..."
156 style = wx.OK|wx.ICON_INFORMATION
157
158 dlg = wx.MessageDialog(self, msg, title, style)
159 dlg.ShowModal()
160 dlg.Destroy()
161
162
163 def _recalcCoords(self, size):
164 """
165 Recalculates all coordinates/geometry and inits the faceBitmap
166 to make sure the buffer is always the same size as the window.
167 """
168
169 self.faceBitmap = wx.EmptyBitmap(*size.Get())
170
171 # Recalc all coords.
172 scale = min([float(size.width) / self.basesize.width,
173 float(size.height) / self.basesize.height])
174
175 centre = wx.Point(size.width / 2., size.height / 2.)
176
177 self.Box.RecalcCoords(size, centre, scale)
178 self.Hands.RecalcCoords(size, centre, scale)
179
180 # Try to find a 'nice' maximum length for the hands so that they won't
181 # overlap the tick marks. OTOH, if you do want to allow overlapping the
182 # lenfac value (defined on __init__ above) has to be set to
183 # something > 1.
184 niceradius = self.Box.GetNiceRadiusForHands(centre)
185 self.Hands.SetMaxRadius(niceradius)
186
187
188 def _drawBox(self):
189 """Draws clock face and tick marks onto the faceBitmap."""
190 dc = wx.BufferedDC(None, self.faceBitmap)
191 dc.SetBackground(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
192 dc.Clear()
193 self.Box.Draw(dc)
194
195
196 def _drawHands(self, dc):
197 """
198 Draws the face bitmap, created on the last DrawBox call, and
199 clock hands.
200 """
201 dc.DrawBitmap(self.faceBitmap, 0, 0)
202 self.Hands.Draw(dc)
203
204
205 # Public methods --------------------------------------------------
206
207 def GetHandSize(self, target=ALL):
208 """Gets thickness of hands."""
209
210 return self.Hands.GetSize(target)
211
212
213 def GetHandFillColour(self, target=ALL):
214 """Gets fill colours of hands."""
215
216 return self.Hands.GetFillColour(target)
217
218
219 def GetHandBorderColour(self, target=ALL):
220 """Gets border colours of hands."""
221
222 return self.Hands.GetBorderColour(target)
223
224
225 def GetHandBorderWidth(self, target=ALL):
226 """Gets border widths of hands."""
227
228 return self.Hands.GetBorderWidth(target)
229
230
231 def GetTickSize(self, target=ALL):
232 """Gets sizes of ticks."""
233
234 return self.Box.GetTickSize(target)
235
236
237
238 def GetTickFillColour(self, target=ALL):
239 """Gets fill colours of ticks."""
240
241 return self.Box.GetTickFillColour(target)
242
243
244
245 def GetTickBorderColour(self, target=ALL):
246 """Gets border colours of ticks."""
247
248 return self.Box.GetTickBorderColour(target)
249
250
251
252 def GetTickBorderWidth(self, target=ALL):
253 """Gets border widths of ticks."""
254
255 return self.Box.GetTickBorderWidth(target)
256
257
258
259 def GetTickPolygon(self, target=ALL):
260 """
261 Gets lists of points to be used as polygon shapes
262 when using the TICKS_POLY style.
263 """
264
265 return self.Box.GetTickPolygon(target)
266
267
268
269 def GetTickFont(self, target=ALL):
270 """
271 Gets fonts for tick marks when using TICKS_DECIMAL or
272 TICKS_ROMAN style.
273 """
274
275 return self.Box.GetTickFont(target)
276
277
278
279 def GetTickOffset(self, target=ALL):
280 """Gets the distance of tick marks for hours from border."""
281
282 return self.Box.GetTickOffset(target)
283
284
285
286 def GetFaceFillColour(self):
287 """Gets fill colours of watch."""
288
289 return self.Box.Face.GetFillColour()
290
291
292
293 def GetFaceBorderColour(self):
294 """Gets border colours of watch."""
295
296 return self.Box.Face.GetBorderColour()
297
298
299
300 def GetFaceBorderWidth(self):
301 """Gets border width of watch."""
302
303 return self.Box.Face.GetBorderWidth()
304
305
306
307 def GetShadowColour(self):
308 """Gets the colour to be used to draw shadows."""
309
310 a_clock_part = self.Box
311 return a_clock_part.GetShadowColour()
312
313
314
315 def GetClockStyle(self):
316 """Returns the current clock style."""
317
318 return self.clockStyle
319
320
321 def GetTickStyle(self, target=ALL):
322 """Gets the tick style(s)."""
323
324 return self.Box.GetTickStyle(target)
325
326
327 def Reset(self):
328 """
329 Forces an immediate recalculation and redraw of all clock
330 elements.
331 """
332 size = self.GetClientSize()
333 if size.x < 1 or size.y < 1:
334 return
335 self.RecalcCoords(size)
336 self.DrawBox()
337 self.Refresh(False)
338
339
340 def SetHandSize(self, size, target=ALL):
341 """Sets thickness of hands."""
342
343 self.Hands.SetSize(size, target)
344
345
346 def SetHandFillColour(self, colour, target=ALL):
347 """Sets fill colours of hands."""
348
349 self.Hands.SetFillColour(colour, target)
350
351
352 def SetHandBorderColour(self, colour, target=ALL):
353 """Sets border colours of hands."""
354
355 self.Hands.SetBorderColour(colour, target)
356
357
358 def SetHandBorderWidth(self, width, target=ALL):
359 """Sets border widths of hands."""
360
361 self.Hands.SetBorderWidth(width, target)
362
363
364 def SetTickSize(self, size, target=ALL):
365 """Sets sizes of ticks."""
366
367 self.Box.SetTickSize(size, target)
368 self.Reset()
369
370
371 def SetTickFillColour(self, colour, target=ALL):
372 """Sets fill colours of ticks."""
373
374 self.Box.SetTickFillColour(colour, target)
375 self.Reset()
376
377
378 def SetTickBorderColour(self, colour, target=ALL):
379 """Sets border colours of ticks."""
380
381 self.Box.SetTickBorderColour(colour, target)
382 self.Reset()
383
384
385 def SetTickBorderWidth(self, width, target=ALL):
386 """Sets border widths of ticks."""
387
388 self.Box.SetTickBorderWidth(width, target)
389 self.Reset()
390
391
392 def SetTickPolygon(self, polygon, target=ALL):
393 """
394 Sets lists of points to be used as polygon shapes
395 when using the TICKS_POLY style.
396 """
397
398 self.Box.SetTickPolygon(polygon, target)
399 self.Reset()
400
401
402 def SetTickFont(self, font, target=ALL):
403 """
404 Sets fonts for tick marks when using text-based tick styles
405 such as TICKS_DECIMAL or TICKS_ROMAN.
406 """
407
408 self.Box.SetTickFont(font, target)
409 self.Reset()
410
411
412 def SetTickOffset(self, offset, target=ALL):
413 """Sets the distance of tick marks for hours from border."""
414
415 self.Box.SetTickOffset(offset, target)
416 self.Reset()
417
418
419 def SetFaceFillColour(self, colour):
420 """Sets fill colours of watch."""
421
422 self.Box.Face.SetFillColour(colour)
423 self.Reset()
424
425
426 def SetFaceBorderColour(self, colour):
427 """Sets border colours of watch."""
428
429 self.Box.Face.SetBorderColour(colour)
430 self.Reset()
431
432
433 def SetFaceBorderWidth(self, width):
434 """Sets border width of watch."""
435
436 self.Box.Face.SetBorderWidth(width)
437 self.Reset()
438
439
440 def SetShadowColour(self, colour):
441 """Sets the colour to be used to draw shadows."""
442
443 self.Hands.SetShadowColour(colour)
444 self.Box.SetShadowColour(colour)
445 self.Reset()
446
447
448 def SetClockStyle(self, style):
449 """
450 Set the clock style, according to the options below.
451
452 ==================== ================================
453 SHOW_QUARTERS_TICKS Show marks for hours 3, 6, 9, 12
454 SHOW_HOURS_TICKS Show marks for all hours
455 SHOW_MINUTES_TICKS Show marks for minutes
456
457 SHOW_HOURS_HAND Show hours hand
458 SHOW_MINUTES_HAND Show minutes hand
459 SHOW_SECONDS_HAND Show seconds hand
460
461 SHOW_SHADOWS Show hands and marks shadows
462
463 ROTATE_TICKS Align tick marks to watch
464 OVERLAP_TICKS Draw tick marks for minutes even
465 when they match the hours marks.
466 ==================== ================================
467 """
468
469 self.clockStyle = style
470 self.Box.SetIsRotated(style & ROTATE_TICKS)
471 self.Reset()
472
473
474 def SetTickStyle(self, style, target=ALL):
475 """
476 Set the tick style, according to the options below.
477
478 ================= ======================================
479 TICKS_NONE Don't show tick marks.
480 TICKS_SQUARE Use squares as tick marks.
481 TICKS_CIRCLE Use circles as tick marks.
482 TICKS_POLY Use a polygon as tick marks. A
483 polygon can be passed using
484 SetTickPolygon, otherwise the default
485 polygon will be used.
486 TICKS_DECIMAL Use decimal numbers as tick marks.
487 TICKS_ROMAN Use Roman numbers as tick marks.
488 TICKS_BINARY Use binary numbers as tick marks.
489 TICKS_HEX Use hexadecimal numbers as tick marks.
490 ================= ======================================
491 """
492
493 self.Box.SetTickStyle(style, target)
494 self.Reset()
495
496
497 def SetBackgroundColour(self, colour):
498 """Overriden base wx.Window method."""
499
500 wx.Window.SetBackgroundColour(self, colour)
501 self.Reset()
502
503
504 def SetForegroundColour(self, colour):
505 """
506 Overriden base wx.Window method. This method sets a colour for
507 all hands and ticks at once.
508 """
509
510 wx.Window.SetForegroundColour(self, colour)
511 self.SetHandFillColour(colour)
512 self.SetHandBorderColour(colour)
513 self.SetTickFillColour(colour)
514 self.SetTickBorderColour(colour)
515 self.Reset()
516
517
518 def SetWindowStyle(self, *args, **kwargs):
519 """Overriden base wx.Window method."""
520
521 size = self.GetSize()
522 self.Freeze()
523 wx.Window.SetWindowStyle(self, *args, **kwargs)
524 self.SetSize((10, 10))
525 self.SetSize(size)
526 self.Thaw()
527
528
529 def SetWindowStyleFlag(self, *args, **kwargs):
530 """Overriden base wx.Window method."""
531
532 self.SetWindowStyle(*args, **kwargs)
533
534
535 # For backwards compatibility -----------------------------------------
536
537 class AnalogClockWindow(AnalogClock):
538 """
539 A simple derived class that provides some backwards compatibility
540 with the old analogclock module.
541 """
542 def SetTickShapes(self, tsh, tsm=None):
543 self.SetTickPolygon(tsh)
544
545 def SetHandWeights(self, h=None, m=None, s=None):
546 if h:
547 self.SetHandSize(h, HOUR)
548 if m:
549 self.SetHandSize(m, MINUTE)
550 if s:
551 self.SetHandSize(s, SECOND)
552
553 def SetHandColours(self, h=None, m=None, s=None):
554 if h and not m and not s:
555 m=h
556 s=h
557 if h:
558 self.SetHandBorderColour(h, HOUR)
559 self.SetHandFillColour(h, HOUR)
560 if m:
561 self.SetHandBorderColour(m, MINUTE)
562 self.SetHandFillColour(m, MINUTE)
563 if s:
564 self.SetHandBorderColour(s, SECOND)
565 self.SetHandFillColour(s, SECOND)
566
567 def SetTickColours(self, h=None, m=None):
568 if not m:
569 m=h
570 if h:
571 self.SetTickBorderColour(h, HOUR)
572 self.SetTickFillColour(h, HOUR)
573 if m:
574 self.SetTickBorderColour(m, MINUTE)
575 self.SetTickFillColour(m, MINUTE)
576
577 def SetTickSizes(self, h=None, m=None):
578 if h:
579 self.SetTickSize(h, HOUR)
580 if m:
581 self.SetTickSize(m, MINUTE)
582
583 def SetTickFontss(self, h=None, m=None):
584 if h:
585 self.SetTickFont(h, HOUR)
586 if m:
587 self.SetTickFont(m, MINUTE)
588
589
590 def SetMinutesOffset(self, o):
591 pass
592
593 def SetShadowColour(self, s):
594 pass
595
596 def SetWatchPenBrush(self, p=None, b=None):
597 if p:
598 self.SetFaceBorderColour(p.GetColour())
599 self.SetFaceBorderWidth(p.GetWidth())
600 if b:
601 self.SetFaceFillColour(b.GetColour())
602
603 def SetClockStyle(self, style):
604 style |= SHOW_HOURS_HAND|SHOW_MINUTES_HAND|SHOW_SECONDS_HAND
605 AnalogClock.SetClockStyle(self, style)
606
607 def SetTickStyles(self, h=None, m=None):
608 if h:
609 self.SetTickStyle(h, HOUR)
610 if m:
611 self.SetTickStyle(h, MINUTE)
612
613
614 # Test stuff ----------------------------------------------------------
615
616 if __name__ == "__main__":
617 print wx.VERSION_STRING
618
619 class AcDemoApp(wx.App):
620 def OnInit(self):
621 frame = wx.Frame(None, -1, "AnalogClock", size=(375, 375))
622 clock = AnalogClock(frame)
623 frame.CentreOnScreen()
624 frame.Show()
625 return True
626
627 acApp = AcDemoApp(0)
628 acApp.MainLoop()
629
630
631 #
632 ##
633 ### eof