001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.widgets; 003 004import java.awt.Component; 005import java.awt.FileDialog; 006import java.awt.Frame; 007import java.io.File; 008import java.io.FilenameFilter; 009 010import javax.swing.JFileChooser; 011import javax.swing.filechooser.FileFilter; 012 013import org.openstreetmap.josm.Main; 014 015/** 016 * File chooser based on the AWT's {@link FileDialog} implementation, 017 * which looks like more a native file chooser than the Swing implementation. 018 * @since 7578 019 */ 020public class NativeFileChooser extends AbstractFileChooser { 021 022 /** The instance of the fileDialog */ 023 private final FileDialog fileDialog; 024 private FileFilter fileFilter; 025 private int selectionMode; 026 027 /** 028 * Constructs a new {@code NativeFileChooser}. 029 * @param file the current file/directory to point to 030 */ 031 public NativeFileChooser(File file) { 032 fileDialog = new FileDialog((Frame) Main.parent); 033 if (file != null) { 034 fileDialog.setDirectory(file.getAbsolutePath()); 035 fileDialog.setFile(file.toString()); 036 } 037 } 038 039 @Override 040 public void addChoosableFileFilter(FileFilter filter) { 041 // TODO implement this after Oracle fixes JDK-4811090 / JDK-6192906 042 // https://bugs.openjdk.java.net/browse/JDK-4811090 : Extend awt filedialog 043 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 044 } 045 046 @Override 047 public FileFilter[] getChoosableFileFilters() { 048 // TODO implement this after Oracle fixes JDK-4811090 / JDK-6192906 049 // https://bugs.openjdk.java.net/browse/JDK-4811090 : Extend awt filedialog 050 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 051 return new FileFilter[]{}; 052 } 053 054 @Override 055 public File getCurrentDirectory() { 056 return new File(fileDialog.getDirectory()); 057 } 058 059 @Override 060 public FileFilter getFileFilter() { 061 return fileFilter; 062 } 063 064 @Override 065 public File getSelectedFile() { 066 return new File(fileDialog.getDirectory() + fileDialog.getFile()); 067 } 068 069 @Override 070 public File[] getSelectedFiles() { 071 return fileDialog.getFiles(); 072 } 073 074 @Override 075 public boolean isMultiSelectionEnabled() { 076 return fileDialog.isMultipleMode(); 077 } 078 079 @Override 080 public void setAcceptAllFileFilterUsed(boolean b) { 081 // TODO implement this after Oracle fixes JDK-4811090 / JDK-6192906 082 // https://bugs.openjdk.java.net/browse/JDK-4811090 : Extend awt filedialog 083 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 084 } 085 086 @Override 087 public void setCurrentDirectory(File f) { 088 fileDialog.setDirectory(f.toString()); 089 } 090 091 @Override 092 public void setDialogTitle(String title) { 093 fileDialog.setTitle(title); 094 } 095 096 @Override 097 public void setFileFilter(final FileFilter cff) { 098 FilenameFilter filter = new FilenameFilter() { 099 public boolean accept(File Directory, String fileName) { 100 return cff.accept(new File(Directory.getAbsolutePath() + fileName)); 101 } 102 }; 103 fileDialog.setFilenameFilter(filter); 104 fileFilter = cff; 105 } 106 107 @Override 108 public void setFileSelectionMode(int selectionMode) { 109 // TODO implement this after Oracle fixes JDK-6192906 / JDK-6699863 / JDK-6927978 / JDK-7125172: 110 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 111 // https://bugs.openjdk.java.net/browse/JDK-6699863 : awt filedialog cannot select directories 112 // https://bugs.openjdk.java.net/browse/JDK-6927978 : Directory Selection standard dialog support 113 // https://bugs.openjdk.java.net/browse/JDK-7125172 : FileDialog objects don't allow directory AND files selection simultaneously 114 115 // There is however a basic support for directory selection on OS X, with Java >= 7u40: 116 // http://stackoverflow.com/questions/1224714/how-can-i-make-a-java-filedialog-accept-directories-as-its-filetype-in-os-x/1224744#1224744 117 // https://bugs.openjdk.java.net/browse/JDK-7161437 : [macosx] awt.FileDialog doesn't respond appropriately for mac when selecting folders 118 this.selectionMode = selectionMode; 119 } 120 121 @Override 122 public void setMultiSelectionEnabled(boolean multiple) { 123 fileDialog.setMultipleMode(multiple); 124 } 125 126 @Override 127 public void setSelectedFile(File file) { 128 fileDialog.setDirectory(file.getAbsolutePath()); 129 fileDialog.setFile(file.getName()); 130 } 131 132 @Override 133 public int showOpenDialog(Component parent) { 134 boolean appleProperty = Main.isPlatformOsx() && selectionMode == JFileChooser.DIRECTORIES_ONLY; 135 if (appleProperty) { 136 System.setProperty("apple.awt.fileDialogForDirectories", "true"); 137 } 138 try { 139 fileDialog.setLocale(locale); 140 fileDialog.setMode(FileDialog.LOAD); 141 fileDialog.setVisible(true); 142 return fileDialog.getFile() == null ? JFileChooser.CANCEL_OPTION : JFileChooser.APPROVE_OPTION; 143 } finally { 144 if (appleProperty) { 145 System.setProperty("apple.awt.fileDialogForDirectories", "false"); 146 } 147 } 148 } 149 150 @Override 151 public int showSaveDialog(Component parent) { 152 fileDialog.setLocale(locale); 153 fileDialog.setMode(FileDialog.SAVE); 154 fileDialog.setVisible(true); 155 return fileDialog.getFile() == null ? JFileChooser.CANCEL_OPTION : JFileChooser.APPROVE_OPTION; 156 } 157 158 /** 159 * Determines if the selection mode is suuported by the native file chooser. 160 * @param selectionMode the selection mode 161 * @return {@code true} if the selection mode is supported, {@code false} otherwise 162 */ 163 public static boolean supportsSelectionMode(int selectionMode) { 164 switch (selectionMode) { 165 case JFileChooser.FILES_AND_DIRECTORIES: 166 // https://bugs.openjdk.java.net/browse/JDK-7125172 : FileDialog objects don't allow directory AND files selection simultaneously 167 return false; 168 case JFileChooser.DIRECTORIES_ONLY: 169 // http://stackoverflow.com/questions/1224714/how-can-i-make-a-java-filedialog-accept-directories-as-its-filetype-in-os-x/1224744#1224744 170 return Main.isPlatformOsx(); 171 case JFileChooser.FILES_ONLY: 172 default: 173 return true; 174 } 175 } 176}