Port the LEDNumberCtrl from wxCode/gizmos in Classic

This commit is contained in:
Robin Dunn
2017-10-27 17:21:59 -07:00
parent 0fb1ce987a
commit 17643e9cd1
6 changed files with 307 additions and 5 deletions

View File

@@ -13,15 +13,19 @@ class TestPanel(wx.Panel):
self.log = log
led = gizmos.LEDNumberCtrl(self, -1, (25,25), (280, 50))
led.SetValue("01234")
led.SetValue("012.34")
led = gizmos.LEDNumberCtrl(self, -1, (25,100), (280, 50))
led.SetValue("56789")
led.SetAlignment(gizmos.LED_ALIGN_RIGHT)
led.SetDrawFaded(False)
led.SetForegroundColour('yellow')
led = gizmos.LEDNumberCtrl(self, -1, (25,175), (280, 50),
gizmos.LED_ALIGN_CENTER)# | gizmos.LED_DRAW_FADED)
led.SetForegroundColour('black')
led.SetBackgroundColour('white')
self.clock = led
self.OnTimer(None)
@@ -32,7 +36,7 @@ class TestPanel(wx.Panel):
def OnTimer(self, evt):
t = time.localtime(time.time())
st = time.strftime("%I-%M-%S", t)
st = time.strftime("%H:%M:%S", t)
self.clock.SetValue(st)

View File

@@ -144,7 +144,7 @@ _treeList = [
'GenericButtons',
'GenericDirCtrl',
'ItemsPicker',
#'LEDNumberCtrl', # TODO
'LEDNumberCtrl',
'MultiSash',
'PlateButton',
'PopupControl',

14
src/gizmos.py Normal file
View File

@@ -0,0 +1,14 @@
#---------------------------------------------------------------------------
# Name: wx/gizmos.py
# Author: Robin Dunn
#
# Created: 27-Oct-2017
# Copyright: (c) 2017 by Total Control Software
# License: wxWindows License
#---------------------------------------------------------------------------
# This is just a compatibility shim to make the gizmos classes usable from
# wx.gizmos like in Classic. They're actually in wx.lib.gizmos now.
from wx.lib.gizmos import *

View File

@@ -500,8 +500,9 @@ def build(bld):
# copy the wx locale message catalogs to the package dir
cfg.build_locale_dir(opj(cfg.PKGDIR, 'locale'))
# copy __init__.py
copy_file('src/__init__.py', cfg.PKGDIR, update=1, verbose=1)
# copy .py files that need to go into the root wx package dir
for name in ['src/__init__.py', 'src/gizmos.py',]:
copy_file(name, cfg.PKGDIR, update=1, verbose=1)
# Create the build tasks for each of our extension modules.

16
wx/lib/gizmos/__init__.py Normal file
View File

@@ -0,0 +1,16 @@
#----------------------------------------------------------------------
# Name: wx.lib.gizmos
# Purpose: Python ports of some of the wrapped C++ classes in the
# wx.gizmos module in Classic wxPython
#
# Author: Robin Dunn
#
# Created: 26-Oct-2017
# Copyright: (c) 2017 by Total Control Software
# Licence: wxWindows license
# Tags:
#----------------------------------------------------------------------
from .ledctrl import *

267
wx/lib/gizmos/ledctrl.py Normal file
View File

@@ -0,0 +1,267 @@
#----------------------------------------------------------------------
# Name: wx.lib.gizmos.ledctrl
# Purpose:
#
# Author: Robin Dunn
#
# Created: 26-Oct-2017
# Copyright: (c) 2017 by Total Control Software
# Licence: wxWindows license
# Tags:
#----------------------------------------------------------------------
import wx
LED_ALIGN_LEFT = 0x01
LED_ALIGN_RIGHT = 0x02
LED_ALIGN_CENTER = 0x04
LED_ALIGN_MASK = 0x07
LED_DRAW_FADED = 0x08
class LEDNumberCtrl(wx.Control):
"""
"""
# constants used internally
class const:
LINE1 = 1
LINE2 = 2
LINE3 = 4
LINE4 = 8
LINE5 = 16
LINE6 = 32
LINE7 = 64
DECIMALSIGN = 128
COLON = 256
DIGITS = {
'0': LINE1 | LINE2 | LINE3 | LINE4 | LINE5 | LINE6,
'1': LINE2 | LINE3,
'2': LINE1 | LINE2 | LINE4 | LINE5 | LINE7,
'3': LINE1 | LINE2 | LINE3 | LINE4 | LINE7,
'4': LINE2 | LINE3 | LINE6 | LINE7,
'5': LINE1 | LINE3 | LINE4 | LINE6 | LINE7,
'6': LINE1 | LINE3 | LINE4 | LINE5 | LINE6 | LINE7,
'7': LINE1 | LINE2 | LINE3,
'8': LINE1 | LINE2 | LINE3 | LINE4 | LINE5 | LINE6 | LINE7,
'9': LINE1 | LINE2 | LINE3 | LINE6 | LINE7,
'-': LINE7,
':': COLON,
}
DIGITALL = 0xFFFF
def __init__(self, parent, id=wx.ID_ANY,
pos=wx.DefaultPosition, size=wx.DefaultSize,
style=LED_ALIGN_LEFT|LED_DRAW_FADED, name='ledctrl'):
super(LEDNumberCtrl, self).__init__(parent, id, pos, size, style, name=name)
# defaults
self._alignment = LED_ALIGN_LEFT
self._lineMargin = -1
self._digitMargin = -1
self._lineLength = -1
self._lineWidth = -1
self._drawFaded = False
self._leftStartPos = -1
self._value = ''
self.SetBackgroundColour(wx.BLACK)
self.SetForegroundColour(wx.GREEN)
self.SetBackgroundStyle(wx.BG_STYLE_PAINT)
# flags
if style & LED_DRAW_FADED:
self.SetDrawFaded(True)
if style & LED_ALIGN_MASK:
self.SetAlignment(style & LED_ALIGN_MASK)
# event bindings
self.Bind(wx.EVT_ERASE_BACKGROUND, lambda evt: None)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
def GetAlignment(self):
"""
"""
return self._alignment
def GetDrawFaded(self):
"""
"""
return self._drawFaded
def GetValue(self):
"""
"""
return self._value
def SetAlignment(self, alignment, redraw=True):
"""
"""
if alignment != self._alignment:
self._alignment = alignment
self._recalcInternals(self.GetClientSize())
if redraw:
self.Refresh(False)
def SetDrawFaded(self, drawFaded, redraw=True):
"""
"""
if drawFaded != self._drawFaded:
self._drawFaded = drawFaded
if redraw:
self.Refresh(False)
def SetValue(self, value, redraw=True):
"""
"""
if value != self._value:
for c in value:
assert c in '0123456789-.: ', "LEDNumberCtrl can only display numeric string values."
self._value = value
self._recalcInternals(self.GetClientSize())
if redraw:
self.Refresh(False)
Alignment = property(GetAlignment, SetAlignment)
DrawFaded = property(GetDrawFaded, SetDrawFaded)
Value = property(GetValue, SetValue)
def OnSize(self, evt):
self._recalcInternals(evt.GetSize())
evt.Skip()
def OnPaint(self, evt):
c = self.const
dc = wx.AutoBufferedPaintDC(self)
# Draw the background
dc.SetBrush(wx.Brush(self.GetBackgroundColour(), wx.BRUSHSTYLE_SOLID))
dc.DrawRectangle(wx.Rect((0, 0), self.GetClientSize()))
# Iterate the digits and draw each
offset = 0
for i, ch in enumerate(self._value):
i -= offset
# Draw faded lines if wanted.
if self._drawFaded and ch != '.':
self._drawDigit(dc, c.DIGITALL, i);
if ch == '.':
# draw the decimal point in the previous segment
self._drawDigit(dc, c.DECIMALSIGN, i-1)
offset += 1
elif ch == ' ':
# skip spaces
continue
else:
self._drawDigit(dc, c.DIGITS[ch], i)
def _recalcInternals(self, size):
height = size.Height
if (height * 0.075) < 1:
self._lineMargin = 1
else:
self._lineMargin = int(height * 0.075)
if (height * 0.275) < 1:
self._lineLength = 1
else:
self._lineLength = int(height * 0.275)
self._lineWidth = self._lineMargin
self._digitMargin = self._lineMargin * 4
# Count the number of characters in the string; '.' characters are not
# included because they do not take up space in the display
count = 0;
for ch in self._value:
if ch != '.':
count += 1
valueWidth = (self._lineLength + self._digitMargin) * count
clientWidth = size.Width
if self._alignment == LED_ALIGN_LEFT:
self._leftStartPos = self._lineMargin
elif self._alignment == LED_ALIGN_RIGHT:
self._leftStartPos = clientWidth - valueWidth - self._lineMargin
elif self._alignment == LED_ALIGN_CENTER:
self._leftStartPos = int((clientWidth - valueWidth) / 2)
else:
raise AssertionError("Unknown alignment value for LEDNumberCtrl.")
def _drawDigit(self, dc, digit, column):
lineColor = self.GetForegroundColour()
c = self.const
if digit == c.DIGITALL:
R = int(lineColor.Red() / 8)
G = int(lineColor.Green() / 8)
B = int(lineColor.Blue() / 8)
lineColor.Set(R, G, B)
XPos = self._leftStartPos + column * (self._lineLength + self._digitMargin)
# Create a pen and draw the lines.
dc.SetPen(wx.Pen(lineColor, self._lineWidth))
if digit & c.LINE1:
dc.DrawLine(XPos + self._lineMargin*2, self._lineMargin,
XPos + self._lineLength + self._lineMargin*2, self._lineMargin)
if digit & c.LINE2:
dc.DrawLine(XPos + self._lineLength + self._lineMargin*3, self._lineMargin*2,
XPos + self._lineLength + self._lineMargin*3, self._lineLength + (self._lineMargin*2))
if digit & c.LINE3:
dc.DrawLine(XPos + self._lineLength + self._lineMargin*3, self._lineLength + (self._lineMargin*4),
XPos + self._lineLength + self._lineMargin*3, self._lineLength*2 + (self._lineMargin*4))
if digit & c.LINE4:
dc.DrawLine(XPos + self._lineMargin*2, self._lineLength*2 + (self._lineMargin*5),
XPos + self._lineLength + self._lineMargin*2, self._lineLength*2 + (self._lineMargin*5))
if digit & c.LINE5:
dc.DrawLine(XPos + self._lineMargin, self._lineLength + (self._lineMargin*4),
XPos + self._lineMargin, self._lineLength*2 + (self._lineMargin*4))
if digit & c.LINE6:
dc.DrawLine(XPos + self._lineMargin, self._lineMargin*2,
XPos + self._lineMargin, self._lineLength + (self._lineMargin*2))
if digit & c.LINE7:
dc.DrawLine(XPos + self._lineMargin*2, self._lineLength + (self._lineMargin*3),
XPos + self._lineMargin*2 + self._lineLength, self._lineLength + (self._lineMargin*3))
if digit & c.DECIMALSIGN:
dc.DrawLine(XPos + self._lineLength + self._lineMargin*4, self._lineLength*2 + (self._lineMargin*5),
XPos + self._lineLength + self._lineMargin*4, self._lineLength*2 + (self._lineMargin*5))
if digit & c.COLON:
dc.SetBrush(wx.Brush(lineColor))
centerX = XPos + (self._lineLength + self._digitMargin)/2
radius = self._lineWidth / 2
dc.DrawCircle(centerX, (self._lineLength + (self._lineMargin*3))/2, radius)
dc.DrawCircle(centerX, (self._lineLength*2 + (self._lineMargin*5))*3/4, radius)