import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
+import net.sf.openrocket.arch.SystemInfo;
import net.sf.openrocket.database.Databases;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.gui.main.ExceptionHandler;
+import net.sf.openrocket.gui.print.PrintSettings;
+import net.sf.openrocket.l10n.L10N;
+import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.BodyComponent;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.FlightDataType;
-import net.sf.openrocket.simulation.GUISimulationConditions;
import net.sf.openrocket.simulation.RK4SimulationStepper;
+import net.sf.openrocket.simulation.SimulationOptions;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
public class Prefs {
private static final LogHelper log = Application.getLogger();
+ private static final String SPLIT_CHARACTER = "|";
+
+
+ private static final List<Locale> SUPPORTED_LOCALES;
+ static {
+ List<Locale> list = new ArrayList<Locale>();
+ for (String lang : new String[] { "en", "de", "es", "fr" }) {
+ list.add(new Locale(lang));
+ }
+ SUPPORTED_LOCALES = Collections.unmodifiableList(list);
+ }
+
+
/**
* Whether to use the debug-node instead of the normal node.
*/
*/
private static class BuildPropertyHolder {
+ public static final Properties PROPERTIES;
public static final String BUILD_VERSION;
public static final String BUILD_SOURCE;
public static final boolean DEFAULT_CHECK_UPDATES;
"build.properties", "build.version");
}
- Properties props = new Properties();
- props.load(is);
+ PROPERTIES = new Properties();
+ PROPERTIES.load(is);
is.close();
- String version = props.getProperty("build.version");
+ String version = PROPERTIES.getProperty("build.version");
if (version == null) {
throw new MissingResourceException(
"build.version not found in property file",
}
BUILD_VERSION = version.trim();
- BUILD_SOURCE = props.getProperty("build.source");
+ BUILD_SOURCE = PROPERTIES.getProperty("build.source");
if (BUILD_SOURCE == null) {
throw new MissingResourceException(
"build.source not found in property file",
"build.properties", "build.source");
}
- String value = props.getProperty("build.checkupdates");
+ String value = PROPERTIES.getProperty("build.checkupdates");
if (value != null)
DEFAULT_CHECK_UPDATES = Boolean.parseBoolean(value);
else
public static final String BODY_COMPONENT_INSERT_POSITION_KEY = "BodyComponentInsertPosition";
-
+ public static final String USER_THRUST_CURVES_KEY = "UserThrustCurves";
+
public static final String CONFIRM_DELETE_SIMULATION = "ConfirmDeleteSimulation";
// Preferences related to data export
* Within a holder class so they will load only when needed.
*/
private static class DefaultMaterialHolder {
+ private static final Translator trans = Application.getTranslator();
+
+ //// Elastic cord (round 2mm, 1/16 in)
private static final Material DEFAULT_LINE_MATERIAL =
- Databases.findMaterial(Material.Type.LINE, "Elastic cord (round 2mm, 1/16 in)",
+ Databases.findMaterial(Material.Type.LINE, trans.get("Databases.materials.Elasticcordround2mm"),
0.0018, false);
+ //// Ripstop nylon
private static final Material DEFAULT_SURFACE_MATERIAL =
- Databases.findMaterial(Material.Type.SURFACE, "Ripstop nylon", 0.067, false);
+ Databases.findMaterial(Material.Type.SURFACE, trans.get("Databases.materials.Ripstopnylon"), 0.067, false);
+ //// Cardboard
private static final Material DEFAULT_BULK_MATERIAL =
- Databases.findMaterial(Material.Type.BULK, "Cardboard", 680, false);
+ Databases.findMaterial(Material.Type.BULK, trans.get("Databases.materials.Cardboard"), 680, false);
}
//////////////////////
* Set a string preference.
*
* @param key the preference key
- * @param value the value to set
+ * @param value the value to set, or <code>null</code> to remove the key
*/
public static void putString(String key, String value) {
+ if (value == null) {
+ PREFNODE.remove(key);
+ return;
+ }
PREFNODE.put(key, value);
storeVersion();
}
+
+ /**
+ * Retrieve an enum value from the user preferences.
+ *
+ * @param <T> the enum type
+ * @param key the key
+ * @param def the default value, cannot be null
+ * @return the value in the preferences, or the default value
+ */
+ public static <T extends Enum<T>> T getEnum(String key, T def) {
+ if (def == null) {
+ throw new BugException("Default value cannot be null");
+ }
+
+ String value = getString(key, null);
+ if (value == null) {
+ return def;
+ }
+
+ try {
+ return Enum.valueOf(def.getDeclaringClass(), value);
+ } catch (IllegalArgumentException e) {
+ return def;
+ }
+ }
+
+ /**
+ * Store an enum value to the user preferences.
+ *
+ * @param key the key
+ * @param value the value to store, or null to remove the value
+ */
+ public static void putEnum(String key, Enum<?> value) {
+ if (value == null) {
+ putString(key, null);
+ } else {
+ putString(key, value.name());
+ }
+ }
+
+
/**
* Return a boolean preference.
*
//////////////////
-
+ public static List<Locale> getSupportedLocales() {
+ return SUPPORTED_LOCALES;
+ }
+
+ public static Locale getUserLocale() {
+ String locale = getString("locale", null);
+ return L10N.toLocale(locale);
+ }
+
+ public static void setUserLocale(Locale l) {
+ if (l == null) {
+ putString("locale", null);
+ } else {
+ putString("locale", l.toString());
+ }
+ }
+
+
public static boolean getCheckUpdates() {
return PREFNODE.getBoolean(CHECK_UPDATES, BuildPropertyHolder.DEFAULT_CHECK_UPDATES);
}
+ /**
+ * Return a list of files/directories to be loaded as custom thrust curves.
+ * <p>
+ * If this property has not been set, the directory "ThrustCurves" 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 thrust curves.
+ */
+ public static List<File> getUserThrustCurveFiles() {
+ List<File> list = new ArrayList<File>();
+
+ String files = getString(USER_THRUST_CURVES_KEY, null);
+ if (files == null) {
+ // Default to application directory
+ File tcdir = getDefaultUserThrustCurveFile();
+ if (!tcdir.isDirectory()) {
+ tcdir.mkdirs();
+ }
+ list.add(tcdir);
+ } else {
+ for (String file : files.split("\\" + SPLIT_CHARACTER)) {
+ file = file.trim();
+ if (file.length() > 0) {
+ list.add(new File(file));
+ }
+ }
+ }
+
+ return list;
+ }
+
+ public static File getDefaultUserThrustCurveFile() {
+ File appdir = SystemInfo.getUserApplicationDirectory();
+ File tcdir = new File(appdir, "ThrustCurves");
+ return tcdir;
+ }
+
+
+ /**
+ * Set the list of files/directories to be loaded as custom thrust curves.
+ *
+ * @param files the files to load, or <code>null</code> to reset to default value.
+ */
+ public static void setUserThrustCurveFiles(List<File> files) {
+ if (files == null) {
+ putString(USER_THRUST_CURVES_KEY, null);
+ return;
+ }
+
+ String str = "";
+
+ for (File file : files) {
+ if (str.length() > 0) {
+ str += SPLIT_CHARACTER;
+ }
+ str += file.getAbsolutePath();
+ }
+ putString(USER_THRUST_CURVES_KEY, str);
+ }
+
+
+
+
public static Color getDefaultColor(Class<? extends RocketComponent> c) {
String color = get("componentColors", c, DEFAULT_COLORS);
if (color == null)
return Color.BLACK;
+ Color clr = parseColor(color);
+ if (clr != null) {
+ return clr;
+ } else {
+ return Color.BLACK;
+ }
+ }
+
+ public static void setDefaultColor(Class<? extends RocketComponent> c, Color color) {
+ if (color == null)
+ return;
+ set("componentColors", c, stringifyColor(color));
+ }
+
+
+ private static Color parseColor(String color) {
+ if (color == null) {
+ return null;
+ }
+
String[] rgb = color.split(",");
if (rgb.length == 3) {
try {
} catch (NumberFormatException ignore) {
}
}
-
- return Color.BLACK;
+ return null;
}
- public static void setDefaultColor(Class<? extends RocketComponent> c, Color color) {
- if (color == null)
- return;
+
+ private static String stringifyColor(Color color) {
String string = color.getRed() + "," + color.getGreen() + "," + color.getBlue();
- set("componentColors", c, string);
+ return string;
}
+
+
public static Color getMotorBorderColor() {
// TODO: MEDIUM: Motor color (settable?)
return new Color(0, 0, 0, 200);
if (dpi < 10)
dpi = 960;
- return ((double) dpi) / 10.0;
+ return (dpi) / 10.0;
}
}
-
+ /**
+ * Return whether to use additional safety code checks.
+ */
+ public static boolean useSafetyChecks() {
+ // Currently default to false unless openrocket.debug.safetycheck is defined
+ String s = System.getProperty("openrocket.debug.safetycheck");
+ if (s != null && !(s.equalsIgnoreCase("false") || s.equalsIgnoreCase("off"))) {
+ return true;
+ }
+ return false;
+ }
+
+
public static Point getWindowPosition(Class<?> c) {
int x, y;
String pref = PREFNODE.node("windows").get("position." + c.getCanonicalName(), null);
return new Dimension(x, y);
}
+
+ public static boolean isWindowMaximized(Class<?> c) {
+ String pref = PREFNODE.node("windows").get("size." + c.getCanonicalName(), null);
+ return "max".equals(pref);
+ }
+
public static void setWindowSize(Class<?> c, Dimension d) {
PREFNODE.node("windows").put("size." + c.getCanonicalName(), "" + d.width + "," + d.height);
storeVersion();
}
+ public static void setWindowMaximized(Class<?> c) {
+ PREFNODE.node("windows").put("size." + c.getCanonicalName(), "max");
+ storeVersion();
+ }
+
+
+ //// Printing
+
+ public static PrintSettings getPrintSettings() {
+ PrintSettings settings = new PrintSettings();
+ Color c;
+
+ c = parseColor(getString("print.template.fillColor", null));
+ if (c != null) {
+ settings.setTemplateFillColor(c);
+ }
+
+ c = parseColor(getString("print.template.borderColor", null));
+ if (c != null) {
+ settings.setTemplateBorderColor(c);
+ }
+
+ settings.setPaperSize(getEnum("print.paper.size", settings.getPaperSize()));
+ settings.setPaperOrientation(getEnum("print.paper.orientation", settings.getPaperOrientation()));
+
+ return settings;
+ }
+
+ public static void setPrintSettings(PrintSettings settings) {
+ putString("print.template.fillColor", stringifyColor(settings.getTemplateFillColor()));
+ putString("print.template.borderColor", stringifyColor(settings.getTemplateBorderColor()));
+ putEnum("print.paper.size", settings.getPaperSize());
+ putEnum("print.paper.orientation", settings.getPaperOrientation());
+ }
//// Background flight data computation
public static Simulation getBackgroundSimulation(Rocket rocket) {
Simulation s = new Simulation(rocket);
- GUISimulationConditions cond = s.getConditions();
+ SimulationOptions cond = s.getOptions();
cond.setTimeStep(RK4SimulationStepper.RECOMMENDED_TIME_STEP * 2);
cond.setWindSpeedAverage(1.0);