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 @Override 102 public boolean accept(File directory, String fileName) { 103 return cff.accept(new File(directory.getAbsolutePath() + fileName)); 104 } 105 }; 106 fileDialog.setFilenameFilter(filter); 107 fileFilter = cff; 108 } 109 110 @Override 111 public void setFileSelectionMode(int selectionMode) { 112 // CHECKSTYLE.OFF: LineLength 113 // TODO implement this after Oracle fixes JDK-6192906 / JDK-6699863 / JDK-6927978 / JDK-7125172: 114 // https://bugs.openjdk.java.net/browse/JDK-6192906 : Add more features to java.awt.FileDialog 115 // https://bugs.openjdk.java.net/browse/JDK-6699863 : awt filedialog cannot select directories 116 // https://bugs.openjdk.java.net/browse/JDK-6927978 : Directory Selection standard dialog support 117 // https://bugs.openjdk.java.net/browse/JDK-7125172 : FileDialog objects don't allow directory AND files selection simultaneously 118 119 // There is however a basic support for directory selection on OS X, with Java >= 7u40: 120 // http://stackoverflow.com/questions/1224714/how-can-i-make-a-java-filedialog-accept-directories-as-its-filetype-in-os-x/1224744#1224744 121 // https://bugs.openjdk.java.net/browse/JDK-7161437 : [macosx] awt.FileDialog doesn't respond appropriately for mac when selecting folders 122 // CHECKSTYLE.ON: LineLength 123 this.selectionMode = selectionMode; 124 } 125 126 @Override 127 public void setMultiSelectionEnabled(boolean multiple) { 128 fileDialog.setMultipleMode(multiple); 129 } 130 131 @Override 132 public void setSelectedFile(File file) { 133 if (file == null) return; 134 fileDialog.setDirectory(file.getParent()); 135 fileDialog.setFile(file.getName()); 136 } 137 138 @Override 139 public int showOpenDialog(Component parent) { 140 boolean appleProperty = Main.isPlatformOsx() && selectionMode == JFileChooser.DIRECTORIES_ONLY; 141 if (appleProperty) { 142 System.setProperty("apple.awt.fileDialogForDirectories", "true"); 143 } 144 try { 145 fileDialog.setLocale(locale); 146 fileDialog.setMode(FileDialog.LOAD); 147 fileDialog.setVisible(true); 148 return fileDialog.getFile() == null ? JFileChooser.CANCEL_OPTION : JFileChooser.APPROVE_OPTION; 149 } finally { 150 if (appleProperty) { 151 System.setProperty("apple.awt.fileDialogForDirectories", "false"); 152 } 153 } 154 } 155 156 @Override 157 public int showSaveDialog(Component parent) { 158 fileDialog.setLocale(locale); 159 fileDialog.setMode(FileDialog.SAVE); 160 fileDialog.setVisible(true); 161 return fileDialog.getFile() == null ? JFileChooser.CANCEL_OPTION : JFileChooser.APPROVE_OPTION; 162 } 163 164 /** 165 * Determines if the selection mode is suuported by the native file chooser. 166 * @param selectionMode the selection mode 167 * @return {@code true} if the selection mode is supported, {@code false} otherwise 168 */ 169 public static boolean supportsSelectionMode(int selectionMode) { 170 switch (selectionMode) { 171 case JFileChooser.FILES_AND_DIRECTORIES: 172 // CHECKSTYLE.OFF: LineLength 173 // https://bugs.openjdk.java.net/browse/JDK-7125172 : FileDialog objects don't allow directory AND files selection simultaneously 174 return false; 175 case JFileChooser.DIRECTORIES_ONLY: 176 // http://stackoverflow.com/questions/1224714/how-can-i-make-a-java-filedialog-accept-directories-as-its-filetype-in-os-x/1224744#1224744 177 // CHECKSTYLE.ON: LineLength 178 return Main.isPlatformOsx(); 179 case JFileChooser.FILES_ONLY: 180 default: 181 return true; 182 } 183 } 184}