Java tutorial
/* * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javafx.stage; import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.List; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import com.sun.glass.ui.CommonDialogs; import com.sun.glass.ui.CommonDialogs.FileChooserResult; import com.sun.javafx.tk.FileChooserType; import com.sun.javafx.tk.Toolkit; /** * Provides support for standard platform file dialogs. These dialogs have look * and feel of the platform UI components which is independent of JavaFX. * <p> * On some platforms where file access may be restricted or not part of the user * model (for example, on some mobile or embedded devices), opening a file * dialog may always result in a no-op (that is, null file(s) being returned). * </p> * <p> * A {@code FileChooser} can be used to invoke file open dialogs for selecting * single file ({@code showOpenDialog}), file open dialogs for selecting * multiple files ({@code showOpenMultipleDialog}) and file save dialogs * ({@code showSaveDialog}). The configuration of the displayed dialog is * controlled by the values of the {@code FileChooser} properties set before the * corresponding {@code show*Dialog} method is called. This configuration * includes the dialog's title, the initial directory displayed in the dialog * and the extension filter(s) for the listed files. For configuration * properties which values haven't been set explicitly, the displayed dialog * uses their platform default values. A call to a show dialog method is * blocked until the user makes a choice or cancels the dialog. The return * value specifies the selected file(s) or equals to {@code null} if the dialog * has been canceled. * </p> * <p> * Example: * <pre>{@code * FileChooser fileChooser = new FileChooser(); * fileChooser.setTitle("Open Resource File"); * fileChooser.getExtensionFilters().addAll( * new ExtensionFilter("Text Files", "*.txt"), * new ExtensionFilter("Image Files", "*.png", "*.jpg", "*.gif"), * new ExtensionFilter("Audio Files", "*.wav", "*.mp3", "*.aac"), * new ExtensionFilter("All Files", "*.*")); * File selectedFile = fileChooser.showOpenDialog(mainStage); * if (selectedFile != null) { * mainStage.display(selectedFile); * } * }</pre> * * @since JavaFX 2.0 */ public final class FileChooser { /** * Defines an extension filter, used for filtering which files can be chosen * in a FileDialog based on the file name extensions. * @since JavaFX 2.0 */ public static final class ExtensionFilter { private final String description; private final List<String> extensions; /** * Creates an {@code ExtensionFilter} with the specified description * and the file name extensions. * <p> * File name extension should be specified in the {@code *.<extension>} * format. * * @param description the textual description for the filter * @param extensions the accepted file name extensions * @throws NullPointerException if the description or the extensions * are {@code null} * @throws IllegalArgumentException if the description or the extensions * are empty */ public ExtensionFilter(final String description, final String... extensions) { validateArgs(description, extensions); this.description = description; this.extensions = Collections.unmodifiableList(Arrays.asList(extensions.clone())); } /** * Creates an {@code ExtensionFilter} with the specified description * and the file name extensions. * <p> * File name extension should be specified in the {@code *.<extension>} * format. * * @param description the textual description for the filter * @param extensions the accepted file name extensions * @throws NullPointerException if the description or the extensions * are {@code null} * @throws IllegalArgumentException if the description or the extensions * are empty */ public ExtensionFilter(final String description, final List<String> extensions) { final String[] extensionsArray = (extensions != null) ? extensions.toArray(new String[extensions.size()]) : null; validateArgs(description, extensionsArray); this.description = description; this.extensions = Collections.unmodifiableList(Arrays.asList(extensionsArray)); } /** * Gets the description for this {@code ExtensionFilter}. * * @return the description */ public String getDescription() { return description; } /** * Gets the file name extensions for this {@code ExtensionFilter}. * <p> * The returned list is unmodifiable and will throw * {@code UnsupportedOperationException} on each modification attempt. * * @return the file name extensions */ public List<String> getExtensions() { return extensions; } private static void validateArgs(final String description, final String[] extensions) { if (description == null) { throw new NullPointerException("Description must not be null"); } if (description.isEmpty()) { throw new IllegalArgumentException("Description must not be empty"); } if (extensions == null) { throw new NullPointerException("Extensions must not be null"); } if (extensions.length == 0) { throw new IllegalArgumentException("At least one extension must be defined"); } for (String extension : extensions) { if (extension == null) { throw new NullPointerException("Extension must not be null"); } if (extension.isEmpty()) { throw new IllegalArgumentException("Extension must not be empty"); } } } } /** * The title of the displayed file dialog. */ private StringProperty title; public final void setTitle(final String value) { titleProperty().set(value); } public final String getTitle() { return (title != null) ? title.get() : null; } public final StringProperty titleProperty() { if (title == null) { title = new SimpleStringProperty(this, "title"); } return title; } /** * The initial directory for the displayed file dialog. */ private ObjectProperty<File> initialDirectory; public final void setInitialDirectory(final File value) { initialDirectoryProperty().set(value); } public final File getInitialDirectory() { return (initialDirectory != null) ? initialDirectory.get() : null; } public final ObjectProperty<File> initialDirectoryProperty() { if (initialDirectory == null) { initialDirectory = new SimpleObjectProperty<File>(this, "initialDirectory"); } return initialDirectory; } /** * The initial file name for the displayed dialog. * <p> * This property is used mostly in the displayed file save dialogs as the * initial file name for the file being saved. If set for a file open * dialog it will have any impact on the displayed dialog only if the * corresponding platform provides support for such property in its * file open dialogs. * </p> * * @since JavaFX 2.2.40 */ private ObjectProperty<String> initialFileName; public final void setInitialFileName(final String value) { initialFileNameProperty().set(value); } public final String getInitialFileName() { return (initialFileName != null) ? initialFileName.get() : null; } public final ObjectProperty<String> initialFileNameProperty() { if (initialFileName == null) { initialFileName = new SimpleObjectProperty<String>(this, "initialFileName"); } return initialFileName; } /** * Specifies the extension filters used in the displayed file dialog. */ private ObservableList<ExtensionFilter> extensionFilters = FXCollections.<ExtensionFilter>observableArrayList(); /** * Gets the extension filters used in the displayed file dialog. Only * one extension filter from the list is active at any time in the displayed * dialog and only files which correspond to this extension filter are * shown. The first extension filter from the list is activated when the * dialog is invoked. Then the user can switch the active extension filter * to any other extension filter from the list and in this way control the * set of displayed files. * * @return An observable list of the extension filters used in this dialog */ public ObservableList<ExtensionFilter> getExtensionFilters() { return extensionFilters; } /** * This property is used to pre-select the extension filter for the next * displayed dialog and to read the user-selected extension filter from the * dismissed dialog. * <p> * When the file dialog is shown, the selectedExtensionFilter will be checked. * If the value of selectedExtensionFilter is null or is not contained in * the list of extension filters, then the first extension filter in the list * of extension filters will be selected instead. Otherwise, the specified * selectedExtensionFilter will be activated. * <p> * After the dialog is dismissed the value of this property is updated to * match the user-selected extension filter from the dialog. * * @since JavaFX 8.0 */ private ObjectProperty<ExtensionFilter> selectedExtensionFilter; public final ObjectProperty<ExtensionFilter> selectedExtensionFilterProperty() { if (selectedExtensionFilter == null) { selectedExtensionFilter = new SimpleObjectProperty<ExtensionFilter>(this, "selectedExtensionFilter"); } return selectedExtensionFilter; } public final void setSelectedExtensionFilter(ExtensionFilter filter) { selectedExtensionFilterProperty().setValue(filter); } public final ExtensionFilter getSelectedExtensionFilter() { return (selectedExtensionFilter != null) ? selectedExtensionFilter.get() : null; } /** * Shows a new file open dialog. The method doesn't return until the * displayed open dialog is dismissed. The return value specifies * the file chosen by the user or {@code null} if no selection has been * made. 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. * * @param ownerWindow the owner window of the displayed file dialog * @return the selected file or {@code null} if no file has been selected */ public File showOpenDialog(final Window ownerWindow) { final List<File> selectedFiles = showDialog(ownerWindow, FileChooserType.OPEN); return ((selectedFiles != null) && (selectedFiles.size() > 0)) ? selectedFiles.get(0) : null; } /** * Shows a new file open dialog in which multiple files can be selected. * The method doesn't return until the displayed open dialog is dismissed. * The return value specifies the files chosen by the user or {@code null} * if no selection has been made. 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. * <p> * The returned list is unmodifiable and will throw * {@code UnsupportedOperationException} on each modification attempt. * * @param ownerWindow the owner window of the displayed file dialog * @return the selected files or {@code null} if no file has been selected */ public List<File> showOpenMultipleDialog(final Window ownerWindow) { final List<File> selectedFiles = showDialog(ownerWindow, FileChooserType.OPEN_MULTIPLE); return ((selectedFiles != null) && (selectedFiles.size() > 0)) ? Collections.unmodifiableList(selectedFiles) : null; } /** * Shows a new file save dialog. The method doesn't return until the * displayed file save dialog is dismissed. The return value specifies the * file chosen by the user or {@code null} if no selection has been made. * 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. * * @param ownerWindow the owner window of the displayed file dialog * @return the selected file or {@code null} if no file has been selected */ public File showSaveDialog(final Window ownerWindow) { final List<File> selectedFiles = showDialog(ownerWindow, FileChooserType.SAVE); return ((selectedFiles != null) && (selectedFiles.size() > 0)) ? selectedFiles.get(0) : null; } private ExtensionFilter findSelectedFilter(CommonDialogs.ExtensionFilter filter) { if (filter != null) { String description = filter.getDescription(); List<String> extensions = filter.getExtensions(); for (ExtensionFilter ef : extensionFilters) { if (description.equals(ef.getDescription()) && extensions.equals(ef.getExtensions())) { return ef; } } } return null; } private List<File> showDialog(final Window ownerWindow, final FileChooserType fileChooserType) { FileChooserResult result = Toolkit.getToolkit().showFileChooser( (ownerWindow != null) ? ownerWindow.getPeer() : null, getTitle(), getInitialDirectory(), getInitialFileName(), fileChooserType, extensionFilters, getSelectedExtensionFilter()); if (result == null) { return null; } List<File> files = result.getFiles(); if (files != null && files.size() > 0) { selectedExtensionFilterProperty().set(findSelectedFilter(result.getExtensionFilter())); } return files; } }