1 package fr.ifremer.quadrige3.ui.swing.action;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import com.google.common.collect.ImmutableList;
25 import org.apache.commons.collections4.CollectionUtils;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 import javax.swing.Action;
31 import javax.swing.JFileChooser;
32 import javax.swing.filechooser.FileFilter;
33 import java.awt.Component;
34 import java.io.File;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.List;
38 import java.util.stream.Collectors;
39
40
41
42
43
44
45 public class FileChooser {
46
47
48
49
50
51
52 public static ToLoadFile forLoadingFile() {
53 return new FileChooserBuilderImpl(ChooseMode.LOAD_FILE);
54 }
55
56
57
58
59
60
61 public static ToLoadFiles forLoadingFiles() {
62 return new FileChooserBuilderImpl(ChooseMode.LOAD_FILES);
63 }
64
65
66
67
68
69
70 public static ToLoadDirectory forLoadingDirectory() {
71 return new FileChooserBuilderImpl(ChooseMode.LOAD_DIRECTORY);
72 }
73
74
75
76
77
78
79 public static ToSave forSaving() {
80 return new FileChooserBuilderImpl(ChooseMode.SAVE);
81 }
82
83 public static void setCurrentDirectory(File dir) {
84 currentDirectory = dir;
85 }
86
87 public static File getCurrentDirectory() {
88 return currentDirectory;
89 }
90
91 public static boolean isCurrentDirectoryDefault() {
92 return currentDirectory.equals(DEFAULT_CURRENT_DIRECTORY_FILE);
93 }
94
95
96
97
98 private static final Log log = LogFactory.getLog(FileChooser.class);
99
100 public static final File DEFAULT_CURRENT_DIRECTORY_FILE = new File(".");
101
102 protected static File currentDirectory = DEFAULT_CURRENT_DIRECTORY_FILE;
103
104 public interface FileResult {
105
106 File getFile();
107
108 List<File> getFiles();
109
110 }
111
112 private interface ChooseResult {
113
114 FileResult choose();
115
116 }
117
118 public interface ToLoadFile extends ChooseResult {
119
120 ToLoadFile setTitle(String title);
121
122 ToLoadFile setApprovalText(String approvalText);
123
124 ToLoadFile setParent(Component parent);
125
126 ToLoadFile setPatternOrDescriptionFilters(List<String> patternOrDescriptionFilters);
127
128 ToLoadFile setPatternOrDescriptionFilters(String pattern, String description, String... patternOrDescriptionFilters);
129
130 ToLoadFile setFileFilters(FileFilter fileFilter, FileFilter... fileFilters);
131
132 ToLoadFile setFileFilters(List<FileFilter> fileFilters);
133
134 ToLoadFile setShowFiles(boolean showFiles);
135
136 ToLoadFile setShowDirectories(boolean showDirectories);
137
138 ToLoadFile setFileHidingEnabled(boolean useFileHiding);
139
140 ToLoadFile setUseAcceptAllFileFilter(boolean useAcceptAllFileFilter);
141
142 ToLoadFile setStartDirectory(File startDirectory);
143
144 ToLoadFile setKeepCurrentDirectory(boolean keepCurrentDirectory);
145
146 }
147
148 public interface ToLoadFiles extends ChooseResult {
149
150 ToLoadFile setTitle(String title);
151
152 ToLoadFile setApprovalText(String approvalText);
153
154 ToLoadFile setParent(Component parent);
155
156 ToLoadFile setPatternOrDescriptionFilters(List<String> patternOrDescriptionFilters);
157
158 ToLoadFile setPatternOrDescriptionFilters(String pattern, String description, String... patternOrDescriptionFilters);
159
160 ToLoadFile setFileFilters(FileFilter fileFilter, FileFilter... fileFilters);
161
162 ToLoadFile setFileFilters(List<FileFilter> fileFilters);
163
164 ToLoadFile setShowFiles(boolean showFiles);
165
166 ToLoadFile setShowDirectories(boolean showDirectories);
167
168 ToLoadFile setFileHidingEnabled(boolean useFileHiding);
169
170 ToLoadFile setUseAcceptAllFileFilter(boolean useAcceptAllFileFilter);
171
172 ToLoadFile setStartDirectory(File startDirectory);
173
174 ToLoadFile setKeepCurrentDirectory(boolean keepCurrentDirectory);
175
176 }
177
178 public interface ToLoadDirectory extends ChooseResult {
179
180 ToLoadDirectory setTitle(String title);
181
182 ToLoadDirectory setApprovalText(String approvalText);
183
184 ToLoadDirectory setParent(Component parent);
185
186 ToLoadDirectory setStartDirectory(File startDirectory);
187
188 ToLoadDirectory setKeepCurrentDirectory(boolean keepCurrentDirectory);
189
190 }
191
192 public interface ToSave extends ChooseResult {
193
194 ToSave setTitle(String title);
195
196 ToSave setApprovalText(String approvalText);
197
198 ToSave setParent(Component parent);
199
200 ToSave setPatternOrDescriptionFilters(List<String> patternOrDescriptionFilters);
201
202 ToSave setPatternOrDescriptionFilters(String pattern, String description, String... patternOrDescriptionFilters);
203
204 ToSave setFileFilters(FileFilter fileFilter, FileFilter... fileFilters);
205
206 ToSave setFileFilters(List<FileFilter> fileFilters);
207
208 ToSave setFileHidingEnabled(boolean useFileHiding);
209
210 ToSave setUseAcceptAllFileFilter(boolean useAcceptAllFileFilter);
211
212 ToSave setFilename(String filename);
213
214 ToSave setStartDirectory(File startDirectory);
215
216 ToSave setKeepCurrentDirectory(boolean keepCurrentDirectory);
217
218 }
219
220 private enum ChooseMode {
221 LOAD_FILE,
222 LOAD_FILES,
223 LOAD_DIRECTORY,
224 SAVE
225 }
226
227 static class EmptyResult implements FileResult {
228
229 @Override
230 public File getFile() {
231 return null;
232 }
233
234 @Override
235 public List<File> getFiles() {
236 return null;
237 }
238 }
239
240 static class FileResultImpl implements FileResult {
241
242 private List<File> result;
243
244 public FileResultImpl(List<File> result) {
245 this.result = result;
246 }
247
248 public FileResultImpl(File[] files) {
249 this.result = new ArrayList<>(Arrays.asList(files));
250 }
251
252 public FileResultImpl(File file) {
253 this.result = ImmutableList.of(file);
254 }
255
256 @Override
257 public File getFile() {
258 return CollectionUtils.size(result) > 0 ? result.get(0) : null;
259 }
260
261 @Override
262 public List<File> getFiles() {
263 return result;
264 }
265 }
266
267 static class FileChooserBuilderImpl implements ToLoadFile, ToLoadFiles, ToLoadDirectory, ToSave {
268
269 private final ChooseMode chooseMode;
270
271 protected String title;
272
273 protected File startDirectory;
274
275 protected String approvalText;
276
277 protected Component parent;
278
279 protected List<FileFilter> fileFilters;
280
281 protected boolean showFiles;
282
283 protected boolean showDirectories;
284
285 protected boolean fileHidingEnabled;
286
287 protected boolean useAcceptAllFileFilter;
288
289 protected boolean keepCurrentDirectory = true;
290
291 protected String filename;
292
293 FileChooserBuilderImpl(ChooseMode chooseMode) {
294 this.chooseMode = chooseMode;
295 }
296
297 @Override
298 public FileChooserBuilderImpl setTitle(String title) {
299 this.title = title;
300 return this;
301 }
302
303 @Override
304 public FileChooserBuilderImpl setApprovalText(String approvalText) {
305 this.approvalText = approvalText;
306 return this;
307 }
308
309 @Override
310 public FileChooserBuilderImpl setStartDirectory(File startDirectory) {
311 this.startDirectory = startDirectory;
312 return this;
313 }
314
315 @Override
316 public FileChooserBuilderImpl setParent(Component parent) {
317 this.parent = parent;
318 return this;
319 }
320
321 @Override
322 public FileChooserBuilderImpl setPatternOrDescriptionFilters(String pattern, String description, String... patternOrDescriptionFilters) {
323 List<String> r = new ArrayList<>();
324 r.add(pattern);
325 r.add(description);
326 r.addAll(Arrays.asList(patternOrDescriptionFilters));
327 setPatternOrDescriptionFilters(r);
328 return this;
329 }
330
331 @Override
332 public FileChooserBuilderImpl setPatternOrDescriptionFilters(List<String> patternOrDescriptionFilters) {
333
334 List<FileFilter> r = new ArrayList<>();
335 if (patternOrDescriptionFilters.size() % 2 != 0) {
336 throw new IllegalArgumentException(
337 "Arguments must be (pattern, description) couple");
338 }
339 for (int i = 0, nbFilters = patternOrDescriptionFilters.size() / 2; i < nbFilters; i++) {
340 String pattern = patternOrDescriptionFilters.get(i * 2);
341 String description = patternOrDescriptionFilters.get(i * 2 + 1);
342 r.add(new FileChooserBuilderImpl.PatternChooserFilter(pattern, description));
343 }
344
345 return setFileFilters(r);
346
347 }
348
349 @Override
350 public FileChooserBuilderImpl setFileFilters(FileFilter fileFilter, FileFilter... fileFilters) {
351 List<FileFilter> r = new ArrayList<>();
352 r.add(fileFilter);
353 r.addAll(Arrays.asList(fileFilters));
354 return setFileFilters(r);
355 }
356
357 @Override
358 public FileChooserBuilderImpl setFileFilters(List<FileFilter> fileFilters) {
359 this.fileFilters = fileFilters;
360 return this;
361 }
362
363 @Override
364 public FileChooserBuilderImpl setShowFiles(boolean showFiles) {
365 this.showFiles = showFiles;
366 return this;
367 }
368
369 @Override
370 public FileChooserBuilderImpl setShowDirectories(boolean showDirectories) {
371 this.showDirectories = showDirectories;
372 return this;
373 }
374
375 @Override
376 public FileChooserBuilderImpl setFileHidingEnabled(boolean fileHidingEnabled) {
377 this.fileHidingEnabled = fileHidingEnabled;
378 return this;
379 }
380
381 @Override
382 public FileChooserBuilderImpl setUseAcceptAllFileFilter(boolean useAcceptAllFileFilter) {
383 this.useAcceptAllFileFilter = useAcceptAllFileFilter;
384 return this;
385 }
386
387 @Override
388 public FileChooserBuilderImpl setFilename(String filename) {
389 this.filename = filename;
390 return this;
391 }
392
393 @Override
394 public FileChooserBuilderImpl setKeepCurrentDirectory(boolean keepCurrentDirectory) {
395 this.keepCurrentDirectory = keepCurrentDirectory;
396 return this;
397 }
398
399 @Override
400 public FileResult choose() {
401
402 FileResult result = null;
403 switch (chooseMode) {
404 case LOAD_FILE:
405 result = chooseToLoadFile();
406 break;
407 case LOAD_FILES:
408 result = chooseToLoadFiles();
409 break;
410 case LOAD_DIRECTORY:
411 result = chooseToLoadDirectory();
412 break;
413 case SAVE:
414 result = chooseToSave();
415 break;
416 }
417
418 return result;
419
420 }
421
422 protected FileResult chooseToLoadFile() {
423
424 try {
425
426 File directory;
427
428 if (startDirectory == null) {
429 directory = getCurrentDirectory();
430 } else {
431 directory = startDirectory;
432 }
433
434 JFileChooser chooser = new JFileChooser(directory);
435
436 chooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
437 if (CollectionUtils.isNotEmpty(fileFilters)) {
438 for (FileFilter filter : fileFilters) {
439 chooser.addChoosableFileFilter(filter);
440 }
441 chooser.setFileFilter(fileFilters.get(0));
442 }
443
444 chooser.setAcceptAllFileFilterUsed(useAcceptAllFileFilter);
445 chooser.setFileHidingEnabled(fileHidingEnabled);
446
447 if (showFiles) {
448 if (showDirectories) {
449 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
450 } else {
451 chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
452 }
453 } else if (showDirectories) {
454 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
455 }
456
457 chooser.setDialogTitle(title);
458 int returnVal = chooser.showDialog(parent, approvalText);
459 if (returnVal == JFileChooser.APPROVE_OPTION) {
460 File theFile = chooser.getSelectedFile();
461 if (theFile != null) {
462 if (keepCurrentDirectory) {
463 setCurrentDirectory(theFile.getParentFile());
464 }
465 return new FileResultImpl(theFile.getAbsoluteFile());
466 }
467 }
468
469 } catch (Exception eee) {
470 if (log.isWarnEnabled())
471 log.warn("Could not choose file to load", eee);
472 }
473
474 return new EmptyResult();
475
476 }
477
478 protected FileResult chooseToLoadFiles() {
479
480 try {
481
482 File directory;
483
484 if (startDirectory == null) {
485 directory = getCurrentDirectory();
486 } else {
487 directory = startDirectory;
488 }
489
490 JFileChooser chooser = new JFileChooser(directory);
491
492 chooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
493 if (CollectionUtils.isNotEmpty(fileFilters)) {
494 for (FileFilter filter : fileFilters) {
495 chooser.addChoosableFileFilter(filter);
496 }
497 chooser.setFileFilter(fileFilters.get(0));
498 }
499
500 chooser.setMultiSelectionEnabled(true);
501
502 Action details = chooser.getActionMap().get("viewTypeDetails");
503 details.actionPerformed(null);
504
505 chooser.setAcceptAllFileFilterUsed(useAcceptAllFileFilter);
506 chooser.setFileHidingEnabled(fileHidingEnabled);
507
508 if (showFiles) {
509 if (showDirectories) {
510 chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
511 } else {
512 chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
513 }
514 } else if (showDirectories) {
515 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
516 }
517
518 chooser.setDialogTitle(title);
519 int returnVal = chooser.showDialog(parent, approvalText);
520 if (returnVal == JFileChooser.APPROVE_OPTION) {
521 File[] theFiles = chooser.getSelectedFiles();
522 if (theFiles != null) {
523 if (keepCurrentDirectory && theFiles.length > 0) {
524 setCurrentDirectory(theFiles[0].getParentFile());
525 }
526 return new FileResultImpl(Arrays.stream(theFiles).map(File::getAbsoluteFile).collect(Collectors.toList()));
527 }
528 }
529
530 } catch (Exception eee) {
531 if (log.isWarnEnabled())
532 log.warn("Could not choose files to load", eee);
533 }
534
535 return new EmptyResult();
536
537 }
538
539 protected FileResult chooseToLoadDirectory() {
540
541 try {
542
543 File directory;
544
545 if (startDirectory == null) {
546 directory = getCurrentDirectory();
547 } else {
548 directory = startDirectory;
549 }
550
551 JFileChooser chooser = new JFileChooser(directory);
552
553 chooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
554 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
555 chooser.setDialogTitle(title);
556 int returnVal = chooser.showDialog(parent, approvalText);
557 if (returnVal == JFileChooser.APPROVE_OPTION) {
558 File theFile = chooser.getSelectedFile();
559 if (theFile != null) {
560 if (theFile.isDirectory()) {
561 if (keepCurrentDirectory) {
562 setCurrentDirectory(theFile);
563 }
564 return new FileResultImpl(theFile);
565 }
566 }
567 }
568
569 } catch (Exception eee) {
570 if (log.isWarnEnabled())
571 log.warn("Could not choose directory to load", eee);
572 }
573
574 return new EmptyResult();
575
576 }
577
578 protected FileResult chooseToSave() {
579
580 try {
581 File directory;
582
583 if (startDirectory == null) {
584 directory = getCurrentDirectory();
585 } else {
586 directory = startDirectory;
587 }
588
589 File selectedFile = new File(directory, filename);
590 JFileChooser chooser = new JFileChooser(selectedFile);
591
592 chooser.setDialogType(JFileChooser.SAVE_DIALOG);
593 chooser.setSelectedFile(selectedFile);
594
595 if (CollectionUtils.isNotEmpty(fileFilters)) {
596 for (FileFilter filter : fileFilters) {
597 chooser.addChoosableFileFilter(filter);
598 }
599 chooser.setFileFilter(fileFilters.get(0));
600 }
601 chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
602 chooser.setDialogTitle(title);
603
604 int returnVal = chooser.showDialog(parent, approvalText);
605 if (returnVal == JFileChooser.APPROVE_OPTION) {
606 File result = chooser.getSelectedFile();
607 if (result != null) {
608 if (keepCurrentDirectory) {
609 setCurrentDirectory(result.getParentFile());
610 }
611 result = result.getAbsoluteFile();
612 return new FileResultImpl(result);
613 }
614 }
615
616 } catch (Exception eee) {
617 if (log.isWarnEnabled())
618 log.warn("Could not choose file to save", eee);
619 }
620
621 return new EmptyResult();
622 }
623
624 public static class PatternChooserFilter extends FileFilter {
625 protected String pattern;
626
627 protected String description;
628
629 public PatternChooserFilter(String pattern, String description) {
630 this.pattern = StringUtils.lowerCase(pattern);
631 this.description = description;
632 }
633
634 @Override
635 public boolean accept(File f) {
636 return f.isDirectory() || f.getAbsolutePath().toLowerCase().matches(pattern);
637 }
638
639 @Override
640 public String getDescription() {
641 return description;
642 }
643
644 }
645
646 }
647
648 protected FileChooser() {
649
650 }
651
652 }