Merge pull request #2554 from SiboVG/issue-1081

[#1081] Add ability to choose user-defined component presets location
This commit is contained in:
Sibo Van Gool 2024-09-10 23:30:05 +02:00 committed by GitHub
commit fd735d85cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 214 additions and 28 deletions

View File

@ -1,6 +1,7 @@
package info.openrocket.core.database;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
@ -28,7 +29,7 @@ public class ComponentPresetDatabaseLoader extends AsynchronousDatabaseLoader {
private static final String SYSTEM_PRESET_DIR = "datafiles/components";
private int fileCount = 0;
private int presetCount = 0;
/** the database is immutable*/
private final ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase();
@ -58,28 +59,28 @@ public class ComponentPresetDatabaseLoader extends AsynchronousDatabaseLoader {
}
/**
* loads the user defined defined components into the database
* loads the user defined component presets into the database
* uses the directory defined in the preferences
*/
private void loadUserComponents() {
log.info("Starting reading user-defined component presets");
SimpleFileFilter orcFilter = new SimpleFileFilter("", false, "orc");
FileIterator iterator;
try {
iterator = new DirectoryIterator(
Application.getPreferences().getDefaultUserComponentDirectory(),
orcFilter,
true);
} catch (IOException ioex) {
log.debug("Error opening UserComponentDirectory", ioex);
return;
}
while (iterator.hasNext()) {
Pair<File, InputStream> f = iterator.next();
Collection<ComponentPreset> presets = loadFile(f.getU().getName(), f.getV());
componentPresetDao.addAll(presets);
fileCount++;
presetCount += presets.size();
int initialCount = presetCount;
for (File file : (Application.getPreferences()).getUserComponentPresetFiles()) {
if (file.isFile()) {
try {
InputStream stream = new FileInputStream(file);
loadFile(file.getName(), stream);
} catch (IOException e) {
log.warn("Error opening file " + file, e);
}
} else if (file.isDirectory()) {
loadDirectory(orcFilter, file);
} else {
log.warn("User-defined motor file " + file + " is neither file nor directory");
}
}
log.info("Ending reading user-defined component presets, presetCount=" + (presetCount-initialCount));
}
/**
@ -90,7 +91,7 @@ public class ComponentPresetDatabaseLoader extends AsynchronousDatabaseLoader {
log.info("Loading component presets from " + SYSTEM_PRESET_DIR);
FileIterator iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR, new SimpleFileFilter("", false, "orc"));
if(iterator == null)
if (iterator == null)
return;
while (iterator.hasNext()) {
@ -115,6 +116,28 @@ public class ComponentPresetDatabaseLoader extends AsynchronousDatabaseLoader {
OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
Collection<ComponentPreset> presets = loader.load(stream, fileName);
return presets;
}
/**
* loads an entire directory of component presets
*
* @param fileFilter the supported extensions of files
* @param file the directory file object
*/
private void loadDirectory(SimpleFileFilter fileFilter, File file) {
FileIterator iterator;
try {
iterator = new DirectoryIterator(file, fileFilter, true);
} catch (IOException ioex) {
log.debug("Error opening UserComponentDirectory", ioex);
return;
}
while (iterator.hasNext()) {
Pair<File, InputStream> f = iterator.next();
Collection<ComponentPreset> presets = loadFile(f.getU().getName(), f.getV());
componentPresetDao.addAll(presets);
fileCount++;
presetCount += presets.size();
}
}
}

View File

@ -45,6 +45,7 @@ public abstract class ApplicationPreferences implements ChangeSource, ORPreferen
public static final String BODY_COMPONENT_INSERT_POSITION_KEY = "BodyComponentInsertPosition";
public static final String STAGE_INSERT_POSITION_KEY = "StageInsertPosition";
public static final String USER_THRUST_CURVES_KEY = "UserThrustCurves";
public static final String USER_COMPONENT_PRESETS_KEY = "UserComponentPresets";
public static final String DEFAULT_MACH_NUMBER = "DefaultMachNumber";
@ -1018,7 +1019,57 @@ public abstract class ApplicationPreferences implements ChangeSource, ORPreferen
return null;
}
public File getDefaultUserComponentDirectory() {
/**
* Return a list of files/directories to be loaded as custom component presets.
* <p>
* If this property has not been set, the directory "Components" in the user
* application directory will be used. The directory will be created if it does not
* exist.
*
* @return a list of files to load as component presets.
*/
public List<File> getUserComponentPresetFiles() {
List<File> list = new ArrayList<>();
String files = getString(USER_COMPONENT_PRESETS_KEY, null);
if (files == null) {
// Default to application directory
File cpdir = getDefaultUserComponentFile();
if (!cpdir.isDirectory()) {
cpdir.mkdirs();
}
list.add(cpdir);
} else {
for (String file : files.split("\\" + SPLIT_CHARACTER)) {
file = file.trim();
if (file.length() > 0) {
list.add(new File(file));
}
}
}
return list;
}
/**
* Returns the files/directories to be loaded as custom component presets, formatting as a string. If there are multiple
* locations, they are separated by a semicolon.
*
* @return a list of files to load as component presets, formatted as a semicolon separated string.
*/
public String getUserComponentPresetFilesAsString() {
List<File> files = getUserComponentPresetFiles();
StringBuilder sb = new StringBuilder();
for (File file : files) {
if (!sb.isEmpty()) {
sb.append(";");
}
sb.append(file.getAbsolutePath());
}
return sb.toString();
}
public File getDefaultUserComponentFile() {
File compdir = new File(SystemInfo.getUserApplicationDirectory(), "Components");
if (!compdir.isDirectory()) {
@ -1034,6 +1085,28 @@ public abstract class ApplicationPreferences implements ChangeSource, ORPreferen
return compdir;
}
/**
* Set the list of files/directories to be loaded as custom component presets.
*
* @param files the files to load, or <code>null</code> to reset to default value.
*/
public void setUserComponentPresetFiles(List<File> files) {
if (files == null) {
putString(USER_COMPONENT_PRESETS_KEY, null);
return;
}
StringBuilder str = new StringBuilder();
for (File file : files) {
if (!str.isEmpty()) {
str.append(SPLIT_CHARACTER);
}
str.append(file.getAbsolutePath());
}
putString(USER_COMPONENT_PRESETS_KEY, str.toString());
}
/**
* Return a list of files/directories to be loaded as custom thrust curves.
* <p>

View File

@ -357,11 +357,14 @@ pref.dlg.checkbox.ShowDiscardConfirmation.ttip = If checked, you will be asked i
pref.dlg.checkbox.ShowDiscardSimulationConfirmation = Show confirmation dialog for discarding simulation changes
pref.dlg.checkbox.ShowDiscardSimulationConfirmation.ttip = If checked, you will be asked if you want really want to discard simulation configuration configuration changes.
pref.dlg.lbl.User-definedthrust = User-defined thrust curves:
pref.dlg.lbl.User-definedComponentPreset = User-defined component presets:
pref.dlg.lbl.Windspeed = Wind speed
pref.dlg.Allthrustcurvefiles = All thrust curve files (*.eng; *.rse; *.zip; directories)
pref.dlg.RASPfiles = RASP motor files (*.eng)
pref.dlg.RockSimfiles = RockSim engine files (*.rse)
pref.dlg.ZIParchives = ZIP archives (*.zip)
pref.dlg.AllComponentPresetfiles = All component preset files (*.orc; directories)
pref.dlg.ORCfiles = OpenRocket component files (*.orc)
pref.dlg.checkbox.Checkupdates = Always check for software updates at startup
pref.dlg.checkbox.Checkupdates.ttip = Check for software updates every time you start up OpenRocket
pref.dlg.checkbox.CheckBetaupdates = Also check for pre-releases

View File

@ -20,6 +20,7 @@ import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
@ -128,7 +129,7 @@ public class GeneralPreferencesPanel extends PreferencesPanel {
//// You need to restart OpenRocket for the theme change to take effect.
final JLabel lblRestartORTheme = new JLabel();
lblRestartORTheme.setForeground(GUIUtil.getUITheme().getDarkErrorColor());
this.add(lblRestartORTheme, "spanx, wrap para*2, growx");
this.add(lblRestartORTheme, "spanx, wrap, growx");
fontSizeSpinner.addChangeListener(new ChangeListener() {
@Override
@ -156,6 +157,8 @@ public class GeneralPreferencesPanel extends PreferencesPanel {
}
});
this.add(new JSeparator(JSeparator.HORIZONTAL), "spanx, growx, wrap para");
//// User-defined thrust curves:
this.add(new JLabel(trans.get("pref.dlg.lbl.User-definedthrust")), "spanx, wrap");
final JTextField field = new JTextField();
@ -251,10 +254,94 @@ public class GeneralPreferencesPanel extends PreferencesPanel {
DescriptionArea desc = new DescriptionArea(trans.get("pref.dlg.DescriptionArea.Adddirectories"), 3, -1.5f, false);
desc.setBackground(GUIUtil.getUITheme().getBackgroundColor());
desc.setForeground(GUIUtil.getUITheme().getTextColor());
this.add(desc, "spanx, growx, wrap 40lp");
this.add(desc, "spanx, growx, wrap unrel");
//// User-defined component presets:
this.add(new JLabel(trans.get("pref.dlg.lbl.User-definedComponentPreset")), "spanx, wrap");
final JTextField fieldCompPres = new JTextField();
str = preferences.getUserComponentPresetFilesAsString();
fieldCompPres.setText(str);
fieldCompPres.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
changed();
}
@Override
public void insertUpdate(DocumentEvent e) {
changed();
}
@Override
public void changedUpdate(DocumentEvent e) {
changed();
}
private void changed() {
String text = fieldCompPres.getText();
List<File> list = new ArrayList<>();
for (String s : text.split(";")) {
s = s.trim();
if (s.length() > 0) {
list.add(new File(s));
}
}
preferences.setUserComponentPresetFiles(list);
}
});
this.add(fieldCompPres, "w 100px, gapright unrel, spanx, growx, split");
//// Add button
button = new JButton(trans.get("pref.dlg.but.add"));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
SimpleFileFilter filter =
new SimpleFileFilter(
trans.get("pref.dlg.AllComponentPresetfiles"),
true, "orc");
chooser.addChoosableFileFilter(filter);
//// OpenRocket component files (*.orc)
chooser.addChoosableFileFilter(new SimpleFileFilter(trans.get("pref.dlg.ORCfiles"),
true, "orc"));
chooser.setFileFilter(filter);
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
if (defaultDirectory != null) {
chooser.setCurrentDirectory(defaultDirectory);
}
//// Add
int returnVal = chooser.showDialog(GeneralPreferencesPanel.this, trans.get("pref.dlg.Add"));
if (returnVal == JFileChooser.APPROVE_OPTION) {
log.info(Markers.USER_MARKER, "Adding component preset file: " + chooser.getSelectedFile());
defaultDirectory = chooser.getCurrentDirectory();
String text = fieldCompPres.getText().trim();
if (text.length() > 0) {
text += ";";
}
text += chooser.getSelectedFile().getAbsolutePath();
fieldCompPres.setText(text);
}
}
});
this.add(button, "gapright unrel");
//// Reset button
button = new JButton(trans.get("pref.dlg.but.reset"));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// First one sets to the default, but does not un-set the pref
fieldCompPres.setText(preferences.getDefaultUserComponentFile().getAbsolutePath());
preferences.setUserComponentPresetFiles(null);
}
});
this.add(button, "wrap");
this.add(new JSeparator(JSeparator.HORIZONTAL), "spanx, growx, wrap para");
//// Check for software updates at startup
final JCheckBox softwareUpdateBox =

View File

@ -332,7 +332,7 @@ public class ComponentPresetEditor extends JPanel implements PresetResultListene
chooser.setCurrentDirectory(editContext.getLastDirectory());
}
else {
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory());
chooser.setCurrentDirectory((Application.getPreferences()).getDefaultUserComponentFile());
}
int option = chooser.showOpenDialog(ComponentPresetEditor.this);
@ -414,7 +414,7 @@ public class ComponentPresetEditor extends JPanel implements PresetResultListene
chooser.setSelectedFile(editContext.getOpenedFile());
}
else {
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory());
chooser.setCurrentDirectory((Application.getPreferences()).getDefaultUserComponentFile());
}
int option = chooser.showSaveDialog(ComponentPresetEditor.this);