]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/analogclock/analogclock.py
ensure that the MasedEditMixin's version of IsEmpty is the one used.
[wxWidgets.git] / wxPython / wx / lib / analogclock / analogclock.py
CommitLineData
caeac82e
RD
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
9import wx
10
11from styles import *
12from helpers import Dyer, Face, Hand, HandSet, TickSet, Box
13from setup import Setup
14
15#----------------------------------------------------------------------
16
17class 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.SetBestFittingSize(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 dc = wx.BufferedDC(wx.ClientDC(self), self.GetClientSize())
132 self.DrawHands(dc)
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."""
190
191 dc = wx.BufferedDC(wx.ClientDC(self), self.GetClientSize())
192 dc.BeginDrawing()
193 dc.SelectObject(self.faceBitmap)
194 dc.SetBackground(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
195 dc.Clear()
196 self.Box.Draw(dc)
197 dc.EndDrawing()
198
199
200 def _drawHands(self, dc):
201 """
202 Draws the face bitmap, created on the last DrawBox call, and
203 clock hands.
204 """
205
206 dc.BeginDrawing()
207 dc.DrawBitmap(self.faceBitmap, 0, 0)
208 self.Hands.Draw(dc)
209 dc.EndDrawing()
210
211
212 # Public methods --------------------------------------------------
213
214 def GetHandSize(self, target=ALL):
215 """Gets thickness of hands."""
216
217 return self.Hands.GetSize(target)
218
219
220 def GetHandFillColour(self, target=ALL):
221 """Gets fill colours of hands."""
222
223 return self.Hands.GetFillColour(target)
224
225
226 def GetHandBorderColour(self, target=ALL):
227 """Gets border colours of hands."""
228
229 return self.Hands.GetBorderColour(target)
230
231
232 def GetHandBorderWidth(self, target=ALL):
233 """Gets border widths of hands."""
234
235 return self.Hands.GetBorderWidth(target)
236
237
238 def GetTickSize(self, target=ALL):
239 """Gets sizes of ticks."""
240
241 return self.Box.GetTickSize(target)
242
243
244
245 def GetTickFillColour(self, target=ALL):
246 """Gets fill colours of ticks."""
247
248 return self.Box.GetTickFillColour(target)
249
250
251
252 def GetTickBorderColour(self, target=ALL):
253 """Gets border colours of ticks."""
254
255 return self.Box.GetTickBorderColour(target)
256
257
258
259 def GetTickBorderWidth(self, target=ALL):
260 """Gets border widths of ticks."""
261
262 return self.Box.GetTickBorderWidth(target)
263
264
265
266 def GetTickPolygon(self, target=ALL):
267 """
268 Gets lists of points to be used as polygon shapes
269 when using the TICKS_POLY style.
270 """
271
272 return self.Box.GetTickPolygon(target)
273
274
275
276 def GetTickFont(self, target=ALL):
277 """
278 Gets fonts for tick marks when using TICKS_DECIMAL or
279 TICKS_ROMAN style.
280 """
281
282 return self.Box.GetTickFont(target)
283
284
285
286 def GetTickOffset(self, target=ALL):
287 """Gets the distance of tick marks for hours from border."""
288
289 return self.Box.GetTickOffset(target)
290
291
292
293 def GetFaceFillColour(self):
294 """Gets fill colours of watch."""
295
296 return self.Box.Face.GetFillColour()
297
298
299
300 def GetFaceBorderColour(self):
301 """Gets border colours of watch."""
302
303 return self.Box.Face.GetBorderColour()
304
305
306
307 def GetFaceBorderWidth(self):
308 """Gets border width of watch."""
309
310 return self.Box.Face.GetBorderWidth()
311
312
313
314 def GetShadowColour(self):
315 """Gets the colour to be used to draw shadows."""
316
317 a_clock_part = self.Box
318 return a_clock_part.GetShadowColour()
319
320
321
322 def GetClockStyle(self):
323 """Returns the current clock style."""
324
325 return self.clockStyle
326
327
328 def GetTickStyle(self, target=ALL):
329 """Gets the tick style(s)."""
330
331 return self.Box.GetTickStyle(target)
332
333
334 def Refresh(self):
335 """
336 Overriden base wx.Window method. Forces an immediate
337 recalculation and redraw of all clock elements.
338 """
339
340 size = self.GetClientSize()
341 if size.x < 1 or size.y < 1:
342 return
343 self.Freeze()
344 self.RecalcCoords(size)
345 self.DrawBox()
346 dc = wx.BufferedDC(wx.ClientDC(self), self.GetClientSize())
347 self.DrawHands(dc)
348 self.Thaw()
349
350
351 def SetHandSize(self, size, target=ALL):
352 """Sets thickness of hands."""
353
354 self.Hands.SetSize(size, target)
355
356
357 def SetHandFillColour(self, colour, target=ALL):
358 """Sets fill colours of hands."""
359
360 self.Hands.SetFillColour(colour, target)
361
362
363 def SetHandBorderColour(self, colour, target=ALL):
364 """Sets border colours of hands."""
365
366 self.Hands.SetBorderColour(colour, target)
367
368
369 def SetHandBorderWidth(self, width, target=ALL):
370 """Sets border widths of hands."""
371
372 self.Hands.SetBorderWidth(width, target)
373
374
375 def SetTickSize(self, size, target=ALL):
376 """Sets sizes of ticks."""
377
378 self.Box.SetTickSize(size, target)
379 self.Refresh()
380
381
382 def SetTickFillColour(self, colour, target=ALL):
383 """Sets fill colours of ticks."""
384
385 self.Box.SetTickFillColour(colour, target)
386 self.Refresh()
387
388
389 def SetTickBorderColour(self, colour, target=ALL):
390 """Sets border colours of ticks."""
391
392 self.Box.SetTickBorderColour(colour, target)
393 self.Refresh()
394
395
396 def SetTickBorderWidth(self, width, target=ALL):
397 """Sets border widths of ticks."""
398
399 self.Box.SetTickBorderWidth(width, target)
400 self.Refresh()
401
402
403 def SetTickPolygon(self, polygon, target=ALL):
404 """
405 Sets lists of points to be used as polygon shapes
406 when using the TICKS_POLY style.
407 """
408
409 self.Box.SetTickPolygon(polygon, target)
410 self.Refresh()
411
412
413 def SetTickFont(self, font, target=ALL):
414 """
415 Sets fonts for tick marks when using text-based tick styles
416 such as TICKS_DECIMAL or TICKS_ROMAN.
417 """
418
419 self.Box.SetTickFont(font, target)
420 self.Refresh()
421
422
423 def SetTickOffset(self, offset, target=ALL):
424 """Sets the distance of tick marks for hours from border."""
425
426 self.Box.SetTickOffset(offset, target)
427 self.Refresh()
428
429
430 def SetFaceFillColour(self, colour):
431 """Sets fill colours of watch."""
432
433 self.Box.Face.SetFillColour(colour)
434 self.Refresh()
435
436
437 def SetFaceBorderColour(self, colour):
438 """Sets border colours of watch."""
439
440 self.Box.Face.SetBorderColour(colour)
441 self.Refresh()
442
443
444 def SetFaceBorderWidth(self, width):
445 """Sets border width of watch."""
446
447 self.Box.Face.SetBorderWidth(width)
448 self.Refresh()
449
450
451 def SetShadowColour(self, colour):
452 """Sets the colour to be used to draw shadows."""
453
454 self.Hands.SetShadowColour(colour)
455 self.Box.SetShadowColour(colour)
456 self.Refresh()
457
458
459 def SetClockStyle(self, style):
460 """
461 Set the clock style, according to the options below.
462
463 ==================== ================================
464 SHOW_QUARTERS_TICKS Show marks for hours 3, 6, 9, 12
465 SHOW_HOURS_TICKS Show marks for all hours
466 SHOW_MINUTES_TICKS Show marks for minutes
467
468 SHOW_HOURS_HAND Show hours hand
469 SHOW_MINUTES_HAND Show minutes hand
470 SHOW_SECONDS_HAND Show seconds hand
471
472 SHOW_SHADOWS Show hands and marks shadows
473
474 ROTATE_TICKS Align tick marks to watch
475 OVERLAP_TICKS Draw tick marks for minutes even
476 when they match the hours marks.
477 ==================== ================================
478 """
479
480 self.clockStyle = style
481 self.Box.SetIsRotated(style & ROTATE_TICKS)
482 self.Refresh()
483
484
485 def SetTickStyle(self, style, target=ALL):
486 """
487 Set the tick style, according to the options below.
488
489 ================= ======================================
490 TICKS_NONE Don't show tick marks.
491 TICKS_SQUARE Use squares as tick marks.
492 TICKS_CIRCLE Use circles as tick marks.
493 TICKS_POLY Use a polygon as tick marks. A
494 polygon can be passed using
495 SetTickPolygon, otherwise the default
496 polygon will be used.
497 TICKS_DECIMAL Use decimal numbers as tick marks.
498 TICKS_ROMAN Use Roman numbers as tick marks.
499 TICKS_BINARY Use binary numbers as tick marks.
500 TICKS_HEX Use hexadecimal numbers as tick marks.
501 ================= ======================================
502 """
503
504 self.Box.SetTickStyle(style, target)
505 self.Refresh()
506
507
508 def SetBackgroundColour(self, colour):
509 """Overriden base wx.Window method."""
510
511 wx.Window.SetBackgroundColour(self, colour)
512 self.Refresh()
513
514
515 def SetForegroundColour(self, colour):
516 """
517 Overriden base wx.Window method. This method sets a colour for
518 all hands and ticks at once.
519 """
520
521 wx.Window.SetForegroundColour(self, colour)
522 self.SetHandFillColour(colour)
523 self.SetHandBorderColour(colour)
524 self.SetTickFillColour(colour)
525 self.SetTickBorderColour(colour)
526 self.Refresh()
527
528
529 def SetWindowStyle(self, *args, **kwargs):
530 """Overriden base wx.Window method."""
531
532 size = self.GetSize()
533 self.Freeze()
534 wx.Window.SetWindowStyle(self, *args, **kwargs)
535 self.SetSize((10, 10))
536 self.SetSize(size)
537 self.Thaw()
538
539
540 def SetWindowStyleFlag(self, *args, **kwargs):
541 """Overriden base wx.Window method."""
542
543 self.SetWindowStyle(*args, **kwargs)
544
545
546# For backwards compatibility -----------------------------------------
547
548class AnalogClockWindow(AnalogClock):
549 """
550 A simple derived class that provides some backwards compatibility
551 with the old analogclock module.
552 """
553 def SetTickShapes(self, tsh, tsm=None):
554 self.SetTickPolygon(tsh)
555
556 def SetHandWeights(self, h=None, m=None, s=None):
557 if h:
558 self.SetHandSize(h, HOUR)
559 if m:
560 self.SetHandSize(m, MINUTE)
561 if s:
99ceaa26 562 self.SetHandSize(s, SECOND)
caeac82e
RD
563
564 def SetHandColours(self, h=None, m=None, s=None):
565 if h and not m and not s:
566 m=h
567 s=h
568 if h:
569 self.SetHandBorderColour(h, HOUR)
570 self.SetHandFillColour(h, HOUR)
571 if m:
572 self.SetHandBorderColour(m, MINUTE)
573 self.SetHandFillColour(m, MINUTE)
574 if s:
99ceaa26
RD
575 self.SetHandBorderColour(s, SECOND)
576 self.SetHandFillColour(s, SECOND)
caeac82e
RD
577
578 def SetTickColours(self, h=None, m=None):
579 if not m:
580 m=h
581 if h:
582 self.SetTickBorderColour(h, HOUR)
583 self.SetTickFillColour(h, HOUR)
584 if m:
585 self.SetTickBorderColour(m, MINUTE)
586 self.SetTickFillColour(m, MINUTE)
587
588 def SetTickSizes(self, h=None, m=None):
589 if h:
590 self.SetTickSize(h, HOUR)
591 if m:
99ceaa26 592 self.SetTickSize(m, MINUTE)
caeac82e
RD
593
594 def SetTickFontss(self, h=None, m=None):
595 if h:
596 self.SetTickFont(h, HOUR)
597 if m:
99ceaa26 598 self.SetTickFont(m, MINUTE)
caeac82e
RD
599
600
601 def SetMinutesOffset(self, o):
602 pass
603
604 def SetShadowColour(self, s):
605 pass
606
607 def SetWatchPenBrush(self, p=None, b=None):
608 if p:
609 self.SetFaceBorderColour(p.GetColour())
610 self.SetFaceBorderWidth(p.GetWidth())
611 if b:
612 self.SetFaceFillColour(b.GetColour())
613
614 def SetClockStyle(self, style):
615 style |= SHOW_HOURS_HAND|SHOW_MINUTES_HAND|SHOW_SECONDS_HAND
616 AnalogClock.SetClockStyle(self, style)
617
618 def SetTickStyles(self, h=None, m=None):
619 if h:
620 self.SetTickStyle(h, HOUR)
621 if m:
622 self.SetTickStyle(h, MINUTE)
623
624
625# Test stuff ----------------------------------------------------------
626
627if __name__ == "__main__":
628 print wx.VERSION_STRING
629
630 class AcDemoApp(wx.App):
631 def OnInit(self):
632 frame = wx.Frame(None, -1, "AnalogClock", size=(375, 375))
633 clock = AnalogClock(frame)
634 frame.CentreOnScreen()
635 frame.Show()
636 return True
637
638 acApp = AcDemoApp(0)
639 acApp.MainLoop()
640
641
642#
643##
644### eof