combobox.py

来自「Wxpython Implemented on Windows CE, Sou」· Python 代码 · 共 672 行 · 第 1/2 页

PY
672
字号
        """
        return not self.__readonly


    def Cut(self):
        """
        This function redefines the externally accessible .Cut to be
        a smart "erase" of the text in question, so as not to corrupt the
        masked control.  NOTE: this must be done in the class derived
        from the base wx control.
        """
        if self._mask:
            self._Cut()             # call the mixin's Cut method
        else:
            wx.ComboBox.Cut(self)    # else revert to base control behavior


    def Paste(self):
        """
        This function redefines the externally accessible .Paste to be
        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
        from the base wx control.
        """
        if self._mask:
            self._Paste()           # call the mixin's Paste method
        else:
            wx.ComboBox.Paste(self)  # else revert to base control behavior


    def Undo(self):
        """
        This function defines the undo operation for the control. (The default
        undo is 1-deep.)
        """
        if self._mask:
            self._Undo()
        else:
            wx.ComboBox.Undo()       # else revert to base control behavior

    def Append( self, choice, clientData=None ):
        """
        This base control function override is necessary so the control can keep track
        of any additions to the list of choices, because wx.ComboBox doesn't have an
        accessor for the choice list.  The code here is the same as in the
        SetParameters() mixin function, but is done for the individual value
        as appended, so the list can be built incrementally without speed penalty.
        """
        if self._mask:
            if type(choice) not in (types.StringType, types.UnicodeType):
                raise TypeError('%s: choices must be a sequence of strings' % str(self._index))
            elif not self.IsValid(choice):
                raise ValueError('%s: "%s" is not a valid value for the control as specified.' % (str(self._index), choice))

            if not self._ctrl_constraints._choices:
                self._ctrl_constraints._compareChoices = []
                self._ctrl_constraints._choices = []
                self._hasList = True

            compareChoice = choice.strip()

            if self._ctrl_constraints._compareNoCase:
                compareChoice = compareChoice.lower()

            if self._ctrl_constraints._alignRight:
                choice = choice.rjust(self._masklength)
            else:
                choice = choice.ljust(self._masklength)
            if self._ctrl_constraints._fillChar != ' ':
                choice = choice.replace(' ', self._fillChar)
##            dbg('updated choice:', choice)


            self._ctrl_constraints._compareChoices.append(compareChoice)
            self._ctrl_constraints._choices.append(choice)
            self._choices = self._ctrl_constraints._choices     # (for shorthand)

            if( not self.IsValid(choice) and
               (not self._ctrl_constraints.IsEmpty(choice) or
                (self._ctrl_constraints.IsEmpty(choice) and self._ctrl_constraints._validRequired) ) ):
                raise ValueError('"%s" is not a valid value for the control "%s" as specified.' % (choice, self.name))

        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 ):
        """
        This base control function override is necessary so the derived control can
        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:
            self._choices = []
            self._ctrl_constraints._autoCompleteIndex = -1
            if self._ctrl_constraints._choices:
                self.SetCtrlParameters(choices=[])
        wx.ComboBox.Clear(self)


    def _OnCtrlParametersChanged(self):
        """
        This overrides the mixin's default OnCtrlParametersChanged to detect
        changes in choice list, so masked.Combobox can update the base control:
        """
        if self.controlInitialized and self._choices != self._ctrl_constraints._choices:
            wx.ComboBox.Clear(self)
            self._choices = self._ctrl_constraints._choices
            for choice in self._choices:
                wx.ComboBox.Append( self, choice )


    # Not all wx platform implementations have .GetMark, so we make the following test,
    # and fall back to our old hack if they don't...
    #
    if not hasattr(wx.ComboBox, 'GetMark'):
        def GetMark(self):
            """
            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
            works, but has the nasty side effect of generating lots of intermediate
            events.
            """
##            dbg(suspend=1)  # turn off debugging around this function
##            dbg('MaskedComboBox::GetMark', indent=1)
            if self.__readonly:
##                dbg(indent=0)
                return 0, 0 # no selection possible for editing
##            sel_start, sel_to = wxComboBox.GetMark(self)        # what I'd *like* to have!
            sel_start = sel_to = self.GetInsertionPoint()
##            dbg("current sel_start:", sel_start)
            value = self.GetValue()
##            dbg('value: "%s"' % value)

            self._ignoreChange = True               # tell _OnTextChange() to ignore next event (if any)

            wx.ComboBox.Cut(self)
            newvalue = self.GetValue()
##            dbg("value after Cut operation:", newvalue)

            if newvalue != value:                   # something was selected; calculate extent
##                dbg("something selected")
                sel_to = sel_start + len(value) - len(newvalue)
                wx.ComboBox.SetValue(self, value)    # restore original value and selection (still ignoring change)
                wx.ComboBox.SetInsertionPoint(self, sel_start)
                wx.ComboBox.SetMark(self, sel_start, sel_to)

            self._ignoreChange = False              # tell _OnTextChange() to pay attn again

##            dbg('computed selection:', sel_start, sel_to, indent=0, suspend=0)
            return sel_start, sel_to
    else:
        def GetMark(self):
##            dbg('MaskedComboBox::GetMark()', indent = 1)
            ret = wx.ComboBox.GetMark(self)
##            dbg('returned', ret, indent=0)
            return ret


    def SetSelection(self, index):
        """
        Necessary override for bookkeeping on choice selection, to keep current value
        current.
        """
##        dbg('MaskedComboBox::SetSelection(%d)' % index)
        if self._mask:
            self._prevValue = self._curValue
            self._curValue = self._choices[index]
            self._ctrl_constraints._autoCompleteIndex = index
        wx.ComboBox.SetSelection(self, index)


    def _OnKeyDownInComboBox(self, event):
        """
        This function is necessary because navigation and control key
        events do not seem to normally be seen by the wxComboBox's
        EVT_CHAR routine.  (Tabs don't seem to be visible no matter
        what... {:-( )
        """
        if event.GetKeyCode() in self._nav + self._control:
            self._OnChar(event)
            return
        else:
            event.Skip()    # let mixin default KeyDown behavior occur


    def _OnSelectChoice(self, event):
        """
        This function appears to be necessary, because the processing done
        on the text of the control somehow interferes with the combobox's
        selection mechanism for the arrow keys.
        """
##        dbg('MaskedComboBox::OnSelectChoice', indent=1)

        if not self._mask:
            event.Skip()
            return

        value = self.GetValue().strip()

        if self._ctrl_constraints._compareNoCase:
            value = value.lower()

        if event.GetKeyCode() == wx.WXK_UP:
            direction = -1
        else:
            direction = 1
        match_index, partial_match = self._autoComplete(
                                                direction,
                                                self._ctrl_constraints._compareChoices,
                                                value,
                                                self._ctrl_constraints._compareNoCase,
                                                current_index = self._ctrl_constraints._autoCompleteIndex)
        if match_index is not None:
##            dbg('setting selection to', match_index)
            # issue appropriate event to outside:
            self._OnAutoSelect(self._ctrl_constraints, match_index=match_index)
            self._CheckValid()
            keep_processing = False
        else:
            pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
            field = self._FindField(pos)
            if self.IsEmpty() or not field._hasList:
##                dbg('selecting 1st value in list')
                self._OnAutoSelect(self._ctrl_constraints, match_index=0)
                self._CheckValid()
                keep_processing = False
            else:
                # attempt field-level auto-complete
##                dbg(indent=0)
                keep_processing = self._OnAutoCompleteField(event)
##        dbg('keep processing?', keep_processing, indent=0)
        return keep_processing


    def _OnAutoSelect(self, field, match_index):
        """
        Override mixin (empty) autocomplete handler, so that autocompletion causes
        combobox to update appropriately.
        """
##        dbg('MaskedComboBox::OnAutoSelect', field._index, indent=1)
##        field._autoCompleteIndex = match_index
        if field == self._ctrl_constraints:
            self.SetSelection(match_index)
##            dbg('issuing combo selection event')
            self.GetEventHandler().ProcessEvent(
                MaskedComboBoxSelectEvent( self.GetId(), match_index, self ) )
        self._CheckValid()
##        dbg('field._autoCompleteIndex:', match_index)
##        dbg('self.GetSelection():', self.GetSelection())
        end = self._goEnd(getPosOnly=True)
##        dbg('scheduling set of end position to:', end)
        # work around bug in wx 2.5
        wx.CallAfter(self.SetInsertionPoint, 0)
        wx.CallAfter(self.SetInsertionPoint, end)
##        dbg(indent=0)


    def _OnReturn(self, event):
        """
        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
        control, because of the implementation of wxComboBox.  So this function
        examines the selection and if it is -1, and the value according to
        (the base control!) is a value in the list, then it schedules a
        programmatic wxComboBox.SetSelection() call to pick the appropriate
        item in the list. (and then does the usual OnReturn bit.)
        """
##        dbg('MaskedComboBox::OnReturn', indent=1)
##        dbg('current value: "%s"' % self.GetValue(), 'current index:', self.GetSelection())
        if self.GetSelection() == -1 and self.GetValue().lower().strip() in self._ctrl_constraints._compareChoices:
            wx.CallAfter(self.SetSelection, self._ctrl_constraints._autoCompleteIndex)

        event.m_keyCode = wx.WXK_TAB
        event.Skip()
##        dbg(indent=0)


class ComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
    """
    The "user-visible" masked combobox control, this class is
    identical to the BaseMaskedComboBox class it's derived from.
    (This extra level of inheritance allows us to add the generic
    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


class PreMaskedComboBox( BaseMaskedComboBox, MaskedEditAccessorsMixin ):
    """
    This class exists to support the use of 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.3
##  1. Made definition of "hack" GetMark conditional on base class not
##     implementing it properly, to allow for migration in wx code base
##     while taking advantage of improvements therein for some platforms.
##
##  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
##  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.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?