source: josm/trunk/src/org/openstreetmap/josm/gui/widgets/FileChooserManager.java@ 13724

Last change on this file since 13724 was 12846, checked in by bastiK, 7 years ago

see #15229 - use Config.getPref() wherever possible

  • Property svn:eol-style set to native
File size: 14.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.widgets;
3
4import java.awt.Component;
5import java.io.File;
6import java.util.Collection;
7import java.util.Collections;
8
9import javax.swing.JFileChooser;
10import javax.swing.filechooser.FileFilter;
11
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.actions.DiskAccessAction;
14import org.openstreetmap.josm.actions.ExtensionFileFilter;
15import org.openstreetmap.josm.actions.SaveActionBase;
16import org.openstreetmap.josm.data.preferences.BooleanProperty;
17import org.openstreetmap.josm.spi.preferences.Config;
18
19/**
20 * A chained utility class used to create and open {@link AbstractFileChooser} dialogs.<br>
21 * Use only this class if you need to control specifically your AbstractFileChooser dialog.<br>
22 * <p>
23 * A simpler usage is to call the {@link DiskAccessAction#createAndOpenFileChooser} methods.
24 *
25 * @since 5438 (creation)
26 * @since 7578 (rename)
27 */
28public class FileChooserManager {
29
30 /**
31 * Property to enable use of native file dialogs.
32 */
33 public static final BooleanProperty PROP_USE_NATIVE_FILE_DIALOG = new BooleanProperty("use.native.file.dialog",
34 // Native dialogs do not support file filters, so do not set them as default, except for OS X where they never worked
35 Main.isPlatformOsx());
36
37 private final boolean open;
38 private final String lastDirProperty;
39 private final String curDir;
40
41 private boolean multiple;
42 private String title;
43 private Collection<? extends FileFilter> filters;
44 private FileFilter defaultFilter;
45 private int selectionMode = JFileChooser.FILES_ONLY;
46 private String extension;
47 private boolean allTypes;
48 private File file;
49
50 private AbstractFileChooser fc;
51
52 /**
53 * Creates a new {@code FileChooserManager} with default values.
54 * @see #createFileChooser
55 */
56 public FileChooserManager() {
57 this(false, null, null);
58 }
59
60 /**
61 * Creates a new {@code FileChooserManager}.
62 * @param open If true, "Open File" dialogs will be created. If false, "Save File" dialogs will be created.
63 * @see #createFileChooser
64 */
65 public FileChooserManager(boolean open) {
66 this(open, null);
67 }
68
69 // CHECKSTYLE.OFF: LineLength
70
71 /**
72 * Creates a new {@code FileChooserManager}.
73 * @param open If true, "Open File" dialogs will be created. If false, "Save File" dialogs will be created.
74 * @param lastDirProperty The name of the property used to get the last directory. This directory is used to initialize the AbstractFileChooser.
75 * Then, if the user effectively chooses a file or a directory, this property will be updated to the directory path.
76 * @see #createFileChooser
77 */
78 public FileChooserManager(boolean open, String lastDirProperty) {
79 this(open, lastDirProperty, null);
80 }
81
82 /**
83 * Creates a new {@code FileChooserManager}.
84 * @param open If true, "Open File" dialogs will be created. If false, "Save File" dialogs will be created.
85 * @param lastDirProperty The name of the property used to get the last directory. This directory is used to initialize the AbstractFileChooser.
86 * Then, if the user effectively chooses a file or a directory, this property will be updated to the directory path.
87 * @param defaultDir The default directory used to initialize the AbstractFileChooser if the {@code lastDirProperty} property value is missing.
88 * @see #createFileChooser
89 */
90 public FileChooserManager(boolean open, String lastDirProperty, String defaultDir) {
91 this.open = open;
92 this.lastDirProperty = lastDirProperty == null || lastDirProperty.isEmpty() ? "lastDirectory" : lastDirProperty;
93 this.curDir = Config.getPref().get(this.lastDirProperty).isEmpty() ?
94 defaultDir == null || defaultDir.isEmpty() ? "." : defaultDir
95 : Config.getPref().get(this.lastDirProperty);
96 }
97
98 // CHECKSTYLE.ON: LineLength
99
100 /**
101 * Replies the {@code AbstractFileChooser} that has been previously created.
102 * @return The {@code AbstractFileChooser} that has been previously created, or {@code null} if it has not been created yet.
103 * @see #createFileChooser
104 */
105 public final AbstractFileChooser getFileChooser() {
106 return fc;
107 }
108
109 /**
110 * Replies the initial directory used to construct the {@code AbstractFileChooser}.
111 * @return The initial directory used to construct the {@code AbstractFileChooser}.
112 */
113 public final String getInitialDirectory() {
114 return curDir;
115 }
116
117 /**
118 * Creates a new {@link AbstractFileChooser} with default settings. All files will be accepted.
119 * @return this
120 */
121 public final FileChooserManager createFileChooser() {
122 return doCreateFileChooser();
123 }
124
125 /**
126 * Creates a new {@link AbstractFileChooser} with given settings for a single {@code FileFilter}.
127 *
128 * @param multiple If true, makes the dialog allow multiple file selections
129 * @param title The string that goes in the dialog window's title bar
130 * @param filter The only file filter that will be proposed by the dialog
131 * @param selectionMode The selection mode that allows the user to:<br><ul>
132 * <li>just select files ({@code JFileChooser.FILES_ONLY})</li>
133 * <li>just select directories ({@code JFileChooser.DIRECTORIES_ONLY})</li>
134 * <li>select both files and directories ({@code JFileChooser.FILES_AND_DIRECTORIES})</li></ul>
135 * @return this
136 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, FileFilter, int, String)
137 */
138 public final FileChooserManager createFileChooser(boolean multiple, String title, FileFilter filter, int selectionMode) {
139 multiple(multiple);
140 title(title);
141 filters(Collections.singleton(filter));
142 defaultFilter(filter);
143 selectionMode(selectionMode);
144
145 doCreateFileChooser();
146 fc.setAcceptAllFileFilterUsed(false);
147 return this;
148 }
149
150 /**
151 * Creates a new {@link AbstractFileChooser} with given settings for a collection of {@code FileFilter}s.
152 *
153 * @param multiple If true, makes the dialog allow multiple file selections
154 * @param title The string that goes in the dialog window's title bar
155 * @param filters The file filters that will be proposed by the dialog
156 * @param defaultFilter The file filter that will be selected by default
157 * @param selectionMode The selection mode that allows the user to:<br><ul>
158 * <li>just select files ({@code JFileChooser.FILES_ONLY})</li>
159 * <li>just select directories ({@code JFileChooser.DIRECTORIES_ONLY})</li>
160 * <li>select both files and directories ({@code JFileChooser.FILES_AND_DIRECTORIES})</li></ul>
161 * @return this
162 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, Collection, FileFilter, int, String)
163 */
164 public final FileChooserManager createFileChooser(boolean multiple, String title, Collection<? extends FileFilter> filters,
165 FileFilter defaultFilter, int selectionMode) {
166 multiple(multiple);
167 title(title);
168 filters(filters);
169 defaultFilter(defaultFilter);
170 selectionMode(selectionMode);
171 return doCreateFileChooser();
172 }
173
174 /**
175 * Creates a new {@link AbstractFileChooser} with given settings for a file extension.
176 *
177 * @param multiple If true, makes the dialog allow multiple file selections
178 * @param title The string that goes in the dialog window's title bar
179 * @param extension The file extension that will be selected as the default file filter
180 * @param allTypes If true, all the files types known by JOSM will be proposed in the "file type" combobox.
181 * If false, only the file filters that include {@code extension} will be proposed
182 * @param selectionMode The selection mode that allows the user to:<br><ul>
183 * <li>just select files ({@code JFileChooser.FILES_ONLY})</li>
184 * <li>just select directories ({@code JFileChooser.DIRECTORIES_ONLY})</li>
185 * <li>select both files and directories ({@code JFileChooser.FILES_AND_DIRECTORIES})</li></ul>
186 * @return this
187 * @see DiskAccessAction#createAndOpenFileChooser(boolean, boolean, String, FileFilter, int, String)
188 */
189 public final FileChooserManager createFileChooser(boolean multiple, String title, String extension, boolean allTypes, int selectionMode) {
190 multiple(multiple);
191 title(title);
192 extension(extension);
193 allTypes(allTypes);
194 selectionMode(selectionMode);
195 return doCreateFileChooser();
196 }
197
198 /**
199 * Builder method to set {@code multiple} property.
200 * @param value If true, makes the dialog allow multiple file selections
201 * @return this
202 */
203 public FileChooserManager multiple(boolean value) {
204 multiple = value;
205 return this;
206 }
207
208 /**
209 * Builder method to set {@code title} property.
210 * @param value The string that goes in the dialog window's title bar
211 * @return this
212 */
213 public FileChooserManager title(String value) {
214 title = value;
215 return this;
216 }
217
218 /**
219 * Builder method to set {@code filters} property.
220 * @param value The file filters that will be proposed by the dialog
221 * @return this
222 */
223 public FileChooserManager filters(Collection<? extends FileFilter> value) {
224 filters = value;
225 return this;
226 }
227
228 /**
229 * Builder method to set {@code defaultFilter} property.
230 * @param value The file filter that will be selected by default
231 * @return this
232 */
233 public FileChooserManager defaultFilter(FileFilter value) {
234 defaultFilter = value;
235 return this;
236 }
237
238 /**
239 * Builder method to set {@code selectionMode} property.
240 * @param value The selection mode that allows the user to:<br><ul>
241 * <li>just select files ({@code JFileChooser.FILES_ONLY})</li>
242 * <li>just select directories ({@code JFileChooser.DIRECTORIES_ONLY})</li>
243 * <li>select both files and directories ({@code JFileChooser.FILES_AND_DIRECTORIES})</li></ul>
244 * @return this
245 */
246 public FileChooserManager selectionMode(int value) {
247 selectionMode = value;
248 return this;
249 }
250
251 /**
252 * Builder method to set {@code extension} property.
253 * @param value The file extension that will be selected as the default file filter
254 * @return this
255 */
256 public FileChooserManager extension(String value) {
257 extension = value;
258 return this;
259 }
260
261 /**
262 * Builder method to set {@code allTypes} property.
263 * @param value If true, all the files types known by JOSM will be proposed in the "file type" combobox.
264 * If false, only the file filters that include {@code extension} will be proposed
265 * @return this
266 */
267 public FileChooserManager allTypes(boolean value) {
268 allTypes = value;
269 return this;
270 }
271
272 /**
273 * Builder method to set {@code file} property.
274 * @param value {@link File} object with default filename
275 * @return this
276 */
277 public FileChooserManager file(File value) {
278 file = value;
279 return this;
280 }
281
282 /**
283 * Builds {@code FileChooserManager} object using properties set by builder methods or default values.
284 * @return this
285 */
286 public FileChooserManager doCreateFileChooser() {
287 File f = new File(curDir);
288 // Use native dialog is preference is set, unless an unsupported selection mode is specifically wanted
289 if (PROP_USE_NATIVE_FILE_DIALOG.get() && NativeFileChooser.supportsSelectionMode(selectionMode)) {
290 fc = new NativeFileChooser(f);
291 } else {
292 fc = new SwingFileChooser(f);
293 }
294
295 if (title != null) {
296 fc.setDialogTitle(title);
297 }
298
299 fc.setFileSelectionMode(selectionMode);
300 fc.setMultiSelectionEnabled(multiple);
301 fc.setAcceptAllFileFilterUsed(false);
302 fc.setSelectedFile(this.file);
303
304 if (filters != null) {
305 for (FileFilter filter : filters) {
306 fc.addChoosableFileFilter(filter);
307 }
308 if (defaultFilter != null) {
309 fc.setFileFilter(defaultFilter);
310 }
311 } else if (open) {
312 ExtensionFileFilter.applyChoosableImportFileFilters(fc, extension, allTypes);
313 } else {
314 ExtensionFileFilter.applyChoosableExportFileFilters(fc, extension, allTypes);
315 }
316 return this;
317 }
318
319 /**
320 * Opens the {@code AbstractFileChooser} that has been created.
321 * @return the {@code AbstractFileChooser} if the user effectively choses a file or directory. {@code null} if the user cancelled the dialog.
322 */
323 public final AbstractFileChooser openFileChooser() {
324 return openFileChooser(null);
325 }
326
327 /**
328 * Opens the {@code AbstractFileChooser} that has been created and waits for the user to choose a file/directory, or cancel the dialog.<br>
329 * When the user choses a file or directory, the {@code lastDirProperty} is updated to the chosen directory path.
330 *
331 * @param parent The Component used as the parent of the AbstractFileChooser. If null, uses {@code Main.parent}.
332 * @return the {@code AbstractFileChooser} if the user effectively choses a file or directory. {@code null} if the user cancelled the dialog.
333 */
334 public AbstractFileChooser openFileChooser(Component parent) {
335 if (fc == null)
336 doCreateFileChooser();
337
338 if (parent == null) {
339 parent = Main.parent;
340 }
341
342 int answer = open ? fc.showOpenDialog(parent) : fc.showSaveDialog(parent);
343 if (answer != JFileChooser.APPROVE_OPTION) {
344 return null;
345 }
346
347 if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) {
348 Config.getPref().put(lastDirProperty, fc.getCurrentDirectory().getAbsolutePath());
349 }
350
351 if (!open && !FileChooserManager.PROP_USE_NATIVE_FILE_DIALOG.get() &&
352 !SaveActionBase.confirmOverwrite(fc.getSelectedFile())) {
353 return null;
354 }
355 return fc;
356 }
357
358 /**
359 * Opens the file chooser dialog, then checks if filename has the given extension.
360 * If not, adds the extension and asks for overwrite if filename exists.
361 *
362 * @return the {@code File} or {@code null} if the user cancelled the dialog.
363 */
364 public File getFileForSave() {
365 return SaveActionBase.checkFileAndConfirmOverWrite(openFileChooser(), extension);
366 }
367}
Note: See TracBrowser for help on using the repository browser.