class_docstr: Handle representation of the filter panel
  
  The code for handling the filter UI is moderately massive, so it gets
  its own class, if for no other reason than to organize the code.
code: def on_predicate_changed(self, event, index, address):
      LOGGER.debug(
          "Predicate choice at %d / %s changed"
          % (index, self.saddress(address))
      )
      structure = self.v.parse()
      sequence = self.find_address(structure, address)
  
      while len(sequence) <= index:
          # The sequence is bad (e.g., bad pipeline or metadata collection)
          # Fill in enough to deal
          #
          sequence.append(
              self.v.predicates[0]
              if len(sequence) == 0
              else sequence[-1].subpredicates[0]
          )
      if index == 0:
          predicates = self.v.predicates
      else:
          predicates = sequence[index - 1].subpredicates
      new_predicate = predicates[event.GetSelection()]
  
      sequence[index] = new_predicate
      predicates = new_predicate.subpredicates
      #
      # Make sure following predicates are legal
      #
      for index in range(index + 1, len(sequence)):
          if isinstance(sequence[index], str):
              is_good = LITERAL_PREDICATE in predicates
          else:
              matches = [
                  p
                  for p in predicates
                  if sequence[index].symbol == p.symbol
              ]
              is_good = len(matches) == 1
              if is_good:
                  sequence[index] = matches[0]
          if not is_good:
              del sequence[index:]
              sequence += self.v.default(predicates)
              break
          if not isinstance(sequence[index], FilterPredicate):
              break
          predicates = sequence[index].subpredicates
      new_text = self.v.build_string(structure)
      self.on_value_change(event, new_text)
  
imports: import logging
  import wx
  from cellprofiler_core.setting.filter import Filter, FilterPredicate
  from cellprofiler_core.setting.filter._filter import AND_PREDICATE, OR_PREDICATE, LITERAL_PREDICATE
  from ._module_view import ModuleView
  from ..utilities.module_view import edit_control_name
label_desc: Use image node_id 17 for calling the FilterPanelController obj's underlying member method code with example usage: obj.on_predicate_changed(event, index, address) without return types