| /* | |
| * Copyright (c) 1995, 2023, 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 java.awt; | |
| import java.awt.peer.FileDialogPeer; | |
| import java.io.File; | |
| import java.io.FilenameFilter; | |
| import java.io.IOException; | |
| import java.io.ObjectInputStream; | |
| import java.io.Serial; | |
| import java.lang.annotation.Native; | |
| import sun.awt.AWTAccessor; | |
| /** | |
| * The {@code FileDialog} class displays a dialog window | |
| * from which the user can select a file. | |
| * <p> | |
| * Since it is a modal dialog, when the application calls | |
| * its {@code show} method to display the dialog, | |
| * it blocks the rest of the application until the user has | |
| * chosen a file. | |
| * | |
| * @see Window#show | |
| * | |
| * @author Sami Shaio | |
| * @author Arthur van Hoff | |
| * @since 1.0 | |
| */ | |
| public class FileDialog extends Dialog { | |
| /** | |
| * This constant value indicates that the purpose of the file | |
| * dialog window is to locate a file from which to read. | |
| */ | |
| @Native | |
| public static final int LOAD = 0; | |
| /** | |
| * This constant value indicates that the purpose of the file | |
| * dialog window is to locate a file to which to write. | |
| */ | |
| @Native | |
| public static final int SAVE = 1; | |
| /** | |
| * There are two {@code FileDialog} modes: {@code LOAD} and | |
| * {@code SAVE}. | |
| * This integer will represent one or the other. | |
| * If the mode is not specified it will default to {@code LOAD}. | |
| * | |
| * @serial | |
| * @see #getMode | |
| * @see #setMode | |
| * @see java.awt.FileDialog#LOAD | |
| * @see java.awt.FileDialog#SAVE | |
| */ | |
| int mode; | |
| /** | |
| * The string specifying the directory to display | |
| * in the file dialog. This variable may be {@code null}. | |
| * | |
| * @serial | |
| * @see #getDirectory | |
| * @see #setDirectory | |
| */ | |
| String dir; | |
| /** | |
| * The string specifying the initial value of the | |
| * filename text field in the file dialog. | |
| * This variable may be {@code null}. | |
| * | |
| * @serial | |
| * @see #getFile | |
| * @see #setFile | |
| */ | |
| String file; | |
| /** | |
| * Contains the File instances for all the files that the user selects. | |
| * | |
| * @serial | |
| * @see #getFiles | |
| * @since 1.7 | |
| */ | |
| private File[] files; | |
| /** | |
| * Represents whether the file dialog allows the multiple file selection. | |
| * | |
| * @serial | |
| * @see #setMultipleMode | |
| * @see #isMultipleMode | |
| * @since 1.7 | |
| */ | |
| private boolean multipleMode = false; | |
| /** | |
| * The filter used as the file dialog's filename filter. | |
| * The file dialog will only be displaying files whose | |
| * names are accepted by this filter. | |
| * This variable may be {@code null}. | |
| * | |
| * @serial | |
| * @see #getFilenameFilter | |
| * @see #setFilenameFilter | |
| * @see FilenameFilter | |
| */ | |
| @SuppressWarnings("serial") // Not statically typed as Serializable | |
| FilenameFilter filter; | |
| private static final String base = "filedlg"; | |
| private static int nameCounter = 0; | |
| /** | |
| * Use serialVersionUID from JDK 1.1 for interoperability. | |
| */ | |
| @Serial | |
| private static final long serialVersionUID = 5035145889651310422L; | |
| static { | |
| AWTAccessor.setFileDialogAccessor( | |
| new AWTAccessor.FileDialogAccessor() { | |
| public void setFiles(FileDialog fileDialog, File[] files) { | |
| fileDialog.setFiles(files); | |
| } | |
| public void setFile(FileDialog fileDialog, String file) { | |
| fileDialog.file = ("".equals(file)) ? null : file; | |
| } | |
| public void setDirectory(FileDialog fileDialog, String directory) { | |
| fileDialog.dir = ("".equals(directory)) ? null : directory; | |
| } | |
| public boolean isMultipleMode(FileDialog fileDialog) { | |
| synchronized (fileDialog.getObjectLock()) { | |
| return fileDialog.multipleMode; | |
| } | |
| } | |
| }); | |
| } | |
| /** | |
| * Creates a file dialog for loading a file. The title of the | |
| * file dialog is initially empty. This is a convenience method for | |
| * {@code FileDialog(parent, "", LOAD)}. | |
| * <p> | |
| * <strong>Note:</strong> Some platforms may not support | |
| * showing the user-specified title in a file dialog. | |
| * In this situation, either no title will be displayed in the file dialog's | |
| * title bar or, on some systems, the file dialog's title bar will not be | |
| * displayed. | |
| * | |
| * @param parent the owner of the dialog | |
| * @since 1.1 | |
| */ | |
| public FileDialog(Frame parent) { | |
| this(parent, "", LOAD); | |
| } | |
| /** | |
| * Creates a file dialog window with the specified title for loading | |
| * a file. The files shown are those in the current directory. | |
| * This is a convenience method for | |
| * {@code FileDialog(parent, title, LOAD)}. | |
| * <p> | |
| * <strong>Note:</strong> Some platforms may not support | |
| * showing the user-specified title in a file dialog. | |
| * In this situation, either no title will be displayed in the file dialog's | |
| * title bar or, on some systems, the file dialog's title bar will not be | |
| * displayed. | |
| * | |
| * @param parent the owner of the dialog | |
| * @param title the title of the dialog | |
| */ | |
| public FileDialog(Frame parent, String title) { | |
| this(parent, title, LOAD); | |
| } | |
| /** | |
| * Creates a file dialog window with the specified title for loading | |
| * or saving a file. | |
| * <p> | |
| * If the value of {@code mode} is {@code LOAD}, then the | |
| * file dialog is finding a file to read, and the files shown are those | |
| * in the current directory. If the value of | |
| * {@code mode} is {@code SAVE}, the file dialog is finding | |
| * a place to write a file. | |
| * <p> | |
| * <strong>Note:</strong> Some platforms may not support | |
| * showing the user-specified title in a file dialog. | |
| * In this situation, either no title will be displayed in the file dialog's | |
| * title bar or, on some systems, the file dialog's title bar will not be | |
| * displayed. | |
| * | |
| * @param parent the owner of the dialog | |
| * @param title the title of the dialog | |
| * @param mode the mode of the dialog; either | |
| * {@code FileDialog.LOAD} or {@code FileDialog.SAVE} | |
| * @throws IllegalArgumentException if an illegal file | |
| * dialog mode is supplied | |
| * @see java.awt.FileDialog#LOAD | |
| * @see java.awt.FileDialog#SAVE | |
| */ | |
| public FileDialog(Frame parent, String title, int mode) { | |
| super(parent, title, true); | |
| this.setMode(mode); | |
| setLayout(null); | |
| } | |
| /** | |
| * Creates a file dialog for loading a file. The title of the | |
| * file dialog is initially empty. This is a convenience method for | |
| * {@code FileDialog(parent, "", LOAD)}. | |
| * <p> | |
| * <strong>Note:</strong> Some platforms may not support | |
| * showing the user-specified title in a file dialog. | |
| * In this situation, either no title will be displayed in the file dialog's | |
| * title bar or, on some systems, the file dialog's title bar will not be | |
| * displayed. | |
| * | |
| * @param parent the owner of the dialog | |
| * @throws java.lang.IllegalArgumentException if the {@code parent}'s | |
| * {@code GraphicsConfiguration} | |
| * is not from a screen device; | |
| * @throws java.lang.IllegalArgumentException if {@code parent} | |
| * is {@code null}; this exception is always thrown when | |
| * {@code GraphicsEnvironment.isHeadless} | |
| * returns {@code true} | |
| * @see java.awt.GraphicsEnvironment#isHeadless | |
| * @since 1.5 | |
| */ | |
| public FileDialog(Dialog parent) { | |
| this(parent, "", LOAD); | |
| } | |
| /** | |
| * Creates a file dialog window with the specified title for loading | |
| * a file. The files shown are those in the current directory. | |
| * This is a convenience method for | |
| * {@code FileDialog(parent, title, LOAD)}. | |
| * <p> | |
| * <strong>Note:</strong> Some platforms may not support | |
| * showing the user-specified title in a file dialog. | |
| * In this situation, either no title will be displayed in the file dialog's | |
| * title bar or, on some systems, the file dialog's title bar will not be | |
| * displayed. | |
| * | |
| * @param parent the owner of the dialog | |
| * @param title the title of the dialog; a {@code null} value | |
| * will be accepted without causing a | |
| * {@code NullPointerException} to be thrown | |
| * @throws java.lang.IllegalArgumentException if the {@code parent}'s | |
| * {@code GraphicsConfiguration} | |
| * is not from a screen device; | |
| * @throws java.lang.IllegalArgumentException if {@code parent} | |
| * is {@code null}; this exception is always thrown when | |
| * {@code GraphicsEnvironment.isHeadless} | |
| * returns {@code true} | |
| * @see java.awt.GraphicsEnvironment#isHeadless | |
| * @since 1.5 | |
| */ | |
| public FileDialog(Dialog parent, String title) { | |
| this(parent, title, LOAD); | |
| } | |
| /** | |
| * Creates a file dialog window with the specified title for loading | |
| * or saving a file. | |
| * <p> | |
| * If the value of {@code mode} is {@code LOAD}, then the | |
| * file dialog is finding a file to read, and the files shown are those | |
| * in the current directory. If the value of | |
| * {@code mode} is {@code SAVE}, the file dialog is finding | |
| * a place to write a file. | |
| * <p> | |
| * <strong>Note:</strong> Some platforms may not support | |
| * showing the user-specified title in a file dialog. | |
| * In this situation, either no title will be displayed in the file dialog's | |
| * title bar or, on some systems, the file dialog's title bar will not be | |
| * displayed. | |
| * | |
| * @param parent the owner of the dialog | |
| * @param title the title of the dialog; a {@code null} value | |
| * will be accepted without causing a | |
| * {@code NullPointerException} to be thrown | |
| * @param mode the mode of the dialog; either | |
| * {@code FileDialog.LOAD} or {@code FileDialog.SAVE} | |
| * @throws java.lang.IllegalArgumentException if an illegal | |
| * file dialog mode is supplied; | |
| * @throws java.lang.IllegalArgumentException if the {@code parent}'s | |
| * {@code GraphicsConfiguration} | |
| * is not from a screen device; | |
| * @throws java.lang.IllegalArgumentException if {@code parent} | |
| * is {@code null}; this exception is always thrown when | |
| * {@code GraphicsEnvironment.isHeadless} | |
| * returns {@code true} | |
| * @see java.awt.GraphicsEnvironment#isHeadless | |
| * @see java.awt.FileDialog#LOAD | |
| * @see java.awt.FileDialog#SAVE | |
| * @since 1.5 | |
| */ | |
| public FileDialog(Dialog parent, String title, int mode) { | |
| super(parent, title, true); | |
| this.setMode(mode); | |
| setLayout(null); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * <p> | |
| * <strong>Note:</strong> Some platforms may not support | |
| * showing the user-specified title in a file dialog. | |
| * In this situation, either no title will be displayed in the file dialog's | |
| * title bar or, on some systems, the file dialog's title bar will not be | |
| * displayed. | |
| */ | |
| @Override | |
| public void setTitle(String title) { | |
| super.setTitle(title); | |
| } | |
| /** | |
| * Constructs a name for this component. Called by {@code getName()} | |
| * when the name is {@code null}. | |
| */ | |
| String constructComponentName() { | |
| synchronized (FileDialog.class) { | |
| return base + nameCounter++; | |
| } | |
| } | |
| /** | |
| * Creates the file dialog's peer. The peer allows us to change the look | |
| * of the file dialog without changing its functionality. | |
| */ | |
| public void addNotify() { | |
| synchronized(getTreeLock()) { | |
| if (parent != null && parent.peer == null) { | |
| parent.addNotify(); | |
| } | |
| if (peer == null) | |
| peer = getComponentFactory().createFileDialog(this); | |
| super.addNotify(); | |
| } | |
| } | |
| /** | |
| * Indicates whether this file dialog box is for loading from a file | |
| * or for saving to a file. | |
| * | |
| * @return the mode of this file dialog window, either | |
| * {@code FileDialog.LOAD} or | |
| * {@code FileDialog.SAVE} | |
| * @see java.awt.FileDialog#LOAD | |
| * @see java.awt.FileDialog#SAVE | |
| * @see java.awt.FileDialog#setMode | |
| */ | |
| public int getMode() { | |
| return mode; | |
| } | |
| /** | |
| * Sets the mode of the file dialog. If {@code mode} is not | |
| * a legal value, an exception will be thrown and {@code mode} | |
| * will not be set. | |
| * | |
| * @param mode the mode for this file dialog, either | |
| * {@code FileDialog.LOAD} or | |
| * {@code FileDialog.SAVE} | |
| * @see java.awt.FileDialog#LOAD | |
| * @see java.awt.FileDialog#SAVE | |
| * @see java.awt.FileDialog#getMode | |
| * @throws IllegalArgumentException if an illegal file | |
| * dialog mode is supplied | |
| * @since 1.1 | |
| */ | |
| public void setMode(int mode) { | |
| switch (mode) { | |
| case LOAD: | |
| case SAVE: | |
| this.mode = mode; | |
| break; | |
| default: | |
| throw new IllegalArgumentException("illegal file dialog mode"); | |
| } | |
| } | |
| /** | |
| * Gets the directory of this file dialog. | |
| * | |
| * @return the (potentially {@code null} or invalid) | |
| * directory of this {@code FileDialog} | |
| * @see java.awt.FileDialog#setDirectory | |
| */ | |
| public String getDirectory() { | |
| return dir; | |
| } | |
| /** | |
| * Sets the directory of this file dialog window to be the | |
| * specified directory. Specifying a {@code null} or an | |
| * invalid directory implies an implementation-defined default. | |
| * This default will not be realized, however, until the user | |
| * has selected a file. Until this point, {@code getDirectory()} | |
| * will return the value passed into this method. | |
| * <p> | |
| * Specifying "" as the directory is exactly equivalent to | |
| * specifying {@code null} as the directory. | |
| * | |
| * @param dir the specified directory | |
| * @see java.awt.FileDialog#getDirectory | |
| */ | |
| public void setDirectory(String dir) { | |
| this.dir = (dir != null && dir.isEmpty()) ? null : dir; | |
| FileDialogPeer peer = (FileDialogPeer)this.peer; | |
| if (peer != null) { | |
| peer.setDirectory(this.dir); | |
| } | |
| } | |
| /** | |
| * Gets the selected file of this file dialog. If the user | |
| * selected {@code CANCEL}, the returned file is {@code null}. | |
| * | |
| * @return the currently selected file of this file dialog window, | |
| * or {@code null} if none is selected | |
| * @see java.awt.FileDialog#setFile | |
| */ | |
| public String getFile() { | |
| return file; | |
| } | |
| /** | |
| * Returns files that the user selects. | |
| * <p> | |
| * If the user cancels the file dialog, | |
| * then the method returns an empty array. | |
| * | |
| * @return files that the user selects or an empty array | |
| * if the user cancels the file dialog. | |
| * @see #setFile(String) | |
| * @see #getFile | |
| * @since 1.7 | |
| */ | |
| public File[] getFiles() { | |
| synchronized (getObjectLock()) { | |
| if (files != null) { | |
| return files.clone(); | |
| } else { | |
| return new File[0]; | |
| } | |
| } | |
| } | |
| /** | |
| * Stores the names of all the files that the user selects. | |
| * | |
| * Note that the method is private and it's intended to be used | |
| * by the peers through the AWTAccessor API. | |
| * | |
| * @param files the array that contains the short names of | |
| * all the files that the user selects. | |
| * | |
| * @see #getFiles | |
| * @since 1.7 | |
| */ | |
| private void setFiles(File[] files) { | |
| synchronized (getObjectLock()) { | |
| this.files = files; | |
| } | |
| } | |
| /** | |
| * Sets the selected file for this file dialog window to be the | |
| * specified file. This file becomes the default file if it is set | |
| * before the file dialog window is first shown. | |
| * <p> | |
| * When the dialog is shown, the specified file is selected. The kind of | |
| * selection depends on the file existence, the dialog type, and the native | |
| * platform. E.g., the file could be highlighted in the file list, or a | |
| * file name editbox could be populated with the file name. | |
| * <p> | |
| * This method accepts either a full file path, or a file name with an | |
| * extension if used together with the {@code setDirectory} method. | |
| * <p> | |
| * Specifying "" as the file is exactly equivalent to specifying | |
| * {@code null} as the file. | |
| * | |
| * @param file the file being set | |
| * @see #getFile | |
| * @see #getFiles | |
| */ | |
| public void setFile(String file) { | |
| this.file = (file != null && file.isEmpty()) ? null : file; | |
| FileDialogPeer peer = (FileDialogPeer)this.peer; | |
| if (peer != null) { | |
| peer.setFile(this.file); | |
| } | |
| } | |
| /** | |
| * Enables or disables multiple file selection for the file dialog. | |
| * | |
| * @param enable if {@code true}, multiple file selection is enabled; | |
| * {@code false} - disabled. | |
| * @see #isMultipleMode | |
| * @since 1.7 | |
| */ | |
| public void setMultipleMode(boolean enable) { | |
| synchronized (getObjectLock()) { | |
| this.multipleMode = enable; | |
| } | |
| } | |
| /** | |
| * Returns whether the file dialog allows the multiple file selection. | |
| * | |
| * @return {@code true} if the file dialog allows the multiple | |
| * file selection; {@code false} otherwise. | |
| * @see #setMultipleMode | |
| * @since 1.7 | |
| */ | |
| public boolean isMultipleMode() { | |
| synchronized (getObjectLock()) { | |
| return multipleMode; | |
| } | |
| } | |
| /** | |
| * Determines this file dialog's filename filter. A filename filter | |
| * allows the user to specify which files appear in the file dialog | |
| * window. Filename filters do not function in Sun's reference | |
| * implementation for Microsoft Windows. | |
| * | |
| * @return this file dialog's filename filter | |
| * @see java.io.FilenameFilter | |
| * @see java.awt.FileDialog#setFilenameFilter | |
| */ | |
| public FilenameFilter getFilenameFilter() { | |
| return filter; | |
| } | |
| /** | |
| * Sets the filename filter for this file dialog window to the | |
| * specified filter. | |
| * Filename filters do not function in Sun's reference | |
| * implementation for Microsoft Windows. | |
| * | |
| * @param filter the specified filter | |
| * @see java.io.FilenameFilter | |
| * @see java.awt.FileDialog#getFilenameFilter | |
| */ | |
| public synchronized void setFilenameFilter(FilenameFilter filter) { | |
| this.filter = filter; | |
| FileDialogPeer peer = (FileDialogPeer)this.peer; | |
| if (peer != null) { | |
| peer.setFilenameFilter(filter); | |
| } | |
| } | |
| /** | |
| * Reads the {@code ObjectInputStream} and performs | |
| * a backwards compatibility check by converting | |
| * either a {@code dir} or a {@code file} | |
| * equal to an empty string to {@code null}. | |
| * | |
| * @param s the {@code ObjectInputStream} to read | |
| * @throws ClassNotFoundException if the class of a serialized object could | |
| * not be found | |
| * @throws IOException if an I/O error occurs | |
| */ | |
| @Serial | |
| private void readObject(ObjectInputStream s) | |
| throws ClassNotFoundException, IOException | |
| { | |
| s.defaultReadObject(); | |
| // 1.1 Compatibility: "" is not converted to null in 1.1 | |
| if (dir != null && dir.isEmpty()) { | |
| dir = null; | |
| } | |
| if (file != null && file.isEmpty()) { | |
| file = null; | |
| } | |
| } | |
| /** | |
| * Returns a string representing the state of this {@code FileDialog} | |
| * window. This method is intended to be used only for debugging purposes, | |
| * and the content and format of the returned string may vary between | |
| * implementations. The returned string may be empty but may not be | |
| * {@code null}. | |
| * | |
| * @return the parameter string of this file dialog window | |
| */ | |
| protected String paramString() { | |
| String str = super.paramString(); | |
| str += ",dir= " + dir; | |
| str += ",file= " + file; | |
| return str + ((mode == LOAD) ? ",load" : ",save"); | |
| } | |
| boolean postsOldMouseEvents() { | |
| return false; | |
| } | |
| } |