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 if (file.isFile()) { 036 fileDialog.setFile(file.toString()); 037 } 038 } 039 } 040 041 @Override 042 public void addChoosableFileFilter(FileFilter filter) { 043 // TODO implement this after Oracle fixes JDK-4811090 / JDK-6192906 044 // https://bugs.openjdk.java.net/browse/JDK-4811090 : Extend awt filedialog 045 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 046 } 047 048 @Override 049 public FileFilter[] getChoosableFileFilters() { 050 // TODO implement this after Oracle fixes JDK-4811090 / JDK-6192906 051 // https://bugs.openjdk.java.net/browse/JDK-4811090 : Extend awt filedialog 052 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 053 return new FileFilter[]{}; 054 } 055 056 @Override 057 public File getCurrentDirectory() { 058 return new File(fileDialog.getDirectory()); 059 } 060 061 @Override 062 public FileFilter getFileFilter() { 063 return fileFilter; 064 } 065 066 @Override 067 public File getSelectedFile() { 068 return new File(fileDialog.getDirectory() + fileDialog.getFile()); 069 } 070 071 @Override 072 public File[] getSelectedFiles() { 073 return fileDialog.getFiles(); 074 } 075 076 @Override 077 public boolean isMultiSelectionEnabled() { 078 return fileDialog.isMultipleMode(); 079 } 080 081 @Override 082 public void setAcceptAllFileFilterUsed(boolean b) { 083 // TODO implement this after Oracle fixes JDK-4811090 / JDK-6192906 084 // https://bugs.openjdk.java.net/browse/JDK-4811090 : Extend awt filedialog 085 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 086 } 087 088 @Override 089 public void setCurrentDirectory(File f) { 090 fileDialog.setDirectory(f.toString()); 091 } 092 093 @Override 094 public void setDialogTitle(String title) { 095 fileDialog.setTitle(title); 096 } 097 098 @Override 099 public void setFileFilter(final FileFilter cff) { 100 FilenameFilter filter = new FilenameFilter() { 101 public boolean accept(File Directory, String fileName) { 102 return cff.accept(new File(Directory.getAbsolutePath() + fileName)); 103 } 104 }; 105 fileDialog.setFilenameFilter(filter); 106 fileFilter = cff; 107 } 108 109 @Override 110 public void setFileSelectionMode(int selectionMode) { 111 // CHECKSTYLE.OFF: LineLength 112 // TODO implement this after Oracle fixes JDK-6192906 / JDK-6699863 / JDK-6927978 / JDK-7125172: 113 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 114 // https://bugs.openjdk.java.net/browse/JDK-6699863 : awt filedialog cannot select directories 115 // https://bugs.openjdk.java.net/browse/JDK-6927978 : Directory Selection standard dialog support 116 // https://bugs.openjdk.java.net/browse/JDK-7125172 : FileDialog objects don't allow directory AND files selection simultaneously 117 118 // There is however a basic support for directory selection on OS X, with Java >= 7u40: 119 // http://stackoverflow.com/questions/1224714/how-can-i-make-a-java-filedialog-accept-directories-as-its-filetype-in-os-x/1224744#1224744 120 // https://bugs.openjdk.java.net/browse/JDK-7161437 : [macosx] awt.FileDialog doesn't respond appropriately for mac when selecting folders 121 // CHECKSTYLE.ON: LineLength 122 this.selectionMode = selectionMode; 123 } 124 125 @Override 126 public void setMultiSelectionEnabled(boolean multiple) { 127 fileDialog.setMultipleMode(multiple); 128 } 129 130 @Override 131 public void setSelectedFile(File file) { 132 fileDialog.setDirectory(file.getAbsolutePath()); 133 fileDialog.setFile(file.getName()); 134 } 135 136 @Override 137 public int showOpenDialog(Component parent) { 138 boolean appleProperty = Main.isPlatformOsx() && selectionMode == JFileChooser.DIRECTORIES_ONLY; 139 if (appleProperty) { 140 System.setProperty("apple.awt.fileDialogForDirectories", "true"); 141 } 142 try { 143 fileDialog.setLocale(locale); 144 fileDialog.setMode(FileDialog.LOAD); 145 fileDialog.setVisible(true); 146 return fileDialog.getFile() == null ? JFileChooser.CANCEL_OPTION : JFileChooser.APPROVE_OPTION; 147 } finally { 148 if (appleProperty) { 149 System.setProperty("apple.awt.fileDialogForDirectories", "false"); 150 } 151 } 152 } 153 154 @Override 155 public int showSaveDialog(Component parent) { 156 fileDialog.setLocale(locale); 157 fileDialog.setMode(FileDialog.SAVE); 158 fileDialog.setVisible(true); 159 return fileDialog.getFile() == null ? JFileChooser.CANCEL_OPTION : JFileChooser.APPROVE_OPTION; 160 } 161 162 /** 163 * Determines if the selection mode is suuported by the native file chooser. 164 * @param selectionMode the selection mode 165 * @return {@code true} if the selection mode is supported, {@code false} otherwise 166 */ 167 public static boolean supportsSelectionMode(int selectionMode) { 168 switch (selectionMode) { 169 case JFileChooser.FILES_AND_DIRECTORIES: 170 // CHECKSTYLE.OFF: LineLength 171 // https://bugs.openjdk.java.net/browse/JDK-7125172 : FileDialog objects don't allow directory AND files selection simultaneously 172 return false; 173 case JFileChooser.DIRECTORIES_ONLY: 174 // http://stackoverflow.com/questions/1224714/how-can-i-make-a-java-filedialog-accept-directories-as-its-filetype-in-os-x/1224744#1224744 175 // CHECKSTYLE.ON: LineLength 176 return Main.isPlatformOsx(); 177 case JFileChooser.FILES_ONLY: 178 default: 179 return true; 180 } 181 } 182}