View Javadoc
1   /*
2    * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  package java.awt;
26  
27  import java.awt.peer.FileDialogPeer;
28  import java.io.FilenameFilter;
29  import java.io.IOException;
30  import java.io.ObjectInputStream;
31  import java.io.File;
32  import sun.awt.AWTAccessor;
33  
34  /**
35   * The <code>FileDialog</code> class displays a dialog window
36   * from which the user can select a file.
37   * <p>
38   * Since it is a modal dialog, when the application calls
39   * its <code>show</code> method to display the dialog,
40   * it blocks the rest of the application until the user has
41   * chosen a file.
42   *
43   * @see Window#show
44   *
45   * @author      Sami Shaio
46   * @author      Arthur van Hoff
47   * @since       JDK1.0
48   */
49  public class FileDialog extends Dialog {
50  
51      /**
52       * This constant value indicates that the purpose of the file
53       * dialog window is to locate a file from which to read.
54       */
55      public static final int LOAD = 0;
56  
57      /**
58       * This constant value indicates that the purpose of the file
59       * dialog window is to locate a file to which to write.
60       */
61      public static final int SAVE = 1;
62  
63      /*
64       * There are two <code>FileDialog</code> modes: <code>LOAD</code> and
65       * <code>SAVE</code>.
66       * This integer will represent one or the other.
67       * If the mode is not specified it will default to <code>LOAD</code>.
68       *
69       * @serial
70       * @see getMode()
71       * @see setMode()
72       * @see java.awt.FileDialog#LOAD
73       * @see java.awt.FileDialog#SAVE
74       */
75      int mode;
76  
77      /*
78       * The string specifying the directory to display
79       * in the file dialog.  This variable may be <code>null</code>.
80       *
81       * @serial
82       * @see getDirectory()
83       * @see setDirectory()
84       */
85      String dir;
86  
87      /*
88       * The string specifying the initial value of the
89       * filename text field in the file dialog.
90       * This variable may be <code>null</code>.
91       *
92       * @serial
93       * @see getFile()
94       * @see setFile()
95       */
96      String file;
97  
98      /**
99       * Contains the File instances for all the files that the user selects.
100      *
101      * @serial
102      * @see #getFiles
103      * @since 1.7
104      */
105     private File[] files;
106 
107     /**
108      * Represents whether the file dialog allows the multiple file selection.
109      *
110      * @serial
111      * @see #setMultipleMode
112      * @see #isMultipleMode
113      * @since 1.7
114      */
115     private boolean multipleMode = false;
116 
117     /*
118      * The filter used as the file dialog's filename filter.
119      * The file dialog will only be displaying files whose
120      * names are accepted by this filter.
121      * This variable may be <code>null</code>.
122      *
123      * @serial
124      * @see #getFilenameFilter()
125      * @see #setFilenameFilter()
126      * @see FileNameFilter
127      */
128     FilenameFilter filter;
129 
130     private static final String base = "filedlg";
131     private static int nameCounter = 0;
132 
133     /*
134      * JDK 1.1 serialVersionUID
135      */
136      private static final long serialVersionUID = 5035145889651310422L;
137 
138 
139     static {
140         /* ensure that the necessary native libraries are loaded */
141         Toolkit.loadLibraries();
142         if (!GraphicsEnvironment.isHeadless()) {
143             initIDs();
144         }
145     }
146 
147     static {
148         AWTAccessor.setFileDialogAccessor(
149             new AWTAccessor.FileDialogAccessor() {
150                 public void setFiles(FileDialog fileDialog, File files[]) {
151                     fileDialog.setFiles(files);
152                 }
153                 public void setFile(FileDialog fileDialog, String file) {
154                     fileDialog.file = ("".equals(file)) ? null : file;
155                 }
156                 public void setDirectory(FileDialog fileDialog, String directory) {
157                     fileDialog.dir = ("".equals(directory)) ? null : directory;
158                 }
159                 public boolean isMultipleMode(FileDialog fileDialog) {
160                     synchronized (fileDialog.getObjectLock()) {
161                         return fileDialog.multipleMode;
162                     }
163                 }
164             });
165     }
166 
167     /**
168      * Initialize JNI field and method IDs for fields that may be
169        accessed from C.
170      */
171     private static native void initIDs();
172 
173     /**
174      * Creates a file dialog for loading a file.  The title of the
175      * file dialog is initially empty.  This is a convenience method for
176      * <code>FileDialog(parent, "", LOAD)</code>.
177      *
178      * @param parent the owner of the dialog
179      * @since JDK1.1
180      */
181     public FileDialog(Frame parent) {
182         this(parent, "", LOAD);
183     }
184 
185     /**
186      * Creates a file dialog window with the specified title for loading
187      * a file. The files shown are those in the current directory.
188      * This is a convenience method for
189      * <code>FileDialog(parent, title, LOAD)</code>.
190      *
191      * @param     parent   the owner of the dialog
192      * @param     title    the title of the dialog
193      */
194     public FileDialog(Frame parent, String title) {
195         this(parent, title, LOAD);
196     }
197 
198     /**
199      * Creates a file dialog window with the specified title for loading
200      * or saving a file.
201      * <p>
202      * If the value of <code>mode</code> is <code>LOAD</code>, then the
203      * file dialog is finding a file to read, and the files shown are those
204      * in the current directory.   If the value of
205      * <code>mode</code> is <code>SAVE</code>, the file dialog is finding
206      * a place to write a file.
207      *
208      * @param     parent   the owner of the dialog
209      * @param     title   the title of the dialog
210      * @param     mode   the mode of the dialog; either
211      *          <code>FileDialog.LOAD</code> or <code>FileDialog.SAVE</code>
212      * @exception  IllegalArgumentException if an illegal file
213      *                 dialog mode is supplied
214      * @see       java.awt.FileDialog#LOAD
215      * @see       java.awt.FileDialog#SAVE
216      */
217     public FileDialog(Frame parent, String title, int mode) {
218         super(parent, title, true);
219         this.setMode(mode);
220         setLayout(null);
221     }
222 
223     /**
224      * Creates a file dialog for loading a file.  The title of the
225      * file dialog is initially empty.  This is a convenience method for
226      * <code>FileDialog(parent, "", LOAD)</code>.
227      *
228      * @param     parent   the owner of the dialog
229      * @exception java.lang.IllegalArgumentException if the <code>parent</code>'s
230      *            <code>GraphicsConfiguration</code>
231      *            is not from a screen device;
232      * @exception java.lang.IllegalArgumentException if <code>parent</code>
233      *            is <code>null</code>; this exception is always thrown when
234      *            <code>GraphicsEnvironment.isHeadless</code>
235      *            returns <code>true</code>
236      * @see java.awt.GraphicsEnvironment#isHeadless
237      * @since 1.5
238      */
239     public FileDialog(Dialog parent) {
240         this(parent, "", LOAD);
241     }
242 
243     /**
244      * Creates a file dialog window with the specified title for loading
245      * a file. The files shown are those in the current directory.
246      * This is a convenience method for
247      * <code>FileDialog(parent, title, LOAD)</code>.
248      *
249      * @param     parent   the owner of the dialog
250      * @param     title    the title of the dialog; a <code>null</code> value
251      *                     will be accepted without causing a
252      *                     <code>NullPointerException</code> to be thrown
253      * @exception java.lang.IllegalArgumentException if the <code>parent</code>'s
254      *            <code>GraphicsConfiguration</code>
255      *            is not from a screen device;
256      * @exception java.lang.IllegalArgumentException if <code>parent</code>
257      *            is <code>null</code>; this exception is always thrown when
258      *            <code>GraphicsEnvironment.isHeadless</code>
259      *            returns <code>true</code>
260      * @see java.awt.GraphicsEnvironment#isHeadless
261      * @since     1.5
262      */
263     public FileDialog(Dialog parent, String title) {
264         this(parent, title, LOAD);
265     }
266 
267     /**
268      * Creates a file dialog window with the specified title for loading
269      * or saving a file.
270      * <p>
271      * If the value of <code>mode</code> is <code>LOAD</code>, then the
272      * file dialog is finding a file to read, and the files shown are those
273      * in the current directory.   If the value of
274      * <code>mode</code> is <code>SAVE</code>, the file dialog is finding
275      * a place to write a file.
276      *
277      * @param     parent   the owner of the dialog
278      * @param     title    the title of the dialog; a <code>null</code> value
279      *                     will be accepted without causing a
280      *                     <code>NullPointerException</code> to be thrown
281      * @param     mode     the mode of the dialog; either
282      *                     <code>FileDialog.LOAD</code> or <code>FileDialog.SAVE</code>
283      * @exception java.lang.IllegalArgumentException if an illegal
284      *            file dialog mode is supplied;
285      * @exception java.lang.IllegalArgumentException if the <code>parent</code>'s
286      *            <code>GraphicsConfiguration</code>
287      *            is not from a screen device;
288      * @exception java.lang.IllegalArgumentException if <code>parent</code>
289      *            is <code>null</code>; this exception is always thrown when
290      *            <code>GraphicsEnvironment.isHeadless</code>
291      *            returns <code>true</code>
292      * @see       java.awt.GraphicsEnvironment#isHeadless
293      * @see       java.awt.FileDialog#LOAD
294      * @see       java.awt.FileDialog#SAVE
295      * @since     1.5
296      */
297     public FileDialog(Dialog parent, String title, int mode) {
298         super(parent, title, true);
299         this.setMode(mode);
300         setLayout(null);
301     }
302 
303     /**
304      * Constructs a name for this component. Called by <code>getName()</code>
305      * when the name is <code>null</code>.
306      */
307     String constructComponentName() {
308         synchronized (FileDialog.class) {
309             return base + nameCounter++;
310         }
311     }
312 
313     /**
314      * Creates the file dialog's peer.  The peer allows us to change the look
315      * of the file dialog without changing its functionality.
316      */
317     public void addNotify() {
318         synchronized(getTreeLock()) {
319             if (parent != null && parent.getPeer() == null) {
320                 parent.addNotify();
321             }
322             if (peer == null)
323                 peer = getToolkit().createFileDialog(this);
324             super.addNotify();
325         }
326     }
327 
328     /**
329      * Indicates whether this file dialog box is for loading from a file
330      * or for saving to a file.
331      *
332      * @return   the mode of this file dialog window, either
333      *               <code>FileDialog.LOAD</code> or
334      *               <code>FileDialog.SAVE</code>
335      * @see      java.awt.FileDialog#LOAD
336      * @see      java.awt.FileDialog#SAVE
337      * @see      java.awt.FileDialog#setMode
338      */
339     public int getMode() {
340         return mode;
341     }
342 
343     /**
344      * Sets the mode of the file dialog.  If <code>mode</code> is not
345      * a legal value, an exception will be thrown and <code>mode</code>
346      * will not be set.
347      *
348      * @param      mode  the mode for this file dialog, either
349      *                 <code>FileDialog.LOAD</code> or
350      *                 <code>FileDialog.SAVE</code>
351      * @see        java.awt.FileDialog#LOAD
352      * @see        java.awt.FileDialog#SAVE
353      * @see        java.awt.FileDialog#getMode
354      * @exception  IllegalArgumentException if an illegal file
355      *                 dialog mode is supplied
356      * @since      JDK1.1
357      */
358     public void setMode(int mode) {
359         switch (mode) {
360           case LOAD:
361           case SAVE:
362             this.mode = mode;
363             break;
364           default:
365             throw new IllegalArgumentException("illegal file dialog mode");
366         }
367     }
368 
369     /**
370      * Gets the directory of this file dialog.
371      *
372      * @return  the (potentially <code>null</code> or invalid)
373      *          directory of this <code>FileDialog</code>
374      * @see       java.awt.FileDialog#setDirectory
375      */
376     public String getDirectory() {
377         return dir;
378     }
379 
380     /**
381      * Sets the directory of this file dialog window to be the
382      * specified directory. Specifying a <code>null</code> or an
383      * invalid directory implies an implementation-defined default.
384      * This default will not be realized, however, until the user
385      * has selected a file. Until this point, <code>getDirectory()</code>
386      * will return the value passed into this method.
387      * <p>
388      * Specifying "" as the directory is exactly equivalent to
389      * specifying <code>null</code> as the directory.
390      *
391      * @param     dir   the specified directory
392      * @see       java.awt.FileDialog#getDirectory
393      */
394     public void setDirectory(String dir) {
395         this.dir = (dir != null && dir.equals("")) ? null : dir;
396         FileDialogPeer peer = (FileDialogPeer)this.peer;
397         if (peer != null) {
398             peer.setDirectory(this.dir);
399         }
400     }
401 
402     /**
403      * Gets the selected file of this file dialog.  If the user
404      * selected <code>CANCEL</code>, the returned file is <code>null</code>.
405      *
406      * @return    the currently selected file of this file dialog window,
407      *                or <code>null</code> if none is selected
408      * @see       java.awt.FileDialog#setFile
409      */
410     public String getFile() {
411         return file;
412     }
413 
414     /**
415      * Returns files that the user selects.
416      * <p>
417      * If the user cancels the file dialog,
418      * then the method returns an empty array.
419      *
420      * @return    files that the user selects or an empty array
421      *            if the user cancels the file dialog.
422      * @see       #setFile(String)
423      * @see       #getFile
424      * @since 1.7
425      */
426     public File[] getFiles() {
427         synchronized (getObjectLock()) {
428             if (files != null) {
429                 return files.clone();
430             } else {
431                 return new File[0];
432             }
433         }
434     }
435 
436     /**
437      * Stores the names of all the files that the user selects.
438      *
439      * Note that the method is private and it's intended to be used
440      * by the peers through the AWTAccessor API.
441      *
442      * @param files     the array that contains the short names of
443      *                  all the files that the user selects.
444      *
445      * @see #getFiles
446      * @since 1.7
447      */
448     private void setFiles(File files[]) {
449         synchronized (getObjectLock()) {
450             this.files = files;
451         }
452     }
453 
454     /**
455      * Sets the selected file for this file dialog window to be the
456      * specified file. This file becomes the default file if it is set
457      * before the file dialog window is first shown.
458      * <p>
459      * When the dialog is shown, the specified file is selected. The kind of
460      * selection depends on the file existence, the dialog type, and the native
461      * platform. E.g., the file could be highlighted in the file list, or a
462      * file name editbox could be populated with the file name.
463      * <p>
464      * This method accepts either a full file path, or a file name with an
465      * extension if used together with the {@code setDirectory} method.
466      * <p>
467      * Specifying "" as the file is exactly equivalent to specifying
468      * {@code null} as the file.
469      *
470      * @param    file   the file being set
471      * @see      #getFile
472      * @see      #getFiles
473      */
474     public void setFile(String file) {
475         this.file = (file != null && file.equals("")) ? null : file;
476         FileDialogPeer peer = (FileDialogPeer)this.peer;
477         if (peer != null) {
478             peer.setFile(this.file);
479         }
480     }
481 
482     /**
483      * Enables or disables multiple file selection for the file dialog.
484      *
485      * @param enable    if {@code true}, multiple file selection is enabled;
486      *                  {@code false} - disabled.
487      * @see #isMultipleMode
488      * @since 1.7
489      */
490     public void setMultipleMode(boolean enable) {
491         synchronized (getObjectLock()) {
492             this.multipleMode = enable;
493         }
494     }
495 
496     /**
497      * Returns whether the file dialog allows the multiple file selection.
498      *
499      * @return          {@code true} if the file dialog allows the multiple
500      *                  file selection; {@code false} otherwise.
501      * @see #setMultipleMode
502      * @since 1.7
503      */
504     public boolean isMultipleMode() {
505         synchronized (getObjectLock()) {
506             return multipleMode;
507         }
508     }
509 
510     /**
511      * Determines this file dialog's filename filter. A filename filter
512      * allows the user to specify which files appear in the file dialog
513      * window.  Filename filters do not function in Sun's reference
514      * implementation for Microsoft Windows.
515      *
516      * @return    this file dialog's filename filter
517      * @see       java.io.FilenameFilter
518      * @see       java.awt.FileDialog#setFilenameFilter
519      */
520     public FilenameFilter getFilenameFilter() {
521         return filter;
522     }
523 
524     /**
525      * Sets the filename filter for this file dialog window to the
526      * specified filter.
527      * Filename filters do not function in Sun's reference
528      * implementation for Microsoft Windows.
529      *
530      * @param   filter   the specified filter
531      * @see     java.io.FilenameFilter
532      * @see     java.awt.FileDialog#getFilenameFilter
533      */
534     public synchronized void setFilenameFilter(FilenameFilter filter) {
535         this.filter = filter;
536         FileDialogPeer peer = (FileDialogPeer)this.peer;
537         if (peer != null) {
538             peer.setFilenameFilter(filter);
539         }
540     }
541 
542     /**
543      * Reads the <code>ObjectInputStream</code> and performs
544      * a backwards compatibility check by converting
545      * either a <code>dir</code> or a <code>file</code>
546      * equal to an empty string to <code>null</code>.
547      *
548      * @param s the <code>ObjectInputStream</code> to read
549      */
550     private void readObject(ObjectInputStream s)
551         throws ClassNotFoundException, IOException
552     {
553         s.defaultReadObject();
554 
555         // 1.1 Compatibility: "" is not converted to null in 1.1
556         if (dir != null && dir.equals("")) {
557             dir = null;
558         }
559         if (file != null && file.equals("")) {
560             file = null;
561         }
562     }
563 
564     /**
565      * Returns a string representing the state of this <code>FileDialog</code>
566      * window. This method is intended to be used only for debugging purposes,
567      * and the content and format of the returned string may vary between
568      * implementations. The returned string may be empty but may not be
569      * <code>null</code>.
570      *
571      * @return  the parameter string of this file dialog window
572      */
573     protected String paramString() {
574         String str = super.paramString();
575         str += ",dir= " + dir;
576         str += ",file= " + file;
577         return str + ((mode == LOAD) ? ",load" : ",save");
578     }
579 
580     boolean postsOldMouseEvents() {
581         return false;
582     }
583 }