1 package net.sf.openrocket.startup;
\r
3 import java.util.HashMap;
\r
4 import java.util.Map;
\r
5 import java.util.Set;
\r
7 import net.sf.openrocket.database.Databases;
\r
8 import net.sf.openrocket.l10n.Translator;
\r
9 import net.sf.openrocket.material.Material;
\r
10 import net.sf.openrocket.preset.ComponentPreset;
\r
11 import net.sf.openrocket.rocketcomponent.BodyComponent;
\r
12 import net.sf.openrocket.rocketcomponent.FinSet;
\r
13 import net.sf.openrocket.rocketcomponent.InternalComponent;
\r
14 import net.sf.openrocket.rocketcomponent.LaunchLug;
\r
15 import net.sf.openrocket.rocketcomponent.MassObject;
\r
16 import net.sf.openrocket.rocketcomponent.RecoveryDevice;
\r
17 import net.sf.openrocket.rocketcomponent.RocketComponent;
\r
18 import net.sf.openrocket.util.BugException;
\r
19 import net.sf.openrocket.util.BuildProperties;
\r
20 import net.sf.openrocket.util.Color;
\r
21 import net.sf.openrocket.util.LineStyle;
\r
22 import net.sf.openrocket.util.MathUtil;
\r
23 import net.sf.openrocket.util.UniqueID;
\r
25 public abstract class Preferences {
\r
28 * Well known string keys to preferences.
\r
29 * There are other strings out there in the source as well.
\r
31 public static final String BODY_COMPONENT_INSERT_POSITION_KEY = "BodyComponentInsertPosition";
\r
32 public static final String USER_THRUST_CURVES_KEY = "UserThrustCurves";
\r
33 public static final String CONFIRM_DELETE_SIMULATION = "ConfirmDeleteSimulation";
\r
34 // Preferences related to data export
\r
35 public static final String EXPORT_FIELD_SEPARATOR = "ExportFieldSeparator";
\r
36 public static final String EXPORT_SIMULATION_COMMENT = "ExportSimulationComment";
\r
37 public static final String EXPORT_FIELD_NAME_COMMENT = "ExportFieldDescriptionComment";
\r
38 public static final String EXPORT_EVENT_COMMENTS = "ExportEventComments";
\r
39 public static final String EXPORT_COMMENT_CHARACTER = "ExportCommentCharacter";
\r
40 public static final String USER_LOCAL = "locale";
\r
42 public static final String PLOT_SHOW_POINTS = "ShowPlotPoints";
\r
44 private static final String CHECK_UPDATES = "CheckUpdates";
\r
45 public static final String LAST_UPDATE = "LastUpdateVersion";
\r
47 public static final String MOTOR_DIAMETER_FILTER = "MotorDiameterMatch";
\r
48 public static final String MOTOR_HIDE_SIMILAR = "MotorHideSimilar";
\r
51 public static final String PREFERRED_THRUST_CURVE_MOTOR_NODE = "preferredThrustCurveMotors";
\r
54 * ******************************************************************************************
\r
56 * Abstract methods which must be implemented by any derived class.
\r
58 public abstract boolean getBoolean( String key, boolean defaultValue );
\r
59 public abstract void putBoolean( String key, boolean value );
\r
61 public abstract int getInt( String key, int defaultValue);
\r
62 public abstract void putInt( String key, int value );
\r
64 public abstract double getDouble( String key, double defaultValue );
\r
65 public abstract void putDouble( String key, double value );
\r
67 public abstract String getString( String key, String defaultValue );
\r
68 public abstract void putString( String key, String value );
\r
71 * Directory represents a way to collect multiple keys together. Implementors may
\r
72 * choose to concatenate the directory with the key using some special character.
\r
75 * @param defaultValue
\r
78 public abstract String getString( String directory, String key, String defaultValue);
\r
80 public abstract void putString( String directory, String key, String value );
\r
83 * ******************************************************************************************
\r
85 public final boolean getCheckUpdates() {
\r
86 return this.getBoolean(CHECK_UPDATES, BuildProperties.getDefaultCheckUpdates());
\r
89 public final void setCheckUpdates(boolean check) {
\r
90 this.putBoolean(CHECK_UPDATES, check);
\r
93 public final double getDefaultMach() {
\r
94 // TODO: HIGH: implement custom default mach number
\r
99 * Return the OpenRocket unique ID.
\r
101 * @return a random ID string that stays constant between OpenRocket executions
\r
103 public final String getUniqueID() {
\r
104 String id = this.getString("id", null);
\r
106 id = UniqueID.uuid();
\r
107 this.putString("id", id);
\r
113 * Returns a limited-range integer value from the preferences. If the value
\r
114 * in the preferences is negative or greater than max, then the default value
\r
117 * @param key The preference to retrieve.
\r
118 * @param max Maximum allowed value for the choice.
\r
119 * @param def Default value.
\r
120 * @return The preference value.
\r
122 public final int getChoice(String key, int max, int def) {
\r
123 int v = this.getInt(key, def);
\r
124 if ((v < 0) || (v > max))
\r
130 * Helper method that puts an integer choice value into the preferences.
\r
132 * @param key the preference key.
\r
133 * @param value the value to store.
\r
135 public final void putChoice(String key, int value) {
\r
136 this.putInt(key, value);
\r
140 * Retrieve an enum value from the user preferences.
\r
142 * @param <T> the enum type
\r
143 * @param key the key
\r
144 * @param def the default value, cannot be null
\r
145 * @return the value in the preferences, or the default value
\r
147 public final <T extends Enum<T>> T getEnum(String key, T def) {
\r
149 throw new BugException("Default value cannot be null");
\r
152 String value = getString(key, null);
\r
153 if (value == null) {
\r
158 return Enum.valueOf(def.getDeclaringClass(), value);
\r
159 } catch (IllegalArgumentException e) {
\r
165 * Store an enum value to the user preferences.
\r
167 * @param key the key
\r
168 * @param value the value to store, or null to remove the value
\r
170 public final void putEnum(String key, Enum<?> value) {
\r
171 if (value == null) {
\r
172 putString(key, null);
\r
174 putString(key, value.name());
\r
178 public Color getDefaultColor(Class<? extends RocketComponent> c) {
\r
179 String color = get("componentColors", c, DEFAULT_COLORS);
\r
181 return Color.BLACK;
\r
183 Color clr = parseColor(color);
\r
187 return Color.BLACK;
\r
191 public final void setDefaultColor(Class<? extends RocketComponent> c, Color color) {
\r
194 putString("componentColors", c.getSimpleName(), stringifyColor(color));
\r
199 * Retrieve a Line style for the given component.
\r
203 public final LineStyle getDefaultLineStyle(Class<? extends RocketComponent> c) {
\r
204 String value = get("componentStyle", c, DEFAULT_LINE_STYLES);
\r
206 return LineStyle.valueOf(value);
\r
207 } catch (Exception e) {
\r
208 return LineStyle.SOLID;
\r
213 * Set a default line style for the given component.
\r
217 public final void setDefaultLineStyle(Class<? extends RocketComponent> c,
\r
221 putString("componentStyle", c.getSimpleName(), style.name());
\r
225 * Get the default material type for the given component.
\r
226 * @param componentClass
\r
227 * @param type the Material.Type to return.
\r
230 public Material getDefaultComponentMaterial(
\r
231 Class<? extends RocketComponent> componentClass,
\r
232 Material.Type type) {
\r
234 String material = get("componentMaterials", componentClass, null);
\r
235 if (material != null) {
\r
237 Material m = Material.fromStorableString(material);
\r
238 if (m.getType() == type)
\r
240 } catch (IllegalArgumentException ignore) {
\r
246 return DefaultMaterialHolder.DEFAULT_LINE_MATERIAL;
\r
248 return DefaultMaterialHolder.DEFAULT_SURFACE_MATERIAL;
\r
250 return DefaultMaterialHolder.DEFAULT_BULK_MATERIAL;
\r
252 throw new IllegalArgumentException("Unknown material type: " + type);
\r
256 * Set the default material for a component type.
\r
257 * @param componentClass
\r
260 public void setDefaultComponentMaterial(
\r
261 Class<? extends RocketComponent> componentClass, Material material) {
\r
263 putString("componentMaterials", componentClass.getSimpleName(),
\r
264 material == null ? null : material.toStorableString());
\r
268 * get a net.sf.openrocket.util.Color object for the given key.
\r
270 * @param defaultValue
\r
273 public final Color getColor( String key, Color defaultValue ) {
\r
274 Color c = parseColor( getString(key,null) );
\r
276 return defaultValue;
\r
282 * set a net.sf.openrocket.util.Color preference value for the given key.
\r
286 public final void putColor( String key, Color value ) {
\r
287 putString( key, stringifyColor(value) );
\r
291 * Helper function to convert a string representation into a net.sf.openrocket.util.Color object.
\r
295 protected static Color parseColor(String color) {
\r
296 if (color == null) {
\r
300 String[] rgb = color.split(",");
\r
301 if (rgb.length == 3) {
\r
303 int red = MathUtil.clamp(Integer.parseInt(rgb[0]), 0, 255);
\r
304 int green = MathUtil.clamp(Integer.parseInt(rgb[1]), 0, 255);
\r
305 int blue = MathUtil.clamp(Integer.parseInt(rgb[2]), 0, 255);
\r
306 return new Color(red, green, blue);
\r
307 } catch (NumberFormatException ignore) {
\r
314 * Helper function to convert a net.sf.openrocket.util.Color object into a
\r
315 * String before storing in a preference.
\r
319 protected static String stringifyColor(Color color) {
\r
320 String string = color.getRed() + "," + color.getGreen() + "," + color.getBlue();
\r
325 * Special helper function which allows for a map of default values.
\r
327 * First getString(directory,componentClass.getSimpleName(), null) is invoked,
\r
328 * if the returned value is null, the defaultMap is consulted for a value.
\r
331 * @param componentClass
\r
332 * @param defaultMap
\r
335 protected String get(String directory,
\r
336 Class<? extends RocketComponent> componentClass,
\r
337 Map<Class<?>, String> defaultMap) {
\r
339 // Search preferences
\r
340 Class<?> c = componentClass;
\r
341 while (c != null && RocketComponent.class.isAssignableFrom(c)) {
\r
342 String value = this.getString(directory, c.getSimpleName(), null);
\r
345 c = c.getSuperclass();
\r
348 if (defaultMap == null)
\r
352 c = componentClass;
\r
353 while (RocketComponent.class.isAssignableFrom(c)) {
\r
354 String value = defaultMap.get(c);
\r
357 c = c.getSuperclass();
\r
363 public abstract void addUserMaterial(Material m);
\r
364 public abstract Set<Material> getUserMaterials();
\r
365 public abstract void removeUserMaterial(Material m);
\r
367 public abstract void setComponentFavorite( ComponentPreset preset, ComponentPreset.Type type, boolean favorite );
\r
368 public abstract Set<String> getComponentFavorites( ComponentPreset.Type type );
\r
371 * Map of default line styles
\r
373 private static final HashMap<Class<?>, String> DEFAULT_LINE_STYLES =
\r
374 new HashMap<Class<?>, String>();
\r
376 DEFAULT_LINE_STYLES.put(RocketComponent.class, LineStyle.SOLID.name());
\r
377 DEFAULT_LINE_STYLES.put(MassObject.class, LineStyle.DASHED.name());
\r
381 * Within a holder class so they will load only when needed.
\r
383 private static class DefaultMaterialHolder {
\r
384 private static final Translator trans = Application.getTranslator();
\r
386 //// Elastic cord (round 2mm, 1/16 in)
\r
387 private static final Material DEFAULT_LINE_MATERIAL =
\r
388 Databases.findMaterial(Material.Type.LINE, "Elasticcordround2mm", trans.get("Databases.materials.Elasticcordround2mm"),0.0018);
\r
390 private static final Material DEFAULT_SURFACE_MATERIAL =
\r
391 Databases.findMaterial(Material.Type.SURFACE, "Ripstopnylon", trans.get("Databases.materials.Ripstopnylon"), 0.067);
\r
393 private static final Material DEFAULT_BULK_MATERIAL =
\r
394 Databases.findMaterial(Material.Type.BULK, "Cardboard", trans.get("Databases.materials.Cardboard"), 680);
\r
397 private static final HashMap<Class<?>, String> DEFAULT_COLORS =
\r
398 new HashMap<Class<?>, String>();
\r
400 DEFAULT_COLORS.put(BodyComponent.class, "0,0,240");
\r
401 DEFAULT_COLORS.put(FinSet.class, "0,0,200");
\r
402 DEFAULT_COLORS.put(LaunchLug.class, "0,0,180");
\r
403 DEFAULT_COLORS.put(InternalComponent.class, "170,0,100");
\r
404 DEFAULT_COLORS.put(MassObject.class, "0,0,0");
\r
405 DEFAULT_COLORS.put(RecoveryDevice.class, "255,0,0");
\r