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

Last change on this file since 9670 was 9670, checked in by bastiK, 8 years ago

applied #12392 - default filename when saving layer (patch by kolesar)

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