def on_left_click(self, event, grid, choices):
        """
        creates popup menu when user clicks on the column
        if that column is in the list of choices that get a drop-down menu.
        allows user to edit the column, but only from available values
        """
        color = self.grid.GetCellBackgroundColour(event.GetRow(), event.GetCol())
        # allow user to cherry-pick cells for editing.  gets selection of meta key for mac, ctrl key for pc
        if event.ControlDown() or event.MetaDown():
            row, col = event.GetRow(), event.GetCol()
            if (row, col) not in self.dispersed_selection:
                self.dispersed_selection.append((row, col))
                self.grid.SetCellBackgroundColour(row, col, 'light blue')
            else:
                self.dispersed_selection.remove((row, col))
                self.grid.SetCellBackgroundColour(row, col, color)# 'white'
            self.grid.ForceRefresh()
            return
        if event.ShiftDown(): # allow user to highlight multiple consecutive cells in a column
            previous_col = self.grid.GetGridCursorCol()
            previous_row = self.grid.GetGridCursorRow()
            col = event.GetCol()
            row = event.GetRow()
            if col != previous_col:
                return
            else:
                if row > previous_row:
                    row_range = list(range(previous_row, row+1))
                else:
                    row_range = list(range(row, previous_row+1))
            for r in row_range:
                self.grid.SetCellBackgroundColour(r, col, 'light blue')
                self.selection.append((r, col))
            self.grid.ForceRefresh()
            return

        selection = False

        if self.dispersed_selection:
            is_dispersed = True
            selection = self.dispersed_selection

        if self.selection:
            is_dispersed = False
            selection = self.selection

        try:
            col = event.GetCol()
            row = event.GetRow()
        except AttributeError:
            row, col = selection[0][0], selection[0][1]

        self.grid.SetGridCursor(row, col)

        if col in list(choices.keys()): # column should have a pop-up menu
            menu = wx.Menu()
            two_tiered = choices[col][1]
            choices = choices[col][0]
            if not two_tiered: # menu is one tiered
                if 'CLEAR cell of all values' not in choices:
                    choices.insert(0, 'CLEAR cell of all values')
                for choice in choices:
                    if not choice:
                        choice = " " # prevents error if choice is an empty string
                    menuitem = menu.Append(wx.ID_ANY, str(choice))
                    self.window.Bind(wx.EVT_MENU, lambda event: self.on_select_menuitem(event, grid, row, col, selection), menuitem)
                self.show_menu(event, menu)
            else: # menu is two_tiered
                clear = menu.Append(-1, 'CLEAR cell of all values')
                self.window.Bind(wx.EVT_MENU, lambda event: self.on_select_menuitem(event, grid, row, col, selection), clear)
                for choice in sorted(choices.items()):
                    submenu = wx.Menu()
                    for item in choice[1]:
                        menuitem = submenu.Append(-1, str(item))
                        self.window.Bind(wx.EVT_MENU, lambda event: self.on_select_menuitem(event, grid, row, col, selection), menuitem)
                    menu.Append(-1, choice[0], submenu)
                self.show_menu(event, menu)

        if selection:
            # re-whiten the cells that were previously highlighted
            for row, col in selection:
                self.grid.SetCellBackgroundColour(row, col, self.col_color)
            self.dispersed_selection = []
            self.selection = []
            self.grid.ForceRefresh()
def on_left_click ( self , event , grid , choices ) : color = self . grid . GetCellBackgroundColour ( event . GetRow ( ) , event . GetCol ( ) ) if event . ControlDown ( ) or event . MetaDown ( ) : row , col = event . GetRow ( ) , event . GetCol ( ) if ( row , col ) not in self . dispersed_selection : self . dispersed_selection . append ( ( row , col ) ) self . grid . SetCellBackgroundColour ( row , col , 'light blue' ) else : self . dispersed_selection . remove ( ( row , col ) ) self . grid . SetCellBackgroundColour ( row , col , color ) self . grid . ForceRefresh ( ) return if event . ShiftDown ( ) : previous_col = self . grid . GetGridCursorCol ( ) previous_row = self . grid . GetGridCursorRow ( ) col = event . GetCol ( ) row = event . GetRow ( ) if col != previous_col : return else : if row > previous_row : row_range = list ( range ( previous_row , row + 1 ) ) else : row_range = list ( range ( row , previous_row + 1 ) ) for r in row_range : self . grid . SetCellBackgroundColour ( r , col , 'light blue' ) self . selection . append ( ( r , col ) ) self . grid . ForceRefresh ( ) return selection = False if self . dispersed_selection : is_dispersed = True selection = self . dispersed_selection if self . selection : is_dispersed = False selection = self . selection try : col = event . GetCol ( ) row = event . GetRow ( ) except AttributeError : row , col = selection [ 0 ] [ 0 ] , selection [ 0 ] [ 1 ] self . grid . SetGridCursor ( row , col ) if col in list ( choices . keys ( ) ) : menu = wx . Menu ( ) two_tiered = choices [ col ] [ 1 ] choices = choices [ col ] [ 0 ] if not two_tiered : if 'CLEAR cell of all values' not in choices : choices . insert ( 0 , 'CLEAR cell of all values' ) for choice in choices : if not choice : choice = " " menuitem = menu . Append ( wx . ID_ANY , str ( choice ) ) self . window . Bind ( wx . EVT_MENU , lambda event : self . on_select_menuitem ( event , grid , row , col , selection ) , menuitem ) self . show_menu ( event , menu ) else : clear = menu . Append ( - 1 , 'CLEAR cell of all values' ) self . window . Bind ( wx . EVT_MENU , lambda event : self . on_select_menuitem ( event , grid , row , col , selection ) , clear ) for choice in sorted ( choices . items ( ) ) : submenu = wx . Menu ( ) for item in choice [ 1 ] : menuitem = submenu . Append ( - 1 , str ( item ) ) self . window . Bind ( wx . EVT_MENU , lambda event : self . on_select_menuitem ( event , grid , row , col , selection ) , menuitem ) menu . Append ( - 1 , choice [ 0 ] , submenu ) self . show_menu ( event , menu ) if selection : for row , col in selection : self . grid . SetCellBackgroundColour ( row , col , self . col_color ) self . dispersed_selection = [ ] self . selection = [ ] self . grid . ForceRefresh ( )
creates popup menu when user clicks on the column
        if that column is in the list of choices that get a drop-down menu.
        allows user to edit the column, but only from available values