/** Initialize the common user interface components. */
  private void initUI() {
    /* initialize fields */
    {
      pFileSeqPanels = new TreeMap<FileSeq, JFileSeqPanel>();
    }

    /* initialize the popup menus */
    {
      initBasicMenus(true, false);
      updateMenuToolTips();
    }

    /* initialize the panel components */
    {
      setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

      /* header */
      {
        pApplyToolTipText = "Replace the working area files with the selected checked-in files.";
        pUnApplyToolTipText = "There are no unsaved changes to Apply at this time.";

        JPanel panel = initHeader(true);
        add(panel);
      }

      add(Box.createRigidArea(new Dimension(0, 4)));

      /* full node name */
      {
        LinkedList<Component> extra = new LinkedList<Component>();
        extra.add(Box.createRigidArea(new Dimension(4, 0)));
        {
          JButton btn = new JButton();
          pSeqLayoutButton = btn;
          btn.setName(pIsListLayout ? "ListLayoutButton" : "TabbedLayoutButton");

          Dimension size = new Dimension(19, 19);
          btn.setMinimumSize(size);
          btn.setMaximumSize(size);
          btn.setPreferredSize(size);

          btn.setActionCommand("seq-layout-changed");
          btn.addActionListener(this);

          extra.add(btn);
        }

        initNameField(this, extra);

        pNodeNameField.setFocusable(true);
        pNodeNameField.addKeyListener(this);
        pNodeNameField.addMouseListener(this);
      }

      add(Box.createRigidArea(new Dimension(0, 4)));

      {
        JTabbedPane tab = new JTabbedPane();
        pFileSeqsTab = tab;
        tab.setVisible(!pIsListLayout);
        add(tab);
      }

      {
        Box vbox = new Box(BoxLayout.Y_AXIS);
        pFileSeqsBox = vbox;

        {
          JScrollPane scroll = UIFactory.createVertScrollPane(vbox);
          pFileSeqsScroll = scroll;
          scroll.setVisible(!pIsListLayout);

          add(scroll);
        }
      }

      Dimension size = new Dimension(sSize + 22, 120);
      setMinimumSize(size);
      setPreferredSize(size);

      setFocusable(true);
      addKeyListener(this);
      addMouseListener(this);
    }

    updateNodeStatus(null, null, null);
  }
  /**
   * Update the UI components to reflect the current per-file status.
   *
   * @param status The current node status.
   * @param novelty The per-file novelty flags.
   * @param offline The revision numbers of the offline checked-in versions.
   */
  protected synchronized void updateNodeStatus(
      NodeStatus status,
      TreeMap<VersionID, TreeMap<FileSeq, boolean[]>> novelty,
      TreeSet<VersionID> offline) {
    super.updateNodeStatus(status, false);

    pNovelty = novelty;
    pOffline = offline;

    NodeDetailsLight details = null;
    if (pStatus != null) details = pStatus.getLightDetails();

    /* files */
    {
      pFileSeqsTab.removeAll();
      pFileSeqsBox.removeAll();
      pFileSeqPanels.clear();

      if ((pNovelty != null) && (details != null)) {
        NodeMod mod = details.getWorkingVersion();
        NodeVersion vsn = details.getLatestVersion();

        NodeCommon com = null;
        if (mod != null) com = mod;
        else if (vsn != null) com = vsn;
        else assert (false);

        /* get the primary and unique secondary file sequences */
        FileSeq primary = com.getPrimarySequence();
        TreeSet<FileSeq> secondary = new TreeSet<FileSeq>();
        {
          secondary.addAll(com.getSecondarySequences());

          TreeSet<FileSeq> unique = new TreeSet<FileSeq>();
          for (TreeMap<FileSeq, boolean[]> table : pNovelty.values()) unique.addAll(table.keySet());

          for (FileSeq ufseq : unique) {
            boolean found = false;

            if (ufseq.similarTo(primary)) found = true;
            else {
              for (FileSeq fseq : secondary) {
                if (ufseq.similarTo(fseq)) {
                  found = true;
                  break;
                }
              }
            }

            if (!found) secondary.add(ufseq);
          }
        }

        /* add the file sequence UI components */
        addFileSeqPanel(primary);
        for (FileSeq fseq : secondary) addFileSeqPanel(fseq);

        if (pIsListLayout) pFileSeqsBox.add(UIFactory.createFiller(sSize));
      }
    }

    pFileSeqsTab.setVisible(!pIsListLayout);
    pFileSeqsScroll.setVisible(pIsListLayout);

    if (pIsListLayout) pFileSeqsScroll.revalidate();
    else pFileSeqsTab.revalidate();
  }