Show
Ignore:
Timestamp:
07/08/08 17:21:01 (5 months ago)
Author:
rob
Message:

Got popup windows working on the mac!
* added magic chicken waving to the event handling in the FakePopupWindow? and TextCtrlAutoComplete? to get it to work on OS X
* removed extraneous stuff from autocomplete

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/peppy/lib/textctrl_autocomplete.py

    r1473 r1474  
    55            Will Sadkin (wsadkin-=at=- nameconnector -=dot=- com) 
    66Copyright 2006 (c) CDF Inc. ( http://www.cdf-imaging.com ) 
     7 
     8Refactored by Rob McMullen as part of peppy (http://peppy.flipturn.org) 
     9 
    710Contributed to the wxPython project under the wxPython project\'s license. 
    811""" 
     
    1215class FakePopupWindow(wx.MiniFrame): 
    1316    def __init__(self, parent, style=None): 
    14         wx.MiniFrame.__init__(self, parent, style = wx.NO_BORDER 
    15                               | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP) 
    16         self.Panel = wx.Panel(self) 
    17         self.list = None 
    18  
    19     def setList(self, list): 
    20         #self.GetSizer().Add(list, 1, wx.EXPAND) 
    21         #self.SetAutoLayout(True) 
    22         #list.Bind(wx.EVT_SET_FOCUS, self.OnFocus) 
    23         #list.Bind(wx.EVT_KEY_UP, self.OnKeyUp) 
    24         self.list = list 
     17        super(FakePopupWindow, self).__init__(parent, style = wx.NO_BORDER |wx.FRAME_FLOAT_ON_PARENT 
     18                              | wx.FRAME_NO_TASKBAR) 
     19        #self.Bind(wx.EVT_KEY_DOWN , self.OnKeyDown) 
     20        self.Bind(wx.EVT_CHAR, self.OnChar) 
     21        self.Bind(wx.EVT_SET_FOCUS, self.OnFocus) 
     22     
     23    def OnChar(self, evt): 
     24        #print("OnChar: keycode=%s" % evt.GetKeyCode()) 
     25        self.GetParent().GetEventHandler().ProcessEvent(evt) 
    2526 
    2627    def Position(self, position, size): 
     
    3233        self.Move((position[0], position[1])) 
    3334         
    34     def SetBackgroundColour(self, colour): 
    35         self.Panel.SetBackgroundColour(colour) 
    36      
    37     def Window(self): 
    38         return self.Panel 
    39      
    4035    def ActivateParent(self): 
    4136        """Activate the parent window 
     
    5550        print("On Focus: set focus to %s" % str(self.GetParent())) 
    5651        self.ActivateParent() 
    57         self.list.SetFocus() 
    5852        evt.Skip() 
    5953 
    60     Window = property(Window) 
    61      
    62 if wx.Platform == '__WXMAC__': 
    63     wx.PopupWindow = FakePopupWindow 
    64  
    65  
    66 class FakePopup(wx.Frame): 
    67     def __init__(self, parent, pos=wx.DefaultPosition): 
    68         style = wx.FRAME_NO_TASKBAR | wx.FRAME_FLOAT_ON_PARENT 
    69         if wx.Platform == '__WXMAC__': 
    70             style = style | wx.BORDER_NONE | wx.POPUP_WINDOW 
    71         else: 
    72             style = style | wx.SIMPLE_BORDER 
    73         wx.Frame.__init__(self, parent, pos=pos, style=style) 
     54 
     55class HighlightListBox(wx.HtmlListBox): 
     56    """Virtual List Box used to highlight partial matches in the ListCtrl""" 
     57    def __init__(self, *args, **kwargs): 
     58        wx.HtmlListBox.__init__(self, *args, **kwargs) 
    7459        self.Bind(wx.EVT_SET_FOCUS, self.OnFocus) 
    75  
    76         sizer = wx.BoxSizer(wx.HORIZONTAL) 
    77         self.SetSizer(sizer) 
    78          
    79         self.list = None 
    80      
    81     def OnKillFocus(self, evt): 
    82         win = evt.GetEventObject() 
    83         print("list losing focus %s" % win) 
    84         evt.Skip() 
    85  
    86     def setKillFocus(self, callback): 
    87         self.GetParent().Bind(wx.EVT_KILL_FOCUS, callback, self.GetParent()) 
    88         self.list.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) 
    89         pass 
    90      
    91     def setList(self, list): 
    92         self.GetSizer().Add(list, 1, wx.EXPAND) 
    93         self.SetAutoLayout(True) 
    94         list.Bind(wx.EVT_SET_FOCUS, self.OnFocus) 
    95         list.Bind(wx.EVT_KEY_UP, self.OnKeyUp) 
    96         self.list = list 
    97      
    98     def Show(self, state=True): 
    99         print("Showing %s" % state) 
    100         import traceback 
    101         traceback.print_stack() 
    102         if state: 
    103             wx.Frame.Show(self, state) 
    104         else: 
    105             wx.Frame.Show(self, state) 
    106  
    107     def ActivateParent(self): 
    108         """Activate the parent window 
    109         @postcondition: parent window is raised 
    110  
    111         """ 
    112         parent = self.GetParent() 
    113         parent.Raise() 
    114         parent.SetFocus() 
    115  
     60         
    11661    def OnFocus(self, evt): 
    11762        """Raise and reset the focus to the parent window whenever 
     
    12065 
    12166        """ 
    122         print("On Focus: set focus to %s" % str(self.GetParent())) 
    123         self.ActivateParent() 
    124         self.GetParent().SetFocus() 
     67        focus = self.GetParent().GetParent() 
     68        #print("On Focus: set focus to %s" % str(focus)) 
     69        focus.SetFocus() 
    12570        evt.Skip() 
    12671 
    127     def OnKeyUp(self, evt): 
    128         """Process key upevents in the control 
    129         @param evt: event that called this handler 
    130  
    131         """ 
    132         if evt.GetKeyCode() == wx.WXK_RETURN: 
    133             self.__PostEvent() 
    134         else: 
    135             evt.Skip() 
    136  
    137  
    138 class HighlightListBox(wx.HtmlListBox): 
    139     """Virtual List Box used to highlight partial matches in the ListCtrl""" 
    14072    def setChoices(self, choices): 
    14173        self.choices = choices 
     
    257189        """ 
    258190        if therest.has_key('style'): 
    259             therest['style']=wx.TE_PROCESS_ENTER | therest['style'] 
    260         else: 
    261             therest['style']=wx.TE_PROCESS_ENTER 
     191            therest['style']=wx.TE_PROCESS_ENTER | wx.TE_PROCESS_TAB |therest['style'] 
     192        else: 
     193            therest['style']=wx.TE_PROCESS_ENTER | wx.TE_PROCESS_TAB 
    262194        wx.TextCtrl.__init__(self, parent, **therest ) 
    263195        #Some variables 
     
    280212        self.dropdownlistbox = HighlightListBox(self.dropdown) 
    281213        if mac: 
    282             self.dropdown.setList(self.dropdownlistbox) 
    283             #self.dropdown.setKillFocus(self.onControlChanged) 
    284             #self.Bind( wx.EVT_KILL_FOCUS, self.onControlChanged, self ) 
    285         else: 
    286             self.Bind( wx.EVT_KILL_FOCUS, self.onControlChanged, self ) 
     214            self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) 
     215         
     216        self.Bind(wx.EVT_KILL_FOCUS, self.onControlChanged) 
    287217         
    288218        self.SetChoices(choices) 
    289219 
    290         self.Bind( wx.EVT_TEXT , self.onEnteredText, self ) 
    291         self.Bind( wx.EVT_KEY_DOWN , self.onKeyDown, self ) 
     220        self.Bind(wx.EVT_TEXT, self.OnText) 
     221        self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) 
    292222        #If need drop down on left click 
    293223        if dropDownClick: 
     
    307237        self._setValueFromSelected() 
    308238 
    309     def onEnteredText(self, event): 
    310         text = event.GetString() 
     239    def OnText(self, evt): 
     240        text = evt.GetString() 
     241        #print("OnText: %s" % text) 
     242        self.processText(text) 
     243        evt.Skip() 
     244     
     245    def processText(self, text=None): 
     246        if text is None: 
     247            text = self.GetValue() 
    311248        if self._entryCallback: 
    312249            self._entryCallback() 
    313250        self.dropdownlistbox.clearBold() 
     251        #print("processText: %s" % text) 
    314252        if not text: 
    315253            # control is empty; hide dropdown if shown: 
    316254            if self.dropdown.IsShown(): 
    317255                self._showDropDown(False) 
    318             event.Skip() 
    319256            return 
    320257        best = None 
     
    351288                self._showDropDown(False) 
    352289        self._listItemVisible() 
    353         event.Skip () 
    354290 
    355291    def onKeyDown ( self, event ) : 
     
    363299        visible = self.dropdown.IsShown() 
    364300        KC = event.GetKeyCode() 
     301        #print("keycode = %d" % KC) 
    365302        if KC == wx.WXK_DOWN : 
    366303            if sel < (dd.GetItemCount () - 1) : 
     
    393330                dd.ScrollPages(-1) 
    394331                dd.SetSelection(first) 
     332        elif KC == wx.WXK_RIGHT: 
     333            # A right arrow at the end of the string is equivalent to a tab 
     334            if self.GetInsertionPoint() == self.GetLastPosition(): 
     335                KC = wx.WXK_TAB 
    395336        if KC == wx.WXK_TAB: 
    396337            #print self._choices 
     
    441382        wx.CallAfter(self.SetFocus) 
    442383        event.Skip () 
     384     
     385    def OnSetFocus(self, evt): 
     386        #print("OnSetFocus: insertion point = %d" % self.GetLastPosition()) 
     387        wx.CallAfter(self.SetInsertionPointEnd) 
    443388 
    444389    def onControlChanged(self, event): 
    445         #print(event) 
    446390        changed = event.GetEventObject() 
    447391        other = event.GetWindow() 
    448392        #print("changed=%s other=%s" % (changed, other)) 
     393        if self._mac: 
     394            wx.CallAfter(self.SetFocus) 
     395            wx.CallAfter(self.SetInsertionPointEnd) 
     396            event.Skip() 
     397            return 
    449398        if self.dropdown.IsShown(): 
    450399            self._showDropDown( False ) 
     
    521470                self.dropdown . SetPosition ( wx.Point(x, y - height - size.GetHeight()) ) 
    522471        self.dropdown.Show ( show ) 
     472        wx.CallAfter(self.SetFocus) 
    523473 
    524474    def _listItemVisible( self ) : 
     
    543493        self.dropdown.SetClientSize( self.popupsize ) 
    544494 
    545 class test: 
    546     def __init__(self): 
    547         args = dict() 
    548         if 1: 
    549             args["colNames"] = ("col1", "col2") 
    550             args["multiChoices"] = [ ("Zoey","WOW"), ("Alpha", "wxPython"), 
    551                                     ("Ceda","Is"), ("Beta", "fantastic"), 
    552                                     ("zoebob", "!!")] 
    553             args["colFetch"] = 1 
    554         else: 
    555             args["choices"] = ["123", "cs", "cds", "Bob","Marley","Alpha"] 
    556         args["selectCallback"] = self.selectCallback 
    557         self.dynamic_choices = [ 
    558                         'aardvark', 'abandon', 'acorn', 'acute', 'adore', 
    559                         'aegis', 'ascertain', 'asteroid', 
    560                         'beautiful', 'bold', 'classic', 
    561                         'daring', 'dazzling', 'debonair', 'definitive', 
    562                         'effective', 'elegant', 
    563                         'http://python.org', 'http://www.google.com', 
    564                         'fabulous', 'fantastic', 'friendly', 'forgiving', 'feature', 
    565                         'sage', 'scarlet', 'scenic', 'seaside', 'showpiece', 'spiffy', 
    566                         'www.wxPython.org', 'www.osafoundation.org' 
    567                         ] 
    568         app = wx.PySimpleApp() 
    569         frm = wx.Frame(None,-1,"Test",style=wx.TAB_TRAVERSAL|wx.DEFAULT_FRAME_STYLE) 
    570         panel = wx.Panel(frm) 
    571         sizer = wx.BoxSizer(wx.VERTICAL) 
    572         self._ctrl = TextCtrlAutoComplete(panel, **args) 
    573         but = wx.Button(panel,label="Set other multi-choice") 
    574         but.Bind(wx.EVT_BUTTON, self.onBtMultiChoice) 
    575         but2 = wx.Button(panel,label="Set other one-colum choice") 
    576         but2.Bind(wx.EVT_BUTTON, self.onBtChangeChoice) 
    577         but3 = wx.Button(panel,label="Set the starting choices") 
    578         but3.Bind(wx.EVT_BUTTON, self.onBtStartChoices) 
    579         but4 = wx.Button(panel,label="Enable dynamic choices") 
    580         but4.Bind(wx.EVT_BUTTON, self.onBtDynamicChoices) 
    581         sizer.Add(but, 0, wx.ADJUST_MINSIZE, 0) 
    582         sizer.Add(but2, 0, wx.ADJUST_MINSIZE, 0) 
    583         sizer.Add(but3, 0, wx.ADJUST_MINSIZE, 0) 
    584         sizer.Add(but4, 0, wx.ADJUST_MINSIZE, 0) 
    585         sizer.Add(self._ctrl, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
    586         panel.SetAutoLayout(True) 
    587         panel.SetSizer(sizer) 
    588         sizer.Fit(panel) 
    589         sizer.SetSizeHints(panel) 
    590         panel.Layout() 
    591         app.SetTopWindow(frm) 
    592         frm.Show() 
    593         but.SetFocus() 
    594         app.MainLoop() 
    595  
    596     def onBtChangeChoice(self, event): 
    597         #change the choices 
    598         self._ctrl.SetChoices(["123", "cs", "cds", "Bob","Marley","Alpha"]) 
    599         self._ctrl.SetEntryCallback(None) 
    600         self._ctrl.SetMatchFunction(None) 
    601  
    602     def onBtMultiChoice(self, event): 
    603         #change the choices 
    604         self._ctrl.SetMultipleChoices( [ ("Test","Hello"), ("Other word","World"), 
    605                                         ("Yes!","it work?") ], colFetch = 1 ) 
    606         self._ctrl.SetEntryCallback(None) 
    607         self._ctrl.SetMatchFunction(None) 
    608  
    609     def onBtStartChoices(self, event): 
    610         #change the choices 
    611         self._ctrl.SetMultipleChoices( [ ("Zoey","WOW"), ("Alpha", "wxPython"), 
    612                                     ("Ceda","Is"), ("Beta", "fantastic"), 
    613                                     ("zoebob", "!!")], colFetch = 1 ) 
    614         self._ctrl.SetEntryCallback(None) 
    615         self._ctrl.SetMatchFunction(None) 
    616  
    617     def onBtDynamicChoices(self, event): 
    618         """ 
    619         Demonstrate dynamic adjustment of the auto-complete list, based on what's 
    620         been typed so far: 
    621         """ 
    622         self._ctrl.SetChoices(self.dynamic_choices) 
    623         self._ctrl.SetEntryCallback(self.setDynamicChoices) 
    624         self._ctrl.SetMatchFunction(self.match) 
    625  
    626     def match(self, text, choice): 
    627         """ 
    628         Demonstrate "smart" matching feature, by ignoring http:// and www. when doing 
    629         matches. 
    630         """ 
    631         t = text.lower() 
    632         c = choice.lower() 
    633         if c.startswith(t): return True 
    634         if c.startswith(r'http://'): c = c[7:] 
    635         if c.startswith(t): return True 
    636         if c.startswith('www.'): c = c[4:] 
    637         if c.startswith(t): 
    638             return 0, len(t) 
    639         return -1, 0 
    640  
    641     def setDynamicChoices(self): 
    642         ctrl = self._ctrl 
    643         text = ctrl.GetValue().lower() 
    644         current_choices = ctrl.GetChoices() 
    645         choices = [choice for choice in self.dynamic_choices if self.match(text, choice)] 
    646         if choices != current_choices: 
    647             ctrl.SetChoices(choices) 
    648  
    649     def selectCallback(self, values): 
    650         """ Simply function that receive the row values when the 
    651             user select an item 
    652         """ 
    653         print "Select Callback called...:",  values 
    654495 
    655496if __name__ == "__main__":