MaskedEdit updates from Will Sadkin:

- Added '*' mask char that means "all ansii chars" (ords 32-255)
    - Added proper unicode support to masked controls and wx.tools.dbg
    - Fixed two reported missing import bugs introduced by package
      creation
    - Converted masked package doc strings to reST format for better
      epydoc support
    - lots of doc string improvements and function hiding to better
      reflect package's public contents.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@29787 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2004-10-11 22:13:18 +00:00
parent 84f85550e5
commit f54a36bba8
11 changed files with 1066 additions and 818 deletions

View File

@@ -324,7 +324,10 @@ def runTest( frame, nb, log ):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
import wx.lib.masked.numctrl as mnum import wx.lib.masked.numctrl as mnum
overview = mnum.__doc__ overview = """<html>
<PRE><FONT SIZE=-1>
""" + mnum.__doc__ + """
</FONT></PRE>"""
if __name__ == '__main__': if __name__ == '__main__':
import sys,os import sys,os

View File

@@ -21,11 +21,12 @@ class TestPanel( scrolled.ScrolledPanel ):
text1 = wx.StaticText( self, -1, "12-hour format:") text1 = wx.StaticText( self, -1, "12-hour format:")
self.time12 = masked.TimeCtrl( self, -1, name="12 hour control" ) self.time12 = masked.TimeCtrl( self, -1, name="12 hour control" )
spin1 = wx.SpinButton( self, -1, wx.DefaultPosition, (-1,20), 0 ) h = self.time12.GetSize().height
spin1 = wx.SpinButton( self, -1, wx.DefaultPosition, (-1,h), wx.SP_VERTICAL )
self.time12.BindSpinButton( spin1 ) self.time12.BindSpinButton( spin1 )
text2 = wx.StaticText( self, -1, "24-hour format:") text2 = wx.StaticText( self, -1, "24-hour format:")
spin2 = wx.SpinButton( self, -1, wx.DefaultPosition, (-1,20), 0 ) spin2 = wx.SpinButton( self, -1, wx.DefaultPosition, (-1,h), wx.SP_VERTICAL )
self.time24 = masked.TimeCtrl( self.time24 = masked.TimeCtrl(
self, -1, name="24 hour control", fmt24hr=True, self, -1, name="24 hour control", fmt24hr=True,
spinButton = spin2 spinButton = spin2
@@ -226,7 +227,10 @@ def runTest( frame, nb, log ):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
import wx.lib.masked.timectrl as timectl import wx.lib.masked.timectrl as timectl
overview = timectl.__doc__ overview = """<html>
<PRE><FONT SIZE=-1>
""" + timectl.__doc__ + """
</FONT></PRE>"""
if __name__ == '__main__': if __name__ == '__main__':
import sys,os import sys,os

View File

@@ -147,6 +147,24 @@ holding down the mouse button.
wxGTK: Enable key based navigation through notebook tabs as in the wxGTK: Enable key based navigation through notebook tabs as in the
native control with Left and right keys. Support for vetoing. native control with Left and right keys. Support for vetoing.
FloatCanvas updates from Chris Barker
PyPlot updates from Gordon Williams:
- Added bar graph demo
- Modified line end shape from round to square.
- Removed FloatDCWrapper for conversion to ints and ints in arguments
MaskedEdit updates from Will Sadkin:
- Added '*' mask char that means "all ansii chars" (ords 32-255)
- Added proper unicode support to masked controls and wx.tools.dbg
- Fixed two reported missing import bugs introduced by package
creation
- Converted masked package doc strings to reST format for better
epydoc support
- lots of doc string improvements and function hiding to better
reflect package's public contents.

View File

@@ -13,19 +13,29 @@
# #
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
import wx """
Provides masked edit capabilities within a ComboBox format, as well as
a base class from which you can derive masked comboboxes tailored to a specific
function. See maskededit module overview for how to configure the control.
"""
import wx, types, string
from wx.lib.masked import * from wx.lib.masked import *
# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would # jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
# be a good place to implement the 2.3 logger class # be a good place to implement the 2.3 logger class
from wx.tools.dbg import Logger from wx.tools.dbg import Logger
dbg = Logger() ##dbg = Logger()
##dbg(enable=0) ##dbg(enable=0)
## ---------- ---------- ---------- ---------- ---------- ---------- ---------- ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
## Because calling SetSelection programmatically does not fire EVT_COMBOBOX ## Because calling SetSelection programmatically does not fire EVT_COMBOBOX
## events, we have to do it ourselves when we auto-complete. ## events, we have to do it ourselves when we auto-complete.
class MaskedComboBoxSelectEvent(wx.PyCommandEvent): class MaskedComboBoxSelectEvent(wx.PyCommandEvent):
"""
Because calling SetSelection programmatically does not fire EVT_COMBOBOX
events, the derived control has to do it itself when it auto-completes.
"""
def __init__(self, id, selection = 0, object=None): def __init__(self, id, selection = 0, object=None):
wx.PyCommandEvent.__init__(self, wx.wxEVT_COMMAND_COMBOBOX_SELECTED, id) wx.PyCommandEvent.__init__(self, wx.wxEVT_COMMAND_COMBOBOX_SELECTED, id)
@@ -40,8 +50,9 @@ class MaskedComboBoxSelectEvent(wx.PyCommandEvent):
class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ): class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
""" """
This masked edit control adds the ability to use a masked input Base class for generic masked edit comboboxes; allows auto-complete of values.
on a combobox, and do auto-complete of such values. It is not meant to be instantiated directly, but rather serves as a base class
for any subsequent refinements.
""" """
def __init__( self, parent, id=-1, value = '', def __init__( self, parent, id=-1, value = '',
pos = wx.DefaultPosition, pos = wx.DefaultPosition,
@@ -138,8 +149,8 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
self._SetInitialValue(value) self._SetInitialValue(value)
self._SetKeycodeHandler(wx.WXK_UP, self.OnSelectChoice) self._SetKeycodeHandler(wx.WXK_UP, self._OnSelectChoice)
self._SetKeycodeHandler(wx.WXK_DOWN, self.OnSelectChoice) self._SetKeycodeHandler(wx.WXK_DOWN, self._OnSelectChoice)
if setupEventHandling: if setupEventHandling:
## Setup event handlers ## Setup event handlers
@@ -148,7 +159,7 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
self.Bind(wx.EVT_LEFT_DCLICK, self._OnDoubleClick) ## select field under cursor on dclick self.Bind(wx.EVT_LEFT_DCLICK, self._OnDoubleClick) ## select field under cursor on dclick
self.Bind(wx.EVT_RIGHT_UP, self._OnContextMenu ) ## bring up an appropriate context menu self.Bind(wx.EVT_RIGHT_UP, self._OnContextMenu ) ## bring up an appropriate context menu
self.Bind(wx.EVT_CHAR, self._OnChar ) ## handle each keypress self.Bind(wx.EVT_CHAR, self._OnChar ) ## handle each keypress
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown ) ## for special processing of up/down keys self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDownInComboBox ) ## for special processing of up/down keys
self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDown ) ## for processing the rest of the control keys self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDown ) ## for processing the rest of the control keys
## (next in evt chain) ## (next in evt chain)
self.Bind(wx.EVT_TEXT, self._OnTextChange ) ## color control appropriately & keep self.Bind(wx.EVT_TEXT, self._OnTextChange ) ## color control appropriately & keep
@@ -173,11 +184,11 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
""" Set the font, then recalculate control size, if appropriate. """ """ Set the font, then recalculate control size, if appropriate. """
wx.ComboBox.SetFont(self, *args, **kwargs) wx.ComboBox.SetFont(self, *args, **kwargs)
if self._autofit: if self._autofit:
dbg('calculated size:', self._CalcSize()) ## dbg('calculated size:', self._CalcSize())
self.SetClientSize(self._CalcSize()) self.SetClientSize(self._CalcSize())
width = self.GetSize().width width = self.GetSize().width
height = self.GetBestSize().height height = self.GetBestSize().height
dbg('setting client size to:', (width, height)) ## dbg('setting client size to:', (width, height))
self.SetBestFittingSize((width, height)) self.SetBestFittingSize((width, height))
@@ -355,11 +366,11 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
def Append( self, choice, clientData=None ): def Append( self, choice, clientData=None ):
""" """
This function override is necessary so we can keep track of any additions to the list This base control function override is necessary so the control can keep track
of choices, because wxComboBox doesn't have an accessor for the choice list. of any additions to the list of choices, because wx.ComboBox doesn't have an
The code here is the same as in the SetParameters() mixin function, but is accessor for the choice list. The code here is the same as in the
done for the individual value as appended, so the list can be built incrementally SetParameters() mixin function, but is done for the individual value
without speed penalty. as appended, so the list can be built incrementally without speed penalty.
""" """
if self._mask: if self._mask:
if type(choice) not in (types.StringType, types.UnicodeType): if type(choice) not in (types.StringType, types.UnicodeType):
@@ -408,8 +419,9 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
def Clear( self ): def Clear( self ):
""" """
This function override is necessary so we can keep track of any additions to the list This base control function override is necessary so the derived control can
of choices, because wxComboBox doesn't have an accessor for the choice list. keep track of any additions to the list of choices, because wx.ComboBox
doesn't have an accessor for the choice list.
""" """
if self._mask: if self._mask:
self._choices = [] self._choices = []
@@ -421,8 +433,8 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
def _OnCtrlParametersChanged(self): def _OnCtrlParametersChanged(self):
""" """
Override mixin's default OnCtrlParametersChanged to detect changes in choice list, so This overrides the mixin's default OnCtrlParametersChanged to detect
we can update the base control: changes in choice list, so masked.Combobox can update the base control:
""" """
if self.controlInitialized and self._choices != self._ctrl_constraints._choices: if self.controlInitialized and self._choices != self._ctrl_constraints._choices:
wx.ComboBox.Clear(self) wx.ComboBox.Clear(self)
@@ -433,7 +445,7 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
def GetMark(self): def GetMark(self):
""" """
This function is a hack to make up for the fact that wxComboBox has no This function is a hack to make up for the fact that wx.ComboBox has no
method for returning the selected portion of its edit control. It method for returning the selected portion of its edit control. It
works, but has the nasty side effect of generating lots of intermediate works, but has the nasty side effect of generating lots of intermediate
events. events.
@@ -470,7 +482,7 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
def SetSelection(self, index): def SetSelection(self, index):
""" """
Necessary for bookkeeping on choice selection, to keep current value Necessary override for bookkeeping on choice selection, to keep current value
current. current.
""" """
## dbg('MaskedComboBox::SetSelection(%d)' % index) ## dbg('MaskedComboBox::SetSelection(%d)' % index)
@@ -481,7 +493,7 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
wx.ComboBox.SetSelection(self, index) wx.ComboBox.SetSelection(self, index)
def OnKeyDown(self, event): def _OnKeyDownInComboBox(self, event):
""" """
This function is necessary because navigation and control key This function is necessary because navigation and control key
events do not seem to normally be seen by the wxComboBox's events do not seem to normally be seen by the wxComboBox's
@@ -495,7 +507,7 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
event.Skip() # let mixin default KeyDown behavior occur event.Skip() # let mixin default KeyDown behavior occur
def OnSelectChoice(self, event): def _OnSelectChoice(self, event):
""" """
This function appears to be necessary, because the processing done This function appears to be necessary, because the processing done
on the text of the control somehow interferes with the combobox's on the text of the control somehow interferes with the combobox's
@@ -569,13 +581,13 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
def _OnReturn(self, event): def _OnReturn(self, event):
""" """
For wxComboBox, it seems that if you hit return when the dropdown is For wx.ComboBox, it seems that if you hit return when the dropdown is
dropped, the event that dismisses the dropdown will also blank the dropped, the event that dismisses the dropdown will also blank the
control, because of the implementation of wxComboBox. So here, control, because of the implementation of wxComboBox. So this function
we look and if the selection is -1, and the value according to examines the selection and if it is -1, and the value according to
(the base control!) is a value in the list, then we schedule a (the base control!) is a value in the list, then it schedules a
programmatic wxComboBox.SetSelection() call to pick the appropriate programmatic wxComboBox.SetSelection() call to pick the appropriate
item in the list. (and then do the usual OnReturn bit.) item in the list. (and then does the usual OnReturn bit.)
""" """
## dbg('MaskedComboBox::OnReturn', indent=1) ## dbg('MaskedComboBox::OnReturn', indent=1)
## dbg('current value: "%s"' % self.GetValue(), 'current index:', self.GetSelection()) ## dbg('current value: "%s"' % self.GetValue(), 'current index:', self.GetSelection())
@@ -589,17 +601,20 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
class ComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ): class ComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
""" """
This extra level of inheritance allows us to add the generic set of The "user-visible" masked combobox control, this class is
masked edit parameters only to this class while allowing other identical to the BaseMaskedComboBox class it's derived from.
classes to derive from the "base" masked combobox control, and provide (This extra level of inheritance allows us to add the generic
a smaller set of valid accessor functions. set of masked edit parameters only to this class while allowing
other classes to derive from the "base" masked combobox control,
and provide a smaller set of valid accessor functions.)
See BaseMaskedComboBox for available methods.
""" """
pass pass
class PreMaskedComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ): class PreMaskedComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
""" """
This allows us to use XRC subclassing. This class exists to support the use of XRC subclassing.
""" """
# This should really be wx.EVT_WINDOW_CREATE but it is not # This should really be wx.EVT_WINDOW_CREATE but it is not
# currently delivered for native controls on all platforms, so # currently delivered for native controls on all platforms, so
@@ -617,9 +632,14 @@ class PreMaskedComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
self.Unbind(self._firstEventType) self.Unbind(self._firstEventType)
self._PostInit() self._PostInit()
i=0 __i = 0
## CHANGELOG: ## CHANGELOG:
## ==================== ## ====================
## Version 1.2
## 1. Converted docstrings to reST format, added doc for ePyDoc.
## 2. Renamed helper functions, vars etc. not intended to be visible in public
## interface to code.
##
## Version 1.1 ## Version 1.1
## 1. Added .SetFont() method that properly resizes control ## 1. Added .SetFont() method that properly resizes control
## 2. Modified control to support construction via XRC mechanism. ## 2. Modified control to support construction via XRC mechanism.

View File

@@ -15,44 +15,43 @@
# o Removed wx prefix # o Removed wx prefix
# #
"""<html><body> """
<P>
<B>masked.Ctrl</B> is actually a factory function for several types of *masked.Ctrl* is actually a factory function for several types of
masked edit controls: masked edit controls:
<P>
<UL> ================= =========================================================
<LI><b>masked.TextCtrl</b> - standard masked edit text box</LI> masked.TextCtrl standard masked edit text box
<LI><b>masked.ComboBox</b> - adds combobox capabilities</LI> masked.ComboBox adds combobox capabilities
<LI><b>masked.IpAddrCtrl</b> - adds logical input semantics for IP address entry</LI> masked.IpAddrCtrl adds logical input semantics for IP address entry
<LI><b>masked.TimeCtrl</b> - special subclass handling lots of time formats as values</LI> masked.TimeCtrl special subclass handling lots of time formats as values
<LI><b>masked.NumCtrl</b> - special subclass handling numeric values</LI> masked.NumCtrl special subclass handling numeric values
</UL> ================= =========================================================
<P>
<B>masked.Ctrl</B> works by looking for a special <b><i>controlType</i></b> masked.Ctrl works by looking for a special *controlType*
parameter in the variable arguments of the control, to determine parameter in the variable arguments of the control, to determine
what kind of instance to return. what kind of instance to return.
controlType can be one of: controlType can be one of::
<PRE><FONT SIZE=-1>
controlTypes.TEXT controlTypes.TEXT
controlTypes.COMBO controlTypes.COMBO
controlTypes.IPADDR controlTypes.IPADDR
controlTypes.TIME controlTypes.TIME
controlTypes.NUMBER controlTypes.NUMBER
</FONT></PRE>
These constants are also available individually, ie, you can These constants are also available individually, ie, you can
use either of the following: use either of the following::
<PRE><FONT SIZE=-1>
from wxPython.wx.lib.masked import Ctrl, COMBO, TEXT, NUMBER, TIME from wxPython.wx.lib.masked import Ctrl, COMBO, TEXT, NUMBER, TIME
from wxPython.wx.lib.masked import Ctrl, controlTypes from wxPython.wx.lib.masked import Ctrl, controlTypes
</FONT></PRE>
If not specified as a keyword argument, the default controlType is If not specified as a keyword argument, the default controlType is
controlTypes.TEXT. controlTypes.TEXT.
<P>
Each of the above classes has its own unique arguments, but MaskedCtrl Each of the above classes has its own unique arguments, but Masked.Ctrl
provides a single "unified" interface for masked controls. Masked.TextCtrl, provides a single "unified" interface for masked controls.
masked.ComboBox and masked.IpAddrCtrl are all documented below; the others have
their own demo pages and interface descriptions.
</body></html>
""" """
from wx.lib.masked import TextCtrl, ComboBox, IpAddrCtrl from wx.lib.masked import TextCtrl, ComboBox, IpAddrCtrl

View File

@@ -14,20 +14,27 @@
# address with extra whitespace removed. # address with extra whitespace removed.
# #
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
"""
Provides a smart text input control that understands the structure and
limits of IP Addresses, and allows automatic field navigation as the
user hits '.' when typing.
"""
import wx import wx, types, string
from wx.lib.masked import BaseMaskedTextCtrl from wx.lib.masked import BaseMaskedTextCtrl
# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would # jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
# be a good place to implement the 2.3 logger class # be a good place to implement the 2.3 logger class
from wx.tools.dbg import Logger from wx.tools.dbg import Logger
dbg = Logger() ##dbg = Logger()
##dbg(enable=0) ##dbg(enable=0)
class IpAddrCtrlAccessorsMixin: class IpAddrCtrlAccessorsMixin:
# Define IpAddrCtrl's list of attributes having their own """
# Get/Set functions, exposing only those that make sense for Defines IpAddrCtrl's list of attributes having their own
# an IP address control. Get/Set functions, exposing only those that make sense for
an IP address control.
"""
exposed_basectrl_params = ( exposed_basectrl_params = (
'fields', 'fields',
@@ -116,6 +123,11 @@ class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
def OnDot(self, event): def OnDot(self, event):
"""
Defines what action to take when the '.' character is typed in the
control. By default, the current field is right-justified, and the
cursor is placed in the next field.
"""
## dbg('IpAddrCtrl::OnDot', indent=1) ## dbg('IpAddrCtrl::OnDot', indent=1)
pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode()) pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
oldvalue = self.GetValue() oldvalue = self.GetValue()
@@ -133,6 +145,9 @@ class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
def GetAddress(self): def GetAddress(self):
"""
Returns the control value, with any spaces removed.
"""
value = BaseMaskedTextCtrl.GetValue(self) value = BaseMaskedTextCtrl.GetValue(self)
return value.replace(' ','') # remove spaces from the value return value.replace(' ','') # remove spaces from the value
@@ -144,6 +159,12 @@ class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
return False return False
def SetValue(self, value): def SetValue(self, value):
"""
Takes a string value, validates it for a valid IP address,
splits it into an array of 4 fields, justifies it
appropriately, and inserts it into the control.
Invalid values will raise a ValueError exception.
"""
## dbg('IpAddrCtrl::SetValue(%s)' % str(value), indent=1) ## dbg('IpAddrCtrl::SetValue(%s)' % str(value), indent=1)
if type(value) not in (types.StringType, types.UnicodeType): if type(value) not in (types.StringType, types.UnicodeType):
## dbg(indent=0) ## dbg(indent=0)
@@ -151,6 +172,7 @@ class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
bValid = True # assume True bValid = True # assume True
parts = value.split('.') parts = value.split('.')
if len(parts) != 4: if len(parts) != 4:
bValid = False bValid = False
else: else:
@@ -184,6 +206,15 @@ class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
BaseMaskedTextCtrl.SetValue(self, value) BaseMaskedTextCtrl.SetValue(self, value)
## dbg(indent=0) ## dbg(indent=0)
i=0 __i=0
## CHANGELOG:
## ====================
## Version 1.2
## 1. Fixed bugs involving missing imports now that these classes are in
## their own module.
## 2. Added doc strings for ePyDoc.
## 3. Renamed helper functions, vars etc. not intended to be visible in public
## interface to code.
##
## Version 1.1 ## Version 1.1
## Made ipaddrctrls allow right-insert in subfields, now that insert/cut/paste works better ## Made ipaddrctrls allow right-insert in subfields, now that insert/cut/paste works better

View File

@@ -50,34 +50,39 @@
# o wxTimeCtrl -> TimeCtrl # o wxTimeCtrl -> TimeCtrl
# #
"""\ '''\
<b>Masked Edit Overview: ====================
=====================</b> Masked Edit Overview
<b>masked.TextCtrl</b> ====================
masked.TextCtrl:
is a sublassed text control that can carefully control the user's input is a sublassed text control that can carefully control the user's input
based on a mask string you provide. based on a mask string you provide.
General usage example: General usage example::
control = masked.TextCtrl( win, -1, '', mask = '(###) ###-####') control = masked.TextCtrl( win, -1, '', mask = '(###) ###-####')
The example above will create a text control that allows only numbers to be The example above will create a text control that allows only numbers to be
entered and then only in the positions indicated in the mask by the # sign. entered and then only in the positions indicated in the mask by the # sign.
<b>masked.ComboBox</b> masked.ComboBox:
is a similar subclass of wxComboBox that allows the same sort of masking, is a similar subclass of wxComboBox that allows the same sort of masking,
but also can do auto-complete of values, and can require the value typed but also can do auto-complete of values, and can require the value typed
to be in the list of choices to be colored appropriately. to be in the list of choices to be colored appropriately.
<b>masked.Ctrl</b> masked.Ctrl:
is actually a factory function for several types of masked edit controls: is actually a factory function for several types of masked edit controls:
<b>masked.TextCtrl</b> - standard masked edit text box ================= ==================================================
<b>masked.ComboBox</b> - adds combobox capabilities masked.TextCtrl standard masked edit text box
<b>masked.IpAddrCtrl</b> - adds special semantics for IP address entry masked.ComboBox adds combobox capabilities
<b>masked.TimeCtrl</b> - special subclass handling lots of types as values masked.IpAddrCtrl adds special semantics for IP address entry
<b>masked.NumCtrl</b> - special subclass handling numeric values masked.TimeCtrl special subclass handling lots of types as values
masked.NumCtrl special subclass handling numeric values
================= ==================================================
It works by looking for a <b><i>controlType</i></b> parameter in the keyword It works by looking for a *controlType* parameter in the keyword
arguments of the control, to determine what kind of instance to return. arguments of the control, to determine what kind of instance to return.
If not specified as a keyword argument, the default control type returned If not specified as a keyword argument, the default control type returned
will be masked.TextCtrl. will be masked.TextCtrl.
@@ -89,19 +94,25 @@
(See end of following discussion for how to configure the wx.MaskedCtrl() (See end of following discussion for how to configure the wx.MaskedCtrl()
to select the above control types.) to select the above control types.)
=========================
<b>INITILIZATION PARAMETERS Initialization Parameters
======================== -------------------------
mask=</b> mask
Allowed mask characters and function: Allowed mask characters and function:
========= ==========================================================
Character Function Character Function
# Allow numeric only (0-9) ========= ==========================================================
N Allow letters and numbers (0-9) # Allow numeric only (0-9)
A Allow uppercase letters only N Allow letters and numbers (0-9)
a Allow lowercase letters only A Allow uppercase letters only
C Allow any letter, upper or lower a Allow lowercase letters only
X Allow string.letters, string.punctuation, string.digits C Allow any letter, upper or lower
&amp; Allow string.punctuation only X Allow string.letters, string.punctuation, string.digits
& Allow string.punctuation only
\* Allow any ansi character
========= ==========================================================
These controls define these sets of characters using string.letters, These controls define these sets of characters using string.letters,
@@ -111,11 +122,13 @@ Allowed mask characters and function:
set the locale. set the locale.
For example, to allow international characters to be used in the For example, to allow international characters to be used in the
above masks, you can place the following in your code as part of above masks, you can place the following in your code as part of
your application's initialization code: your application's initialization code::
import locale import locale
locale.setlocale(locale.LC_ALL, '') locale.setlocale(locale.LC_ALL, '')
The controls now also support (by popular demand) all "ansi" chars,
that is, all ascii codes between 32 and 255, by use of the * mask character.
Using these mask characters, a variety of template masks can be built. See Using these mask characters, a variety of template masks can be built. See
the demo for some other common examples include date+time, social security the demo for some other common examples include date+time, social security
@@ -124,7 +137,7 @@ Allowed mask characters and function:
(use \\ for literal backslash, as in: r'CCC\\NNN'.) (use \\ for literal backslash, as in: r'CCC\\NNN'.)
<b>Note:</b> *Note:*
Masks containing only # characters and one optional decimal point Masks containing only # characters and one optional decimal point
character are handled specially, as "numeric" controls. Such character are handled specially, as "numeric" controls. Such
controls have special handling for typing the '-' key, handling controls have special handling for typing the '-' key, handling
@@ -135,36 +148,43 @@ Allowed mask characters and function:
forth (see below). These allow you to construct reasonable forth (see below). These allow you to construct reasonable
numeric entry controls. numeric entry controls.
<b>Note:</b> *Note:*
Changing the mask for a control deletes any previous field classes Changing the mask for a control deletes any previous field classes
(and any associated validation or formatting constraints) for them. (and any associated validation or formatting constraints) for them.
<b>useFixedWidthFont=</b> useFixedWidthFont
By default, masked edit controls use a fixed width font, so that By default, masked edit controls use a fixed width font, so that
the mask characters are fixed within the control, regardless of the mask characters are fixed within the control, regardless of
subsequent modifications to the value. Set to False if having subsequent modifications to the value. Set to False if having
the control font be the same as other controls is required. the control font be the same as other controls is required. (This is
a control-level parameter.)
defaultEncoding
(Applies to unicode systems only) By default, the default unicode encoding
used is latin1, or iso-8859-1. If necessary, you can set this control-level
parameter to govern the codec used to decode your keyboard inputs.
(This is a control-level parameter.)
<b>formatcodes=</b> formatcodes
These other properties can be passed to the class when instantiating it: These other properties can be passed to the class when instantiating it:
Formatcodes are specified as a string of single character formatting Formatcodes are specified as a string of single character formatting
codes that modify behavior of the control: codes that modify behavior of the control::
_ Allow spaces _ Allow spaces
! Force upper ! Force upper
^ Force lower ^ Force lower
R Right-align field(s) R Right-align field(s)
r Right-insert in field(s) (implies R) r Right-insert in field(s) (implies R)
&lt; Stay in field until explicit navigation out of it < Stay in field until explicit navigation out of it
&gt; Allow insert/delete within partially filled fields (as > Allow insert/delete within partially filled fields (as
opposed to the default "overwrite" mode for fixed-width opposed to the default "overwrite" mode for fixed-width
masked edit controls.) This allows single-field controls masked edit controls.) This allows single-field controls
or each field within a multi-field control to optionally or each field within a multi-field control to optionally
behave more like standard text controls. behave more like standard text controls.
(See EMAIL or phone number autoformat examples.) (See EMAIL or phone number autoformat examples.)
<i>Note: This also governs whether backspace/delete operations *Note: This also governs whether backspace/delete operations
shift contents of field to right of cursor, or just blank the shift contents of field to right of cursor, or just blank the
erased section. erased section.
@@ -172,7 +192,7 @@ Allowed mask characters and function:
or control allows right insert anywhere within the current or control allows right insert anywhere within the current
non-empty value in the field. (Otherwise right-insert behavior non-empty value in the field. (Otherwise right-insert behavior
is only performed to when the entire right-insertable field is is only performed to when the entire right-insertable field is
selected or the cursor is at the right edge of the field.</i> selected or the cursor is at the right edge of the field.*
, Allow grouping character in integer fields of numeric controls , Allow grouping character in integer fields of numeric controls
@@ -202,8 +222,9 @@ Allowed mask characters and function:
(See USSTATE autoformat demo for how this can be used.) (See USSTATE autoformat demo for how this can be used.)
S select entire field when navigating to new field S select entire field when navigating to new field
<b>fillChar= fillChar
defaultValue=</b>
defaultValue
These controls have two options for the initial state of the control. These controls have two options for the initial state of the control.
If a blank control with just the non-editable characters showing If a blank control with just the non-editable characters showing
is desired, simply leave the constructor variable fillChar as its is desired, simply leave the constructor variable fillChar as its
@@ -217,31 +238,39 @@ defaultValue=</b>
This value must satisfy the non-editable characters of the mask, This value must satisfy the non-editable characters of the mask,
but need not conform to the replaceable characters. but need not conform to the replaceable characters.
<b>groupChar= groupChar
decimalChar=</b>
decimalChar
These parameters govern what character is used to group numbers These parameters govern what character is used to group numbers
and is used to indicate the decimal point for numeric format controls. and is used to indicate the decimal point for numeric format controls.
The default groupChar is ',', the default decimalChar is '.' The default groupChar is ',', the default decimalChar is '.'
By changing these, you can customize the presentation of numbers By changing these, you can customize the presentation of numbers
for your location. for your location.
eg: formatcodes = ',', groupChar="'" allows 12'345.34
formatcodes = ',', groupChar='.', decimalChar=',' allows 12.345,34
<b>shiftDecimalChar=</b> Eg::
formatcodes = ',', groupChar="'" allows 12'345.34
formatcodes = ',', groupChar='.', decimalChar=',' allows 12.345,34
(These are control-level parameters.)
shiftDecimalChar
The default "shiftDecimalChar" (used for "backwards-tabbing" until The default "shiftDecimalChar" (used for "backwards-tabbing" until
shift-tab is fixed in wxPython) is '>' (for QUERTY keyboards.) for shift-tab is fixed in wxPython) is '>' (for QUERTY keyboards.) for
other keyboards, you may want to customize this, eg '?' for shift ',' on other keyboards, you may want to customize this, eg '?' for shift ',' on
AZERTY keyboards, ':' or ';' for other European keyboards, etc. AZERTY keyboards, ':' or ';' for other European keyboards, etc.
(This is a control-level parameter.)
<b>useParensForNegatives=False</b> useParensForNegatives=False
This option can be used with signed numeric format controls to This option can be used with signed numeric format controls to
indicate signs via () rather than '-'. indicate signs via () rather than '-'.
(This is a control-level parameter.)
<b>autoSelect=False</b> autoSelect=False
This option can be used to have a field or the control try to This option can be used to have a field or the control try to
auto-complete on each keystroke if choices have been specified. auto-complete on each keystroke if choices have been specified.
<b>autoCompleteKeycodes=[]</b> autoCompleteKeycodes=[]
By default, DownArrow, PageUp and PageDown will auto-complete a By default, DownArrow, PageUp and PageDown will auto-complete a
partially entered field. Shift-DownArrow, Shift-UpArrow, PageUp partially entered field. Shift-DownArrow, Shift-UpArrow, PageUp
and PageDown will also auto-complete, but if the field already and PageDown will also auto-complete, but if the field already
@@ -252,72 +281,81 @@ decimalChar=</b>
Additional auto-complete keys can be specified via this parameter. Additional auto-complete keys can be specified via this parameter.
Any keys so specified will act like PageDown. Any keys so specified will act like PageDown.
(This is a control-level parameter.)
<b>Validating User Input: Validating User Input
======================</b> =====================
There are a variety of initialization parameters that are used to validate There are a variety of initialization parameters that are used to validate
user input. These parameters can apply to the control as a whole, and/or user input. These parameters can apply to the control as a whole, and/or
to individual fields: to individual fields:
excludeChars= A string of characters to exclude even if otherwise allowed ===================== ==================================================================
includeChars= A string of characters to allow even if otherwise disallowed excludeChars A string of characters to exclude even if otherwise allowed
validRegex= Use a regular expression to validate the contents of the text box includeChars A string of characters to allow even if otherwise disallowed
validRange= Pass a rangeas list (low,high) to limit numeric fields/values validRegex Use a regular expression to validate the contents of the text box
choices= A list of strings that are allowed choices for the control. validRange Pass a rangeas list (low,high) to limit numeric fields/values
choiceRequired= value must be member of choices list choices A list of strings that are allowed choices for the control.
compareNoCase= Perform case-insensitive matching when validating against list choiceRequired value must be member of choices list
<i>Note: for masked.ComboBox, this defaults to True.</i> compareNoCase Perform case-insensitive matching when validating against list
emptyInvalid= Boolean indicating whether an empty value should be considered invalid *Note: for masked.ComboBox, this defaults to True.*
emptyInvalid Boolean indicating whether an empty value should be considered
invalid
validFunc= A function to call of the form: bool = func(candidate_value) validFunc A function to call of the form: bool = func(candidate_value)
which will return True if the candidate_value satisfies some which will return True if the candidate_value satisfies some
external criteria for the control in addition to the the external criteria for the control in addition to the the
other validation, or False if not. (This validation is other validation, or False if not. (This validation is
applied last in the chain of validations.) applied last in the chain of validations.)
validRequired= Boolean indicating whether or not keys that are allowed by the validRequired Boolean indicating whether or not keys that are allowed by the
mask, but result in an invalid value are allowed to be entered mask, but result in an invalid value are allowed to be entered
into the control. Setting this to True implies that a valid into the control. Setting this to True implies that a valid
default value is set for the control. default value is set for the control.
retainFieldValidation= retainFieldValidation False by default; if True, this allows individual fields to
False by default; if True, this allows individual fields to retain their own validation constraints independently of any
retain their own validation constraints independently of any subsequent changes to the control's overall parameters.
subsequent changes to the control's overall parameters. (This is a control-level parameter.)
validator= Validators are not normally needed for masked controls, because validator Validators are not normally needed for masked controls, because
of the nature of the validation and control of input. However, of the nature of the validation and control of input. However,
you can supply one to provide data transfer routines for the you can supply one to provide data transfer routines for the
controls. controls.
===================== ==================================================================
<b>Coloring Behavior: Coloring Behavior
==================</b> =================
The following parameters have been provided to allow you to change the default The following parameters have been provided to allow you to change the default
coloring behavior of the control. These can be set at construction, or via coloring behavior of the control. These can be set at construction, or via
the .SetCtrlParameters() function. Pass a color as string e.g. 'Yellow': the .SetCtrlParameters() function. Pass a color as string e.g. 'Yellow':
emptyBackgroundColour= Control Background color when identified as empty. Default=White ======================== =======================================================================
invalidBackgroundColour= Control Background color when identified as Not valid. Default=Yellow emptyBackgroundColour Control Background color when identified as empty. Default=White
validBackgroundColour= Control Background color when identified as Valid. Default=white invalidBackgroundColour Control Background color when identified as Not valid. Default=Yellow
validBackgroundColour Control Background color when identified as Valid. Default=white
======================== =======================================================================
The following parameters control the default foreground color coloring behavior of the The following parameters control the default foreground color coloring behavior of the
control. Pass a color as string e.g. 'Yellow': control. Pass a color as string e.g. 'Yellow':
foregroundColour= Control foreground color when value is not negative. Default=Black
signedForegroundColour= Control foreground color when value is negative. Default=Red ======================== ======================================================================
foregroundColour Control foreground color when value is not negative. Default=Black
signedForegroundColour Control foreground color when value is negative. Default=Red
======================== ======================================================================
<b>Fields: Fields
=======</b> ======
Each part of the mask that allows user input is considered a field. The fields Each part of the mask that allows user input is considered a field. The fields
are represented by their own class instances. You can specify field-specific are represented by their own class instances. You can specify field-specific
constraints by constructing or accessing the field instances for the control constraints by constructing or accessing the field instances for the control
and then specifying those constraints via parameters. and then specifying those constraints via parameters.
<b>fields=</b> fields
This parameter allows you to specify Field instances containing This parameter allows you to specify Field instances containing
constraints for the individual fields of a control, eg: local constraints for the individual fields of a control, eg: local
choice lists, validation rules, functions, regexps, etc. choice lists, validation rules, functions, regexps, etc.
@@ -329,50 +367,57 @@ decimalChar=</b>
Any field not represented by the list or dictionary will be Any field not represented by the list or dictionary will be
implicitly created by the control. implicitly created by the control.
eg: Eg::
fields = [ Field(formatcodes='_r'), Field('choices=['a', 'b', 'c']) ] fields = [ Field(formatcodes='_r'), Field('choices=['a', 'b', 'c']) ]
or
Or::
fields = { fields = {
1: ( Field(formatcodes='_R', choices=['a', 'b', 'c']), 1: ( Field(formatcodes='_R', choices=['a', 'b', 'c']),
3: ( Field(choices=['01', '02', '03'], choiceRequired=True) 3: ( Field(choices=['01', '02', '03'], choiceRequired=True)
} }
The following parameters are available for individual fields, with the The following parameters are available for individual fields, with the
same semantics as for the whole control but applied to the field in question: same semantics as for the whole control but applied to the field in question:
fillChar # if set for a field, it will override the control's fillChar for that field ============== =============================================================================
groupChar # if set for a field, it will override the control's default fillChar if set for a field, it will override the control's fillChar for that field
defaultValue # sets field-specific default value; overrides any default from control groupChar if set for a field, it will override the control's default
compareNoCase # overrides control's settings defaultValue sets field-specific default value; overrides any default from control
emptyInvalid # determines whether field is required to be filled at all times compareNoCase overrides control's settings
validRequired # if set, requires field to contain valid value emptyInvalid determines whether field is required to be filled at all times
validRequired if set, requires field to contain valid value
============== =============================================================================
If any of the above parameters are subsequently specified for the control as a If any of the above parameters are subsequently specified for the control as a
whole, that new value will be propagated to each field, unless the whole, that new value will be propagated to each field, unless the
retainFieldValidation control-level parameter is set. retainFieldValidation control-level parameter is set.
formatcodes # Augments control's settings ============== ==============================
excludeChars # ' ' ' formatcodes Augments control's settings
includeChars # ' ' ' excludeChars ' ' '
validRegex # ' ' ' includeChars ' ' '
validRange # ' ' ' validRegex ' ' '
choices # ' ' ' validRange ' ' '
choiceRequired # ' ' ' choices ' ' '
validFunc # ' ' ' choiceRequired ' ' '
validFunc ' ' '
============== ==============================
<b>Control Class Functions: Control Class Functions
======================== =======================
.GetPlainValue(value=None)</b> .GetPlainValue(value=None)
Returns the value specified (or the control's text value Returns the value specified (or the control's text value
not specified) without the formatting text. not specified) without the formatting text.
In the example above, might return phone no='3522640075', In the example above, might return phone no='3522640075',
whereas control.GetValue() would return '(352) 264-0075' whereas control.GetValue() would return '(352) 264-0075'
<b>.ClearValue()</b> .ClearValue()
Returns the control's value to its default, and places the Returns the control's value to its default, and places the
cursor at the beginning of the control. cursor at the beginning of the control.
<b>.SetValue()</b> .SetValue()
Does "smart replacement" of passed value into the control, as does Does "smart replacement" of passed value into the control, as does
the .Paste() method. As with other text entry controls, the the .Paste() method. As with other text entry controls, the
.SetValue() text replacement begins at left-edge of the control, .SetValue() text replacement begins at left-edge of the control,
@@ -384,7 +429,9 @@ decimalChar=</b>
control before attempting to set the value. control before attempting to set the value.
If a value does not follow the format of the control's mask, or will If a value does not follow the format of the control's mask, or will
not fit into the control, a ValueError exception will be raised. not fit into the control, a ValueError exception will be raised.
Eg:
Eg::
mask = '(###) ###-####' mask = '(###) ###-####'
.SetValue('1234567890') => '(123) 456-7890' .SetValue('1234567890') => '(123) 456-7890'
.SetValue('(123)4567890') => '(123) 456-7890' .SetValue('(123)4567890') => '(123) 456-7890'
@@ -403,53 +450,58 @@ decimalChar=</b>
.SetValue('%.2f' % -111.12345 ) => ' -111.12' .SetValue('%.2f' % -111.12345 ) => ' -111.12'
<b>.IsValid(value=None)</b> .IsValid(value=None)
Returns True if the value specified (or the value of the control Returns True if the value specified (or the value of the control
if not specified) passes validation tests if not specified) passes validation tests
<b>.IsEmpty(value=None)</b> .IsEmpty(value=None)
Returns True if the value specified (or the value of the control Returns True if the value specified (or the value of the control
if not specified) is equal to an "empty value," ie. all if not specified) is equal to an "empty value," ie. all
editable characters == the fillChar for their respective fields. editable characters == the fillChar for their respective fields.
<b>.IsDefault(value=None)</b> .IsDefault(value=None)
Returns True if the value specified (or the value of the control Returns True if the value specified (or the value of the control
if not specified) is equal to the initial value of the control. if not specified) is equal to the initial value of the control.
<b>.Refresh()</b> .Refresh()
Recolors the control as appropriate to its current settings. Recolors the control as appropriate to its current settings.
<b>.SetCtrlParameters(**kwargs)</b> .SetCtrlParameters(\*\*kwargs)
This function allows you to set up and/or change the control parameters This function allows you to set up and/or change the control parameters
after construction; it takes a list of key/value pairs as arguments, after construction; it takes a list of key/value pairs as arguments,
where the keys can be any of the mask-specific parameters in the constructor. where the keys can be any of the mask-specific parameters in the constructor.
Eg:
Eg::
ctl = masked.TextCtrl( self, -1 ) ctl = masked.TextCtrl( self, -1 )
ctl.SetCtrlParameters( mask='###-####', ctl.SetCtrlParameters( mask='###-####',
defaultValue='555-1212', defaultValue='555-1212',
formatcodes='F') formatcodes='F')
<b>.GetCtrlParameter(parametername)</b> .GetCtrlParameter(parametername)
This function allows you to retrieve the current value of a parameter This function allows you to retrieve the current value of a parameter
from the control. from the control.
<b><i>Note:</i></b> Each of the control parameters can also be set using its *Note:* Each of the control parameters can also be set using its
own Set and Get function. These functions follow a regular form: own Set and Get function. These functions follow a regular form:
All of the parameter names start with lower case; for their All of the parameter names start with lower case; for their
corresponding Set/Get function, the parameter name is capitalized. corresponding Set/Get function, the parameter name is capitalized.
Eg: ctl.SetMask('###-####')
Eg::
ctl.SetMask('###-####')
ctl.SetDefaultValue('555-1212') ctl.SetDefaultValue('555-1212')
ctl.GetChoiceRequired() ctl.GetChoiceRequired()
ctl.GetFormatcodes() ctl.GetFormatcodes()
<b><i>Note:</i></b> After any change in parameters, the choices for the *Note:* After any change in parameters, the choices for the
control are reevaluated to ensure that they are still legal. If you control are reevaluated to ensure that they are still legal. If you
have large choice lists, it is therefore more efficient to set parameters have large choice lists, it is therefore more efficient to set parameters
before setting the choices available. before setting the choices available.
<b>.SetFieldParameters(field_index, **kwargs)</b> .SetFieldParameters(field_index, \*\*kwargs)
This function allows you to specify change individual field This function allows you to specify change individual field
parameters after construction. (Indices are 0-based.) parameters after construction. (Indices are 0-based.)
<b>.GetFieldParameter(field_index, parametername)</b> .GetFieldParameter(field_index, parametername)
Allows the retrieval of field parameters after construction Allows the retrieval of field parameters after construction
@@ -472,12 +524,12 @@ Take a look at the demo; the zip-code validation succeeds as long as the
first five numerals are entered. the last four are optional, but if first five numerals are entered. the last four are optional, but if
any are entered, there must be 4 to be valid. any are entered, there must be 4 to be valid.
<B>masked.Ctrl Configuration masked.Ctrl Configuration
==========================</B> =========================
masked.Ctrl works by looking for a special <b><i>controlType</i></b> masked.Ctrl works by looking for a special *controlType*
parameter in the variable arguments of the control, to determine parameter in the variable arguments of the control, to determine
what kind of instance to return. what kind of instance to return.
controlType can be one of: controlType can be one of::
controlTypes.TEXT controlTypes.TEXT
controlTypes.COMBO controlTypes.COMBO
@@ -486,14 +538,15 @@ controlType can be one of:
controlTypes.NUMBER controlTypes.NUMBER
These constants are also available individually, ie, you can These constants are also available individually, ie, you can
use either of the following: use either of the following::
from wxPython.wx.lib.masked import MaskedCtrl, controlTypes from wxPython.wx.lib.masked import MaskedCtrl, controlTypes
from wxPython.wx.lib.masked import MaskedCtrl, COMBO, TEXT, NUMBER, IPADDR from wxPython.wx.lib.masked import MaskedCtrl, COMBO, TEXT, NUMBER, IPADDR
If not specified as a keyword argument, the default controlType is If not specified as a keyword argument, the default controlType is
controlTypes.TEXT. controlTypes.TEXT.
"""
'''
""" """
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -756,7 +809,7 @@ import wx
# be a good place to implement the 2.3 logger class # be a good place to implement the 2.3 logger class
from wx.tools.dbg import Logger from wx.tools.dbg import Logger
dbg = Logger() ##dbg = Logger()
##dbg(enable=1) ##dbg(enable=1)
## ---------- ---------- ---------- ---------- ---------- ---------- ---------- ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
@@ -792,7 +845,10 @@ control = (
## X- allow any character (string.letters, string.punctuation, string.digits) ## X- allow any character (string.letters, string.punctuation, string.digits)
## Note: locale settings affect what "uppercase", lowercase, etc comprise. ## Note: locale settings affect what "uppercase", lowercase, etc comprise.
## ##
maskchars = ("#","A","a","X","C","N", '&') maskchars = ("#","A","a","X","C","N",'*','&')
ansichars = ""
for i in xrange(32, 256):
ansichars += chr(i)
months = '(01|02|03|04|05|06|07|08|09|10|11|12)' months = '(01|02|03|04|05|06|07|08|09|10|11|12)'
charmonths = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)' charmonths = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)'
@@ -1181,6 +1237,16 @@ autoformats.sort()
## ---------- ---------- ---------- ---------- ---------- ---------- ---------- ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
class Field: class Field:
"""
This class manages the individual fields in a masked edit control.
Each field has a zero-based index, indicating its position in the
control, an extent, an associated mask, and a plethora of optional
parameters. Fields can be instantiated and then associated with
parent masked controls, in order to provide field-specific configuration.
Alternatively, fields will be implicitly created by the parent control
if not provided at construction, at which point, the fields can then
manipulated by the controls .SetFieldParameters() method.
"""
valid_params = { valid_params = {
'index': None, ## which field of mask; set by parent control. 'index': None, ## which field of mask; set by parent control.
'mask': "", ## mask chars for this field 'mask': "", ## mask chars for this field
@@ -1250,7 +1316,7 @@ class Field:
## dbg(indent=0, suspend=0) ## dbg(indent=0, suspend=0)
raise AttributeError('invalid keyword argument "%s"' % key) raise AttributeError('invalid keyword argument "%s"' % key)
if self._index is not None: dbg('field index:', self._index) ## if self._index is not None: dbg('field index:', self._index)
## dbg('parameters:', indent=1) ## dbg('parameters:', indent=1)
for key, value in kwargs.items(): for key, value in kwargs.items():
## dbg('%s:' % key, value) ## dbg('%s:' % key, value)
@@ -1293,7 +1359,7 @@ class Field:
#### dbg("self._old_fillChar: '%s'" % self._old_fillChar) #### dbg("self._old_fillChar: '%s'" % self._old_fillChar)
if kwargs.has_key('mask') or kwargs.has_key('validRegex'): # (set/changed) if kwargs.has_key('mask') or kwargs.has_key('validRegex'): # (set/changed)
self._isInt = isInteger(self._mask) self._isInt = _isInteger(self._mask)
## dbg('isInt?', self._isInt, 'self._mask:"%s"' % self._mask) ## dbg('isInt?', self._isInt, 'self._mask:"%s"' % self._mask)
## dbg(indent=0, suspend=0) ## dbg(indent=0, suspend=0)
@@ -1306,7 +1372,7 @@ class Field:
""" """
## dbg(suspend=1) ## dbg(suspend=1)
## dbg('maskededit.Field::_ValidateParameters', indent=1) ## dbg('maskededit.Field::_ValidateParameters', indent=1)
if self._index is not None: dbg('field index:', self._index) ## if self._index is not None: dbg('field index:', self._index)
#### dbg('parameters:', indent=1) #### dbg('parameters:', indent=1)
## for key, value in kwargs.items(): ## for key, value in kwargs.items():
#### dbg('%s:' % key, value) #### dbg('%s:' % key, value)
@@ -1582,6 +1648,7 @@ class MaskedEditMixin:
""" """
This class allows us to abstract the masked edit functionality that could This class allows us to abstract the masked edit functionality that could
be associated with any text entry control. (eg. wx.TextCtrl, wx.ComboBox, etc.) be associated with any text entry control. (eg. wx.TextCtrl, wx.ComboBox, etc.)
It forms the basis for all of the lib.masked controls.
""" """
valid_ctrl_params = { valid_ctrl_params = {
'mask': 'XXXXXXXXXXXXX', ## mask string for formatting this control 'mask': 'XXXXXXXXXXXXX', ## mask string for formatting this control
@@ -1590,6 +1657,7 @@ class MaskedEditMixin:
'datestyle': 'MDY', ## optional date style for date-type values. Can trigger autocomplete year 'datestyle': 'MDY', ## optional date style for date-type values. Can trigger autocomplete year
'autoCompleteKeycodes': [], ## Optional list of additional keycodes which will invoke field-auto-complete 'autoCompleteKeycodes': [], ## Optional list of additional keycodes which will invoke field-auto-complete
'useFixedWidthFont': True, ## Use fixed-width font instead of default for base control 'useFixedWidthFont': True, ## Use fixed-width font instead of default for base control
'defaultEncoding': 'latin1', ## optional argument to indicate unicode codec to use (unicode ctrls only)
'retainFieldValidation': False, ## Set this to true if setting control-level parameters independently, 'retainFieldValidation': False, ## Set this to true if setting control-level parameters independently,
## from field validation constraints ## from field validation constraints
'emptyBackgroundColour': "White", 'emptyBackgroundColour': "White",
@@ -1670,7 +1738,8 @@ class MaskedEditMixin:
'X': string.letters + string.punctuation + string.digits, 'X': string.letters + string.punctuation + string.digits,
'C': string.letters, 'C': string.letters,
'N': string.letters + string.digits, 'N': string.letters + string.digits,
'&': string.punctuation '&': string.punctuation,
'*': ansichars
} }
## self._ignoreChange is used by MaskedComboBox, because ## self._ignoreChange is used by MaskedComboBox, because
@@ -1701,7 +1770,8 @@ class MaskedEditMixin:
def SetCtrlParameters(self, **kwargs): def SetCtrlParameters(self, **kwargs):
""" """
This public function can be used to set individual or multiple masked edit This public function can be used to set individual or multiple masked edit
parameters after construction. parameters after construction. (See maskededit module overview for the list
of valid parameters.)
""" """
## dbg(suspend=1) ## dbg(suspend=1)
## dbg('MaskedEditMixin::SetCtrlParameters', indent=1) ## dbg('MaskedEditMixin::SetCtrlParameters', indent=1)
@@ -1850,8 +1920,8 @@ class MaskedEditMixin:
self._autofit = self._ctrl_constraints._autofit self._autofit = self._ctrl_constraints._autofit
self._isNeg = False self._isNeg = False
self._isDate = 'D' in self._ctrl_constraints._formatcodes and isDateType(mask) self._isDate = 'D' in self._ctrl_constraints._formatcodes and _isDateType(mask)
self._isTime = 'T' in self._ctrl_constraints._formatcodes and isTimeType(mask) self._isTime = 'T' in self._ctrl_constraints._formatcodes and _isTimeType(mask)
if self._isDate: if self._isDate:
# Set _dateExtent, used in date validation to locate date in string; # Set _dateExtent, used in date validation to locate date in string;
# always set as though year will be 4 digits, even if mask only has # always set as though year will be 4 digits, even if mask only has
@@ -1926,7 +1996,7 @@ class MaskedEditMixin:
## dbg(indent=0, suspend=0) ## dbg(indent=0, suspend=0)
def SetMaskParameters(self, **kwargs): def SetMaskParameters(self, **kwargs):
""" old name for this function """ """ old name for the SetCtrlParameters function (DEPRECATED)"""
return self.SetCtrlParameters(**kwargs) return self.SetCtrlParameters(**kwargs)
@@ -1942,7 +2012,7 @@ class MaskedEditMixin:
TypeError('"%s".GetCtrlParameter: invalid parameter "%s"' % (self.name, paramname)) TypeError('"%s".GetCtrlParameter: invalid parameter "%s"' % (self.name, paramname))
def GetMaskParameter(self, paramname): def GetMaskParameter(self, paramname):
""" old name for this function """ """ old name for the GetCtrlParameters function (DEPRECATED)"""
return self.GetCtrlParameter(paramname) return self.GetCtrlParameter(paramname)
@@ -1978,6 +2048,8 @@ class MaskedEditMixin:
Because changes to fields can affect the overall control, Because changes to fields can affect the overall control,
direct access to the fields is prevented, and the control direct access to the fields is prevented, and the control
is always "reconfigured" after setting a field parameter. is always "reconfigured" after setting a field parameter.
(See maskededit module overview for the list of valid field-level
parameters.)
""" """
if field_index not in self._field_indices: if field_index not in self._field_indices:
raise IndexError('%s is not a valid field for control "%s".' % (str(field_index), self.name)) raise IndexError('%s is not a valid field for control "%s".' % (str(field_index), self.name))
@@ -2106,13 +2178,13 @@ class MaskedEditMixin:
self._decimalChar = self._ctrl_constraints._decimalChar self._decimalChar = self._ctrl_constraints._decimalChar
self._shiftDecimalChar = self._ctrl_constraints._shiftDecimalChar self._shiftDecimalChar = self._ctrl_constraints._shiftDecimalChar
self._isFloat = isFloatingPoint(s) and not self._ctrl_constraints._validRegex self._isFloat = _isFloatingPoint(s) and not self._ctrl_constraints._validRegex
self._isInt = isInteger(s) and not self._ctrl_constraints._validRegex self._isInt = _isInteger(s) and not self._ctrl_constraints._validRegex
self._signOk = '-' in self._ctrl_constraints._formatcodes and (self._isFloat or self._isInt) self._signOk = '-' in self._ctrl_constraints._formatcodes and (self._isFloat or self._isInt)
self._useParens = self._ctrl_constraints._useParensForNegatives self._useParens = self._ctrl_constraints._useParensForNegatives
self._isNeg = False self._isNeg = False
#### dbg('self._signOk?', self._signOk, 'self._useParens?', self._useParens) #### dbg('self._signOk?', self._signOk, 'self._useParens?', self._useParens)
#### dbg('isFloatingPoint(%s)?' % (s), isFloatingPoint(s), #### dbg('isFloatingPoint(%s)?' % (s), _isFloatingPoint(s),
## 'ctrl regex:', self._ctrl_constraints._validRegex) ## 'ctrl regex:', self._ctrl_constraints._validRegex)
if self._signOk and s[0] != ' ': if self._signOk and s[0] != ' ':
@@ -2818,22 +2890,34 @@ class MaskedEditMixin:
keep_processing = False keep_processing = False
else: else:
field = self._FindField(pos) field = self._FindField(pos)
## dbg("key ='%s'" % chr(key)) ## dbg("key ='%s'" % chr(key))
if chr(key) == ' ': ## if chr(key) == ' ':
## dbg('okSpaces?', field._okSpaces) ## dbg('okSpaces?', field._okSpaces)
pass ## pass
char = chr(key) # (must work if we got this far)
if chr(key) in field._excludeChars + self._ctrl_constraints._excludeChars: if 'unicode' in wx.PlatformInfo:
char = char.decode(self._defaultEncoding)
excludes = u''
if type(field._excludeChars) != types.UnicodeType:
excludes += field._excludeChars.decode(self._defaultEncoding)
if type(self._ctrl_constraints) != types.UnicodeType:
excludes += self._ctrl_constraints._excludeChars.decode(self._defaultEncoding)
else:
excludes = field._excludeChars + self._ctrl_constraints._excludeChars
if char in excludes:
keep_processing = False keep_processing = False
if keep_processing and self._isCharAllowed( chr(key), pos, checkRegex = True ): if keep_processing and self._isCharAllowed( char, pos, checkRegex = True ):
## dbg("key allowed by mask") ## dbg("key allowed by mask")
# insert key into candidate new value, but don't change control yet: # insert key into candidate new value, but don't change control yet:
oldstr = self._GetValue() oldstr = self._GetValue()
newstr, newpos, new_select_to, match_field, match_index = self._insertKey( newstr, newpos, new_select_to, match_field, match_index = self._insertKey(
chr(key), pos, sel_start, sel_to, self._GetValue(), allowAutoSelect = True) char, pos, sel_start, sel_to, self._GetValue(), allowAutoSelect = True)
## dbg("str with '%s' inserted:" % chr(key), '"%s"' % newstr) ## dbg("str with '%s' inserted:" % char, '"%s"' % newstr)
if self._ctrl_constraints._validRequired and not self.IsValid(newstr): if self._ctrl_constraints._validRequired and not self.IsValid(newstr):
## dbg('not valid; checking to see if adjusted string is:') ## dbg('not valid; checking to see if adjusted string is:')
keep_processing = False keep_processing = False
@@ -4184,10 +4268,10 @@ class MaskedEditMixin:
else: else:
year_field = 2 year_field = 2
## dbg('getYear: "%s"' % getYear(text, self._datestyle)) ## dbg('getYear: "%s"' % _getYear(text, self._datestyle))
year = string.replace( getYear( text, self._datestyle),self._fields[year_field]._fillChar,"") # drop extra fillChars year = string.replace( _getYear( text, self._datestyle),self._fields[year_field]._fillChar,"") # drop extra fillChars
month = getMonth( text, self._datestyle) month = _getMonth( text, self._datestyle)
day = getDay( text, self._datestyle) day = _getDay( text, self._datestyle)
## dbg('self._datestyle:', self._datestyle, 'year:', year, 'Month', month, 'day:', day) ## dbg('self._datestyle:', self._datestyle, 'year:', year, 'Month', month, 'day:', day)
yearVal = None yearVal = None
@@ -4228,7 +4312,7 @@ class MaskedEditMixin:
else: # pad with 0's to make a 4-digit year else: # pad with 0's to make a 4-digit year
year = "%04d" % yearVal year = "%04d" % yearVal
if self._4digityear or force4digit_year: if self._4digityear or force4digit_year:
text = makeDate(year, month, day, self._datestyle, text) + text[self._dateExtent:] text = _makeDate(year, month, day, self._datestyle, text) + text[self._dateExtent:]
## dbg('newdate: "%s"' % text, indent=0) ## dbg('newdate: "%s"' % text, indent=0)
return text return text
@@ -4288,6 +4372,12 @@ class MaskedEditMixin:
""" """
maskChar = self.maskdict[pos] maskChar = self.maskdict[pos]
okchars = self.maskchardict[maskChar] ## entry, get mask approved characters okchars = self.maskchardict[maskChar] ## entry, get mask approved characters
# convert okchars to unicode if required; will force subsequent appendings to
# result in unicode strings
if 'unicode' in wx.PlatformInfo and type(okchars) != types.UnicodeType:
okchars = okchars.decode(self._defaultEncoding)
field = self._FindField(pos) field = self._FindField(pos)
if okchars and field._okSpaces: ## Allow spaces? if okchars and field._okSpaces: ## Allow spaces?
okchars += " " okchars += " "
@@ -4861,6 +4951,11 @@ class MaskedEditMixin:
left = text[0:pos] left = text[0:pos]
right = text[pos+1:] right = text[pos+1:]
if 'unicode' in wx.PlatformInfo and type(char) != types.UnicodeType:
# convert the keyboard constant to a unicode value, to
# ensure it can be concatenated into the control value:
char = char.decode(self._defaultEncoding)
newtext = left + char + right newtext = left + char + right
if self._signOk and self._useParens: if self._signOk and self._useParens:
@@ -5108,7 +5203,7 @@ class MaskedEditMixin:
fstr.replace(field._fillChar, ' ') fstr.replace(field._fillChar, ' ')
datestr = datestr[:start] + fstr + datestr[end:] datestr = datestr[:start] + fstr + datestr[end:]
year, month, day = getDateParts( datestr, self._datestyle) year, month, day = _getDateParts( datestr, self._datestyle)
year = int(year) year = int(year)
## dbg('self._dateExtent:', self._dateExtent) ## dbg('self._dateExtent:', self._dateExtent)
if self._dateExtent == 11: if self._dateExtent == 11:
@@ -5186,7 +5281,7 @@ class MaskedEditMixin:
if not valid: if not valid:
## dbg('cannot convert string to valid time') ## dbg('cannot convert string to valid time')
pass pass
if valid: dbg('valid time') ## if valid: dbg('valid time')
## dbg(indent=0) ## dbg(indent=0)
return valid return valid
@@ -5383,6 +5478,9 @@ class MaskedEditMixin:
else: else:
item = 'selection' item = 'selection'
## dbg('maxlength:', maxlength) ## dbg('maxlength:', maxlength)
if 'unicode' in wx.PlatformInfo and type(paste_text) != types.UnicodeType:
paste_text = paste_text.decode(self._defaultEncoding)
length_considered = len(paste_text) length_considered = len(paste_text)
if length_considered > maxlength: if length_considered > maxlength:
## dbg('paste text will not fit into the %s:' % item, indent=0) ## dbg('paste text will not fit into the %s:' % item, indent=0)
@@ -5477,6 +5575,10 @@ class MaskedEditMixin:
paste_text = value paste_text = value
if paste_text is not None: if paste_text is not None:
if 'unicode' in wx.PlatformInfo and type(paste_text) != types.UnicodeType:
paste_text = paste_text.decode(self._defaultEncoding)
## dbg('paste text: "%s"' % paste_text) ## dbg('paste text: "%s"' % paste_text)
# (conversion will raise ValueError if paste isn't legal) # (conversion will raise ValueError if paste isn't legal)
sel_start, sel_to = self._GetSelection() sel_start, sel_to = self._GetSelection()
@@ -5963,32 +6065,32 @@ class MaskedEditMixin:
pass pass
## ---------- ---------- ---------- ---------- ---------- ---------- ---------- ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
# ## TRICKY BIT: to avoid a ton of boiler-plate, and to
# ## automate the getter/setter generation for each valid
# ## control parameter so we never forget to add the
# ## functions when adding parameters, this loop
# ## programmatically adds them to the class:
# ## (This makes it easier for Designers like Boa to
# ## deal with masked controls.)
#
# ## To further complicate matters, this is done with an
# ## extra level of inheritance, so that "general" classes like
# ## MaskedTextCtrl can have all possible attributes,
# ## while derived classes, like TimeCtrl and MaskedNumCtrl
# ## can prevent exposure of those optional attributes of their base
# ## class that do not make sense for their derivation. Therefore,
# ## we define
# ## BaseMaskedTextCtrl(TextCtrl, MaskedEditMixin)
# ## and
# ## MaskedTextCtrl(BaseMaskedTextCtrl, MaskedEditAccessorsMixin).
# ##
# ## This allows us to then derive:
# ## MaskedNumCtrl( BaseMaskedTextCtrl )
# ##
# ## and not have to expose all the same accessor functions for the
# ## derived control when they don't all make sense for it.
# ##
class MaskedEditAccessorsMixin: class MaskedEditAccessorsMixin:
"""
To avoid a ton of boiler-plate, and to automate the getter/setter generation
for each valid control parameter so we never forget to add the functions when
adding parameters, this class programmatically adds the masked edit mixin
parameters to itself.
(This makes it easier for Designers like Boa to deal with masked controls.)
To further complicate matters, this is done with an extra level of inheritance,
so that "general" classes like masked.TextCtrl can have all possible attributes,
while derived classes, like masked.TimeCtrl and masked.NumCtrl can prevent
exposure of those optional attributes of their base class that do not make
sense for their derivation.
Therefore, we define:
BaseMaskedTextCtrl(TextCtrl, MaskedEditMixin)
and
masked.TextCtrl(BaseMaskedTextCtrl, MaskedEditAccessorsMixin).
This allows us to then derive:
masked.NumCtrl( BaseMaskedTextCtrl )
and not have to expose all the same accessor functions for the
derived control when they don't all make sense for it.
"""
# Define the default set of attributes exposed by the most generic masked controls: # Define the default set of attributes exposed by the most generic masked controls:
exposed_basectrl_params = MaskedEditMixin.valid_ctrl_params.keys() + Field.valid_params.keys() exposed_basectrl_params = MaskedEditMixin.valid_ctrl_params.keys() + Field.valid_params.keys()
@@ -6014,7 +6116,7 @@ class MaskedEditAccessorsMixin:
## ---------- ---------- ---------- ---------- ---------- ---------- ---------- ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
## these are helper subroutines: ## these are helper subroutines:
def movetofloat( origvalue, fmtstring, neg, addseparators=False, sepchar = ',',fillchar=' '): def _movetofloat( origvalue, fmtstring, neg, addseparators=False, sepchar = ',',fillchar=' '):
""" addseparators = add separator character every three numerals if True """ addseparators = add separator character every three numerals if True
""" """
fmt0 = fmtstring.split('.') fmt0 = fmtstring.split('.')
@@ -6027,7 +6129,7 @@ def movetofloat( origvalue, fmtstring, neg, addseparators=False, sepchar = ',',f
return (ret,len(fmt1)) return (ret,len(fmt1))
def isDateType( fmtstring ): def _isDateType( fmtstring ):
""" Checks the mask and returns True if it fits an allowed """ Checks the mask and returns True if it fits an allowed
date or datetime format. date or datetime format.
""" """
@@ -6048,7 +6150,7 @@ def isDateType( fmtstring ):
if re.match(filter,fmtstring): return True if re.match(filter,fmtstring): return True
return False return False
def isTimeType( fmtstring ): def _isTimeType( fmtstring ):
""" Checks the mask and returns True if it fits an allowed """ Checks the mask and returns True if it fits an allowed
time format. time format.
""" """
@@ -6058,19 +6160,19 @@ def isTimeType( fmtstring ):
return False return False
def isFloatingPoint( fmtstring): def _isFloatingPoint( fmtstring):
filter = re.compile("[ ]?[#]+\.[#]+\n") filter = re.compile("[ ]?[#]+\.[#]+\n")
if re.match(filter,fmtstring+"\n"): return True if re.match(filter,fmtstring+"\n"): return True
return False return False
def isInteger( fmtstring ): def _isInteger( fmtstring ):
filter = re.compile("[#]+\n") filter = re.compile("[#]+\n")
if re.match(filter,fmtstring+"\n"): return True if re.match(filter,fmtstring+"\n"): return True
return False return False
def getDateParts( dateStr, dateFmt ): def _getDateParts( dateStr, dateFmt ):
if len(dateStr) > 11: clip = dateStr[0:11] if len(dateStr) > 11: clip = dateStr[0:11]
else: clip = dateStr else: clip = dateStr
if clip[-2] not in string.digits: if clip[-2] not in string.digits:
@@ -6092,14 +6194,14 @@ def getDateParts( dateStr, dateFmt ):
return y,m,d return y,m,d
def getDateSepChar(dateStr): def _getDateSepChar(dateStr):
clip = dateStr[0:10] clip = dateStr[0:10]
dateSep = (('/' in clip) * '/') + (('-' in clip) * '-') + (('.' in clip) * '.') dateSep = (('/' in clip) * '/') + (('-' in clip) * '-') + (('.' in clip) * '.')
return dateSep return dateSep
def makeDate( year, month, day, dateFmt, dateStr): def _makeDate( year, month, day, dateFmt, dateStr):
sep = getDateSepChar( dateStr) sep = _getDateSepChar( dateStr)
if dateFmt == "MDY": if dateFmt == "MDY":
return "%s%s%s%s%s" % (month,sep,day,sep,year) ## year, month, date parts return "%s%s%s%s%s" % (month,sep,day,sep,year) ## year, month, date parts
elif dateFmt == "DMY": elif dateFmt == "DMY":
@@ -6110,20 +6212,20 @@ def makeDate( year, month, day, dateFmt, dateStr):
return none return none
def getYear(dateStr,dateFmt): def _getYear(dateStr,dateFmt):
parts = getDateParts( dateStr, dateFmt) parts = _getDateParts( dateStr, dateFmt)
return parts[0] return parts[0]
def getMonth(dateStr,dateFmt): def _getMonth(dateStr,dateFmt):
parts = getDateParts( dateStr, dateFmt) parts = _getDateParts( dateStr, dateFmt)
return parts[1] return parts[1]
def getDay(dateStr,dateFmt): def _getDay(dateStr,dateFmt):
parts = getDateParts( dateStr, dateFmt) parts = _getDateParts( dateStr, dateFmt)
return parts[2] return parts[2]
## ---------- ---------- ---------- ---------- ---------- ---------- ---------- ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
class test(wx.PySimpleApp): class __test(wx.PySimpleApp):
def OnInit(self): def OnInit(self):
from wx.lib.rcsizer import RowColSizer from wx.lib.rcsizer import RowColSizer
self.frame = wx.Frame( None, -1, "MaskedEditMixin 0.0.7 Demo Page #1", size = (700,600)) self.frame = wx.Frame( None, -1, "MaskedEditMixin 0.0.7 Demo Page #1", size = (700,600))
@@ -6247,7 +6349,7 @@ Try entering nonsensical or partial values in validated fields to see what happe
self.frame.Close() self.frame.Close()
def onClickPage(self, event): def onClickPage(self, event):
self.page2 = test2(self.frame,-1,"") self.page2 = __test2(self.frame,-1,"")
self.page2.Show(True) self.page2.Show(True)
def _onCheck1(self,event): def _onCheck1(self,event):
@@ -6279,7 +6381,7 @@ Try entering nonsensical or partial values in validated fields to see what happe
## ---------- ---------- ---------- ---------- ---------- ---------- ---------- ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
class test2(wx.Frame): class __test2(wx.Frame):
def __init__(self, parent, id, caption): def __init__(self, parent, id, caption):
wx.Frame.__init__( self, parent, id, "MaskedEdit control 0.0.7 Demo Page #2 -- AutoFormats", size = (550,600)) wx.Frame.__init__( self, parent, id, "MaskedEdit control 0.0.7 Demo Page #2 -- AutoFormats", size = (550,600))
from wx.lib.rcsizer import RowColSizer from wx.lib.rcsizer import RowColSizer
@@ -6365,9 +6467,9 @@ To see a great example of validations in action, try entering a bad email addres
## ---------- ---------- ---------- ---------- ---------- ---------- ---------- ## ---------- ---------- ---------- ---------- ---------- ---------- ----------
if __name__ == "__main__": if __name__ == "__main__":
app = test(False) app = __test(False)
i=1 __i=0
## ##
## Current Issues: ## Current Issues:
## =================================== ## ===================================
@@ -6426,6 +6528,14 @@ i=1
## CHANGELOG: ## CHANGELOG:
## ==================== ## ====================
## Version 1.8
## 1. Fixed bug involving incorrect variable name, causing combobox autocomplete to fail.
## 2. Added proper support for unicode version of wxPython
## 3. Added * as mask char meaning "all ansi chars" (ordinals 32-255).
## 4. Converted doc strings to use reST format, for ePyDoc documentation.
## 5. Renamed helper functions, classes, etc. not intended to be visible in public
## interface to code.
##
## Version 1.7 ## Version 1.7
## 1. Fixed intra-right-insert-field erase, such that it doesn't leave a hole, but instead ## 1. Fixed intra-right-insert-field erase, such that it doesn't leave a hole, but instead
## shifts the text to the left accordingly. ## shifts the text to the left accordingly.

View File

@@ -44,61 +44,61 @@
# o wxMaskedNumCtrl -> masked.NumCtrl # o wxMaskedNumCtrl -> masked.NumCtrl
# #
"""<html><body> """
<P> masked.NumCtrl:
<B>masked.NumCtrl:</B> - allows you to get and set integer or floating point numbers as value,</LI>
<UL> - provides bounds support and optional value limiting,</LI>
<LI>allows you to get and set integer or floating point numbers as value,</LI> - has the right-insert input style that MaskedTextCtrl supports,</LI>
<LI>provides bounds support and optional value limiting,</LI> - provides optional automatic grouping, sign control and format, grouping and decimal
<LI>has the right-insert input style that MaskedTextCtrl supports,</LI> character selection, etc. etc.</LI>
<LI>provides optional automatic grouping, sign control and format, grouping and decimal
character selection, etc. etc.</LI>
</UL> Being derived from masked.TextCtrl, the control only allows
<P> fixed-point notation. That is, it has a fixed (though reconfigurable)
Being derived from MaskedTextCtrl, the control only allows maximum width for the integer portion and optional fixed width
fixed-point notation. That is, it has a fixed (though reconfigurable) fractional portion.
maximum width for the integer portion and optional fixed width
fractional portion. Here's the API::
<P>
Here's the API: from wx.lib.masked import NumCtrl
<DL><PRE>
<B>masked.NumCtrl</B>( NumCtrl(
parent, id = -1, parent, id = -1,
<B>value</B> = 0, value = 0,
pos = wx.DefaultPosition, pos = wx.DefaultPosition,
size = wx.DefaultSize, size = wx.DefaultSize,
style = 0, style = 0,
validator = wx.DefaultValidator, validator = wx.DefaultValidator,
name = "masked.number", name = "masked.number",
<B>integerWidth</B> = 10, integerWidth = 10,
<B>fractionWidth</B> = 0, fractionWidth = 0,
<B>allowNone</B> = False, allowNone = False,
<B>allowNegative</B> = True, allowNegative = True,
<B>useParensForNegatives</B> = False, useParensForNegatives = False,
<B>groupDigits</B> = False, groupDigits = False,
<B>groupChar</B> = ',', groupChar = ',',
<B>decimalChar</B> = '.', decimalChar = '.',
<B>min</B> = None, min = None,
<B>max</B> = None, max = None,
<B>limited</B> = False, limited = False,
<B>selectOnEntry</b> = True, selectOnEntry = True,
<B>foregroundColour</B> = "Black", foregroundColour = "Black",
<B>signedForegroundColour</B> = "Red", signedForegroundColour = "Red",
<B>emptyBackgroundColour</B> = "White", emptyBackgroundColour = "White",
<B>validBackgroundColour</B> = "White", validBackgroundColour = "White",
<B>invalidBackgroundColour</B> = "Yellow", invalidBackgroundColour = "Yellow",
<B>autoSize</B> = True autoSize = True
) )
</PRE>
<UL>
<DT><B>value</B> value
<DD>If no initial value is set, the default will be zero, or If no initial value is set, the default will be zero, or
the minimum value, if specified. If an illegal string is specified, the minimum value, if specified. If an illegal string is specified,
a ValueError will result. (You can always later set the initial a ValueError will result. (You can always later set the initial
value with SetValue() after instantiation of the control.) value with SetValue() after instantiation of the control.)
<BR>
<DL><B>integerWidth</B> integerWidth
<DD>Indicates how many places to the right of any decimal point Indicates how many places to the right of any decimal point
should be allowed in the control. This will, perforce, limit should be allowed in the control. This will, perforce, limit
the size of the values that can be entered. This number need the size of the values that can be entered. This number need
not include space for grouping characters or the sign, if either not include space for grouping characters or the sign, if either
@@ -106,271 +106,276 @@ Here's the API:
mask is automatically by the control. The default of 10 mask is automatically by the control. The default of 10
will allow any 32 bit integer value. The minimum value will allow any 32 bit integer value. The minimum value
for integerWidth is 1. for integerWidth is 1.
<BR>
<DL><B>fractionWidth</B> fractionWidth
<DD>Indicates how many decimal places to show for numeric value. Indicates how many decimal places to show for numeric value.
If default (0), then the control will display and return only If default (0), then the control will display and return only
integer or long values. integer or long values.
<BR>
<DT><B>allowNone</B> allowNone
<DD>Boolean indicating whether or not the control is allowed to be Boolean indicating whether or not the control is allowed to be
empty, representing a value of None for the control. empty, representing a value of None for the control.
<BR>
<DT><B>allowNegative</B> allowNegative
<DD>Boolean indicating whether or not control is allowed to hold Boolean indicating whether or not control is allowed to hold
negative numbers. negative numbers.
<BR>
<DT><B>useParensForNegatives</B> useParensForNegatives
<DD>If true, this will cause negative numbers to be displayed with ()s If true, this will cause negative numbers to be displayed with ()s
rather than -, (although '-' will still trigger a negative number.) rather than -, (although '-' will still trigger a negative number.)
<BR>
<DT><B>groupDigits</B> groupDigits
<DD>Indicates whether or not grouping characters should be allowed and/or Indicates whether or not grouping characters should be allowed and/or
inserted when leaving the control or the decimal character is entered. inserted when leaving the control or the decimal character is entered.
<BR>
<DT><B>groupChar</B> groupChar
<DD>What grouping character will be used if allowed. (By default ',') What grouping character will be used if allowed. (By default ',')
<BR>
<DT><B>decimalChar</B> decimalChar
<DD>If fractionWidth is > 0, what character will be used to represent If fractionWidth is > 0, what character will be used to represent
the decimal point. (By default '.') the decimal point. (By default '.')
<BR>
<DL><B>min</B> min
<DD>The minimum value that the control should allow. This can be also be The minimum value that the control should allow. This can be also be
adjusted with SetMin(). If the control is not limited, any value adjusted with SetMin(). If the control is not limited, any value
below this bound will result in a background colored with the current below this bound will result in a background colored with the current
invalidBackgroundColour. If the min specified will not fit into the invalidBackgroundColour. If the min specified will not fit into the
control, the min setting will be ignored. control, the min setting will be ignored.
<BR>
<DT><B>max</B> max
<DD>The maximum value that the control should allow. This can be The maximum value that the control should allow. This can be
adjusted with SetMax(). If the control is not limited, any value adjusted with SetMax(). If the control is not limited, any value
above this bound will result in a background colored with the current above this bound will result in a background colored with the current
invalidBackgroundColour. If the max specified will not fit into the invalidBackgroundColour. If the max specified will not fit into the
control, the max setting will be ignored. control, the max setting will be ignored.
<BR>
<DT><B>limited</B> limited
<DD>Boolean indicating whether the control prevents values from Boolean indicating whether the control prevents values from
exceeding the currently set minimum and maximum values (bounds). exceeding the currently set minimum and maximum values (bounds).
If False and bounds are set, out-of-bounds values will If False and bounds are set, out-of-bounds values will
result in a background colored with the current invalidBackgroundColour. result in a background colored with the current invalidBackgroundColour.
<BR>
<DT><B>selectOnEntry</B> selectOnEntry
<DD>Boolean indicating whether or not the value in each field of the Boolean indicating whether or not the value in each field of the
control should be automatically selected (for replacement) when control should be automatically selected (for replacement) when
that field is entered, either by cursor movement or tabbing. that field is entered, either by cursor movement or tabbing.
This can be desirable when using these controls for rapid data entry. This can be desirable when using these controls for rapid data entry.
<BR>
<DT><B>foregroundColour</B> foregroundColour
<DD>Color value used for positive values of the control. Color value used for positive values of the control.
<BR>
<DT><B>signedForegroundColour</B> signedForegroundColour
<DD>Color value used for negative values of the control. Color value used for negative values of the control.
<BR>
<DT><B>emptyBackgroundColour</B> emptyBackgroundColour
<DD>What background color to use when the control is considered What background color to use when the control is considered
"empty." (allow_none must be set to trigger this behavior.) "empty." (allow_none must be set to trigger this behavior.)
<BR>
<DT><B>validBackgroundColour</B> validBackgroundColour
<DD>What background color to use when the control value is What background color to use when the control value is
considered valid. considered valid.
<BR>
<DT><B>invalidBackgroundColour</B> invalidBackgroundColour
<DD>Color value used for illegal values or values out-of-bounds of the Color value used for illegal values or values out-of-bounds of the
control when the bounds are set but the control is not limited. control when the bounds are set but the control is not limited.
<BR>
<DT><B>autoSize</B> autoSize
<DD>Boolean indicating whether or not the control should set its own Boolean indicating whether or not the control should set its own
width based on the integer and fraction widths. True by default. width based on the integer and fraction widths. True by default.
<B><I>Note:</I></B> Setting this to False will produce seemingly odd <I>Note:</I> Setting this to False will produce seemingly odd
behavior unless the control is large enough to hold the maximum behavior unless the control is large enough to hold the maximum
specified value given the widths and the sign positions; if not, specified value given the widths and the sign positions; if not,
the control will appear to "jump around" as the contents scroll. the control will appear to "jump around" as the contents scroll.
(ie. autoSize is highly recommended.) (ie. autoSize is highly recommended.)
</UL>
<BR> --------------------------
<BR>
<DT><B>masked.EVT_NUM(win, id, func)</B> masked.EVT_NUM(win, id, func)
<DD>Respond to a EVT_COMMAND_MASKED_NUMBER_UPDATED event, generated when Respond to a EVT_COMMAND_MASKED_NUMBER_UPDATED event, generated when
the value changes. Notice that this event will always be sent when the the value changes. Notice that this event will always be sent when the
control's contents changes - whether this is due to user input or control's contents changes - whether this is due to user input or
comes from the program itself (for example, if SetValue() is called.) comes from the program itself (for example, if SetValue() is called.)
<BR>
<BR>
<DT><B>SetValue(int|long|float|string)</B> SetValue(int|long|float|string)
<DD>Sets the value of the control to the value specified, if Sets the value of the control to the value specified, if
possible. The resulting actual value of the control may be possible. The resulting actual value of the control may be
altered to conform to the format of the control, changed altered to conform to the format of the control, changed
to conform with the bounds set on the control if limited, to conform with the bounds set on the control if limited,
or colored if not limited but the value is out-of-bounds. or colored if not limited but the value is out-of-bounds.
A ValueError exception will be raised if an invalid value A ValueError exception will be raised if an invalid value
is specified. is specified.
<BR>
<DT><B>GetValue()</B> GetValue()
<DD>Retrieves the numeric value from the control. The value Retrieves the numeric value from the control. The value
retrieved will be either be returned as a long if the retrieved will be either be returned as a long if the
fractionWidth is 0, or a float otherwise. fractionWidth is 0, or a float otherwise.
<BR>
<BR>
<DT><B>SetParameters(**kwargs)</B> SetParameters(\*\*kwargs)
<DD>Allows simultaneous setting of various attributes Allows simultaneous setting of various attributes
of the control after construction. Keyword arguments of the control after construction. Keyword arguments
allowed are the same parameters as supported in the constructor. allowed are the same parameters as supported in the constructor.
<BR>
<BR>
<DT><B>SetIntegerWidth(value)</B> SetIntegerWidth(value)
<DD>Resets the width of the integer portion of the control. The Resets the width of the integer portion of the control. The
value must be >= 1, or an AttributeError exception will result. value must be >= 1, or an AttributeError exception will result.
This value should account for any grouping characters that might This value should account for any grouping characters that might
be inserted (if grouping is enabled), but does not need to account be inserted (if grouping is enabled), but does not need to account
for the sign, as that is handled separately by the control. for the sign, as that is handled separately by the control.
<DT><B>GetIntegerWidth()</B> GetIntegerWidth()
<DD>Returns the current width of the integer portion of the control, Returns the current width of the integer portion of the control,
not including any reserved sign position. not including any reserved sign position.
<BR>
<BR>
<DT><B>SetFractionWidth(value)</B> SetFractionWidth(value)
<DD>Resets the width of the fractional portion of the control. The Resets the width of the fractional portion of the control. The
value must be >= 0, or an AttributeError exception will result. If value must be >= 0, or an AttributeError exception will result. If
0, the current value of the control will be truncated to an integer 0, the current value of the control will be truncated to an integer
value. value.
<DT><B>GetFractionWidth()</B> GetFractionWidth()
<DD>Returns the current width of the fractional portion of the control. Returns the current width of the fractional portion of the control.
<BR>
<BR>
<DT><B>SetMin(min=None)</B> SetMin(min=None)
<DD>Resets the minimum value of the control. If a value of <I>None</I> Resets the minimum value of the control. If a value of <I>None</I>
is provided, then the control will have no explicit minimum value. is provided, then the control will have no explicit minimum value.
If the value specified is greater than the current maximum value, If the value specified is greater than the current maximum value,
then the function returns False and the minimum will not change from then the function returns False and the minimum will not change from
its current setting. On success, the function returns True. its current setting. On success, the function returns True.
<DT><DD>
If successful and the current value is lower than the new lower If successful and the current value is lower than the new lower
bound, if the control is limited, the value will be automatically bound, if the control is limited, the value will be automatically
adjusted to the new minimum value; if not limited, the value in the adjusted to the new minimum value; if not limited, the value in the
control will be colored as invalid. control will be colored as invalid.
<DT><DD>
If min > the max value allowed by the width of the control, If min > the max value allowed by the width of the control,
the function will return False, and the min will not be set. the function will return False, and the min will not be set.
<BR>
<DT><B>GetMin()</B> GetMin()
<DD>Gets the current lower bound value for the control. Gets the current lower bound value for the control.
It will return None if no lower bound is currently specified. It will return None if no lower bound is currently specified.
<BR>
<BR>
<DT><B>SetMax(max=None)</B> SetMax(max=None)
<DD>Resets the maximum value of the control. If a value of <I>None</I> Resets the maximum value of the control. If a value of <I>None</I>
is provided, then the control will have no explicit maximum value. is provided, then the control will have no explicit maximum value.
If the value specified is less than the current minimum value, then If the value specified is less than the current minimum value, then
the function returns False and the maximum will not change from its the function returns False and the maximum will not change from its
current setting. On success, the function returns True. current setting. On success, the function returns True.
<DT><DD>
If successful and the current value is greater than the new upper If successful and the current value is greater than the new upper
bound, if the control is limited the value will be automatically bound, if the control is limited the value will be automatically
adjusted to this maximum value; if not limited, the value in the adjusted to this maximum value; if not limited, the value in the
control will be colored as invalid. control will be colored as invalid.
<DT><DD>
If max > the max value allowed by the width of the control, If max > the max value allowed by the width of the control,
the function will return False, and the max will not be set. the function will return False, and the max will not be set.
<BR>
<DT><B>GetMax()</B> GetMax()
<DD>Gets the current upper bound value for the control. Gets the current upper bound value for the control.
It will return None if no upper bound is currently specified. It will return None if no upper bound is currently specified.
<BR>
<BR>
<DT><B>SetBounds(min=None,max=None)</B> SetBounds(min=None,max=None)
<DD>This function is a convenience function for setting the min and max This function is a convenience function for setting the min and max
values at the same time. The function only applies the maximum bound values at the same time. The function only applies the maximum bound
if setting the minimum bound is successful, and returns True if setting the minimum bound is successful, and returns True
only if both operations succeed. <B><I>Note:</I></B> leaving out an argument only if both operations succeed. <B><I>Note:</I> leaving out an argument
will remove the corresponding bound. will remove the corresponding bound.
<DT><B>GetBounds()</B> GetBounds()
<DD>This function returns a two-tuple (min,max), indicating the This function returns a two-tuple (min,max), indicating the
current bounds of the control. Each value can be None if current bounds of the control. Each value can be None if
that bound is not set. that bound is not set.
<BR>
<BR>
<DT><B>IsInBounds(value=None)</B> IsInBounds(value=None)
<DD>Returns <I>True</I> if no value is specified and the current value Returns <I>True</I> if no value is specified and the current value
of the control falls within the current bounds. This function can also of the control falls within the current bounds. This function can also
be called with a value to see if that value would fall within the current be called with a value to see if that value would fall within the current
bounds of the given control. bounds of the given control.
<BR>
<BR>
<DT><B>SetLimited(bool)</B> SetLimited(bool)
<DD>If called with a value of True, this function will cause the control If called with a value of True, this function will cause the control
to limit the value to fall within the bounds currently specified. to limit the value to fall within the bounds currently specified.
If the control's value currently exceeds the bounds, it will then If the control's value currently exceeds the bounds, it will then
be limited accordingly. be limited accordingly.
If called with a value of False, this function will disable value If called with a value of False, this function will disable value
limiting, but coloring of out-of-bounds values will still take limiting, but coloring of out-of-bounds values will still take
place if bounds have been set for the control. place if bounds have been set for the control.
<DT><B>GetLimited()</B>
<DT><B>IsLimited()</B> GetLimited()
<DD>Returns <I>True</I> if the control is currently limiting the
value to fall within the current bounds. IsLimited()
<BR> Returns <I>True</I> if the control is currently limiting the
<BR> value to fall within the current bounds.
<DT><B>SetAllowNone(bool)</B>
<DD>If called with a value of True, this function will cause the control
to allow the value to be empty, representing a value of None. SetAllowNone(bool)
If called with a value of False, this function will prevent the value If called with a value of True, this function will cause the control
from being None. If the value of the control is currently None, to allow the value to be empty, representing a value of None.
ie. the control is empty, then the value will be changed to that If called with a value of False, this function will prevent the value
of the lower bound of the control, or 0 if no lower bound is set. from being None. If the value of the control is currently None,
<DT><B>GetAllowNone()</B> ie. the control is empty, then the value will be changed to that
<DT><B>IsNoneAllowed()</B> of the lower bound of the control, or 0 if no lower bound is set.
<DD>Returns <I>True</I> if the control currently allows its
value to be None. GetAllowNone()
<BR>
<BR> IsNoneAllowed()
<DT><B>SetAllowNegative(bool)</B> Returns <I>True</I> if the control currently allows its
<DD>If called with a value of True, this function will cause the value to be None.
control to allow the value to be negative (and reserve space for
displaying the sign. If called with a value of False, and the
value of the control is currently negative, the value of the SetAllowNegative(bool)
control will be converted to the absolute value, and then If called with a value of True, this function will cause the
limited appropriately based on the existing bounds of the control control to allow the value to be negative (and reserve space for
(if any). displaying the sign. If called with a value of False, and the
<DT><B>GetAllowNegative()</B> value of the control is currently negative, the value of the
<DT><B>IsNegativeAllowed()</B> control will be converted to the absolute value, and then
<DD>Returns <I>True</I> if the control currently permits values limited appropriately based on the existing bounds of the control
to be negative. (if any).
<BR>
<BR> GetAllowNegative()
<DT><B>SetGroupDigits(bool)</B>
<DD>If called with a value of True, this will make the control IsNegativeAllowed()
automatically add and manage grouping characters to the presented Returns <I>True</I> if the control currently permits values
value in integer portion of the control. to be negative.
<DT><B>GetGroupDigits()</B>
<DT><B>IsGroupingAllowed()</B>
<DD>Returns <I>True</I> if the control is currently set to group digits. SetGroupDigits(bool)
<BR> If called with a value of True, this will make the control
<BR> automatically add and manage grouping characters to the presented
<DT><B>SetGroupChar()</B> value in integer portion of the control.
<DD>Sets the grouping character for the integer portion of the
control. (The default grouping character this is ','. GetGroupDigits()
<DT><B>GetGroupChar()</B>
<DD>Returns the current grouping character for the control. IsGroupingAllowed()
<BR> Returns <I>True</I> if the control is currently set to group digits.
<BR>
<DT><B>SetSelectOnEntry()</B>
<DD>If called with a value of <I>True</I>, this will make the control SetGroupChar()
automatically select the contents of each field as it is entered Sets the grouping character for the integer portion of the
within the control. (The default is True.) control. (The default grouping character this is ','.
<DT><B>GetSelectOnEntry()</B> GetGroupChar()
<DD>Returns <I>True</I> if the control currently auto selects Returns the current grouping character for the control.
the field values on entry.
<BR>
<BR> SetSelectOnEntry()
<DT><B>SetAutoSize(bool)</B> If called with a value of <I>True</I>, this will make the control
<DD>Resets the autoSize attribute of the control. automatically select the contents of each field as it is entered
<DT><B>GetAutoSize()</B> within the control. (The default is True.)
<DD>Returns the current state of the autoSize attribute for the control. GetSelectOnEntry()
<BR> Returns <I>True</I> if the control currently auto selects
<BR> the field values on entry.
</DL>
</body></html>
SetAutoSize(bool)
Resets the autoSize attribute of the control.
GetAutoSize()
Returns the current state of the autoSize attribute for the control.
""" """
import copy import copy
@@ -396,6 +401,10 @@ EVT_NUM = wx.PyEventBinder(wxEVT_COMMAND_MASKED_NUMBER_UPDATED, 1)
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
class NumberUpdatedEvent(wx.PyCommandEvent): class NumberUpdatedEvent(wx.PyCommandEvent):
"""
Used to fire an EVT_NUM event whenever the value in a NumCtrl changes.
"""
def __init__(self, id, value = 0, object=None): def __init__(self, id, value = 0, object=None):
wx.PyCommandEvent.__init__(self, wxEVT_COMMAND_MASKED_NUMBER_UPDATED, id) wx.PyCommandEvent.__init__(self, wxEVT_COMMAND_MASKED_NUMBER_UPDATED, id)
@@ -410,9 +419,11 @@ class NumberUpdatedEvent(wx.PyCommandEvent):
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
class NumCtrlAccessorsMixin: class NumCtrlAccessorsMixin:
# Define masked.NumCtrl's list of attributes having their own """
# Get/Set functions, ignoring those that make no sense for Defines masked.NumCtrl's list of attributes having their own
# an numeric control. Get/Set functions, ignoring those that make no sense for
a numeric control.
"""
exposed_basectrl_params = ( exposed_basectrl_params = (
'decimalChar', 'decimalChar',
'shiftDecimalChar', 'shiftDecimalChar',
@@ -449,6 +460,11 @@ class NumCtrlAccessorsMixin:
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
"""
Masked edit control supporting "native" numeric values, ie. .SetValue(3), for
example, and supporting a variety of formatting options, including automatic
rounding specifiable precision, grouping and decimal place characters, etc.
"""
valid_ctrl_params = { valid_ctrl_params = {
@@ -591,7 +607,8 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
def SetParameters(self, **kwargs): def SetParameters(self, **kwargs):
""" """
This routine is used to initialize and reconfigure the control: This function is used to initialize and reconfigure the control.
See TimeCtrl module overview for available parameters.
""" """
## dbg('NumCtrl::SetParameters', indent=1) ## dbg('NumCtrl::SetParameters', indent=1)
maskededit_kwargs = {} maskededit_kwargs = {}
@@ -1731,7 +1748,7 @@ if __name__ == '__main__':
except: except:
traceback.print_exc() traceback.print_exc()
i=0 __i=0
## To-Do's: ## To-Do's:
## =============================## ## =============================##
## 1. Add support for printf-style format specification. ## 1. Add support for printf-style format specification.

View File

@@ -15,51 +15,50 @@
# masked.TimeCtrl, and masked.IpAddrCtrl. # masked.TimeCtrl, and masked.IpAddrCtrl.
# #
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
"""
Provides a generic, fully configurable masked edit text control, as well as
a base class from which you can derive masked controls tailored to a specific
function. See maskededit module overview for how to configure the control.
"""
import wx import wx
from wx.lib.masked import * from wx.lib.masked import *
# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would # jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
# be a good place to implement the 2.3 logger class # be a good place to implement the 2.3 logger class
from wx.tools.dbg import Logger from wx.tools.dbg import Logger
dbg = Logger() ##dbg = Logger()
##dbg(enable=1) ##dbg(enable=1)
# ## TRICKY BIT: to avoid a ton of boiler-plate, and to
# ## automate the getter/setter generation for each valid
# ## control parameter so we never forget to add the
# ## functions when adding parameters, this loop
# ## programmatically adds them to the class:
# ## (This makes it easier for Designers like Boa to
# ## deal with masked controls.)
#
# ## To further complicate matters, this is done with an
# ## extra level of inheritance, so that "general" classes like
# ## MaskedTextCtrl can have all possible attributes,
# ## while derived classes, like TimeCtrl and MaskedNumCtrl
# ## can prevent exposure of those optional attributes of their base
# ## class that do not make sense for their derivation. Therefore,
# ## we define
# ## BaseMaskedTextCtrl(TextCtrl, MaskedEditMixin)
# ## and
# ## MaskedTextCtrl(BaseMaskedTextCtrl, MaskedEditAccessorsMixin).
# ##
# ## This allows us to then derive:
# ## MaskedNumCtrl( BaseMaskedTextCtrl )
# ##
# ## and not have to expose all the same accessor functions for the
# ## derived control when they don't all make sense for it.
# ##
class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ): class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
""" """
This is the primary derivation from MaskedEditMixin. It provides This is the primary derivation from MaskedEditMixin. It provides
a general masked text control that can be configured with different a general masked text control that can be configured with different
masks. It's actually a "base masked textCtrl", so that the masks.
MaskedTextCtrl class can be derived from it, and add those
accessor functions to it that are appropriate to the general class, However, this is done with an extra level of inheritance, so that
whilst other classes can derive from BaseMaskedTextCtrl, and "general" classes like masked.TextCtrl can have all possible attributes,
only define those accessor functions that are appropriate for while derived classes, like masked.TimeCtrl and masked.NumCtrl
those derivations. can prevent exposure of those optional attributes of their base
class that do not make sense for their derivation. Therefore,
we define::
BaseMaskedTextCtrl(TextCtrl, MaskedEditMixin)
and::
masked.TextCtrl(BaseMaskedTextCtrl, MaskedEditAccessorsMixin).
This allows us to then derive::
masked.NumCtrl( BaseMaskedTextCtrl )
and not have to expose all the same accessor functions for the
derived control when they don't all make sense for it.
In practice, BaseMaskedTextCtrl should never be instantiated directly,
but should only be used in derived classes.
""" """
def __init__( self, parent, id=-1, value = '', def __init__( self, parent, id=-1, value = '',
@@ -119,12 +118,12 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
#### dbg("MaskedTextCtrl::_SetSelection(%(sel_start)d, %(sel_to)d)" % locals()) #### dbg("MaskedTextCtrl::_SetSelection(%(sel_start)d, %(sel_to)d)" % locals())
return self.SetSelection( sel_start, sel_to ) return self.SetSelection( sel_start, sel_to )
def SetSelection(self, sel_start, sel_to): ## def SetSelection(self, sel_start, sel_to):
""" ## """
This is just for debugging... ## This is just for debugging...
""" ## """
## dbg("MaskedTextCtrl::SetSelection(%(sel_start)d, %(sel_to)d)" % locals()) ## dbg("MaskedTextCtrl::SetSelection(%(sel_start)d, %(sel_to)d)" % locals())
wx.TextCtrl.SetSelection(self, sel_start, sel_to) ## wx.TextCtrl.SetSelection(self, sel_start, sel_to)
def _GetInsertionPoint(self): def _GetInsertionPoint(self):
@@ -134,12 +133,12 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
#### dbg("MaskedTextCtrl::_SetInsertionPoint(%(pos)d)" % locals()) #### dbg("MaskedTextCtrl::_SetInsertionPoint(%(pos)d)" % locals())
self.SetInsertionPoint(pos) self.SetInsertionPoint(pos)
def SetInsertionPoint(self, pos): ## def SetInsertionPoint(self, pos):
""" ## """
This is just for debugging... ## This is just for debugging...
""" ## """
## dbg("MaskedTextCtrl::SetInsertionPoint(%(pos)d)" % locals()) ## dbg("MaskedTextCtrl::SetInsertionPoint(%(pos)d)" % locals())
wx.TextCtrl.SetInsertionPoint(self, pos) ## wx.TextCtrl.SetInsertionPoint(self, pos)
def _GetValue(self): def _GetValue(self):
@@ -149,6 +148,7 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
""" """
return self.GetValue() return self.GetValue()
def _SetValue(self, value): def _SetValue(self, value):
""" """
Allow mixin to set the raw value of the control with this function. Allow mixin to set the raw value of the control with this function.
@@ -163,7 +163,7 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
def SetValue(self, value): def SetValue(self, value):
""" """
This function redefines the externally accessible .SetValue to be This function redefines the externally accessible .SetValue() to be
a smart "paste" of the text in question, so as not to corrupt the a smart "paste" of the text in question, so as not to corrupt the
masked control. NOTE: this must be done in the class derived masked control. NOTE: this must be done in the class derived
from the base wx control. from the base wx control.
@@ -226,6 +226,7 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
wx.CallAfter(self._SetSelection, replace_to, replace_to) wx.CallAfter(self._SetSelection, replace_to, replace_to)
## dbg(indent=0) ## dbg(indent=0)
def SetFont(self, *args, **kwargs): def SetFont(self, *args, **kwargs):
""" Set the font, then recalculate control size, if appropriate. """ """ Set the font, then recalculate control size, if appropriate. """
wx.TextCtrl.SetFont(self, *args, **kwargs) wx.TextCtrl.SetFont(self, *args, **kwargs)
@@ -316,10 +317,10 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
def IsModified(self): def IsModified(self):
""" """
This function overrides the raw wxTextCtrl method, because the This function overrides the raw wx.TextCtrl method, because the
masked edit mixin uses SetValue to change the value, which doesn't masked edit mixin uses SetValue to change the value, which doesn't
modify the state of this attribute. So, we keep track on each modify the state of this attribute. So, the derived control keeps track
keystroke to see if the value changes, and if so, it's been on each keystroke to see if the value changes, and if so, it's been
modified. modified.
""" """
return wx.TextCtrl.IsModified(self) or self.modified return wx.TextCtrl.IsModified(self) or self.modified
@@ -334,17 +335,20 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
class TextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ): class TextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ):
""" """
This extra level of inheritance allows us to add the generic set of The "user-visible" masked text control; it is identical to the
masked edit parameters only to this class while allowing other BaseMaskedTextCtrl class it's derived from.
classes to derive from the "base" masked text control, and provide (This extra level of inheritance allows us to add the generic
a smaller set of valid accessor functions. set of masked edit parameters only to this class while allowing
other classes to derive from the "base" masked text control,
and provide a smaller set of valid accessor functions.)
See BaseMaskedTextCtrl for available methods.
""" """
pass pass
class PreMaskedTextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ): class PreMaskedTextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ):
""" """
This allows us to use XRC subclassing. This class exists to support the use of XRC subclassing.
""" """
# This should really be wx.EVT_WINDOW_CREATE but it is not # This should really be wx.EVT_WINDOW_CREATE but it is not
# currently delivered for native controls on all platforms, so # currently delivered for native controls on all platforms, so
@@ -362,9 +366,13 @@ class PreMaskedTextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ):
self.Unbind(self._firstEventType) self.Unbind(self._firstEventType)
self._PostInit() self._PostInit()
i=0 __i=0
## CHANGELOG: ## CHANGELOG:
## ==================== ## ====================
## Version 1.2
## - Converted docstrings to reST format, added doc for ePyDoc.
## removed debugging override functions.
##
## Version 1.1 ## Version 1.1
## 1. Added .SetFont() method that properly resizes control ## 1. Added .SetFont() method that properly resizes control
## 2. Modified control to support construction via XRC mechanism. ## 2. Modified control to support construction via XRC mechanism.

View File

@@ -43,229 +43,233 @@
# o wxTimeCtrl -> masked.TimeCtrl # o wxTimeCtrl -> masked.TimeCtrl
# #
"""<html><body> """
<P> *TimeCtrl* provides a multi-cell control that allows manipulation of a time
<B>TimeCtrl</B> provides a multi-cell control that allows manipulation of a time
value. It supports 12 or 24 hour format, and you can use wxDateTime or mxDateTime value. It supports 12 or 24 hour format, and you can use wxDateTime or mxDateTime
to get/set values from the control. to get/set values from the control.
<P>
Left/right/tab keys to switch cells within a TimeCtrl, and the up/down arrows act Left/right/tab keys to switch cells within a TimeCtrl, and the up/down arrows act
like a spin control. TimeCtrl also allows for an actual spin button to be attached like a spin control. TimeCtrl also allows for an actual spin button to be attached
to the control, so that it acts like the up/down arrow keys. to the control, so that it acts like the up/down arrow keys.
<P>
The <B>!</B> or <B>c</B> key sets the value of the control to the current time. The ! or c key sets the value of the control to the current time.
<P>
Here's the API for TimeCtrl: Here's the API for TimeCtrl::
<DL><PRE>
<B>TimeCtrl</B>( from wx.lib.masked import TimeCtrl
TimeCtrl(
parent, id = -1, parent, id = -1,
<B>value</B> = '00:00:00', value = '00:00:00',
pos = wx.DefaultPosition, pos = wx.DefaultPosition,
size = wx.DefaultSize, size = wx.DefaultSize,
<B>style</B> = wxTE_PROCESS_TAB, style = wxTE_PROCESS_TAB,
<B>validator</B> = wx.DefaultValidator, validator = wx.DefaultValidator,
name = "time", name = "time",
<B>format</B> = 'HHMMSS', format = 'HHMMSS',
<B>fmt24hr</B> = False, fmt24hr = False,
<B>displaySeconds</B> = True, displaySeconds = True,
<B>spinButton</B> = None, spinButton = None,
<B>min</B> = None, min = None,
<B>max</B> = None, max = None,
<B>limited</B> = None, limited = None,
<B>oob_color</B> = "Yellow" oob_color = "Yellow"
) )
</PRE>
<UL>
<DT><B>value</B> value
<DD>If no initial value is set, the default will be midnight; if an illegal string If no initial value is set, the default will be midnight; if an illegal string
is specified, a ValueError will result. (You can always later set the initial time is specified, a ValueError will result. (You can always later set the initial time
with SetValue() after instantiation of the control.) with SetValue() after instantiation of the control.)
<DL><B>size</B>
<DD>The size of the control will be automatically adjusted for 12/24 hour format size
The size of the control will be automatically adjusted for 12/24 hour format
if wx.DefaultSize is specified. NOTE: due to a problem with wx.DateTime, if the if wx.DefaultSize is specified. NOTE: due to a problem with wx.DateTime, if the
locale does not use 'AM/PM' for its values, the default format will automatically locale does not use 'AM/PM' for its values, the default format will automatically
change to 24 hour format, and an AttributeError will be thrown if a non-24 format change to 24 hour format, and an AttributeError will be thrown if a non-24 format
is specified. is specified.
<DT><B>style</B>
<DD>By default, TimeCtrl will process TAB events, by allowing tab to the style
By default, TimeCtrl will process TAB events, by allowing tab to the
different cells within the control. different cells within the control.
<DT><B>validator</B>
<DD>By default, TimeCtrl just uses the default (empty) validator, as all validator
By default, TimeCtrl just uses the default (empty) validator, as all
of its validation for entry control is handled internally. However, a validator of its validation for entry control is handled internally. However, a validator
can be supplied to provide data transfer capability to the control. can be supplied to provide data transfer capability to the control.
<BR>
<DT><B>format</B> format
<DD>This parameter can be used instead of the fmt24hr and displaySeconds This parameter can be used instead of the fmt24hr and displaySeconds
parameters, respectively; it provides a shorthand way to specify the time parameters, respectively; it provides a shorthand way to specify the time
format you want. Accepted values are 'HHMMSS', 'HHMM', '24HHMMSS', and format you want. Accepted values are 'HHMMSS', 'HHMM', '24HHMMSS', and
'24HHMM'. If the format is specified, the other two arguments will be ignored. '24HHMM'. If the format is specified, the other two arguments will be ignored.
<BR>
<DT><B>fmt24hr</B> fmt24hr
<DD>If True, control will display time in 24 hour time format; if False, it will If True, control will display time in 24 hour time format; if False, it will
use 12 hour AM/PM format. SetValue() will adjust values accordingly for the use 12 hour AM/PM format. SetValue() will adjust values accordingly for the
control, based on the format specified. (This value is ignored if the <i>format</i> control, based on the format specified. (This value is ignored if the *format*
parameter is specified.) parameter is specified.)
<BR>
<DT><B>displaySeconds</B> displaySeconds
<DD>If True, control will include a seconds field; if False, it will If True, control will include a seconds field; if False, it will
just show hours and minutes. (This value is ignored if the <i>format</i> just show hours and minutes. (This value is ignored if the *format*
parameter is specified.) parameter is specified.)
<BR>
<DT><B>spinButton</B> spinButton
<DD>If specified, this button's events will be bound to the behavior of the If specified, this button's events will be bound to the behavior of the
TimeCtrl, working like up/down cursor key events. (See BindSpinButton.) TimeCtrl, working like up/down cursor key events. (See BindSpinButton.)
<BR>
<DT><B>min</B> min
<DD>Defines the lower bound for "valid" selections in the control. Defines the lower bound for "valid" selections in the control.
By default, TimeCtrl doesn't have bounds. You must set both upper and lower By default, TimeCtrl doesn't have bounds. You must set both upper and lower
bounds to make the control pay attention to them, (as only one bound makes no sense bounds to make the control pay attention to them, (as only one bound makes no sense
with times.) "Valid" times will fall between the min and max "pie wedge" of the with times.) "Valid" times will fall between the min and max "pie wedge" of the
clock. clock.
<DT><B>max</B> max
<DD>Defines the upper bound for "valid" selections in the control. Defines the upper bound for "valid" selections in the control.
"Valid" times will fall between the min and max "pie wedge" of the "Valid" times will fall between the min and max "pie wedge" of the
clock. (This can be a "big piece", ie. <b>min = 11pm, max= 10pm</b> clock. (This can be a "big piece", ie. min = 11pm, max= 10pm
means <I>all but the hour from 10:00pm to 11pm are valid times.</I>) means *all but the hour from 10:00pm to 11pm are valid times.*)
<DT><B>limited</B> limited
<DD>If True, the control will not permit entry of values that fall outside the If True, the control will not permit entry of values that fall outside the
set bounds. set bounds.
<BR>
<DT><B>oob_color</B> oob_color
<DD>Sets the background color used to indicate out-of-bounds values for the control Sets the background color used to indicate out-of-bounds values for the control
when the control is not limited. This is set to "Yellow" by default. when the control is not limited. This is set to "Yellow" by default.
</DL>
</UL>
<BR>
<BR>
<BR>
<DT><B>EVT_TIMEUPDATE(win, id, func)</B>
<DD>func is fired whenever the value of the control changes.
<BR>
<BR>
<DT><B>SetValue(time_string | wxDateTime | wxTimeSpan | mx.DateTime | mx.DateTimeDelta)</B>
<DD>Sets the value of the control to a particular time, given a valid
value; raises ValueError on invalid value.
<EM>NOTE:</EM> This will only allow mx.DateTime or mx.DateTimeDelta if mx.DateTime
was successfully imported by the class module.
<BR>
<DT><B>GetValue(as_wxDateTime = False, as_mxDateTime = False, as_wxTimeSpan=False, as mxDateTimeDelta=False)</B>
<DD>Retrieves the value of the time from the control. By default this is
returned as a string, unless one of the other arguments is set; args are
searched in the order listed; only one value will be returned.
<BR>
<DT><B>GetWxDateTime(value=None)</B>
<DD>When called without arguments, retrieves the value of the control, and applies
it to the wxDateTimeFromHMS() constructor, and returns the resulting value.
The date portion will always be set to Jan 1, 1970. This form is the same
as GetValue(as_wxDateTime=True). GetWxDateTime can also be called with any of the
other valid time formats settable with SetValue, to regularize it to a single
wxDateTime form. The function will raise ValueError on an unconvertable argument.
<BR>
<DT><B>GetMxDateTime()</B>
<DD>Retrieves the value of the control and applies it to the DateTime.Time()
constructor,and returns the resulting value. (The date portion will always be
set to Jan 1, 1970.) (Same as GetValue(as_wxDateTime=True); provided for backward
compatibility with previous release.)
<BR>
<BR>
<DT><B>BindSpinButton(SpinBtton)</B>
<DD>Binds an externally created spin button to the control, so that up/down spin
events change the active cell or selection in the control (in addition to the
up/down cursor keys.) (This is primarily to allow you to create a "standard"
interface to time controls, as seen in Windows.)
<BR>
<BR>
<DT><B>SetMin(min=None)</B>
<DD>Sets the expected minimum value, or lower bound, of the control.
(The lower bound will only be enforced if the control is
configured to limit its values to the set bounds.)
If a value of <I>None</I> is provided, then the control will have
explicit lower bound. If the value specified is greater than
the current lower bound, then the function returns False and the
lower bound will not change from its current setting. On success,
the function returns True. Even if set, if there is no corresponding
upper bound, the control will behave as if it is unbounded.
<DT><DD>If successful and the current value is outside the
new bounds, if the control is limited the value will be
automatically adjusted to the nearest bound; if not limited,
the background of the control will be colored with the current
out-of-bounds color.
<BR>
<DT><B>GetMin(as_string=False)</B>
<DD>Gets the current lower bound value for the control, returning
None, if not set, or a wxDateTime, unless the as_string parameter
is set to True, at which point it will return the string
representation of the lower bound.
<BR>
<BR>
<DT><B>SetMax(max=None)</B>
<DD>Sets the expected maximum value, or upper bound, of the control.
(The upper bound will only be enforced if the control is
configured to limit its values to the set bounds.)
If a value of <I>None</I> is provided, then the control will
have no explicit upper bound. If the value specified is less
than the current lower bound, then the function returns False and
the maximum will not change from its current setting. On success,
the function returns True. Even if set, if there is no corresponding
lower bound, the control will behave as if it is unbounded.
<DT><DD>If successful and the current value is outside the
new bounds, if the control is limited the value will be
automatically adjusted to the nearest bound; if not limited,
the background of the control will be colored with the current
out-of-bounds color.
<BR>
<DT><B>GetMax(as_string = False)</B>
<DD>Gets the current upper bound value for the control, returning
None, if not set, or a wxDateTime, unless the as_string parameter
is set to True, at which point it will return the string
representation of the lower bound.
<BR> --------------------
<BR>
<DT><B>SetBounds(min=None,max=None)</B> EVT_TIMEUPDATE(win, id, func)
<DD>This function is a convenience function for setting the min and max func is fired whenever the value of the control changes.
values at the same time. The function only applies the maximum bound
if setting the minimum bound is successful, and returns True
only if both operations succeed. <B><I>Note: leaving out an argument SetValue(time_string | wxDateTime | wxTimeSpan | mx.DateTime | mx.DateTimeDelta)
will remove the corresponding bound, and result in the behavior of Sets the value of the control to a particular time, given a valid
an unbounded control.</I></B> value; raises ValueError on invalid value.
<BR>
<DT><B>GetBounds(as_string = False)</B> *NOTE:* This will only allow mx.DateTime or mx.DateTimeDelta if mx.DateTime
<DD>This function returns a two-tuple (min,max), indicating the was successfully imported by the class module.
current bounds of the control. Each value can be None if
that bound is not set. The values will otherwise be wxDateTimes GetValue(as_wxDateTime = False, as_mxDateTime = False, as_wxTimeSpan=False, as mxDateTimeDelta=False)
unless the as_string argument is set to True, at which point they Retrieves the value of the time from the control. By default this is
will be returned as string representations of the bounds. returned as a string, unless one of the other arguments is set; args are
<BR> searched in the order listed; only one value will be returned.
<BR>
<DT><B>IsInBounds(value=None)</B> GetWxDateTime(value=None)
<DD>Returns <I>True</I> if no value is specified and the current value When called without arguments, retrieves the value of the control, and applies
of the control falls within the current bounds. This function can also it to the wxDateTimeFromHMS() constructor, and returns the resulting value.
be called with a value to see if that value would fall within the current The date portion will always be set to Jan 1, 1970. This form is the same
bounds of the given control. It will raise ValueError if the value as GetValue(as_wxDateTime=True). GetWxDateTime can also be called with any of the
specified is not a wxDateTime, mxDateTime (if available) or parsable string. other valid time formats settable with SetValue, to regularize it to a single
<BR> wxDateTime form. The function will raise ValueError on an unconvertable argument.
<BR>
<DT><B>IsValid(value)</B> GetMxDateTime()
<DD>Returns <I>True</I>if specified value is a legal time value and Retrieves the value of the control and applies it to the DateTime.Time()
falls within the current bounds of the given control. constructor,and returns the resulting value. (The date portion will always be
<BR> set to Jan 1, 1970.) (Same as GetValue(as_wxDateTime=True); provided for backward
<BR> compatibility with previous release.)
<DT><B>SetLimited(bool)</B>
<DD>If called with a value of True, this function will cause the control
to limit the value to fall within the bounds currently specified. BindSpinButton(SpinBtton)
(Provided both bounds have been set.) Binds an externally created spin button to the control, so that up/down spin
If the control's value currently exceeds the bounds, it will then events change the active cell or selection in the control (in addition to the
be set to the nearest bound. up/down cursor keys.) (This is primarily to allow you to create a "standard"
If called with a value of False, this function will disable value interface to time controls, as seen in Windows.)
limiting, but coloring of out-of-bounds values will still take
place if bounds have been set for the control.
<DT><B>IsLimited()</B> SetMin(min=None)
<DD>Returns <I>True</I> if the control is currently limiting the Sets the expected minimum value, or lower bound, of the control.
value to fall within the current bounds. (The lower bound will only be enforced if the control is
<BR> configured to limit its values to the set bounds.)
</DL> If a value of *None* is provided, then the control will have
</body></html> explicit lower bound. If the value specified is greater than
the current lower bound, then the function returns False and the
lower bound will not change from its current setting. On success,
the function returns True. Even if set, if there is no corresponding
upper bound, the control will behave as if it is unbounded.
If successful and the current value is outside the
new bounds, if the control is limited the value will be
automatically adjusted to the nearest bound; if not limited,
the background of the control will be colored with the current
out-of-bounds color.
GetMin(as_string=False)
Gets the current lower bound value for the control, returning
None, if not set, or a wxDateTime, unless the as_string parameter
is set to True, at which point it will return the string
representation of the lower bound.
SetMax(max=None)
Sets the expected maximum value, or upper bound, of the control.
(The upper bound will only be enforced if the control is
configured to limit its values to the set bounds.)
If a value of *None* is provided, then the control will
have no explicit upper bound. If the value specified is less
than the current lower bound, then the function returns False and
the maximum will not change from its current setting. On success,
the function returns True. Even if set, if there is no corresponding
lower bound, the control will behave as if it is unbounded.
If successful and the current value is outside the
new bounds, if the control is limited the value will be
automatically adjusted to the nearest bound; if not limited,
the background of the control will be colored with the current
out-of-bounds color.
GetMax(as_string = False)
Gets the current upper bound value for the control, returning
None, if not set, or a wxDateTime, unless the as_string parameter
is set to True, at which point it will return the string
representation of the lower bound.
SetBounds(min=None,max=None)
This function is a convenience function for setting the min and max
values at the same time. The function only applies the maximum bound
if setting the minimum bound is successful, and returns True
only if both operations succeed. *Note: leaving out an argument
will remove the corresponding bound, and result in the behavior of
an unbounded control.*
GetBounds(as_string = False)
This function returns a two-tuple (min,max), indicating the
current bounds of the control. Each value can be None if
that bound is not set. The values will otherwise be wxDateTimes
unless the as_string argument is set to True, at which point they
will be returned as string representations of the bounds.
IsInBounds(value=None)
Returns *True* if no value is specified and the current value
of the control falls within the current bounds. This function can also
be called with a value to see if that value would fall within the current
bounds of the given control. It will raise ValueError if the value
specified is not a wxDateTime, mxDateTime (if available) or parsable string.
IsValid(value)
Returns *True* if specified value is a legal time value and
falls within the current bounds of the given control.
SetLimited(bool)
If called with a value of True, this function will cause the control
to limit the value to fall within the bounds currently specified.
(Provided both bounds have been set.)
If the control's value currently exceeds the bounds, it will then
be set to the nearest bound.
If called with a value of False, this function will disable value
limiting, but coloring of out-of-bounds values will still take
place if bounds have been set for the control.
IsLimited()
Returns *True* if the control is currently limiting the
value to fall within the current bounds.
""" """
import copy import copy
@@ -291,6 +295,9 @@ wxEVT_TIMEVAL_UPDATED = wx.NewEventType()
EVT_TIMEUPDATE = wx.PyEventBinder(wxEVT_TIMEVAL_UPDATED, 1) EVT_TIMEUPDATE = wx.PyEventBinder(wxEVT_TIMEVAL_UPDATED, 1)
class TimeUpdatedEvent(wx.PyCommandEvent): class TimeUpdatedEvent(wx.PyCommandEvent):
"""
Used to fire an EVT_TIMEUPDATE event whenever the value in a TimeCtrl changes.
"""
def __init__(self, id, value ='12:00:00 AM'): def __init__(self, id, value ='12:00:00 AM'):
wx.PyCommandEvent.__init__(self, wxEVT_TIMEVAL_UPDATED, id) wx.PyCommandEvent.__init__(self, wxEVT_TIMEVAL_UPDATED, id)
self.value = value self.value = value
@@ -299,9 +306,10 @@ class TimeUpdatedEvent(wx.PyCommandEvent):
return self.value return self.value
class TimeCtrlAccessorsMixin: class TimeCtrlAccessorsMixin:
# Define TimeCtrl's list of attributes having their own """
# Get/Set functions, ignoring those that make no sense for Defines TimeCtrl's list of attributes having their own Get/Set functions,
# an numeric control. ignoring those in the base class that make no sense for a time control.
"""
exposed_basectrl_params = ( exposed_basectrl_params = (
'defaultValue', 'defaultValue',
'description', 'description',
@@ -328,6 +336,9 @@ class TimeCtrlAccessorsMixin:
class TimeCtrl(BaseMaskedTextCtrl): class TimeCtrl(BaseMaskedTextCtrl):
"""
Masked control providing several time formats and manipulation of time values.
"""
valid_ctrl_params = { valid_ctrl_params = {
'format' : 'HHMMSS', # default format code 'format' : 'HHMMSS', # default format code
@@ -467,6 +478,9 @@ class TimeCtrl(BaseMaskedTextCtrl):
def SetParameters(self, **kwargs): def SetParameters(self, **kwargs):
"""
Function providing access to the parameters governing TimeCtrl display and bounds.
"""
## dbg('TimeCtrl::SetParameters(%s)' % repr(kwargs), indent=1) ## dbg('TimeCtrl::SetParameters(%s)' % repr(kwargs), indent=1)
maskededit_kwargs = {} maskededit_kwargs = {}
reset_format = False reset_format = False
@@ -621,6 +635,11 @@ class TimeCtrl(BaseMaskedTextCtrl):
as_mxDateTime = False, as_mxDateTime = False,
as_wxTimeSpan = False, as_wxTimeSpan = False,
as_mxDateTimeDelta = False): as_mxDateTimeDelta = False):
"""
This function returns the value of the display as a string by default, but
supports return as a wx.DateTime, mx.DateTime, wx.TimeSpan, or mx.DateTimeDelta,
if requested. (Evaluated in the order above-- first one wins!)
"""
if as_wxDateTime or as_mxDateTime or as_wxTimeSpan or as_mxDateTimeDelta: if as_wxDateTime or as_mxDateTime or as_wxTimeSpan or as_mxDateTimeDelta:
@@ -640,7 +659,7 @@ class TimeCtrl(BaseMaskedTextCtrl):
def SetWxDateTime(self, wxdt): def SetWxDateTime(self, wxdt):
""" """
Because SetValue can take a wxDateTime, this is now just an alias. Because SetValue can take a wx.DateTime, this is now just an alias.
""" """
self.SetValue(wxdt) self.SetValue(wxdt)
@@ -654,9 +673,9 @@ class TimeCtrl(BaseMaskedTextCtrl):
wxTimeSpan wxTimeSpan
mxDateTime mxDateTime
mxDateTimeDelta mxDateTimeDelta
and converts it to a wxDateTime that always has Jan 1, 1970 as its date and converts it to a wx.DateTime that always has Jan 1, 1970 as its date
portion, so that range comparisons around values can work using portion, so that range comparisons around values can work using
wxDateTime's built-in comparison function. If a value is not wx.DateTime's built-in comparison function. If a value is not
provided to convert, the string value of the control will be used. provided to convert, the string value of the control will be used.
If the value is not one of the accepted types, a ValueError will be If the value is not one of the accepted types, a ValueError will be
raised. raised.
@@ -725,13 +744,17 @@ class TimeCtrl(BaseMaskedTextCtrl):
def SetMxDateTime(self, mxdt): def SetMxDateTime(self, mxdt):
""" """
Because SetValue can take an mxDateTime, (if DateTime is importable), Because SetValue can take an mx.DateTime, (if DateTime is importable),
this is now just an alias. this is now just an alias.
""" """
self.SetValue(value) self.SetValue(value)
def GetMxDateTime(self, value=None): def GetMxDateTime(self, value=None):
"""
Returns the value of the control as an mx.DateTime, with the date
portion set to January 1, 1970.
"""
if value is None: if value is None:
t = self.GetValue(as_mxDateTime=True) t = self.GetValue(as_mxDateTime=True)
else: else:
@@ -869,7 +892,7 @@ class TimeCtrl(BaseMaskedTextCtrl):
values at the same time. The function only applies the maximum bound values at the same time. The function only applies the maximum bound
if setting the minimum bound is successful, and returns True if setting the minimum bound is successful, and returns True
only if both operations succeed. only if both operations succeed.
NOTE: leaving out an argument will remove the corresponding bound. **NOTE:** leaving out an argument will remove the corresponding bound.
""" """
ret = self.SetMin(min) ret = self.SetMin(min)
return ret and self.SetMax(max) return ret and self.SetMax(max)
@@ -969,7 +992,7 @@ class TimeCtrl(BaseMaskedTextCtrl):
def IsLimited(self): def IsLimited(self):
""" """
Returns True if the control is currently limiting the Returns True if the control is currently limiting the
value to fall within any current bounds. Note: can value to fall within any current bounds. *Note:* can
be set even if there are no current bounds. be set even if there are no current bounds.
""" """
return self.__limited return self.__limited
@@ -1072,9 +1095,10 @@ class TimeCtrl(BaseMaskedTextCtrl):
def SetInsertionPoint(self, pos): def SetInsertionPoint(self, pos):
""" """
Records the specified position and associated cell before calling base class' function. This override records the specified position and associated cell before
This is necessary to handle the optional spin button, because the insertion calling base class' function. This is necessary to handle the optional
point is lost when the focus shifts to the spin button. spin button, because the insertion point is lost when the focus shifts
to the spin button.
""" """
## dbg('TimeCtrl::SetInsertionPoint', pos, indent=1) ## dbg('TimeCtrl::SetInsertionPoint', pos, indent=1)
BaseMaskedTextCtrl.SetInsertionPoint(self, pos) # (causes EVT_TEXT event to fire) BaseMaskedTextCtrl.SetInsertionPoint(self, pos) # (causes EVT_TEXT event to fire)
@@ -1333,7 +1357,15 @@ if __name__ == '__main__':
app.MainLoop() app.MainLoop()
except: except:
traceback.print_exc() traceback.print_exc()
i=0 __i=0
## CHANGELOG:
## ====================
## Version 1.3
## 1. Converted docstrings to reST format, added doc for ePyDoc.
## 2. Renamed helper functions, vars etc. not intended to be visible in public
## interface to code.
##
## Version 1.2 ## Version 1.2
## 1. Changed parameter name display_seconds to displaySeconds, to follow ## 1. Changed parameter name display_seconds to displaySeconds, to follow
## other masked edit conventions. ## other masked edit conventions.

View File

@@ -147,8 +147,14 @@ class Logger:
return return
if self._dbg and len(args) and not self._suspend: if self._dbg and len(args) and not self._suspend:
# (emulate print functionality) # (emulate print functionality; handle unicode as best as possible:)
strs = [str(arg) for arg in args] strs = []
for arg in args:
try:
strs.append(str(arg))
except:
strs.append(repr(arg))
output = ' '.join(strs) output = ' '.join(strs)
if self.name: output = self.name+': ' + output if self.name: output = self.name+': ' + output
output = ' ' * 3 * self._indent + output output = ' ' * 3 * self._indent + output