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

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

There is a newer version: 6.70.10.2
Show newest version
/* 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 com.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 - 2025 Weber Informatics LLC | Privacy Policy