public static @NotNull <T> List<T> collectExpandedObjects(@NotNull JTree tree, @NotNull TreePath root, @NotNull Function<? super TreePath, ? extends T> mapper) {
    int count = tree.getRowCount();
    if (count == 0) return Collections.emptyList(); // tree is empty
    int row = tree.getRowForPath(root);
    if (row < 0) {
      return !tree.isRootVisible() && root.equals(getVisiblePathWithValidation(tree, 0, count).getParentPath())
             ? collectExpandedObjects(tree, mapper) // collect expanded objects under a hidden root
             : Collections.emptyList(); // root path is not visible
    }
    if (!tree.isExpanded(row)) return Collections.emptyList(); // root path is not expanded
    List<T> list = new ArrayList<>(count);
    ContainerUtil.addIfNotNull(list, mapper.apply(root));
    int depth = root.getPathCount();
    for (row++; row < count; row++) {
      TreePath path = getVisiblePathWithValidation(tree, row, count);
      if (depth >= path.getPathCount()) break; // not a descendant of a root path
      if (tree.isExpanded(row)) ContainerUtil.addIfNotNull(list, mapper.apply(path));
    }
    return list;
  }
public static @NotNull <T> List<T> collectExpandedObjects(@NotNull JTree tree, @NotNull TreePath root, @NotNull Function<? super TreePath, ? extends T> mapper)