/** Sets the list of roots, old roots will be cleared. */
  public void setRoots(File... newRoots) {
    this.roots.clear();
    // call cancel editing before tree is cleared
    directoryTree.cancelEditing();
    directoryTreeModel.removeSubRoots();
    this.roots.addAll(retainAncestors(newRoots));

    List<File> list = new ArrayList<File>(roots);
    Collections.sort(
        list,
        new Comparator<File>() {
          public int compare(File o1, File o2) {
            if (o1.equals(SharingSettings.TORRENT_DATA_DIR_SETTING.getValue())) {
              return -1;
            }
            if (o2.equals(SharingSettings.TORRENT_DATA_DIR_SETTING.getValue())) {
              return 1;
            }
            return o1.compareTo(o2);
          }
        });

    for (File root : list) {
      directoryTreeModel.addSubRoot(root);
    }
    setRootExpanded();
  }
 /** Constructs the tree path for a directory. */
 private TreePath getTreePath(File dir) {
   LinkedList<File> files = new LinkedList<File>();
   files.add(dir);
   File parent = dir.getParentFile();
   while (parent != null && !directoryTreeModel.isSubRoot(dir)) {
     files.addFirst(parent);
     dir = parent;
     parent = parent.getParentFile();
   }
   Object[] path = new Object[files.size() + 1];
   path[0] = directoryTreeModel.getRoot();
   System.arraycopy(files.toArray(), 0, path, 1, path.length - 1);
   return new TreePath(path);
 }
 /**
  * Adds a root to the tree if it's not already in there.
  *
  * @return false if dir is already in the tree
  */
 public boolean addRoot(File dir) {
   // remove from deselected in any case
   boolean changed = deselected.remove(dir);
   // check if already included
   for (File root : roots) {
     if (FileUtils.isAncestor(root, dir)) {
       if (root.equals(dir)) {
         if (changed) {
           directoryTreeModel.valueForPathChanged(getTreePath(dir), null);
         }
         return changed;
       }
       // make sure it is included
       removeFromPath(dir);
       TreePath path = getTreePath(dir);
       directoryTree.scrollPathToVisible(path);
       return changed;
     } else if (FileUtils.isAncestor(dir, root)) {
       removeRoot(root);
       addDirToTree(dir);
       // expand to root and its parent, since expand has no effect if root
       // doesn't have subfolders
       setExpanded(root);
       // guaranteed to not be null since at least dir is its real ancestor
       setExpanded(root.getParentFile());
       return true;
     }
   }
   addDirToTree(dir);
   setRootExpanded();
   return true;
 }
  /**
   * Constructs the tree view with a list of roots.
   *
   * @param blackListSet set of subfolders that are marked as not included, cannot be null
   * @param roots list of roots, can be null
   */
  public RecursiveLibraryDirectoryPanel(
      boolean precheckFolders, Set<File> blackListSet, File... roots) {
    super(new BorderLayout());
    this.roots = new TreeSet<File>(FileTreeModel.DEFAULT_COMPARATOR);
    this.deselected = new HashSet<File>(blackListSet);

    if (!precheckFolders) {
      addFoldersToExclude(new HashSet<File>(Arrays.asList(roots)));
    }

    // center
    directoryTreeModel = new FileTreeModel("");
    directoryTreeModel.setFileFilter(new IncludedFolderFilter());

    directoryTree = new RootNotEditableTree(directoryTreeModel);
    directoryTree.setBorder(new EmptyBorder(4, 4, 4, 4));
    directoryTree.setCellRenderer(fileTreeCellRenderer);
    directoryTree.setCellEditor(new FileTreeCellEditor());
    directoryTree.setEditable(true);
    directoryTree.setVisibleRowCount(8);
    directoryTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

    JScrollPane jspDirectories = new JScrollPane(directoryTree);
    mainPanel = new JPanel(new BorderLayout());
    mainPanel.add(jspDirectories, BorderLayout.CENTER);
    legendPanel = new JPanel();
    mainPanel.add(legendPanel, BorderLayout.SOUTH);

    add(mainPanel, BorderLayout.CENTER);

    setRoots(roots);

    updateLanguage();
  }
 /** Removes <code>root</code> from the tree of included roots. */
 public void removeRoot(File root) {
   if (roots.remove(root)) {
     // remove old root and add dir and expand to root
     // cancel editing, since we're removing from the tree
     directoryTree.cancelEditing();
     directoryTreeModel.removeSubRoot(root);
     removeFromPath(root);
   }
 }
 /**
  * Removes all files from <code>deselected</code> that are ancestors
  * of <code>file</code or vice versa.
  */
 private void removeFromPath(File file) {
   // remove all children, file itself is removed here too
   for (Iterator<File> i = deselected.iterator(); i.hasNext(); ) {
     File f = i.next();
     if (FileUtils.isAncestor(file, f)) {
       i.remove();
     }
   }
   while (file != null && !roots.contains(file)) {
     // mark other children of parent as excluded
     File parent = file.getParentFile();
     if (ancestorIsExcluded(parent)) {
       deselected.remove(parent);
       int childCount = directoryTreeModel.getChildCount(parent);
       for (int j = 0; j < childCount; j++) {
         File sibling = (File) directoryTreeModel.getChild(parent, j);
         if (sibling != null && !sibling.equals(file)) {
           deselected.add(sibling);
         }
       }
     }
     file = parent;
   }
 }
 /** Returns the text used by the tree cell renderers. */
 private String getText(File file) {
   return directoryTreeModel.isSubRoot(file) ? file.getAbsolutePath() : file.getName();
 }
 private void addDirToTree(File dir) {
   roots.add(dir);
   directoryTreeModel.addSubRoot(dir);
 }
 /** Expand the visible or invisible root node. */
 public void setRootExpanded() {
   directoryTree.expandPath(new TreePath(directoryTreeModel.getRoot()));
 }
 /** Resets the text of various components to the current language. */
 public void updateLanguage() {
   createLegendPanel(legendPanel);
   directoryTreeModel.changeRootText(I18n.tr("Library Folders"));
 }