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

org.sellcom.javafx.stage.PathChooser Maven / Gradle / Ivy

/*
 * Copyright (c) 2015-2017 Petr Zelenka .
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sellcom.javafx.stage;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.sellcom.core.Contract;
import org.sellcom.core.Strings;
import org.sellcom.core.io.MorePaths;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Window;

/**
 * {@code FileChooser} equivalent handling {@code Path}s instead of {@code File}s.
 *
 * @since 1.0
 *
 * @see FileChooser
 */
public class PathChooser {

	private final FileChooser fileChooser = new FileChooser();

	private final ObjectProperty initialDirectoryProperty = new SimpleObjectProperty<>();


	/**
	 * Crates a new {@code PathChooser}.
	 *
	 * @since 1.0
	 */
	public PathChooser() {
		setupBindings();
	}


	/**
	 * Returns the extension filters of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public ObservableList getExtensionFilters() {
		return fileChooser.getExtensionFilters();
	}

	/**
	 * Returns the initial directory of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public Path getInitialDirectory() {
		return initialDirectoryProperty.get();
	}

	/**
	 * Returns the initial file name of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public String getInitialFileName() {
		return fileChooser.getInitialFileName();
	}

	/**
	 * Returns the selected extension filter of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public ExtensionFilter getSelectedExtensionFilter() {
		return fileChooser.getSelectedExtensionFilter();
	}

	/**
	 * Returns the title of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public String getTitle() {
		return fileChooser.getTitle();
	}

	/**
	 * Returns the property for the initial directory of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public ObjectProperty initialDirectoryProperty() {
		return initialDirectoryProperty;
	}

	/**
	 * Returns the property for the initial file name of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public ObjectProperty initialFileNameProperty() {
		return fileChooser.initialFileNameProperty();
	}

	/**
	 * Returns the property for the selected extension filter of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public ObjectProperty selectedExtensionFilterProperty() {
		return fileChooser.selectedExtensionFilterProperty();
	}

	/**
	 * Sets the initial directory of the displayed file dialog.
	 *
	 * @throws IllegalArgumentException if {@code directory} is {@code null}
	 *
	 * @since 1.0
	 */
	public void setInitialDirectory(Path directory) {
		Contract.checkArgument(directory != null, "Directory must not be null");

		initialDirectoryProperty.set(directory);
	}

	/**
	 * Sets the initial file name of the displayed file dialog.
	 *
	 * @throws IllegalArgumentException if {@code fileName} is {@code null} or empty
	 *
	 * @since 1.0
	 */
	public void setInitialFileName(String fileName) {
		Contract.checkArgument(!Strings.isNullOrEmpty(fileName), "File name must not be null or empty");

		fileChooser.setInitialFileName(fileName);
	}

	/**
	 * Sets the selected extension filter of the displayed file dialog.
	 *
	 * @throws IllegalArgumentException if {@code extensionFilter} is {@code null}
	 *
	 * @since 1.0
	 */
	public void setSelectedExtensionFilter(ExtensionFilter extensionFilter) {
		Contract.checkArgument(extensionFilter != null, "Extension filter must not be null");

		fileChooser.setSelectedExtensionFilter(extensionFilter);
	}

	/**
	 * Sets the title of the displayed file dialog.
	 *
	 * @throws IllegalArgumentException if {@code title} is {@code null} or empty
	 *
	 * @since 1.0
	 */
	public void setTitle(String title) {
		Contract.checkArgument(!Strings.isNullOrEmpty(title), "Title must not be null or empty");

		fileChooser.setTitle(title);
	}

	/**
	 * Shows a file open dialog.
	 * The method does not return until the displayed open dialog is dismissed.
	 * If the owner window for the file dialog is set, input to all windows in the dialog's owner chain is blocked while the file dialog is being shown.
	 *
	 * @since 1.0
	 */
	public Optional showOpenDialog(Window ownerWindow) {
		return Optional.ofNullable(fileChooser.showOpenDialog(ownerWindow))
				.map(File::toPath);
	}

	/**
	 * Shows a file open dialog in which multiple files can be selected.
	 * The method does not return until the displayed open dialog is dismissed.
	 * If the owner window for the file dialog is set, input to all windows in the dialog's owner chain is blocked while the file dialog is being shown.
	 *
	 * @since 1.0
	 */
	public List showOpenMultipleDialog(Window ownerWindow) {
		return fileChooser.showOpenMultipleDialog(ownerWindow).stream()
				.map(File::toPath)
				.collect(Collectors.toList());
	}

	/**
	 * Shows a file save dialog.
	 * The method does not return until the displayed open dialog is dismissed.
	 * If the owner window for the file dialog is set, input to all windows in the dialog's owner chain is blocked while the file dialog is being shown.
	 *
	 * @since 1.0
	 */
	public Optional showSaveDialog(Window ownerWindow) {
		Optional selectedFile = Optional.ofNullable(fileChooser.showSaveDialog(ownerWindow))
				.map(File::toPath);

		if (selectedFile.isPresent()) {
			List possibleExtensions = getSelectedExtensionFilter().getExtensions().stream()
					.filter(extension -> !Strings.endsWith(extension, ".*", false)) // Skip generic extension
					.collect(Collectors.toList());

			if (!possibleExtensions.isEmpty()) {
				String actualExtension = MorePaths.getFileExtension(selectedFile.get());
				Optional expectedExtension = possibleExtensions.stream()
						.map(extension -> extension.replace("*.", ""))
						.filter(extension -> extension.equalsIgnoreCase(actualExtension))
						.findFirst();

				if (!expectedExtension.isPresent()) { // Expected extension not found, append the first found
					String pathWithoutExtension = selectedFile.get().toString();
					String extension = possibleExtensions.get(0).replace("*.", "");

					selectedFile = Optional.of(Paths.get(pathWithoutExtension + "." + extension));
				}
			}
		}

		return selectedFile;
	}

	/**
	 * Returns the property for the title of the displayed file dialog.
	 *
	 * @since 1.0
	 */
	public StringProperty titleProperty() {
		return fileChooser.titleProperty();
	}


	private void setupBindings() {
		initialDirectoryProperty.addListener((observable, oldValue, newValue) -> {
			if (Files.isDirectory(newValue)) {
				fileChooser.setInitialDirectory(newValue.toAbsolutePath().toFile());
			}
		});
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy