from wx.tools.dbg import Logger
dbg = Logger()
-##dbg(enable=0)
+##dbg(enable=1)
## ---------- ---------- ---------- ---------- ---------- ---------- ----------
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.SetBestFittingSize((width, height))
# Set value/type-specific formatting
self._applyFormatting()
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 SetBestFittingSize. 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.SetBestFittingSize((width, height))
+
# Set value/type-specific formatting
self._applyFormatting()
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
## 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')
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:
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):
"""
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:
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
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)
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)
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
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
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)
pos = pos+2
if newvalue != value:
+## dbg('old value: "%s"\nnew value: "%s"' % (value, newvalue))
self._SetValue(newvalue)
self._SetInsertionPoint(pos)
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
matched_str = newtext
newtext = self._ctrl_constraints._choices[match_index]
edit_end = self._ctrl_constraints._extent[1]
- new_select_to = min(edit_end, len(newvalue.rstrip()))
+ new_select_to = min(edit_end, len(newtext.rstrip()))
match_field = self._ctrl_constraints
if self._ctrl_constraints._insertRight:
# adjust position to just after partial match in control:
we need to pull the following trick:
"""
## dbg('MaskedEditMixin::_OnFocus')
+ if self.IsBeingDeleted() or self.GetParent().IsBeingDeleted():
+ return
wx.CallAfter(self._fixSelection)
event.Skip()
self.Refresh()
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
## 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