/** Update the menu item tool tips. */
  @Override
  protected void updateMenuToolTips() {
    super.updateMenuToolTips();

    UserPrefs prefs = UserPrefs.getInstance();
    updateMenuToolTip(
        pApplyItem, prefs.getApplyChanges(), "Apply the changes to the working version.");
  }
  /**
   * Apply the updated information to this panel.
   *
   * @param author Owner of the current working area.
   * @param view Name of the current working area view.
   * @param status The current status for the node being displayed.
   * @param novelty The per-file novelty flags.
   * @param offline The revision numbers of the offline checked-in versions.
   */
  public synchronized void applyPanelUpdates(
      String author,
      String view,
      NodeStatus status,
      TreeMap<VersionID, TreeMap<FileSeq, boolean[]>> novelty,
      TreeSet<VersionID> offline) {
    if (!pAuthor.equals(author) || !pView.equals(view)) super.setAuthorView(author, view);

    updateNodeStatus(status, novelty, offline);
  }
  /** Replace working files with the selected checked-in files. */
  @Override
  public void doApply() {
    super.doApply();

    if (pIsFrozen) return;

    TreeMap<String, VersionID> files = new TreeMap<String, VersionID>();
    for (JFileSeqPanel panel : pFileSeqPanels.values()) files.putAll(panel.getFilesToRevert());

    RevertTask task = new RevertTask(files);
    task.start();
  }
  public void fromGlue(GlueDecoder decoder) throws GlueException {
    super.fromGlue(decoder);

    Boolean tf = (Boolean) decoder.decode("IsListLayout");
    pIsListLayout = (tf != null) && tf;
  }
 public void toGlue(GlueEncoder encoder) throws GlueException {
   super.toGlue(encoder);
   encoder.encode("IsListLayout", pIsListLayout);
 }
  /** Invoked when an action occurs. */
  public void actionPerformed(ActionEvent e) {
    super.actionPerformed(e);

    String cmd = e.getActionCommand();
    if (cmd.equals("seq-layout-changed")) doSeqLayoutChanged();
  }
 /** Reset the caches of toolset plugins and plugin menu layouts. */
 @Override
 public void clearPluginCache() {
   super.clearPluginCache();
   for (JFileSeqPanel panel : pFileSeqPanels.values()) panel.clearPluginCache();
 }
  /**
   * 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();
  }
  /** Register the name of a panel property which has just been modified. */
  @Override
  public void unsavedChange(String name) {
    for (JFileSeqPanel panel : pFileSeqPanels.values()) panel.setApplyItemEnabled(true);

    super.unsavedChange(name);
  }
  /**
   * Perform any operations needed after an panel operation has completed.
   *
   * <p>This method is run by the Swing Event thread.
   */
  @Override
  public void postPanelOp() {
    for (JFileSeqPanel panel : pFileSeqPanels.values()) panel.setApplyItemEnabled(false);

    super.postPanelOp();
  }
  /** Set the author and view. */
  @Override
  public synchronized void setAuthorView(String author, String view) {
    super.setAuthorView(author, view);

    updatePanels();
  }