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());
}
});
}
}