Merge pull request #2554 from SiboVG/issue-1081
[#1081] Add ability to choose user-defined component presets location
This commit is contained in:
commit
fd735d85cc
@ -1,6 +1,7 @@
|
|||||||
package info.openrocket.core.database;
|
package info.openrocket.core.database;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -28,7 +29,7 @@ public class ComponentPresetDatabaseLoader extends AsynchronousDatabaseLoader {
|
|||||||
private static final String SYSTEM_PRESET_DIR = "datafiles/components";
|
private static final String SYSTEM_PRESET_DIR = "datafiles/components";
|
||||||
private int fileCount = 0;
|
private int fileCount = 0;
|
||||||
private int presetCount = 0;
|
private int presetCount = 0;
|
||||||
|
|
||||||
/** the database is immutable*/
|
/** the database is immutable*/
|
||||||
private final ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase();
|
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
|
* uses the directory defined in the preferences
|
||||||
*/
|
*/
|
||||||
private void loadUserComponents() {
|
private void loadUserComponents() {
|
||||||
|
log.info("Starting reading user-defined component presets");
|
||||||
SimpleFileFilter orcFilter = new SimpleFileFilter("", false, "orc");
|
SimpleFileFilter orcFilter = new SimpleFileFilter("", false, "orc");
|
||||||
FileIterator iterator;
|
int initialCount = presetCount;
|
||||||
try {
|
for (File file : (Application.getPreferences()).getUserComponentPresetFiles()) {
|
||||||
iterator = new DirectoryIterator(
|
if (file.isFile()) {
|
||||||
Application.getPreferences().getDefaultUserComponentDirectory(),
|
try {
|
||||||
orcFilter,
|
InputStream stream = new FileInputStream(file);
|
||||||
true);
|
loadFile(file.getName(), stream);
|
||||||
} catch (IOException ioex) {
|
} catch (IOException e) {
|
||||||
log.debug("Error opening UserComponentDirectory", ioex);
|
log.warn("Error opening file " + file, e);
|
||||||
return;
|
}
|
||||||
}
|
} else if (file.isDirectory()) {
|
||||||
while (iterator.hasNext()) {
|
loadDirectory(orcFilter, file);
|
||||||
Pair<File, InputStream> f = iterator.next();
|
} else {
|
||||||
Collection<ComponentPreset> presets = loadFile(f.getU().getName(), f.getV());
|
log.warn("User-defined motor file " + file + " is neither file nor directory");
|
||||||
componentPresetDao.addAll(presets);
|
}
|
||||||
fileCount++;
|
|
||||||
presetCount += presets.size();
|
|
||||||
}
|
}
|
||||||
|
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);
|
log.info("Loading component presets from " + SYSTEM_PRESET_DIR);
|
||||||
FileIterator iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR, new SimpleFileFilter("", false, "orc"));
|
FileIterator iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR, new SimpleFileFilter("", false, "orc"));
|
||||||
|
|
||||||
if(iterator == null)
|
if (iterator == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
@ -115,6 +116,28 @@ public class ComponentPresetDatabaseLoader extends AsynchronousDatabaseLoader {
|
|||||||
OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
|
OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
|
||||||
Collection<ComponentPreset> presets = loader.load(stream, fileName);
|
Collection<ComponentPreset> presets = loader.load(stream, fileName);
|
||||||
return presets;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 BODY_COMPONENT_INSERT_POSITION_KEY = "BodyComponentInsertPosition";
|
||||||
public static final String STAGE_INSERT_POSITION_KEY = "StageInsertPosition";
|
public static final String STAGE_INSERT_POSITION_KEY = "StageInsertPosition";
|
||||||
public static final String USER_THRUST_CURVES_KEY = "UserThrustCurves";
|
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";
|
public static final String DEFAULT_MACH_NUMBER = "DefaultMachNumber";
|
||||||
|
|
||||||
@ -1018,7 +1019,57 @@ public abstract class ApplicationPreferences implements ChangeSource, ORPreferen
|
|||||||
return null;
|
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");
|
File compdir = new File(SystemInfo.getUserApplicationDirectory(), "Components");
|
||||||
|
|
||||||
if (!compdir.isDirectory()) {
|
if (!compdir.isDirectory()) {
|
||||||
@ -1034,6 +1085,28 @@ public abstract class ApplicationPreferences implements ChangeSource, ORPreferen
|
|||||||
return compdir;
|
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.
|
* Return a list of files/directories to be loaded as custom thrust curves.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -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 = 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.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-definedthrust = User-defined thrust curves:
|
||||||
|
pref.dlg.lbl.User-definedComponentPreset = User-defined component presets:
|
||||||
pref.dlg.lbl.Windspeed = Wind speed
|
pref.dlg.lbl.Windspeed = Wind speed
|
||||||
pref.dlg.Allthrustcurvefiles = All thrust curve files (*.eng; *.rse; *.zip; directories)
|
pref.dlg.Allthrustcurvefiles = All thrust curve files (*.eng; *.rse; *.zip; directories)
|
||||||
pref.dlg.RASPfiles = RASP motor files (*.eng)
|
pref.dlg.RASPfiles = RASP motor files (*.eng)
|
||||||
pref.dlg.RockSimfiles = RockSim engine files (*.rse)
|
pref.dlg.RockSimfiles = RockSim engine files (*.rse)
|
||||||
pref.dlg.ZIParchives = ZIP archives (*.zip)
|
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 = 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.Checkupdates.ttip = Check for software updates every time you start up OpenRocket
|
||||||
pref.dlg.checkbox.CheckBetaupdates = Also check for pre-releases
|
pref.dlg.checkbox.CheckBetaupdates = Also check for pre-releases
|
||||||
|
@ -20,6 +20,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JProgressBar;
|
import javax.swing.JProgressBar;
|
||||||
|
import javax.swing.JSeparator;
|
||||||
import javax.swing.JSpinner;
|
import javax.swing.JSpinner;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import javax.swing.SwingUtilities;
|
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.
|
//// You need to restart OpenRocket for the theme change to take effect.
|
||||||
final JLabel lblRestartORTheme = new JLabel();
|
final JLabel lblRestartORTheme = new JLabel();
|
||||||
lblRestartORTheme.setForeground(GUIUtil.getUITheme().getDarkErrorColor());
|
lblRestartORTheme.setForeground(GUIUtil.getUITheme().getDarkErrorColor());
|
||||||
this.add(lblRestartORTheme, "spanx, wrap para*2, growx");
|
this.add(lblRestartORTheme, "spanx, wrap, growx");
|
||||||
|
|
||||||
fontSizeSpinner.addChangeListener(new ChangeListener() {
|
fontSizeSpinner.addChangeListener(new ChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -156,6 +157,8 @@ public class GeneralPreferencesPanel extends PreferencesPanel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.add(new JSeparator(JSeparator.HORIZONTAL), "spanx, growx, wrap para");
|
||||||
|
|
||||||
//// User-defined thrust curves:
|
//// User-defined thrust curves:
|
||||||
this.add(new JLabel(trans.get("pref.dlg.lbl.User-definedthrust")), "spanx, wrap");
|
this.add(new JLabel(trans.get("pref.dlg.lbl.User-definedthrust")), "spanx, wrap");
|
||||||
final JTextField field = new JTextField();
|
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);
|
DescriptionArea desc = new DescriptionArea(trans.get("pref.dlg.DescriptionArea.Adddirectories"), 3, -1.5f, false);
|
||||||
desc.setBackground(GUIUtil.getUITheme().getBackgroundColor());
|
desc.setBackground(GUIUtil.getUITheme().getBackgroundColor());
|
||||||
desc.setForeground(GUIUtil.getUITheme().getTextColor());
|
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
|
//// Check for software updates at startup
|
||||||
final JCheckBox softwareUpdateBox =
|
final JCheckBox softwareUpdateBox =
|
||||||
|
@ -332,7 +332,7 @@ public class ComponentPresetEditor extends JPanel implements PresetResultListene
|
|||||||
chooser.setCurrentDirectory(editContext.getLastDirectory());
|
chooser.setCurrentDirectory(editContext.getLastDirectory());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory());
|
chooser.setCurrentDirectory((Application.getPreferences()).getDefaultUserComponentFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
int option = chooser.showOpenDialog(ComponentPresetEditor.this);
|
int option = chooser.showOpenDialog(ComponentPresetEditor.this);
|
||||||
@ -414,7 +414,7 @@ public class ComponentPresetEditor extends JPanel implements PresetResultListene
|
|||||||
chooser.setSelectedFile(editContext.getOpenedFile());
|
chooser.setSelectedFile(editContext.getOpenedFile());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory());
|
chooser.setCurrentDirectory((Application.getPreferences()).getDefaultUserComponentFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
int option = chooser.showSaveDialog(ComponentPresetEditor.this);
|
int option = chooser.showSaveDialog(ComponentPresetEditor.this);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user