| 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 |