git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39808 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			986 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			986 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # AnalogClock's base classes
 | |
| #   E. A. Tacao <e.a.tacao |at| estadao.com.br>
 | |
| #   http://j.domaindlx.com/elements28/wxpython/
 | |
| #   15 Fev 2006, 22:00 GMT-03:00
 | |
| # Distributed under the wxWidgets license.
 | |
| 
 | |
| from time import strftime, localtime
 | |
| import math
 | |
| import wx
 | |
| 
 | |
| from styles import *
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| _targets = [HOUR, MINUTE, SECOND]
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class Element:
 | |
|     """Base class for face, hands and tick marks."""
 | |
| 
 | |
|     def __init__(self, idx=0, pos=None, size=None, offset=0, clocksize=None,
 | |
|                  scale=1, rotate=False, kind=""):
 | |
| 
 | |
|         self.idx = idx
 | |
|         self.pos = pos
 | |
|         self.size = size
 | |
|         self.offset = offset
 | |
|         self.clocksize = clocksize
 | |
|         self.scale = scale
 | |
|         self.rotate = rotate
 | |
|         self.kind = kind
 | |
| 
 | |
|         self.text = None
 | |
|         self.angfac = [6, 30][self.kind == "hours"]
 | |
| 
 | |
| 
 | |
|     def _pol2rect(self, m, t):
 | |
|         return m * math.cos(math.radians(t)), m * math.sin(math.radians(t))
 | |
| 
 | |
| 
 | |
|     def _rect2pol(self, x, y):
 | |
|         return math.hypot(x, y), math.degrees(math.atan2(y, x))
 | |
| 
 | |
| 
 | |
|     def DrawRotated(self, dc, offset=0):
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def DrawStraight(self, dc, offset=0):
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc, offset=0):
 | |
|         if self.rotate:
 | |
|             self.DrawRotated(dc, offset)
 | |
|         else:
 | |
|             self.DrawStraight(dc, offset)
 | |
| 
 | |
| 
 | |
|     def RecalcCoords(self, clocksize, centre, scale):
 | |
|         pass
 | |
|         
 | |
|         
 | |
|     def GetSize(self):
 | |
|         return self.size
 | |
| 
 | |
| 
 | |
|     def GetOffset(self):
 | |
|         return self.offset
 | |
| 
 | |
| 
 | |
|     def GetIsRotated(self, rotate):
 | |
|         return self.rotate
 | |
| 
 | |
| 
 | |
|     def GetMaxSize(self, scale=1):
 | |
|         return self.size * scale
 | |
|         
 | |
|         
 | |
|     def GetScale(self):
 | |
|         return self.scale
 | |
| 
 | |
| 
 | |
|     def SetIsRotated(self, rotate):
 | |
|         self.rotate = rotate
 | |
| 
 | |
| 
 | |
|     def GetMaxSize(self, scale=1):
 | |
|         return self.size * scale
 | |
| 
 | |
| 
 | |
|     def GetPolygon(self):
 | |
|         return self.polygon
 | |
| 
 | |
| 
 | |
|     def SetPosition(self, pos):
 | |
|         self.pos = pos
 | |
| 
 | |
| 
 | |
|     def SetSize(self, size):
 | |
|         self.size = size
 | |
| 
 | |
| 
 | |
|     def SetOffset(self, offset):
 | |
|         self.offset = offset
 | |
| 
 | |
| 
 | |
|     def SetClockSize(self, clocksize):
 | |
|         self.clocksize = clocksize
 | |
| 
 | |
| 
 | |
|     def SetScale(self, scale):
 | |
|         self.scale = scale
 | |
| 
 | |
| 
 | |
|     def SetIsRotated(self, rotate):
 | |
|         self.rotate = rotate
 | |
| 
 | |
| 
 | |
|     def SetPolygon(self, polygon):
 | |
|         self.polygon = polygon
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class ElementWithDyer(Element):
 | |
|     """Base class for clock face and hands."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         self.dyer = kwargs.pop("dyer", Dyer())
 | |
|         Element.__init__(self, **kwargs)
 | |
| 
 | |
| 
 | |
|     def GetFillColour(self):
 | |
|         return self.dyer.GetFillColour()
 | |
| 
 | |
| 
 | |
|     def GetBorderColour(self):
 | |
|         return self.dyer.GetBorderColour()
 | |
| 
 | |
| 
 | |
|     def GetBorderWidth(self):
 | |
|         return self.dyer.GetBorderWidth()
 | |
| 
 | |
| 
 | |
|     def GetShadowColour(self):
 | |
|         return self.dyer.GetShadowColour()
 | |
| 
 | |
|         
 | |
|     def SetFillColour(self, colour):
 | |
|         self.dyer.SetFillColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetBorderColour(self, colour):
 | |
|         self.dyer.SetBorderColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetBorderWidth(self, width):
 | |
|         self.dyer.SetBorderWidth(width)
 | |
|         
 | |
|         
 | |
|     def SetShadowColour(self, colour):
 | |
|         self.dyer.SetShadowColour(colour)
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class Face(ElementWithDyer):
 | |
|     """Holds info about the clock face."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         ElementWithDyer.__init__(self, **kwargs)
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc):
 | |
|         self.dyer.Select(dc)
 | |
|         dc.DrawCircle(self.pos.x, self.pos.y, self.radius)
 | |
| 
 | |
| 
 | |
|     def RecalcCoords(self, clocksize, centre, scale):
 | |
|         self.radius = min(clocksize.Get()) / 2. - self.dyer.width / 2.
 | |
|         self.pos = centre
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class Hand(ElementWithDyer):
 | |
|     """Holds info about a clock hand."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         self.lenfac = kwargs.pop("lenfac")
 | |
|         ElementWithDyer.__init__(self, **kwargs)
 | |
| 
 | |
|         self.SetPolygon([[-1, 0], [0, -1], [1, 0], [0, 4]])
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc, end, offset=0):
 | |
|         radius, centre, r = end
 | |
|         angle = math.degrees(r)
 | |
|         polygon = self.polygon[:]
 | |
|         vscale = radius / max([y for x, y in polygon])
 | |
| 
 | |
|         for i, (x, y) in enumerate(polygon):
 | |
|             x *= self.scale * self.size
 | |
|             y *= vscale * self.lenfac
 | |
|             m, t = self._rect2pol(x, y)
 | |
|             polygon[i] = self._pol2rect(m, t - angle)
 | |
| 
 | |
|         dc.DrawPolygon(polygon, centre.x + offset, centre.y + offset)
 | |
| 
 | |
| 
 | |
|     def RecalcCoords(self, clocksize, centre, scale):
 | |
|         self.pos = centre
 | |
|         self.scale = scale
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickSquare(Element):
 | |
|     """Holds info about a tick mark."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         Element.__init__(self, **kwargs)
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc, offset=0):
 | |
|         width = height = self.size * self.scale
 | |
|         x = self.pos.x - width / 2.
 | |
|         y = self.pos.y - height / 2.
 | |
| 
 | |
|         dc.DrawRectangle(x + offset, y + offset, width, height)
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickCircle(Element):
 | |
|     """Holds info about a tick mark."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         Element.__init__(self, **kwargs)
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc, offset=0):
 | |
|         radius = self.size * self.scale / 2.
 | |
|         x = self.pos.x
 | |
|         y = self.pos.y
 | |
| 
 | |
|         dc.DrawCircle(x + offset, y + offset, radius)
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickPoly(Element):
 | |
|     """Holds info about a tick mark."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         Element.__init__(self, **kwargs)
 | |
| 
 | |
|         self.SetPolygon([[0, 1], [1, 0], [2, 1], [1, 5]])
 | |
| 
 | |
| 
 | |
|     def _calcPolygon(self):
 | |
|         width = max([x for x, y in self.polygon])
 | |
|         height = max([y for x, y in self.polygon])
 | |
|         tscale = self.size / max(width, height) * self.scale
 | |
|         polygon = [(x * tscale, y * tscale) for x, y in self.polygon]
 | |
| 
 | |
|         width = max([x for x, y in polygon])
 | |
|         height = max([y for x, y in polygon])
 | |
|         
 | |
|         return polygon, width, height
 | |
| 
 | |
| 
 | |
|     def DrawStraight(self, dc, offset=0):
 | |
|         polygon, width, height = self._calcPolygon()
 | |
| 
 | |
|         x = self.pos.x - width / 2.
 | |
|         y = self.pos.y - height / 2.
 | |
| 
 | |
|         dc.DrawPolygon(polygon, x + offset, y + offset)
 | |
| 
 | |
| 
 | |
|     def DrawRotated(self, dc, offset=0):
 | |
|         polygon, width, height = self._calcPolygon()
 | |
| 
 | |
|         angle = 360 - self.angfac * (self.idx + 1)
 | |
|         r = math.radians(angle)
 | |
| 
 | |
|         for i in range(len(polygon)):
 | |
|             m, t = self._rect2pol(*polygon[i])
 | |
|             t -= angle
 | |
|             polygon[i] = self._pol2rect(m, t)
 | |
| 
 | |
|         x = self.pos.x - math.cos(r) * width / 2. - math.sin(r) * height / 2.
 | |
|         y = self.pos.y - math.cos(r) * height / 2. + math.sin(r) * width / 2.
 | |
| 
 | |
|         dc.DrawPolygon(polygon, x + offset, y + offset)
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickDecimal(Element):
 | |
|     """Holds info about a tick mark."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         Element.__init__(self, **kwargs)
 | |
| 
 | |
|         self.text = "%s" % (self.idx + 1)
 | |
| 
 | |
| 
 | |
|     def DrawStraight(self, dc, offset=0):
 | |
|         width, height = dc.GetTextExtent(self.text)
 | |
| 
 | |
|         x = self.pos.x - width / 2.
 | |
|         y = self.pos.y - height / 2.
 | |
| 
 | |
|         dc.DrawText(self.text, x + offset, y + offset)
 | |
| 
 | |
| 
 | |
|     def DrawRotated(self, dc, offset=0):
 | |
|         width, height = dc.GetTextExtent(self.text)
 | |
| 
 | |
|         angle = 360 - self.angfac * (self.idx + 1)
 | |
|         r = math.radians(angle)
 | |
| 
 | |
|         x = self.pos.x - math.cos(r) * width / 2. - math.sin(r) * height / 2.
 | |
|         y = self.pos.y - math.cos(r) * height / 2. + math.sin(r) * width / 2.
 | |
| 
 | |
|         dc.DrawRotatedText(self.text, x + offset, y + offset, angle)
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickRoman(TickDecimal):
 | |
|     """Holds info about a tick mark."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         TickDecimal.__init__(self, **kwargs)
 | |
| 
 | |
|         self.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"][self.idx]
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickBinary(TickDecimal):
 | |
|     """Holds info about a tick mark."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         TickDecimal.__init__(self, **kwargs)
 | |
| 
 | |
|         def d2b(n, b=""):
 | |
|             while n > 0:
 | |
|                 b = str(n % 2) + b; n = n >> 1
 | |
|             return b.zfill(4)
 | |
| 
 | |
|         self.text = d2b(self.idx + 1)
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickHex(TickDecimal):
 | |
|     """Holds info about a tick mark."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         TickDecimal.__init__(self, **kwargs)
 | |
| 
 | |
|         self.text = hex(self.idx + 1)[2:].upper()
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickNone(Element):
 | |
|     """Holds info about a tick mark."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         Element.__init__(self, **kwargs)
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc, offset=0):
 | |
|         pass
 | |
|         
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class Dyer:
 | |
|     """Stores info about colours and borders of clock Elements."""
 | |
| 
 | |
|     def __init__(self, border=None, width=0, fill=None, shadow=None):
 | |
|         """
 | |
|         self.border (wx.Colour)  border colour
 | |
|         self.width  (int)        border width
 | |
|         self.fill   (wx.Colour)  fill colour
 | |
|         self.shadow (wx.Colour)  shadow colour
 | |
|         """
 | |
| 
 | |
|         self.border = border or \
 | |
|                       wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
 | |
|         self.fill   = fill or \
 | |
|                       wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
 | |
|         self.shadow = shadow or \
 | |
|                       wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW)
 | |
|         self.width  = width
 | |
| 
 | |
| 
 | |
|     def Select(self, dc, shadow=False):
 | |
|         """Selects the current settings into the dc."""
 | |
| 
 | |
|         if not shadow:
 | |
|             dc.SetPen(wx.Pen(self.border, self.width, wx.SOLID))
 | |
|             dc.SetBrush(wx.Brush(self.fill, wx.SOLID))
 | |
|             dc.SetTextForeground(self.fill)
 | |
|         else:
 | |
|             dc.SetPen(wx.Pen(self.shadow, self.width, wx.SOLID))
 | |
|             dc.SetBrush(wx.Brush(self.shadow, wx.SOLID))
 | |
|             dc.SetTextForeground(self.shadow)
 | |
| 
 | |
| 
 | |
|     def GetFillColour(self):
 | |
|         return self.fill
 | |
| 
 | |
| 
 | |
|     def GetBorderColour(self):
 | |
|         return self.border
 | |
| 
 | |
| 
 | |
|     def GetBorderWidth(self):
 | |
|         return self.width
 | |
| 
 | |
| 
 | |
|     def GetShadowColour(self):
 | |
|         return self.shadow
 | |
| 
 | |
| 
 | |
|     def SetFillColour(self, colour):
 | |
|         self.fill = colour
 | |
| 
 | |
| 
 | |
|     def SetBorderColour(self, colour):
 | |
|         self.border = colour
 | |
| 
 | |
| 
 | |
|     def SetBorderWidth(self, width):
 | |
|         self.width = width
 | |
| 
 | |
| 
 | |
|     def SetShadowColour(self, colour):
 | |
|         self.shadow = colour
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class HandSet:
 | |
|     """Manages the set of hands."""
 | |
| 
 | |
|     def __init__(self, parent, h, m, s):
 | |
|         self.parent = parent
 | |
| 
 | |
|         self.hands = [h, m, s]
 | |
|         self.radius = 1
 | |
|         self.centre = wx.Point(1, 1)
 | |
| 
 | |
| 
 | |
|     def _draw(self, dc, shadow=False):
 | |
|         ends = [int(x) for x in strftime("%I %M %S", localtime()).split()]
 | |
| 
 | |
|         flags = [self.parent.clockStyle & flag \
 | |
|                  for flag in self.parent.allHandStyles]
 | |
| 
 | |
|         a_hand = self.hands[0]
 | |
| 
 | |
|         if shadow:
 | |
|             offset = self.parent.shadowOffset * a_hand.GetScale()
 | |
|         else:
 | |
|             offset = 0
 | |
| 
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             # Is this hand supposed to be drawn?
 | |
|             if flags[i]:
 | |
|                 idx = ends[i]
 | |
|                 # Is this the hours hand?
 | |
|                 if i == 0:
 | |
|                     idx = idx * 5 + ends[1] / 12 - 1
 | |
|                 # else prevent exceptions on leap seconds
 | |
|                 elif idx <= 0 or idx > 60:
 | |
|                     idx = 59
 | |
|                 # and adjust idx offset for minutes and non-leap seconds 
 | |
|                 else:
 | |
|                     idx = idx - 1
 | |
|                 angle = math.radians(180 - 6 * (idx + 1))
 | |
| 
 | |
|                 hand.dyer.Select(dc, shadow)
 | |
|                 hand.Draw(dc, (self.radius, self.centre, angle), offset)
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc):
 | |
|         if self.parent.clockStyle & SHOW_SHADOWS:
 | |
|             self._draw(dc, True)
 | |
|         self._draw(dc)
 | |
| 
 | |
| 
 | |
|     def RecalcCoords(self, clocksize, centre, scale):
 | |
|         self.centre = centre
 | |
|         [hand.RecalcCoords(clocksize, centre, scale) for hand in self.hands]
 | |
| 
 | |
| 
 | |
|     def SetMaxRadius(self, radius):
 | |
|         self.radius = radius
 | |
| 
 | |
| 
 | |
|     def GetSize(self, target):
 | |
|         r = []
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 r.append(hand.GetSize())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetFillColour(self, target):
 | |
|         r = []
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 r.append(hand.GetFillColour())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetBorderColour(self, target):
 | |
|         r = []
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 r.append(hand.GetBorderColour())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetBorderWidth(self, target):
 | |
|         r = []
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 r.append(hand.GetBorderWidth())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetShadowColour(self):
 | |
|         r = []
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 r.append(hand.GetShadowColour())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def SetSize(self, size, target):
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 hand.SetSize(size)
 | |
| 
 | |
| 
 | |
|     def SetFillColour(self, colour, target):
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 hand.SetFillColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetBorderColour(self, colour, target):
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 hand.SetBorderColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetBorderWidth(self, width, target):
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             if _targets[i] & target:
 | |
|                 hand.SetBorderWidth(width)
 | |
| 
 | |
| 
 | |
|     def SetShadowColour(self, colour):
 | |
|         for i, hand in enumerate(self.hands):
 | |
|             hand.SetShadowColour(colour)
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class TickSet:
 | |
|     """Manages a set of tick marks."""
 | |
| 
 | |
|     def __init__(self, parent, **kwargs):
 | |
|         self.parent = parent
 | |
|         self.dyer = Dyer()
 | |
|         self.noe = {"minutes": 60, "hours": 12}[kwargs["kind"]]
 | |
|         self.font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
 | |
| 
 | |
|         style = kwargs.pop("style")
 | |
|         self.kwargs = kwargs
 | |
|         self.SetStyle(style)
 | |
| 
 | |
| 
 | |
|     def _draw(self, dc, shadow=False):
 | |
|         dc.SetFont(self.font)
 | |
|         
 | |
|         a_tick = self.ticks[0]
 | |
| 
 | |
|         if shadow:
 | |
|             offset = self.parent.shadowOffset * a_tick.GetScale()
 | |
|         else:
 | |
|             offset = 0
 | |
| 
 | |
|         clockStyle = self.parent.clockStyle
 | |
| 
 | |
|         for idx, tick in self.ticks.items():
 | |
|             draw = False
 | |
| 
 | |
|             # Are we a set of hours?
 | |
|             if self.noe == 12:
 | |
|                 # Should we show all hours ticks?
 | |
|                 if clockStyle & SHOW_HOURS_TICKS:
 | |
|                     draw = True
 | |
|                 # Or is this tick a quarter and should we show only quarters?
 | |
|                 elif clockStyle & SHOW_QUARTERS_TICKS and not (idx + 1) % 3.:
 | |
|                     draw = True
 | |
|             # Are we a set of minutes and minutes should be shown?
 | |
|             elif self.noe == 60 and clockStyle & SHOW_MINUTES_TICKS:
 | |
|                 # If this tick occupies the same position of an hour/quarter
 | |
|                 # tick, should we still draw it anyway?
 | |
|                 if clockStyle & OVERLAP_TICKS:
 | |
|                     draw = True
 | |
|                 # Right, sir. I promise I won't overlap any tick.
 | |
|                 else:
 | |
|                     # Ensure that this tick won't overlap an hour tick.
 | |
|                     if clockStyle & SHOW_HOURS_TICKS:
 | |
|                         if (idx + 1) % 5.:
 | |
|                             draw = True
 | |
|                     # Ensure that this tick won't overlap a quarter tick.
 | |
|                     elif clockStyle & SHOW_QUARTERS_TICKS:
 | |
|                         if (idx + 1) % 15.:
 | |
|                             draw = True
 | |
|                     # We're not drawing quarters nor hours, so we can draw all
 | |
|                     # minutes ticks.
 | |
|                     else:
 | |
|                         draw = True
 | |
| 
 | |
|             if draw:
 | |
|                 tick.Draw(dc, offset)
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc):
 | |
|         if self.parent.clockStyle & SHOW_SHADOWS:
 | |
|             self.dyer.Select(dc, True)
 | |
|             self._draw(dc, True)
 | |
|         self.dyer.Select(dc)
 | |
|         self._draw(dc)
 | |
| 
 | |
| 
 | |
|     def RecalcCoords(self, clocksize, centre, scale):
 | |
|         a_tick = self.ticks[0]
 | |
| 
 | |
|         size = a_tick.GetMaxSize(scale)
 | |
|         maxsize = size
 | |
| 
 | |
|         # Try to find a 'good' max size for text-based ticks.
 | |
|         if a_tick.text is not None:
 | |
|             self.font.SetPointSize(size)
 | |
|             dc = wx.MemoryDC()
 | |
|             dc.SelectObject(wx.EmptyBitmap(*clocksize.Get()))
 | |
|             dc.SetFont(self.font)
 | |
|             maxsize = size
 | |
|             for tick in self.ticks.values():
 | |
|                 maxsize = max(*(dc.GetTextExtent(tick.text) + (maxsize,)))
 | |
| 
 | |
|         radius = self.radius = min(clocksize.Get()) / 2. - \
 | |
|                                self.dyer.width / 2. - \
 | |
|                                maxsize / 2. - \
 | |
|                                a_tick.GetOffset() * scale - \
 | |
|                                self.parent.shadowOffset * scale
 | |
| 
 | |
|         # If we are a set of hours, the number of elements of this tickset is 
 | |
|         # 12 and ticks are separated by a distance of 30 degrees;
 | |
|         # if we are a set of minutes, the number of elements of this tickset is
 | |
|         # 60 and ticks are separated by a distance of 6 degrees.
 | |
|         angfac = [6, 30][self.noe == 12]
 | |
| 
 | |
|         for i, tick in self.ticks.items():
 | |
|             tick.SetClockSize(clocksize)
 | |
|             tick.SetScale(scale)
 | |
| 
 | |
|             deg = 180 - angfac * (i + 1)
 | |
|             angle = math.radians(deg)
 | |
| 
 | |
|             x = centre.x + radius * math.sin(angle)
 | |
|             y = centre.y + radius * math.cos(angle)
 | |
| 
 | |
|             tick.SetPosition(wx.Point(x, y))
 | |
| 
 | |
| 
 | |
|     def GetSize(self):
 | |
|         return self.kwargs["size"]
 | |
| 
 | |
| 
 | |
|     def GetFillColour(self):
 | |
|         return self.dyer.GetFillColour()
 | |
| 
 | |
| 
 | |
|     def GetBorderColour(self):
 | |
|         return self.dyer.GetBorderColour()
 | |
| 
 | |
| 
 | |
|     def GetBorderWidth(self):
 | |
|         return self.dyer.GetBorderWidth()
 | |
| 
 | |
| 
 | |
|     def GetPolygon(self):
 | |
|         a_tick = self.ticks.values()[0]
 | |
|         return a_tick.GetPolygon()
 | |
| 
 | |
| 
 | |
|     def GetFont(self):
 | |
|         return self.font
 | |
| 
 | |
| 
 | |
|     def GetOffset(self):
 | |
|         a_tick = self.ticks[0]
 | |
|         return a_tick.GetOffset()
 | |
| 
 | |
| 
 | |
|     def GetShadowColour(self):
 | |
|         return self.dyer.GetShadowColour()
 | |
| 
 | |
| 
 | |
|     def GetIsRotated(self):
 | |
|         a_tick = self.ticks[0]
 | |
|         return a_tick.GetIsRotated()
 | |
| 
 | |
| 
 | |
|     def GetStyle(self):
 | |
|         return self.style
 | |
| 
 | |
| 
 | |
|     def SetSize(self, size):
 | |
|         self.kwargs["size"] = size
 | |
|         [tick.SetSize(size) for tick in self.ticks.values()]
 | |
| 
 | |
| 
 | |
|     def SetFillColour(self, colour):
 | |
|         self.dyer.SetFillColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetBorderColour(self, colour):
 | |
|         self.dyer.SetBorderColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetBorderWidth(self, width):
 | |
|         self.dyer.SetBorderWidth(width)
 | |
| 
 | |
| 
 | |
|     def SetPolygon(self, polygon):
 | |
|         [tick.SetPolygon(polygon) for tick in self.ticks.values()]
 | |
| 
 | |
| 
 | |
|     def SetFont(self, font):
 | |
|         self.font = font
 | |
| 
 | |
| 
 | |
|     def SetOffset(self, offset):
 | |
|         self.kwargs["offset"] = offset
 | |
|         [tick.SetOffset(offset) for tick in self.ticks.values()]
 | |
| 
 | |
| 
 | |
|     def SetShadowColour(self, colour):
 | |
|         self.dyer.SetShadowColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetIsRotated(self, rotate):
 | |
|         self.kwargs["rotate"] = rotate
 | |
|         [tick.SetIsRotated(rotate) for tick in self.ticks.values()]
 | |
| 
 | |
| 
 | |
|     def SetStyle(self, style):
 | |
|         self.style = style
 | |
|         tickclass = allTickStyles[style]
 | |
|         self.kwargs["rotate"] = self.parent.clockStyle & ROTATE_TICKS
 | |
| 
 | |
|         self.ticks = {}
 | |
|         for i in range(self.noe):
 | |
|             self.kwargs["idx"] = i
 | |
|             self.ticks[i] = tickclass(**self.kwargs)
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class Box:
 | |
|     """Gathers info about the clock face and tick sets."""
 | |
| 
 | |
|     def __init__(self, parent, Face, TicksM, TicksH):
 | |
|         self.parent = parent
 | |
|         self.Face   = Face
 | |
|         self.TicksH = TicksH
 | |
|         self.TicksM = TicksM
 | |
| 
 | |
| 
 | |
|     def GetNiceRadiusForHands(self, centre):
 | |
|         a_tick = self.TicksM.ticks[0]
 | |
|         scale = a_tick.GetScale()
 | |
|         bw = max(self.TicksH.dyer.width / 2. * scale,
 | |
|                  self.TicksM.dyer.width / 2. * scale)
 | |
| 
 | |
|         mgt = self.TicksM.ticks[59]
 | |
|         my = mgt.pos.y + mgt.GetMaxSize(scale) + bw
 | |
| 
 | |
|         hgt = self.TicksH.ticks[11]
 | |
|         hy = hgt.pos.y + hgt.GetMaxSize(scale) + bw
 | |
| 
 | |
|         niceradius = centre.y - max(my, hy)
 | |
|         return niceradius
 | |
| 
 | |
| 
 | |
|     def Draw(self, dc):
 | |
|         [getattr(self, attr).Draw(dc) \
 | |
|          for attr in ["Face", "TicksM", "TicksH"]]
 | |
| 
 | |
| 
 | |
|     def RecalcCoords(self, size, centre, scale):
 | |
|         [getattr(self, attr).RecalcCoords(size, centre, scale) \
 | |
|          for attr in ["Face", "TicksH", "TicksM"]]
 | |
| 
 | |
| 
 | |
|     def GetTickSize(self, target):
 | |
|         r = []
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 r.append(tick.GetSize())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetTickFillColour(self, target):
 | |
|         r = []
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 r.append(tick.GetFillColour())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetTickBorderColour(self, target):
 | |
|         r = []
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 r.append(tick.GetBorderColour())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetTickBorderWidth(self, target):
 | |
|         r = []
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 r.append(tick.GetBorderWidth())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetTickPolygon(self, target):
 | |
|         r = []
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 r.append(tick.GetPolygon())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetTickFont(self, target):
 | |
|         r = []
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 r.append(tick.GetFont())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetIsRotated(self):
 | |
|         a_tickset = self.TicksH
 | |
|         return a_tickset.GetIsRotated()
 | |
| 
 | |
| 
 | |
|     def GetTickOffset(self, target):
 | |
|         r = []
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 r.append(tick.GetOffset())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def GetShadowColour(self):
 | |
|         a_tickset = self.TicksH
 | |
|         return a_tickset.GetShadowColour()
 | |
| 
 | |
| 
 | |
|     def GetTickStyle(self, target):
 | |
|         r = []
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 r.append(tick.GetStyle())
 | |
|         return tuple(r)
 | |
| 
 | |
| 
 | |
|     def SetTickSize(self, size, target):
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 tick.SetSize(size)
 | |
| 
 | |
| 
 | |
|     def SetTickFillColour(self, colour, target):
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 tick.SetFillColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetTickBorderColour(self, colour, target):
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 tick.SetBorderColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetTickBorderWidth(self, width, target):
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 tick.SetBorderWidth(width)
 | |
| 
 | |
| 
 | |
|     def SetTickPolygon(self, polygon, target):
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 tick.SetPolygon(polygon)
 | |
| 
 | |
| 
 | |
|     def SetTickFont(self, font, target):
 | |
|         fs = font.GetNativeFontInfoDesc()
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 tick.SetFont(wx.FontFromNativeInfoString(fs))
 | |
| 
 | |
| 
 | |
|     def SetIsRotated(self, rotate):
 | |
|         [getattr(self, attr).SetIsRotated(rotate) \
 | |
|          for attr in ["TicksH", "TicksM"]]
 | |
| 
 | |
| 
 | |
|     def SetTickOffset(self, offset, target):
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 tick.SetOffset(offset)
 | |
| 
 | |
| 
 | |
|     def SetShadowColour(self, colour):
 | |
|         for attr in ["TicksH", "TicksM"]:
 | |
|             tick = getattr(self, attr)
 | |
|             tick.SetShadowColour(colour)
 | |
| 
 | |
| 
 | |
|     def SetTickStyle(self, style, target):
 | |
|         for i, attr in enumerate(["TicksH", "TicksM"]):
 | |
|             if _targets[i] & target:
 | |
|                 tick = getattr(self, attr)
 | |
|                 tick.SetStyle(style)
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| # Relationship between styles and ticks class names.
 | |
| allTickStyles = {TICKS_BINARY:  TickBinary,
 | |
|                  TICKS_CIRCLE:  TickCircle,
 | |
|                  TICKS_DECIMAL: TickDecimal,
 | |
|                  TICKS_HEX:     TickHex,
 | |
|                  TICKS_NONE:    TickNone,
 | |
|                  TICKS_POLY:    TickPoly,
 | |
|                  TICKS_ROMAN:   TickRoman,
 | |
|                  TICKS_SQUARE:  TickSquare}
 | |
| 
 | |
| 
 | |
| #
 | |
| ##
 | |
| ### eof
 |