From 503aa8cbe201c8a4dbe0b1098966f9779e13a703 Mon Sep 17 00:00:00 2001 From: Wolf Posdorfer Date: Sat, 21 Nov 2020 17:32:11 +0100 Subject: [PATCH 1/4] allows adding files and folders via filechooser and drag and drop need to switch to JFileChooser, as javafx filechooser doesnt allow files+folders selection selection folders (filechooser/dragndrop) now recursively walks the directory and adds every file.xyz it finds --- .../Controllers/GamesController.java | 126 +++++++++++++----- 1 file changed, 95 insertions(+), 31 deletions(-) diff --git a/src/main/java/nsusbloader/Controllers/GamesController.java b/src/main/java/nsusbloader/Controllers/GamesController.java index 5d2424c..4146b20 100644 --- a/src/main/java/nsusbloader/Controllers/GamesController.java +++ b/src/main/java/nsusbloader/Controllers/GamesController.java @@ -28,7 +28,6 @@ import javafx.scene.input.TransferMode; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Region; import javafx.stage.DirectoryChooser; -import javafx.stage.FileChooser; import nsusbloader.AppPreferences; import nsusbloader.com.net.NETCommunications; import nsusbloader.com.usb.UsbCommunications; @@ -40,11 +39,22 @@ import nsusbloader.ServiceWindow; import java.io.File; import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.ResourceBundle; +import javax.swing.JFileChooser; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.filechooser.FileFilter; + public class GamesController implements Initializable { + + private static final String REGEX_ONLY_NSP = ".*\\.nsp$"; + private static final String REGEX_ALLFILES_TINFOIL = ".*\\.(nsp$|xci$|nsz$|xcz$)"; + @FXML private AnchorPane usbNetPane; @@ -186,32 +196,88 @@ public class GamesController implements Initializable { return nsIpTextField.getText(); } + + private boolean isGoldLeaf() { + return getSelectedProtocol().equals("GoldLeaf") + && (!MediatorControl.getInstance().getContoller().getSettingsCtrlr().getGoldleafSettings().getNSPFileFilterForGL()); + } + + private boolean isTinfoil() { + return getSelectedProtocol().equals("TinFoil") + && MediatorControl.getInstance().getContoller().getSettingsCtrlr().getTinfoilSettings().isXciNszXczSupport(); + } + + private String getRegexForFiles() { + if (isTinfoil()) + return REGEX_ALLFILES_TINFOIL; + else if (isGoldLeaf()) + return REGEX_ONLY_NSP; + else + return REGEX_ONLY_NSP; + } + /** * Functionality for selecting NSP button. * */ private void selectFilesBtnAction(){ - List filesList; - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle(resourceBundle.getString("btn_OpenFile")); + final String regex = getRegexForFiles(); + if(!UIManager.getLookAndFeel().isNativeLookAndFeel()) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { + // :shrug emoji: + // defaults to Metal Look and Feel + } + } - fileChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath))); + JFileChooser fileChooser = new JFileChooser(new File(FilesHelper.getRealFolder(previouslyOpenedPath))); + fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + fileChooser.setMultiSelectionEnabled(true); + fileChooser.setFileFilter(new FileFilter() { + public String getDescription() { + return "Switch Files"; + } + public boolean accept(File f) { + return f.isDirectory() || f.getName().toLowerCase().matches(regex); + } + }); + + if(fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { + List files = Arrays.asList(fileChooser.getSelectedFiles()); + List allFiles = new ArrayList<>(); - if (getSelectedProtocol().equals("TinFoil") && MediatorControl.getInstance().getContoller().getSettingsCtrlr().getTinfoilSettings().isXciNszXczSupport()) - fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP/XCI/NSZ/XCZ", "*.nsp", "*.xci", "*.nsz", "*.xcz")); - else if (getSelectedProtocol().equals("GoldLeaf") && (! MediatorControl.getInstance().getContoller().getSettingsCtrlr().getGoldleafSettings().getNSPFileFilterForGL())) - fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Any file", "*.*"), - new FileChooser.ExtensionFilter("NSP ROM", "*.nsp") - ); - else - fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP ROM", "*.nsp")); + if (files.size() != 0) { + files.stream().filter(File::isDirectory).forEach(f -> collectFiles(allFiles, f, regex)); + files.stream().filter(f -> f.getName().toLowerCase().matches(regex)).forEach(allFiles::add); + } - filesList = fileChooser.showOpenMultipleDialog(usbNetPane.getScene().getWindow()); - if (filesList != null && !filesList.isEmpty()) { - tableFilesListController.setFiles(filesList); - uploadStopBtn.setDisable(false); - previouslyOpenedPath = filesList.get(0).getParent(); + if (allFiles.size() > 0) { + tableFilesListController.setFiles(allFiles); + uploadStopBtn.setDisable(false); + previouslyOpenedPath = allFiles.get(0).getParent(); + } } } + + /** + * used to recursively walk all directories, every file will be added to the storage list + * @param storage used to hold files + * @param startFolder where to start + * @param regex for filenames + */ + private void collectFiles(List storage, File startFolder, final String regex) { + if (startFolder.isDirectory()) { + File[] files = startFolder.listFiles(); + for (File f : files) { + if (f.isDirectory()) { + collectFiles(storage, f, regex); + } else if (f.getName().toLowerCase().matches(regex)) { + storage.add(f); + } + } + } + } + /** * Functionality for selecting Split NSP button. * */ @@ -325,20 +391,18 @@ public class GamesController implements Initializable { * */ @FXML private void handleDrop(DragEvent event){ - List filesDropped = event.getDragboard().getFiles(); - SettingsController settingsController = MediatorControl.getInstance().getContoller().getSettingsCtrlr(); - SettingsBlockTinfoilController tinfoilSettings = settingsController.getTinfoilSettings(); - SettingsBlockGoldleafController goldleafController = settingsController.getGoldleafSettings(); + final String regex = getRegexForFiles(); + + List files = event.getDragboard().getFiles(); + List allFiles = new ArrayList<>(); - if (getSelectedProtocol().equals("TinFoil") && tinfoilSettings.isXciNszXczSupport()) - filesDropped.removeIf(file -> ! file.getName().toLowerCase().matches("(.*\\.nsp$)|(.*\\.xci$)|(.*\\.nsz$)|(.*\\.xcz$)")); - else if (getSelectedProtocol().equals("GoldLeaf") && (! goldleafController.getNSPFileFilterForGL())) - filesDropped.removeIf(file -> (file.isDirectory() && ! file.getName().toLowerCase().matches(".*\\.nsp$"))); - else - filesDropped.removeIf(file -> ! file.getName().toLowerCase().matches(".*\\.nsp$")); - - if ( ! filesDropped.isEmpty() ) - tableFilesListController.setFiles(filesDropped); + if (files.size() != 0) { + files.stream().filter(File::isDirectory).forEach(f -> collectFiles(allFiles, f, regex)); + files.stream().filter(f -> f.getName().toLowerCase().matches(regex)).forEach(allFiles::add); + } + + if ( ! allFiles.isEmpty() ) + tableFilesListController.setFiles(allFiles); event.setDropCompleted(true); event.consume(); From b2202cf483cc0db5c39353ad8a21305b3216a40a Mon Sep 17 00:00:00 2001 From: Wolf Posdorfer Date: Tue, 24 Nov 2020 19:12:19 +0100 Subject: [PATCH 2/4] Reverting FileChooser and adding DirChooser - old filechooser - directory chooser can choose any directory and recursively adds all *.xyz files - add button template --- .../Controllers/GamesController.java | 126 ++++++++++-------- src/main/resources/GamesTab.fxml | 5 + src/main/resources/locale.properties | 1 + src/main/resources/locale_de_DE.properties | 2 + src/main/resources/locale_en_US.properties | 1 + 5 files changed, 80 insertions(+), 55 deletions(-) diff --git a/src/main/java/nsusbloader/Controllers/GamesController.java b/src/main/java/nsusbloader/Controllers/GamesController.java index 4146b20..9c89719 100644 --- a/src/main/java/nsusbloader/Controllers/GamesController.java +++ b/src/main/java/nsusbloader/Controllers/GamesController.java @@ -28,6 +28,7 @@ import javafx.scene.input.TransferMode; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Region; import javafx.stage.DirectoryChooser; +import javafx.stage.FileChooser; import nsusbloader.AppPreferences; import nsusbloader.com.net.NETCommunications; import nsusbloader.com.usb.UsbCommunications; @@ -40,16 +41,10 @@ import nsusbloader.ServiceWindow; import java.io.File; import java.net.URL; import java.util.ArrayList; -import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.ResourceBundle; -import javax.swing.JFileChooser; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.filechooser.FileFilter; - public class GamesController implements Initializable { private static final String REGEX_ONLY_NSP = ".*\\.nsp$"; @@ -70,7 +65,7 @@ public class GamesController implements Initializable { public NSTableViewController tableFilesListController; // Accessible from Mediator (for drag-n-drop support) @FXML - private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn; + private Button selectNspBtn, selectSplitNspBtn, selectFolderBtn, uploadStopBtn; private String previouslyOpenedPath; private Region btnUpStopImage; private ResourceBundle resourceBundle; @@ -140,16 +135,17 @@ public class GamesController implements Initializable { switchThemeBtn.setGraphic(btnSwitchImage); this.switchThemeBtn.setOnAction(e->switchTheme()); - - uploadStopBtn.setDisable(getSelectedProtocol().equals("TinFoil")); selectNspBtn.setOnAction(e-> selectFilesBtnAction()); + selectNspBtn.getStyleClass().add("buttonSelect"); + + selectFolderBtn.setOnAction(e-> selectFoldersBtnAction()); + selectFolderBtn.getStyleClass().add("buttonSelect"); selectSplitNspBtn.setOnAction(e-> selectSplitBtnAction()); selectSplitNspBtn.getStyleClass().add("buttonSelect"); uploadStopBtn.setOnAction(e-> uploadBtnAction()); - - selectNspBtn.getStyleClass().add("buttonSelect"); + uploadStopBtn.setDisable(getSelectedProtocol().equals("TinFoil")); this.btnUpStopImage = new Region(); btnUpStopImage.getStyleClass().add("regionUpload"); @@ -196,69 +192,89 @@ public class GamesController implements Initializable { return nsIpTextField.getText(); } - private boolean isGoldLeaf() { - return getSelectedProtocol().equals("GoldLeaf") - && (!MediatorControl.getInstance().getContoller().getSettingsCtrlr().getGoldleafSettings().getNSPFileFilterForGL()); + return getSelectedProtocol().equals("GoldLeaf"); } private boolean isTinfoil() { - return getSelectedProtocol().equals("TinFoil") - && MediatorControl.getInstance().getContoller().getSettingsCtrlr().getTinfoilSettings().isXciNszXczSupport(); + return getSelectedProtocol().equals("TinFoil"); } + private boolean isNSPFileFilterForGL() { + return MediatorControl.getInstance().getContoller().getSettingsCtrlr().getGoldleafSettings().getNSPFileFilterForGL(); + } + + private boolean isXciNszXczSupport() { + return MediatorControl.getInstance().getContoller().getSettingsCtrlr().getTinfoilSettings().isXciNszXczSupport(); + } + + /** + * regex for selected program and selected file filter
+ * tinfoil + xcinszxcz
+ * tinfoil + nsponly
+ * goldleaf
+ * etc.. + */ private String getRegexForFiles() { - if (isTinfoil()) + if (isTinfoil() && isXciNszXczSupport()) return REGEX_ALLFILES_TINFOIL; - else if (isGoldLeaf()) - return REGEX_ONLY_NSP; else return REGEX_ONLY_NSP; + // currently only tinfoil supports all filetypes + // everything else only supports nsp + // else if (isGoldLeaf()) + // return REGEX_ONLY_NSP; + // else } /** * Functionality for selecting NSP button. - * */ - private void selectFilesBtnAction(){ - final String regex = getRegexForFiles(); - if(!UIManager.getLookAndFeel().isNativeLookAndFeel()) { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { - // :shrug emoji: - // defaults to Metal Look and Feel - } + */ + private void selectFilesBtnAction() { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle(resourceBundle.getString("btn_OpenFile")); + + fileChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath))); + + if (isTinfoil() && isXciNszXczSupport()) { + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP/XCI/NSZ/XCZ", "*.nsp", "*.xci", "*.nsz", "*.xcz")); + } else if (isGoldLeaf() && !isNSPFileFilterForGL()) { + fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Any file", "*.*"), + new FileChooser.ExtensionFilter("NSP ROM", "*.nsp")); + } else { + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP ROM", "*.nsp")); } - JFileChooser fileChooser = new JFileChooser(new File(FilesHelper.getRealFolder(previouslyOpenedPath))); - fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - fileChooser.setMultiSelectionEnabled(true); - fileChooser.setFileFilter(new FileFilter() { - public String getDescription() { - return "Switch Files"; - } - public boolean accept(File f) { - return f.isDirectory() || f.getName().toLowerCase().matches(regex); - } - }); - - if(fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { - List files = Arrays.asList(fileChooser.getSelectedFiles()); - List allFiles = new ArrayList<>(); - - if (files.size() != 0) { - files.stream().filter(File::isDirectory).forEach(f -> collectFiles(allFiles, f, regex)); - files.stream().filter(f -> f.getName().toLowerCase().matches(regex)).forEach(allFiles::add); - } - - if (allFiles.size() > 0) { - tableFilesListController.setFiles(allFiles); - uploadStopBtn.setDisable(false); - previouslyOpenedPath = allFiles.get(0).getParent(); - } + List filesList = fileChooser.showOpenMultipleDialog(usbNetPane.getScene().getWindow()); + if (filesList != null && !filesList.isEmpty()) { + tableFilesListController.setFiles(filesList); + uploadStopBtn.setDisable(false); + previouslyOpenedPath = filesList.get(0).getParent(); } } + /** + * Functionality for selecting folders button. + * will scan all folders recursively for nsp-files + */ + private void selectFoldersBtnAction() { + DirectoryChooser chooser = new DirectoryChooser(); + chooser.setTitle(resourceBundle.getString("btn_OpenFolders")); + chooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath))); + + File startFolder = chooser.showDialog(usbNetPane.getScene().getWindow()); + if (startFolder != null) { + List allFiles = new ArrayList<>(); + collectFiles(allFiles, startFolder, getRegexForFiles()); + + if (!allFiles.isEmpty()) { + tableFilesListController.setFiles(allFiles); + uploadStopBtn.setDisable(false); + previouslyOpenedPath = startFolder.getParent(); + } + } + } + /** * used to recursively walk all directories, every file will be added to the storage list * @param storage used to hold files diff --git a/src/main/resources/GamesTab.fxml b/src/main/resources/GamesTab.fxml index 4df7b16..15a924a 100644 --- a/src/main/resources/GamesTab.fxml +++ b/src/main/resources/GamesTab.fxml @@ -58,6 +58,11 @@ +