#!/usr/bin/env python
import wx
import wx.combo

class MyChoice(wx.combo.ComboCtrl):
    def __init__(self,parent,choices,selection,size,pos):
        wx.combo.ComboCtrl.__init__(self,parent,size=size,pos=pos)
        MyComboPopup(self,choices,selection)
        self.Bind(wx.EVT_KILL_FOCUS,self.onLostFocus)

    def onLostFocus(self,evt):
        print 'lost focus'
#       self.SetSelection(-1,-1)
        evt.Skip()

class MyComboPopup(wx.ListBox, wx.combo.ComboPopup):
    def __init__(self,comboCtrl,choices,selection):
        self.comboCtrl = comboCtrl
        self.choices = choices
        self.curitem = self.selection = selection
        wx.combo.ComboPopup.__init__(self)
        comboCtrl.SetPopupControl(self)
        comboCtrl.SetValue(choices[selection])

    def Create(self, parent):
        # Create the popup child control.  Return true for success.
        self.listBox = wx.ListBox(parent,choices=self.choices)
        self.listBox.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.listBox.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        return True

    def OnKeyDown(self, evt):
        if evt.KeyCode == wx.WXK_DOWN:
            if self.curitem < len(self.choices)-1:
                self.curitem += 1
                self.listBox.Select(self.curitem)
                return
        if evt.KeyCode == wx.WXK_UP:
            if self.curitem > 0:
                self.curitem -= 1
                self.listBox.Select(self.curitem)
                return
        if evt.KeyCode == wx.WXK_ESCAPE:
            self.Dismiss()
            return
        if evt.KeyCode in (wx.WXK_TAB,wx.WXK_RETURN,wx.WXK_NUMPAD_ENTER):
            self.selection = self.curitem
            self.Dismiss()
            return

    def OnLeftDown(self, evt):
        item = self.listBox.HitTest(evt.GetPosition())
        if item > -1:
            self.selection = item
            self.Dismiss()

    def GetControl(self):
        # Return the widget that is to be used for the popup
        return self.listBox

    def GetStringValue(self):
        # Return a string representation of the current item.
        return self.choices[self.selection]

    def OnPopup(self):
        # Called immediately after the popup is shown
        self.curitem = self.selection
        self.listBox.Select(self.selection)
        wx.combo.ComboPopup.OnPopup(self)

    def OnDismiss(self):
        # Called when popup is dismissed
        wx.combo.ComboPopup.OnDismiss(self)

    def OnComboKeyEvent(self, evt):
        # Receives key events from the parent ComboCtrl.  Events not
        # handled should be skipped, as usual.
        if evt.KeyCode == wx.WXK_SPACE:
            self.comboCtrl.ShowPopup()
        elif evt.KeyCode == wx.WXK_DOWN:
            if self.selection < len(self.choices)-1:
                self.selection += 1
                self.comboCtrl.SetValue(self.choices[self.selection])
        elif evt.KeyCode == wx.WXK_UP:
            if self.selection > 0:
                self.selection -= 1
                self.comboCtrl.SetValue(self.choices[self.selection])

    def GetAdjustedSize(self, minWidth, prefHeight, maxHeight):
        # Return final size of popup. Called on every popup, just prior to OnPopup.
        # minWidth = preferred minimum width for window
        # prefHeight = preferred height. Only applies if > 0,
        # maxHeight = max height for window, as limited by screen size
        #   and should only be rounded down, if necessary.
        prefHeight = 30 * len(self.choices)
        return wx.combo.ComboPopup.GetAdjustedSize(self, minWidth, prefHeight, maxHeight)

class MyPanel(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent,-1)

        choices = ['Category 1','Category 2','Category 3']
        selection = 1

        wx.StaticText(self,-1,'Field1',pos=(50,30))
        wx.TextCtrl(self,-1,'',size=(180,-1),pos=(150,30))

        wx.StaticText(self,-1,'Field2',pos=(50,80))
        MyChoice(self,choices,selection,size=(180,-1),pos=(150,80))

        wx.StaticText(self,-1,'Field3',pos=(50,130))
        wx.TextCtrl(self,-1,'',size=(180,-1),pos=(150,130))

        self.SetFocus()

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,None,-1,"Custom ComboCtrl test",size=(400,200))
        panel = MyPanel(self)
        self.CentreOnScreen()

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame()
        frame.Show(1)
        return 1

app = MyApp(0)
app.MainLoop()
