From f1c2b334f1b8b512e0a0891e514910807717b35f Mon Sep 17 00:00:00 2001 From: hades Date: Tue, 7 Apr 2020 10:52:19 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-28701=20=E8=AE=BE=E8=AE=A1=E5=99=A8-?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9=E5=99=A8=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8C=E6=9B=BF=E6=8D=A2=E4=B8=BA=E7=B3=BB=E7=BB=9F=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9=E5=BC=B9=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ifilechooser/FRFileChooserFactory.java | 27 ++ .../javafx/UINativeFileChooser.java | 348 ++++++++++++++++++ .../{ => swing}/AbstractFileChooser.java | 2 +- .../{ => swing}/UINativeFileChooser.java | 3 +- 4 files changed, 378 insertions(+), 2 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/gui/ifilechooser/FRFileChooserFactory.java create mode 100644 designer-base/src/main/java/com/fr/design/gui/ifilechooser/javafx/UINativeFileChooser.java rename designer-base/src/main/java/com/fr/design/gui/ifilechooser/{ => swing}/AbstractFileChooser.java (97%) rename designer-base/src/main/java/com/fr/design/gui/ifilechooser/{ => swing}/UINativeFileChooser.java (97%) diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FRFileChooserFactory.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FRFileChooserFactory.java new file mode 100644 index 000000000..0bc57dd43 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FRFileChooserFactory.java @@ -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(); + } + } + +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/javafx/UINativeFileChooser.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/javafx/UINativeFileChooser.java new file mode 100644 index 000000000..b1a1576af --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/javafx/UINativeFileChooser.java @@ -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 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 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 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); + } + } + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/AbstractFileChooser.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/swing/AbstractFileChooser.java similarity index 97% rename from designer-base/src/main/java/com/fr/design/gui/ifilechooser/AbstractFileChooser.java rename to designer-base/src/main/java/com/fr/design/gui/ifilechooser/swing/AbstractFileChooser.java index ca460aa0f..682f60e35 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/AbstractFileChooser.java +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/swing/AbstractFileChooser.java @@ -1,4 +1,4 @@ -package com.fr.design.gui.ifilechooser; +package com.fr.design.gui.ifilechooser.swing; import javax.swing.filechooser.FileFilter; import java.awt.*; diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/UINativeFileChooser.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/swing/UINativeFileChooser.java similarity index 97% rename from designer-base/src/main/java/com/fr/design/gui/ifilechooser/UINativeFileChooser.java rename to designer-base/src/main/java/com/fr/design/gui/ifilechooser/swing/UINativeFileChooser.java index 9c956372d..dd2394f79 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/UINativeFileChooser.java +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/swing/UINativeFileChooser.java @@ -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.stable.os.OperatingSystem;