Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JFileChooser with custom FileSystemView implementation

I extended FileSystemView and overwrote every method in this class. The model looks like this:

public class RemoteSystemFilesView extends FileSystemView {

   private IDirectoryService directoryService;

   public RemoteSystemFilesView(IDirectoryService aDirectoryService){ 
      this.directoryService = aDirectoryService; 
   }
   ....
}

The directoryService object returns directories from the remote UNIX server. Then, I create JFileChooser.

JFileChooser fc = new JFileChooser(new RemoteSystemFilesView(new DirectoryService()));
int returnVal = fc.showOpenDialog(this);

The dialog shows remote dirs and files correctly, but then I doubleClick on one of the displayed folders, I expect to navigate into that folder, but instead folder path appears in the field "File name" and that's it. I can't go to any other directory except root (/). Should I implement something else also in JFileChooser, not just in FileSystemView?

like image 524
polis Avatar asked Nov 09 '22 22:11

polis


1 Answers

The problem might be that your FileSystemView is actually returning plain java.io.File objects.

Instead try to return a VirtualFile wrapper object that extends java.io.File and returns true for the public boolean exists() and wraps returns VirtualFile instead of java.io.File for all the necessary methods.

This is an example of a VirtualFileSystem that I developed. It uses java.nio.Path because my code is mainly based in them. I hope it gives you a good starting point for understanding how to modify your code.

private static class VirtualFileSystemView extends FileSystemView {

    final Path base;

    final Set<Path> choices;

    private VirtualFileSystemView(final Path base,
                final Set<Path> choices) {
        this.base = base;
        this.choices = choices;
    }

    @Override
    protected File createFileSystemRoot(File f) {
        return new VirtualFile(f);
    }

    @Override
    public boolean isComputerNode(File dir) {
        return false;
    }

    @Override
    public boolean isFloppyDrive(File dir) {
        return false;
    }

    @Override
    public boolean isDrive(File dir) {
        return false;
    }

    @Override
    public Icon getSystemIcon(File f) {
        return null;
    }

    @Override
    public String getSystemTypeDescription(File f) {
        return f.toPath().toString();
    }

    @Override
    public String getSystemDisplayName(File f) {
        return f.getName();
    }

    @Override
    public File getParentDirectory(final File dir) {
        return new VirtualFile(dir.getParentFile());
    }

    @Override
    public File[] getFiles(final File dir, boolean useFileHiding) {
        final List<File> files = new ArrayList<>(choices.size());

        choices.stream()
                    .filter((path) -> (path.getParent().equals(dir.toPath()))).
                    forEach((path) -> {
                        files.add(new VirtualFile(path.toFile()));
                    });

        return files.toArray(new File[files.size()]);
    }

    @Override
    public File createFileObject(final String path) {
        return new VirtualFile(path);
    }

    @Override
    public File createFileObject(final File dir, final String filename) {
        Path fileObject;

        if (dir != null) {
            fileObject = Paths.get(dir.toPath().toString(), filename);
        } else {
            fileObject = Paths.get(filename);
        }
        return new VirtualFile(fileObject.toFile());
    }

    @Override
    public File getDefaultDirectory() {
        return new VirtualFile(base.toFile());
    }

    @Override
    public File getHomeDirectory() {
        return new VirtualFile(base.toFile());
    }

    @Override
    public File[] getRoots() {
        final List<File> files = new ArrayList<>(choices.size());

        files.add(new VirtualFile(base.toFile()));
        return files.toArray(new File[files.size()]);
    }

    @Override
    public boolean isFileSystemRoot(final File dir) {
        boolean isRoot = dir.toPath().getParent() == null;
        return isRoot;
    }

    @Override
    public boolean isHiddenFile(final File f) {
        return false;
    }

    @Override
    public boolean isFileSystem(final File f) {
        return !isFileSystemRoot(f);
    }

    @Override
    public File getChild(final File parent, final String fileName) {
        return new VirtualFile(parent, fileName);
    }

    @Override
    public boolean isParent(final File folder, final File file) {
        return file.toPath().getParent().equals(folder.toPath());
    }

    @Override
    public Boolean isTraversable(final File f) {
        boolean isTraversable = false;

        for (final Path path : choices) {
            if (path.startsWith(f.toPath())) {
                isTraversable = true;
                break;
            }
        }
        return isTraversable;
    }

    @Override
    public boolean isRoot(final File f) {
        boolean isRoot = false;

        for (final Path path : choices) {
            if (path.getParent().equals(f.toPath())) {
                isRoot = true;
            }
        }
        return isRoot;
    }

    @Override
    public File createNewFolder(final File containingDir) throws IOException {
        return new VirtualFile(containingDir);
    }


    private class VirtualFile extends File {

        private static final long serialVersionUID = -1752685357864733168L;

        private VirtualFile(final File file) {
            super(file.toString());
        }

        private VirtualFile(String pathname) {
            super(pathname);
        }

        private VirtualFile(String parent, String child) {
            super(parent, child);
        }

        private VirtualFile(File parent, String child) {
            super(parent, child);
        }

        @Override
        public boolean exists() {
            return true;
        }

        @Override
        public boolean isDirectory() {
            return VirtualFileSystemView.this.isTraversable(this);
        }

        @Override
        public File getCanonicalFile() throws IOException {
            return new VirtualFile(super.getCanonicalFile());
        }

        @Override
        public File getAbsoluteFile() {
            return new VirtualFile(super.getAbsoluteFile());
        }

        @Override
        public File getParentFile() {
            File parent = super.getParentFile();

            if (parent != null) {
                parent = new VirtualFile(super.getParentFile());
            }
            return parent;
        }

    }

}
like image 174
Marcelo Ruiz Avatar answered Nov 14 '22 22:11

Marcelo Ruiz