/**
   * Update the layouts tree.
   *
   * @param current The name of the current layout or <CODE>null</CODE> if none.
   */
  public void updateLayouts(Path current) throws PipelineException {
    DefaultMutableTreeNode root = null;
    {
      root = new DefaultMutableTreeNode(new TreeData(), true);

      {
        Path path = new Path(PackageInfo.getSettingsPath(), "layouts");
        rebuildTreeModel(path, new Path("/"), root);
      }

      DefaultTreeModel model = (DefaultTreeModel) pTree.getModel();
      model.setRoot(root);

      {
        Enumeration e = root.depthFirstEnumeration();
        if (e != null) {
          while (e.hasMoreElements()) {
            DefaultMutableTreeNode tnode = (DefaultMutableTreeNode) e.nextElement();
            pTree.expandPath(new TreePath(tnode.getPath()));
          }
        }
      }
    }

    pTree.clearSelection();
    if (current != null) {
      TreePath tpath = null;
      DefaultMutableTreeNode tnode = root;
      for (String comp : current.getComponents()) {
        DefaultMutableTreeNode next = null;
        Enumeration e = tnode.children();
        if (e != null) {
          while (e.hasMoreElements()) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) e.nextElement();
            TreeData data = (TreeData) child.getUserObject();
            if (data.toString().equals(comp)) {
              tpath = new TreePath(child.getPath());
              next = child;
              break;
            }
          }
        }

        if (next == null) break;

        tnode = next;
      }

      if (tpath != null) {
        pTree.setSelectionPath(tpath);
        pTree.makeVisible(tpath);
      }
    }
  }
  /**
   * Expands the sub folders and image informations under the specified node.
   *
   * @param node the node.
   */
  protected void expandNode(DefaultMutableTreeNode node) {
    try {
      Object[] paths = node.getPath();

      String path_str = "";
      Vector folder_list = new Vector();
      for (int i = 1; i < paths.length; i++) {
        String name = (String) ((DefaultMutableTreeNode) paths[i]).getUserObject();
        path_str += "/" + name;

        // Converts January...December to 1...12.
        if (mode == DATE_ORIENTED && i == 2) {
          for (int m = 1; m <= 12; m++) {
            if (JulianDay.getFullSpellMonthString(m).equals(name)) name = String.valueOf(m);
          }
        }

        folder_list.addElement(name);
      }

      // When to expand sub folders.
      Vector folders = new Vector();
      if (mode == DATE_ORIENTED) folders = db_manager.getDateOrientedFolders(folder_list);
      if (mode == PATH_ORIENTED) folders = db_manager.getPathOrientedFolders(folder_list);
      addNode(node, folders);

      // When to expand image informations.
      XmlDBAccessor accessor = null;
      if (mode == DATE_ORIENTED) accessor = db_manager.getDateOrientedAccessor(folder_list);
      if (mode == PATH_ORIENTED) accessor = db_manager.getPathOrientedAccessor(folder_list);
      if (accessor != null) {
        Vector name_list = new Vector();
        XmlInformation info = (XmlInformation) accessor.getFirstElement();
        while (info != null) {
          name_list.addElement(info.getPath());
          hash_info.put(path_str + "/" + info.getPath(), info);
          info = (XmlInformation) accessor.getNextElement();
        }
        addNode(node, name_list);
      }

      revalidate();
      repaint();
    } catch (IOException exception) {
      String message = "Failed to read the database.";
      JOptionPane.showMessageDialog(pane, message, "Error", JOptionPane.ERROR_MESSAGE);
    }
  }
  /**
   * Processes an idChanged event. Search is different from all other navigators in that you while
   * search tree is synchronized the highlighting doesn't occur unless selected from the search
   * navigator.
   */
  public void idChanged(HelpModelEvent e) {
    ID id = e.getID();
    URL url = e.getURL();
    HelpModel helpModel = searchnav.getModel();
    debug("idChanged(" + e + ")");

    if (e.getSource() != helpModel) {
      debug("Internal inconsistency!");
      debug("  " + e.getSource() + " != " + helpModel);
      throw new Error("Internal error");
    }

    TreePath s = tree.getSelectionPath();
    if (s != null) {
      Object o = s.getLastPathComponent();
      // should require only a TreeNode
      if (o instanceof DefaultMutableTreeNode) {
        DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o;
        SearchTOCItem item = (SearchTOCItem) tn.getUserObject();
        if (item != null) {
          ID nId = item.getID();
          if (nId != null && nId.equals(id)) {
            return;
          }
        }
      }
    }

    DefaultMutableTreeNode node = findIDorURL(topNode, id, url);
    if (node == null) {
      // node doesn't exist. Need to clear the selection.
      debug("node didn't exist");
      tree.clearSelection();
      return;
    }
    TreePath path = new TreePath(node.getPath());
    tree.expandPath(path);
    tree.setSelectionPath(path);
    tree.scrollPathToVisible(path);
  }
    public void valueChanged(TreeSelectionEvent event) {
      // DefaultMutableTreeNode node = new DefaultMutableTreeNode();
      DefaultMutableTreeNode node;
      TreePath paths[] = event.getPaths();

      // Statistical variables
      Object bestNode;
      Object worstNode;
      double avgFitness = 0;
      double bestFitness = -1;
      double worstFitness = -1;

      // Update Selection Panel to reflect current selections
      for (int i = 0; i < paths.length; i++) {
        // If a parent node is selected, select all children nodes
        DefaultMutableTreeNode tmpNode = (DefaultMutableTreeNode) paths[i].getLastPathComponent();

        // If Root is selected, clear all selections
        if (tmpNode.isRoot()) {
          tree.clearSelection();
          selectedChildrenPaths.removeAllElements();
          break;
        }

        if (tmpNode.getAllowsChildren()) {
          ArrayList tmpNodeChildren = new ArrayList();

          for (Enumeration e = tmpNode.children(); e.hasMoreElements(); ) {
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) e.nextElement();
            TreePath treePath = new TreePath(childNode.getPath());

            if (event.isAddedPath(paths[i])) {
              if (!selectedChildrenPaths.contains(treePath))
                selectedChildrenPaths.addElement(treePath);
            } else selectedChildrenPaths.removeElement(treePath);
          }

          // TreePath [] treePaths = new TreePath[tmpNodeChildren.size()];

          // if ( event.isAddedPath(paths[i]) )
          //    tree.addSelectionPaths( (TreePath []) tmpNodeChildren.toArray(treePaths) );
          // else
          //    tree.removeSelectionPaths( (TreePath[]) tmpNodeChildren.toArray(treePaths) );

          // Collapse parent view -- commented for future use, DO NOT IMPLEMENT AS SHOWN
          // tree.collapsePath( paths[i] );
        } else // only a single node is being examined
        {
          if (event.isAddedPath(paths[i])) {
            if (!selectedChildrenPaths.contains(paths[i]))
              selectedChildrenPaths.addElement(paths[i]);
          } else selectedChildrenPaths.removeElement(paths[i]);
        }
      }

      // If selections exist, enabled "Save Selected" menu item
      if (selectedChildrenPaths.size() > 0) miSave.setEnabled(true);
      else miSave.setEnabled(false);

      // Calculate selection information statistics
      for (int j = 0; j < selectedChildrenPaths.size(); j++) {
        double fitness = 0;

        node =
            (DefaultMutableTreeNode)
                ((TreePath) selectedChildrenPaths.elementAt(j)).getLastPathComponent();

        fitness = gaMonitor.getFitness(node.getUserObject());

        avgFitness += fitness;

        if (fitness > bestFitness || bestFitness == -1) {
          bestFitness = fitness;
          bestNode = node;
        }

        if (fitness < worstFitness || worstFitness == -1) {
          worstFitness = fitness;
          worstNode = node;
        }
      }

      // Finialize Statistics
      if (bestFitness != -1) avgFitness = avgFitness / (double) selectedChildrenPaths.size();

      // Panel may not exist!  If null, ignore
      if (selectionStatsPanel != null) {
        if (bestFitness != -1)
          selectionStatsPanel.setSelectionStats(
              selectedChildrenPaths.size(), avgFitness, bestFitness, worstFitness);
        else selectionStatsPanel.setEmptySelection();
      }
    }