source: josm/trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java@ 7608

Last change on this file since 7608 was 7578, checked in by Don-vip, 10 years ago

fix #10024 - Add an option in Preferences/Look-and-Feel to use native file-choosing dialogs.
They look nicer but they do not support file filters, so we cannot use them (yet) as default.
Based on patch by Lesath and code review by simon04.
The native dialogs are not used if selection mode is not supported ("files and directories" on all platforms, "directories" on systems other than OS X)

  • Property svn:eol-style set to native
File size: 13.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import java.io.File;
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.Comparator;
8import java.util.LinkedList;
9import java.util.List;
10import java.util.ServiceConfigurationError;
11
12import javax.swing.filechooser.FileFilter;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.gui.MapView;
16import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
17import org.openstreetmap.josm.io.AllFormatsImporter;
18import org.openstreetmap.josm.io.FileExporter;
19import org.openstreetmap.josm.io.FileImporter;
20
21/**
22 * A file filter that filters after the extension. Also includes a list of file
23 * filters used in JOSM.
24 * @since 32
25 */
26public class ExtensionFileFilter extends FileFilter implements java.io.FileFilter {
27
28 /**
29 * List of supported formats for import.
30 * @since 4869
31 */
32 public static final ArrayList<FileImporter> importers;
33
34 /**
35 * List of supported formats for export.
36 * @since 4869
37 */
38 public static final ArrayList<FileExporter> exporters;
39
40 // add some file types only if the relevant classes are there.
41 // this gives us the option to painlessly drop them from the .jar
42 // and build JOSM versions without support for these formats
43
44 static {
45
46 importers = new ArrayList<>();
47
48 String[] importerNames = {
49 "org.openstreetmap.josm.io.OsmImporter",
50 "org.openstreetmap.josm.io.OsmGzipImporter",
51 "org.openstreetmap.josm.io.OsmZipImporter",
52 "org.openstreetmap.josm.io.OsmChangeImporter",
53 "org.openstreetmap.josm.io.GpxImporter",
54 "org.openstreetmap.josm.io.NMEAImporter",
55 "org.openstreetmap.josm.io.NoteImporter",
56 "org.openstreetmap.josm.io.OsmBzip2Importer",
57 "org.openstreetmap.josm.io.JpgImporter",
58 "org.openstreetmap.josm.io.WMSLayerImporter",
59 "org.openstreetmap.josm.io.AllFormatsImporter",
60 "org.openstreetmap.josm.io.session.SessionImporter"
61 };
62
63 for (String classname : importerNames) {
64 try {
65 FileImporter importer = (FileImporter) Class.forName(classname).newInstance();
66 importers.add(importer);
67 MapView.addLayerChangeListener(importer);
68 } catch (Exception e) {
69 if (Main.isDebugEnabled()) {
70 Main.debug(e.getMessage());
71 }
72 } catch (ServiceConfigurationError e) {
73 // error seen while initializing WMSLayerImporter in plugin unit tests:
74 // -
75 // ServiceConfigurationError: javax.imageio.spi.ImageWriterSpi:
76 // Provider com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageWriterSpi could not be instantiated
77 // Caused by: java.lang.IllegalArgumentException: vendorName == null!
78 // at javax.imageio.spi.IIOServiceProvider.<init>(IIOServiceProvider.java:76)
79 // at javax.imageio.spi.ImageReaderWriterSpi.<init>(ImageReaderWriterSpi.java:231)
80 // at javax.imageio.spi.ImageWriterSpi.<init>(ImageWriterSpi.java:213)
81 // at com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageWriterSpi.<init>(CLibJPEGImageWriterSpi.java:84)
82 // -
83 // This is a very strange behaviour of JAI:
84 // http://thierrywasyl.wordpress.com/2009/07/24/jai-how-to-solve-vendorname-null-exception/
85 // -
86 // that can lead to various problems, see #8583 comments
87 Main.error(e);
88 }
89 }
90
91 exporters = new ArrayList<>();
92
93 String[] exporterNames = {
94 "org.openstreetmap.josm.io.GpxExporter",
95 "org.openstreetmap.josm.io.OsmExporter",
96 "org.openstreetmap.josm.io.OsmGzipExporter",
97 "org.openstreetmap.josm.io.OsmBzip2Exporter",
98 "org.openstreetmap.josm.io.GeoJSONExporter",
99 "org.openstreetmap.josm.io.WMSLayerExporter"
100 };
101
102 for (String classname : exporterNames) {
103 try {
104 FileExporter exporter = (FileExporter)Class.forName(classname).newInstance();
105 exporters.add(exporter);
106 MapView.addLayerChangeListener(exporter);
107 } catch (Exception e) {
108 if (Main.isDebugEnabled()) {
109 Main.debug(e.getMessage());
110 }
111 } catch (ServiceConfigurationError e) {
112 // see above in importers initialization
113 Main.error(e);
114 }
115 }
116 }
117
118 private final String extensions;
119 private final String description;
120 private final String defaultExtension;
121
122 protected static void sort(List<ExtensionFileFilter> filters) {
123 Collections.sort(
124 filters,
125 new Comparator<ExtensionFileFilter>() {
126 private AllFormatsImporter all = new AllFormatsImporter();
127 @Override
128 public int compare(ExtensionFileFilter o1, ExtensionFileFilter o2) {
129 if (o1.getDescription().equals(all.filter.getDescription())) return 1;
130 if (o2.getDescription().equals(all.filter.getDescription())) return -1;
131 return o1.getDescription().compareTo(o2.getDescription());
132 }
133 }
134 );
135 }
136
137 /**
138 * Updates the {@link AllFormatsImporter} that is contained in the importers list. If
139 * you do not use the importers variable directly, you don’t need to call this.
140 * <p>
141 * Updating the AllFormatsImporter is required when plugins add new importers that
142 * support new file extensions. The old AllFormatsImporter doesn’t include the new
143 * extensions and thus will not display these files.
144 *
145 * @since 5131
146 */
147 public static void updateAllFormatsImporter() {
148 for(int i=0; i < importers.size(); i++) {
149 if(importers.get(i) instanceof AllFormatsImporter) {
150 importers.set(i, new AllFormatsImporter());
151 }
152 }
153 }
154
155 /**
156 * Replies an ordered list of {@link ExtensionFileFilter}s for importing.
157 * The list is ordered according to their description, an {@link AllFormatsImporter}
158 * is append at the end.
159 *
160 * @return an ordered list of {@link ExtensionFileFilter}s for importing.
161 * @since 2029
162 */
163 public static List<ExtensionFileFilter> getImportExtensionFileFilters() {
164 updateAllFormatsImporter();
165 LinkedList<ExtensionFileFilter> filters = new LinkedList<>();
166 for (FileImporter importer : importers) {
167 filters.add(importer.filter);
168 }
169 sort(filters);
170 return filters;
171 }
172
173 /**
174 * Replies an ordered list of enabled {@link ExtensionFileFilter}s for exporting.
175 * The list is ordered according to their description, an {@link AllFormatsImporter}
176 * is append at the end.
177 *
178 * @return an ordered list of enabled {@link ExtensionFileFilter}s for exporting.
179 * @since 2029
180 */
181 public static List<ExtensionFileFilter> getExportExtensionFileFilters() {
182 LinkedList<ExtensionFileFilter> filters = new LinkedList<>();
183 for (FileExporter exporter : exporters) {
184 if (filters.contains(exporter.filter) || !exporter.isEnabled()) {
185 continue;
186 }
187 filters.add(exporter.filter);
188 }
189 sort(filters);
190 return filters;
191 }
192
193 /**
194 * Replies the default {@link ExtensionFileFilter} for a given extension
195 *
196 * @param extension the extension
197 * @return the default {@link ExtensionFileFilter} for a given extension
198 * @since 2029
199 */
200 public static ExtensionFileFilter getDefaultImportExtensionFileFilter(String extension) {
201 if (extension == null) return new AllFormatsImporter().filter;
202 for (FileImporter importer : importers) {
203 if (extension.equals(importer.filter.getDefaultExtension()))
204 return importer.filter;
205 }
206 return new AllFormatsImporter().filter;
207 }
208
209 /**
210 * Replies the default {@link ExtensionFileFilter} for a given extension
211 *
212 * @param extension the extension
213 * @return the default {@link ExtensionFileFilter} for a given extension
214 * @since 2029
215 */
216 public static ExtensionFileFilter getDefaultExportExtensionFileFilter(String extension) {
217 if (extension == null) return new AllFormatsImporter().filter;
218 for (FileExporter exporter : exporters) {
219 if (extension.equals(exporter.filter.getDefaultExtension()))
220 return exporter.filter;
221 }
222 return new AllFormatsImporter().filter;
223 }
224
225 /**
226 * Applies the choosable {@link FileFilter} to a {@link AbstractFileChooser} before using the
227 * file chooser for selecting a file for reading.
228 *
229 * @param fileChooser the file chooser
230 * @param extension the default extension
231 * @param allTypes If true, all the files types known by JOSM will be proposed in the "file type" combobox.
232 * If false, only the file filters that include {@code extension} will be proposed
233 * @since 5438
234 */
235 public static void applyChoosableImportFileFilters(AbstractFileChooser fileChooser, String extension, boolean allTypes) {
236 for (ExtensionFileFilter filter: getImportExtensionFileFilters()) {
237 if (allTypes || filter.acceptName("file."+extension)) {
238 fileChooser.addChoosableFileFilter(filter);
239 }
240 }
241 fileChooser.setFileFilter(getDefaultImportExtensionFileFilter(extension));
242 }
243
244 /**
245 * Applies the choosable {@link FileFilter} to a {@link AbstractFileChooser} before using the
246 * file chooser for selecting a file for writing.
247 *
248 * @param fileChooser the file chooser
249 * @param extension the default extension
250 * @param allTypes If true, all the files types known by JOSM will be proposed in the "file type" combobox.
251 * If false, only the file filters that include {@code extension} will be proposed
252 * @since 5438
253 */
254 public static void applyChoosableExportFileFilters(AbstractFileChooser fileChooser, String extension, boolean allTypes) {
255 for (ExtensionFileFilter filter: getExportExtensionFileFilters()) {
256 if (allTypes || filter.acceptName("file."+extension)) {
257 fileChooser.addChoosableFileFilter(filter);
258 }
259 }
260 fileChooser.setFileFilter(getDefaultExportExtensionFileFilter(extension));
261 }
262
263 /**
264 * Construct an extension file filter by giving the extension to check after.
265 * @param extension The comma-separated list of file extensions
266 * @param defaultExtension The default extension
267 * @param description A short textual description of the file type
268 * @since 1169
269 */
270 public ExtensionFileFilter(String extension, String defaultExtension, String description) {
271 this.extensions = extension;
272 this.defaultExtension = defaultExtension;
273 this.description = description;
274 }
275
276 /**
277 * Returns true if this file filter accepts the given filename.
278 * @param filename The filename to check after
279 * @return true if this file filter accepts the given filename (i.e if this filename ends with one of the extensions)
280 * @since 1169
281 */
282 public boolean acceptName(String filename) {
283 String name = filename.toLowerCase();
284 for (String ext : extensions.split(","))
285 if (name.endsWith("."+ext))
286 return true;
287 return false;
288 }
289
290 @Override
291 public boolean accept(File pathname) {
292 if (pathname.isDirectory())
293 return true;
294 return acceptName(pathname.getName());
295 }
296
297 @Override
298 public String getDescription() {
299 return description;
300 }
301
302 /**
303 * Replies the comma-separated list of file extensions of this file filter.
304 * @return the comma-separated list of file extensions of this file filter, as a String
305 * @since 5131
306 */
307 public String getExtensions() {
308 return extensions;
309 }
310
311 /**
312 * Replies the default file extension of this file filter.
313 * @return the default file extension of this file filter
314 * @since 2029
315 */
316 public String getDefaultExtension() {
317 return defaultExtension;
318 }
319
320 @Override
321 public int hashCode() {
322 final int prime = 31;
323 int result = 1;
324 result = prime * result + ((defaultExtension == null) ? 0 : defaultExtension.hashCode());
325 result = prime * result + ((description == null) ? 0 : description.hashCode());
326 result = prime * result + ((extensions == null) ? 0 : extensions.hashCode());
327 return result;
328 }
329
330 @Override
331 public boolean equals(Object obj) {
332 if (this == obj)
333 return true;
334 if (obj == null)
335 return false;
336 if (getClass() != obj.getClass())
337 return false;
338 ExtensionFileFilter other = (ExtensionFileFilter) obj;
339 if (defaultExtension == null) {
340 if (other.defaultExtension != null)
341 return false;
342 } else if (!defaultExtension.equals(other.defaultExtension))
343 return false;
344 if (description == null) {
345 if (other.description != null)
346 return false;
347 } else if (!description.equals(other.description))
348 return false;
349 if (extensions == null) {
350 if (other.extensions != null)
351 return false;
352 } else if (!extensions.equals(other.extensions))
353 return false;
354 return true;
355 }
356}
Note: See TracBrowser for help on using the repository browser.