diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileDialogBase.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileDialogBase.java new file mode 100644 index 0000000000..ee94cf04bb --- /dev/null +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileDialogBase.java @@ -0,0 +1,84 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.uielements; + +import com.willwinder.universalgcodesender.uielements.helpers.FilenameFilterAdapter; +import org.apache.commons.lang3.StringUtils; + +import javax.swing.filechooser.FileFilter; +import java.awt.FileDialog; +import java.awt.Frame; +import java.io.File; +import java.util.Optional; + +/** + * A generic file dialog base + */ +public class FileDialogBase extends FileDialog { + + public FileDialogBase(String directory) { + super((Frame) null); + + File directoryFile = new File(directory); + if (directoryFile.isFile()) { + directory = directoryFile.getParent(); + } + setDirectory(directory); + } + + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + setModal(true); + requestFocus(); + } + + /** + * Returns the selected file or an empty optional + * + * @return the selected file + */ + public Optional getSelectedFile() { + String file = getFile(); + if (StringUtils.isEmpty(file)) { + return Optional.empty(); + } + + return Optional.of(new File(getDirectory() + File.separatorChar + getFile())); + } + + /** + * Sets a file filter + * + * @param fileFilter the file filter + */ + public void setFileFilter(FileFilter fileFilter) { + setFilenameFilter(new FilenameFilterAdapter(fileFilter)); + } + + /** + * Sets the selected file + * + * @param file the selected file + */ + public void setSelectedFile(File file) { + setDirectory(file.getParent()); + setFile(file.getName()); + } +} diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileOpenDialog.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileOpenDialog.java new file mode 100644 index 0000000000..d58135637b --- /dev/null +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileOpenDialog.java @@ -0,0 +1,28 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.uielements; + +import java.awt.FileDialog; + +public class FileOpenDialog extends FileDialogBase { + public FileOpenDialog(String directory) { + super(directory); + setMode(FileDialog.LOAD); + } +} diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileSaveDialog.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileSaveDialog.java new file mode 100644 index 0000000000..745b096266 --- /dev/null +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/FileSaveDialog.java @@ -0,0 +1,32 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.uielements; + +import java.awt.FileDialog; + +public class FileSaveDialog extends FileDialogBase { + public FileSaveDialog(String directory) { + super(directory); + setMode(FileDialog.SAVE); + } + + public FileSaveDialog() { + this(""); + } +} diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/FirmwareSettingsFileTypeFilter.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/FirmwareSettingsFileTypeFilter.java index e781c40238..e01546da86 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/FirmwareSettingsFileTypeFilter.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/FirmwareSettingsFileTypeFilter.java @@ -1,5 +1,5 @@ /* - Copyright 2018 Will Winder + Copyright 2018-2024 Will Winder This file is part of Universal Gcode Sender (UGS). @@ -19,9 +19,9 @@ This file is part of Universal Gcode Sender (UGS). package com.willwinder.universalgcodesender.uielements.components; +import com.willwinder.universalgcodesender.uielements.FileOpenDialog; import org.apache.commons.lang3.StringUtils; -import javax.swing.JFileChooser; import javax.swing.filechooser.FileFilter; import java.io.File; @@ -29,20 +29,16 @@ This file is part of Universal Gcode Sender (UGS). * FileFilter which is limited to firmware settings files. */ public class FirmwareSettingsFileTypeFilter extends FileFilter { - public static JFileChooser getSettingsFileChooser() { - FirmwareSettingsFileTypeFilter filter = new FirmwareSettingsFileTypeFilter(); - - // Setup file browser with the last path used. - JFileChooser fileChooser = new JFileChooser(); - fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooser.setFileHidingEnabled(true); - fileChooser.addChoosableFileFilter(filter); - fileChooser.setAcceptAllFileFilterUsed(true); - fileChooser.setFileFilter(filter); - - return fileChooser; + private static FileOpenDialog fileOpenDialog; + + public static FileOpenDialog getSettingsFileChooser() { + if (fileOpenDialog == null) { + fileOpenDialog = new FileOpenDialog(""); + fileOpenDialog.setFileFilter(new FirmwareSettingsFileTypeFilter()); + } + return fileOpenDialog; } - + @Override public boolean accept(File f) { if (f.isDirectory()) { @@ -51,7 +47,7 @@ public boolean accept(File f) { return StringUtils.endsWith(f.getName(), ".settings"); } - + @Override public String getDescription() { return "Firmware settings"; diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/firmware/FirmwareSettingsDialog.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/firmware/FirmwareSettingsDialog.java index 9996c47fbe..dd25372dc5 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/uielements/firmware/FirmwareSettingsDialog.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/firmware/FirmwareSettingsDialog.java @@ -25,13 +25,14 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.firmware.IFirmwareSettingsListener; import com.willwinder.universalgcodesender.i18n.Localization; import com.willwinder.universalgcodesender.model.BackendAPI; +import com.willwinder.universalgcodesender.uielements.FileOpenDialog; +import com.willwinder.universalgcodesender.uielements.FileSaveDialog; import com.willwinder.universalgcodesender.uielements.components.FirmwareSettingsFileTypeFilter; import com.willwinder.universalgcodesender.utils.SettingsComparator; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JDialog; -import javax.swing.JFileChooser; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.TableColumnModel; @@ -57,9 +58,9 @@ public class FirmwareSettingsDialog extends JDialog implements IFirmwareSettings private static final int COL_INDEX_SETTING = 0; private static final Logger logger = Logger.getLogger(FirmwareSettingsDialog.class.getName()); - private final IFirmwareSettings firmwareSettingsManager; + private final transient IFirmwareSettings firmwareSettingsManager; private final FirmwareSettingsTableModel firmwareSettingsTableModel; - private final BackendAPI backend; + private final transient BackendAPI backend; private JButton closeButton; private JButton saveButton; @@ -169,22 +170,20 @@ private void initComponents() { } private void importButtonActionPerformed() { - JFileChooser fileChooser = new JFileChooser(); - fileChooser.setFileFilter(new FirmwareSettingsFileTypeFilter()); - if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - FirmwareSettingUtils.importSettings(fileChooser.getSelectedFile(), backend.getController().getFirmwareSettings()); - } + FileOpenDialog fileChooser = FirmwareSettingsFileTypeFilter.getSettingsFileChooser(); + fileChooser.setVisible(true); + fileChooser.getSelectedFile().ifPresent(file -> FirmwareSettingUtils.importSettings(file, backend.getController().getFirmwareSettings())); } private void exportButtonActionPerformed() { - JFileChooser fileChooser = new JFileChooser(); + FileSaveDialog fileSaveDialog = new FileSaveDialog(); + fileSaveDialog.setFileFilter(new FirmwareSettingsFileTypeFilter()); + String date = LocalDate.now().format(DateTimeFormatter.ISO_DATE); - fileChooser.setSelectedFile(new File("firmware_" + date + ".settings")); - fileChooser.setFileFilter(new FirmwareSettingsFileTypeFilter()); - if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { - File file = fileChooser.getSelectedFile(); - FirmwareSettingUtils.exportSettings(file, backend.getController()); - } + fileSaveDialog.setSelectedFile(new File("firmware_" + date + ".settings")); + fileSaveDialog.setVisible(true); + + fileSaveDialog.getSelectedFile().ifPresent(file -> FirmwareSettingUtils.exportSettings(file, backend.getController())); } private void closeButtonActionPerformed() { diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/helpers/FilenameFilterAdapter.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/helpers/FilenameFilterAdapter.java new file mode 100644 index 0000000000..b80668b551 --- /dev/null +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/helpers/FilenameFilterAdapter.java @@ -0,0 +1,48 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.uielements.helpers; + +import org.apache.commons.io.filefilter.IOFileFilter; + +import javax.swing.filechooser.FileFilter; +import java.io.File; + +/** + * A file filter adapter to be used together with apache commons + * + * @author Joacim Breiler + */ +public class FilenameFilterAdapter implements IOFileFilter { + + private final FileFilter fileFilter; + + public FilenameFilterAdapter(FileFilter fileFilter) { + this.fileFilter = fileFilter; + } + + @Override + public boolean accept(File file) { + return fileFilter.accept(file); + } + + @Override + public boolean accept(File dir, String name) { + return fileFilter.accept(new File(dir.getAbsolutePath() + File.separatorChar + name)); + } +} diff --git a/ugs-platform/ugs-platform-plugin-setup-wizard/src/main/java/com/willwinder/ugs/nbp/setupwizard/panels/WizardPanelImportSettings.java b/ugs-platform/ugs-platform-plugin-setup-wizard/src/main/java/com/willwinder/ugs/nbp/setupwizard/panels/WizardPanelImportSettings.java index cda1820421..1396fb3356 100644 --- a/ugs-platform/ugs-platform-plugin-setup-wizard/src/main/java/com/willwinder/ugs/nbp/setupwizard/panels/WizardPanelImportSettings.java +++ b/ugs-platform/ugs-platform-plugin-setup-wizard/src/main/java/com/willwinder/ugs/nbp/setupwizard/panels/WizardPanelImportSettings.java @@ -24,6 +24,7 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.firmware.FirmwareSettingsFile; import com.willwinder.universalgcodesender.i18n.Localization; import com.willwinder.universalgcodesender.model.BackendAPI; +import com.willwinder.universalgcodesender.uielements.FileOpenDialog; import com.willwinder.universalgcodesender.uielements.components.FirmwareSettingsFileTypeFilter; import com.willwinder.universalgcodesender.uielements.components.RoundedPanel; import com.willwinder.universalgcodesender.uielements.helpers.ThemeColors; @@ -33,8 +34,6 @@ This file is part of Universal Gcode Sender (UGS). import org.openide.util.ImageUtilities; import javax.swing.JButton; -import javax.swing.JFileChooser; -import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -108,15 +107,15 @@ private void initComponents() { labelNameValue = new JLabel(""); labelNameValue.setFont(labelNameValue.getFont().deriveFont(Font.BOLD, 16)); - labelFirmware = new JLabel(Localization.getString("platform.plugin.setupwizard.import-settings.firmware"), JLabel.RIGHT); + labelFirmware = new JLabel(Localization.getString("platform.plugin.setupwizard.import-settings.firmware"), SwingConstants.RIGHT); labelFirmware.setFont(labelFirmware.getFont().deriveFont(Font.BOLD)); labelFirmwareValue = new JLabel(""); - labelCreatedBy = new JLabel(Localization.getString("platform.plugin.setupwizard.import-settings.created-by"), JLabel.RIGHT); + labelCreatedBy = new JLabel(Localization.getString("platform.plugin.setupwizard.import-settings.created-by"), SwingConstants.RIGHT); labelCreatedBy.setFont(labelCreatedBy.getFont().deriveFont(Font.BOLD)); labelCreatedByValue = new JLabel(""); - labelDate = new JLabel(Localization.getString("platform.plugin.setupwizard.import-settings.created-date"), JLabel.RIGHT); + labelDate = new JLabel(Localization.getString("platform.plugin.setupwizard.import-settings.created-date"), SwingConstants.RIGHT); labelDate.setFont(labelDate.getFont().deriveFont(Font.BOLD)); labelDateValue = new JLabel(""); @@ -129,11 +128,9 @@ private void initComponents() { buttonOpen = new JButton(Localization.getString("platform.plugin.setupwizard.import-settings.open-settings")); buttonOpen.addActionListener(event -> { - JFileChooser fileChooser = FirmwareSettingsFileTypeFilter.getSettingsFileChooser(); - int returnVal = fileChooser.showOpenDialog(new JFrame()); - if (returnVal == JFileChooser.APPROVE_OPTION) { - loadSettingsFile(fileChooser.getSelectedFile()); - } + FileOpenDialog fileChooser = FirmwareSettingsFileTypeFilter.getSettingsFileChooser(); + fileChooser.setVisible(true); + fileChooser.getSelectedFile().ifPresent(this::loadSettingsFile); }); buttonImport = new JButton(Localization.getString("platform.plugin.setupwizard.import-settings.import")); diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OpenAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OpenAction.java index b1c0d91922..e9b2ecadc1 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OpenAction.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OpenAction.java @@ -22,7 +22,7 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.ugs.nbp.lib.lookup.CentralLookup; import com.willwinder.ugs.nbp.lib.services.LocalizingService; import com.willwinder.universalgcodesender.model.BackendAPI; -import org.apache.commons.lang3.StringUtils; +import com.willwinder.universalgcodesender.uielements.FileOpenDialog; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionReferences; @@ -31,8 +31,6 @@ This file is part of Universal Gcode Sender (UGS). import org.openide.util.Lookup; import javax.swing.AbstractAction; -import java.awt.FileDialog; -import java.awt.Frame; import java.awt.event.ActionEvent; import java.io.File; @@ -59,7 +57,7 @@ public final class OpenAction extends AbstractAction { public static final String ICON_BASE = "resources/icons/open.svg"; private final transient FileFilterService fileFilterService; private final transient BackendAPI backend; - private final FileDialog fileChooser; + private final FileOpenDialog fileOpenDialog; public OpenAction() { this(CentralLookup.getDefault().lookup(BackendAPI.class).getSettings().getLastOpenedFilename()); @@ -74,7 +72,7 @@ public OpenAction(String directory) { putValue("menuText", LocalizingService.OpenTitle); putValue(NAME, LocalizingService.OpenTitle); - fileChooser = createFileChooser(directory); + fileOpenDialog = new FileOpenDialog(directory); } @Override @@ -84,25 +82,13 @@ public boolean isEnabled() { @Override public void actionPerformed(ActionEvent e) { - // Fetches all available file formats that UGS can open - fileChooser.setFilenameFilter(fileFilterService.getFilenameFilters()); - fileChooser.setVisible(true); - if (StringUtils.isNotEmpty(fileChooser.getFile())) { - File selectedFile = new File(fileChooser.getDirectory() + File.separatorChar + fileChooser.getFile()); - openFile(selectedFile); - } + fileOpenDialog.setFilenameFilter(fileFilterService.getFilenameFilters()); + fileOpenDialog.setVisible(true); + fileOpenDialog.getSelectedFile().ifPresent(this::openFile); } public void openFile(File selectedFile) { OpenFileAction action = new OpenFileAction(selectedFile); action.actionPerformed(null); } - - private FileDialog createFileChooser(String directory) { - FileDialog fileDialog = new FileDialog((Frame)null); - fileDialog.setDirectory(directory); - fileDialog.setMode(FileDialog.LOAD); - fileDialog.setMultipleMode(false); - return fileDialog; - } } diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/services/FileFilterService.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/services/FileFilterService.java index 2f3a286d1e..b0f69d82d3 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/services/FileFilterService.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/services/FileFilterService.java @@ -19,12 +19,11 @@ This file is part of Universal Gcode Sender (UGS). package com.willwinder.ugs.nbp.core.services; import com.willwinder.universalgcodesender.uielements.components.GcodeFileTypeFilter; -import org.apache.commons.io.filefilter.IOFileFilter; +import com.willwinder.universalgcodesender.uielements.helpers.FilenameFilterAdapter; import org.apache.commons.io.filefilter.OrFileFilter; import org.openide.util.lookup.ServiceProvider; import javax.swing.filechooser.FileFilter; -import java.io.File; import java.io.FilenameFilter; import java.util.HashSet; import java.util.Set; @@ -51,17 +50,7 @@ public void registerFileFilter(FileFilter fileFilter) { public FilenameFilter getFilenameFilters() { return new OrFileFilter(fileFilters.stream() - .map(fileFilter -> new IOFileFilter() { - @Override - public boolean accept(File file) { - return fileFilter.accept(file); - } - - @Override - public boolean accept(File directory, String filename) { - return fileFilter.accept(new File(directory.getAbsolutePath() + File.separatorChar + filename)); - } - } ) + .map(FilenameFilterAdapter::new) .collect(Collectors.toList())); } }