Rewrite TestCtrlAutoComplete to fix all bugs
authorlbessard
Fri, 16 Jan 2009 08:54:37 +0100
changeset 295 bc6fc07c3153
parent 294 39b3d4a2195b
child 296 37b2b4adbb1d
Rewrite TestCtrlAutoComplete to fix all bugs
TextCtrlAutoComplete.py
--- a/TextCtrlAutoComplete.py	Thu Jan 15 10:05:07 2009 +0100
+++ b/TextCtrlAutoComplete.py	Fri Jan 16 08:54:37 2009 +0100
@@ -1,119 +1,66 @@
-
-'''
-
-wxPython Custom Widget Collection 20060207
-Written By: Edward Flick (eddy -=at=- cdf-imaging -=dot=- com)
-            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 locale, wx, sys, cStringIO
-
-import  wx.lib.mixins.listctrl  as  listmix
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of Beremiz, a Integrated Development Environment for
+#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import wx
 import cPickle
-from wx import ImageFromStream, BitmapFromImage
-#----------------------------------------------------------------------
-def getSmallUpArrowData():
-    return \
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
-\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
-\x00\x00<IDAT8\x8dcddbf\xa0\x040Q\xa4{h\x18\xf0\xff\xdf\xdf\xffd\x1b\x00\xd3\
-\x8c\xcf\x10\x9c\x06\xa0k\xc2e\x08m\xc2\x00\x97m\xd8\xc41\x0c \x14h\xe8\xf2\
-\x8c\xa3)q\x10\x18\x00\x00R\xd8#\xec\xb2\xcd\xc1Y\x00\x00\x00\x00IEND\xaeB`\
-\x82'
-
-def getSmallUpArrowBitmap():
-    return BitmapFromImage(getSmallUpArrowImage())
-
-def getSmallUpArrowImage():
-    stream = cStringIO.StringIO(getSmallUpArrowData())
-    return ImageFromStream(stream)
-
-
-def getSmallDnArrowData():
-    return \
-"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
-\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
-\x00\x00HIDAT8\x8dcddbf\xa0\x040Q\xa4{\xd4\x00\x06\x06\x06\x06\x06\x16t\x81\
-\xff\xff\xfe\xfe'\xa4\x89\x91\x89\x99\x11\xa7\x0b\x90%\ti\xc6j\x00>C\xb0\x89\
-\xd3.\x10\xd1m\xc3\xe5*\xbc.\x80i\xc2\x17.\x8c\xa3y\x81\x01\x00\xa1\x0e\x04e\
-?\x84B\xef\x00\x00\x00\x00IEND\xaeB`\x82"
-
-def getSmallDnArrowBitmap():
-    return BitmapFromImage(getSmallDnArrowImage())
-
-def getSmallDnArrowImage():
-    stream = cStringIO.StringIO(getSmallDnArrowData())
-    return ImageFromStream(stream)
-#----------------------------------------------------------------------
-
-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, colNames=None, choices = None,
-                  multiChoices=None, showHead=True, dropDownClick=True,
-                  colFetch=-1, colSearch=0, hideOnNoMatch=True,
-                  selectCallback=None, entryCallback=None, matchFunction=None,
-                  element_path=None, **therest) :
-        '''
+
+MAX_ITEM_COUNT = 10
+MAX_ITEM_SHOWN = 6
+ITEM_HEIGHT = 25
+
+class TextCtrlAutoComplete(wx.TextCtrl):
+
+    def __init__ (self, parent, choices=None, dropDownClick=True,
+                  element_path=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, **therest )
+        """
+
+        therest['style'] = wx.TE_PROCESS_ENTER | therest.get('style', 0)
+
+        wx.TextCtrl.__init__(self, parent, **therest)
 
         #Some variables
         self._dropDownClick = dropDownClick
-        self._colNames = colNames
-        self._multiChoices = multiChoices
-        self._showHead = showHead
-        self._choices = choices
         self._lastinsertionpoint = 0
-        self._hideOnNoMatch = hideOnNoMatch
-        self._selectCallback = selectCallback
-        self._entryCallback = entryCallback
-        self._matchFunction = matchFunction
-
-        self._screenheight = wx.SystemSettings.GetMetric( wx.SYS_SCREEN_Y )
+        
+        self._screenheight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
         self.element_path = element_path
-        #sort variable needed by listmix
-        self.itemDataMap = dict()
-
+        
         #widgets
-        self.dropdown = wx.PopupWindow( self )
+        self.dropdown = wx.PopupWindow(self)
 
         #Control the style
-        flags = wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_SORT_ASCENDING
-        if not (showHead and multiChoices) :
-            flags = flags | wx.LC_NO_HEADER
-
+        flags = wx.LB_HSCROLL | wx.LB_SINGLE | wx.LB_SORT
+        
         #Create the list and bind the events
-        self.dropdownlistbox = myListCtrl( self.dropdown, style=flags,
-                                 pos=wx.Point( 0, 0) )
-
-        #initialize the parent
-        if multiChoices: ln = len(multiChoices)
-        else: ln = 1
-        #else: ln = len(choices)
-        listmix.ColumnSorterMixin.__init__(self, ln)
-
-        #load the data
-        if multiChoices: self.SetMultipleChoices (multiChoices, colSearch=colSearch, colFetch=colFetch)
-        else: self.SetChoices ( choices )
+        self.dropdownlistbox = wx.ListBox(self.dropdown, style=flags,
+                                 pos=wx.Point(0, 0))
+        
+        self.SetChoices(choices)
 
         #gp = self
         #while ( gp != None ) :
@@ -121,466 +68,139 @@
         #    gp.Bind ( wx.EVT_SIZE , self.onControlChanged, gp )
         #    gp = gp.GetParent()
 
-        self.Bind( wx.EVT_KILL_FOCUS, self.onControlChanged, self )
-        self.Bind( wx.EVT_TEXT , self.onEnteredText, self )
-        self.Bind( wx.EVT_KEY_DOWN , self.onKeyDown, self )
+        self.Bind(wx.EVT_KILL_FOCUS, self.onControlChanged, self)
+        self.Bind(wx.EVT_TEXT_ENTER, self.onControlChanged, self)
+        self.Bind(wx.EVT_TEXT, self.onEnteredText, self)
+        self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown, self)
 
         #If need drop down on left click
         if dropDownClick:
-            self.Bind ( wx.EVT_LEFT_DOWN , self.onClickToggleDown, self )
-            self.Bind ( wx.EVT_LEFT_UP , self.onClickToggleUp, self )
-
-        self.dropdown.Bind( wx.EVT_LISTBOX , self.onListItemSelected, self.dropdownlistbox )
-        self.dropdownlistbox.Bind(wx.EVT_LEFT_DOWN, self.onListClick)
-        self.dropdownlistbox.Bind(wx.EVT_LEFT_DCLICK, self.onListDClick)
-        self.dropdownlistbox.Bind(wx.EVT_LIST_COL_CLICK, self.onListColClick)
-
-        self.il = wx.ImageList(16, 16)
-
-        self.sm_dn = self.il.Add(getSmallDnArrowBitmap())
-        self.sm_up = self.il.Add(getSmallUpArrowBitmap())
-
-        self.dropdownlistbox.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
-        self._ascending = True
-
-
-    #-- methods called from mixin class
-    def GetSortImages(self):
-        return (self.sm_dn, self.sm_up)
-
-    def GetListCtrl(self):
-        return self.dropdownlistbox
-
-    # -- event methods
-    def onListClick(self, evt):
-        toSel, flag = self.dropdownlistbox.HitTest( evt.GetPosition() )
-        #no values on poition, return
-        if toSel == -1: return
-        self.dropdownlistbox.Select(toSel)
-
-    def onListDClick(self, evt):
-        self._setValueFromSelected()
-
-    def onListColClick(self, evt):
-        col = evt.GetColumn()
-
-        #reverse the sort
-        if col == self._colSearch:
-            self._ascending = not self._ascending
-
-        self.SortListItems( evt.GetColumn(), ascending=self._ascending )
-        self._colSearch = evt.GetColumn()
-        evt.Skip()
+            self.Bind(wx.EVT_LEFT_DOWN , self.onClickToggleDown, self)
+            self.Bind(wx.EVT_LEFT_UP , self.onClickToggleUp, self)
+
+        self.dropdownlistbox.Bind(wx.EVT_LISTBOX, self.onListItemSelected)
+        self.dropdownlistbox.Bind(wx.EVT_LISTBOX_DCLICK, self.onListItemSelected)
+
+    def ChangeValue(self, value):
+        wx.TextCtrl.ChangeValue(self, value)
+        self._refreshListBoxChoices()
 
     def onEnteredText(self, event):
-        text = event.GetString()
-
-        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
-        if self._multiChoices:
-            #load the sorted data into the listbox
-            dd = self.dropdownlistbox
-            choices = [dd.GetItem(x, self._colSearch).GetText()
-                for x in xrange(dd.GetItemCount())]
-        else:
-            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 ) :
+        wx.CallAfter(self._refreshListBoxChoices)
+        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
-        elif KC == wx.WXK_LEFT :
-            if not self._multiChoices: return
-            if self._colSearch > 0:
-                self._colSearch -=1
-            self._showDropDown ()
-        elif KC == wx.WXK_RIGHT:
-            if not self._multiChoices: return
-            if self._colSearch < self.dropdownlistbox.GetColumnCount() -1:
-                self._colSearch += 1
-            self._showDropDown()
-
-        if visible :
-            if event.GetKeyCode() == wx.WXK_RETURN :
+        keycode = event.GetKeyCode()
+        if keycode in [wx.WXK_DOWN, wx.WXK_UP]:
+            if not visible:
+                self._showDropDown()
+            elif keycode == wx.WXK_DOWN:
+                self._moveSelection(1)
+            else:
+                self._moveSelection(-1)
+        elif keycode in [wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_RETURN] and visible:
+            if self.dropdownlistbox.GetSelection() != wx.NOT_FOUND:
                 self._setValueFromSelected()
-                skip = False
-            if event.GetKeyCode() == wx.WXK_ESCAPE :
-                self._showDropDown( False )
-                skip = False
-        if skip :
+            else:
+                self._showDropDown(False)
+                event.Skip()
+        elif event.GetKeyCode() == wx.WXK_ESCAPE:
+            self._showDropDown(False)
+        else:
             event.Skip()
 
-    def onListItemSelected (self, event):
+    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 ()
+        event.Skip()
+
+    def onClickToggleUp(self, event):
+        if self.GetInsertionPoint() == self._lastinsertionpoint:
+            self._showDropDown(not self.dropdown.IsShown())
+        event.Skip()
 
     def onControlChanged(self, event):
         res = self.GetValue()
         config = wx.ConfigBase.Get()
         listentries = cPickle.loads(str(config.Read(self.element_path, cPickle.dumps([]))))
-        if len(res) and res not in listentries:
-            config.Write(self.element_path, cPickle.dumps((listentries + [res])[-10:]))
+        if res and res not in listentries:
+            listentries = (listentries + [res])[-MAX_ITEM_COUNT:]
+            config.Write(self.element_path, cPickle.dumps(listentries))
             config.Flush()
-            self.SetChoices((listentries + [res])[-10:])
-        self._showDropDown( False )
-        event.Skip()
-
-
-    # -- Interfaces methods
-    def SetMultipleChoices(self, choices, colSearch=0, colFetch=-1):
-        ''' Set multi-column choice
-        '''
-        self._multiChoices = choices
-        self._choices = None
-        if not isinstance(self._multiChoices, list):
-            self._multiChoices = [ x for x in self._multiChoices]
-
-        flags = wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_SORT_ASCENDING
-        if not self._showHead:
-            flags |= wx.LC_NO_HEADER
-        self.dropdownlistbox.SetWindowStyleFlag(flags)
-
-        #prevent errors on "old" systems
-        if sys.version.startswith("2.3"):
-            self._multiChoices.sort(lambda x, y: cmp(x[0].lower(), y[0].lower()))
+            self.SetChoices(listentries)
+        self._showDropDown(False)
+        event.Skip()
+    
+    def SetChoices(self, choices):
+        self._choices = choices
+        self._refreshListBoxChoices()
+        
+    def GetChoices(self):
+        return self._choices
+    
+#-------------------------------------------------------------------------------
+#                           Internal methods
+#-------------------------------------------------------------------------------
+
+    def _refreshListBoxChoices(self):
+        text = self.GetValue()
+
+        self.dropdownlistbox.Clear()
+        for choice in self._choices:
+            if choice.startswith(text):
+                self.dropdownlistbox.Append(choice)
+        
+        itemcount = min(len(self.dropdownlistbox.GetStrings()), MAX_ITEM_SHOWN)
+        self.popupsize = wx.Size(self.GetSize()[0], ITEM_HEIGHT * itemcount + 4)
+        self.dropdownlistbox.SetSize(self.popupsize)
+        self.dropdown.SetClientSize(self.popupsize)
+    
+    def _moveSelection(self, direction):
+        selected = self.dropdownlistbox.GetSelection()
+        if selected == wx.NOT_FOUND:
+            if direction >= 0:
+                selected = 0
+            else:
+                selected = self.dropdownlistbox.GetCount() - 1
         else:
-            self._multiChoices.sort(key=lambda x: locale.strxfrm(x[0]).lower() )
-
-        self._updateDataList(self._multiChoices)
-
-        lChoices = len(choices)
-        if lChoices < 2:
-            raise ValueError, "You have to pass me a multi-dimension list"
-
-        for numCol, rowValues in enumerate(choices[0]):
-
-            if self._colNames: colName = self._colNames[numCol]
-            else: colName = "Select %i" % numCol
-
-            self.dropdownlistbox.InsertColumn(numCol, colName)
-
-        for numRow, valRow in enumerate(choices):
-
-            for numCol, colVal in enumerate(valRow):
-                if numCol == 0:
-                    index = self.dropdownlistbox.InsertImageStringItem(sys.maxint, colVal, -1)
-                self.dropdownlistbox.SetStringItem(index, numCol, colVal)
-                self.dropdownlistbox.SetItemData(index, numRow)
-
-        self._setListSize()
-        self._colSearch = colSearch
-        self._colFetch = colFetch
-
-    def SetChoices(self, choices):
-        '''
-        Sets the choices available in the popup wx.ListBox.
-        The items will be sorted case insensitively.
-        '''
-        self._choices = choices
-        self._multiChoices = None
-        flags = wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_SORT_ASCENDING | wx.LC_NO_HEADER
-        self.dropdownlistbox.SetWindowStyleFlag(flags)
-                
-        #if not isinstance(choices, list):
-        #    self._choices = [ x for x in choices if len(x)]
-        self._choices = [ x for x in choices if len(x)]
-        #prevent errors on "old" systems
-        if sys.version.startswith("2.3"):
-            self._choices.sort(lambda x, y: cmp(x.lower(), y.lower()))
-        else:
-            self._choices.sort(key=lambda x: locale.strxfrm(x).lower())
-
-        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 GetChoices(self):
-        if self._choices:
-            return self._choices
-        else:
-            return self._multiChoices
-
-    def SetSelectCallback(self, cb=None):
-        self._selectCallback = cb
-
-    def SetEntryCallback(self, cb=None):
-        self._entryCallback = cb
-
-    def SetMatchFunction(self, mf=None):
-        self._matchFunction = mf
-
-
-    #-- Internal methods
-    def _setValueFromSelected( self ) :
-         '''
+            selected = (selected + direction) % (self.dropdownlistbox.GetCount() + 1)
+        if selected == self.dropdownlistbox.GetCount():
+            selected = wx.NOT_FOUND
+        self.dropdownlistbox.SetSelection(selected)
+    
+    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 ) :
-        '''
+         """
+         selected = self.dropdownlistbox.GetStringSelection()
+         if selected:
+            self.SetValue(selected)
+            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 ( 0, height )
+            width, height = self.GetSizeTuple()
+            x, y = self.ClientToScreenXY(0, height)
             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
-        else:
-            numVal = 0
-        self.SetColumnCount(numVal)
-
-    def _setListSize(self):
-        if self._multiChoices:
-            choices = self._multiChoices
-        else:
-            choices = self._choices
-
-        longest = 0
-        for choice in choices :
-            longest = max(len(choice), longest)
-
-        longest += 3
-        itemcount = min( len( choices ) , 7 ) + 2
-        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()
-        if 1:
-            args["colNames"] = ("col1", "col2")
-            args["multiChoices"] = [ ("Zoey","WOW"), ("Alpha", "wxPython"),
-                                    ("Ceda","Is"), ("Beta", "fantastic"),
-                                    ("zoebob", "!!")]
-            args["colFetch"] = 1
-        else:
-            args["choices"] = ["123", "cs", "cds", "Bob","Marley","Alpha"]
-
-        args["selectCallback"] = self.selectCallback
-
-        self.dynamic_choices = [
-                        'aardvark', '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.TAB_TRAVERSAL|wx.DEFAULT_FRAME_STYLE)
-        panel = wx.Panel(frm)
-        sizer = wx.BoxSizer(wx.VERTICAL)
-
-        self._ctrl = TextCtrlAutoComplete(panel, **args)
-        but = wx.Button(panel,label="Set other multi-choice")
-        but.Bind(wx.EVT_BUTTON, self.onBtMultiChoice)
-        but2 = wx.Button(panel,label="Set other one-colum choice")
-        but2.Bind(wx.EVT_BUTTON, self.onBtChangeChoice)
-        but3 = wx.Button(panel,label="Set the starting choices")
-        but3.Bind(wx.EVT_BUTTON, self.onBtStartChoices)
-        but4 = wx.Button(panel,label="Enable dynamic choices")
-        but4.Bind(wx.EVT_BUTTON, self.onBtDynamicChoices)
-
-        sizer.Add(but, 0, wx.ADJUST_MINSIZE, 0)
-        sizer.Add(but2, 0, wx.ADJUST_MINSIZE, 0)
-        sizer.Add(but3, 0, wx.ADJUST_MINSIZE, 0)
-        sizer.Add(but4, 0, wx.ADJUST_MINSIZE, 0)
-        sizer.Add(self._ctrl, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        panel.SetAutoLayout(True)
-        panel.SetSizer(sizer)
-        sizer.Fit(panel)
-        sizer.SetSizeHints(panel)
-        panel.Layout()
-        app.SetTopWindow(frm)
-        frm.Show()
-        but.SetFocus()
-        app.MainLoop()
-
-    def onBtChangeChoice(self, event):
-        #change the choices
-        self._ctrl.SetChoices(["123", "cs", "cds", "Bob","Marley","Alpha"])
-        self._ctrl.SetEntryCallback(None)
-        self._ctrl.SetMatchFunction(None)
-
-    def onBtMultiChoice(self, event):
-        #change the choices
-        self._ctrl.SetMultipleChoices( [ ("Test","Hello"), ("Other word","World"),
-                                        ("Yes!","it work?") ], colFetch = 1 )
-        self._ctrl.SetEntryCallback(None)
-        self._ctrl.SetMatchFunction(None)
-
-    def onBtStartChoices(self, event):
-        #change the choices
-        self._ctrl.SetMultipleChoices( [ ("Zoey","WOW"), ("Alpha", "wxPython"),
-                                    ("Ceda","Is"), ("Beta", "fantastic"),
-                                    ("zoebob", "!!")], colFetch = 1 )
-        self._ctrl.SetEntryCallback(None)
-        self._ctrl.SetMatchFunction(None)
-
-    def onBtDynamicChoices(self, event):
-        '''
-        Demonstrate dynamic adjustment of the auto-complete list, based on what's
-        been typed so far:
-        '''
-        self._ctrl.SetChoices(self.dynamic_choices)
-        self._ctrl.SetEntryCallback(self.setDynamicChoices)
-        self._ctrl.SetMatchFunction(self.match)
-
-
-    def match(self, text, choice):
-        '''
-        Demonstrate "smart" matching feature, by ignoring http:// and www. when doing
-        matches.
-        '''
-        t = text.lower()
-        c = choice.lower()
-        if c.startswith(t): return True
-        if c.startswith(r'http://'): c = c[7:]
-        if c.startswith(t): return True
-        if c.startswith('www.'): c = c[4:]
-        return c.startswith(t)
-
-    def setDynamicChoices(self):
-        ctrl = self._ctrl
-        text = ctrl.GetValue().lower()
-        current_choices = ctrl.GetChoices()
-        choices = [choice for choice in self.dynamic_choices if self.match(text, choice)]
-        if choices != current_choices:
-            ctrl.SetChoices(choices)
-
-    def selectCallback(self, values):
-        """ Simply function that receive the row values when the
-            user select an item
-        """
-        print "Select Callback called...:",  values
-
-
-if __name__ == "__main__":
-    test()
-
+                self.dropdown.SetPosition(wx.Point(x, y))
+            else:
+                self.dropdown.SetPosition(wx.Point(x, y - height - size.GetHeight()))
+        self.dropdown.Show(show) 
+