1 /*
2  * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *   - Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *   - Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *   - Neither the name of Oracle nor the names of its
16  *     contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * This source code is provided to illustrate the usage of a given feature
34  * or technique and has been deliberately simplified. Additional steps
35  * required for a production-quality application, such as security checks,
36  * input validation and proper error handling, might not be present in
37  * this sample code.
38  */
39 
40 
41 
42 import java.lang.reflect.InvocationTargetException;
43 import java.util.logging.Level;
44 import java.util.logging.Logger;
45 import javax.swing.UIManager.LookAndFeelInfo;
46 import java.awt.BorderLayout;
47 import java.awt.CardLayout;
48 import java.awt.Component;
49 import java.awt.Dimension;
50 import java.awt.Graphics;
51 import java.awt.Image;
52 import java.awt.Insets;
53 import java.awt.event.ActionEvent;
54 import java.awt.event.ActionListener;
55 import java.beans.PropertyChangeEvent;
56 import java.beans.PropertyChangeListener;
57 import java.util.List;
58 import javax.swing.BorderFactory;
59 import javax.swing.Box;
60 import javax.swing.BoxLayout;
61 import javax.swing.ButtonGroup;
62 import javax.swing.DefaultComboBoxModel;
63 import javax.swing.ImageIcon;
64 import javax.swing.JButton;
65 import javax.swing.JCheckBox;
66 import javax.swing.JComboBox;
67 import javax.swing.JComponent;
68 import javax.swing.JDialog;
69 import javax.swing.JFileChooser;
70 import javax.swing.JFrame;
71 import javax.swing.JLabel;
72 import javax.swing.JOptionPane;
73 import javax.swing.JPanel;
74 import javax.swing.JRadioButton;
75 import javax.swing.JTextField;
76 import javax.swing.JToggleButton;
77 import javax.swing.LookAndFeel;
78 import javax.swing.SwingUtilities;
79 import javax.swing.UIManager;
80 import javax.swing.UnsupportedLookAndFeelException;
81 import javax.swing.WindowConstants;
82 import javax.swing.filechooser.FileFilter;
83 import javax.swing.filechooser.FileNameExtensionFilter;
84 import javax.swing.filechooser.FileSystemView;
85 import java.util.ArrayList;
86 import javax.swing.plaf.FileChooserUI;
87 import javax.swing.plaf.basic.BasicFileChooserUI;
88 import java.io.File;
89 import static javax.swing.JFileChooser.*;
90 
91 
92 /**
93  *
94  * A demo which makes extensive use of the file chooser.
95  *
96  * @author Jeff Dinkins
97  */
98 @SuppressWarnings("serial")
99 public class FileChooserDemo extends JPanel implements ActionListener {
100 
101     public static final String NIMBUS_LAF_NAME = "Nimbus";
102     private static JFrame frame;
103     private final List<SupportedLaF> supportedLaFs =
104             new ArrayList<SupportedLaF>();
105     private static SupportedLaF nimbusLaF;
106 
107 
108     private static class SupportedLaF {
109 
110         private final String name;
111         private final LookAndFeel laf;
112 
SupportedLaF(String name, LookAndFeel laf)113         SupportedLaF(String name, LookAndFeel laf) {
114             this.name = name;
115             this.laf = laf;
116         }
117 
118         @Override
toString()119         public String toString() {
120             return name;
121         }
122     }
123     private JButton showButton;
124     private JCheckBox showAllFilesFilterCheckBox;
125     private JCheckBox showImageFilesFilterCheckBox;
126     private JCheckBox showFullDescriptionCheckBox;
127     private JCheckBox useFileViewCheckBox;
128     private JCheckBox useFileSystemViewCheckBox;
129     private JCheckBox accessoryCheckBox;
130     private JCheckBox setHiddenCheckBox;
131     private JCheckBox useEmbedInWizardCheckBox;
132     private JCheckBox useControlsCheckBox;
133     private JCheckBox enableDragCheckBox;
134     private JRadioButton singleSelectionRadioButton;
135     private JRadioButton multiSelectionRadioButton;
136     private JRadioButton openRadioButton;
137     private JRadioButton saveRadioButton;
138     private JRadioButton customButton;
139     private JComboBox<SupportedLaF> lafComboBox;
140     private JRadioButton justFilesRadioButton;
141     private JRadioButton justDirectoriesRadioButton;
142     private JRadioButton bothFilesAndDirectoriesRadioButton;
143     private JTextField customField;
144     private final ExampleFileView fileView;
145     private final ExampleFileSystemView fileSystemView;
146     private static final Dimension hpad10 = new Dimension(10, 1);
147     private static final Dimension vpad20 = new Dimension(1, 20);
148     private static final Dimension vpad7 = new Dimension(1, 7);
149     private static final Dimension vpad4 = new Dimension(1, 4);
150     private static final Insets insets = new Insets(5, 10, 0, 10);
151     private final FilePreviewer previewer;
152     private final JFileChooser chooser;
153 
154     @SuppressWarnings("LeakingThisInConstructor")
FileChooserDemo()155     public FileChooserDemo() {
156         UIManager.LookAndFeelInfo[] installedLafs = UIManager.
157                 getInstalledLookAndFeels();
158         for (UIManager.LookAndFeelInfo lafInfo : installedLafs) {
159             try {
160                 Class<?> lnfClass = Class.forName(lafInfo.getClassName());
161                 LookAndFeel laf = (LookAndFeel) (lnfClass.getDeclaredConstructor().newInstance());
162                 if (laf.isSupportedLookAndFeel()) {
163                     String name = lafInfo.getName();
164                     SupportedLaF supportedLaF = new SupportedLaF(name, laf);
165                     supportedLaFs.add(supportedLaF);
166                     if (NIMBUS_LAF_NAME.equals(name)) {
167                         nimbusLaF = supportedLaF;
168                     }
169                 }
170             } catch (Exception ignored) {
171                 // If ANYTHING weird happens, don't add this L&F
172             }
173         }
174 
175         setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
176 
177         chooser = new JFileChooser();
178         previewer = new FilePreviewer(chooser);
179 
180         // Create Custom FileView
181         fileView = new ExampleFileView();
182         fileView.putIcon("jpg", new ImageIcon(getClass().getResource(
183                 "/resources/images/jpgIcon.jpg")));
184         fileView.putIcon("gif", new ImageIcon(getClass().getResource(
185                 "/resources/images/gifIcon.gif")));
186 
187         // Create Custom FileSystemView
188         fileSystemView = new ExampleFileSystemView();
189 
190         // create a radio listener to listen to option changes
191         OptionListener optionListener = new OptionListener();
192 
193         // Create options
194         openRadioButton = new JRadioButton("Open");
195         openRadioButton.setSelected(true);
196         openRadioButton.addActionListener(optionListener);
197 
198         saveRadioButton = new JRadioButton("Save");
199         saveRadioButton.addActionListener(optionListener);
200 
201         customButton = new JRadioButton("Custom");
202         customButton.addActionListener(optionListener);
203 
204         customField = new JTextField(8) {
205 
206             @Override
207             public Dimension getMaximumSize() {
208                 return new Dimension(getPreferredSize().width,
209                         getPreferredSize().height);
210             }
211         };
212         customField.setText("Doit");
213         customField.setAlignmentY(JComponent.TOP_ALIGNMENT);
214         customField.setEnabled(false);
215         customField.addActionListener(optionListener);
216 
217         ButtonGroup group1 = new ButtonGroup();
218         group1.add(openRadioButton);
219         group1.add(saveRadioButton);
220         group1.add(customButton);
221 
222         // filter buttons
223         showAllFilesFilterCheckBox = new JCheckBox("Show \"All Files\" Filter");
224         showAllFilesFilterCheckBox.addActionListener(optionListener);
225         showAllFilesFilterCheckBox.setSelected(true);
226 
227         showImageFilesFilterCheckBox = new JCheckBox("Show JPG and GIF Filters");
228         showImageFilesFilterCheckBox.addActionListener(optionListener);
229         showImageFilesFilterCheckBox.setSelected(false);
230 
231         accessoryCheckBox = new JCheckBox("Show Preview");
232         accessoryCheckBox.addActionListener(optionListener);
233         accessoryCheckBox.setSelected(false);
234 
235         // more options
236         setHiddenCheckBox = new JCheckBox("Show Hidden Files");
237         setHiddenCheckBox.addActionListener(optionListener);
238 
239         showFullDescriptionCheckBox = new JCheckBox("With File Extensions");
240         showFullDescriptionCheckBox.addActionListener(optionListener);
241         showFullDescriptionCheckBox.setSelected(true);
242         showFullDescriptionCheckBox.setEnabled(false);
243 
244         useFileViewCheckBox = new JCheckBox("Use FileView");
245         useFileViewCheckBox.addActionListener(optionListener);
246         useFileViewCheckBox.setSelected(false);
247 
248         useFileSystemViewCheckBox = new JCheckBox("Use FileSystemView", false);
249         useFileSystemViewCheckBox.addActionListener(optionListener);
250 
251         useEmbedInWizardCheckBox = new JCheckBox("Embed in Wizard");
252         useEmbedInWizardCheckBox.addActionListener(optionListener);
253         useEmbedInWizardCheckBox.setSelected(false);
254 
255         useControlsCheckBox = new JCheckBox("Show Control Buttons");
256         useControlsCheckBox.addActionListener(optionListener);
257         useControlsCheckBox.setSelected(true);
258 
259         enableDragCheckBox = new JCheckBox("Enable Dragging");
260         enableDragCheckBox.addActionListener(optionListener);
261 
262         // File or Directory chooser options
263         ButtonGroup group3 = new ButtonGroup();
264         justFilesRadioButton = new JRadioButton("Just Select Files");
265         justFilesRadioButton.setSelected(true);
266         group3.add(justFilesRadioButton);
267         justFilesRadioButton.addActionListener(optionListener);
268 
269         justDirectoriesRadioButton = new JRadioButton("Just Select Directories");
270         group3.add(justDirectoriesRadioButton);
271         justDirectoriesRadioButton.addActionListener(optionListener);
272 
273         bothFilesAndDirectoriesRadioButton = new JRadioButton(
274                 "Select Files or Directories");
275         group3.add(bothFilesAndDirectoriesRadioButton);
276         bothFilesAndDirectoriesRadioButton.addActionListener(optionListener);
277 
278         singleSelectionRadioButton = new JRadioButton("Single Selection", true);
279         singleSelectionRadioButton.addActionListener(optionListener);
280 
281         multiSelectionRadioButton = new JRadioButton("Multi Selection");
282         multiSelectionRadioButton.addActionListener(optionListener);
283 
284         ButtonGroup group4 = new ButtonGroup();
285         group4.add(singleSelectionRadioButton);
286         group4.add(multiSelectionRadioButton);
287 
288 
289         // Create show button
290         showButton = new JButton("Show FileChooser");
291         showButton.addActionListener(this);
292         showButton.setMnemonic('s');
293 
294         // Create laf combo box
295         lafComboBox = new JComboBox<>(supportedLaFs.toArray(new SupportedLaF[0]));
296         lafComboBox.setSelectedItem(nimbusLaF);
297         lafComboBox.setEditable(false);
298         lafComboBox.addActionListener(optionListener);
299 
300         // ********************************************************
301         // ******************** Dialog Type ***********************
302         // ********************************************************
303         JPanel control1 = new InsetPanel(insets);
304         control1.setBorder(BorderFactory.createTitledBorder("Dialog Type"));
305 
306         control1.setLayout(new BoxLayout(control1, BoxLayout.Y_AXIS));
307         control1.add(Box.createRigidArea(vpad20));
308         control1.add(openRadioButton);
309         control1.add(Box.createRigidArea(vpad7));
310         control1.add(saveRadioButton);
311         control1.add(Box.createRigidArea(vpad7));
312         control1.add(customButton);
313         control1.add(Box.createRigidArea(vpad4));
314         JPanel fieldWrapper = new JPanel();
315         fieldWrapper.setLayout(new BoxLayout(fieldWrapper, BoxLayout.X_AXIS));
316         fieldWrapper.setAlignmentX(Component.LEFT_ALIGNMENT);
317         fieldWrapper.add(Box.createRigidArea(hpad10));
318         fieldWrapper.add(Box.createRigidArea(hpad10));
319         fieldWrapper.add(customField);
320         control1.add(fieldWrapper);
321         control1.add(Box.createRigidArea(vpad20));
322         control1.add(Box.createGlue());
323 
324         // ********************************************************
325         // ***************** Filter Controls **********************
326         // ********************************************************
327         JPanel control2 = new InsetPanel(insets);
328         control2.setBorder(BorderFactory.createTitledBorder("Filter Controls"));
329         control2.setLayout(new BoxLayout(control2, BoxLayout.Y_AXIS));
330         control2.add(Box.createRigidArea(vpad20));
331         control2.add(showAllFilesFilterCheckBox);
332         control2.add(Box.createRigidArea(vpad7));
333         control2.add(showImageFilesFilterCheckBox);
334         control2.add(Box.createRigidArea(vpad4));
335         JPanel checkWrapper = new JPanel();
336         checkWrapper.setLayout(new BoxLayout(checkWrapper, BoxLayout.X_AXIS));
337         checkWrapper.setAlignmentX(Component.LEFT_ALIGNMENT);
338         checkWrapper.add(Box.createRigidArea(hpad10));
339         checkWrapper.add(Box.createRigidArea(hpad10));
340         checkWrapper.add(showFullDescriptionCheckBox);
341         control2.add(checkWrapper);
342         control2.add(Box.createRigidArea(vpad20));
343         control2.add(Box.createGlue());
344 
345         // ********************************************************
346         // ****************** Display Options *********************
347         // ********************************************************
348         JPanel control3 = new InsetPanel(insets);
349         control3.setBorder(BorderFactory.createTitledBorder("Display Options"));
350         control3.setLayout(new BoxLayout(control3, BoxLayout.Y_AXIS));
351         control3.add(Box.createRigidArea(vpad20));
352         control3.add(setHiddenCheckBox);
353         control3.add(Box.createRigidArea(vpad7));
354         control3.add(useFileViewCheckBox);
355         control3.add(Box.createRigidArea(vpad7));
356         control3.add(useFileSystemViewCheckBox);
357         control3.add(Box.createRigidArea(vpad7));
358         control3.add(accessoryCheckBox);
359         control3.add(Box.createRigidArea(vpad7));
360         control3.add(useEmbedInWizardCheckBox);
361         control3.add(Box.createRigidArea(vpad7));
362         control3.add(useControlsCheckBox);
363         control3.add(Box.createRigidArea(vpad7));
364         control3.add(enableDragCheckBox);
365         control3.add(Box.createRigidArea(vpad20));
366         control3.add(Box.createGlue());
367 
368         // ********************************************************
369         // ************* File & Directory Options *****************
370         // ********************************************************
371         JPanel control4 = new InsetPanel(insets);
372         control4.setBorder(BorderFactory.createTitledBorder(
373                 "File and Directory Options"));
374         control4.setLayout(new BoxLayout(control4, BoxLayout.Y_AXIS));
375         control4.add(Box.createRigidArea(vpad20));
376         control4.add(justFilesRadioButton);
377         control4.add(Box.createRigidArea(vpad7));
378         control4.add(justDirectoriesRadioButton);
379         control4.add(Box.createRigidArea(vpad7));
380         control4.add(bothFilesAndDirectoriesRadioButton);
381         control4.add(Box.createRigidArea(vpad20));
382         control4.add(singleSelectionRadioButton);
383         control4.add(Box.createRigidArea(vpad7));
384         control4.add(multiSelectionRadioButton);
385         control4.add(Box.createRigidArea(vpad20));
386         control4.add(Box.createGlue());
387 
388 
389         // ********************************************************
390         // **************** Look & Feel Switch ********************
391         // ********************************************************
392         JPanel panel = new JPanel();
393         panel.add(new JLabel("Look and Feel: "));
394         panel.add(lafComboBox);
395         panel.add(showButton);
396 
397         // ********************************************************
398         // ****************** Wrap 'em all up *********************
399         // ********************************************************
400         JPanel wrapper = new JPanel();
401         wrapper.setLayout(new BoxLayout(wrapper, BoxLayout.X_AXIS));
402 
403         add(Box.createRigidArea(vpad20));
404 
405         wrapper.add(Box.createRigidArea(hpad10));
406         wrapper.add(Box.createRigidArea(hpad10));
407         wrapper.add(control1);
408         wrapper.add(Box.createRigidArea(hpad10));
409         wrapper.add(control2);
410         wrapper.add(Box.createRigidArea(hpad10));
411         wrapper.add(control3);
412         wrapper.add(Box.createRigidArea(hpad10));
413         wrapper.add(control4);
414         wrapper.add(Box.createRigidArea(hpad10));
415         wrapper.add(Box.createRigidArea(hpad10));
416 
417         add(wrapper);
418         add(Box.createRigidArea(vpad20));
419         add(panel);
420         add(Box.createRigidArea(vpad20));
421     }
422 
actionPerformed(ActionEvent e)423     public void actionPerformed(ActionEvent e) {
424         if (customButton.isSelected()) {
425             chooser.setApproveButtonText(customField.getText());
426         }
427         if (chooser.isMultiSelectionEnabled()) {
428             chooser.setSelectedFiles(null);
429         } else {
430             chooser.setSelectedFile(null);
431         }
432         // clear the preview from the previous display of the chooser
433         JComponent accessory = chooser.getAccessory();
434         if (accessory != null) {
435             ((FilePreviewer) accessory).loadImage(null);
436         }
437 
438         if (useEmbedInWizardCheckBox.isSelected()) {
439             WizardDialog wizard = new WizardDialog(frame, true);
440             wizard.setVisible(true);
441             wizard.dispose();
442             return;
443         }
444 
445         int retval = chooser.showDialog(frame, null);
446         if (retval == APPROVE_OPTION) {
447             JOptionPane.showMessageDialog(frame, getResultString());
448         } else if (retval == CANCEL_OPTION) {
449             JOptionPane.showMessageDialog(frame,
450                     "User cancelled operation. No file was chosen.");
451         } else if (retval == ERROR_OPTION) {
452             JOptionPane.showMessageDialog(frame,
453                     "An error occurred. No file was chosen.");
454         } else {
455             JOptionPane.showMessageDialog(frame, "Unknown operation occurred.");
456         }
457     }
458 
resetFileFilters(boolean enableFilters, boolean showExtensionInDescription)459     private void resetFileFilters(boolean enableFilters,
460             boolean showExtensionInDescription) {
461         chooser.resetChoosableFileFilters();
462         if (enableFilters) {
463             FileFilter jpgFilter = createFileFilter(
464                     "JPEG Compressed Image Files",
465                     showExtensionInDescription, "jpg");
466             FileFilter gifFilter = createFileFilter("GIF Image Files",
467                     showExtensionInDescription, "gif");
468             FileFilter bothFilter = createFileFilter("JPEG and GIF Image Files",
469                     showExtensionInDescription, "jpg",
470                     "gif");
471             chooser.addChoosableFileFilter(bothFilter);
472             chooser.addChoosableFileFilter(jpgFilter);
473             chooser.addChoosableFileFilter(gifFilter);
474         }
475     }
476 
createFileFilter(String description, boolean showExtensionInDescription, String... extensions)477     private FileFilter createFileFilter(String description,
478             boolean showExtensionInDescription, String... extensions) {
479         if (showExtensionInDescription) {
480             description = createFileNameFilterDescriptionFromExtensions(
481                     description, extensions);
482         }
483         return new FileNameExtensionFilter(description, extensions);
484     }
485 
createFileNameFilterDescriptionFromExtensions( String description, String[] extensions)486     private String createFileNameFilterDescriptionFromExtensions(
487             String description, String[] extensions) {
488         String fullDescription = (description == null) ? "(" : description
489                 + " (";
490         // build the description from the extension list
491         fullDescription += "." + extensions[0];
492         for (int i = 1; i < extensions.length; i++) {
493             fullDescription += ", .";
494             fullDescription += extensions[i];
495         }
496         fullDescription += ")";
497         return fullDescription;
498     }
499 
500 
501     private class WizardDialog extends JDialog implements ActionListener {
502 
503         CardLayout cardLayout;
504         JPanel cardPanel;
505         JLabel messageLabel;
506         JButton backButton, nextButton, closeButton;
507 
508         @SuppressWarnings("LeakingThisInConstructor")
WizardDialog(JFrame frame, boolean modal)509         WizardDialog(JFrame frame, boolean modal) {
510             super(frame, "Embedded JFileChooser Demo", modal);
511 
512             cardLayout = new CardLayout();
513             cardPanel = new JPanel(cardLayout);
514             getContentPane().add(cardPanel, BorderLayout.CENTER);
515 
516             messageLabel = new JLabel("", JLabel.CENTER);
517             cardPanel.add(chooser, "fileChooser");
518             cardPanel.add(messageLabel, "label");
519             cardLayout.show(cardPanel, "fileChooser");
520             chooser.addActionListener(this);
521 
522             JPanel buttonPanel = new JPanel();
523             backButton = new JButton("< Back");
524             nextButton = new JButton("Next >");
525             closeButton = new JButton("Close");
526 
527             buttonPanel.add(backButton);
528             buttonPanel.add(nextButton);
529             buttonPanel.add(closeButton);
530 
531             getContentPane().add(buttonPanel, BorderLayout.SOUTH);
532 
533             backButton.setEnabled(false);
534             getRootPane().setDefaultButton(nextButton);
535 
536             backButton.addActionListener(this);
537             nextButton.addActionListener(this);
538             closeButton.addActionListener(this);
539 
540             pack();
541             setLocationRelativeTo(frame);
542         }
543 
actionPerformed(ActionEvent evt)544         public void actionPerformed(ActionEvent evt) {
545             Object src = evt.getSource();
546             String cmd = evt.getActionCommand();
547 
548             if (src == backButton) {
549                 back();
550             } else if (src == nextButton) {
551                 FileChooserUI ui = chooser.getUI();
552                 if (ui instanceof BasicFileChooserUI) {
553                     // Workaround for bug 4528663. This is necessary to
554                     // pick up the contents of the file chooser text field.
555                     // This will trigger an APPROVE_SELECTION action.
556                     ((BasicFileChooserUI) ui).getApproveSelectionAction().
557                             actionPerformed(null);
558                 } else {
559                     next();
560                 }
561             } else if (src == closeButton) {
562                 close();
563             } else if (APPROVE_SELECTION.equals(cmd)) {
564                 next();
565             } else if (CANCEL_SELECTION.equals(cmd)) {
566                 close();
567             }
568         }
569 
back()570         private void back() {
571             backButton.setEnabled(false);
572             nextButton.setEnabled(true);
573             cardLayout.show(cardPanel, "fileChooser");
574             getRootPane().setDefaultButton(nextButton);
575             chooser.requestFocus();
576         }
577 
next()578         private void next() {
579             backButton.setEnabled(true);
580             nextButton.setEnabled(false);
581             messageLabel.setText(getResultString());
582             cardLayout.show(cardPanel, "label");
583             getRootPane().setDefaultButton(closeButton);
584             closeButton.requestFocus();
585         }
586 
close()587         private void close() {
588             setVisible(false);
589         }
590 
591         @Override
dispose()592         public void dispose() {
593             chooser.removeActionListener(this);
594 
595             // The chooser is hidden by CardLayout on remove
596             // so fix it here
597             cardPanel.remove(chooser);
598             chooser.setVisible(true);
599 
600             super.dispose();
601         }
602     }
603 
getResultString()604     private String getResultString() {
605         String resultString;
606         String filter;
607         if (chooser.getFileFilter() == null) {
608             filter = "";
609         } else {
610             filter = chooser.getFileFilter().getDescription();
611         }
612         String path = null;
613         boolean isDirMode = (chooser.getFileSelectionMode() == DIRECTORIES_ONLY);
614         boolean isMulti = chooser.isMultiSelectionEnabled();
615 
616         if (isMulti) {
617             File[] files = chooser.getSelectedFiles();
618             if (files != null && files.length > 0) {
619                 path = "";
620                 for (File file : files) {
621                     path = path + "<br>" + file.getPath();
622                 }
623             }
624         } else {
625             File file = chooser.getSelectedFile();
626             if (file != null) {
627                 path = "<br>" + file.getPath();
628             }
629         }
630         if (path != null) {
631             path = path.replace(" ", "&nbsp;");
632             filter = filter.replace(" ", "&nbsp;");
633             resultString =
634                     "<html>You chose " + (isMulti ? "these" : "this") + " " + (isDirMode ? (isMulti
635                     ? "directories" : "directory")
636                     : (isMulti ? "files" : "file")) + ": <code>" + path
637                     + "</code><br><br>with filter: <br><code>" + filter;
638         } else {
639             resultString = "Nothing was chosen";
640         }
641         return resultString;
642     }
643 
644 
645     /** An ActionListener that listens to the radio buttons. */
646     private class OptionListener implements ActionListener {
647 
actionPerformed(ActionEvent e)648         public void actionPerformed(ActionEvent e) {
649             JComponent c = (JComponent) e.getSource();
650             boolean selected = false;
651             if (c instanceof JToggleButton) {
652                 selected = ((JToggleButton) c).isSelected();
653             }
654 
655             if (c == openRadioButton) {
656                 chooser.setDialogType(OPEN_DIALOG);
657                 customField.setEnabled(false);
658                 repaint();
659             } else if (c == useEmbedInWizardCheckBox) {
660                 useControlsCheckBox.setEnabled(!selected);
661                 useControlsCheckBox.setSelected(!selected);
662                 chooser.setControlButtonsAreShown(!selected);
663             } else if (c == useControlsCheckBox) {
664                 chooser.setControlButtonsAreShown(selected);
665             } else if (c == enableDragCheckBox) {
666                 chooser.setDragEnabled(selected);
667             } else if (c == saveRadioButton) {
668                 chooser.setDialogType(SAVE_DIALOG);
669                 customField.setEnabled(false);
670                 repaint();
671             } else if (c == customButton || c == customField) {
672                 customField.setEnabled(true);
673                 chooser.setDialogType(CUSTOM_DIALOG);
674                 repaint();
675             } else if (c == showAllFilesFilterCheckBox) {
676                 chooser.setAcceptAllFileFilterUsed(selected);
677             } else if (c == showImageFilesFilterCheckBox) {
678                 resetFileFilters(selected,
679                         showFullDescriptionCheckBox.isSelected());
680                 showFullDescriptionCheckBox.setEnabled(selected);
681             } else if (c == setHiddenCheckBox) {
682                 chooser.setFileHidingEnabled(!selected);
683             } else if (c == accessoryCheckBox) {
684                 if (selected) {
685                     chooser.setAccessory(previewer);
686                 } else {
687                     chooser.setAccessory(null);
688                 }
689             } else if (c == useFileViewCheckBox) {
690                 if (selected) {
691                     chooser.setFileView(fileView);
692                 } else {
693                     chooser.setFileView(null);
694                 }
695             } else if (c == useFileSystemViewCheckBox) {
696                 if (selected) {
697                     chooser.setFileSystemView(fileSystemView);
698                 } else {
699                     // Restore default behaviour
700                     chooser.setFileSystemView(FileSystemView.getFileSystemView());
701                 }
702             } else if (c == showFullDescriptionCheckBox) {
703                 resetFileFilters(showImageFilesFilterCheckBox.isSelected(),
704                         selected);
705             } else if (c == justFilesRadioButton) {
706                 chooser.setFileSelectionMode(FILES_ONLY);
707             } else if (c == justDirectoriesRadioButton) {
708                 chooser.setFileSelectionMode(DIRECTORIES_ONLY);
709             } else if (c == bothFilesAndDirectoriesRadioButton) {
710                 chooser.setFileSelectionMode(FILES_AND_DIRECTORIES);
711             } else if (c == singleSelectionRadioButton) {
712                 if (selected) {
713                     chooser.setMultiSelectionEnabled(false);
714                 }
715             } else if (c == multiSelectionRadioButton) {
716                 if (selected) {
717                     chooser.setMultiSelectionEnabled(true);
718                 }
719             } else if (c == lafComboBox) {
720                 SupportedLaF supportedLaF = ((SupportedLaF) lafComboBox.
721                         getSelectedItem());
722                 LookAndFeel laf = supportedLaF.laf;
723                 try {
724                     UIManager.setLookAndFeel(laf);
725                     SwingUtilities.updateComponentTreeUI(frame);
726                     if (chooser != null) {
727                         SwingUtilities.updateComponentTreeUI(chooser);
728                     }
729                     frame.pack();
730                 } catch (UnsupportedLookAndFeelException exc) {
731                     // This should not happen because we already checked
732                     ((DefaultComboBoxModel<?>) lafComboBox.getModel()).
733                             removeElement(supportedLaF);
734                 }
735             }
736 
737         }
738     }
739 
740 
741     private class FilePreviewer extends JComponent implements
742             PropertyChangeListener {
743 
744         ImageIcon thumbnail = null;
745 
746         @SuppressWarnings("LeakingThisInConstructor")
FilePreviewer(JFileChooser fc)747         public FilePreviewer(JFileChooser fc) {
748             setPreferredSize(new Dimension(100, 50));
749             fc.addPropertyChangeListener(this);
750         }
751 
loadImage(File f)752         public void loadImage(File f) {
753             if (f == null) {
754                 thumbnail = null;
755             } else {
756                 ImageIcon tmpIcon = new ImageIcon(f.getPath());
757                 if (tmpIcon.getIconWidth() > 90) {
758                     thumbnail = new ImageIcon(
759                             tmpIcon.getImage().getScaledInstance(90, -1,
760                             Image.SCALE_DEFAULT));
761                 } else {
762                     thumbnail = tmpIcon;
763                 }
764             }
765         }
766 
propertyChange(PropertyChangeEvent e)767         public void propertyChange(PropertyChangeEvent e) {
768             String prop = e.getPropertyName();
769             if (SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
770                 if (isShowing()) {
771                     loadImage((File) e.getNewValue());
772                     repaint();
773                 }
774             }
775         }
776 
777         @Override
paint(Graphics g)778         public void paint(Graphics g) {
779             if (thumbnail != null) {
780                 int x = getWidth() / 2 - thumbnail.getIconWidth() / 2;
781                 int y = getHeight() / 2 - thumbnail.getIconHeight() / 2;
782                 if (y < 0) {
783                     y = 0;
784                 }
785 
786                 if (x < 5) {
787                     x = 5;
788                 }
789                 thumbnail.paintIcon(this, g, x, y);
790             }
791         }
792     }
793 
main(String[] s)794     public static void main(String[] s) {
795         try {
796             SwingUtilities.invokeAndWait(new Runnable() {
797 
798                 public void run() {
799                     /*
800                      * NOTE: By default, the look and feel will be set to the
801                      * Cross Platform Look and Feel (which is currently Metal).
802                      * The following code tries to set the Look and Feel to Nimbus.
803                      * https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/nimbus.html
804                      */
805                     try {
806                         for (LookAndFeelInfo info : UIManager.
807                                 getInstalledLookAndFeels()) {
808                             if (NIMBUS_LAF_NAME.equals(info.getName())) {
809                                 UIManager.setLookAndFeel(info.getClassName());
810                                 break;
811                             }
812                         }
813                     } catch (Exception ignored) {
814                     }
815 
816                     FileChooserDemo panel = new FileChooserDemo();
817 
818                     frame = new JFrame("FileChooserDemo");
819                     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
820                     frame.getContentPane().add("Center", panel);
821                     frame.pack();
822                     frame.setVisible(true);
823                 }
824             });
825         } catch (InterruptedException ex) {
826             Logger.getLogger(FileChooserDemo.class.getName()).log(Level.SEVERE,
827                     null,
828                     ex);
829         } catch (InvocationTargetException ex) {
830             Logger.getLogger(FileChooserDemo.class.getName()).log(Level.SEVERE,
831                     null,
832                     ex);
833         }
834     }
835 
836 
837     private static class InsetPanel extends JPanel {
838 
839         Insets i;
840 
InsetPanel(Insets i)841         InsetPanel(Insets i) {
842             this.i = i;
843         }
844 
845         @Override
getInsets()846         public Insets getInsets() {
847             return i;
848         }
849     }
850 }
851