language selector, bug fixed
This commit is contained in:
parent
27caf60161
commit
244e792453
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
||||
2011-07-21 Sampo Niskanen
|
||||
|
||||
* [BUG] Converting triangular fin to freeform
|
||||
* [BUG] Unit conversions in printout
|
||||
* [BUG] Mass computations in printout
|
||||
* [BUG] "Not a drop" exception in ComponentTreeTransferHandler
|
||||
* [BUG] Plot annotation positioned wrong
|
||||
* [BUG] Exception when writing PDF failed
|
||||
* Language selector in preferences
|
||||
|
||||
2011-07-18 Sampo Niskanen
|
||||
|
||||
* Select motor type based on known manufacturers
|
||||
|
||||
@ -6,7 +6,11 @@
|
||||
#
|
||||
# className.ComponentType.componentName
|
||||
#
|
||||
|
||||
#
|
||||
# Text tokens within braces should not be translated, e.g.
|
||||
# "The file '{filename}' exists."
|
||||
# They are pieces that are inserted dynamically.
|
||||
#
|
||||
|
||||
|
||||
! Set to the name of the current translation file (used for debugging purposes)
|
||||
@ -65,6 +69,15 @@ BasicFrame.WarningDialog.txt1 = The following problems were encountered while op
|
||||
BasicFrame.WarningDialog.txt2 = Some design features may not have been loaded correctly.
|
||||
BasicFrame.WarningDialog.title = Warnings while opening file
|
||||
|
||||
|
||||
! General error messages used in multiple contexts
|
||||
error.fileExists.title = File exists
|
||||
error.fileExists.desc = File '{filename}' exists. Do you want to overwrite it?
|
||||
|
||||
error.writing.title = Error writing file
|
||||
error.writing.desc = An error occurred while writing to the file:
|
||||
|
||||
|
||||
! Labels used in buttons of dialog windows
|
||||
button.ok = OK
|
||||
button.cancel = Cancel
|
||||
@ -105,6 +118,7 @@ PrintDialog.error.preview.title = Unable to open preview
|
||||
PrintDialog.error.preview.desc1 = Unable to open PDF preview.
|
||||
PrintDialog.error.preview.desc2 = Please use the "Save as PDF" option instead.
|
||||
|
||||
|
||||
!PrintSettingsDialog
|
||||
PrintSettingsDialog.title = Print settings
|
||||
PrintSettingsDialog.lbl.Templatefillcolor = Template fill color:
|
||||
@ -130,6 +144,8 @@ bugreport.dlg.failedmsg2 = Please send the report manually to
|
||||
bugreport.dlg.failedmsg3 = Error sending report
|
||||
bugreport.reportDialog.txt = <html><b>You can report a bug in OpenRocket by filling in and submitting the form below.</b><br>You can also report bugs and include attachments on the project web site.
|
||||
bugreport.reportDialog.txt2 = <html><b>Please include a short description about what you were doing when the exception occurred.</b>
|
||||
bugreport.dlg.provideDescription = Please provide a description of the bug first.
|
||||
bugreport.dlg.provideDescription.title = Bug description missing
|
||||
|
||||
|
||||
! Debug log dialog
|
||||
@ -186,7 +202,7 @@ matedtpan.but.ttip.delete = Delete a user-defined material
|
||||
matedtpan.but.ttip.revertall = Delete all user-defined materials
|
||||
matedtpan.title.Deletealluser-defined = Delete all user-defined materials?
|
||||
matedtpan.title.Revertall = Revert all?
|
||||
matedtpan.lbl.edtmaterials = <html><i>Editing materials will not affect existing rocket designs.</i>
|
||||
matedtpan.lbl.edtmaterials = Editing materials will not affect existing rocket designs.
|
||||
|
||||
!MaterialModel
|
||||
MaterialModel.title.Material = Material
|
||||
@ -221,7 +237,7 @@ pref.dlg.lbl.Linedensity = Line density:
|
||||
pref.dlg.lbl.Motordimensions = Motor dimensions:
|
||||
pref.dlg.lbl.Surfacedensity = Surface density:
|
||||
pref.dlg.lbl.Distance = Distance:
|
||||
pref.dlg.lbl.Bulkdensity = Bulk density::
|
||||
pref.dlg.lbl.Bulkdensity = Bulk density:
|
||||
pref.dlg.lbl.Velocity = Velocity:
|
||||
pref.dlg.lbl.Surfaceroughness = Surface roughness:
|
||||
pref.dlg.lbl.Acceleration = Acceleration:
|
||||
@ -235,6 +251,7 @@ pref.dlg.lbl.Temperature = Temperature:
|
||||
pref.dlg.lbl.Momentofinertia = Moment of inertia:
|
||||
pref.dlg.lbl.Pressure = Pressure:
|
||||
pref.dlg.lbl.Stability = Stability:
|
||||
pref.dlg.lbl.FlightTime = Flight time:
|
||||
pref.dlg.lbl.effect1 = The effects will take place the next time you open a window.
|
||||
pref.dlg.lbl.Checkingupdates = Checking for updates...
|
||||
pref.dlg.lbl.msg1 = An error occurred while communicating with the server.
|
||||
@ -249,6 +266,9 @@ pref.dlg.PrefBooleanSelector2 = Confirm
|
||||
pref.dlg.Add = Add
|
||||
pref.dlg.DescriptionArea.Adddirectories = Add directories, RASP motor files (*.eng), RockSim engine files (*.rse) or ZIP archives separated by a semicolon (;) to load external thrust curves. Changes will take effect the next time you start OpenRocket.
|
||||
|
||||
PreferencesDialog.lbl.language = Interface language:
|
||||
PreferencesDialog.languages.default = System default
|
||||
PreferencesDialog.lbl.languageEffect = The language will change the next time you start OpenRocket.
|
||||
|
||||
! Simulation edit dialog
|
||||
simedtdlg.but.runsimulation = Run simulation
|
||||
@ -1254,7 +1274,9 @@ ScaleDialog.lbl.scaleFromTo.ttip = Define the scaling based on an original and r
|
||||
ScaleDialog.checkbox.scaleMass = Update explicit mass values
|
||||
ScaleDialog.checkbox.scaleMass.ttip = Scale mass component and override mass values by the cube of the scaling factor
|
||||
ScaleDialog.button.scale = Scale
|
||||
|
||||
ScaleDialog.undo.scaleRocket = Scale rocket
|
||||
ScaleDialog.undo.scaleComponent = Scale component
|
||||
ScaleDialog.undo.scaleComponents = Scale components
|
||||
|
||||
!icons
|
||||
Icons.Undo = Undo
|
||||
|
||||
@ -191,7 +191,7 @@ matedtpan.but.ttip.delete = Benutzerdefiniertes Material l
|
||||
matedtpan.but.ttip.revertall = Alle benutzerdefinierten Materialien löschen
|
||||
matedtpan.title.Deletealluser-defined = Alle benutzerdefinierten Materialien löschen?
|
||||
matedtpan.title.Revertall = Alle löschen?
|
||||
matedtpan.lbl.edtmaterials = <html><i>Das Bearbeiten der Materialien beeinflusst keine bereits existierenden Raketendesigns.</i>
|
||||
matedtpan.lbl.edtmaterials = Das Bearbeiten der Materialien beeinflusst keine bereits existierenden Raketendesigns.
|
||||
|
||||
!MaterialModel
|
||||
MaterialModel.title.Material = Material
|
||||
|
||||
@ -195,7 +195,7 @@ matedtpan.but.ttip.delete = Borrar un material pre definido
|
||||
matedtpan.but.ttip.revertall = Borrar todos los materiales predefinidos
|
||||
matedtpan.title.Deletealluser-defined = ¿Borrar todos los materiales predefinidos?
|
||||
matedtpan.title.Revertall = ¿Revertir todo?
|
||||
matedtpan.lbl.edtmaterials = <html><i>Editar materiales que no afectaran los diseños existentes.</i>
|
||||
matedtpan.lbl.edtmaterials = Editar materiales que no afectaran los diseños existentes.
|
||||
|
||||
!MaterialModel
|
||||
MaterialModel.title.Material = Material
|
||||
|
||||
@ -186,7 +186,7 @@ matedtpan.but.ttip.delete = Supprimer un mat
|
||||
matedtpan.but.ttip.revertall = Supprimer tous les matériaux personnalisés
|
||||
matedtpan.title.Deletealluser-defined = Effacer tous les matériaux personalisés?
|
||||
matedtpan.title.Revertall = Revenir aux valeurs précédentes?
|
||||
matedtpan.lbl.edtmaterials = <html><i>Modifier les matériaux n'affectera pas les projets fusée existants.</i>
|
||||
matedtpan.lbl.edtmaterials = Modifier les matériaux n'affectera pas les projets fusée existants.
|
||||
|
||||
!MaterialModel
|
||||
MaterialModel.title.Material = Matériau
|
||||
|
||||
BIN
pix-src/icons/edit-scale.xcf.gz
Normal file
BIN
pix-src/icons/edit-scale.xcf.gz
Normal file
Binary file not shown.
@ -20,6 +20,7 @@ edit-delete.png
|
||||
edit-paste.png
|
||||
edit-redo.png
|
||||
edit-undo.png
|
||||
edit-scale.png (modified from edit-copy.png)
|
||||
|
||||
|
||||
From the "Crystal" project:
|
||||
|
||||
BIN
pix/icons/edit-scale.png
Normal file
BIN
pix/icons/edit-scale.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 636 B |
@ -254,7 +254,12 @@ public class Simulation implements ChangeSource, Cloneable {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simulate the flight.
|
||||
*
|
||||
* @param additionalListeners additional simulation listeners (those defined by the simulation are used in any case)
|
||||
* @throws SimulationException if a problem occurs during simulation
|
||||
*/
|
||||
public void simulate(SimulationListener... additionalListeners)
|
||||
throws SimulationException {
|
||||
mutex.lock("simulate");
|
||||
|
||||
@ -11,12 +11,12 @@ import java.util.List;
|
||||
|
||||
import net.sf.openrocket.file.iterator.DirectoryIterator;
|
||||
import net.sf.openrocket.file.iterator.FileIterator;
|
||||
import net.sf.openrocket.gui.main.SimpleFileFilter;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.motor.ThrustCurveMotor;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.Pair;
|
||||
import net.sf.openrocket.util.SimpleFileFilter;
|
||||
|
||||
public final class MotorLoaderHelper {
|
||||
|
||||
|
||||
@ -33,12 +33,10 @@ public class RockSimMotorLoader extends AbstractMotorLoader {
|
||||
public static final Charset CHARSET = Charset.forName(CHARSET_NAME);
|
||||
|
||||
|
||||
/** Any delay longed than this will be interpreted as a plugged motor. */
|
||||
/** Any delay longer than this will be interpreted as a plugged motor. */
|
||||
private static final int DELAY_LIMIT = 90;
|
||||
|
||||
|
||||
// FIXME: Obtain default motor type from manufacturer info
|
||||
|
||||
|
||||
@Override
|
||||
protected Charset getDefaultCharset() {
|
||||
|
||||
@ -43,9 +43,9 @@ public class BugReportDialog extends JDialog {
|
||||
|
||||
private static final String REPORT_EMAIL = "openrocket-bugs@lists.sourceforge.net";
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
|
||||
public BugReportDialog(Window parent, String labelText, String message) {
|
||||
|
||||
public BugReportDialog(Window parent, String labelText, final String message, final boolean sendIfUnchanged) {
|
||||
//// Bug report
|
||||
super(parent, trans.get("bugreport.dlg.title"), Dialog.ModalityType.APPLICATION_MODAL);
|
||||
|
||||
@ -67,7 +67,7 @@ public class BugReportDialog extends JDialog {
|
||||
panel.add(label, "gapleft para, wrap");
|
||||
|
||||
//// Otherwise, send the text below to the address:
|
||||
panel.add(new JLabel(trans.get("bugreport.dlg.otherwise") +" "),
|
||||
panel.add(new JLabel(trans.get("bugreport.dlg.otherwise") + " "),
|
||||
"gapleft para, split 2, gapright rel");
|
||||
panel.add(new SelectableLabel(REPORT_EMAIL), "growx, wrap para");
|
||||
|
||||
@ -115,6 +115,13 @@ public class BugReportDialog extends JDialog {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String text = textArea.getText();
|
||||
if (text.equals(message) && !sendIfUnchanged) {
|
||||
JOptionPane.showMessageDialog(BugReportDialog.this,
|
||||
trans.get("bugreport.dlg.provideDescription"),
|
||||
trans.get("bugreport.dlg.provideDescription.title"), JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
BugReporter.sendBugReport(text);
|
||||
@ -127,7 +134,7 @@ public class BugReportDialog extends JDialog {
|
||||
"Bug report sent", JOptionPane.INFORMATION_MESSAGE);*/
|
||||
JOptionPane.showMessageDialog(BugReportDialog.this,
|
||||
new Object[] { trans.get("bugreport.dlg.successmsg1"),
|
||||
trans.get("bugreport.dlg.successmsg2") },
|
||||
trans.get("bugreport.dlg.successmsg2") },
|
||||
trans.get("bugreport.dlg.successmsg3"), JOptionPane.INFORMATION_MESSAGE);
|
||||
|
||||
} catch (Exception ex) {
|
||||
@ -137,9 +144,9 @@ public class BugReportDialog extends JDialog {
|
||||
new Object[] { trans.get("bugreport.dlg.failedmsg1"),
|
||||
ex.getClass().getSimpleName() + ": " + ex.getMessage(), " ",
|
||||
//// Please send the report manually to
|
||||
trans.get("bugreport.dlg.failedmsg2") +" " + REPORT_EMAIL },
|
||||
trans.get("bugreport.dlg.failedmsg2") + " " + REPORT_EMAIL },
|
||||
//// Error sending report
|
||||
trans.get("bugreport.dlg.failedmsg3"), JOptionPane.ERROR_MESSAGE);
|
||||
trans.get("bugreport.dlg.failedmsg3"), JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -197,10 +204,8 @@ public class BugReportDialog extends JDialog {
|
||||
sb.append("---------- End of bug report ----------\n");
|
||||
sb.append('\n');
|
||||
|
||||
BugReportDialog reportDialog =
|
||||
new BugReportDialog(parent,
|
||||
//// <html><b>You can report a bug in OpenRocket by filling in and submitting the form below.</b><br>You can also report bugs and include attachments on the project web site.
|
||||
trans.get("bugreport.reportDialog.txt"), sb.toString());
|
||||
BugReportDialog reportDialog = new BugReportDialog(parent,
|
||||
trans.get("bugreport.reportDialog.txt"), sb.toString(), false);
|
||||
reportDialog.setVisible(true);
|
||||
}
|
||||
|
||||
@ -258,8 +263,8 @@ public class BugReportDialog extends JDialog {
|
||||
sb.append('\n');
|
||||
|
||||
BugReportDialog reportDialog =
|
||||
//// <html><b>Please include a short description about what you were doing when the exception occurred.</b>
|
||||
new BugReportDialog(parent, trans.get("bugreport.reportDialog.txt2"), sb.toString());
|
||||
//// <html><b>Please include a short description about what you were doing when the exception occurred.</b>
|
||||
new BugReportDialog(parent, trans.get("bugreport.reportDialog.txt2"), sb.toString(), true);
|
||||
reportDialog.setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
@ -23,13 +23,11 @@ import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.gui.main.ExceptionHandler;
|
||||
import net.sf.openrocket.gui.print.PrintController;
|
||||
import net.sf.openrocket.gui.print.PrintSettings;
|
||||
import net.sf.openrocket.gui.print.PrintableContext;
|
||||
@ -40,6 +38,7 @@ import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.FileHelper;
|
||||
import net.sf.openrocket.util.GUIUtil;
|
||||
import net.sf.openrocket.util.Prefs;
|
||||
|
||||
@ -48,9 +47,6 @@ import net.sf.openrocket.util.Prefs;
|
||||
*/
|
||||
public class PrintDialog extends JDialog implements TreeSelectionListener {
|
||||
|
||||
// FIXME: Printouts use SI units even when imperial are selected
|
||||
// FIXME: Array out of bounds exception when printing
|
||||
|
||||
private static final LogHelper log = Application.getLogger();
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
@ -322,40 +318,37 @@ public class PrintDialog extends JDialog implements TreeSelectionListener {
|
||||
private boolean onSavePDF() {
|
||||
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
// Note: source for ExampleFileFilter can be found in FileChooserDemo,
|
||||
// under the demo/jfc directory in the Java 2 SDK, Standard Edition.
|
||||
FileFilter filter = new FileFilter() {
|
||||
|
||||
//Accept all directories and all pdf files.
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
if (f.isDirectory())
|
||||
return true;
|
||||
return f.getName().toLowerCase().endsWith(".pdf");
|
||||
}
|
||||
|
||||
//The description of this filter
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return trans.get("filetypes.pdf");
|
||||
}
|
||||
};
|
||||
chooser.setFileFilter(filter);
|
||||
chooser.setFileFilter(FileHelper.PDF_FILTER);
|
||||
|
||||
// Select initial directory
|
||||
File dir = document.getFile();
|
||||
if (dir != null) {
|
||||
dir = dir.getParentFile();
|
||||
}
|
||||
if (dir == null) {
|
||||
dir = Prefs.getDefaultDirectory();
|
||||
}
|
||||
chooser.setCurrentDirectory(dir);
|
||||
|
||||
int returnVal = chooser.showSaveDialog(this);
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
File file = chooser.getSelectedFile();
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION && file != null) {
|
||||
|
||||
file = FileHelper.ensureExtension(file, "pdf");
|
||||
if (!FileHelper.confirmWrite(file, this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
String fname = chooser.getSelectedFile().getCanonicalPath();
|
||||
if (!getExtension(fname).equals("pdf")) {
|
||||
fname = fname + ".pdf";
|
||||
}
|
||||
File f = new File(fname);
|
||||
|
||||
PrintSettings settings = Prefs.getPrintSettings();
|
||||
// TODO: HIGH: Remove UIManager, and pass settings to the actual printing methods
|
||||
TemplateProperties.setColors(settings);
|
||||
generateReport(f, settings);
|
||||
generateReport(file, settings);
|
||||
|
||||
} catch (IOException e) {
|
||||
ExceptionHandler.handleErrorCondition(e);
|
||||
FileHelper.errorWriting(e, this);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
@ -363,16 +356,4 @@ public class PrintDialog extends JDialog implements TreeSelectionListener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extension of a file.
|
||||
*/
|
||||
private static String getExtension(String s) {
|
||||
String ext = null;
|
||||
int i = s.lastIndexOf('.');
|
||||
|
||||
if (i > 0 && i < s.length() - 1) {
|
||||
ext = s.substring(i + 1).toLowerCase();
|
||||
}
|
||||
return ext != null ? ext : "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,8 +206,6 @@ public class ScaleDialog extends JDialog {
|
||||
|
||||
private boolean changing = false;
|
||||
|
||||
// FIXME: Localize
|
||||
|
||||
/**
|
||||
* Sole constructor.
|
||||
*
|
||||
@ -430,7 +428,7 @@ public class ScaleDialog extends JDialog {
|
||||
|
||||
// Scale the entire rocket design
|
||||
try {
|
||||
document.startUndo("Scale rocket");
|
||||
document.startUndo(trans.get("undo.scaleRocket"));
|
||||
for (RocketComponent c : document.getRocket()) {
|
||||
scale(c, mul, scaleMass);
|
||||
}
|
||||
@ -442,7 +440,7 @@ public class ScaleDialog extends JDialog {
|
||||
|
||||
// Scale component and subcomponents
|
||||
try {
|
||||
document.startUndo("Scale components");
|
||||
document.startUndo(trans.get("undo.scaleComponents"));
|
||||
for (RocketComponent c : selection) {
|
||||
scale(c, mul, scaleMass);
|
||||
}
|
||||
@ -454,7 +452,7 @@ public class ScaleDialog extends JDialog {
|
||||
|
||||
// Scale only the selected component
|
||||
try {
|
||||
document.startUndo("Scale component");
|
||||
document.startUndo(trans.get("undo.scaleComponent"));
|
||||
scale(selection, mul, scaleMass);
|
||||
} finally {
|
||||
document.stopUndo();
|
||||
|
||||
@ -24,6 +24,8 @@ import net.sf.openrocket.database.Database;
|
||||
import net.sf.openrocket.database.Databases;
|
||||
import net.sf.openrocket.gui.adaptors.Column;
|
||||
import net.sf.openrocket.gui.adaptors.ColumnTableModel;
|
||||
import net.sf.openrocket.gui.components.StyledLabel;
|
||||
import net.sf.openrocket.gui.components.StyledLabel.Style;
|
||||
import net.sf.openrocket.gui.dialogs.CustomMaterialDialog;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.material.Material;
|
||||
@ -32,7 +34,7 @@ import net.sf.openrocket.unit.UnitGroup;
|
||||
import net.sf.openrocket.unit.Value;
|
||||
|
||||
public class MaterialEditPanel extends JPanel {
|
||||
|
||||
|
||||
private final JTable table;
|
||||
|
||||
private final JButton addButton;
|
||||
@ -40,12 +42,12 @@ public class MaterialEditPanel extends JPanel {
|
||||
private final JButton deleteButton;
|
||||
private final JButton revertButton;
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
|
||||
|
||||
public MaterialEditPanel() {
|
||||
super(new MigLayout("fill"));
|
||||
|
||||
|
||||
|
||||
// TODO: LOW: Create sorter that keeps material types always in order
|
||||
final ColumnTableModel model = new ColumnTableModel(
|
||||
//// Material
|
||||
@ -61,6 +63,7 @@ public class MaterialEditPanel extends JPanel {
|
||||
public Object getValueAt(int row) {
|
||||
return getMaterial(row).getType().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultWidth() {
|
||||
return 15;
|
||||
@ -86,22 +89,24 @@ public class MaterialEditPanel extends JPanel {
|
||||
throw new IllegalStateException("Material type " + m.getType());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultWidth() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass() {
|
||||
return Value.class;
|
||||
}
|
||||
}
|
||||
) {
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return Databases.BULK_MATERIAL.size() + Databases.SURFACE_MATERIAL.size() +
|
||||
Databases.LINE_MATERIAL.size();
|
||||
}
|
||||
};
|
||||
) {
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return Databases.BULK_MATERIAL.size() + Databases.SURFACE_MATERIAL.size() +
|
||||
Databases.LINE_MATERIAL.size();
|
||||
}
|
||||
};
|
||||
|
||||
table = new JTable(model);
|
||||
model.setColumnWidths(table.getColumnModel());
|
||||
@ -109,7 +114,7 @@ public class MaterialEditPanel extends JPanel {
|
||||
table.setDefaultRenderer(Object.class, new MaterialCellRenderer());
|
||||
this.add(new JScrollPane(table), "w 200px, h 100px, grow 100");
|
||||
|
||||
|
||||
|
||||
//// New button
|
||||
addButton = new JButton(trans.get("matedtpan.but.new"));
|
||||
//// Add a new material
|
||||
@ -120,7 +125,7 @@ public class MaterialEditPanel extends JPanel {
|
||||
CustomMaterialDialog dialog = new CustomMaterialDialog(
|
||||
SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
|
||||
//// Add a custom material
|
||||
null, false, trans.get("matedtpan.title.Addcustmaterial"));
|
||||
null, false, trans.get("matedtpan.title.Addcustmaterial"));
|
||||
dialog.setVisible(true);
|
||||
if (dialog.getOkClicked()) {
|
||||
Material mat = dialog.getMaterial();
|
||||
@ -155,7 +160,7 @@ public class MaterialEditPanel extends JPanel {
|
||||
dialog = new CustomMaterialDialog(
|
||||
SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
|
||||
//// Add a custom material
|
||||
m, false, trans.get("matedtpan.title.Addcustmaterial"),
|
||||
m, false, trans.get("matedtpan.title.Addcustmaterial"),
|
||||
//// The built-in materials cannot be modified.
|
||||
trans.get("matedtpan.title2.Editmaterial"));
|
||||
}
|
||||
@ -196,7 +201,7 @@ public class MaterialEditPanel extends JPanel {
|
||||
});
|
||||
this.add(deleteButton, "gap rel rel para para, growx 1, top");
|
||||
|
||||
|
||||
|
||||
this.add(new JPanel(), "grow 1");
|
||||
|
||||
//// Revert all button
|
||||
@ -206,27 +211,27 @@ public class MaterialEditPanel extends JPanel {
|
||||
revertButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int sel = JOptionPane.showConfirmDialog(MaterialEditPanel.this,
|
||||
int sel = JOptionPane.showConfirmDialog(MaterialEditPanel.this,
|
||||
//// Delete all user-defined materials?
|
||||
trans.get("matedtpan.title.Deletealluser-defined"),
|
||||
trans.get("matedtpan.title.Deletealluser-defined"),
|
||||
//// Revert all?
|
||||
trans.get("matedtpan.title.Revertall"),
|
||||
trans.get("matedtpan.title.Revertall"),
|
||||
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||
if (sel == JOptionPane.YES_OPTION) {
|
||||
Iterator<Material> iterator;
|
||||
|
||||
|
||||
iterator = Databases.LINE_MATERIAL.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (iterator.next().isUserDefined())
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
|
||||
iterator = Databases.SURFACE_MATERIAL.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (iterator.next().isUserDefined())
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
|
||||
iterator = Databases.BULK_MATERIAL.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (iterator.next().isUserDefined())
|
||||
@ -237,7 +242,7 @@ public class MaterialEditPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
});
|
||||
this.add(revertButton, "gap rel rel para para, growx 1, bottom, wrap");
|
||||
this.add(revertButton, "gap rel rel para para, growx 1, bottom, wrap unrel");
|
||||
|
||||
setButtonStates();
|
||||
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@ -257,9 +262,9 @@ public class MaterialEditPanel extends JPanel {
|
||||
|
||||
//// <html><i>Editing materials will not affect existing
|
||||
//// rocket designs.</i>
|
||||
this.add(new JLabel(trans.get("matedtpan.lbl.edtmaterials")), "span");
|
||||
|
||||
this.add(new StyledLabel(trans.get("matedtpan.lbl.edtmaterials"), -2, Style.ITALIC), "span");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -273,9 +278,9 @@ public class MaterialEditPanel extends JPanel {
|
||||
|
||||
case LINE:
|
||||
return Databases.LINE_MATERIAL;
|
||||
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Material type invalid, m="+m);
|
||||
throw new IllegalArgumentException("Material type invalid, m=" + m);
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,18 +301,18 @@ public class MaterialEditPanel extends JPanel {
|
||||
} else {
|
||||
deleteButton.setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
// Revert button enabled if any user-defined material exists
|
||||
boolean found = false;
|
||||
|
||||
for (Material m: Databases.BULK_MATERIAL) {
|
||||
for (Material m : Databases.BULK_MATERIAL) {
|
||||
if (m.isUserDefined()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
for (Material m: Databases.SURFACE_MATERIAL) {
|
||||
for (Material m : Databases.SURFACE_MATERIAL) {
|
||||
if (m.isUserDefined()) {
|
||||
found = true;
|
||||
break;
|
||||
@ -315,7 +320,7 @@ public class MaterialEditPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
for (Material m: Databases.LINE_MATERIAL) {
|
||||
for (Material m : Databases.LINE_MATERIAL) {
|
||||
if (m.isUserDefined()) {
|
||||
found = true;
|
||||
break;
|
||||
@ -346,25 +351,25 @@ public class MaterialEditPanel extends JPanel {
|
||||
if (row < n) {
|
||||
return Databases.LINE_MATERIAL.get(row);
|
||||
}
|
||||
throw new IndexOutOfBoundsException("row="+origRow+" while material count" +
|
||||
" bulk:" + Databases.BULK_MATERIAL.size() +
|
||||
throw new IndexOutOfBoundsException("row=" + origRow + " while material count" +
|
||||
" bulk:" + Databases.BULK_MATERIAL.size() +
|
||||
" surface:" + Databases.SURFACE_MATERIAL.size() +
|
||||
" line:" + Databases.LINE_MATERIAL.size());
|
||||
}
|
||||
|
||||
|
||||
private class MaterialCellRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
|
||||
*/
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
Component c = super.getTableCellRendererComponent(table, value, isSelected,
|
||||
Component c = super.getTableCellRendererComponent(table, value, isSelected,
|
||||
hasFocus, row, column);
|
||||
if (c instanceof JLabel) {
|
||||
JLabel label = (JLabel)c;
|
||||
JLabel label = (JLabel) c;
|
||||
Material m = getMaterial(row);
|
||||
|
||||
if (isSelected) {
|
||||
@ -383,5 +388,5 @@ public class MaterialEditPanel extends JPanel {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -8,7 +8,9 @@ import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.swing.AbstractListModel;
|
||||
import javax.swing.ComboBoxModel;
|
||||
@ -32,15 +34,19 @@ import net.sf.openrocket.communication.UpdateInfo;
|
||||
import net.sf.openrocket.communication.UpdateInfoRetriever;
|
||||
import net.sf.openrocket.gui.components.DescriptionArea;
|
||||
import net.sf.openrocket.gui.components.StyledLabel;
|
||||
import net.sf.openrocket.gui.components.StyledLabel.Style;
|
||||
import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
|
||||
import net.sf.openrocket.gui.main.SimpleFileFilter;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.unit.Unit;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
import net.sf.openrocket.util.GUIUtil;
|
||||
import net.sf.openrocket.util.Named;
|
||||
import net.sf.openrocket.util.Prefs;
|
||||
import net.sf.openrocket.util.SimpleFileFilter;
|
||||
import net.sf.openrocket.util.Utils;
|
||||
|
||||
|
||||
public class PreferencesDialog extends JDialog {
|
||||
private static final LogHelper log = Application.getLogger();
|
||||
@ -49,10 +55,10 @@ public class PreferencesDialog extends JDialog {
|
||||
|
||||
private File defaultDirectory = null;
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
private PreferencesDialog() {
|
||||
|
||||
private PreferencesDialog(Window parent) {
|
||||
//// Preferences
|
||||
super((Window) null, trans.get("pref.dlg.title.Preferences"), Dialog.ModalityType.APPLICATION_MODAL);
|
||||
super(parent, trans.get("pref.dlg.title.Preferences"), Dialog.ModalityType.APPLICATION_MODAL);
|
||||
|
||||
JPanel panel = new JPanel(new MigLayout("fill, gap unrel", "[grow]", "[grow][]"));
|
||||
|
||||
@ -60,13 +66,13 @@ public class PreferencesDialog extends JDialog {
|
||||
panel.add(tabbedPane, "grow, wrap");
|
||||
|
||||
//// Units and Default units
|
||||
tabbedPane.addTab(trans.get("pref.dlg.tab.Units"), null, unitsPane(),
|
||||
tabbedPane.addTab(trans.get("pref.dlg.tab.Units"), null, unitsPane(),
|
||||
trans.get("pref.dlg.tab.Defaultunits"));
|
||||
//// Materials and Custom materials
|
||||
tabbedPane.addTab(trans.get("pref.dlg.tab.Materials"), null, new MaterialEditPanel(),
|
||||
trans.get("pref.dlg.tab.Custommaterials"));
|
||||
//// Options and Miscellaneous options
|
||||
tabbedPane.addTab(trans.get("pref.dlg.tab.Options"), null, optionsPane(),
|
||||
tabbedPane.addTab(trans.get("pref.dlg.tab.Options"), null, optionsPane(),
|
||||
trans.get("pref.dlg.tab.Miscellaneousoptions"));
|
||||
|
||||
//// Close button
|
||||
@ -98,14 +104,44 @@ public class PreferencesDialog extends JDialog {
|
||||
private JPanel optionsPane() {
|
||||
JPanel panel = new JPanel(new MigLayout("fillx, ins 30lp n n n"));
|
||||
|
||||
|
||||
//// Language selector
|
||||
Locale userLocale = Prefs.getUserLocale();
|
||||
List<Named<Locale>> locales = new ArrayList<Named<Locale>>();
|
||||
for (Locale l : Prefs.getSupportedLocales()) {
|
||||
locales.add(new Named<Locale>(l, l.getDisplayLanguage()));
|
||||
}
|
||||
Collections.sort(locales);
|
||||
locales.add(0, new Named<Locale>(null, trans.get("languages.default")));
|
||||
|
||||
final JComboBox languageCombo = new JComboBox(locales.toArray());
|
||||
for (int i = 0; i < locales.size(); i++) {
|
||||
if (Utils.equals(userLocale, locales.get(i).get())) {
|
||||
languageCombo.setSelectedIndex(i);
|
||||
}
|
||||
}
|
||||
languageCombo.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Named<Locale> selection = (Named<Locale>) languageCombo.getSelectedItem();
|
||||
Prefs.setUserLocale(selection.get());
|
||||
}
|
||||
});
|
||||
panel.add(new JLabel(trans.get("lbl.language")), "gapright para");
|
||||
panel.add(languageCombo, "wrap rel, growx, sg combos");
|
||||
|
||||
panel.add(new StyledLabel(trans.get("PreferencesDialog.lbl.languageEffect"), -3, Style.ITALIC), "span, wrap para*2");
|
||||
|
||||
|
||||
//// Position to insert new body components:
|
||||
panel.add(new JLabel(trans.get("pref.dlg.lbl.Positiontoinsert")), "gapright para");
|
||||
panel.add(new JComboBox(new PrefChoiseSelector(Prefs.BODY_COMPONENT_INSERT_POSITION_KEY,
|
||||
//// Always ask
|
||||
//// Insert in middle
|
||||
//// Add to end
|
||||
trans.get("pref.dlg.PrefChoiseSelector1"),
|
||||
trans.get("pref.dlg.PrefChoiseSelector2"),
|
||||
trans.get("pref.dlg.PrefChoiseSelector1"),
|
||||
trans.get("pref.dlg.PrefChoiseSelector2"),
|
||||
trans.get("pref.dlg.PrefChoiseSelector3"))), "wrap para, growx, sg combos");
|
||||
|
||||
//// Confirm deletion of simulations:
|
||||
@ -113,7 +149,7 @@ public class PreferencesDialog extends JDialog {
|
||||
panel.add(new JComboBox(new PrefBooleanSelector(Prefs.CONFIRM_DELETE_SIMULATION,
|
||||
//// Delete
|
||||
//// Confirm
|
||||
trans.get("pref.dlg.PrefBooleanSelector1"),
|
||||
trans.get("pref.dlg.PrefBooleanSelector1"),
|
||||
trans.get("pref.dlg.PrefBooleanSelector2"), true)), "wrap 40lp, growx, sg combos");
|
||||
|
||||
//// User-defined thrust curves:
|
||||
@ -164,11 +200,11 @@ public class PreferencesDialog extends JDialog {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
SimpleFileFilter filter =
|
||||
new SimpleFileFilter(
|
||||
//// All thrust curve files (*.eng; *.rse; *.zip; directories)
|
||||
trans.get("pref.dlg.Allthrustcurvefiles"),
|
||||
true, "eng", "rse", "zip");
|
||||
SimpleFileFilter filter =
|
||||
new SimpleFileFilter(
|
||||
//// All thrust curve files (*.eng; *.rse; *.zip; directories)
|
||||
trans.get("pref.dlg.Allthrustcurvefiles"),
|
||||
true, "eng", "rse", "zip");
|
||||
chooser.addChoosableFileFilter(filter);
|
||||
//// RASP motor files (*.eng)
|
||||
chooser.addChoosableFileFilter(new SimpleFileFilter(trans.get("pref.dlg.RASPfiles"),
|
||||
@ -222,8 +258,8 @@ public class PreferencesDialog extends JDialog {
|
||||
|
||||
|
||||
//// Check for software updates at startup
|
||||
final JCheckBox softwareUpdateBox =
|
||||
new JCheckBox(trans.get("pref.dlg.checkbox.Checkupdates"));
|
||||
final JCheckBox softwareUpdateBox =
|
||||
new JCheckBox(trans.get("pref.dlg.checkbox.Checkupdates"));
|
||||
softwareUpdateBox.setSelected(Prefs.getCheckUpdates());
|
||||
softwareUpdateBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
@ -355,6 +391,7 @@ public class PreferencesDialog extends JDialog {
|
||||
combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_PRESSURE));
|
||||
panel.add(combo, "sizegroup boxes, wrap");
|
||||
|
||||
|
||||
//// Stability:
|
||||
panel.add(new JLabel(trans.get("pref.dlg.lbl.Stability")));
|
||||
combo = new JComboBox(new DefaultUnitSelector(UnitGroup.UNITS_STABILITY));
|
||||
@ -388,7 +425,7 @@ public class PreferencesDialog extends JDialog {
|
||||
|
||||
//// The effects will take place the next time you open a window.
|
||||
panel.add(new StyledLabel(
|
||||
trans.get("pref.dlg.lbl.effect1"), -2),
|
||||
trans.get("pref.dlg.lbl.effect1"), -2, Style.ITALIC),
|
||||
"spanx, wrap");
|
||||
|
||||
|
||||
@ -636,11 +673,11 @@ public class PreferencesDialog extends JDialog {
|
||||
|
||||
private static PreferencesDialog dialog = null;
|
||||
|
||||
public static void showPreferences() {
|
||||
public static void showPreferences(Window parent) {
|
||||
if (dialog != null) {
|
||||
dialog.dispose();
|
||||
}
|
||||
dialog = new PreferencesDialog();
|
||||
dialog = new PreferencesDialog(parent);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,6 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.tree.DefaultTreeSelectionModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
@ -92,6 +91,7 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.rocketcomponent.Stage;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.BugException;
|
||||
import net.sf.openrocket.util.FileHelper;
|
||||
import net.sf.openrocket.util.GUIUtil;
|
||||
import net.sf.openrocket.util.Icons;
|
||||
import net.sf.openrocket.util.MemoryManagement;
|
||||
@ -114,23 +114,6 @@ public class BasicFrame extends JFrame {
|
||||
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
// FileFilters for different types of rocket design files
|
||||
private static final FileFilter ALL_DESIGNS_FILTER =
|
||||
//// All rocket designs (*.ork; *.rkt)
|
||||
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter1"),
|
||||
".ork", ".ork.gz", ".rkt", ".rkt.gz");
|
||||
|
||||
private static final FileFilter OPENROCKET_DESIGN_FILTER =
|
||||
//// OpenRocket designs (*.ork)
|
||||
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter2"), ".ork", ".ork.gz");
|
||||
|
||||
private static final FileFilter ROCKSIM_DESIGN_FILTER =
|
||||
//// RockSim designs (*.rkt)
|
||||
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter3"), ".rkt", ".rkt.gz");
|
||||
|
||||
|
||||
|
||||
|
||||
public static final int COMPONENT_TAB = 0;
|
||||
public static final int SIMULATION_TAB = 1;
|
||||
|
||||
@ -612,9 +595,7 @@ public class BasicFrame extends JFrame {
|
||||
|
||||
|
||||
item = new JMenuItem(trans.get("main.menu.edit.resize"));
|
||||
// FIXME: Icon
|
||||
//item.setIcon(Icons.PREFERENCES);
|
||||
//// Setup the application preferences
|
||||
item.setIcon(Icons.EDIT_SCALE);
|
||||
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.resize.desc"));
|
||||
item.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
@ -638,7 +619,7 @@ public class BasicFrame extends JFrame {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
log.user("Preferences selected");
|
||||
PreferencesDialog.showPreferences();
|
||||
PreferencesDialog.showPreferences(BasicFrame.this);
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
@ -1007,10 +988,10 @@ public class BasicFrame extends JFrame {
|
||||
private void openAction() {
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
|
||||
chooser.addChoosableFileFilter(ALL_DESIGNS_FILTER);
|
||||
chooser.addChoosableFileFilter(OPENROCKET_DESIGN_FILTER);
|
||||
chooser.addChoosableFileFilter(ROCKSIM_DESIGN_FILTER);
|
||||
chooser.setFileFilter(ALL_DESIGNS_FILTER);
|
||||
chooser.addChoosableFileFilter(FileHelper.ALL_DESIGNS_FILTER);
|
||||
chooser.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
|
||||
chooser.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
|
||||
chooser.setFileFilter(FileHelper.ALL_DESIGNS_FILTER);
|
||||
|
||||
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
chooser.setMultiSelectionEnabled(true);
|
||||
@ -1234,7 +1215,7 @@ public class BasicFrame extends JFrame {
|
||||
log.info("Saving document to " + file);
|
||||
|
||||
// Saving RockSim designs is not supported
|
||||
if (ROCKSIM_DESIGN_FILTER.accept(file)) {
|
||||
if (FileHelper.ROCKSIM_DESIGN_FILTER.accept(file)) {
|
||||
file = new File(file.getAbsolutePath().replaceAll(".[rR][kK][tT](.[gG][zZ])?$",
|
||||
".ork"));
|
||||
|
||||
@ -1262,7 +1243,7 @@ public class BasicFrame extends JFrame {
|
||||
StorageOptionChooser storageChooser =
|
||||
new StorageOptionChooser(document, document.getDefaultStorageOptions());
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setFileFilter(OPENROCKET_DESIGN_FILTER);
|
||||
chooser.setFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
|
||||
chooser.setCurrentDirectory(Prefs.getDefaultDirectory());
|
||||
chooser.setAccessory(storageChooser);
|
||||
if (document.getFile() != null)
|
||||
@ -1283,22 +1264,9 @@ public class BasicFrame extends JFrame {
|
||||
Prefs.setDefaultDirectory(chooser.getCurrentDirectory());
|
||||
storageChooser.storeOptions(document.getDefaultStorageOptions());
|
||||
|
||||
if (file.getName().indexOf('.') < 0) {
|
||||
log.debug("File name does not contain extension, adding .ork");
|
||||
String name = file.getAbsolutePath();
|
||||
name = name + ".ork";
|
||||
file = new File(name);
|
||||
}
|
||||
|
||||
if (file.exists()) {
|
||||
log.info("File " + file + " exists, confirming overwrite from user");
|
||||
int result = JOptionPane.showConfirmDialog(this,
|
||||
"File '" + file.getName() + "' exists. Do you want to overwrite it?",
|
||||
"File exists", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||
if (result != JOptionPane.YES_OPTION) {
|
||||
log.user("User decided not to overwrite the file");
|
||||
return false;
|
||||
}
|
||||
file = FileHelper.ensureExtension(file, "ork");
|
||||
if (!FileHelper.confirmWrite(file, this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return saveAs(file);
|
||||
|
||||
@ -103,6 +103,12 @@ public class ComponentTreeTransferHandler extends TransferHandler {
|
||||
@Override
|
||||
public boolean importData(TransferHandler.TransferSupport support) {
|
||||
|
||||
// We currently only support drop, not paste
|
||||
if (!support.isDrop()) {
|
||||
log.warn("Import action is not a drop action");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sun JRE silently ignores any RuntimeExceptions in importData, yeech!
|
||||
try {
|
||||
|
||||
|
||||
@ -69,7 +69,7 @@ public class PlotDialog extends JDialog {
|
||||
|
||||
private static final float PLOT_STROKE_WIDTH = 1.5f;
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
|
||||
private static final Color DEFAULT_EVENT_COLOR = new Color(0, 0, 0);
|
||||
private static final Map<FlightEvent.Type, Color> EVENT_COLORS =
|
||||
new HashMap<FlightEvent.Type, Color>();
|
||||
@ -364,7 +364,7 @@ public class PlotDialog extends JDialog {
|
||||
}
|
||||
}
|
||||
|
||||
final double xcoord;
|
||||
double xcoord;
|
||||
if (a == 0) {
|
||||
xcoord = domain.get(tindex);
|
||||
} else {
|
||||
@ -375,15 +375,25 @@ public class PlotDialog extends JDialog {
|
||||
FlightDataType type = config.getType(index);
|
||||
List<Double> range = branch.get(type);
|
||||
|
||||
final double ycoord;
|
||||
// Image annotations are not supported on the right-side axis
|
||||
// TODO: LOW: Can this be achieved by JFreeChart?
|
||||
if (filled.getAxis(index) != SimulationPlotPanel.LEFT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double ycoord;
|
||||
if (a == 0) {
|
||||
ycoord = range.get(tindex);
|
||||
} else {
|
||||
ycoord = a * range.get(tindex) + (1 - a) * range.get(tindex + 1);
|
||||
}
|
||||
|
||||
// Convert units
|
||||
xcoord = config.getDomainAxisUnit().toUnit(xcoord);
|
||||
ycoord = config.getUnit(index).toUnit(ycoord);
|
||||
|
||||
XYImageAnnotation annotation =
|
||||
new XYImageAnnotation(xcoord, ycoord, image, RectangleAnchor.CENTER);
|
||||
new XYImageAnnotation(xcoord, ycoord, image, RectangleAnchor.CENTER);
|
||||
annotation.setToolTipText(event);
|
||||
plot.addAnnotation(annotation);
|
||||
}
|
||||
@ -448,7 +458,6 @@ public class PlotDialog extends JDialog {
|
||||
GUIUtil.setDisposableDialogOptions(this, button);
|
||||
}
|
||||
|
||||
|
||||
private String getLabel(FlightDataType type, Unit unit) {
|
||||
String name = type.getName();
|
||||
if (unit != null && !UnitGroup.UNITS_NONE.contains(unit) &&
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -12,38 +12,39 @@ import net.sf.openrocket.simulation.FlightData;
|
||||
* finished. The worker can be cancelled if necessary.
|
||||
*/
|
||||
public class PrintSimulationWorker {
|
||||
|
||||
public static FlightData doit (Simulation sim) {
|
||||
return new InnerPrintSimulationWorker(sim).doit();
|
||||
}
|
||||
|
||||
static class InnerPrintSimulationWorker extends SimulationWorker {
|
||||
|
||||
public InnerPrintSimulationWorker (Simulation sim) {
|
||||
super(sim);
|
||||
}
|
||||
|
||||
public FlightData doit() {
|
||||
return doInBackground();
|
||||
}
|
||||
@Override
|
||||
protected void simulationDone () {
|
||||
// Do nothing if cancelled
|
||||
if (isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
simulation.getSimulatedData();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called if the simulation is interrupted due to an exception.
|
||||
*
|
||||
* @param t the Throwable that caused the interruption
|
||||
*/
|
||||
@Override
|
||||
protected void simulationInterrupted (final Throwable t) {
|
||||
}
|
||||
}
|
||||
|
||||
public static FlightData doit(Simulation sim) {
|
||||
return new InnerPrintSimulationWorker(sim).doit();
|
||||
}
|
||||
|
||||
static class InnerPrintSimulationWorker extends SimulationWorker {
|
||||
|
||||
public InnerPrintSimulationWorker(Simulation sim) {
|
||||
super(sim);
|
||||
}
|
||||
|
||||
public FlightData doit() {
|
||||
return doInBackground();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void simulationDone() {
|
||||
// Do nothing if cancelled
|
||||
if (isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
simulation.getSimulatedData();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called if the simulation is interrupted due to an exception.
|
||||
*
|
||||
* @param t the Throwable that caused the interruption
|
||||
*/
|
||||
@Override
|
||||
protected void simulationInterrupted(final Throwable t) {
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/net/sf/openrocket/l10n/L10N.java
Normal file
57
src/net/sf/openrocket/l10n/L10N.java
Normal file
@ -0,0 +1,57 @@
|
||||
package net.sf.openrocket.l10n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Helper methods for localization needs.
|
||||
*
|
||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||
*/
|
||||
public final class L10N {
|
||||
|
||||
private L10N() {
|
||||
// Prevent instantiation
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace a text token by a replacement value.
|
||||
* <p>
|
||||
* A text token is a string portion that should be surrounded by
|
||||
* braces, "{text}".
|
||||
*
|
||||
* @param original the original string.
|
||||
* @param token the text token to replace.
|
||||
* @param replacement the replacement text.
|
||||
* @return the modified string.
|
||||
*/
|
||||
public static String replace(String original, String token, String replacement) {
|
||||
return Pattern.compile(token, Pattern.LITERAL).matcher(original).replaceAll(replacement);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a language code into a Locale.
|
||||
*
|
||||
* @param langcode the language code (<code>null</code> ok).
|
||||
* @return the corresponding locale (or <code>null</code> if the input was <code>null</code>)
|
||||
*/
|
||||
public static Locale toLocale(String langcode) {
|
||||
if (langcode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Locale l;
|
||||
String[] split = langcode.split("[_-]", 3);
|
||||
if (split.length == 1) {
|
||||
l = new Locale(split[0]);
|
||||
} else if (split.length == 2) {
|
||||
l = new Locale(split[0], split[1]);
|
||||
} else {
|
||||
l = new Locale(split[0], split[1], split[2]);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
@ -24,7 +24,7 @@ import net.sf.openrocket.util.Prefs;
|
||||
public class StabilityDomain implements SimulationDomain {
|
||||
|
||||
/*
|
||||
* FIXME: Should this rather inspect stability during flight
|
||||
* TODO: HIGH: Should this rather inspect stability during flight
|
||||
*/
|
||||
|
||||
private final double limit;
|
||||
|
||||
@ -7,70 +7,72 @@ import net.sf.openrocket.util.MathUtil;
|
||||
|
||||
public class EllipticalFinSet extends FinSet {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
public static final int POINTS = 21;
|
||||
|
||||
|
||||
private static final int POINTS = 31;
|
||||
|
||||
// Static positioning for the fin points
|
||||
private static final double[] POINT_X = new double[POINTS];
|
||||
private static final double[] POINT_Y = new double[POINTS];
|
||||
static {
|
||||
for (int i=0; i < POINTS; i++) {
|
||||
double a = Math.PI * (POINTS-1-i)/(POINTS-1);
|
||||
POINT_X[i] = (Math.cos(a)+1)/2;
|
||||
for (int i = 0; i < POINTS; i++) {
|
||||
double a = Math.PI * (POINTS - 1 - i) / (POINTS - 1);
|
||||
POINT_X[i] = (Math.cos(a) + 1) / 2;
|
||||
POINT_Y[i] = Math.sin(a);
|
||||
}
|
||||
POINT_X[0] = 0;
|
||||
POINT_Y[0] = 0;
|
||||
POINT_X[POINTS-1] = 1;
|
||||
POINT_Y[POINTS-1] = 0;
|
||||
POINT_X[POINTS - 1] = 1;
|
||||
POINT_Y[POINTS - 1] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private double height = 0.05;
|
||||
|
||||
|
||||
public EllipticalFinSet() {
|
||||
this.length = 0.05;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Coordinate[] getFinPoints() {
|
||||
double len = MathUtil.max(length, 0.0001);
|
||||
Coordinate[] points = new Coordinate[POINTS];
|
||||
for (int i=0; i < POINTS; i++) {
|
||||
points[i] = new Coordinate(POINT_X[i]*length, POINT_Y[i]*height);
|
||||
for (int i = 0; i < POINTS; i++) {
|
||||
points[i] = new Coordinate(POINT_X[i] * len, POINT_Y[i] * height);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getSpan() {
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getComponentName() {
|
||||
//// Elliptical fin set
|
||||
return trans.get("EllipticalFinSet.Ellipticalfinset");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
public void setHeight(double height) {
|
||||
if (MathUtil.equals(this.height, height))
|
||||
return;
|
||||
this.height = height;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setLength(double length) {
|
||||
if (MathUtil.equals(this.length, length))
|
||||
return;
|
||||
this.length = length;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -15,8 +15,6 @@ import net.sf.openrocket.util.Transformation;
|
||||
public abstract class FinSet extends ExternalComponent {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
// FIXME: converting triangular fins to freeform fails
|
||||
|
||||
/**
|
||||
* Maximum allowed cant of fins.
|
||||
*/
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
package net.sf.openrocket.rocketcomponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
|
||||
/**
|
||||
* A set of trapezoidal fins. The root and tip chords are perpendicular to the rocket
|
||||
@ -13,9 +17,9 @@ import net.sf.openrocket.util.Coordinate;
|
||||
|
||||
public class TrapezoidFinSet extends FinSet {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
public static final double MAX_SWEEP_ANGLE=(89*Math.PI/180.0);
|
||||
|
||||
|
||||
public static final double MAX_SWEEP_ANGLE = (89 * Math.PI / 180.0);
|
||||
|
||||
/*
|
||||
* sweep tipChord
|
||||
* | |___________
|
||||
@ -32,64 +36,67 @@ public class TrapezoidFinSet extends FinSet {
|
||||
private double tipChord = 0;
|
||||
private double height = 0;
|
||||
private double sweep = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
public TrapezoidFinSet() {
|
||||
this (3, 0.05, 0.05, 0.025, 0.05);
|
||||
this(3, 0.05, 0.05, 0.025, 0.05);
|
||||
}
|
||||
|
||||
|
||||
// TODO: HIGH: height=0 -> CP = NaN
|
||||
public TrapezoidFinSet(int fins, double rootChord, double tipChord, double sweep,
|
||||
double height) {
|
||||
super();
|
||||
|
||||
|
||||
this.setFinCount(fins);
|
||||
this.length = rootChord;
|
||||
this.tipChord = tipChord;
|
||||
this.sweep = sweep;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setFinShape(double rootChord, double tipChord, double sweep, double height,
|
||||
double thickness) {
|
||||
if (this.length==rootChord && this.tipChord==tipChord && this.sweep==sweep &&
|
||||
this.height==height && this.thickness==thickness)
|
||||
if (this.length == rootChord && this.tipChord == tipChord && this.sweep == sweep &&
|
||||
this.height == height && this.thickness == thickness)
|
||||
return;
|
||||
this.length=rootChord;
|
||||
this.tipChord=tipChord;
|
||||
this.sweep=sweep;
|
||||
this.height=height;
|
||||
this.thickness=thickness;
|
||||
this.length = rootChord;
|
||||
this.tipChord = tipChord;
|
||||
this.sweep = sweep;
|
||||
this.height = height;
|
||||
this.thickness = thickness;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public double getRootChord() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setRootChord(double r) {
|
||||
if (length == r)
|
||||
return;
|
||||
length = Math.max(r,0);
|
||||
length = Math.max(r, 0);
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
public double getTipChord() {
|
||||
return tipChord;
|
||||
}
|
||||
|
||||
public void setTipChord(double r) {
|
||||
if (tipChord == r)
|
||||
return;
|
||||
tipChord = Math.max(r,0);
|
||||
tipChord = Math.max(r, 0);
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the sweep length.
|
||||
*/
|
||||
public double getSweep() {
|
||||
return sweep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sweep length.
|
||||
*/
|
||||
@ -99,7 +106,7 @@ public class TrapezoidFinSet extends FinSet {
|
||||
sweep = r;
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the sweep angle. This is calculated from the true sweep and height, and is not
|
||||
* stored separetely.
|
||||
@ -107,13 +114,14 @@ public class TrapezoidFinSet extends FinSet {
|
||||
public double getSweepAngle() {
|
||||
if (height == 0) {
|
||||
if (sweep > 0)
|
||||
return Math.PI/2;
|
||||
return Math.PI / 2;
|
||||
if (sweep < 0)
|
||||
return -Math.PI/2;
|
||||
return -Math.PI / 2;
|
||||
return 0;
|
||||
}
|
||||
return Math.atan(sweep/height);
|
||||
return Math.atan(sweep / height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sweep by the sweep angle. The sweep is calculated and set by this method,
|
||||
* and the angle itself is not stored.
|
||||
@ -128,34 +136,37 @@ public class TrapezoidFinSet extends FinSet {
|
||||
return;
|
||||
setSweep(sweep);
|
||||
}
|
||||
|
||||
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(double r) {
|
||||
if (height == r)
|
||||
return;
|
||||
height = Math.max(r,0);
|
||||
height = Math.max(r, 0);
|
||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the geometry of a trapezoidal fin.
|
||||
*/
|
||||
@Override
|
||||
public Coordinate[] getFinPoints() {
|
||||
Coordinate[] c = new Coordinate[4];
|
||||
|
||||
c[0] = Coordinate.NUL;
|
||||
c[1] = new Coordinate(sweep,height);
|
||||
c[2] = new Coordinate(sweep+tipChord,height);
|
||||
c[3] = new Coordinate(length,0);
|
||||
|
||||
return c;
|
||||
List<Coordinate> list = new ArrayList<Coordinate>(4);
|
||||
|
||||
list.add(Coordinate.NUL);
|
||||
list.add(new Coordinate(sweep, height));
|
||||
if (tipChord > 0.0001) {
|
||||
list.add(new Coordinate(sweep + tipChord, height));
|
||||
}
|
||||
list.add(new Coordinate(MathUtil.max(length, 0.0001), 0));
|
||||
|
||||
return list.toArray(new Coordinate[list.size()]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the span of a trapezoidal fin.
|
||||
*/
|
||||
@ -163,12 +174,12 @@ public class TrapezoidFinSet extends FinSet {
|
||||
public double getSpan() {
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getComponentName() {
|
||||
//// Trapezoidal fin set
|
||||
return trans.get("TrapezoidFinSet.TrapezoidFinSet");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package net.sf.openrocket.simulation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
@ -445,8 +446,8 @@ public class GUISimulationConditions implements ChangeSource, Cloneable {
|
||||
conditions.setLaunchLatitude(getLaunchLatitude());
|
||||
|
||||
PinkNoiseWindModel windModel = new PinkNoiseWindModel();
|
||||
// FIXME: Random seed
|
||||
windModel.setSeed(1);
|
||||
// TODO: HIGH: Randomness source for simulation
|
||||
windModel.setSeed(new Random().nextInt());
|
||||
windModel.setAverage(getWindSpeedAverage());
|
||||
windModel.setStandardDeviation(getWindSpeedDeviation());
|
||||
conditions.setWindModel(windModel);
|
||||
|
||||
@ -50,8 +50,8 @@ public class RK4SimulationStepper extends AbstractSimulationStepper {
|
||||
private static final double MIN_TIME_STEP = 0.001;
|
||||
|
||||
|
||||
// FIXME: Random seed
|
||||
private final Random random = new Random(10);
|
||||
// TODO: HIGH: Randomness source from simulation
|
||||
private final Random random = new Random();
|
||||
|
||||
|
||||
|
||||
|
||||
@ -89,6 +89,10 @@ public final class Application {
|
||||
* @return a translator.
|
||||
*/
|
||||
public static Translator getTranslator() {
|
||||
if (baseTranslator instanceof DebugTranslator) {
|
||||
return baseTranslator;
|
||||
}
|
||||
|
||||
Translator t = baseTranslator;
|
||||
t = new ClassBasedTranslator(t, 1);
|
||||
t = new ExceptionSuppressingTranslator(t);
|
||||
|
||||
@ -25,9 +25,9 @@ import net.sf.openrocket.file.motor.MotorLoaderHelper;
|
||||
import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
|
||||
import net.sf.openrocket.gui.main.BasicFrame;
|
||||
import net.sf.openrocket.gui.main.ExceptionHandler;
|
||||
import net.sf.openrocket.gui.main.SimpleFileFilter;
|
||||
import net.sf.openrocket.gui.main.Splash;
|
||||
import net.sf.openrocket.l10n.DebugTranslator;
|
||||
import net.sf.openrocket.l10n.L10N;
|
||||
import net.sf.openrocket.l10n.ResourceBundleTranslator;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.logging.DelegatorLogger;
|
||||
@ -39,6 +39,7 @@ import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.motor.ThrustCurveMotor;
|
||||
import net.sf.openrocket.util.GUIUtil;
|
||||
import net.sf.openrocket.util.Prefs;
|
||||
import net.sf.openrocket.util.SimpleFileFilter;
|
||||
|
||||
|
||||
/**
|
||||
@ -123,19 +124,20 @@ public class Startup {
|
||||
* Initializes the localization system.
|
||||
*/
|
||||
private static void initializeL10n() {
|
||||
String locale = System.getProperty("openrocket.locale");
|
||||
if (locale != null) {
|
||||
Locale l;
|
||||
String[] split = locale.split("[_-]", 3);
|
||||
if (split.length == 1) {
|
||||
l = new Locale(split[0]);
|
||||
} else if (split.length == 2) {
|
||||
l = new Locale(split[0], split[1]);
|
||||
} else {
|
||||
l = new Locale(split[0], split[1], split[2]);
|
||||
}
|
||||
|
||||
String langcode = System.getProperty("openrocket.locale");
|
||||
if (langcode != null) {
|
||||
Locale l = L10N.toLocale(langcode);
|
||||
log.info("Setting custom locale " + l);
|
||||
Locale.setDefault(l);
|
||||
} else {
|
||||
Locale l = Prefs.getUserLocale();
|
||||
if (l != null) {
|
||||
log.info("Setting user-selected locale " + l);
|
||||
Locale.setDefault(l);
|
||||
} else {
|
||||
log.info("Using default locale " + Locale.getDefault());
|
||||
}
|
||||
}
|
||||
|
||||
Translator t;
|
||||
@ -151,7 +153,6 @@ public class Startup {
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void runMain(String[] args) {
|
||||
|
||||
// Initialize the splash screen with version info
|
||||
|
||||
@ -7,11 +7,11 @@ import net.sf.openrocket.util.Chars;
|
||||
public abstract class Unit {
|
||||
|
||||
/** No unit with 2 digit precision */
|
||||
public static final Unit NOUNIT2 = new GeneralUnit(1,""+Chars.ZWSP, 2);
|
||||
|
||||
protected final double multiplier; // meters = units * multiplier
|
||||
public static final Unit NOUNIT2 = new GeneralUnit(1, "" + Chars.ZWSP, 2);
|
||||
|
||||
protected final double multiplier; // meters = units * multiplier
|
||||
protected final String unit;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new Unit with a given multiplier and unit name.
|
||||
*
|
||||
@ -26,7 +26,7 @@ public abstract class Unit {
|
||||
this.multiplier = multiplier;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts from SI units to this unit. The default implementation simply divides by the
|
||||
* multiplier.
|
||||
@ -35,9 +35,9 @@ public abstract class Unit {
|
||||
* @return Value in these units
|
||||
*/
|
||||
public double toUnit(double value) {
|
||||
return value/multiplier;
|
||||
return value / multiplier;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert from this type of units to SI units. The default implementation simply
|
||||
* multiplies by the multiplier.
|
||||
@ -46,9 +46,9 @@ public abstract class Unit {
|
||||
* @return Value in SI units
|
||||
*/
|
||||
public double fromUnit(double value) {
|
||||
return value*multiplier;
|
||||
return value * multiplier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the unit name.
|
||||
@ -111,10 +111,12 @@ public abstract class Unit {
|
||||
return unit;
|
||||
}
|
||||
|
||||
// TODO: Should this use grouping separator ("#,##0.##")?
|
||||
|
||||
private static final DecimalFormat intFormat = new DecimalFormat("#");
|
||||
private static final DecimalFormat decFormat = new DecimalFormat("0.##");
|
||||
private static final DecimalFormat expFormat = new DecimalFormat("0.00E0");
|
||||
|
||||
|
||||
/**
|
||||
* Format the given value (in SI units) to a string representation of the value in this
|
||||
* units. An suitable amount of decimals for the unit are used in the representation.
|
||||
@ -125,7 +127,7 @@ public abstract class Unit {
|
||||
*/
|
||||
public String toString(double value) {
|
||||
double val = toUnit(value);
|
||||
|
||||
|
||||
if (Math.abs(val) > 1E6) {
|
||||
return expFormat.format(val);
|
||||
}
|
||||
@ -135,7 +137,7 @@ public abstract class Unit {
|
||||
if (Math.abs(val) <= 0.005) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
|
||||
double sign = Math.signum(val);
|
||||
val = Math.abs(val);
|
||||
double mul = 1.0;
|
||||
@ -143,7 +145,7 @@ public abstract class Unit {
|
||||
mul *= 10;
|
||||
val *= 10;
|
||||
}
|
||||
val = Math.rint(val)/mul * sign;
|
||||
val = Math.rint(val) / mul * sign;
|
||||
|
||||
return decFormat.format(val);
|
||||
}
|
||||
@ -168,7 +170,7 @@ public abstract class Unit {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new Value object with the specified value and this unit.
|
||||
*
|
||||
@ -189,7 +191,7 @@ public abstract class Unit {
|
||||
* @return Rounded value.
|
||||
*/
|
||||
public abstract double round(double value);
|
||||
|
||||
|
||||
/**
|
||||
* Return the next rounded value after the given value.
|
||||
* @param value Value in these units.
|
||||
@ -224,13 +226,12 @@ public abstract class Unit {
|
||||
return false;
|
||||
if (this.getClass() != other.getClass())
|
||||
return false;
|
||||
return ((this.multiplier == ((Unit)other).multiplier) &&
|
||||
this.unit.equals(((Unit)other).unit));
|
||||
return ((this.multiplier == ((Unit) other).multiplier) && this.unit.equals(((Unit) other).unit));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.getClass().hashCode() + this.unit.hashCode();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
115
src/net/sf/openrocket/util/FileHelper.java
Normal file
115
src/net/sf/openrocket/util/FileHelper.java
Normal file
@ -0,0 +1,115 @@
|
||||
package net.sf.openrocket.util;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
import net.sf.openrocket.l10n.L10N;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.logging.LogHelper;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
|
||||
/**
|
||||
* Helper methods related to user-initiated file manipulation.
|
||||
* <p>
|
||||
* These methods log the necessary information to the debug log.
|
||||
*
|
||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||
*/
|
||||
public final class FileHelper {
|
||||
private static final LogHelper log = Application.getLogger();
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
|
||||
// TODO: MEDIUM: Rename translation keys
|
||||
|
||||
/** File filter for any rocket designs (*.ork, *.rkt) */
|
||||
public static final FileFilter ALL_DESIGNS_FILTER =
|
||||
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter1"),
|
||||
".ork", ".ork.gz", ".rkt", ".rkt.gz");
|
||||
|
||||
/** File filter for OpenRocket designs (*.ork) */
|
||||
public static final FileFilter OPENROCKET_DESIGN_FILTER =
|
||||
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter2"), ".ork", ".ork.gz");
|
||||
|
||||
/** File filter for RockSim designs (*.rkt) */
|
||||
public static final FileFilter ROCKSIM_DESIGN_FILTER =
|
||||
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter3"), ".rkt", ".rkt.gz");
|
||||
|
||||
/** File filter for PDF files (*.pdf) */
|
||||
public static final FileFilter PDF_FILTER =
|
||||
new SimpleFileFilter(trans.get("filetypes.pdf"), ".pdf");
|
||||
|
||||
|
||||
|
||||
|
||||
private FileHelper() {
|
||||
// Prevent instantiation
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the provided file has a file extension. If the file does not have
|
||||
* any extension, append the provided extension to it.
|
||||
*
|
||||
* @param original the original file
|
||||
* @param extension the extension to append if none exists (without preceding dot)
|
||||
* @return the resulting filen
|
||||
*/
|
||||
public static File ensureExtension(File original, String extension) {
|
||||
|
||||
if (original.getName().indexOf('.') < 0) {
|
||||
log.debug(1, "File name does not contain extension, adding '" + extension + "'");
|
||||
String name = original.getAbsolutePath();
|
||||
name = name + "." + extension;
|
||||
return new File(name);
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Confirm that it is allowed to write to a file. If the file exists,
|
||||
* a confirmation dialog will be presented to the user to ensure overwriting is ok.
|
||||
*
|
||||
* @param file the file that is going to be written.
|
||||
* @param parent the parent component for the dialog.
|
||||
* @return <code>true</code> to write, <code>false</code> to abort.
|
||||
*/
|
||||
public static boolean confirmWrite(File file, Component parent) {
|
||||
if (file.exists()) {
|
||||
log.info(1, "File " + file + " exists, confirming overwrite from user");
|
||||
int result = JOptionPane.showConfirmDialog(parent,
|
||||
L10N.replace(trans.get("error.fileExists.desc"), "{filename}", file.getName()),
|
||||
trans.get("error.fileExists.title"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||
if (result != JOptionPane.YES_OPTION) {
|
||||
log.user(1, "User decided not to overwrite the file");
|
||||
return false;
|
||||
}
|
||||
log.user(1, "User decided to overwrite the file");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display an error message to the user that writing a file failed.
|
||||
*
|
||||
* @param e the I/O exception that caused the error.
|
||||
* @param parent the parent component for the dialog.
|
||||
*/
|
||||
public static void errorWriting(IOException e, Component parent) {
|
||||
|
||||
log.warn(1, "Error writing to file", e);
|
||||
JOptionPane.showMessageDialog(parent,
|
||||
new Object[] {
|
||||
trans.get("error.writing.desc"),
|
||||
e.getLocalizedMessage()
|
||||
}, trans.get("error.writing.title"), JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -18,7 +18,7 @@ import net.sf.openrocket.startup.Application;
|
||||
public class Icons {
|
||||
private static final LogHelper log = Application.getLogger();
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
|
||||
static {
|
||||
log.debug("Starting to load icons");
|
||||
}
|
||||
@ -60,6 +60,7 @@ public class Icons {
|
||||
public static final Icon EDIT_COPY = loadImageIcon("pix/icons/edit-copy.png", "Copy");
|
||||
public static final Icon EDIT_PASTE = loadImageIcon("pix/icons/edit-paste.png", "Paste");
|
||||
public static final Icon EDIT_DELETE = loadImageIcon("pix/icons/edit-delete.png", "Delete");
|
||||
public static final Icon EDIT_SCALE = loadImageIcon("pix/icons/edit-scale.png", "Scale");
|
||||
|
||||
public static final Icon ZOOM_IN = loadImageIcon("pix/icons/zoom-in.png", "Zoom in");
|
||||
public static final Icon ZOOM_OUT = loadImageIcon("pix/icons/zoom-out.png", "Zoom out");
|
||||
|
||||
56
src/net/sf/openrocket/util/Named.java
Normal file
56
src/net/sf/openrocket/util/Named.java
Normal file
@ -0,0 +1,56 @@
|
||||
package net.sf.openrocket.util;
|
||||
|
||||
import java.text.Collator;
|
||||
|
||||
/**
|
||||
* An object holder that provides a custom toString return value.
|
||||
* <p>
|
||||
* The class supports sorting by the name.
|
||||
*
|
||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||
* @param <T> the holder type
|
||||
*/
|
||||
public class Named<T> implements Comparable<Named<T>> {
|
||||
|
||||
private final T object;
|
||||
private final String name;
|
||||
|
||||
private Collator collator = null;
|
||||
|
||||
/**
|
||||
* Sole constructor.
|
||||
*
|
||||
* @param object the held object
|
||||
* @param name the value to return by toString().
|
||||
*/
|
||||
public Named(T object, String name) {
|
||||
this.object = object;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the held object.
|
||||
*
|
||||
* @return the object.
|
||||
*/
|
||||
public T get() {
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(Named<T> other) {
|
||||
if (collator == null) {
|
||||
collator = Collator.getInstance();
|
||||
}
|
||||
|
||||
return collator.compare(this.toString(), other.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@ -8,9 +8,11 @@ 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;
|
||||
@ -23,6 +25,7 @@ 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;
|
||||
@ -47,6 +50,16 @@ public class Prefs {
|
||||
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.
|
||||
*/
|
||||
@ -391,7 +404,24 @@ public class Prefs {
|
||||
//////////////////
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package net.sf.openrocket.gui.main;
|
||||
package net.sf.openrocket.util;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
20
src/net/sf/openrocket/util/Utils.java
Normal file
20
src/net/sf/openrocket/util/Utils.java
Normal file
@ -0,0 +1,20 @@
|
||||
package net.sf.openrocket.util;
|
||||
|
||||
public class Utils {
|
||||
|
||||
/**
|
||||
* Null-safe equals method.
|
||||
*
|
||||
* @param first the first object to compare
|
||||
* @param second the second object to compare
|
||||
* @return whether the two objects are both equal or both <code>null</code>
|
||||
*/
|
||||
public static boolean equals(Object first, Object second) {
|
||||
if (first == null) {
|
||||
return second == null;
|
||||
} else {
|
||||
return first.equals(second);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,6 +17,7 @@ import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.file.GeneralRocketLoader;
|
||||
import net.sf.openrocket.file.RocketLoadException;
|
||||
import net.sf.openrocket.file.motor.GeneralMotorLoader;
|
||||
import net.sf.openrocket.l10n.ResourceBundleTranslator;
|
||||
import net.sf.openrocket.masscalc.BasicMassCalculator;
|
||||
import net.sf.openrocket.masscalc.MassCalculator;
|
||||
import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
|
||||
@ -72,6 +73,7 @@ public class IntegrationTest {
|
||||
db.startLoading();
|
||||
assertEquals(1, db.getMotorSets().size());
|
||||
Application.setMotorSetDatabase(db);
|
||||
Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user