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.
class_docstr_tok: ["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 populate_subpanel(self, structure, address):
      parent_sizer = self.panel.Sizer
      any_all_name = self.anyall_choice_name(address)
      anyall = self.find_and_mark(any_all_name)
      self.hide_show_dict[self.static_text_name(0, address)] = True
      if len(address) == 0:
          self.hide_show_dict[self.static_text_name(1, address)] = True
      if anyall is None:
          anyall = self.make_anyall_ctrl(address)
          sizer = self.get_sizer(address)
          idx = self.get_sizer_index(
              sizer, self.stretch_spacer_dict[tuple(address)]
          )
          if len(address) == 0:
              text = wx.StaticText(
                  self.panel,
                  -1,
                  "Match",
                  name=self.static_text_name(0, address),
              )
              sizer.Insert(
                  idx, text, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL
              )
              sizer.Insert(idx + 1, 3, 0)
              sizer.Insert(
                  idx + 2,
                  anyall,
                  0,
                  wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
              )
              sizer.Insert(idx + 3, 3, 0)
              text = wx.StaticText(
                  self.panel,
                  -1,
                  "of the following rules",
                  name=self.static_text_name(1, address),
              )
              sizer.Insert(
                  idx + 4,
                  text,
                  0,
                  wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
              )
          else:
              sizer.Insert(
                  idx,
                  anyall,
                  0,
                  wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
              )
              sizer.Insert(idx + 1, 3, 0)
              text = wx.StaticText(
                  self.panel,
                  -1,
                  "of the following are true",
                  name=self.static_text_name(0, address),
              )
              sizer.Insert(
                  idx + 2,
                  text,
                  0,
                  wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
              )
      else:
          self.hide_show_dict[self.line_name(address)] = True
          if len(address) > 0:
              #
              # Show the buttons for the anyall if not top level
              #
              self.hide_show_dict[
                  self.remove_button_name(address)
              ] = True
              self.hide_show_dict[self.add_button_name(address)] = True
              self.hide_show_dict[
                  self.add_group_button_name(address)
              ] = True
  
      if anyall.GetStringSelection() != structure[0].display_name:
          anyall.SetStringSelection(structure[0].display_name)
          anyall.SetToolTip(structure[0].doc)
      #
      # Now each subelement should be a list.
      #
      for subindex, substructure in enumerate(structure[1:]):
          subaddress = address + [subindex]
          if substructure[0].subpredicates is list:
              # A sublist
              self.populate_subpanel(substructure, subaddress)
          else:
              # A list of predicates
              sizer = self.get_sizer(subaddress)
              predicates = self.v.predicates
              for i, token in enumerate(substructure):
                  if isinstance(token, str):
                      literal_ctrl = self.make_literal(
                          token, i, subaddress, sizer
                      )
                      predicates = []
                  else:
                      choice_ctrl = self.make_predicate_choice(
                          predicates, i, subaddress, sizer
                      )
                      if (
                          choice_ctrl.GetStringSelection()
                          != token.display_name
                      ):
                          choice_ctrl.SetStringSelection(
                              token.display_name
                          )
                      if token.doc is not None:
                          choice_ctrl.SetToolTip(token.doc)
                      predicates = token.subpredicates
              i = len(substructure)
              while len(predicates) > 0:
                  #
                  # We can get here if there's a badly constructed token
                  # list - for instance if an invalid subpredicate was
                  # chosen or none existed because of some error, but now
                  # they do.
                  #
                  if (
                      len(predicates) == 1
                      and predicates[0] is LITERAL_PREDICATE
                  ):
                      self.make_literal("", i, subaddress, sizer)
                  else:
                      self.make_predicate_choice(
                          predicates, i, subaddress, sizer
                      )
                  i += 1
                  predicates = predicates[0].subpredicates
      #
      # Don't allow delete of only rule
      #
      name = self.remove_button_name(address + [0])
      delete_button = self.panel.FindWindowByName(name)
      delete_button.Enable(len(structure) > 2)
  
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 24 for calling the FilterPanelController obj's underlying member method code with example usage: obj.populate_subpanel(structure, address) without return types