Question

I am trying to create a FileFilter that will only allow the user to open a directory that contains a certain file. The use case is that these directories are workspaces that have a file called smart.workspace inside.

Currently my filter is as follows...

class SMARTWorkspaceFilter extends javax.swing.filechooser.FileFilter {

    String description = "SMART Workspace";
    String fileNameFilter = "smart.workspace";

    SMARTWorkspaceFilter() {

    }

    @Override
    public boolean accept(File file) {

        log.debug("Testing file: " + file.getName());

        if (file.isFile()) {
            return false;
        }

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {

                log.debug("Directory: " + f.isDirectory());
                log.debug("Name: " + f.getName());

                if (f.isDirectory()) {
                    return true;
                }

                if (f.getName().equals(fileNameFilter)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public String getDescription() {
        return description;
    }
}

Obviously my problem is that to allow the user to navigate to the workspace folder I have to allow for sub directories.

For the file chooser I am using the option DIRECTORIES_ONLY.

Is it possible to only allow the user to select a directory based on the directories contents?

For example the directory 'workspace' exists at C://Folder1/Folder2/wokspace, I would want to allow the FileChooser to 'start' at C:// and allow the user to navigate to the 'workspace' folder and accept it. The FileChooser shouldn't allow the acceptance of Folder1 or Folder2 but still allow the navigation through Folder1 and Folder2.

Was it helpful?

Solution

I dont think you can make the FileFilter differentiate between "files/directories that should be displayed an can be accessed" and "files/directories that can be selected".

A solution for your problem that comes to my mind is: Let the user search/select the smart.workspace file and then navigate from there to the parent folder.

If you need the dialog to do exactly as you described above you will have to get involved in detail with the JFileChooser. Hopefully extending that class gives you enough access to change the behaviour as desired.

OTHER TIPS

Your problem is that your return statements are conflicting. You don't need the first if statement as you're returning false by default (unless it's a directory AND that directory contains the special file).

class SMARTWorkspaceFilter extends javax.swing.filechooser.FileFilter {

    String description = "SMART Workspace";
    String fileNameFilter = "smart.workspace";

    SMARTWorkspaceFilter() {

    }

    @Override
    public boolean accept(File file) {
        log.debug("Testing file: " + file.getName());
        // have we selected a directory
        if(file.isDirectory()) {
            File[] files = file.listFiles();
            // for all files in the directory
            for(File f : files) {
                log.debug("Directory: " + f.isDirectory());
                log.debug("Name: " + f.getName());
                // if the name is the name of the special file, return true
                if(f.getName().equals(fileNameFilter)) {
                    return true;
                }
            }
        }

        // else, return false
        return false;
    }

    @Override
    public String getDescription() {
        return description;
    }
}

Ultimately @SebastianH is correct, it doesn't seem possible through the FileFilter. instead I extended the JFileChooser.

javax.swing.JFileChooser fileChooser = new javax.swing.JFileChooser(defaultLocation){
    @Override
    public boolean isDirectorySelectionEnabled() {
        setOpenButtonState(this, false);

        File file = getSelectedFile();

        if(file == null){
            return false;
        }

        if(file.isDirectory()){
            File[] files = file.listFiles();
            for(File f : files){
                if(f.isFile() && f.getName().equals("smart.workspace")){
                    setOpenButtonState(this, true);
                    return true;
                }
            }
        }

        return false;
    }

    private void setOpenButtonState(java.awt.Container c, boolean flag) {
        int len = c.getComponentCount();
        for (int i = 0; i < len; i++) {
            java.awt.Component comp = c.getComponent(i);

            if (comp instanceof javax.swing.JButton) {
                javax.swing.JButton b = (javax.swing.JButton)comp;

                if ( b != null && b.getText() != null && b.getText().equals("Open") ) {
                    b.setEnabled(flag);
                }

            } else if (comp instanceof java.awt.Container) {
                setOpenButtonState((java.awt.Container) comp, flag);
            }
        }     
    }

};

In addition to preventing the selection I added the nicety of disabling the Open button to avoid confusion.

Credit for the disabling open button --> Disable Open button in JFileChooser?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top