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