All Downloads are FREE. Search and download functionalities are using the official Maven repository.

anlavn.ui.filechooser.JnaFileChooser Maven / Gradle / Ivy

/* This file is part of JnaFileChooser.
 *
 * JnaFileChooser is free software: you can redistribute it and/or modify it
 * under the terms of the new BSD license.
 *
 * JnaFileChooser is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.
 */
package anlavn.ui.filechooser;

import java.awt.Window;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;

import com.sun.jna.Platform;

/**
 * JnaFileChooser is a wrapper around the native Windows file chooser and folder
 * browser that falls back to the Swing JFileChooser on platforms other than
 * Windows or if the user chooses a combination of features that are not
 * supported by the native dialogs (for example multiple selection of
 * directories).
 *
 * Example: JnaFileChooser fc = new JnaFileChooser(); fc.setFilter("All Files",
 * "*"); fc.setFilter("Pictures", "jpg", "jpeg", "gif", "png", "bmp");
 * fc.setMultiSelectionEnabled(true);
 * fc.setMode(JnaFileChooser.Mode.FilesAndDirectories); if
 * (fc.showOpenDialog(parent)) { Files[] selected = fc.getSelectedFiles(); // do
 * something with selected }
 *
 */
public class JnaFileChooser {

    private static enum Action {
        Open, Save
    }

    /**
     * the availabe selection modes of the dialog
     */
    public static enum Mode {
        Files(JFileChooser.FILES_ONLY),
        Directories(JFileChooser.DIRECTORIES_ONLY),
        FilesAndDirectories(JFileChooser.FILES_AND_DIRECTORIES);
        private int jFileChooserValue;

        private Mode(int jfcv) {
            this.jFileChooserValue = jfcv;
        }

        public int getJFileChooserValue() {
            return jFileChooserValue;
        }
    }

    protected File[] selectedFiles;
    protected File currentDirectory;
    protected ArrayList filters;
    protected boolean multiSelectionEnabled;
    protected Mode mode;

    protected String defaultFile;
    protected String dialogTitle;
    protected String openButtonText;
    protected String saveButtonText;

    /**
     * creates a new file chooser with multiselection disabled and mode set to
     * allow file selection only.
     */
    public JnaFileChooser() {
        filters = new ArrayList();
        multiSelectionEnabled = false;
        mode = Mode.Files;
        selectedFiles = new File[]{null};

        defaultFile = "";
        dialogTitle = "";
        openButtonText = "";
        saveButtonText = "";
    }

    /**
     * creates a new file chooser with the specified initial directory
     *
     * @param currentDirectory the initial directory
     */
    public JnaFileChooser(File currentDirectory) {
        this();
        if (currentDirectory != null) {
            this.currentDirectory = currentDirectory.isDirectory()
                    ? currentDirectory : currentDirectory.getParentFile();
        }
    }

    /**
     * creates a new file chooser with the specified initial directory
     *
     * @param currentDirectoryPath the initial directory
     */
    public JnaFileChooser(String currentDirectoryPath) {
        this(currentDirectoryPath != null
                ? new File(currentDirectoryPath) : null);
    }

    /**
     * shows a dialog for opening files
     *
     * @param parent the parent window
     *
     * @return true if the user clicked OK
     */
    public boolean showOpenDialog(Window parent) {
        return showDialog(parent, Action.Open);
    }

    /**
     * shows a dialog for saving files
     *
     * @param parent the parent window
     *
     * @return true if the user clicked OK
     */
    public boolean showSaveDialog(Window parent) {
        return showDialog(parent, Action.Save);
    }

    private boolean showDialog(Window parent, Action action) {
        // native windows filechooser doesn't support mixed selection mode
        if (Platform.isWindows() && mode != Mode.FilesAndDirectories) {
            // windows filechooser can only multiselect files
            if (multiSelectionEnabled && mode == Mode.Files) {
                // TODO Here we would use the native windows dialog
                // to choose multiple files. However I haven't been able
                // to get it to work properly yet because it requires
                // tricky callback magic and somehow this didn't work for me
                // quite as documented (probably because I messed something up).
                // Because I don't need this feature right now I've put it on
                // hold to get on with stuff.
                // Example code: http://support.microsoft.com/kb/131462/en-us
                // GetOpenFileName: http://msdn.microsoft.com/en-us/library/ms646927.aspx
                // OFNHookProc: http://msdn.microsoft.com/en-us/library/ms646931.aspx
                // CDN_SELCHANGE: http://msdn.microsoft.com/en-us/library/ms646865.aspx
                // SendMessage: http://msdn.microsoft.com/en-us/library/ms644950.aspx
            } else if (!multiSelectionEnabled) {
                if (mode == Mode.Files) {
                    return showWindowsFileChooser(parent, action);
                } else if (mode == Mode.Directories) {
                    return showWindowsFolderBrowser(parent);
                }
            }
        }

        // fallback to Swing
        return showSwingFileChooser(parent, action);
    }

    private boolean showSwingFileChooser(Window parent, Action action) {
        final JFileChooser fc = new JFileChooser(currentDirectory);
        fc.setMultiSelectionEnabled(multiSelectionEnabled);
        fc.setFileSelectionMode(mode.getJFileChooserValue());

        // set select file
        if (!defaultFile.isEmpty() & action == Action.Save) {
            File fsel = new File(defaultFile);
            fc.setSelectedFile(fsel);
        }
        if (!dialogTitle.isEmpty()) {
            fc.setDialogTitle(dialogTitle);
        }
        if (action == Action.Open & !openButtonText.isEmpty()) {
            fc.setApproveButtonText(openButtonText);
        } else if (action == Action.Save & !saveButtonText.isEmpty()) {
            fc.setApproveButtonText(saveButtonText);
        }

        // build filters
        if (filters.size() > 0) {
            boolean useAcceptAllFilter = false;
            for (final String[] spec : filters) {
                // the "All Files" filter is handled specially by JFileChooser
                if (spec[1].equals("*")) {
                    useAcceptAllFilter = true;
                    continue;
                }
                fc.addChoosableFileFilter(new FileNameExtensionFilter(
                        spec[0], Arrays.copyOfRange(spec, 1, spec.length)));
            }
            fc.setAcceptAllFileFilterUsed(useAcceptAllFilter);
        }

        int result = -1;
        if (action == Action.Open) {
            result = fc.showOpenDialog(parent);
        } else {
            if (saveButtonText.isEmpty()) {
                result = fc.showSaveDialog(parent);
            } else {
                result = fc.showDialog(parent, null);
            }
        }
        if (result == JFileChooser.APPROVE_OPTION) {
            selectedFiles = multiSelectionEnabled
                    ? fc.getSelectedFiles() : new File[]{fc.getSelectedFile()};
            currentDirectory = fc.getCurrentDirectory();
            return true;
        }

        return false;
    }

    private boolean showWindowsFileChooser(Window parent, Action action) {
        final WindowsFileChooser fc = new WindowsFileChooser(currentDirectory);
        fc.setFilters(filters);

        if (!defaultFile.isEmpty()) {
            fc.setDefaultFilename(defaultFile);
        }

        if (!dialogTitle.isEmpty()) {
            fc.setTitle(dialogTitle);
        }

        final boolean result = fc.showDialog(parent, action == Action.Open);
        if (result) {
            selectedFiles = new File[]{fc.getSelectedFile()};
            currentDirectory = fc.getCurrentDirectory();
        }
        return result;
    }

    private boolean showWindowsFolderBrowser(Window parent) {
        final WindowsFolderBrowser fb = new WindowsFolderBrowser();
        if (!dialogTitle.isEmpty()) {
            fb.setTitle(dialogTitle);
        }
        final File file = fb.showDialog(parent);
        if (file != null) {
            selectedFiles = new File[]{file};
            currentDirectory = file.getParentFile() != null
                    ? file.getParentFile() : file;
            return true;
        }

        return false;
    }

    /**
     * add a filter to the user-selectable list of file filters
     *
     * @param name name of the filter
     * @param filter you must pass at least 1 argument, the arguments are the
     * file extensions.
     */
    public void addFilter(String name, String... filter) {
        if (filter.length < 1) {
            throw new IllegalArgumentException();
        }
        ArrayList parts = new ArrayList();
        parts.add(name);
        Collections.addAll(parts, filter);
        filters.add(parts.toArray(new String[parts.size()]));
    }

    /**
     * sets the selection mode
     *
     * @param mode the selection mode
     */
    public void setMode(Mode mode) {
        this.mode = mode;
    }

    public Mode getMode() {
        return mode;
    }

    public void setCurrentDirectory(String currentDirectoryPath) {
        this.currentDirectory = (currentDirectoryPath != null ? new File(currentDirectoryPath) : null);
    }

    /**
     * sets whether to enable multiselection
     *
     * @param enabled true to enable multiselection, false to disable it
     */
    public void setMultiSelectionEnabled(boolean enabled) {
        this.multiSelectionEnabled = enabled;
    }

    public boolean isMultiSelectionEnabled() {
        return multiSelectionEnabled;
    }

    public void setDefaultFileName(String dfile) {
        this.defaultFile = dfile;
    }

    /**
     * set a title name
     *
     * @param title of dialog
     *
     */
    public void setTitle(String title) {
        this.dialogTitle = title;
    }

    /**
     * set a open button name
     *
     * @param buttonText button text
     *
     */
    public void setOpenButtonText(String buttonText) {
        this.openButtonText = buttonText;
    }

    /**
     * set a save button name
     *
     * @param buttonText button text
     *
     */
    public void setSaveButtonText(String buttonText) {
        this.saveButtonText = buttonText;
    }

    public File[] getSelectedFiles() {
        return selectedFiles;
    }

    public File getSelectedFile() {
        return selectedFiles[0];
    }

    public File getCurrentDirectory() {
        return currentDirectory;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy