MaskedEditCtrl updates from Will Sadkin
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@26096 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -4,6 +4,7 @@ import sys
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import wx
|
import wx
|
||||||
|
import wx.lib.maskededit as me
|
||||||
import wx.lib.maskednumctrl as mnum
|
import wx.lib.maskednumctrl as mnum
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -31,13 +32,13 @@ The controls at the top reconfigure the resulting control at the bottom.
|
|||||||
)
|
)
|
||||||
|
|
||||||
groupcharlabel = wx.StaticText( panel,-1, "Grouping char:" )
|
groupcharlabel = wx.StaticText( panel,-1, "Grouping char:" )
|
||||||
self.groupchar = mnum.MaskedTextCtrl(
|
self.groupchar = me.MaskedTextCtrl(
|
||||||
panel, -1, value=',', mask='&', excludeChars = '-()',
|
panel, -1, value=',', mask='&', excludeChars = '-()',
|
||||||
formatcodes='F', emptyInvalid=True, validRequired=True
|
formatcodes='F', emptyInvalid=True, validRequired=True
|
||||||
)
|
)
|
||||||
|
|
||||||
decimalcharlabel = wx.StaticText( panel,-1, "Decimal char:" )
|
decimalcharlabel = wx.StaticText( panel,-1, "Decimal char:" )
|
||||||
self.decimalchar = mnum.MaskedTextCtrl(
|
self.decimalchar = me.MaskedTextCtrl(
|
||||||
panel, -1, value='.', mask='&', excludeChars = '-()',
|
panel, -1, value='.', mask='&', excludeChars = '-()',
|
||||||
formatcodes='F', emptyInvalid=True, validRequired=True
|
formatcodes='F', emptyInvalid=True, validRequired=True
|
||||||
)
|
)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
|||||||
# Created: 09/06/2003
|
# Created: 09/06/2003
|
||||||
# Copyright: (c) 2003 by Will Sadkin
|
# Copyright: (c) 2003 by Will Sadkin
|
||||||
# RCS-ID: $Id$
|
# RCS-ID: $Id$
|
||||||
# License: wxWindows license
|
# License: wxWidgets license
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
# NOTE:
|
# NOTE:
|
||||||
# This was written to provide a numeric edit control for wxPython that
|
# This was written to provide a numeric edit control for wxPython that
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
# are exceeded.
|
# are exceeded.
|
||||||
#
|
#
|
||||||
# MaskedNumCtrl is intended to support fixed-point numeric entry, and
|
# MaskedNumCtrl is intended to support fixed-point numeric entry, and
|
||||||
# is derived from MaskedTextCtrl. As such, it supports a limited range
|
# is derived from BaseMaskedTextCtrl. As such, it supports a limited range
|
||||||
# of values to comply with a fixed-width entry mask.
|
# of values to comply with a fixed-width entry mask.
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
|
# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
|
||||||
@@ -65,10 +65,10 @@ Here's the API:
|
|||||||
<B>MaskedNumCtrl</B>(
|
<B>MaskedNumCtrl</B>(
|
||||||
parent, id = -1,
|
parent, id = -1,
|
||||||
<B>value</B> = 0,
|
<B>value</B> = 0,
|
||||||
pos = wxDefaultPosition,
|
pos = wx.DefaultPosition,
|
||||||
size = wxDefaultSize,
|
size = wx.DefaultSize,
|
||||||
style = 0,
|
style = 0,
|
||||||
validator = wxDefaultValidator,
|
validator = wx.DefaultValidator,
|
||||||
name = "maskednumber",
|
name = "maskednumber",
|
||||||
<B>integerWidth</B> = 10,
|
<B>integerWidth</B> = 10,
|
||||||
<B>fractionWidth</B> = 0,
|
<B>fractionWidth</B> = 0,
|
||||||
@@ -87,6 +87,7 @@ Here's the API:
|
|||||||
<B>emptyBackgroundColour</B> = "White",
|
<B>emptyBackgroundColour</B> = "White",
|
||||||
<B>validBackgroundColour</B> = "White",
|
<B>validBackgroundColour</B> = "White",
|
||||||
<B>invalidBackgroundColour</B> = "Yellow",
|
<B>invalidBackgroundColour</B> = "Yellow",
|
||||||
|
<B>autoSize</B> = True
|
||||||
)
|
)
|
||||||
</PRE>
|
</PRE>
|
||||||
<UL>
|
<UL>
|
||||||
@@ -177,11 +178,20 @@ Here's the API:
|
|||||||
<DT><B>invalidBackgroundColour</B>
|
<DT><B>invalidBackgroundColour</B>
|
||||||
<DD>Color value used for illegal values or values out-of-bounds of the
|
<DD>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>
|
||||||
|
<DD>Boolean indicating whether or not the control should set its own
|
||||||
|
width based on the integer and fraction widths. True by default.
|
||||||
|
<B><I>Note:</I></B> Setting this to False will produce seemingly odd
|
||||||
|
behavior unless the control is large enough to hold the maximum
|
||||||
|
specified value given the widths and the sign positions; if not,
|
||||||
|
the control will appear to "jump around" as the contents scroll.
|
||||||
|
(ie. autoSize is highly recommended.)
|
||||||
</UL>
|
</UL>
|
||||||
<BR>
|
<BR>
|
||||||
<BR>
|
<BR>
|
||||||
<DT><B>EVT_MASKEDNUM(win, id, func)</B>
|
<DT><B>EVT_MASKEDNUM(win, id, func)</B>
|
||||||
<DD>Respond to a wxEVT_COMMAND_MASKED_NUMBER_UPDATED event, generated when
|
<DD>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.)
|
||||||
@@ -353,6 +363,12 @@ within the control. (The default is True.)
|
|||||||
the field values on entry.
|
the field values on entry.
|
||||||
<BR>
|
<BR>
|
||||||
<BR>
|
<BR>
|
||||||
|
<DT><B>SetAutoSize(bool)</B>
|
||||||
|
<DD>Resets the autoSize attribute of the control.
|
||||||
|
<DT><B>GetAutoSize()</B>
|
||||||
|
<DD>Returns the current state of the autoSize attribute for the control.
|
||||||
|
<BR>
|
||||||
|
<BR>
|
||||||
</DL>
|
</DL>
|
||||||
</body></html>
|
</body></html>
|
||||||
"""
|
"""
|
||||||
@@ -368,8 +384,7 @@ MAXINT = maxint # (constants should be in upper case)
|
|||||||
MININT = -maxint-1
|
MININT = -maxint-1
|
||||||
|
|
||||||
from wx.tools.dbg import Logger
|
from wx.tools.dbg import Logger
|
||||||
from wx.lib.maskededit import MaskedEditMixin, MaskedTextCtrl, Field
|
from wx.lib.maskededit import MaskedEditMixin, BaseMaskedTextCtrl, Field
|
||||||
|
|
||||||
dbg = Logger()
|
dbg = Logger()
|
||||||
dbg(enable=0)
|
dbg(enable=0)
|
||||||
|
|
||||||
@@ -394,16 +409,55 @@ class MaskedNumNumberUpdatedEvent(wx.PyCommandEvent):
|
|||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
|
class MaskedNumCtrlAccessorsMixin:
|
||||||
|
# Define wxMaskedNumCtrl's list of attributes having their own
|
||||||
|
# Get/Set functions, ignoring those that make no sense for
|
||||||
|
# an numeric control.
|
||||||
|
exposed_basectrl_params = (
|
||||||
|
'decimalChar',
|
||||||
|
'shiftDecimalChar',
|
||||||
|
'groupChar',
|
||||||
|
'useParensForNegatives',
|
||||||
|
'defaultValue',
|
||||||
|
'description',
|
||||||
|
|
||||||
|
'useFixedWidthFont',
|
||||||
|
'autoSize',
|
||||||
|
'signedForegroundColour',
|
||||||
|
'emptyBackgroundColour',
|
||||||
|
'validBackgroundColour',
|
||||||
|
'invalidBackgroundColour',
|
||||||
|
|
||||||
|
'emptyInvalid',
|
||||||
|
'validFunc',
|
||||||
|
'validRequired',
|
||||||
|
)
|
||||||
|
for param in exposed_basectrl_params:
|
||||||
|
propname = param[0].upper() + param[1:]
|
||||||
|
exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
|
||||||
|
exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
|
||||||
|
|
||||||
|
if param.find('Colour') != -1:
|
||||||
|
# add non-british spellings, for backward-compatibility
|
||||||
|
propname.replace('Colour', 'Color')
|
||||||
|
|
||||||
|
exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
|
||||||
|
exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MaskedNumCtrl(BaseMaskedTextCtrl, MaskedNumCtrlAccessorsMixin):
|
||||||
|
|
||||||
class MaskedNumCtrl(MaskedTextCtrl):
|
|
||||||
|
|
||||||
valid_ctrl_params = {
|
valid_ctrl_params = {
|
||||||
'integerWidth': 10, # by default allow all 32-bit integers
|
'integerWidth': 10, # by default allow all 32-bit integers
|
||||||
'fractionWidth': 0, # by default, use integers
|
'fractionWidth': 0, # by default, use integers
|
||||||
'decimalChar': '.', # by default, use '.' for decimal point
|
'decimalChar': '.', # by default, use '.' for decimal point
|
||||||
'allowNegative': True, # by default, allow negative numbers
|
'allowNegative': True, # by default, allow negative numbers
|
||||||
'useParensForNegatives': False, # by default, use '-' to indicate negatives
|
'useParensForNegatives': False, # by default, use '-' to indicate negatives
|
||||||
'groupDigits': True, # by default, don't insert grouping
|
'groupDigits': True, # by default, don't insert grouping
|
||||||
'groupChar': ',', # by default, use ',' for grouping
|
'groupChar': ',', # by default, use ',' for grouping
|
||||||
'min': None, # by default, no bounds set
|
'min': None, # by default, no bounds set
|
||||||
'max': None,
|
'max': None,
|
||||||
@@ -415,7 +469,8 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
'emptyBackgroundColour': "White",
|
'emptyBackgroundColour': "White",
|
||||||
'validBackgroundColour': "White",
|
'validBackgroundColour': "White",
|
||||||
'invalidBackgroundColour': "Yellow",
|
'invalidBackgroundColour': "Yellow",
|
||||||
'useFixedWidthFont': True, # by default, use a fixed-width font
|
'useFixedWidthFont': True, # by default, use a fixed-width font
|
||||||
|
'autoSize': True, # by default, set the width of the control based on the mask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -488,6 +543,12 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
del init_args['integerWidth']
|
del init_args['integerWidth']
|
||||||
del init_args['fractionWidth']
|
del init_args['fractionWidth']
|
||||||
|
|
||||||
|
self._autoSize = init_args['autoSize']
|
||||||
|
if self._autoSize:
|
||||||
|
formatcodes = 'FR<'
|
||||||
|
else:
|
||||||
|
formatcodes = 'R<'
|
||||||
|
|
||||||
|
|
||||||
mask = intmask+fracmask
|
mask = intmask+fracmask
|
||||||
|
|
||||||
@@ -497,11 +558,11 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
self._typedSign = False
|
self._typedSign = False
|
||||||
|
|
||||||
# Construct the base control:
|
# Construct the base control:
|
||||||
MaskedTextCtrl.__init__(
|
BaseMaskedTextCtrl.__init__(
|
||||||
self, parent, id, '',
|
self, parent, id, '',
|
||||||
pos, size, style, validator, name,
|
pos, size, style, validator, name,
|
||||||
mask = mask,
|
mask = mask,
|
||||||
formatcodes = 'FR<',
|
formatcodes = formatcodes,
|
||||||
fields = fields,
|
fields = fields,
|
||||||
validFunc=self.IsInBounds,
|
validFunc=self.IsInBounds,
|
||||||
setupEventHandling = False)
|
setupEventHandling = False)
|
||||||
@@ -538,7 +599,8 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
|
|
||||||
if( (kwargs.has_key('integerWidth') and kwargs['integerWidth'] != self._integerWidth)
|
if( (kwargs.has_key('integerWidth') and kwargs['integerWidth'] != self._integerWidth)
|
||||||
or (kwargs.has_key('fractionWidth') and kwargs['fractionWidth'] != self._fractionWidth)
|
or (kwargs.has_key('fractionWidth') and kwargs['fractionWidth'] != self._fractionWidth)
|
||||||
or (kwargs.has_key('groupDigits') and kwargs['groupDigits'] != self._groupDigits) ):
|
or (kwargs.has_key('groupDigits') and kwargs['groupDigits'] != self._groupDigits)
|
||||||
|
or (kwargs.has_key('autoSize') and kwargs['autoSize'] != self._autoSize) ):
|
||||||
|
|
||||||
fields = {}
|
fields = {}
|
||||||
|
|
||||||
@@ -614,7 +676,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
dbg('kwargs:', kwargs)
|
dbg('kwargs:', kwargs)
|
||||||
|
|
||||||
# reprocess existing format codes to ensure proper resulting format:
|
# reprocess existing format codes to ensure proper resulting format:
|
||||||
formatcodes = self.GetFormatcodes()
|
formatcodes = self.GetCtrlParameter('formatcodes')
|
||||||
if kwargs.has_key('allowNegative'):
|
if kwargs.has_key('allowNegative'):
|
||||||
if kwargs['allowNegative'] and '-' not in formatcodes:
|
if kwargs['allowNegative'] and '-' not in formatcodes:
|
||||||
formatcodes += '-'
|
formatcodes += '-'
|
||||||
@@ -641,6 +703,16 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
formatcodes = formatcodes.replace('S','')
|
formatcodes = formatcodes.replace('S','')
|
||||||
maskededit_kwargs['formatcodes'] = formatcodes
|
maskededit_kwargs['formatcodes'] = formatcodes
|
||||||
|
|
||||||
|
if kwargs.has_key('autoSize'):
|
||||||
|
self._autoSize = kwargs['autoSize']
|
||||||
|
if kwargs['autoSize'] and 'F' not in formatcodes:
|
||||||
|
formatcodes += 'F'
|
||||||
|
maskededit_kwargs['formatcodes'] = formatcodes
|
||||||
|
elif not kwargs['autoSize'] and 'F' in formatcodes:
|
||||||
|
formatcodes = formatcodes.replace('F', '')
|
||||||
|
maskededit_kwargs['formatcodes'] = formatcodes
|
||||||
|
|
||||||
|
|
||||||
if 'r' in formatcodes and self._fractionWidth:
|
if 'r' in formatcodes and self._fractionWidth:
|
||||||
# top-level mask should only be right insert if no fractional
|
# top-level mask should only be right insert if no fractional
|
||||||
# part will be shown; ie. if reconfiguring control, remove
|
# part will be shown; ie. if reconfiguring control, remove
|
||||||
@@ -648,6 +720,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
formatcodes = formatcodes.replace('r', '')
|
formatcodes = formatcodes.replace('r', '')
|
||||||
maskededit_kwargs['formatcodes'] = formatcodes
|
maskededit_kwargs['formatcodes'] = formatcodes
|
||||||
|
|
||||||
|
|
||||||
if kwargs.has_key('limited'):
|
if kwargs.has_key('limited'):
|
||||||
if kwargs['limited'] and not self._limited:
|
if kwargs['limited'] and not self._limited:
|
||||||
maskededit_kwargs['validRequired'] = True
|
maskededit_kwargs['validRequired'] = True
|
||||||
@@ -661,6 +734,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
|
|
||||||
# Record end of integer and place cursor there:
|
# Record end of integer and place cursor there:
|
||||||
integerEnd = self._fields[0]._extent[1]
|
integerEnd = self._fields[0]._extent[1]
|
||||||
|
self.SetInsertionPoint(0)
|
||||||
self.SetInsertionPoint(integerEnd)
|
self.SetInsertionPoint(integerEnd)
|
||||||
self.SetSelection(integerEnd, integerEnd)
|
self.SetSelection(integerEnd, integerEnd)
|
||||||
|
|
||||||
@@ -733,7 +807,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
dbg('abs(value):', value)
|
dbg('abs(value):', value)
|
||||||
self._isNeg = False
|
self._isNeg = False
|
||||||
|
|
||||||
elif not self._allowNone and MaskedTextCtrl.GetValue(self) == '':
|
elif not self._allowNone and BaseMaskedTextCtrl.GetValue(self) == '':
|
||||||
if self._min > 0:
|
if self._min > 0:
|
||||||
value = self._min
|
value = self._min
|
||||||
else:
|
else:
|
||||||
@@ -775,7 +849,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
else:
|
else:
|
||||||
fracstart, fracend = self._fields[1]._extent
|
fracstart, fracend = self._fields[1]._extent
|
||||||
if candidate is None:
|
if candidate is None:
|
||||||
value = self._toGUI(MaskedTextCtrl.GetValue(self))
|
value = self._toGUI(BaseMaskedTextCtrl.GetValue(self))
|
||||||
else:
|
else:
|
||||||
value = self._toGUI(candidate)
|
value = self._toGUI(candidate)
|
||||||
fracstring = value[fracstart:fracend].strip()
|
fracstring = value[fracstart:fracend].strip()
|
||||||
@@ -824,8 +898,8 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
|
|
||||||
if numvalue == "":
|
if numvalue == "":
|
||||||
if self._allowNone:
|
if self._allowNone:
|
||||||
dbg('calling base MaskedTextCtrl._SetValue(self, "%s")' % value)
|
dbg('calling base BaseMaskedTextCtrl._SetValue(self, "%s")' % value)
|
||||||
MaskedTextCtrl._SetValue(self, value)
|
BaseMaskedTextCtrl._SetValue(self, value)
|
||||||
self.Refresh()
|
self.Refresh()
|
||||||
return
|
return
|
||||||
elif self._min > 0 and self.IsLimited():
|
elif self._min > 0 and self.IsLimited():
|
||||||
@@ -925,7 +999,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
# reasonable instead:
|
# reasonable instead:
|
||||||
dbg('setting replacement value:', replacement)
|
dbg('setting replacement value:', replacement)
|
||||||
self._SetValue(self._toGUI(replacement))
|
self._SetValue(self._toGUI(replacement))
|
||||||
sel_start = MaskedTextCtrl.GetValue(self).find(str(abs(replacement))) # find where it put the 1, so we can select it
|
sel_start = BaseMaskedTextCtrl.GetValue(self).find(str(abs(replacement))) # find where it put the 1, so we can select it
|
||||||
sel_to = sel_start + len(str(abs(replacement)))
|
sel_to = sel_start + len(str(abs(replacement)))
|
||||||
dbg('queuing selection of (%d, %d)' %(sel_start, sel_to))
|
dbg('queuing selection of (%d, %d)' %(sel_start, sel_to))
|
||||||
wx.CallAfter(self.SetInsertionPoint, sel_start)
|
wx.CallAfter(self.SetInsertionPoint, sel_start)
|
||||||
@@ -951,8 +1025,8 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
|
|
||||||
|
|
||||||
sel_start, sel_to = self._GetSelection() # record current insertion point
|
sel_start, sel_to = self._GetSelection() # record current insertion point
|
||||||
dbg('calling base MaskedTextCtrl._SetValue(self, "%s")' % adjvalue)
|
dbg('calling BaseMaskedTextCtrl._SetValue(self, "%s")' % adjvalue)
|
||||||
MaskedTextCtrl._SetValue(self, adjvalue)
|
BaseMaskedTextCtrl._SetValue(self, adjvalue)
|
||||||
# After all actions so far scheduled, check that resulting cursor
|
# After all actions so far scheduled, check that resulting cursor
|
||||||
# position is appropriate, and move if not:
|
# position is appropriate, and move if not:
|
||||||
wx.CallAfter(self._CheckInsertionPoint)
|
wx.CallAfter(self._CheckInsertionPoint)
|
||||||
@@ -985,7 +1059,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
# delete next digit to appropriate side:
|
# delete next digit to appropriate side:
|
||||||
if self._groupDigits:
|
if self._groupDigits:
|
||||||
key = event.GetKeyCode()
|
key = event.GetKeyCode()
|
||||||
value = MaskedTextCtrl.GetValue(self)
|
value = BaseMaskedTextCtrl.GetValue(self)
|
||||||
sel_start, sel_to = self._GetSelection()
|
sel_start, sel_to = self._GetSelection()
|
||||||
|
|
||||||
if key == wx.WXK_BACK:
|
if key == wx.WXK_BACK:
|
||||||
@@ -1011,7 +1085,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
self.SetInsertionPoint(sel_start)
|
self.SetInsertionPoint(sel_start)
|
||||||
self.SetSelection(sel_start, sel_to+1)
|
self.SetSelection(sel_start, sel_to+1)
|
||||||
|
|
||||||
MaskedTextCtrl._OnErase(self, event)
|
BaseMaskedTextCtrl._OnErase(self, event)
|
||||||
dbg(indent=0)
|
dbg(indent=0)
|
||||||
|
|
||||||
|
|
||||||
@@ -1025,7 +1099,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
before passing the events on.
|
before passing the events on.
|
||||||
"""
|
"""
|
||||||
dbg('MaskedNumCtrl::OnTextChange', indent=1)
|
dbg('MaskedNumCtrl::OnTextChange', indent=1)
|
||||||
if not MaskedTextCtrl._OnTextChange(self, event):
|
if not BaseMaskedTextCtrl._OnTextChange(self, event):
|
||||||
dbg(indent=0)
|
dbg(indent=0)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1046,7 +1120,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
|
|
||||||
def _GetValue(self):
|
def _GetValue(self):
|
||||||
"""
|
"""
|
||||||
Override of MaskedTextCtrl to allow amixin to get the raw text value of the
|
Override of BaseMaskedTextCtrl to allow mixin to get the raw text value of the
|
||||||
control with this function.
|
control with this function.
|
||||||
"""
|
"""
|
||||||
return wx.TextCtrl.GetValue(self)
|
return wx.TextCtrl.GetValue(self)
|
||||||
@@ -1056,7 +1130,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
"""
|
"""
|
||||||
Returns the current numeric value of the control.
|
Returns the current numeric value of the control.
|
||||||
"""
|
"""
|
||||||
return self._fromGUI( MaskedTextCtrl.GetValue(self) )
|
return self._fromGUI( BaseMaskedTextCtrl.GetValue(self) )
|
||||||
|
|
||||||
def SetValue(self, value):
|
def SetValue(self, value):
|
||||||
"""
|
"""
|
||||||
@@ -1067,16 +1141,16 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
A ValueError exception will be raised if an invalid value
|
A ValueError exception will be raised if an invalid value
|
||||||
is specified.
|
is specified.
|
||||||
"""
|
"""
|
||||||
MaskedTextCtrl.SetValue( self, self._toGUI(value) )
|
BaseMaskedTextCtrl.SetValue( self, self._toGUI(value) )
|
||||||
|
|
||||||
|
|
||||||
def SetIntegerWidth(self, value):
|
def SetIntegerWidth(self, value):
|
||||||
self.SetCtrlParameters(integerWidth=value)
|
self.SetParameters(integerWidth=value)
|
||||||
def GetIntegerWidth(self):
|
def GetIntegerWidth(self):
|
||||||
return self._integerWidth
|
return self._integerWidth
|
||||||
|
|
||||||
def SetFractionWidth(self, value):
|
def SetFractionWidth(self, value):
|
||||||
self.SetCtrlParameters(fractionWidth=value)
|
self.SetParameters(fractionWidth=value)
|
||||||
def GetFractionWidth(self):
|
def GetFractionWidth(self):
|
||||||
return self._fractionWidth
|
return self._fractionWidth
|
||||||
|
|
||||||
@@ -1221,7 +1295,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
except ValueError, e:
|
except ValueError, e:
|
||||||
dbg('error getting NumValue(self._toGUI(value)):', e, indent=0)
|
dbg('error getting NumValue(self._toGUI(value)):', e, indent=0)
|
||||||
return False
|
return False
|
||||||
if value == '':
|
if value.strip() == '':
|
||||||
value = None
|
value = None
|
||||||
elif self._fractionWidth:
|
elif self._fractionWidth:
|
||||||
value = float(value)
|
value = float(value)
|
||||||
@@ -1294,6 +1368,12 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
def GetSelectOnEntry(self):
|
def GetSelectOnEntry(self):
|
||||||
return self._selectOnEntry
|
return self._selectOnEntry
|
||||||
|
|
||||||
|
def SetAutoSize(self, value):
|
||||||
|
self.SetParameters(autoSize=value)
|
||||||
|
def GetAutoSize(self):
|
||||||
|
return self._autoSize
|
||||||
|
|
||||||
|
|
||||||
# (Other parameter accessors are inherited from base class)
|
# (Other parameter accessors are inherited from base class)
|
||||||
|
|
||||||
|
|
||||||
@@ -1311,6 +1391,14 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
elif type(value) in (types.StringType, types.UnicodeType):
|
elif type(value) in (types.StringType, types.UnicodeType):
|
||||||
value = self._GetNumValue(value)
|
value = self._GetNumValue(value)
|
||||||
dbg('cleansed num value: "%s"' % value)
|
dbg('cleansed num value: "%s"' % value)
|
||||||
|
if value == "":
|
||||||
|
if self.IsNoneAllowed():
|
||||||
|
dbg(indent=0)
|
||||||
|
return self._template
|
||||||
|
else:
|
||||||
|
dbg('exception raised:', e, indent=0)
|
||||||
|
raise ValueError ('wxMaskedNumCtrl requires numeric value, passed %s'% repr(value) )
|
||||||
|
# else...
|
||||||
try:
|
try:
|
||||||
if self._fractionWidth or value.find('.') != -1:
|
if self._fractionWidth or value.find('.') != -1:
|
||||||
value = float(value)
|
value = float(value)
|
||||||
@@ -1380,7 +1468,7 @@ class MaskedNumCtrl(MaskedTextCtrl):
|
|||||||
# So, to ensure consistency and to prevent spurious ValueErrors,
|
# So, to ensure consistency and to prevent spurious ValueErrors,
|
||||||
# we make the following test, and react accordingly:
|
# we make the following test, and react accordingly:
|
||||||
#
|
#
|
||||||
if value == '':
|
if value.strip() == '':
|
||||||
if not self.IsNoneAllowed():
|
if not self.IsNoneAllowed():
|
||||||
dbg('empty value; not allowed,returning 0', indent = 0)
|
dbg('empty value; not allowed,returning 0', indent = 0)
|
||||||
if self._fractionWidth:
|
if self._fractionWidth:
|
||||||
@@ -1514,3 +1602,12 @@ i=0
|
|||||||
## =============================##
|
## =============================##
|
||||||
## 1. Add support for printf-style format specification.
|
## 1. Add support for printf-style format specification.
|
||||||
## 2. Add option for repositioning on 'illegal' insertion point.
|
## 2. Add option for repositioning on 'illegal' insertion point.
|
||||||
|
##
|
||||||
|
## Version 1.1
|
||||||
|
## 1. Fixed .SetIntegerWidth() and .SetFractionWidth() functions.
|
||||||
|
## 2. Added autoSize parameter, to allow manual sizing of the control.
|
||||||
|
## 3. Changed inheritance to use wxBaseMaskedTextCtrl, to remove exposure of
|
||||||
|
## nonsensical parameter methods from the control, so it will work
|
||||||
|
## properly with Boa.
|
||||||
|
## 4. Fixed allowNone bug found by user sameerc1@grandecom.net
|
||||||
|
|
||||||
|
@@ -60,12 +60,14 @@ Here's the API for TimeCtrl:
|
|||||||
<B>TimeCtrl</B>(
|
<B>TimeCtrl</B>(
|
||||||
parent, id = -1,
|
parent, id = -1,
|
||||||
<B>value</B> = '12:00:00 AM',
|
<B>value</B> = '12:00:00 AM',
|
||||||
pos = wxDefaultPosition,
|
pos = wx.DefaultPosition,
|
||||||
size = wxDefaultSize,
|
size = wx.DefaultSize,
|
||||||
<B>style</B> = wxTE_PROCESS_TAB,
|
<B>style</B> = wxTE_PROCESS_TAB,
|
||||||
<B>validator</B> = wxDefaultValidator,
|
<B>validator</B> = wx.DefaultValidator,
|
||||||
name = "time",
|
name = "time",
|
||||||
|
<B>format</B> = 'HHMMSS',
|
||||||
<B>fmt24hr</B> = False,
|
<B>fmt24hr</B> = False,
|
||||||
|
<B>displaySeconds</B> = True,
|
||||||
<B>spinButton</B> = None,
|
<B>spinButton</B> = None,
|
||||||
<B>min</B> = None,
|
<B>min</B> = None,
|
||||||
<B>max</B> = None,
|
<B>max</B> = None,
|
||||||
@@ -80,7 +82,7 @@ Here's the API for TimeCtrl:
|
|||||||
with SetValue() after instantiation of the control.)
|
with SetValue() after instantiation of the control.)
|
||||||
<DL><B>size</B>
|
<DL><B>size</B>
|
||||||
<DD>The size of the control will be automatically adjusted for 12/24 hour format
|
<DD>The size of the control will be automatically adjusted for 12/24 hour format
|
||||||
if wxDefaultSize is specified.
|
if wx.DefaultSize is specified.
|
||||||
<DT><B>style</B>
|
<DT><B>style</B>
|
||||||
<DD>By default, TimeCtrl will process TAB events, by allowing tab to the
|
<DD>By default, TimeCtrl will process TAB events, by allowing tab to the
|
||||||
different cells within the control.
|
different cells within the control.
|
||||||
@@ -89,11 +91,23 @@ Here's the API for TimeCtrl:
|
|||||||
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>
|
<BR>
|
||||||
|
<DT><B>format</B>
|
||||||
|
<DD>This parameter can be used instead of the fmt24hr and displaySeconds
|
||||||
|
parameters, respectively; it provides a shorthand way to specify the time
|
||||||
|
format you want. Accepted values are 'HHMMSS', 'HHMM', '24HHMMSS', and
|
||||||
|
'24HHMM'. If the format is specified, the other two arguments will be ignored.
|
||||||
|
<BR>
|
||||||
<DT><B>fmt24hr</B>
|
<DT><B>fmt24hr</B>
|
||||||
<DD>If True, control will display time in 24 hour time format; if False, it will
|
<DD>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.
|
control, based on the format specified. (This value is ignored if the <i>format</i>
|
||||||
|
parameter is specified.)
|
||||||
<BR>
|
<BR>
|
||||||
|
<DT><B>displaySeconds</B>
|
||||||
|
<DD>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>
|
||||||
|
parameter is specified.)
|
||||||
|
<BR>
|
||||||
<DT><B>spinButton</B>
|
<DT><B>spinButton</B>
|
||||||
<DD>If specified, this button's events will be bound to the behavior of the
|
<DD>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.)
|
||||||
@@ -151,7 +165,7 @@ set to Jan 1, 1970.) (Same as GetValue(as_wxDateTime=True); provided for backwar
|
|||||||
compatibility with previous release.)
|
compatibility with previous release.)
|
||||||
<BR>
|
<BR>
|
||||||
<BR>
|
<BR>
|
||||||
<DT><B>BindSpinButton(wxSpinBtton)</B>
|
<DT><B>BindSpinButton(SpinBtton)</B>
|
||||||
<DD>Binds an externally created spin button to the control, so that up/down spin
|
<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
|
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"
|
up/down cursor keys.) (This is primarily to allow you to create a "standard"
|
||||||
@@ -258,7 +272,7 @@ import types
|
|||||||
import wx
|
import wx
|
||||||
|
|
||||||
from wx.tools.dbg import Logger
|
from wx.tools.dbg import Logger
|
||||||
from wx.lib.maskededit import MaskedTextCtrl, Field
|
from wx.lib.maskededit import BaseMaskedTextCtrl, Field
|
||||||
|
|
||||||
dbg = Logger()
|
dbg = Logger()
|
||||||
dbg(enable=0)
|
dbg(enable=0)
|
||||||
@@ -281,11 +295,40 @@ class TimeUpdatedEvent(wx.PyCommandEvent):
|
|||||||
"""Retrieve the value of the time control at the time this event was generated"""
|
"""Retrieve the value of the time control at the time this event was generated"""
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
|
class TimeCtrlAccessorsMixin:
|
||||||
|
# Define TimeCtrl's list of attributes having their own
|
||||||
|
# Get/Set functions, ignoring those that make no sense for
|
||||||
|
# an numeric control.
|
||||||
|
exposed_basectrl_params = (
|
||||||
|
'defaultValue',
|
||||||
|
'description',
|
||||||
|
|
||||||
class TimeCtrl(MaskedTextCtrl):
|
'useFixedWidthFont',
|
||||||
|
'emptyBackgroundColour',
|
||||||
|
'validBackgroundColour',
|
||||||
|
'invalidBackgroundColour',
|
||||||
|
|
||||||
|
'validFunc',
|
||||||
|
'validRequired',
|
||||||
|
)
|
||||||
|
for param in exposed_basectrl_params:
|
||||||
|
propname = param[0].upper() + param[1:]
|
||||||
|
exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
|
||||||
|
exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
|
||||||
|
|
||||||
|
if param.find('Colour') != -1:
|
||||||
|
# add non-british spellings, for backward-compatibility
|
||||||
|
propname.replace('Colour', 'Color')
|
||||||
|
|
||||||
|
exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
|
||||||
|
exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
|
||||||
|
|
||||||
|
|
||||||
|
class TimeCtrl(BaseMaskedTextCtrl):
|
||||||
|
|
||||||
valid_ctrl_params = {
|
valid_ctrl_params = {
|
||||||
'display_seconds' : True, # by default, shows seconds
|
'format' : 'HHMMSS', # default format code
|
||||||
|
'displaySeconds' : True, # by default, shows seconds
|
||||||
'min': None, # by default, no bounds set
|
'min': None, # by default, no bounds set
|
||||||
'max': None,
|
'max': None,
|
||||||
'limited': False, # by default, no limiting even if bounds set
|
'limited': False, # by default, no limiting even if bounds set
|
||||||
@@ -316,61 +359,39 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
max = self.__max
|
max = self.__max
|
||||||
limited = self.__limited
|
limited = self.__limited
|
||||||
self.__posCurrent = 0
|
self.__posCurrent = 0
|
||||||
|
# handle deprecated keword argument name:
|
||||||
|
if kwargs.has_key('display_seconds'):
|
||||||
|
kwargs['displaySeconds'] = kwargs['display_seconds']
|
||||||
|
del kwargs['display_seconds']
|
||||||
|
if not kwargs.has_key('displaySeconds'):
|
||||||
|
kwargs['displaySeconds'] = True
|
||||||
|
|
||||||
|
# (handle positional arg (from original release) differently from rest of kwargs:)
|
||||||
|
self.__fmt24hr = False
|
||||||
|
if not kwargs.has_key('format'):
|
||||||
|
if fmt24hr:
|
||||||
|
if kwargs.has_key('displaySeconds') and kwargs['displaySeconds']:
|
||||||
|
kwargs['format'] = '24HHMMSS'
|
||||||
|
del kwargs['displaySeconds']
|
||||||
|
else:
|
||||||
|
kwargs['format'] = '24HHMM'
|
||||||
|
else:
|
||||||
|
if kwargs.has_key('displaySeconds') and kwargs['displaySeconds']:
|
||||||
|
kwargs['format'] = 'HHMMSS'
|
||||||
|
del kwargs['displaySeconds']
|
||||||
|
else:
|
||||||
|
kwargs['format'] = 'HHMM'
|
||||||
|
|
||||||
# (handle positional args (from original release) differently from rest of kwargs:)
|
if not kwargs.has_key('useFixedWidthFont'):
|
||||||
self.__fmt24hr = fmt24hr
|
# allow control over font selection:
|
||||||
|
kwargs['useFixedWidthFont'] = self.__useFixedWidthFont
|
||||||
|
|
||||||
maskededit_kwargs = {}
|
maskededit_kwargs = self.SetParameters(**kwargs)
|
||||||
|
|
||||||
# assign keyword args as appropriate:
|
# allow for explicit size specification:
|
||||||
for key, param_value in kwargs.items():
|
if size != wx.DefaultSize:
|
||||||
if key not in TimeCtrl.valid_ctrl_params.keys():
|
# override (and remove) "autofit" autoformat code in standard time formats:
|
||||||
raise AttributeError('invalid keyword argument "%s"' % key)
|
maskededit_kwargs['formatcodes'] = 'T!'
|
||||||
|
|
||||||
if key == "display_seconds":
|
|
||||||
self.__display_seconds = param_value
|
|
||||||
|
|
||||||
elif key == "min": min = param_value
|
|
||||||
elif key == "max": max = param_value
|
|
||||||
elif key == "limited": limited = param_value
|
|
||||||
|
|
||||||
elif key == "useFixedWidthFont":
|
|
||||||
maskededit_kwargs[key] = param_value
|
|
||||||
elif key == "oob_color":
|
|
||||||
maskededit_kwargs['invalidBackgroundColor'] = param_value
|
|
||||||
|
|
||||||
if self.__fmt24hr:
|
|
||||||
if self.__display_seconds: maskededit_kwargs['autoformat'] = 'MILTIMEHHMMSS'
|
|
||||||
else: maskededit_kwargs['autoformat'] = 'MILTIMEHHMM'
|
|
||||||
|
|
||||||
# Set hour field to zero-pad, right-insert, require explicit field change,
|
|
||||||
# select entire field on entry, and require a resultant valid entry
|
|
||||||
# to allow character entry:
|
|
||||||
hourfield = Field(formatcodes='0r<SV', validRegex='0\d|1\d|2[0123]', validRequired=True)
|
|
||||||
else:
|
|
||||||
if self.__display_seconds: maskededit_kwargs['autoformat'] = 'TIMEHHMMSS'
|
|
||||||
else: maskededit_kwargs['autoformat'] = 'TIMEHHMM'
|
|
||||||
|
|
||||||
# Set hour field to allow spaces (at start), right-insert,
|
|
||||||
# require explicit field change, select entire field on entry,
|
|
||||||
# and require a resultant valid entry to allow character entry:
|
|
||||||
hourfield = Field(formatcodes='_0<rSV', validRegex='0[1-9]| [1-9]|1[012]', validRequired=True)
|
|
||||||
ampmfield = Field(formatcodes='S', emptyInvalid = True, validRequired = True)
|
|
||||||
|
|
||||||
# Field 1 is always a zero-padded right-insert minute field,
|
|
||||||
# similarly configured as above:
|
|
||||||
minutefield = Field(formatcodes='0r<SV', validRegex='[0-5]\d', validRequired=True)
|
|
||||||
|
|
||||||
fields = [ hourfield, minutefield ]
|
|
||||||
if self.__display_seconds:
|
|
||||||
fields.append(copy.copy(minutefield)) # second field has same constraints as field 1
|
|
||||||
|
|
||||||
if not self.__fmt24hr:
|
|
||||||
fields.append(ampmfield)
|
|
||||||
|
|
||||||
# set fields argument:
|
|
||||||
maskededit_kwargs['fields'] = fields
|
|
||||||
|
|
||||||
# This allows range validation if set
|
# This allows range validation if set
|
||||||
maskededit_kwargs['validFunc'] = self.IsInBounds
|
maskededit_kwargs['validFunc'] = self.IsInBounds
|
||||||
@@ -379,16 +400,8 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
# dynamically without affecting individual field constraint validation
|
# dynamically without affecting individual field constraint validation
|
||||||
maskededit_kwargs['retainFieldValidation'] = True
|
maskededit_kwargs['retainFieldValidation'] = True
|
||||||
|
|
||||||
# allow control over font selection:
|
|
||||||
maskededit_kwargs['useFixedWidthFont'] = self.__useFixedWidthFont
|
|
||||||
|
|
||||||
# allow for explicit size specification:
|
|
||||||
if size != wx.DefaultSize:
|
|
||||||
# override (and remove) "autofit" autoformat code in standard time formats:
|
|
||||||
maskededit_kwargs['formatcodes'] = 'T!'
|
|
||||||
|
|
||||||
# Now we can initialize the base control:
|
# Now we can initialize the base control:
|
||||||
MaskedTextCtrl.__init__(
|
BaseMaskedTextCtrl.__init__(
|
||||||
self, parent, id=id,
|
self, parent, id=id,
|
||||||
pos=pos, size=size,
|
pos=pos, size=size,
|
||||||
style = style,
|
style = style,
|
||||||
@@ -425,7 +438,7 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
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_KEY_DOWN, self._OnKeyDown ) ## capture control events not normally seen, eg ctrl-tab.
|
self.Bind(wx.EVT_KEY_DOWN, self._OnKeyDown ) ## capture control events not normally seen, eg ctrl-tab.
|
||||||
self.Bind(wx.EVT_CHAR, self.__OnChar ) ## remove "shift" attribute from colon key event,
|
self.Bind(wx.EVT_CHAR, self.__OnChar ) ## remove "shift" attribute from colon key event,
|
||||||
## then call MaskedTextCtrl._OnChar with
|
## then call BaseMaskedTextCtrl._OnChar with
|
||||||
## the possibly modified event.
|
## the possibly modified event.
|
||||||
self.Bind(wx.EVT_TEXT, self.__OnTextChange, self ) ## color control appropriately and EVT_TIMEUPDATE events
|
self.Bind(wx.EVT_TEXT, self.__OnTextChange, self ) ## color control appropriately and EVT_TIMEUPDATE events
|
||||||
|
|
||||||
@@ -442,6 +455,110 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
self.BindSpinButton(spinButton) # bind spin button up/down events to this control
|
self.BindSpinButton(spinButton) # bind spin button up/down events to this control
|
||||||
|
|
||||||
|
|
||||||
|
def SetParameters(self, **kwargs):
|
||||||
|
dbg('TimeCtrl::SetParameters(%s)' % repr(kwargs), indent=1)
|
||||||
|
maskededit_kwargs = {}
|
||||||
|
reset_format = False
|
||||||
|
|
||||||
|
if kwargs.has_key('display_seconds'):
|
||||||
|
kwargs['displaySeconds'] = kwargs['display_seconds']
|
||||||
|
del kwargs['display_seconds']
|
||||||
|
if kwargs.has_key('format') and kwargs.has_key('displaySeconds'):
|
||||||
|
del kwargs['displaySeconds'] # always apply format if specified
|
||||||
|
|
||||||
|
# assign keyword args as appropriate:
|
||||||
|
for key, param_value in kwargs.items():
|
||||||
|
if key not in TimeCtrl.valid_ctrl_params.keys():
|
||||||
|
raise AttributeError('invalid keyword argument "%s"' % key)
|
||||||
|
|
||||||
|
if key == 'format':
|
||||||
|
# handle both local or generic 'maskededit' autoformat codes:
|
||||||
|
if param_value == 'HHMMSS' or param_value == 'TIMEHHMMSS':
|
||||||
|
self.__displaySeconds = True
|
||||||
|
self.__fmt24hr = False
|
||||||
|
elif param_value == 'HHMM' or param_value == 'TIMEHHMM':
|
||||||
|
self.__displaySeconds = False
|
||||||
|
self.__fmt24hr = False
|
||||||
|
elif param_value == '24HHMMSS' or param_value == '24HRTIMEHHMMSS':
|
||||||
|
self.__displaySeconds = True
|
||||||
|
self.__fmt24hr = True
|
||||||
|
elif param_value == '24HHMM' or param_value == '24HRTIMEHHMM':
|
||||||
|
self.__displaySeconds = False
|
||||||
|
self.__fmt24hr = True
|
||||||
|
else:
|
||||||
|
raise AttributeError('"%s" is not a valid format' % param_value)
|
||||||
|
reset_format = True
|
||||||
|
|
||||||
|
elif key in ("displaySeconds", "display_seconds") and not kwargs.has_key('format'):
|
||||||
|
self.__displaySeconds = param_value
|
||||||
|
reset_format = True
|
||||||
|
|
||||||
|
elif key == "min": min = param_value
|
||||||
|
elif key == "max": max = param_value
|
||||||
|
elif key == "limited": limited = param_value
|
||||||
|
|
||||||
|
elif key == "useFixedWidthFont":
|
||||||
|
maskededit_kwargs[key] = param_value
|
||||||
|
|
||||||
|
elif key == "oob_color":
|
||||||
|
maskededit_kwargs['invalidBackgroundColor'] = param_value
|
||||||
|
|
||||||
|
if reset_format:
|
||||||
|
if self.__fmt24hr:
|
||||||
|
if self.__displaySeconds: maskededit_kwargs['autoformat'] = '24HRTIMEHHMMSS'
|
||||||
|
else: maskededit_kwargs['autoformat'] = '24HRTIMEHHMM'
|
||||||
|
|
||||||
|
# Set hour field to zero-pad, right-insert, require explicit field change,
|
||||||
|
# select entire field on entry, and require a resultant valid entry
|
||||||
|
# to allow character entry:
|
||||||
|
hourfield = Field(formatcodes='0r<SV', validRegex='0\d|1\d|2[0123]', validRequired=True)
|
||||||
|
else:
|
||||||
|
if self.__displaySeconds: maskededit_kwargs['autoformat'] = 'TIMEHHMMSS'
|
||||||
|
else: maskededit_kwargs['autoformat'] = 'TIMEHHMM'
|
||||||
|
|
||||||
|
# Set hour field to allow spaces (at start), right-insert,
|
||||||
|
# require explicit field change, select entire field on entry,
|
||||||
|
# and require a resultant valid entry to allow character entry:
|
||||||
|
hourfield = Field(formatcodes='_0<rSV', validRegex='0[1-9]| [1-9]|1[012]', validRequired=True)
|
||||||
|
ampmfield = Field(formatcodes='S', emptyInvalid = True, validRequired = True)
|
||||||
|
|
||||||
|
# Field 1 is always a zero-padded right-insert minute field,
|
||||||
|
# similarly configured as above:
|
||||||
|
minutefield = Field(formatcodes='0r<SV', validRegex='[0-5]\d', validRequired=True)
|
||||||
|
|
||||||
|
fields = [ hourfield, minutefield ]
|
||||||
|
if self.__displaySeconds:
|
||||||
|
fields.append(copy.copy(minutefield)) # second field has same constraints as field 1
|
||||||
|
|
||||||
|
if not self.__fmt24hr:
|
||||||
|
fields.append(ampmfield)
|
||||||
|
|
||||||
|
# set fields argument:
|
||||||
|
maskededit_kwargs['fields'] = fields
|
||||||
|
|
||||||
|
# This allows range validation if set
|
||||||
|
maskededit_kwargs['validFunc'] = self.IsInBounds
|
||||||
|
|
||||||
|
# This allows range limits to affect insertion into control or not
|
||||||
|
# dynamically without affecting individual field constraint validation
|
||||||
|
maskededit_kwargs['retainFieldValidation'] = True
|
||||||
|
|
||||||
|
if hasattr(self, 'controlInitialized') and self.controlInitialized:
|
||||||
|
self.SetCtrlParameters(**maskededit_kwargs) # set appropriate parameters
|
||||||
|
|
||||||
|
# Validate initial value and set if appropriate
|
||||||
|
try:
|
||||||
|
self.SetBounds(min, max)
|
||||||
|
self.SetLimited(limited)
|
||||||
|
self.SetValue(value)
|
||||||
|
except:
|
||||||
|
self.SetValue('12:00:00 AM')
|
||||||
|
dbg(indent=0)
|
||||||
|
return {} # no arguments to return
|
||||||
|
else:
|
||||||
|
dbg(indent=0)
|
||||||
|
return maskededit_kwargs
|
||||||
|
|
||||||
|
|
||||||
def BindSpinButton(self, sb):
|
def BindSpinButton(self, sb):
|
||||||
"""
|
"""
|
||||||
@@ -496,7 +613,7 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
elif as_mxDateTimeDelta:
|
elif as_mxDateTimeDelta:
|
||||||
value = DateTime.DateTimeDelta(0, value.GetHour(), value.GetMinute(), value.GetSecond())
|
value = DateTime.DateTimeDelta(0, value.GetHour(), value.GetMinute(), value.GetSecond())
|
||||||
else:
|
else:
|
||||||
value = MaskedTextCtrl.GetValue(self)
|
value = BaseMaskedTextCtrl.GetValue(self)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
@@ -888,6 +1005,16 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def SetFormat(self, format):
|
||||||
|
self.SetParameters(format=format)
|
||||||
|
|
||||||
|
def GetFormat(self):
|
||||||
|
if self.__displaySeconds:
|
||||||
|
if self.__fmt24hr: return '24HHMMSS'
|
||||||
|
else: return 'HHMMSS'
|
||||||
|
else:
|
||||||
|
if self.__fmt24hr: return '24HHMM'
|
||||||
|
else: return 'HHMM'
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------------------------------------
|
||||||
# these are private functions and overrides:
|
# these are private functions and overrides:
|
||||||
@@ -896,7 +1023,7 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
def __OnTextChange(self, event=None):
|
def __OnTextChange(self, event=None):
|
||||||
dbg('TimeCtrl::OnTextChange', indent=1)
|
dbg('TimeCtrl::OnTextChange', indent=1)
|
||||||
|
|
||||||
# Allow wxMaskedtext base control to color as appropriate,
|
# Allow Maskedtext base control to color as appropriate,
|
||||||
# and Skip the EVT_TEXT event (if appropriate.)
|
# and Skip the EVT_TEXT event (if appropriate.)
|
||||||
##! WS: For some inexplicable reason, every wxTextCtrl.SetValue()
|
##! WS: For some inexplicable reason, every wxTextCtrl.SetValue()
|
||||||
## call is generating two (2) EVT_TEXT events. (!)
|
## call is generating two (2) EVT_TEXT events. (!)
|
||||||
@@ -905,7 +1032,7 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
## event iff the value has actually changed. The masked edit
|
## event iff the value has actually changed. The masked edit
|
||||||
## OnTextChange routine does this, and returns True on a valid event,
|
## OnTextChange routine does this, and returns True on a valid event,
|
||||||
## False otherwise.
|
## False otherwise.
|
||||||
if not MaskedTextCtrl._OnTextChange(self, event):
|
if not BaseMaskedTextCtrl._OnTextChange(self, event):
|
||||||
return
|
return
|
||||||
|
|
||||||
dbg('firing TimeUpdatedEvent...')
|
dbg('firing TimeUpdatedEvent...')
|
||||||
@@ -922,7 +1049,7 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
point is lost when the focus shifts to the spin button.
|
point is lost when the focus shifts to the spin button.
|
||||||
"""
|
"""
|
||||||
dbg('TimeCtrl::SetInsertionPoint', pos, indent=1)
|
dbg('TimeCtrl::SetInsertionPoint', pos, indent=1)
|
||||||
MaskedTextCtrl.SetInsertionPoint(self, pos) # (causes EVT_TEXT event to fire)
|
BaseMaskedTextCtrl.SetInsertionPoint(self, pos) # (causes EVT_TEXT event to fire)
|
||||||
self.__posCurrent = self.GetInsertionPoint()
|
self.__posCurrent = self.GetInsertionPoint()
|
||||||
dbg(indent=0)
|
dbg(indent=0)
|
||||||
|
|
||||||
@@ -941,7 +1068,7 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
sel_to = cell_end
|
sel_to = cell_end
|
||||||
|
|
||||||
self.__bSelection = sel_start != sel_to
|
self.__bSelection = sel_start != sel_to
|
||||||
MaskedTextCtrl.SetSelection(self, sel_start, sel_to)
|
BaseMaskedTextCtrl.SetSelection(self, sel_start, sel_to)
|
||||||
dbg(indent=0)
|
dbg(indent=0)
|
||||||
|
|
||||||
|
|
||||||
@@ -998,7 +1125,7 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
if keycode == ord(':'):
|
if keycode == ord(':'):
|
||||||
dbg('colon seen! removing shift attribute')
|
dbg('colon seen! removing shift attribute')
|
||||||
event.m_shiftDown = False
|
event.m_shiftDown = False
|
||||||
MaskedTextCtrl._OnChar(self, event ) ## handle each keypress
|
BaseMaskedTextCtrl._OnChar(self, event ) ## handle each keypress
|
||||||
dbg(indent=0)
|
dbg(indent=0)
|
||||||
|
|
||||||
|
|
||||||
@@ -1084,11 +1211,11 @@ class TimeCtrl(MaskedTextCtrl):
|
|||||||
converts it to a string appropriate for the format of the control.
|
converts it to a string appropriate for the format of the control.
|
||||||
"""
|
"""
|
||||||
if self.__fmt24hr:
|
if self.__fmt24hr:
|
||||||
if self.__display_seconds: strval = wxdt.Format('%H:%M:%S')
|
if self.__displaySeconds: strval = wxdt.Format('%H:%M:%S')
|
||||||
else: strval = wxdt.Format('%H:%M')
|
else: strval = wxdt.Format('%H:%M')
|
||||||
else:
|
else:
|
||||||
if self.__display_seconds: strval = wxdt.Format('%I:%M:%S %p')
|
if self.__displaySeconds: strval = wxdt.Format('%I:%M:%S %p')
|
||||||
else: strval = wxdt.Format('%I:%M %p')
|
else: strval = wxdt.Format('%I:%M %p')
|
||||||
|
|
||||||
return strval
|
return strval
|
||||||
|
|
||||||
@@ -1178,3 +1305,11 @@ if __name__ == '__main__':
|
|||||||
app.MainLoop()
|
app.MainLoop()
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
i=0
|
||||||
|
## Version 1.2
|
||||||
|
## 1. Changed parameter name display_seconds to displaySeconds, to follow
|
||||||
|
## other masked edit conventions.
|
||||||
|
## 2. Added format parameter, to remove need to use both fmt24hr and displaySeconds.
|
||||||
|
## 3. Changed inheritance to use BaseMaskedTextCtrl, to remove exposure of
|
||||||
|
## nonsensical parameter methods from the control, so it will work
|
||||||
|
## properly with Boa.
|
||||||
|
Reference in New Issue
Block a user