autocomplete

Discussion in 'Python' started by walterigo@yahoo.com, Jun 10, 2006.

  1. Guest

    hello.
    I have been working all too hard trying to figure out how to get
    TextCtrlAutoComplete.py to start another word after it finishes the
    last word. I want it to start the autocomplete process all over again
    after it finishes the autocomplete process. I have striped down the
    program to a smaller version than the orginal. it now works in a
    multiline wx.textctrl box. belive that the program only needs one or
    two lines to complete the taks and start all over again.

    here is a copy of the code


    '''

    wxPython Custom Widget Collection 20060207
    Written By: Edward Flick ()
    Michele Petrazzo (michele -=dot=- petrazzo -=at=- unipex
    -=dot=- it)
    Will Sadkin (wsadkin-=at=- nameconnector -=dot=- com)
    Copyright 2006 (c) CDF Inc. ( http://www.cdf-imaging.com )
    Contributed to the wxPython project under the wxPython project's
    license.

    '''



    import wx
    import sys

    import wx.lib.mixins.listctrl as listmix


    class myListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    def __init__(self,
    parent,
    ID=-1,
    pos=wx.DefaultPosition,
    size=wx.DefaultSize,
    style=0):
    wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
    listmix.ListCtrlAutoWidthMixin.__init__(self)

    class TextCtrlAutoComplete (wx.TextCtrl, listmix.ColumnSorterMixin ):

    def __init__ ( self, parent, choices = None,
    showHead=False, dropDownClick=True,
    colFetch=-1, colSearch=0, hideOnNoMatch=True,
    selectCallback=None, entryCallback=None,
    matchFunction=None,
    **therest) :
    '''
    Constructor works just like wx.TextCtrl except you can pass in
    a
    list of choices. You can also change the choice list at any
    time
    by calling setChoices.
    '''

    if therest.has_key('style'):
    therest['style']=wx.TE_PROCESS_ENTER | therest['style']
    else:
    therest['style']=wx.TE_PROCESS_ENTER


    wx.TextCtrl.__init__(self,parent,-1,'',size=(500,500),style=wx.TE_MULTILINE)
    #wx.TextCtrl.__init__(self, parent, **therest )
    self._hideOnNoMatch = hideOnNoMatch
    self._selectCallback = selectCallback
    self._matchFunction = matchFunction
    self._screenheight = wx.SystemSettings.GetMetric(
    wx.SYS_SCREEN_Y )

    #sort variable needed by listmix
    self.itemDataMap = dict()

    #widgets
    self.dropdown = wx.PopupWindow( self )

    #Control the style
    flags = wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_SORT_ASCENDING
    if not (showHead) :
    flags = flags | wx.LC_NO_HEADER

    #Create the list and bind the events
    self.dropdownlistbox = myListCtrl( self.dropdown, style=flags,
    pos=wx.Point( 0, 0) )
    gp = self
    while ( gp != None ) :
    gp = gp.GetParent()
    self.Bind( wx.EVT_TEXT , self.onEnteredText, self )
    self.Bind( wx.EVT_KEY_DOWN , self.onKeyDown, self )
    self.dropdownlistbox.Bind(wx.EVT_LEFT_DCLICK,
    self.onListDClick)

    def onListDClick(self, evt):
    self._setValueFromSelected()

    def onEnteredText(self, event):
    text = event.GetString()
    #print('onEnterdText text: ',text)
    if self._entryCallback:
    self._entryCallback()


    if not text:
    # control is empty; hide dropdown if shown:
    if self.dropdown.IsShown():
    self._showDropDown(False)
    event.Skip()
    return
    found = False
    choices = self._choices

    for numCh, choice in enumerate(choices):
    if self._matchFunction and self._matchFunction(text,
    choice):
    found = True
    elif choice.lower().startswith(text.lower()) :
    found = True
    if found:
    self._showDropDown(True)
    item = self.dropdownlistbox.GetItem(numCh)
    toSel = item.GetId()
    self.dropdownlistbox.Select(toSel)
    break

    if not found:

    self.dropdownlistbox.Select(self.dropdownlistbox.GetFirstSelected(),
    False)
    if self._hideOnNoMatch:
    self._showDropDown(False)

    self._listItemVisible()

    event.Skip ()

    def onKeyDown ( self, event ) :
    """ Do some work when the user press on the keys:
    up and down: move the cursor
    left and right: move the search
    """
    skip = True

    sel = self.dropdownlistbox.GetFirstSelected()
    visible = self.dropdown.IsShown()

    KC = event.GetKeyCode()
    if KC == wx.WXK_DOWN :
    if sel < (self.dropdownlistbox.GetItemCount () - 1) :
    self.dropdownlistbox.Select ( sel+1 )
    self._listItemVisible()
    self._showDropDown ()
    skip = False
    elif KC == wx.WXK_UP :
    if sel > 0 :
    self.dropdownlistbox.Select ( sel - 1 )
    self._listItemVisible()
    self._showDropDown ()
    skip = False

    if visible :
    if event.GetKeyCode() == wx.WXK_RETURN :
    self._setValueFromSelected()
    skip = False
    if event.GetKeyCode() == wx.WXK_ESCAPE :
    self._showDropDown( False )
    skip = False
    if skip :
    event.Skip()

    def onListItemSelected (self, event):
    self._setValueFromSelected()
    event.Skip()

    def onClickToggleDown(self, event):
    self._lastinsertionpoint = self.GetInsertionPoint()
    event.Skip ()

    def onClickToggleUp ( self, event ) :
    if ( self.GetInsertionPoint() == self._lastinsertionpoint ) :
    self._showDropDown ( not self.dropdown.IsShown() )
    event.Skip ()


    # -- Interfaces methods



    def SetChoices(self, choices):

    #Sets the choices available in the popup wx.ListBox.
    #The items will be sorted case insensitively.
    self._choices = choices
    flags = wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_SORT_ASCENDING
    | wx.LC_NO_HEADER
    self._updateDataList(self._choices)
    self.dropdownlistbox.InsertColumn(0, "")
    for num, colVal in enumerate(self._choices):
    index =
    self.dropdownlistbox.InsertImageStringItem(sys.maxint, colVal, -1)
    self.dropdownlistbox.SetStringItem(index, 0, colVal)
    self.dropdownlistbox.SetItemData(index, num)

    self._setListSize()

    # there is only one choice for both search and fetch if setting
    a single column:
    self._colSearch = 0
    self._colFetch = -1
    def SetSelectCallback(self, cb=None):
    self._selectCallback = cb

    def SetEntryCallback(self, cb=None):
    self._entryCallback = cb

    #-- Internal methods
    def _setValueFromSelected( self ) :
    '''
    Sets the wx.TextCtrl value from the selected wx.ListCtrl item.
    Will do nothing if no item is selected in the wx.ListCtrl.
    '''
    sel = self.dropdownlistbox.GetFirstSelected()
    if sel > -1:
    if self._colFetch != -1: col = self._colFetch
    else: col = self._colSearch
    itemtext = self.dropdownlistbox.GetItem(sel, col).GetText()

    if self._selectCallback:
    dd = self.dropdownlistbox
    values = [dd.GetItem(sel, x).GetText()
    for x in xrange(dd.GetColumnCount())]
    self._selectCallback( values )


    self.SetValue (itemtext)
    self.SetInsertionPointEnd ()
    self.SetSelection ( -1, -1 )
    self._showDropDown ( False )



    def _showDropDown ( self, show = True ) :
    '''
    Either display the drop down list (show = True) or hide it
    (show = False).
    '''

    if show :
    size = self.dropdown.GetSize()
    width, height = self . GetSizeTuple()
    x, y = self . ClientToScreenXY ( wx.CentreX+6, wx.CentreY+6
    )
    if size.GetWidth() != width :
    size.SetWidth(width)
    self.dropdown.SetSize(size)

    self.dropdownlistbox.SetSize(self.dropdown.GetClientSize())
    if (y + size.GetHeight()) < self._screenheight :
    self.dropdown . SetPosition ( wx.Point(x, y) )
    else:
    self.dropdown . SetPosition ( wx.Point(x, y - height -
    size.GetHeight()) )
    self.dropdown.Show ( show )

    def _listItemVisible( self ) :
    '''
    Moves the selected item to the top of the list ensuring it is
    always visible.
    '''
    toSel = self.dropdownlistbox.GetFirstSelected ()
    if toSel == -1: return
    self.dropdownlistbox.EnsureVisible( toSel )

    def _updateDataList(self, choices):
    #delete, if need, all the previous data
    if self.dropdownlistbox.GetColumnCount() != 0:
    self.dropdownlistbox.DeleteAllColumns()
    self.dropdownlistbox.DeleteAllItems()

    #and update the dict
    if choices:
    for numVal, data in enumerate(choices):
    self.itemDataMap[numVal] = data
    #print("data is %s",data)
    else:
    numVal = 0
    self.SetColumnCount(numVal)

    def _setListSize(self):
    choices = self._choices
    longest = 0
    for choice in choices :
    longest = max(len(choice), longest)

    #longest += 3
    itemcount = min( len( choices ) , 7 ) + .5
    charheight = self.dropdownlistbox.GetCharHeight()
    charwidth = self.dropdownlistbox.GetCharWidth()
    self.popupsize = wx.Size( charwidth*longest,
    charheight*itemcount )
    self.dropdownlistbox.SetSize ( self.popupsize )
    self.dropdown.SetClientSize( self.popupsize )





    class test:
    def __init__(self):
    args = dict()
    args["selectCallback"] = self.selectCallback

    self.dynamic_choices = [
    'hello world', 'abandon', 'acorn', 'acute',
    'adore',
    'aegis', 'ascertain', 'asteroid',
    'beautiful', 'bold', 'classic',
    'daring', 'dazzling', 'debonair', 'definitive',
    'effective', 'elegant',
    'http://python.org', 'http://www.google.com',
    'fabulous', 'fantastic', 'friendly',
    'forgiving', 'feature',
    'sage', 'scarlet', 'scenic', 'seaside',
    'showpiece', 'spiffy',
    'www.wxPython.org', 'www.osafoundation.org'
    ]


    app = wx.PySimpleApp()
    frm = wx.Frame(None,-1,"Test",
    style=wx.CLEAR
    |wx.DEFAULT_FRAME_STYLE
    )
    panel = wx.Panel(frm)
    self._ctrl = TextCtrlAutoComplete(panel, **args)
    self.onBtDynamicChoices(self.onBtDynamicChoices)

    frm.Show()
    app.MainLoop()


    def onBtDynamicChoices(self, event):
    self._ctrl.SetChoices(self.dynamic_choices)
    self._ctrl.SetEntryCallback(self.setDynamicChoices)


    def match(self, text, choice):
    t = text.lower()
    c = choice.lower()
    #print('The Value is %S',choice)
    return c.startswith(t)

    def setDynamicChoices(self):
    if wx.EVT_KEY_DOWN == ' ': print "Space bar pressed"
    text = self._ctrl.GetValue().lower()
    choices = [choice for choice in self.dynamic_choices if
    self.match(text, choice)]
    self._ctrl.SetChoices(choices)
    #print('The Value is %S',text)

    def selectCallback(self, values):
    """ Simply function that receive the row values when the
    user select an item
    """
    print "Select Callback called...:", values
    self.wordCheck(values)

    def wordCheck(self,values):
    pass #print"Word to check:",values


    if __name__ == "__main__":
    test()
     
    , Jun 10, 2006
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike P

    autocomplete

    Mike P, Jun 25, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    950
    Natty Gur
    Jun 25, 2003
  2. Ali

    Set AutoComplete to Off

    Ali, Nov 18, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    436
  3. Lloyd Sheen

    Stopping AutoComplete

    Lloyd Sheen, Nov 21, 2003, in forum: ASP .Net
    Replies:
    2
    Views:
    2,215
    Saravana [MVP]
    Nov 21, 2003
  4. Grey
    Replies:
    5
    Views:
    17,443
    PeterBrunone
    Sep 6, 2006
  5. moondaddy
    Replies:
    7
    Views:
    565
    Jeffrey Tan[MSFT]
    Apr 8, 2004
Loading...

Share This Page