code: def on_key_down(self, event):
      keycode = event.GetKeyCode()
      cmd_down = event.CmdDown()
      shift_down = event.ShiftDown()
      ################
      #
      # Left Arrow
      #
      ################
      if keycode in (wx.WXK_LEFT, wx.WXK_NUMPAD_LEFT):
          if self.__cursor_pos > 0:
              self.move_cursor_pos(
                  self.__cursor_pos - 1, not shift_down
              )
      ################
      #
      # Right Arrow
      #
      ################
      elif keycode in (wx.WXK_RIGHT, wx.WXK_NUMPAD_RIGHT):
          if self.__cursor_pos < len(self.__tokens):
              self.move_cursor_pos(
                  self.__cursor_pos + 1, not shift_down
              )
      ################
      #
      # Down arrow (next metadata item)
      #
      ################
      elif keycode in (wx.WXK_DOWN, wx.WXK_NUMPAD_DOWN):
          pos = self.__cursor_pos
          if pos < len(self.__tokens) and isinstance(
              self.__tokens[pos], self.MetadataToken
          ):
              token = self.__tokens[pos]
              try:
                  idx = self.__metadata_choices.index(token.value) + 1
                  idx %= len(self.__metadata_choices)
              except ValueError:
                  idx = 0
              if len(self.__metadata_choices):
                  token.value = self.__metadata_choices[idx]
                  self.on_token_change()
      #################
      #
      # Up arrow (prev metadata item)
      #
      #################
      elif keycode in (wx.WXK_UP, wx.WXK_NUMPAD_UP):
          pos = self.__cursor_pos
          if pos < len(self.__tokens) and isinstance(
              self.__tokens[pos], self.MetadataToken
          ):
              token = self.__tokens[pos]
              try:
                  idx = self.__metadata_choices.index(token.value) - 1
                  if idx < 0:
                      idx = len(self.__metadata_choices) - 1
              except ValueError:
                  idx = 0
              if len(self.__metadata_choices):
                  token.value = self.__metadata_choices[idx]
                  self.on_token_change()
      #################
      #
      # Insert (add metadata item)
      #
      #################
      elif keycode in (wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT):
          pos = self.__cursor_pos
          token = self.MetadataToken()
          token.value = self.__metadata_choices[0]
          self.__tokens.insert(pos, token)
          self.on_token_change()
      #################
      #
      # Backspace
      #
      #################
      elif keycode == wx.WXK_BACK:
          pos = self.__cursor_pos
          if pos > 0:
              pos -= 1
              self.move_cursor_pos(pos)
              del self.__tokens[pos]
              self.on_token_change()
      ##################
      #
      # Delete
      #
      ##################
      elif keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE):
          if self.selection[0] == self.selection[1]:
              pos = self.__cursor_pos
              if pos < len(self.__tokens):
                  del self.__tokens[pos]
                  self.on_token_change()
          else:
              self.delete_selection()
      #################
      #
      # Home
      #
      #################
      elif keycode in (wx.WXK_HOME, wx.WXK_NUMPAD_HOME):
          self.move_cursor_pos(0, not shift_down)
      #################
      #
      # End
      #
      #################
      elif keycode in (wx.WXK_END, wx.WXK_NUMPAD_END):
          self.move_cursor_pos(len(self.__tokens), not shift_down)
      #################
      #
      # Context menu
      #
      #################
      elif keycode == wx.WXK_WINDOWS_MENU:
          self.on_context_menu(event)
      #################
      #
      #  Tab
      #
      #################
      elif keycode == wx.WXK_TAB:
          #
          # Code adapted from wx.lib.calendar: author Lorne White
          #
          forward = not event.ShiftDown()
          ne = wx.NavigationKeyEvent()
          ne.SetDirection(forward)
          ne.SetCurrentFocus(self)
          ne.SetEventObject(self)
          self.GetParent().GetEventHandler().ProcessEvent(ne)
          #
          # Seems to be confused about the focus
          #
          if self.FindFocus() != self and self.__caret is not None:
              self.__caret.Hide()
              del self.__caret
              self.__caret = None
      ##################
      #
      # Paste
      #
      ##################
      elif (keycode == ord("V")) and cmd_down:
          # Cribbed from the WX drag and drop demo
          if wx.TheClipboard.Open():
              try:
                  data_object = wx.TextDataObject()
                  success = wx.TheClipboard.GetData(data_object)
              finally:
                  wx.TheClipboard.Close()
              if success:
                  self.delete_selection()
                  self.__tokens = (
                      self.__tokens[0 : self.__cursor_pos]
                      + list(data_object.GetText())
                      + self.__tokens[self.__cursor_pos :]
                  )
                  self.move_cursor_pos(
                      self.__cursor_pos + len(data_object.GetText())
                  )
                  self.on_token_change()
      ################
      #
      # Cut / copy
      #
      ################
      elif (keycode in (ord("C"), ord("X"))) and cmd_down:
          if self.selection[0] == self.selection[1]:
              return
          selection = list(self.selection)
          selection.sort()
          text = self.get_text(selection[0], selection[1])
          if wx.TheClipboard.Open():
              try:
                  self.__clipboard_text = wx.TextDataObject()
                  self.__clipboard_text.SetText(text)
                  wx.TheClipboard.SetData(self.__clipboard_text)
              finally:
                  wx.TheClipboard.Close()
          if keycode == ord("X"):
              self.delete_selection()
      else:
          event.Skip()
  
imports: import wx
  import wx.lib.masked
  from cellprofiler_core.constants.measurement import C_FRAME
  from cellprofiler_core.constants.measurement import C_METADATA
  from cellprofiler_core.constants.measurement import C_SERIES
  from cellprofiler_core.constants.measurement import IMAGE
  from cellprofiler_core.preferences import get_primary_outline_color
label_desc: Use image node_id 8 for calling the MetadataControl obj's underlying member method code with example usage: obj.on_key_down(event) without return types