/**
  * Calculate what the selection path should be once the specified node has been removed from the
  * tree.
  */
 private TreePath calculatePostRemoveSelectionPath(PreferencesNode node) {
   PreferencesNode parentNode = (PreferencesNode) node.getParent();
   int childCount = parentNode.getChildCount();
   if (childCount == 1) {
     // the only child is to be removed - select the parent
     return new TreePath(parentNode.getPath());
   }
   int nodeIndex = parentNode.getIndex(node);
   if (nodeIndex == childCount - 1) {
     // the last child in the list is to be removed - select the previous child
     return new TreePath(((PreferencesNode) parentNode.getChildAt(nodeIndex - 1)).getPath());
   }
   // by default, select the next child
   return new TreePath(((PreferencesNode) parentNode.getChildAt(nodeIndex + 1)).getPath());
 }
  /** we can't simply rename the node - we have to clone it, then remove it... */
  void renameSelectedNode() {
    PreferencesNode selectedNode = this.selectedPreferencesNode();
    if (selectedNode == null || selectedNode.cannotBeRemoved()) {
      return;
    }

    String name = this.promptForNodeName();
    if (name == null) {
      return;
    }

    Preferences oldPreferences = selectedNode.preferences();
    PreferencesNode parentNode = (PreferencesNode) selectedNode.getParent();
    Preferences parentPreferences = parentNode.preferences();
    try {
      if (parentPreferences.nodeExists(name)) {
        // cannot rename to same name as existing node
        return;
      }
    } catch (BackingStoreException ex) {
      this.handleException(ex);
      return;
    }

    // clear the selection *before* removing the node, so we are no longer
    // listening to the node when it gets deleted - it will be in an invalid state...
    this.treeSelectionModel.clearSelection();
    Preferences newPreferences = parentPreferences.node(name);
    try {
      this.clone(oldPreferences, newPreferences);
      oldPreferences.removeNode();
      // flush the changes, so events are fired and the tree is updated
      parentPreferences.flush();
    } catch (BackingStoreException ex) {
      this.handleException(ex);
      return; // skip the selection of a node that might not be there...
    }
    PreferencesNode newNode = parentNode.childNodeFor(newPreferences);
    this.treeSelectionModel.setSelectionPath(new TreePath(newNode.getPath()));
  }
  void addChildToSelectedNode() {
    PreferencesNode selectedNode = this.selectedPreferencesNode();
    if (selectedNode == null) {
      return;
    }
    String name = this.promptForNodeName();
    if (name == null) {
      return;
    }

    Preferences preferences = selectedNode.preferences();
    // this will cause the preferences to be created if it does not already exist
    Preferences newPreferences = preferences.node(name);
    try {
      // flush the change, so an event is fired and the node is
      // created and added to the tree before we try to select it
      preferences.flush();
    } catch (BackingStoreException ex) {
      this.handleException(ex);
      return; // skip the selection of a node that might not be there...
    }
    PreferencesNode newNode = selectedNode.childNodeFor(newPreferences);
    this.treeSelectionModel.setSelectionPath(new TreePath(newNode.getPath()));
  }