VASSAL.tools.filechooser.FileChooser.java Source code

Java tutorial

Introduction

Here is the source code for VASSAL.tools.filechooser.FileChooser.java

Source

/*
 * $Id$
 *
 * Copyright (c) 2006-2009 by Joel Uckelman
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License (LGPL) as published by the Free Software Foundation.
 *
 * This library 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.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, copies are available
 * at http://www.opensource.org.
 */
package VASSAL.tools.filechooser;

import java.awt.Component;
import java.awt.Dialog;
import java.awt.FileDialog;
import java.awt.Frame;
import java.io.File;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import org.apache.commons.lang.SystemUtils;

import VASSAL.configure.DirectoryConfigurer;

/**
 * FileChooser provides a wrapper for {@link javax.swing.JFileChooser} and
 * {@link java.awt.FileDialog}, selecting whichever is preferred on the
 * user's OS. <code>FileChooser</code>'s methods mirror those of
 * <code>JFileChooser</code>.
 *
 * @author Joel Uckelman
 */
public abstract class FileChooser {
    protected Component parent;
    protected DirectoryConfigurer prefs;
    public final static int APPROVE_OPTION = JFileChooser.APPROVE_OPTION;
    public final static int CANCEL_OPTION = JFileChooser.CANCEL_OPTION;
    public final static int ERROR_OPTION = JFileChooser.ERROR_OPTION;
    public final static int FILES_ONLY = JFileChooser.FILES_ONLY;
    public final static int DIRECTORIES_ONLY = JFileChooser.DIRECTORIES_ONLY;

    protected FileChooser(Component parent, DirectoryConfigurer pref) {
        this.parent = parent;
        this.prefs = pref;
    }

    public static FileChooser createFileChooser(Component parent) {
        return createFileChooser(parent, null);
    }

    public static FileChooser createFileChooser(Component parent, DirectoryConfigurer prefs) {
        return createFileChooser(parent, prefs, FILES_ONLY);
    }

    /**
     * Creates a FileChooser appropriate for the user's OS.
     *
     * @param parent
     *          The Component over which the FileChooser should appear.
     * @param prefs
     *          A FileConfigure that stores the preferred starting directory of the FileChooser in preferences
     */
    public static FileChooser createFileChooser(Component parent, DirectoryConfigurer prefs, int mode) {
        FileChooser fc;
        if (SystemUtils.IS_OS_MAC_OSX) {
            // Mac has a good native file dialog
            fc = new NativeFileChooser(parent, prefs, mode);
        } else if (mode == FILES_ONLY && SystemUtils.IS_OS_WINDOWS) {
            // Window has a good native file dialog, but it doesn't support selecting directories
            fc = new NativeFileChooser(parent, prefs, mode);
        } else {
            // Linux's native dialog is inferior to Swing's
            fc = new SwingFileChooser(parent, prefs, mode);
        }
        return fc;
    }

    public abstract File getCurrentDirectory();

    public abstract void setCurrentDirectory(File dir);

    public abstract void rescanCurrentDirectory();

    public abstract File getSelectedFile();

    public abstract void setSelectedFile(File file);

    public abstract String getDialogTitle();

    public abstract void setDialogTitle(String title);

    public abstract int showOpenDialog(Component parent);

    public abstract int showSaveDialog(Component parent);

    public abstract FileFilter getFileFilter();

    public abstract void setFileFilter(FileFilter filter);

    public abstract void addChoosableFileFilter(FileFilter filter);

    public abstract boolean removeChoosableFileFilter(FileFilter filter);

    public abstract void resetChoosableFileFilters();

    /**
     * Selects <tt>filename.sav</tt> if <tt>filename.foo</tt> is selected.
     */
    public void selectDotSavFile() {
        File file = getSelectedFile();
        if (file != null) {
            String name = file.getPath();
            if (name != null) {
                int index = name.lastIndexOf('.');
                if (index > 0) {
                    name = name.substring(0, index) + ".vsav";
                    setSelectedFile(new File(name));
                }
            }
        }
    }

    /**
     * Same as {@link #showOpenDialog(Component)}, but uses the <tt>parent</tt> set on creation of this FileDialog.
     */
    public int showOpenDialog() {
        return showOpenDialog(parent);
    }

    /**
     * Same as {@link #showSaveDialog(Component)}, but uses the <tt>parent</tt> set on creation of this FileDialog.
     */
    public int showSaveDialog() {
        return showSaveDialog(parent);
    }

    protected void updateDirectoryPreference() {
        if (prefs != null && getCurrentDirectory() != null && !getCurrentDirectory().equals(prefs.getFileValue())) {
            prefs.setValue(getCurrentDirectory());
        }
    }

    private static class SwingFileChooser extends FileChooser {
        private JFileChooser fc = new JFileChooser();

        public SwingFileChooser(Component parent, DirectoryConfigurer prefs, int mode) {
            super(parent, prefs);
            if (prefs != null && prefs.getFileValue() != null) {
                setCurrentDirectory(prefs.getFileValue());
            }
            if (mode == DIRECTORIES_ONLY) {
                setFileFilter(new DirectoryFileFilter());
            }
            fc.setFileSelectionMode(mode);
        }

        public File getCurrentDirectory() {
            return fc.getCurrentDirectory();
        }

        public void setCurrentDirectory(File dir) {
            fc.setCurrentDirectory(dir);
        }

        public void rescanCurrentDirectory() {
            fc.rescanCurrentDirectory();
        }

        public File getSelectedFile() {
            return fc.getSelectedFile();
        }

        public void setSelectedFile(File file) {
            fc.setSelectedFile(file);
        }

        public int getFileSelectionMode() {
            return fc.getFileSelectionMode();
        }

        public void setFileSelectionMode(int mode) {
            fc.setFileSelectionMode(mode);
        }

        public String getDialogTitle() {
            return fc.getDialogTitle();
        }

        public void setDialogTitle(String title) {
            fc.setDialogTitle(title);
        }

        public int showOpenDialog(Component parent) {
            int value = fc.showOpenDialog(parent);
            updateDirectoryPreference();
            return value;
        }

        public int showSaveDialog(Component parent) {
            int value = fc.showSaveDialog(parent);
            if (value == APPROVE_OPTION && getSelectedFile().exists()
                    && JOptionPane.NO_OPTION == JOptionPane.showConfirmDialog(parent,
                            "Overwrite " + getSelectedFile().getName() + "?", "File Exists",
                            JOptionPane.YES_NO_OPTION)) {
                value = CANCEL_OPTION;
            }
            updateDirectoryPreference();
            return value;
        }

        public FileFilter getFileFilter() {
            javax.swing.filechooser.FileFilter ff = fc.getFileFilter();
            return ff instanceof FileFilter ? (FileFilter) ff : null;
        }

        public void setFileFilter(FileFilter filter) {
            fc.setFileFilter(filter);
        }

        public void addChoosableFileFilter(FileFilter filter) {
            fc.addChoosableFileFilter(filter);
        }

        public boolean removeChoosableFileFilter(FileFilter filter) {
            return fc.removeChoosableFileFilter(filter);
        }

        public void resetChoosableFileFilters() {
            fc.resetChoosableFileFilters();
        }
    }

    private static class NativeFileChooser extends FileChooser {
        private File cur;
        private String title;
        private FileFilter filter;
        private int mode = FILES_ONLY;

        public NativeFileChooser(Component parent, DirectoryConfigurer prefs, int mode) {
            super(parent, prefs);

            if (prefs != null && prefs.getFileValue() != null) {
                setCurrentDirectory(prefs.getFileValue());
            }

            this.mode = mode;

            if (mode == DIRECTORIES_ONLY) {
                setFileFilter(new DirectoryFileFilter());
            }
        }

        public File getCurrentDirectory() {
            return cur == null ? null : cur.getParentFile();
        }

        public void setCurrentDirectory(File dir) {
            cur = dir;
        }

        public void rescanCurrentDirectory() {
        }

        public File getSelectedFile() {
            return cur;
        }

        public void setSelectedFile(File file) {
            cur = file;
        }

        public int getFileSelectionMode() {
            return mode;
        }

        public void setFileSelectionMode(int mode) {
            this.mode = mode;
        }

        public String getDialogTitle() {
            return title;
        }

        public void setDialogTitle(String title) {
            this.title = title;
        }

        //
        // On Java 1.5, we cannot create parentless Dialogs. Instead, we make
        // a single global hidden Frame to be the parent of all such orphans.
        // This can be removed when we stop supporting Java 1.5.
        //
        protected static final boolean isJava15;
        protected static final Frame dummy;

        static {
            final String jvmver = System.getProperty("java.version");
            isJava15 = jvmver == null || jvmver.startsWith("1.5");
            dummy = isJava15 ? new Frame() : null;
        }

        protected FileDialog awt_file_dialog_init(Component parent) {
            final FileDialog fd;

            if (parent == null) {
                if (isJava15) {
                    // Parentless Dialogs throw IllegalArgumentException with Java 1.5.
                    fd = new FileDialog(dummy, title);
                } else {
                    fd = new FileDialog((Frame) null, title);
                }
            } else if (parent instanceof Dialog) {
                fd = new FileDialog((Dialog) parent, title);
            } else if (parent instanceof Frame) {
                fd = new FileDialog((Frame) parent, title);
            } else {
                final Dialog d = (Dialog) SwingUtilities.getAncestorOfClass(Dialog.class, parent);
                if (d != null) {
                    fd = new FileDialog(d, title);
                } else {
                    final Frame f = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, parent);
                    if (f != null) {
                        fd = new FileDialog(f, title);
                    } else {
                        // should be impossible, parent is not in a dialog or frame!
                        throw new IllegalArgumentException("parent is contained in neither a Dialog nor a Frame");
                    }
                }
            }

            fd.setModal(true);
            fd.setFilenameFilter(filter);
            if (cur != null) {
                if (cur.isDirectory())
                    fd.setDirectory(cur.getPath());
                else {
                    fd.setDirectory(cur.getParent());
                    fd.setFile(cur.getName());
                }
            }
            return fd;
        }

        public int showOpenDialog(Component parent) {
            final FileDialog fd = awt_file_dialog_init(parent);
            fd.setMode(FileDialog.LOAD);
            System.setProperty("apple.awt.fileDialogForDirectories", String.valueOf(mode == DIRECTORIES_ONLY));
            fd.setVisible(true);

            final int value;
            if (fd.getFile() != null) {
                cur = new File(fd.getDirectory(), fd.getFile());
                value = FileChooser.APPROVE_OPTION;
            } else {
                value = FileChooser.CANCEL_OPTION;
            }
            updateDirectoryPreference();
            return value;
        }

        public int showSaveDialog(Component parent) {
            final FileDialog fd = awt_file_dialog_init(parent);
            fd.setMode(FileDialog.SAVE);
            fd.setVisible(true);

            final int value;
            if (fd.getFile() != null) {
                cur = new File(fd.getDirectory(), fd.getFile());
                value = FileChooser.APPROVE_OPTION;
            } else {
                value = FileChooser.CANCEL_OPTION;
            }
            updateDirectoryPreference();
            return value;
        }

        public FileFilter getFileFilter() {
            return filter;
        }

        public void setFileFilter(FileFilter filter) {
            this.filter = filter;
        }

        public void addChoosableFileFilter(FileFilter filter) {
        }

        public boolean removeChoosableFileFilter(FileFilter filter) {
            return false;
        }

        public void resetChoosableFileFilters() {
        }
    }
}