Patches from Will Sadkin:

MaskedEditMixin:
- fixed size calculations on changing fonts
- fixed tabbing logic now that tab events are entered into the control
  by default (ie event.Skip()) if wx.TE_PROCESS_TAB is set
- fixed code attempting to fix the selection after focus events
  generated on control destruction, to prevent tracebacks

TextCtrl, ComboBox
- Added support for XRC
- Fixed sizing calculation code
- Added SetFont() override method that will recalculate the size if this
  is called.
- Added AppendItems() for ComboBox

NumCtrl:
- prevented ctrl from accepting same grouping and decimal character,
- fixed issue preventing paste from working if decimal char was different
  than '.'

TimeCtrl:
- Fixed default value to use 24hour time (which will be converted
  appropriately if format supports it, and added code to check if
  local timezone uses "AM/PM" for this concept; if not, control now
  defaults to 24hour format, and disallows the am/pm form.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28400 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2004-07-22 18:38:34 +00:00
parent b591b7cf2b
commit 339983ff62
6 changed files with 257 additions and 55 deletions

View File

@@ -12,8 +12,8 @@
# import relevant external symbols into package namespace:
from maskededit import *
from textctrl import BaseMaskedTextCtrl, TextCtrl
from combobox import BaseMaskedComboBox, ComboBox, MaskedComboBoxSelectEvent
from textctrl import BaseMaskedTextCtrl, PreMaskedTextCtrl, TextCtrl
from combobox import BaseMaskedComboBox, PreMaskedComboBox, ComboBox, MaskedComboBoxSelectEvent
from numctrl import NumCtrl, wxEVT_COMMAND_MASKED_NUMBER_UPDATED, EVT_NUM, NumberUpdatedEvent
from timectrl import TimeCtrl, wxEVT_TIMEVAL_UPDATED, EVT_TIMEUPDATE, TimeUpdatedEvent
from ipaddrctrl import IpAddrCtrl

View File

@@ -54,11 +54,6 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
**kwargs):
# This is necessary, because wxComboBox currently provides no
# method for determining later if this was specified in the
# constructor for the control...
self.__readonly = style & wx.CB_READONLY == wx.CB_READONLY
kwargs['choices'] = choices ## set up maskededit to work with choice list too
## Since combobox completion is case-insensitive, always validate same way
@@ -80,15 +75,56 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
choices=choices, style=style|wx.WANTS_CHARS,
validator=validator,
name=name)
self.controlInitialized = True
self._PostInit(style=style, setupEventHandling=setupEventHandling,
name=name, value=value, **kwargs)
def _PostInit(self, style=wx.CB_DROPDOWN,
setupEventHandling = True, ## setup event handling by default):
name = "maskedComboBox", value='', **kwargs):
# This is necessary, because wxComboBox currently provides no
# method for determining later if this was specified in the
# constructor for the control...
self.__readonly = style & wx.CB_READONLY == wx.CB_READONLY
if not hasattr(self, 'controlInitialized'):
self.controlInitialized = True ## must have been called via XRC, therefore base class is constructed
if not kwargs.has_key('choices'):
choices=[]
kwargs['choices'] = choices ## set up maskededit to work with choice list too
self._choices = []
## Since combobox completion is case-insensitive, always validate same way
if not kwargs.has_key('compareNoCase'):
kwargs['compareNoCase'] = True
MaskedEditMixin.__init__( self, name, **kwargs )
self._choices = self._ctrl_constraints._choices
## dbg('self._choices:', self._choices)
if self._ctrl_constraints._alignRight:
choices = [choice.rjust(self._masklength) for choice in choices]
else:
choices = [choice.ljust(self._masklength) for choice in choices]
wx.ComboBox.Clear(self)
wx.ComboBox.AppendItems(self, choices)
# Set control font - fixed width by default
self._setFont()
if self._autofit:
self.SetClientSize(self._CalcSize())
self.SetSizeHints(self.GetSize())
width = self.GetSize().width
height = self.GetBestSize().height
self.SetSize((width, height))
self.SetSizeHints((width, height))
if value:
# ensure value is width of the mask of the control:
@@ -134,6 +170,19 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
return (size[0]+20, size[1])
def SetFont(self, *args, **kwargs):
""" Set the font, then recalculate control size, if appropriate. """
wx.ComboBox.SetFont(self, *args, **kwargs)
if self._autofit:
dbg('calculated size:', self._CalcSize())
self.SetClientSize(self._CalcSize())
width = self.GetSize().width
height = self.GetBestSize().height
dbg('setting client size to:', (width, height))
self.SetSize((width, height))
self.SetSizeHints((width, height))
def _GetSelection(self):
"""
Allow mixin to get the text selection of this control.
@@ -306,7 +355,6 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
else:
wx.ComboBox.Undo() # else revert to base control behavior
def Append( self, choice, clientData=None ):
"""
This function override is necessary so we can keep track of any additions to the list
@@ -352,6 +400,13 @@ class BaseMaskedComboBox( wx.ComboBox, MaskedEditMixin ):
wx.ComboBox.Append(self, choice, clientData)
def AppendItems( self, choices ):
"""
AppendItems() is handled in terms of Append, to avoid code replication.
"""
for choice in choices:
self.Append(choice)
def Clear( self ):
"""
@@ -544,3 +599,30 @@ class ComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
pass
class PreMaskedComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
"""
This allows us to use XRC subclassing.
"""
# This should really be wx.EVT_WINDOW_CREATE but it is not
# currently delivered for native controls on all platforms, so
# we'll use EVT_SIZE instead. It should happen shortly after the
# control is created as the control is set to its "best" size.
_firstEventType = wx.EVT_SIZE
def __init__(self):
pre = wx.PreComboBox()
self.PostCreate(pre)
self.Bind(self._firstEventType, self.OnCreate)
def OnCreate(self, evt):
self.Unbind(self._firstEventType)
self._PostInit()
i=0
## CHANGELOG:
## ====================
## Version 1.1
## 1. Added .SetFont() method that properly resizes control
## 2. Modified control to support construction via XRC mechanism.
## 3. Added AppendItems() to conform with latest combobox.

View File

@@ -757,7 +757,7 @@ import wx
from wx.tools.dbg import Logger
dbg = Logger()
##dbg(enable=0)
##dbg(enable=1)
## ---------- ---------- ---------- ---------- ---------- ---------- ----------
@@ -1914,9 +1914,13 @@ class MaskedEditMixin:
self._prevValue = newvalue # disallow undo of sign type
if self._autofit:
## dbg('setting client size to:', self._CalcSize())
## dbg('calculated size:', self._CalcSize())
self.SetClientSize(self._CalcSize())
self.SetSizeHints(self.GetSize())
width = self.GetSize().width
height = self.GetBestSize().height
## dbg('setting client size to:', (width, height))
self.SetSize((width, height))
self.SetSizeHints((width, height))
# Set value/type-specific formatting
self._applyFormatting()
@@ -1991,8 +1995,24 @@ class MaskedEditMixin:
self._SetInitialValue()
if self._autofit:
# this is tricky, because, as Robin explains:
# "Basically there are two sizes to deal with, that are potentially
# different. The client size is the inside size and may, depending
# on platform, exclude the borders and such. The normal size is
# the outside size that does include the borders. What you are
# calculating (in _CalcSize) is the client size, but the sizers
# deal with the full size and so that is the minimum size that
# we need to set with SetSizeHints. The root of the problem is
# that in _calcSize the current client size height is returned,
# instead of a height based on the current font. So I suggest using
# _calcSize to just get the width, and then use GetBestSize to
# get the height."
self.SetClientSize(self._CalcSize())
self.SetSizeHints(self.GetSize())
width = self.GetSize().width
height = self.GetBestSize().height
self.SetSize((width, height))
self.SetSizeHints((width, height))
# Set value/type-specific formatting
self._applyFormatting()
@@ -2642,7 +2662,7 @@ class MaskedEditMixin:
sizing_text += 'M'
#### dbg('len(sizing_text):', len(sizing_text), 'sizing_text: "%s"' % sizing_text)
w, h = self.GetTextExtent(sizing_text)
size = (w+4, self.GetClientSize().height)
size = (w+4, self.GetSize().height)
#### dbg('size:', size, indent=0)
return size
@@ -2690,7 +2710,7 @@ class MaskedEditMixin:
## dbg('ignoring bogus text change event', indent=0)
pass
else:
## dbg('curvalue: "%s", newvalue: "%s"' % (self._curValue, newvalue))
## dbg('curvalue: "%s", newvalue: "%s", len(newvalue): %d' % (self._curValue, newvalue, len(newvalue)))
if self._Change():
if self._signOk and self._isNeg and newvalue.find('-') == -1 and newvalue.find('(') == -1:
## dbg('clearing self._isNeg')
@@ -2864,6 +2884,8 @@ class MaskedEditMixin:
if newfield != field and newfield._selectOnFieldEntry:
## dbg('queuing selection: (%d, %d)' % (newfield._extent[0], newfield._extent[1]))
wx.CallAfter(self._SetSelection, newfield._extent[0], newfield._extent[1])
else:
wx.CallAfter(self._SetSelection, newpos, new_select_to)
keep_processing = False
elif keep_processing:
@@ -3400,12 +3422,12 @@ class MaskedEditMixin:
def _OnReturn(self, event):
"""
Changes the event to look like a tab event, so we can then call
event.Skip() on it, and have the parent form "do the right thing."
Swallows the return, issues a Navigate event instead, since
masked controls are "single line" by defn.
"""
## dbg('MaskedEditMixin::OnReturn')
event.m_keyCode = wx.WXK_TAB
event.Skip()
self.Navigate(True)
return False
def _OnHome(self,event):
@@ -3486,9 +3508,6 @@ class MaskedEditMixin:
"""
Primarily handles TAB events, but can be used for any key that
designer wants to change fields within a masked edit control.
NOTE: at the moment, although coded to handle shift-TAB and
control-shift-TAB, these events are not sent to the controls
by the framework.
"""
## dbg('MaskedEditMixin::_OnChangeField', indent = 1)
# determine end of current field:
@@ -3500,7 +3519,10 @@ class MaskedEditMixin:
self._AdjustField(pos)
if event.GetKeyCode() == wx.WXK_TAB:
## dbg('tab to next ctrl')
event.Skip()
# As of 2.5.2, you don't call event.Skip() to do
# this, but instead force explicit navigation, if
# wx.TE_PROCESS_TAB is used (like in the masked edits)
self.Navigate(True)
#else: do nothing
## dbg(indent=0)
return False
@@ -3534,7 +3556,10 @@ class MaskedEditMixin:
self._AdjustField(pos)
if event.GetKeyCode() == wx.WXK_TAB:
## dbg('tab to previous ctrl')
event.Skip()
# As of 2.5.2, you don't call event.Skip() to do
# this, but instead force explicit navigation, if
# wx.TE_PROCESS_TAB is used (like in the masked edits)
self.Navigate(False)
else:
## dbg('position at beginning')
wx.CallAfter(self._SetInsertionPoint, field_start)
@@ -3580,7 +3605,10 @@ class MaskedEditMixin:
self._AdjustField(pos)
if event.GetKeyCode() == wx.WXK_TAB:
## dbg('tab to next ctrl')
event.Skip()
# As of 2.5.2, you don't call event.Skip() to do
# this, but instead force explicit navigation, if
# wx.TE_PROCESS_TAB is used (like in the masked edits)
self.Navigate(True)
else:
## dbg('position at end')
wx.CallAfter(self._SetInsertionPoint, field_end)
@@ -3594,7 +3622,10 @@ class MaskedEditMixin:
self._AdjustField(pos)
if event.GetKeyCode() == wx.WXK_TAB:
## dbg('tab to next ctrl')
event.Skip()
# As of 2.5.2, you don't call event.Skip() to do
# this, but instead force explicit navigation, if
# wx.TE_PROCESS_TAB is used (like in the masked edits)
self.Navigate(True)
#else: do nothing
## dbg(indent=0)
return False
@@ -3640,6 +3671,8 @@ class MaskedEditMixin:
if fraction._selectOnFieldEntry:
## dbg('queuing selection after decimal point to:', (start, end))
wx.CallAfter(self._SetSelection, start, end)
else:
wx.CallAfter(self._SetSelection, start, start)
keep_processing = False
if self._isInt: ## handle integer value, truncate from current position
@@ -3654,6 +3687,7 @@ class MaskedEditMixin:
if newstr.find(')') != -1:
newpos -= 1 # (don't move past right paren)
wx.CallAfter(self._SetInsertionPoint, newpos)
wx.CallAfter(self._SetSelection, newpos, newpos)
keep_processing = False
## dbg(indent=0)
@@ -3949,6 +3983,7 @@ class MaskedEditMixin:
pos = pos+2
if newvalue != value:
## dbg('old value: "%s"\nnew value: "%s"' % (value, newvalue))
self._SetValue(newvalue)
self._SetInsertionPoint(pos)
@@ -4042,6 +4077,8 @@ class MaskedEditMixin:
self._SetInsertionPoint(pos)
if pos < sel_to: # restore selection
self._SetSelection(pos, sel_to)
else:
self._SetSelection(pos, pos)
## dbg('adjusted pos:', pos, indent=0)
return pos
@@ -5182,7 +5219,10 @@ class MaskedEditMixin:
the control, and deselect.
"""
## dbg('MaskedEditMixin::_fixSelection', indent=1)
if not self._mask or not self._IsEditable():
# can get here if called with wx.CallAfter after underlying
# control has been destroyed on close, but after focus
# events
if not self or not self._mask or not self._IsEditable():
## dbg(indent=0)
return
@@ -6396,6 +6436,8 @@ i=1
## chars properly.)
## 4. Fixed autoselect behavior to work similarly to (2) above, so that combobox
## selection will only select the non-empty text, as per request.
## 5. Fixed tabbing to work with 2.5.2 semantics.
## 6. Fixed size calculation to handle changing fonts
##
## Version 1.6
## 1. Reorganized masked controls into separate package, renamed things accordingly

View File

@@ -386,7 +386,7 @@ MININT = -maxint-1
from wx.tools.dbg import Logger
from wx.lib.masked import MaskedEditMixin, Field, BaseMaskedTextCtrl
dbg = Logger()
##dbg(enable=0)
##dbg(enable=1)
#----------------------------------------------------------------------------
@@ -654,14 +654,26 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
maskededit_kwargs['mask'] = intmask+fracmask
if kwargs.has_key('groupChar'):
if kwargs.has_key('groupChar') or kwargs.has_key('decimalChar'):
old_groupchar = self._groupChar # save so we can reformat properly
## dbg("old_groupchar: '%s'" % old_groupchar)
maskededit_kwargs['groupChar'] = kwargs['groupChar']
if kwargs.has_key('decimalChar'):
old_decimalchar = self._decimalChar
## dbg("old_groupchar: '%s'" % old_groupchar)
## dbg("old_decimalchar: '%s'" % old_decimalchar)
groupchar = old_groupchar
decimalchar = old_decimalchar
if kwargs.has_key('groupChar'):
maskededit_kwargs['groupChar'] = kwargs['groupChar']
groupchar = kwargs['groupChar']
if kwargs.has_key('decimalChar'):
maskededit_kwargs['decimalChar'] = kwargs['decimalChar']
decimalchar = kwargs['decimalChar']
# Add sanity check to make sure these are distinct, and if not,
# raise attribute error
if groupchar == decimalchar:
raise AttributeError('groupChar and decimalChar must be distinct')
# for all other parameters, assign keyword args as appropriate:
for key, param_value in kwargs.items():
@@ -1089,9 +1101,8 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
and value[sel_start:sel_to] == self._groupChar ):
self.SetInsertionPoint(sel_start)
self.SetSelection(sel_start, sel_to+1)
return BaseMaskedTextCtrl._OnErase(self, event, just_return_value)
## dbg(indent=0)
return BaseMaskedTextCtrl._OnErase(self, event, just_return_value)
def OnTextChange( self, event ):
@@ -1146,7 +1157,9 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
A ValueError exception will be raised if an invalid value
is specified.
"""
## dbg('NumCtrl::SetValue(%s)' % value, indent=1)
BaseMaskedTextCtrl.SetValue( self, self._toGUI(value) )
## dbg(indent=0)
def SetIntegerWidth(self, value):
@@ -1519,7 +1532,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
Preprocessor for base control paste; if value needs to be right-justified
to fit in control, do so prior to paste:
"""
## dbg('NumCtrl::_Paste (value = "%s")' % value)
## dbg('NumCtrl::_Paste (value = "%s")' % value, indent=1)
if value is None:
paste_text = self._getClipboardContents()
else:
@@ -1533,7 +1546,7 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
#
field = self._FindField(sel_start)
edit_start, edit_end = field._extent
paste_text = paste_text.replace(self._groupChar, '').replace(self._decimalChar, '.').replace('(', '-').replace(')','')
paste_text = paste_text.replace(self._groupChar, '').replace('(', '-').replace(')','')
if field._insertRight and self._groupDigits:
# want to paste to the left; see if it will fit:
left_text = old_value[edit_start:sel_start].lstrip()
@@ -1564,12 +1577,6 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
self.SetInsertionPoint(sel_to)
self.SetSelection(sel_start, sel_to)
## # treat paste as "replace number", if appropriate:
## sel_start, sel_to = self._GetSelection()
## if sel_start == sel_to or self._selectOnEntry and (sel_start, sel_to) == self._fields[0]._extent:
## paste_text = self._toGUI(paste_text)
## self._SetSelection(0, len(self._mask))
new_text, replace_to = MaskedEditMixin._Paste(self,
paste_text,
raise_on_invalid=raise_on_invalid,

View File

@@ -22,7 +22,7 @@ from wx.lib.masked import *
# be a good place to implement the 2.3 logger class
from wx.tools.dbg import Logger
dbg = Logger()
##dbg(enable=0)
##dbg(enable=1)
# ## TRICKY BIT: to avoid a ton of boiler-plate, and to
# ## automate the getter/setter generation for each valid
@@ -76,6 +76,13 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
style=style, validator=validator,
name=name)
self._PostInit(setupEventHandling = setupEventHandling,
name=name, value=value,**kwargs )
def _PostInit(self,setupEventHandling=True,
name='maskedTextCtrl' , value='', **kwargs):
self.controlInitialized = True
MaskedEditMixin.__init__( self, name, **kwargs )
@@ -219,6 +226,18 @@ class BaseMaskedTextCtrl( wx.TextCtrl, MaskedEditMixin ):
wx.CallAfter(self._SetSelection, replace_to, replace_to)
## dbg(indent=0)
def SetFont(self, *args, **kwargs):
""" Set the font, then recalculate control size, if appropriate. """
wx.TextCtrl.SetFont(self, *args, **kwargs)
if self._autofit:
## dbg('calculated size:', self._CalcSize())
self.SetClientSize(self._CalcSize())
width = self.GetSize().width
height = self.GetBestSize().height
## dbg('setting client size to:', (width, height))
self.SetSize((width, height))
self.SetSizeHints((width, height))
def Clear(self):
""" Blanks the current control value by replacing it with the default value."""
@@ -324,3 +343,29 @@ class TextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ):
pass
class PreMaskedTextCtrl( BaseMaskedTextCtrl, MaskedEditAccessorsMixin ):
"""
This allows us to use XRC subclassing.
"""
# This should really be wx.EVT_WINDOW_CREATE but it is not
# currently delivered for native controls on all platforms, so
# we'll use EVT_SIZE instead. It should happen shortly after the
# control is created as the control is set to its "best" size.
_firstEventType = wx.EVT_SIZE
def __init__(self):
pre = wx.PreTextCtrl()
self.PostCreate(pre)
self.Bind(self._firstEventType, self.OnCreate)
def OnCreate(self, evt):
self.Unbind(self._firstEventType)
self._PostInit()
i=0
## CHANGELOG:
## ====================
## Version 1.1
## 1. Added .SetFont() method that properly resizes control
## 2. Modified control to support construction via XRC mechanism.

View File

@@ -59,7 +59,7 @@ Here's the API for TimeCtrl:
<DL><PRE>
<B>TimeCtrl</B>(
parent, id = -1,
<B>value</B> = '12:00:00 AM',
<B>value</B> = '00:00:00',
pos = wx.DefaultPosition,
size = wx.DefaultSize,
<B>style</B> = wxTE_PROCESS_TAB,
@@ -82,7 +82,10 @@ Here's the API for TimeCtrl:
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
if wx.DefaultSize is specified.
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
change to 24 hour format, and an AttributeError will be thrown if a non-24 format
is specified.
<DT><B>style</B>
<DD>By default, TimeCtrl will process TAB events, by allowing tab to the
different cells within the control.
@@ -337,7 +340,7 @@ class TimeCtrl(BaseMaskedTextCtrl):
}
def __init__ (
self, parent, id=-1, value = '12:00:00 AM',
self, parent, id=-1, value = '00:00:00',
pos = wx.DefaultPosition, size = wx.DefaultSize,
fmt24hr=False,
spinButton = None,
@@ -348,6 +351,15 @@ class TimeCtrl(BaseMaskedTextCtrl):
# set defaults for control:
## dbg('setting defaults:')
self.__fmt24hr = False
wxdt = wx.DateTimeFromDMY(1, 0, 1970)
if wxdt.Format('%p') != 'AM':
TimeCtrl.valid_ctrl_params['format'] = '24HHMMSS'
self.__fmt24hr = True
fmt24hr = True # force/change default positional argument
# (will countermand explicit set to False too.)
for key, param_value in TimeCtrl.valid_ctrl_params.items():
# This is done this way to make setattr behave consistently with
# "private attribute" name mangling
@@ -367,7 +379,6 @@ class TimeCtrl(BaseMaskedTextCtrl):
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']:
@@ -449,7 +460,7 @@ class TimeCtrl(BaseMaskedTextCtrl):
self.SetLimited(limited)
self.SetValue(value)
except:
self.SetValue('12:00:00 AM')
self.SetValue('00:00:00')
if spinButton:
self.BindSpinButton(spinButton) # bind spin button up/down events to this control
@@ -472,6 +483,12 @@ class TimeCtrl(BaseMaskedTextCtrl):
raise AttributeError('invalid keyword argument "%s"' % key)
if key == 'format':
wxdt = wx.DateTimeFromDMY(1, 0, 1970)
if wxdt.Format('%p') != 'AM':
require24hr = True
else:
require24hr = False
# handle both local or generic 'maskededit' autoformat codes:
if param_value == 'HHMMSS' or param_value == 'TIMEHHMMSS':
self.__displaySeconds = True
@@ -487,6 +504,10 @@ class TimeCtrl(BaseMaskedTextCtrl):
self.__fmt24hr = True
else:
raise AttributeError('"%s" is not a valid format' % param_value)
if require24hr and not self.__fmt24hr:
raise AttributeError('"%s" is an unsupported time format for the current locale' % param_value)
reset_format = True
elif key in ("displaySeconds", "display_seconds") and not kwargs.has_key('format'):
@@ -552,7 +573,7 @@ class TimeCtrl(BaseMaskedTextCtrl):
self.SetLimited(limited)
self.SetValue(value)
except:
self.SetValue('12:00:00 AM')
self.SetValue('00:00:00')
## dbg(indent=0)
return {} # no arguments to return
else:
@@ -663,6 +684,11 @@ class TimeCtrl(BaseMaskedTextCtrl):
## dbg('checkTime == len(value)?', valid)
if not valid:
# deal with bug/deficiency in wx.DateTime:
if wxdt.Format('%p') not in ('AM', 'PM') and checkTime in (5,8):
# couldn't parse the AM/PM field
raise ValueError('cannot convert string "%s" to valid time for the current locale; please use 24hr time instead' % value)
else:
## dbg(indent=0, suspend=0)
raise ValueError('cannot convert string "%s" to valid time' % value)