X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b881fc787d2823bdd8a415080b82feee90804a17..d8d7193d767beecab7335e58df1fa0d25ae1e2ea:/wxPython/wx/lib/analogclock.py diff --git a/wxPython/wx/lib/analogclock.py b/wxPython/wx/lib/analogclock.py index 6bd878f3fe..72a21e7957 100644 --- a/wxPython/wx/lib/analogclock.py +++ b/wxPython/wx/lib/analogclock.py @@ -1,5 +1,6 @@ +# -*- coding: iso-8859-1 -*- #---------------------------------------------------------------------- -# Name: wxPython.lib.analogclock +# Name: wx.lib.analogclock # Purpose: A simple analog clock window # # Author: several folks on wxPython-users @@ -14,38 +15,113 @@ # o Updated for wx namespace # o Tested with updated demo and with builtin test. # +# 15-February-2004 - E. A. Tacao +# +# o Many ehnacements +# + + +import math +import sys +import string +import time + +import wx -import math -import string -import sys -import time +from analogclockopts import ACCustomizationFrame -import wx -class AnalogClockWindow(wx.Window): - """A simple analog clock window""" +# self.clockStyle: +SHOW_QUARTERS_TICKS = 1 +SHOW_HOURS_TICKS = 2 +SHOW_MINUTES_TICKS = 4 +ROTATE_TICKS = 8 +SHOW_HOURS_HAND = 16 +SHOW_MINUTES_HAND = 32 +SHOW_SECONDS_HAND = 64 +SHOW_SHADOWS = 128 +OVERLAP_TICKS = 256 - TICKS_NONE = 0 - TICKS_SQUARE = 1 - TICKS_CIRCLE = 2 +# self.tickMarkHoursStyle and self.tickMarkMinutesStyle: +TICKS_NONE = 1 +TICKS_SQUARE = 2 +TICKS_CIRCLE = 4 +TICKS_POLY = 8 +TICKS_DECIMAL = 16 +TICKS_ROMAN = 32 + + +class AnalogClockWindow(wx.PyWindow): + """An analog clock window""" def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name="clock"): - + # Initialize the wxWindow... - wx.Window.__init__(self, parent, ID, pos, size, style, name) + wx.PyWindow.__init__(self, parent, ID, pos, size, style, name) + + # Initialize some variables and defaults... + self.clockStep = 1 + self.prefs_open = False + + self.tickShapeHours = self.tickShapeMinutes= [[0,0], + [1,-1], + [2,0], + [1,4]] + self.handHoursThickness = 5 + self.handHoursColour = (0, 0, 0) + + self.handMinutesThickness = 3 + self.handMinutesColour = (0, 0, 0) + + self.handSecondsThickness = 1 + self.handSecondsColour = (0, 0, 0) + + self.tickMarkHoursPen = wx.Pen((0, 0, 0), 1, wx.SOLID) + self.tickMarkHoursBrush = wx.Brush((0, 0, 0), wx.SOLID) + self.markSizeHour = 10 + self.tickMarkHoursFont = wx.Font(0, wx.SWISS, wx.NORMAL, wx.BOLD) + self.tickMarkHoursFont.SetPointSize(self.markSizeHour) + + self.tickMarkMinutesPen = wx.Pen((0, 0, 0), 1, wx.SOLID) + self.tickMarkMinutesBrush = wx.Brush((0, 0, 0), wx.SOLID) + self.markSizeMin = 6 + self.tickMarkMinutesFont = wx.Font(self.markSizeMin, wx.SWISS, wx.NORMAL, wx.BOLD) + + self.offM = 0 + + self.shadowPenColour = self.shadowBrushColour = (128,128,128) + + self.watchPen = None + self.watchBrush = None - # Initialize the default clock settings... - self.minuteMarks = 60 - self.hourMarks = 12 - self.tickMarksBrushC = self.GetForegroundColour() - self.tickMarksPenC = self.GetForegroundColour() - self.tickMarkStyle = self.TICKS_SQUARE + self.clockStyle = SHOW_HOURS_TICKS | SHOW_MINUTES_TICKS | SHOW_SHADOWS | ROTATE_TICKS + self.handsStyle = SHOW_SECONDS_HAND + self.tickMarkHoursStyle = TICKS_POLY + self.tickMarkMinutesStyle = TICKS_CIRCLE + + self.currentTime=None + + size = wx.Size(*size) + bestSize = self.GetBestSize() + size.x = max(size.x, bestSize.x) + size.y = max(size.y, bestSize.y) + self.SetSize(size) + # Make an initial bitmap for the face, it will be updated and # painted at the first EVT_SIZE event. W, H = size self.faceBitmap = wx.EmptyBitmap(max(W,1), max(H,1)) + + # Set event handlers... + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None) + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_TIMER, self.OnTimerExpire) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnQuit) + self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) + self.Bind(wx.EVT_RIGHT_UP, self.OnRightClick) # Initialize the timer that drives the update of the clock # face. Update every half second to ensure that there is at @@ -53,149 +129,671 @@ class AnalogClockWindow(wx.Window): self.timer = wx.Timer(self) self.timer.Start(500) - # Set event handlers... - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_TIMER, self.OnTimerExpire) - self.Bind(wx.EVT_WINDOW_DESTROY, self.OnQuit) + def DoGetBestSize(self): + return wx.Size(25,25) - def SetTickMarkStyle(self, style): - """ - Set the style of the marks around the edge of the clock. - Options are TICKS_NONE, TICKS_SQUARE, and TICKS_CIRCLE - """ - self.tickMarkStyle = style + + def OnPaint(self, event): + dc = wx.BufferedPaintDC(self) + if hasattr(self, 'coords'): + self._doDrawHands(dc, True) - def SetTickMarkColours(self, brushC, penC="BLACK"): - """ - Set the brush colour and optionally the pen colour of - the marks around the edge of the clock. - """ - self.tickMarksBrushC = brushC - self.tickMarksPenC = penC + def OnTimerExpire(self, event): + size = self.GetClientSize() + dc = wx.BufferedDC(wx.ClientDC(self), size) + self._doDrawHands(dc, True) - SetTickMarkColour = SetTickMarkColours + def OnQuit(self, event): + self.timer.Stop() + del self.timer - def SetHandsColour(self, c): - """An alias for SetForegroundColour""" - self.SetForegroundColour(c) # the hands just use the foreground colour + + def OnRightDown(self, event): + self.x = event.GetX() + self.y = event.GetY() + event.Skip() - # Using the current settings, render the points and line endings for the - # circle inside the specified device context. In this case, the DC is - # a memory based device context that will be blitted to the actual - # display DC inside the OnPaint() event handler. - def OnSize(self, event): - # The faceBitmap init is done here, to make sure the buffer is always - # the same size as the Window - size = self.GetClientSize() - self.faceBitmap = wx.EmptyBitmap(size.width, size.height) - self.DrawFace() + def OnRightClick(self, event): + # only do this part the first time so the events are only bound once + if not hasattr(self, "popupID1"): + self.popupID1 = wx.NewId() + self.popupID2 = wx.NewId() + self.Bind(wx.EVT_MENU, self.OnPopupOne, id=self.popupID1) + self.Bind(wx.EVT_MENU, self.OnPopupTwo, id=self.popupID2) + # make a menu + sm = wx.Menu() - def OnPaint(self, event): - self.DrawHands(wx.PaintDC(self)) + sm.Append(self.popupID1, "Customize...") + sm.Append(self.popupID2, "About...") + # If there already a setup window open, we must not appear... + if not self.prefs_open: + # Popup the menu. If an item is selected then its handler + # will be called before PopupMenu returns. + self.PopupMenu(sm, (self.x,self.y)) + sm.Destroy() - def OnQuit(self, event): - self.timer.Stop() - del self.timer + def OnPopupOne(self, event): + self.prefs_open=True + frame = ACCustomizationFrame(self, -1, "AnalogClock Preferences") + frame.Show(True) - def OnTimerExpire(self, event): - self.DrawHands(wx.ClientDC(self)) + def OnPopupTwo(self, event): + dlg = wx.MessageDialog(self, "AnalogClockWindow\n\nby Several folks on wxPython-users\nwith enhancements from E. A. Tacão", + 'About', wx.OK | wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() - def DrawHands(self, drawDC): - # Start by drawing the face bitmap - drawDC.DrawBitmap(self.faceBitmap, (0,0)) - currentTime = time.localtime(time.time()) - hour, minutes, seconds = currentTime[3:6] + def OnSize(self, event): + # The faceBitmap init is done here, to make sure the buffer is always + # the same size as the Window + size = self.GetClientSize() + if size.x < 1 or size.y < 1: + return + + self.faceBitmap = wx.EmptyBitmap(size.width, size.height) + + # Update drawing coordinates... + new_dim = size.Get() + if not hasattr(self,"dim"): + self.dim = new_dim + + x,y=[0,1] + self.scale = min([float(new_dim[x]) / self.dim[x], + float(new_dim[y]) / self.dim[y]]) + + self.centerX = self.faceBitmap.GetWidth() / 2 + self.centerY = self.faceBitmap.GetHeight() / 2 - W,H = self.faceBitmap.GetWidth(), self.faceBitmap.GetHeight() - centerX = W / 2 - centerY = H / 2 + self.shadowDistance = 2 * self.scale - radius = min(centerX, centerY) - hour += minutes / 60.0 # added so the hour hand moves continuously - x, y = self.point(hour, 12, (radius * .65)) - hourX, hourY = (x + centerX), (centerY - y) - x, y = self.point(minutes, 60, (radius * .85)) - minutesX, minutesY = (x + centerX), (centerY - y) - x, y = self.point(seconds, 60, (radius * .85)) - secondsX, secondsY = (x + centerX), (centerY - y) + self.radius_watch = min(self.centerX, self.centerY) - # Draw the hour hand... - drawDC.SetPen(wx.Pen(self.GetForegroundColour(), 5, wx.SOLID)) - drawDC.DrawLine((centerX, centerY), (hourX, hourY)) + self._doDrawFace() + - # Draw the minutes hand... - drawDC.SetPen(wx.Pen(self.GetForegroundColour(), 3, wx.SOLID)) - drawDC.DrawLine((centerX, centerY), (minutesX, minutesY)) - # Draw the seconds hand... - drawDC.SetPen(wx.Pen(self.GetForegroundColour(), 1, wx.SOLID)) - drawDC.DrawLine((centerX, centerY), (secondsX, secondsY)) + def _doDrawHands(self, drawDC, force=0): + currentTime = list(time.localtime(time.time())[3:6]) + if not (self.handsStyle & SHOW_SECONDS_HAND): + currentTime[2]=-1 - # Draw the specified set of line marks inside the clock face for the - # hours or minutes... - def DrawFace(self): + if not (force or currentTime != self.currentTime): + return + self.currentTime = currentTime + hour, minutes, seconds = currentTime + + # Start by drawing the face bitmap + drawDC.DrawBitmap(self.faceBitmap, 0,0) + + + # NOTE: All this hand drawing code below should be refactored into a helper function. + + + # Draw hours hand shadow + mStep = 6 * self.clockStep + angle = hour * 30 + if angle > 360: + angle = angle - 360 + angle = angle + round(minutes/(mStep*2)) * mStep + + x,y,f = self._getCoords("hand_hours", angle) + + if f and self.clockStyle & SHOW_SHADOWS: + drawDC.SetPen(wx.Pen(self.shadowPenColour, + int(self.handHoursThickness * self.scale), + wx.SOLID)) + drawDC.DrawLine(self.centerX + self.shadowDistance, + self.centerY + self.shadowDistance, + x + self.shadowDistance, + y + self.shadowDistance) + + # Draw minutes hand shadow + angle = minutes * 6 + x,y,f = self._getCoords("hand_minutes", angle) + + if f and self.clockStyle & SHOW_SHADOWS: + drawDC.SetPen(wx.Pen(self.shadowPenColour, + int(self.handMinutesThickness * self.scale), + wx.SOLID)) + drawDC.DrawLine(self.centerX + self.shadowDistance, + self.centerY + self.shadowDistance, + x + self.shadowDistance, + y + self.shadowDistance) + + # Draw seconds hand shadow if required + if seconds >= 0: + angle = seconds * 6 + x,y,f = self._getCoords("hand_seconds", angle) + + if f and self.clockStyle & SHOW_SHADOWS: + drawDC.SetPen(wx.Pen(self.shadowPenColour, + int(self.handSecondsThickness * self.scale), + wx.SOLID)) + drawDC.DrawLine(self.centerX + self.shadowDistance, + self.centerY + self.shadowDistance, + x + self.shadowDistance, + y + self.shadowDistance) + + + # Draw hours hand + angle = hour * 30 + if angle > 360: + angle = angle - 360 + angle = angle + round(minutes/(mStep*2)) * mStep + + x,y,f = self._getCoords("hand_hours", angle) + + if f: + drawDC.SetPen(wx.Pen(self.handHoursColour, + int(self.handHoursThickness * self.scale), + wx.SOLID)) + drawDC.DrawLine(self.centerX, self.centerY, x, y) + + # Draw minutes hand + angle = minutes * 6 + x,y,f = self._getCoords("hand_minutes", angle) + + if f: + drawDC.SetPen(wx.Pen(self.handMinutesColour, + int(self.handMinutesThickness * self.scale), + wx.SOLID)) + drawDC.DrawLine(self.centerX, self.centerY, x, y) + + # Draw seconds hand if required + if seconds >= 0: + angle = seconds * 6 + x,y,f = self._getCoords("hand_seconds", angle) + if f: + drawDC.SetPen(wx.Pen(self.handSecondsColour, + int(self.handSecondsThickness * self.scale), + wx.SOLID)) + drawDC.DrawLine(self.centerX, self.centerY, x, y) + + + + def _doDrawFace(self): backgroundBrush = wx.Brush(self.GetBackgroundColour(), wx.SOLID) drawDC = wx.MemoryDC() drawDC.SelectObject(self.faceBitmap) drawDC.SetBackground(backgroundBrush) drawDC.Clear() - W,H = self.faceBitmap.GetWidth(), self.faceBitmap.GetHeight() - centerX = W / 2 - centerY = H / 2 + self.handHoursLength = 0.65 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC)) + self.handMinutesLength = 0.85 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC)) + self.handSecondsLength = 0.85 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC)) + + self.radius_ticks_hours = self.radius_watch - self.shadowDistance - self._getMarkMaxSize("ticks_hours", drawDC) + self.radius_ticks_minutes = self.radius_ticks_hours + + self._calcSteps() + + # Draw the watch... + self._drawWatch(drawDC) # Draw the marks for hours and minutes... - self.DrawTimeMarks(drawDC, self.minuteMarks, centerX, centerY, 4) - self.DrawTimeMarks(drawDC, self.hourMarks, centerX, centerY, 9) + circle = 360 + mStep = 6 * self.clockStep + + if self.clockStyle & SHOW_SHADOWS: + for i in range(0, circle, mStep): + for t in self.coords.keys(): + if t.find("ticks") > -1: + x,y,f = self._getCoords(t, i) + if f: + self._doDrawTickMark(i, drawDC, t, + x + self.shadowDistance, + y + self.shadowDistance, + True) + + for i in range(0, circle, mStep): + for t in self.coords.keys(): + if t.find("ticks") > -1: + x,y,f = self._getCoords(t, i) + if f: + self._doDrawTickMark(i, drawDC, t, x, y) + + + + def _doDrawTickMark(self, angle, drawDC, tipo, x, y, is_a_shadow=None): + opts = {"ticks_hours": [self.tickMarkHoursPen, self.tickMarkHoursBrush, self.markSizeHour, self.tickMarkHoursStyle], + "ticks_quarters": [self.tickMarkHoursPen, self.tickMarkHoursBrush, self.markSizeHour, self.tickMarkHoursStyle], + "ticks_minutes": [self.tickMarkMinutesPen, self.tickMarkMinutesBrush, self.markSizeMin, self.tickMarkMinutesStyle]} + + pen, brush, size, style = opts[tipo]; + size = size * self.scale + + if is_a_shadow: + drawDC.SetPen(wx.Pen(self.shadowPenColour, 1, wx.SOLID)) + drawDC.SetBrush(wx.Brush(self.shadowBrushColour, wx.SOLID)) + drawDC.SetTextForeground(self.shadowBrushColour) + else: + drawDC.SetPen(pen) + drawDC.SetBrush(brush) + drawDC.SetTextForeground(brush.GetColour()) + + if style & TICKS_CIRCLE: + x, y = self._center2corner(x, y, tipo) + drawDC.DrawEllipse(x, y, size, size) + + elif style & TICKS_SQUARE: + x, y = self._center2corner(x, y, tipo) + drawDC.DrawRectangle(x, y, size, size) + + elif (style & TICKS_DECIMAL) or (style & TICKS_ROMAN): + self._draw_rotate_text(drawDC, x, y, tipo, angle) + + elif style & TICKS_POLY: + self._draw_rotate_polygon(drawDC, x, y, tipo, angle) + + + def _draw_rotate_text(self, drawDC, x, y, tipo, angle): + text = self._build_text(angle, tipo) + lX, lY = self._center2corner(x, y, tipo, drawDC) + lX = lX * len(text) + angle = 360 - angle + + if self.clockStyle & ROTATE_TICKS: + radiansPerDegree = math.pi / 180 + x = int(x - + ((math.cos((angle) * radiansPerDegree)*lX) + + (math.sin((angle) * radiansPerDegree)*lY))) + y = int(y - + ((math.cos((angle) * radiansPerDegree)*lY) - + (math.sin((angle) * radiansPerDegree)*lX))) + drawDC.DrawRotatedText(text, x,y, angle) + + else: + x = x - lX + y = y - lY + drawDC.DrawText(text, x, y) + + + def _draw_rotate_polygon(self, drawDC, x, y, tipo, angle): + if tipo=="ticks_quarters": + tipo="ticks_hours" + + # Add to empty list to prevent system-wide hard freezes under XP... + points = {"ticks_hours":self.tickShapeHours+[], "ticks_minutes":self.tickShapeMinutes+[]}[tipo] + size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo] + + maxX = max(map(lambda x:x[0],points)) + minX = min(map(lambda x:x[0],points)) + maxY = max(map(lambda x:x[0],points)) + minY = min(map(lambda x:x[0],points)) + + maxB = abs(max(maxX, maxY)); + f = size / maxB + + orgX = (maxX - minX) / 2. + orgY = (maxY - minY) / 2. + + radiansPerDegree = math.pi / 180 + scaledX = x + scaledY = y + + for z in range(0, len(points)): + x,y = points[z] + x = x * f - orgX * f + y = y * f - orgY * f + if self.clockStyle & ROTATE_TICKS: + m,t = self._rect2pol(x,y) + t = t + angle + x,y = self._pol2rect(m,t) + x = x + scaledX + y = y + scaledY + points[z] = [int(x), int(y)] + + drawDC.DrawPolygon(points) + + + def _pol2rect(self, r, w, deg=1): # radian if deg=0; degree if deg=1 + if deg: + w = math.pi * w / 180.0 + return r * math.cos(w), r * math.sin(w) + + + def _rect2pol(self, x, y, deg=1): # radian if deg=0; degree if deg=1 + if deg: + return math.hypot(x, y), 180.0 * math.atan2(y, x) / math.pi + else: + return math.hypot(x, y), math.atan2(y, x) + + + def _center2corner(self, x, y, tipo, drawDC=None): + if tipo == "ticks_quarters": + tipo = "ticks_hours" + + style = {"ticks_hours":self.tickMarkHoursStyle, "ticks_minutes":self.tickMarkMinutesStyle}[tipo] + size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo] + + if style & TICKS_DECIMAL or style & TICKS_ROMAN: + font = {"ticks_hours":self.tickMarkHoursFont, "ticks_minutes":self.tickMarkMinutesFont}[tipo] + font.SetPointSize(int(size)); + drawDC.SetFont(font) + lX = drawDC.GetCharWidth() / 2. + lY = drawDC.GetCharHeight() / 2. + x = lX + y = lY + else: + size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo] + x=x-size/2.;y=y-size/2. + return x, y + + + def _build_text(self, angle, tipo): + if tipo == "ticks_quarters": + tipo = "ticks_hours" + a = angle + if a <= 0: + a = a + 360 + divider = {"ticks_hours":30,"ticks_minutes":6}[tipo] + a = int(a / divider) + + style = {"ticks_hours":self.tickMarkHoursStyle," ticks_minutes":self.tickMarkMinutesStyle}[tipo] + if style & TICKS_ROMAN: + text=["I","II","III","IV","V","VI","VII","VIII","IX","X", \ + "XI","XII","XIII","XIV","XV","XVI","XVII","XVIII","XIX","XX", \ + "XXI","XXII","XXIII","XXIV","XXV","XXVI","XXVII","XXVIII","XXIX","XXX", \ + "XXXI","XXXII","XXXIII","XXXIV","XXXV","XXXVI","XXXVII","XXXVIII","XXXIX","XL", \ + "XLI","XLII","XLIII","XLIV","XLV","XLVI","XLVII","XLVIII","XLIX","L", \ + "LI","LII","LIII","LIV","LV","LVI","LVII","LVIII","LIX","LX"][a-1] + else: + text = "%s" % a + + return text + + + def _getMarkMaxSize(self, tipo, drawDC=None): + if tipo == "ticks_quarters": + tipo = "ticks_hours" + + style = {"ticks_hours":self.tickMarkHoursStyle, "ticks_minutes":self.tickMarkMinutesStyle}[tipo] + size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo] + + if style & TICKS_DECIMAL or style & TICKS_ROMAN: + lX = 2 * drawDC.GetCharWidth() + lY = drawDC.GetCharHeight() + size = math.sqrt(lX**2 + lY**2) * self.scale + else: + size=math.sqrt(2) * size + + return size + + + def _drawWatch(self, drawDC): + # Draw the watch... + if self.watchPen or self.watchBrush: + if self.watchPen: + drawDC.SetPen(self.watchPen) + if self.watchBrush: + drawDC.SetBrush(self.watchBrush) + else: + drawDC.SetBrush(wx.Brush(self.GetBackgroundColour(), wx.SOLID)) + drawDC.DrawCircle(self.centerX, self.centerY, self.radius_watch) + + + def _calcSteps(self): + # Calcule todos os pontos para: + # - marcas de horas + # - marcas de minutos + # - ponteiro de horas + # - ponteiro de minutos + # - ponteiro de segundos + + circle = 360 + mStep = 6 * self.clockStep # Step in degrees... + + vq = 90 * (self.clockStyle & SHOW_QUARTERS_TICKS) / SHOW_QUARTERS_TICKS + vh = 30 * (self.clockStyle & SHOW_HOURS_TICKS) / SHOW_HOURS_TICKS + vm = 1 * (self.clockStyle & SHOW_MINUTES_TICKS) / SHOW_MINUTES_TICKS + + coords = {"ticks_quarters": [self.radius_ticks_hours, 60,vq,{}], + "ticks_hours": [self.radius_ticks_hours, 60,vh,{}], + "ticks_minutes": [self.radius_ticks_minutes,60,vm,{}], + "hand_hours": [self.handHoursLength, 60,1, {}], + "hand_minutes": [self.handMinutesLength, 60,1, {}], + "hand_seconds": [self.handSecondsLength, 60,1, {}]} + + radiansPerDegree = math.pi / 180 + for t in coords.keys(): + for i in range(0, circle+mStep, mStep): + radius = coords[t][0] + if t == "ticks_minutes": + radius = radius - self.offM + step_angle = 360. / coords[t][1] + pre = coords[t][2] + x = self.centerX + radius * math.sin(i * radiansPerDegree) + y = self.centerY + radius * math.cos(i * radiansPerDegree) + f = (pre and (i/step_angle == int(i/step_angle)) and (float(i)/pre == int(i/pre))) + coords[t][3][i] = [x,y,f] + + if not self.clockStyle & OVERLAP_TICKS: + for i in range(0, circle + mStep, mStep): + f=coords["ticks_minutes"][3][i][2] + if f and \ + (coords["ticks_hours"][3].get(i,[0,0,0])[2] or coords["ticks_quarters"][3].get(i,[0,0,0])[2]): + f=False + coords["ticks_minutes"][3][i][2]=f + + self.coords = coords + + + def _getCoords(self, tipo, angle): + # Returns coords and 'use flag' based on current angle... + k = 360 - (angle + 180) + if k <= 0: + k = k + 360 + return self.coords[tipo][3][k] + + +# ----------------------------------------------------- +# + def SetTickShapes(self, tsh, tsm=None): + """ + tsh, tsm: [[x0,y0], [x1,y1], ... [xn,yn]] - def DrawTimeMarks(self, drawDC, markCount, centerX, centerY, markSize): - for i in range(markCount): - x, y = self.point(i + 1, markCount, min(centerX,centerY) - 16) - scaledX = x + centerX - markSize/2 - scaledY = centerY - y - markSize/2 + Sets lists of lists of points to be used as polygon shapes + when using the TICKS_POLY style. If tsm is ommitted, + we'll use tsh for both shapes. + """ - drawDC.SetBrush(wx.Brush(self.tickMarksBrushC, wx.SOLID)) - drawDC.SetPen(wx.Pen(self.tickMarksPenC, 1, wx.SOLID)) + if not tsm: + tsm=tsh - if self.tickMarkStyle != self.TICKS_NONE: - if self.tickMarkStyle == self.TICKS_CIRCLE: - drawDC.DrawEllipse((scaledX - 2, scaledY), (markSize, markSize)) - else: - drawDC.DrawRectangle((scaledX - 3, scaledY), (markSize, markSize)) + self.tickShapeHours = tsh + self.tickShapeMinutes = tsm - def point(self, tick, range, radius): - angle = tick * (360.0 / range) - radiansPerDegree = math.pi / 180 - pointX = int(round(radius * math.sin(angle * radiansPerDegree))) - pointY = int(round(radius * math.cos(angle * radiansPerDegree))) - return wx.Point(pointX, pointY) + def SetHandWeights(self, h=None, m=None, s=None): + """ + h, m, s: value + + Sets thickness of hands. + """ + + if h: + self.handHoursThickness = h + if m: + self.handMinutesThickness = m + if s: + self.handSecondsThickness = s + + + def SetHandColours(self, h=None, m=None, s=None): + """ + h, m, s: wx.Colour + + Sets colours of hands. If m and s are ommitted, + we'll use h for all. + """ + + if h and not m and not s: + m=h + s=h + + if h: + self.handHoursColour = h + if m: + self.handMinutesColour = m + if s: + self.handSecondsColour = s + + + def SetTickColours(self, h=None, m=None): + """ + h, m: wx.Colour + + Sets colours of ticks. If m is ommitted, + we'll use h for both. + """ + + if not m: + m=h + + if h: + self.tickMarkHoursPen = wx.Pen(h, 1, wx.SOLID) + self.tickMarkHoursBrush = wx.Brush(h, wx.SOLID) + + if m: + self.tickMarkMinutesPen = wx.Pen(m, 1, wx.SOLID) + self.tickMarkMinutesBrush = wx.Brush(m, wx.SOLID) + + + def SetTickSizes(self, h=None, m=None): + """ + h, m: value + + Sizes for tick marks. + """ + + if h: + self.markSizeHour = h + if m: + self.markSizeMin = m + + + def SetTickFonts(self, h=None, m=None): + """ + h, m: wx.Font + + Fonts for tick marks when using TICKS_DECIMAL or TICKS_ROMAN style. + If m is ommitted, we'll use h for both. + """ + if not m: + m=h + if h: + self.tickMarkHoursFont = h + self.tickMarkHoursFont.SetPointSize(self.markSizeHour) + if m: + self.tickMarkMinutesFont = m + self.tickMarkMinutesFont.SetPointSize(self.markSizeMin) + + + def SetMinutesOffset(self, o): + """ + s = value + + Sets the distance between tick marks for hours and minutes. + """ + self.offM = o + + + def SetShadowColour(self, s): + """ + s = wx.Colour or (r,g,b) tuple. + + Sets the colour to be used to draw shadows. + """ + + self.shadowPenColour = self.shadowBrushColour = s + + + def SetWatchPenBrush(self, p=None, b=None): + """ + p = wx.Pen; b = wx.Brush + + Set the pen and brush for the watch. + """ + + if p: + self.watchPen = p + if b: + self.watchBrush = b + + + def SetClockStyle(self, style): + """ + Set the clock style, acording to these options: + + ==================== ================================ + SHOW_QUARTERS_TICKS Show marks for hours 3, 6, 9, 12 + SHOW_HOURS_TICKS Show marks for all hours + SHOW_MINUTES_TICKS Show marks for minutes + + SHOW_HOURS_HAND Show hours hand + SHOW_MINUTES_HAND Show minutes hand + SHOW_SECONDS_HAND Show seconds hand + + SHOW_SHADOWS Show hands and marks shadows + + ROTATE_TICKS Align tick marks to watch + OVERLAP_TICKS Draw tick marks for minutes even + when they match the hours marks. + ==================== ================================ + """ + + self.clockStyle = style + + + def SetTickStyles(self, h=None, m=None): + """ + Set the ticks styles, acording to the options below. + + ================= ===================================== + TICKS_NONE Don't show tick marks. + TICKS_SQUARE Use squares as tick marks. + TICKS_CIRCLE Use circles as tick marks. + TICKS_POLY Use a polygon as tick marks. The + polygon must be passed using + SetTickShapes, otherwise the default + polygon will be used. + TICKS_DECIMAL Use decimal numbers. + TICKS_ROMAN Use Roman numbers. + ================= ===================================== + """ + + if h: + self.tickMarkHoursStyle = h + if m: + self.tickMarkMinutesStyle = m +# +# ----------------------------------------------------- if __name__ == "__main__": + print wx.VERSION_STRING class App(wx.App): def OnInit(self): - frame = wx.Frame(None, -1, "AnalogClockWindow Test", size=(375,375)) + frame = wx.Frame(None, -1, "AnalogClockWindow", size=(375,375)) clock = AnalogClockWindow(frame) - clock.SetTickMarkColours("RED") - clock.SetHandsColour("WHITE") - clock.SetBackgroundColour("BLUE") + + # Settings below are used by default... + #clock.SetClockStyle(SHOW_HOURS_TICKS|SHOW_MINUTES_TICKS|SHOW_SHADOWS|ROTATE_TICKS) + #clock.SetTickStyles(TICKS_POLY, TICKS_CIRCLE) frame.Centre(wx.BOTH) frame.Show(True) @@ -206,4 +804,6 @@ if __name__ == "__main__": theApp.MainLoop() - +# +## +### eof