language selector, bug fixed

This commit is contained in:
Sampo Niskanen 2011-07-21 18:08:42 +00:00
parent 27caf60161
commit 244e792453
38 changed files with 1176 additions and 804 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

Binary file not shown.

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

View File

@ -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");

View File

@ -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 {

View File

@ -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() {

View File

@ -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);
}

View File

@ -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 : "";
}
}

View File

@ -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();

View File

@ -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 {
}
}
}

View File

@ -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);
}

View File

@ -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);

View 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 {

View File

@ -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

View File

@ -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) {
}
}
}

View 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;
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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.
*/

View File

@ -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");
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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();
}
}

View 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);
}
}

View File

@ -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");

View 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());
}
}

View File

@ -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);

View File

@ -1,4 +1,4 @@
package net.sf.openrocket.gui.main;
package net.sf.openrocket.util;
import java.io.File;

View 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);
}
}
}

View File

@ -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"));
}
/**