hades
5 years ago
4 changed files with 378 additions and 2 deletions
@ -0,0 +1,27 @@ |
|||||||
|
package com.fr.design.gui.ifilechooser; |
||||||
|
|
||||||
|
import com.fr.design.gui.ifilechooser.javafx.UINativeFileChooser; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/4/7 |
||||||
|
*/ |
||||||
|
public class FRFileChooserFactory { |
||||||
|
|
||||||
|
/** |
||||||
|
* 默认提供原生风格 |
||||||
|
* |
||||||
|
* @return 文件选择器 |
||||||
|
*/ |
||||||
|
public static JFileChooser createFileChooser() { |
||||||
|
if (UINativeFileChooser.isAvailable()) { |
||||||
|
return new UINativeFileChooser(); |
||||||
|
} else { |
||||||
|
return new JFileChooser(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,348 @@ |
|||||||
|
package com.fr.design.gui.ifilechooser.javafx; |
||||||
|
|
||||||
|
import java.awt.*; |
||||||
|
import java.io.File; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.concurrent.CountDownLatch; |
||||||
|
import javafx.application.Platform; |
||||||
|
import javafx.embed.swing.JFXPanel; |
||||||
|
import javafx.stage.DirectoryChooser; |
||||||
|
import javafx.stage.FileChooser; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import javax.swing.filechooser.FileFilter; |
||||||
|
import javax.swing.filechooser.FileNameExtensionFilter; |
||||||
|
import javax.swing.filechooser.FileSystemView; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 基于javafx的原生风格文件选择器 |
||||||
|
* 解决swing原生文件选择器不支持文件过滤的问题 |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/4/2 |
||||||
|
*/ |
||||||
|
public class UINativeFileChooser extends JFileChooser { |
||||||
|
|
||||||
|
private static final boolean FX_AVAILABLE; |
||||||
|
private List<File> currentFiles; |
||||||
|
private FileChooser fileChooser; |
||||||
|
private File currentFile; |
||||||
|
private DirectoryChooser directoryChooser; |
||||||
|
|
||||||
|
static { |
||||||
|
boolean isFx; |
||||||
|
try { |
||||||
|
Class.forName("javafx.stage.FileChooser"); |
||||||
|
isFx = true; |
||||||
|
JFXPanel jfxPanel = new JFXPanel(); |
||||||
|
} catch (ClassNotFoundException e) { |
||||||
|
isFx = false; |
||||||
|
} |
||||||
|
|
||||||
|
FX_AVAILABLE = isFx; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isAvailable() { |
||||||
|
return FX_AVAILABLE; |
||||||
|
} |
||||||
|
|
||||||
|
public UINativeFileChooser() { |
||||||
|
initFxFileChooser(null); |
||||||
|
} |
||||||
|
|
||||||
|
public UINativeFileChooser(String currentDirectoryPath) { |
||||||
|
super(currentDirectoryPath); |
||||||
|
initFxFileChooser(new File(currentDirectoryPath)); |
||||||
|
} |
||||||
|
|
||||||
|
public UINativeFileChooser(File currentDirectory) { |
||||||
|
super(currentDirectory); |
||||||
|
initFxFileChooser(currentDirectory); |
||||||
|
} |
||||||
|
|
||||||
|
public UINativeFileChooser(FileSystemView fsv) { |
||||||
|
super(fsv); |
||||||
|
initFxFileChooser(fsv.getDefaultDirectory()); |
||||||
|
} |
||||||
|
|
||||||
|
public UINativeFileChooser(File currentDirectory, FileSystemView fsv) { |
||||||
|
super(currentDirectory, fsv); |
||||||
|
initFxFileChooser(currentDirectory); |
||||||
|
} |
||||||
|
|
||||||
|
public UINativeFileChooser(String currentDirectoryPath, FileSystemView fsv) { |
||||||
|
super(currentDirectoryPath, fsv); |
||||||
|
initFxFileChooser(new File(currentDirectoryPath)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int showOpenDialog(final Component parent) throws HeadlessException { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
return super.showOpenDialog(parent); |
||||||
|
} |
||||||
|
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1); |
||||||
|
Platform.runLater(new Runnable() { |
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
|
||||||
|
if (parent != null) { |
||||||
|
parent.setEnabled(false); |
||||||
|
} |
||||||
|
|
||||||
|
if (DIRECTORIES_ONLY == getFileSelectionMode()) { |
||||||
|
currentFile = directoryChooser.showDialog(null); |
||||||
|
} else { |
||||||
|
if (isMultiSelectionEnabled()) { |
||||||
|
currentFiles = fileChooser.showOpenMultipleDialog(null); |
||||||
|
} else { |
||||||
|
currentFile = fileChooser.showOpenDialog(null); |
||||||
|
} |
||||||
|
} |
||||||
|
latch.countDown(); |
||||||
|
} |
||||||
|
|
||||||
|
}); |
||||||
|
try { |
||||||
|
latch.await(); |
||||||
|
} catch (InterruptedException ex) { |
||||||
|
throw new RuntimeException(ex); |
||||||
|
} finally { |
||||||
|
if (parent != null) { |
||||||
|
parent.setEnabled(true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (isMultiSelectionEnabled()) { |
||||||
|
if (currentFiles != null) { |
||||||
|
return JFileChooser.APPROVE_OPTION; |
||||||
|
} else { |
||||||
|
return JFileChooser.CANCEL_OPTION; |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (currentFile != null) { |
||||||
|
return JFileChooser.APPROVE_OPTION; |
||||||
|
} else { |
||||||
|
return JFileChooser.CANCEL_OPTION; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int showSaveDialog(final Component parent) throws HeadlessException { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
return super.showSaveDialog(parent); |
||||||
|
} |
||||||
|
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1); |
||||||
|
|
||||||
|
Platform.runLater(new Runnable() { |
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
|
||||||
|
if (parent != null) { |
||||||
|
parent.setEnabled(false); |
||||||
|
} |
||||||
|
|
||||||
|
if (DIRECTORIES_ONLY == getFileSelectionMode()) { |
||||||
|
currentFile = directoryChooser.showDialog(null); |
||||||
|
} else { |
||||||
|
currentFile = fileChooser.showSaveDialog(null); |
||||||
|
} |
||||||
|
latch.countDown(); |
||||||
|
} |
||||||
|
|
||||||
|
}); |
||||||
|
try { |
||||||
|
latch.await(); |
||||||
|
} catch (InterruptedException ex) { |
||||||
|
throw new RuntimeException(ex); |
||||||
|
} finally { |
||||||
|
if (parent != null) { |
||||||
|
parent.setEnabled(true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (currentFile != null) { |
||||||
|
return JFileChooser.APPROVE_OPTION; |
||||||
|
} else { |
||||||
|
return JFileChooser.CANCEL_OPTION; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int showDialog(Component parent, String approveButtonText) { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
return super.showDialog(parent, approveButtonText); |
||||||
|
} |
||||||
|
return showOpenDialog(parent); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public File[] getSelectedFiles() { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
return super.getSelectedFiles(); |
||||||
|
} |
||||||
|
if (currentFiles == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return currentFiles.toArray(new File[currentFiles.size()]); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public File getSelectedFile() { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
return super.getSelectedFile(); |
||||||
|
} |
||||||
|
return currentFile; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setSelectedFiles(File[] selectedFiles) { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
super.setSelectedFiles(selectedFiles); |
||||||
|
return; |
||||||
|
} |
||||||
|
if (selectedFiles == null || selectedFiles.length == 0) { |
||||||
|
currentFiles = null; |
||||||
|
} else { |
||||||
|
setSelectedFile(selectedFiles[0]); |
||||||
|
currentFiles = new ArrayList<>(Arrays.asList(selectedFiles)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setSelectedFile(File file) { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
super.setSelectedFile(file); |
||||||
|
return; |
||||||
|
} |
||||||
|
currentFile = file; |
||||||
|
if (file != null) { |
||||||
|
if (file.isDirectory()) { |
||||||
|
fileChooser.setInitialDirectory(file.getAbsoluteFile()); |
||||||
|
|
||||||
|
if (directoryChooser != null) { |
||||||
|
directoryChooser.setInitialDirectory(file.getAbsoluteFile()); |
||||||
|
} |
||||||
|
} else if (file.isFile()) { |
||||||
|
fileChooser.setInitialDirectory(file.getParentFile()); |
||||||
|
fileChooser.setInitialFileName(file.getName()); |
||||||
|
|
||||||
|
if (directoryChooser != null) { |
||||||
|
directoryChooser.setInitialDirectory(file.getParentFile()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setFileSelectionMode(int mode) { |
||||||
|
super.setFileSelectionMode(mode); |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (mode == DIRECTORIES_ONLY) { |
||||||
|
if (directoryChooser == null) { |
||||||
|
directoryChooser = new DirectoryChooser(); |
||||||
|
} |
||||||
|
setSelectedFile(currentFile); |
||||||
|
setDialogTitle(getDialogTitle()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setDialogTitle(String dialogTitle) { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
super.setDialogTitle(dialogTitle); |
||||||
|
return; |
||||||
|
} |
||||||
|
fileChooser.setTitle(dialogTitle); |
||||||
|
if (directoryChooser != null) { |
||||||
|
directoryChooser.setTitle(dialogTitle); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getDialogTitle() { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
return super.getDialogTitle(); |
||||||
|
} |
||||||
|
return fileChooser.getTitle(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void changeToParentDirectory() { |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
super.changeToParentDirectory(); |
||||||
|
return; |
||||||
|
} |
||||||
|
File parentDir = fileChooser.getInitialDirectory().getParentFile(); |
||||||
|
if (parentDir.isDirectory()) { |
||||||
|
fileChooser.setInitialDirectory(parentDir); |
||||||
|
if (directoryChooser != null) { |
||||||
|
directoryChooser.setInitialDirectory(parentDir); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addChoosableFileFilter(FileFilter filter) { |
||||||
|
super.addChoosableFileFilter(filter); |
||||||
|
if (!FX_AVAILABLE || filter == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (filter.getClass().equals(FileNameExtensionFilter.class)) { |
||||||
|
FileNameExtensionFilter f = (FileNameExtensionFilter) filter; |
||||||
|
|
||||||
|
List<String> ext = new ArrayList<>(); |
||||||
|
for (String extension : f.getExtensions()) { |
||||||
|
ext.add(extension.replaceAll("^\\*?\\.?(.*)$", "*.$1")); |
||||||
|
} |
||||||
|
fileChooser.getExtensionFilters() |
||||||
|
.add(new FileChooser.ExtensionFilter(f.getDescription(), ext)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setAcceptAllFileFilterUsed(boolean bool) { |
||||||
|
boolean differs = isAcceptAllFileFilterUsed() ^ bool; |
||||||
|
super.setAcceptAllFileFilterUsed(bool); |
||||||
|
if (!FX_AVAILABLE) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (!differs) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (bool) { |
||||||
|
fileChooser.getExtensionFilters() |
||||||
|
.add(new FileChooser.ExtensionFilter("All files", "*.*")); |
||||||
|
} else { |
||||||
|
for (Iterator<FileChooser.ExtensionFilter> it |
||||||
|
= fileChooser.getExtensionFilters().iterator(); it.hasNext();) { |
||||||
|
FileChooser.ExtensionFilter filter = it.next(); |
||||||
|
if (filter.getExtensions().size() == 1 |
||||||
|
&& filter.getExtensions().contains("*.*")) { |
||||||
|
it.remove(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void initFxFileChooser(File currentFile) { |
||||||
|
if (FX_AVAILABLE) { |
||||||
|
fileChooser = new FileChooser(); |
||||||
|
this.currentFile = currentFile; |
||||||
|
setSelectedFile(currentFile); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,4 +1,4 @@ |
|||||||
package com.fr.design.gui.ifilechooser; |
package com.fr.design.gui.ifilechooser.swing; |
||||||
|
|
||||||
import javax.swing.filechooser.FileFilter; |
import javax.swing.filechooser.FileFilter; |
||||||
import java.awt.*; |
import java.awt.*; |
@ -1,5 +1,6 @@ |
|||||||
package com.fr.design.gui.ifilechooser; |
package com.fr.design.gui.ifilechooser.swing; |
||||||
|
|
||||||
|
import com.fr.design.gui.ifilechooser.swing.AbstractFileChooser; |
||||||
import com.fr.design.mainframe.DesignerContext; |
import com.fr.design.mainframe.DesignerContext; |
||||||
import com.fr.stable.os.OperatingSystem; |
import com.fr.stable.os.OperatingSystem; |
||||||
|
|
Loading…
Reference in new issue