docs: def InitUI(self):
          """
          initialize window
          """
          self.main_sizer = wx.BoxSizer(wx.VERTICAL)
  
          if self.grid_type in self.contribution.tables:
              dataframe = self.contribution.tables[self.grid_type]
          else:
              dataframe = None
          self.grid_builder = GridBuilder(self.contribution, self.grid_type,
                                          self.panel, parent_type=self.parent_type,
                                          reqd_headers=self.reqd_headers,
                                          exclude_cols=self.exclude_cols,
                                          huge=self.huge)
  
          self.grid = self.grid_builder.make_grid()
          self.grid.InitUI()
  
  
          ## Column management buttons
          self.add_cols_button = wx.Button(self.panel, label="Add additional columns",
                                           name='add_cols_btn',
                                           size=(170, 20))
          self.Bind(wx.EVT_BUTTON, self.on_add_cols, self.add_cols_button)
          self.remove_cols_button = wx.Button(self.panel, label="Remove columns",
                                              name='remove_cols_btn',
                                              size=(170, 20))
  
          self.Bind(wx.EVT_BUTTON, self.on_remove_cols, self.remove_cols_button)
  
          ## Row management buttons
          self.remove_row_button = wx.Button(self.panel, label="Remove last row",
                                             name='remove_last_row_btn')
          self.Bind(wx.EVT_BUTTON, self.on_remove_row, self.remove_row_button)
          many_rows_box = wx.BoxSizer(wx.HORIZONTAL)
          self.add_many_rows_button = wx.Button(self.panel, label="Add row(s)",
                                                name='add_many_rows_btn')
          self.rows_spin_ctrl = wx.SpinCtrl(self.panel, value='1', initial=1,
                                            name='rows_spin_ctrl')
          many_rows_box.Add(self.add_many_rows_button, flag=wx.ALIGN_CENTRE)
          many_rows_box.Add(self.rows_spin_ctrl)
          self.Bind(wx.EVT_BUTTON, self.on_add_rows, self.add_many_rows_button)
  
          self.deleteRowButton = wx.Button(self.panel, id=-1,
                                           label='Delete selected row(s)',
                                           name='delete_row_btn')
          self.Bind(wx.EVT_BUTTON, lambda event: self.on_remove_row(event, False), self.deleteRowButton)
          self.deleteRowButton.Disable()
  
          # measurements table should not be able to add new rows
          # that should be done elsewhere
          if self.huge:
              self.add_many_rows_button.Disable()
              self.rows_spin_ctrl.Disable()
              self.remove_row_button.Disable()
              # can't remove cols (seg fault), but can add them
              #self.add_cols_button.Disable()
              self.remove_cols_button.Disable()
  
  
          ## Data management buttons
          self.importButton = wx.Button(self.panel, id=-1,
                                        label='Import MagIC-format file',
                                        name='import_btn')
          self.Bind(wx.EVT_BUTTON, self.onImport, self.importButton)
          self.exitButton = wx.Button(self.panel, id=-1,
                                      label='Save and close grid',
                                      name='save_and_quit_btn')
          self.Bind(wx.EVT_BUTTON, self.onSave, self.exitButton)
          self.cancelButton = wx.Button(self.panel, id=-1, label='Cancel',
                                        name='cancel_btn')
          self.Bind(wx.EVT_BUTTON, self.onCancelButton, self.cancelButton)
          self.Bind(wx.EVT_CLOSE, self.onCancelButton)
  
          ## Input/output buttons
          self.copyButton = wx.Button(self.panel, id=-1,
                                       label="Start copy mode",
                                       name="copy_mode_btn")
          self.Bind(wx.EVT_BUTTON, self.onCopyMode, self.copyButton)
          self.selectAllButton = wx.Button(self.panel, id=-1,
                                           label="Copy all cells",
                                           name="select_all_btn")
          self.Bind(wx.EVT_BUTTON, self.onSelectAll, self.selectAllButton)
          self.copySelectionButton = wx.Button(self.panel, id=-1,
                                           label="Copy selected cells",
                                           name="copy_selection_btn")
          self.Bind(wx.EVT_BUTTON, self.onCopySelection, self.copySelectionButton)
          self.copySelectionButton.Disable()
  
          ## Help message and button
          # button
          self.toggle_help_btn = wx.Button(self.panel, id=-1, label="Show help",
                                           name='toggle_help_btn')
          self.Bind(wx.EVT_BUTTON, self.toggle_help, self.toggle_help_btn)
          # message
          self.help_msg_boxsizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, name='help_msg_boxsizer'), wx.VERTICAL)
  
          if self.grid_type == 'measurements':
              self.default_msg_text = "Edit measurements here.\nIn general, measurements should be imported directly into Pmag GUI,\nwhich has protocols for converting many lab formats into the MagIC format.\nIf we are missing your particular lab format, please let us know: https://github.com/PmagPy/PmagPy/issues.\nThis grid is just meant for looking at your measurements and doing small edits.\nCurrently, you can't add/remove rows here.  You can add columns and edit cell values."
          else:
              self.default_msg_text = 'Edit {} here.\nYou can add or remove both rows and columns, however required columns may not be deleted.\nControlled vocabularies are indicated by **, and will have drop-down-menus.\nSuggested vocabularies are indicated by ^^, and also have drop-down-menus.\nTo edit all values in a column, click the column header.\nYou can cut and paste a block of cells from an Excel-like file.\nJust click the top left cell and use command "v".'.format(self.grid_type)
          txt = ''
          if self.grid_type == 'locations':
              txt = '\n\nNote: you can fill in location start/end latitude/longitude here.\nHowever, if you add sites in step 2, the program will calculate those values automatically,\nbased on site latitudes/logitudes.\nThese values will be written to your upload file.'
          if self.grid_type == 'samples':
              txt = "\n\nNote: you can fill in lithology, class, and type for each sample here.\nHowever, if the sample's class, lithology, and type are the same as its parent site,\nthose values will propagate down, and will be written to your sample file automatically."
          if self.grid_type == 'specimens':
              txt = "\n\nNote: you can fill in lithology, class, and type for each specimen here.\nHowever, if the specimen's class, lithology, and type are the same as its parent sample,\nthose values will propagate down, and will be written to your specimen file automatically."
          if self.grid_type == 'ages':
              txt = "\n\nNote: only ages for which you provide data will be written to your upload file."
          self.default_msg_text += txt
          self.msg_text = wx.StaticText(self.panel, label=self.default_msg_text,
                                        style=wx.TE_CENTER, name='msg text')
          self.help_msg_boxsizer.Add(self.msg_text)
          self.help_msg_boxsizer.ShowItems(False)
  
          ## Code message and button
          # button
          self.toggle_codes_btn = wx.Button(self.panel, id=-1,
                                            label="Show method codes",
                                            name='toggle_codes_btn')
          self.Bind(wx.EVT_BUTTON, self.toggle_codes, self.toggle_codes_btn)
          # message
          self.code_msg_boxsizer = pw.MethodCodeDemystifier(self.panel, self.contribution.vocab)
          self.code_msg_boxsizer.ShowItems(False)
  
          ## Add content to sizers
          self.hbox = wx.BoxSizer(wx.HORIZONTAL)
          col_btn_vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='Columns',
                                                        name='manage columns'), wx.VERTICAL)
          row_btn_vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='Rows',
                                                        name='manage rows'), wx.VERTICAL)
          self.main_btn_vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='Manage data',
                                                              name='manage data'), wx.VERTICAL)
          input_output_vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='In/Out',
                                                             name='manage in out'), wx.VERTICAL)
          col_btn_vbox.Add(self.add_cols_button, flag=wx.ALL, border=5)
          col_btn_vbox.Add(self.remove_cols_button, flag=wx.ALL, border=5)
          row_btn_vbox.Add(many_rows_box, flag=wx.ALL, border=5)
          row_btn_vbox.Add(self.remove_row_button, flag=wx.ALL, border=5)
          row_btn_vbox.Add(self.deleteRowButton, flag=wx.ALL, border=5)
          self.main_btn_vbox.Add(self.importButton, flag=wx.ALL, border=5)
          self.main_btn_vbox.Add(self.exitButton, flag=wx.ALL, border=5)
          self.main_btn_vbox.Add(self.cancelButton, flag=wx.ALL, border=5)
          input_output_vbox.Add(self.copyButton, flag=wx.ALL, border=5)
          input_output_vbox.Add(self.selectAllButton, flag=wx.ALL, border=5)
          input_output_vbox.Add(self.copySelectionButton, flag=wx.ALL, border=5)
          self.hbox.Add(col_btn_vbox)
          self.hbox.Add(row_btn_vbox)
          self.hbox.Add(self.main_btn_vbox)
          self.hbox.Add(input_output_vbox)
  
          #self.panel.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.onLeftClickLabel, self.grid)
          self.grid.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.onLeftClickLabel, self.grid)
          #
          self.Bind(wx.EVT_KEY_DOWN, self.on_key_down)
          self.panel.Bind(wx.EVT_TEXT_PASTE, self.do_fit)
          # add actual data!
          self.grid_builder.add_data_to_grid(self.grid, self.grid_type)
          # fill in some default values
          self.grid_builder.fill_defaults()
          # set scrollbars
          self.grid.set_scrollbars()
  
          ## this would be a way to prevent editing
          ## some cells in age grid.
          ## with multiple types of ages, though,
          ## this doesn't make much sense
          #if self.grid_type == 'ages':
          #    attr = wx.grid.GridCellAttr()
          #    attr.SetReadOnly(True)
          #    self.grid.SetColAttr(1, attr)
  
          self.drop_down_menu = drop_down_menus.Menus(self.grid_type, self.contribution, self.grid)
          self.grid_box = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, name='grid container'), wx.VERTICAL)
          self.grid_box.Add(self.grid, 1, flag=wx.ALL|wx.EXPAND, border=5)
  
          # final layout, set size
          self.main_sizer.Add(self.hbox, flag=wx.ALL|wx.ALIGN_CENTER,#|wx.SHAPED,
                              border=20)
          self.main_sizer.Add(self.toggle_help_btn, 0,
                              flag=wx.BOTTOM|wx.ALIGN_CENTRE,#|wx.SHAPED,
                              border=5)
          self.main_sizer.Add(self.help_msg_boxsizer, 0,
                              flag=wx.BOTTOM|wx.ALIGN_CENTRE,
                              border=10)
          self.main_sizer.Add(self.toggle_codes_btn, 0,
                              flag=wx.BOTTOM|wx.ALIGN_CENTRE,#|wx.SHAPED,
                              border=5)
          self.main_sizer.Add(self.code_msg_boxsizer, 0,
                              flag=wx.BOTTOM|wx.ALIGN_CENTRE,#|wx.SHAPED,
                              border=5)
          self.main_sizer.Add(self.grid_box, 2, flag=wx.ALL|wx.ALIGN_CENTER|wx.EXPAND, border=10)
          self.panel.SetSizer(self.main_sizer)
          panel_sizer = wx.BoxSizer(wx.VERTICAL)
          panel_sizer.Add(self.panel, 1, wx.EXPAND)
          self.SetSizer(panel_sizer)
          panel_sizer.Fit(self)
          ## this keeps sizing correct if the user resizes the window manually
          #self.Bind(wx.EVT_SIZE, self.do_fit)
  #        self.Centre()
          self.Show()