source: josm/trunk/src/org/openstreetmap/josm/gui/widgets/JFileChooserManager.java@ 5438

Last change on this file since 5438 was 5438, checked in by Don-vip, 12 years ago

fix #6733 - File Open dialog incorrectly accepts folder selection

Major rework of how the JFileChooser are created in JOSM

  • Simple need: use DiskAccessAction.createAndOpenFileChooser methods
  • Complex need: use directly the new class JFileChooserManager

Concerning the directory selection for geottaged images, this is still possible via:

  • right-click on GPX layer -> Import Photos
File size: 10.8 KB
Line 
1package org.openstreetmap.josm.gui.widgets;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.awt.Component;
6import java.io.File;
7import java.util.Collection;
8import java.util.Collections;
9
10import javax.swing.JFileChooser;
11import javax.swing.filechooser.FileFilter;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.actions.DiskAccessAction;
15import org.openstreetmap.josm.actions.ExtensionFileFilter;
16import org.openstreetmap.josm.gui.ExtendedDialog;
17
18/**
19 * A chained utility class used to create and open {@link JFileChooser} dialogs.<br/>
20 * Use only this class if you need to control specifically your JFileChooser dialog.<br/>
21 * <p>
22 * A simpler usage is to call the {@link DiskAccessAction#createAndOpenFileChooser} methods.
23 *
24 * @since 5438
25 */
26public class JFileChooserManager {
27 private final boolean open;
28 private final String lastDirProperty;
29 private final String curDir;
30
31 private JFileChooser fc;
32
33 /**
34 * Creates a new {@code JFileChooserManager}.
35 * @param open If true, "Open File" dialogs will be created. If false, "Save File" dialogs will be created.
36 * @see #createFileChooser
37 */
38 public JFileChooserManager(boolean open) {
39 this(open, null);
40 }
41
42 /**
43 * Creates a new {@code JFileChooserManager}.
44 * @param open If true, "Open File" dialogs will be created. If false, "Save File" dialogs will be created.
45 * @param lastDirProperty The name of the property used to get the last directory. This directory is used to initialize the JFileChooser.
46 * Then, if the user effetively choses a file or a directory, this property will be updated to the directory path.
47 * @see #createFileChooser
48 */
49 public JFileChooserManager(boolean open, String lastDirProperty) {
50 this(open, lastDirProperty, null);
51 }
52
53 /**
54 * Creates a new {@code JFileChooserManager}.
55 * @param open If true, "Open File" dialogs will be created. If false, "Save File" dialogs will be created.
56 * @param lastDirProperty The name of the property used to get the last directory. This directory is used to initialize the JFileChooser.
57 * Then, if the user effetively choses a file or a directory, this property will be updated to the directory path.
58 * @param defaultDir The default directory used to initialize the JFileChooser if the {@code lastDirProperty} property value is missing.
59 * @see #createFileChooser
60 */
61 public JFileChooserManager(boolean open, String lastDirProperty, String defaultDir) {
62 this.open = open;
63 this.lastDirProperty = lastDirProperty == null || lastDirProperty.isEmpty() ? "lastDirectory" : lastDirProperty;
64 this.curDir = Main.pref.get(this.lastDirProperty).isEmpty() ?
65 (defaultDir == null || defaultDir.isEmpty() ? "." : defaultDir)
66 : Main.pref.get(this.lastDirProperty);
67 }
68
69 /**
70 * Replies the {@code JFileChooser} that has been previously created.
71 * @return The {@code JFileChooser} that has been previously created, or {@code null} if it has not been created yet.
72 * @see #createFileChooser
73 */
74 public final JFileChooser getFileChooser() {
75 return fc;
76 }
77
78 /**
79 * Replies the initial directory used to construct the {@code JFileChooser}.
80 * @return The initial directory used to construct the {@code JFileChooser}.
81 */
82 public final String getInitialDirectory() {
83 return curDir;
84 }
85
86 /**
87 * Creates a new {@link JFileChooser} with default settings. All files will be accepted.
88 * @return this
89 */
90 public final JFileChooserManager createFileChooser() {
91 return doCreateFileChooser(false, null, null, null, null, JFileChooser.FILES_ONLY, false);
92 }
93
94 /**
95 * Creates a new {@link JFileChooser} with given settings for a single {@code FileFilter}.
96 *
97 * @param multiple If true, makes the dialog allow multiple file selections
98 * @param title The string that goes in the dialog window's title bar
99 * @param filter The only file filter that will be proposed by the dialog
100 * @param selectionMode The selection mode that allows the user to:<br/>
101 * <li>just select files ({@code JFileChooser.FILES_ONLY})</li>
102 * <li>just select directories ({@code JFileChooser.DIRECTORIES_ONLY})</li>
103 * <li>select both files and directories ({@code JFileChooser.FILES_AND_DIRECTORIES})</li>
104 * @return this
105 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, FileFilter, int, String)
106 */
107 public final JFileChooserManager createFileChooser(boolean multiple, String title, FileFilter filter, int selectionMode) {
108 doCreateFileChooser(multiple, title, Collections.singleton(filter), filter, null, selectionMode, false);
109 getFileChooser().setAcceptAllFileFilterUsed(false);
110 return this;
111 }
112
113 /**
114 * Creates a new {@link JFileChooser} with given settings for a collection of {@code FileFilter}s.
115 *
116 * @param multiple If true, makes the dialog allow multiple file selections
117 * @param title The string that goes in the dialog window's title bar
118 * @param filters The file filters that will be proposed by the dialog
119 * @param defaultFilter The file filter that will be selected by default
120 * @param selectionMode The selection mode that allows the user to:<br/>
121 * <li>just select files ({@code JFileChooser.FILES_ONLY})</li>
122 * <li>just select directories ({@code JFileChooser.DIRECTORIES_ONLY})</li>
123 * <li>select both files and directories ({@code JFileChooser.FILES_AND_DIRECTORIES})</li>
124 * @return this
125 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, Collection, FileFilter, int, String)
126 */
127 public final JFileChooserManager createFileChooser(boolean multiple, String title, Collection<? extends FileFilter> filters, FileFilter defaultFilter, int selectionMode) {
128 return doCreateFileChooser(multiple, title, filters, defaultFilter, null, selectionMode, false);
129 }
130
131 /**
132 * Creates a new {@link JFileChooser} with given settings for a file extension.
133 *
134 * @param multiple If true, makes the dialog allow multiple file selections
135 * @param title The string that goes in the dialog window's title bar
136 * @param extension The file extension that will be selected as the default file filter
137 * @param allTypes If true, all the files types known by JOSM will be proposed in the "file type" combobox.
138 * If false, only the file filters that include {@code extension} will be proposed
139 * @param selectionMode The selection mode that allows the user to:<br/>
140 * <li>just select files ({@code JFileChooser.FILES_ONLY})</li>
141 * <li>just select directories ({@code JFileChooser.DIRECTORIES_ONLY})</li>
142 * <li>select both files and directories ({@code JFileChooser.FILES_AND_DIRECTORIES})</li>
143 * @return this
144 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, FileFilter, int, String)
145 */
146 public final JFileChooserManager createFileChooser(boolean multiple, String title, String extension, boolean allTypes, int selectionMode) {
147 return doCreateFileChooser(multiple, title, null, null, extension, selectionMode, allTypes);
148 }
149
150 private final JFileChooserManager doCreateFileChooser(boolean multiple, String title, Collection<? extends FileFilter> filters, FileFilter defaultFilter, String extension, int selectionMode, boolean allTypes) {
151 fc = new JFileChooser(new File(curDir));
152 if (title != null) {
153 fc.setDialogTitle(title);
154 }
155
156 fc.setFileSelectionMode(selectionMode);
157 fc.setMultiSelectionEnabled(multiple);
158 fc.setAcceptAllFileFilterUsed(false);
159
160 if (filters != null) {
161 for (FileFilter filter : filters) {
162 fc.addChoosableFileFilter(filter);
163 }
164 if (defaultFilter != null) {
165 fc.setFileFilter(defaultFilter);
166 }
167 } else if (open) {
168 ExtensionFileFilter.applyChoosableImportFileFilters(fc, extension, allTypes);
169 } else {
170 ExtensionFileFilter.applyChoosableExportFileFilters(fc, extension, allTypes);
171 }
172 return this;
173 }
174
175 /**
176 * Opens the {@code JFileChooser} that has been created. Nothing happens if it has not been created yet.
177 * @return the {@code JFileChooser} if the user effectively choses a file or directory. {@code null} if the user cancelled the dialog.
178 */
179 public final JFileChooser openFileChooser() {
180 return openFileChooser(null);
181 }
182
183 /**
184 * Opens the {@code JFileChooser} that has been created and waits for the user to choose a file/directory, or cancel the dialog.<br/>
185 * Nothing happens if the dialog has not been created yet.<br/>
186 * When the user choses a file or directory, the {@code lastDirProperty} is updated to the chosen directory path.
187 *
188 * @param parent The Component used as the parent of the JFileChooser. If null, uses {@code Main.parent}.
189 * @return the {@code JFileChooser} if the user effectively choses a file or directory. {@code null} if the user cancelled the dialog.
190 */
191 public JFileChooser openFileChooser(Component parent) {
192 if (fc != null) {
193 if (parent == null) {
194 parent = Main.parent;
195 }
196
197 int answer = open ? fc.showOpenDialog(parent) : fc.showSaveDialog(parent);
198 if (answer != JFileChooser.APPROVE_OPTION) {
199 return null;
200 }
201
202 if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) {
203 Main.pref.put(lastDirProperty, fc.getCurrentDirectory().getAbsolutePath());
204 }
205
206 if (!open) {
207 File file = fc.getSelectedFile();
208 if (file != null && file.exists()) {
209 ExtendedDialog dialog = new ExtendedDialog(
210 Main.parent,
211 tr("Overwrite"),
212 new String[] {tr("Overwrite"), tr("Cancel")}
213 );
214 dialog.setContent(tr("File exists. Overwrite?"));
215 dialog.setButtonIcons(new String[] {"save_as.png", "cancel.png"});
216 dialog.showDialog();
217 if (dialog.getValue() != 1) {
218 return null;
219 }
220 }
221 }
222 }
223 return fc;
224 }
225}
Note: See TracBrowser for help on using the repository browser.