📄 numctrl.py
字号:
if self._fractionWidth != kwargs['fractionWidth']:
self._fractionWidth = kwargs['fractionWidth']
if self._fractionWidth:
fracmask = '.' + '#{%d}' % self._fractionWidth
fields[1] = Field(defaultValue='0'*self._fractionWidth)
emptyInvalid = False
else:
emptyInvalid = True
fracmask = ''
## dbg('fracmask:', fracmask)
if kwargs.has_key('integerWidth'):
if type(kwargs['integerWidth']) != types.IntType:
## dbg(indent=0)
raise AttributeError('invalid integerWidth (%s) specified; expected integer' % repr(kwargs['integerWidth']))
elif kwargs['integerWidth'] < 0:
## dbg(indent=0)
raise AttributeError('invalid integerWidth (%s) specified; must be > 0' % repr(kwargs['integerWidth']))
else:
self._integerWidth = kwargs['integerWidth']
if kwargs.has_key('groupDigits'):
self._groupDigits = kwargs['groupDigits']
if self._groupDigits:
self._groupSpace = (self._integerWidth - 1) / 3
else:
self._groupSpace = 0
intmask = '#{%d}' % (self._integerWidth + self._groupSpace)
## dbg('intmask:', intmask)
fields[0] = Field(formatcodes='r<>', emptyInvalid=emptyInvalid)
maskededit_kwargs['fields'] = fields
# don't bother to reprocess these arguments:
if kwargs.has_key('integerWidth'):
del kwargs['integerWidth']
if kwargs.has_key('fractionWidth'):
del kwargs['fractionWidth']
maskededit_kwargs['mask'] = intmask+fracmask
if kwargs.has_key('groupChar') or kwargs.has_key('decimalChar'):
old_groupchar = self._groupChar # save so we can reformat properly
old_decimalchar = self._decimalChar
## dbg("old_groupchar: '%s'" % old_groupchar)
## dbg("old_decimalchar: '%s'" % old_decimalchar)
groupchar = old_groupchar
decimalchar = old_decimalchar
old_numvalue = self._GetNumValue(self._GetValue())
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():
key = key.replace('Color', 'Colour')
if key not in NumCtrl.valid_ctrl_params.keys():
raise AttributeError('invalid keyword argument "%s"' % key)
elif key not in MaskedEditMixin.valid_ctrl_params.keys():
setattr(self, '_' + key, param_value)
elif key in ('mask', 'autoformat'): # disallow explicit setting of mask
raise AttributeError('invalid keyword argument "%s"' % key)
else:
maskededit_kwargs[key] = param_value
## dbg('kwargs:', kwargs)
# reprocess existing format codes to ensure proper resulting format:
formatcodes = self.GetCtrlParameter('formatcodes')
if kwargs.has_key('allowNegative'):
if kwargs['allowNegative'] and '-' not in formatcodes:
formatcodes += '-'
maskededit_kwargs['formatcodes'] = formatcodes
elif not kwargs['allowNegative'] and '-' in formatcodes:
formatcodes = formatcodes.replace('-','')
maskededit_kwargs['formatcodes'] = formatcodes
if kwargs.has_key('groupDigits'):
if kwargs['groupDigits'] and ',' not in formatcodes:
formatcodes += ','
maskededit_kwargs['formatcodes'] = formatcodes
elif not kwargs['groupDigits'] and ',' in formatcodes:
formatcodes = formatcodes.replace(',','')
maskededit_kwargs['formatcodes'] = formatcodes
if kwargs.has_key('selectOnEntry'):
self._selectOnEntry = kwargs['selectOnEntry']
## dbg("kwargs['selectOnEntry']?", kwargs['selectOnEntry'], "'S' in formatcodes?", 'S' in formatcodes)
if kwargs['selectOnEntry'] and 'S' not in formatcodes:
formatcodes += 'S'
maskededit_kwargs['formatcodes'] = formatcodes
elif not kwargs['selectOnEntry'] and 'S' in formatcodes:
formatcodes = formatcodes.replace('S','')
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:
# top-level mask should only be right insert if no fractional
# part will be shown; ie. if reconfiguring control, remove
# previous "global" setting.
formatcodes = formatcodes.replace('r', '')
maskededit_kwargs['formatcodes'] = formatcodes
if kwargs.has_key('limited'):
if kwargs['limited'] and not self._limited:
maskededit_kwargs['validRequired'] = True
elif not kwargs['limited'] and self._limited:
maskededit_kwargs['validRequired'] = False
self._limited = kwargs['limited']
## dbg('maskededit_kwargs:', maskededit_kwargs)
if maskededit_kwargs.keys():
self.SetCtrlParameters(**maskededit_kwargs)
# Go ensure all the format codes necessary are present:
orig_intformat = intformat = self.GetFieldParameter(0, 'formatcodes')
if 'r' not in intformat:
intformat += 'r'
if '>' not in intformat:
intformat += '>'
if intformat != orig_intformat:
if self._fractionWidth:
self.SetFieldParameters(0, formatcodes=intformat)
else:
self.SetCtrlParameters(formatcodes=intformat)
# Record end of integer and place cursor there unless selecting, or select entire field:
integerStart, integerEnd = self._fields[0]._extent
if not self._fields[0]._selectOnFieldEntry:
self.SetInsertionPoint(0)
self.SetInsertionPoint(integerEnd)
self.SetSelection(integerEnd, integerEnd)
else:
self.SetInsertionPoint(0) # include any sign
self.SetSelection(0, integerEnd)
# Set min and max as appropriate:
if kwargs.has_key('min'):
min = kwargs['min']
if( self._max is None
or min is None
or (self._max is not None and self._max >= min) ):
## dbg('examining min')
if min is not None:
try:
textmin = self._toGUI(min, apply_limits = False)
except ValueError:
## dbg('min will not fit into control; ignoring', indent=0)
raise
## dbg('accepted min')
self._min = min
else:
## dbg('ignoring min')
pass
if kwargs.has_key('max'):
max = kwargs['max']
if( self._min is None
or max is None
or (self._min is not None and self._min <= max) ):
## dbg('examining max')
if max is not None:
try:
textmax = self._toGUI(max, apply_limits = False)
except ValueError:
## dbg('max will not fit into control; ignoring', indent=0)
raise
## dbg('accepted max')
self._max = max
else:
## dbg('ignoring max')
pass
if kwargs.has_key('allowNegative'):
self._allowNegative = kwargs['allowNegative']
# Ensure current value of control obeys any new restrictions imposed:
text = self._GetValue()
## dbg('text value: "%s"' % text)
if kwargs.has_key('groupChar') and self._groupChar != old_groupchar and text.find(old_groupchar) != -1:
text = old_numvalue
## dbg('old_groupchar: "%s" newgroupchar: "%s"' % (old_groupchar, self._groupChar))
if kwargs.has_key('decimalChar') and self._decimalChar != old_decimalchar and text.find(old_decimalchar) != -1:
text = old_numvalue
if text != self._GetValue():
if self._decimalChar != '.':
# ensure latest decimal char is in "numeric value" so it won't be removed
# when going to the GUI:
text = text.replace('.', self._decimalChar)
newtext = self._toGUI(text)
## dbg('calling wx.TextCtrl.SetValue(self, %s)' % newtext)
wx.TextCtrl.SetValue(self, newtext)
value = self.GetValue()
## dbg('self._allowNegative?', self._allowNegative)
if not self._allowNegative and self._isNeg:
value = abs(value)
## dbg('abs(value):', value)
self._isNeg = False
elif not self._allowNone and BaseMaskedTextCtrl.GetValue(self) == '':
if self._min > 0:
value = self._min
else:
value = 0
sel_start, sel_to = self.GetSelection()
if self.IsLimited() and self._min is not None and value < self._min:
## dbg('Set to min value:', self._min)
self._SetValue(self._toGUI(self._min))
elif self.IsLimited() and self._max is not None and value > self._max:
## dbg('Setting to max value:', self._max)
self._SetValue(self._toGUI(self._max))
else:
# reformat current value as appropriate to possibly new conditions
## dbg('Reformatting value:', value)
sel_start, sel_to = self.GetSelection()
self._SetValue(self._toGUI(value))
self.Refresh() # recolor as appropriate
## dbg('finished NumCtrl::SetParameters', indent=0)
def _GetNumValue(self, value):
"""
This function attempts to "clean up" a text value, providing a regularized
convertable string, via atol() or atof(), for any well-formed numeric text value.
"""
return value.replace(self._groupChar, '').replace(self._decimalChar, '.').replace('(', '-').replace(')','').strip()
def GetFraction(self, candidate=None):
"""
Returns the fractional portion of the value as a float. If there is no
fractional portion, the value returned will be 0.0.
"""
if not self._fractionWidth:
return 0.0
else:
fracstart, fracend = self._fields[1]._extent
if candidate is None:
value = self._toGUI(BaseMaskedTextCtrl.GetValue(self))
else:
value = self._toGUI(candidate)
fracstring = value[fracstart:fracend].strip()
if not value:
return 0.0
else:
return string.atof(fracstring)
def _OnChangeSign(self, event):
## dbg('NumCtrl::_OnChangeSign', indent=1)
self._typedSign = True
MaskedEditMixin._OnChangeSign(self, event)
## dbg(indent=0)
def _disallowValue(self):
## dbg('NumCtrl::_disallowValue')
# limited and -1 is out of bounds
if self._typedSign:
self._isNeg = False
if not wx.Validator_IsSilent():
wx.Bell()
sel_start, sel_to = self._GetSelection()
## dbg('queuing reselection of (%d, %d)' % (sel_start, sel_to))
wx.CallAfter(self.SetInsertionPoint, sel_start) # preserve current selection/position
wx.CallAfter(self.SetSelection, sel_start, sel_to)
def _SetValue(self, value):
"""
This routine supersedes the base masked control _SetValue(). It is
needed to ensure that the value of the control is always representable/convertable
to a numeric return value (via GetValue().) This routine also handles
automatic adjustment and grouping of the value without explicit intervention
by the user.
"""
## dbg('NumCtrl::_SetValue("%s")' % value, indent=1)
if( (self._fractionWidth and value.find(self._decimalChar) == -1) or
(self._fractionWidth == 0 and value.find(self._decimalChar) != -1) ) :
value = self._toGUI(value)
numvalue = self._GetNumValue(value)
## dbg('cleansed value: "%s"' % numvalue)
replacement = None
if numvalue == "":
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -