class_docstr: Define an application like layout of widgets.
  
  Parameters
  ----------
  
  header: instance of Widget
  left_sidebar: instance of Widget
  center: instance of Widget
  right_sidebar: instance of Widget
  footer: instance of Widget
      widgets to fill the positions in the layout
  
  merge: bool
      flag to say whether the empty positions should be automatically merged
  
  pane_widths: list of numbers/strings
      the fraction of the total layout width each of the central panes should occupy
      (left_sidebar,
      center, right_sidebar)
  
  pane_heights: list of numbers/strings
      the fraction of the width the vertical space that the panes should occupy
       (left_sidebar, center, right_sidebar)
  
  {style_params}
  
  Examples
  --------
code: def _update_layout(self):
      grid_template_areas = [
          ["header", "header", "header"],
          ["left-sidebar", "center", "right-sidebar"],
          ["footer", "footer", "footer"],
      ]
  
      grid_template_columns = self._convert_sizes(self.pane_widths)
      grid_template_rows = self._convert_sizes(self.pane_heights)
  
      all_children = {
          "header": self.header,
          "footer": self.footer,
          "left-sidebar": self.left_sidebar,
          "right-sidebar": self.right_sidebar,
          "center": self.center,
      }
  
      children = {
          position: child
          for position, child in all_children.items()
          if child is not None
      }
  
      if not children:
          return
  
      for position, child in children.items():
          child.layout.grid_area = position
  
      if self.merge:
          if len(children) == 1:
              position = list(children.keys())[0]
              grid_template_areas = [
                  [position, position, position],
                  [position, position, position],
                  [position, position, position],
              ]
  
          else:
              if self.center is None:
                  for row in grid_template_areas:
                      del row[1]
                  del grid_template_columns[1]
  
              if self.left_sidebar is None:
                  grid_template_areas[1][0] = grid_template_areas[1][1]
  
              if self.right_sidebar is None:
                  grid_template_areas[1][-1] = grid_template_areas[1][
                      -2
                  ]
  
              if (
                  self.left_sidebar is None
                  and self.right_sidebar is None
                  and self.center is None
              ):
                  grid_template_areas = [["header"], ["footer"]]
                  grid_template_columns = ["1fr"]
                  grid_template_rows = ["1fr", "1fr"]
  
              if self.header is None:
                  del grid_template_areas[0]
                  del grid_template_rows[0]
  
              if self.footer is None:
                  del grid_template_areas[-1]
                  del grid_template_rows[-1]
  
      grid_template_areas_css = "\n".join(
          '"{}"'.format(" ".join(line)) for line in grid_template_areas
      )
  
      self.layout.grid_template_columns = " ".join(
          grid_template_columns
      )
      self.layout.grid_template_rows = " ".join(grid_template_rows)
      self.layout.grid_template_areas = grid_template_areas_css
  
      self.children = tuple(children.values())
  
imports: import re
  from collections import defaultdict
  from traitlets import Instance, Bool, Unicode, CUnicode, CaselessStrEnum, Tuple
  from traitlets import Integer
  from traitlets import HasTraits, TraitError
  from traitlets import observe, validate
  from .widget import Widget
  from .widget_box import GridBox
  from .docutils import doc_subst
label_desc: Use image node_id 4 for calling the AppLayout obj's underlying member method code with example usage: obj._update_layout() without return types