Startup cleanup. Moved the entire swing application startup into a

single class.  Created BasicApplication as a simple way to initialize
little applications.  Pulled the dependency on WatcherService out from
DecalImage.
This commit is contained in:
kruland2607 2013-05-12 20:26:22 -05:00
parent d1ea73a455
commit ae7b2b3af1
41 changed files with 1146 additions and 1343 deletions

View File

@ -27,7 +27,7 @@
<property name="dist.src" value="${jar.dir}/${pkgname}-src.zip"/>
<!-- The main class of the application -->
<property name="main-class" value="net.sf.openrocket.startup.Startup"/>
<property name="main-class" value="net.sf.openrocket.startup.JiJStartup"/>
<property name="expanded-libs" value="${lib.dir}/miglayout15-swing.jar"/>

View File

@ -1,8 +0,0 @@
<configuration debug="false">
<appender name="buffer"
class="net.sf.openrocket.logging.LogbackBufferLoggerAdaptor">
</appender>
<root level="TRACE">
<appender-ref ref="buffer" />
</root>
</configuration>

View File

@ -13,6 +13,7 @@ public interface DecalImage extends ChangeSource, Comparable<DecalImage> {
public InputStream getBytes() throws FileNotFoundException, IOException;
public void exportImage(File file, boolean watchForChanges) throws IOException;
public void exportImage(File file) throws IOException;
public void fireChangeEvent(Object source);
}

View File

@ -33,8 +33,11 @@ class ResourceDecalImage implements DecalImage {
}
@Override
public void exportImage(File file, boolean watchForChanges) throws IOException {
public void exportImage(File file) throws IOException {
}
@Override
public void fireChangeEvent(Object source) {
}
@Override

View File

@ -11,30 +11,16 @@ import org.slf4j.LoggerFactory;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.startup.Application;
public abstract class ComponentPresetDatabase extends Database<ComponentPreset> implements ComponentPresetDao {
public class ComponentPresetDatabase extends Database<ComponentPreset> implements ComponentPresetDao {
private static final Logger logger = LoggerFactory.getLogger(ComponentPresetDatabase.class);
private volatile boolean startedLoading = false;
private volatile boolean endedLoading = false;
private final boolean asynchronous;
/** Set to true the first time {@link #blockUntilLoaded()} is called. */
protected volatile boolean inUse = false;
public ComponentPresetDatabase() {
super();
this.asynchronous = false;
}
public ComponentPresetDatabase(boolean asynchronous ) {
super();
this.asynchronous = asynchronous;
}
@Override
public List<ComponentPreset> listAll() {
blockUntilLoaded();
return list;
}
@ -45,7 +31,6 @@ public abstract class ComponentPresetDatabase extends Database<ComponentPreset>
@Override
public List<ComponentPreset> listForType( ComponentPreset.Type type ) {
blockUntilLoaded();
if ( type == null ) {
return Collections.<ComponentPreset>emptyList();
}
@ -71,8 +56,6 @@ public abstract class ComponentPresetDatabase extends Database<ComponentPreset>
*/
@Override
public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite ) {
blockUntilLoaded();
if ( !favorite ) {
return listForType(type);
}
@ -91,8 +74,6 @@ public abstract class ComponentPresetDatabase extends Database<ComponentPreset>
@Override
public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type ) {
blockUntilLoaded();
if( type == null || type.length == 0 ) {
return Collections.<ComponentPreset>emptyList();
}
@ -118,13 +99,11 @@ public abstract class ComponentPresetDatabase extends Database<ComponentPreset>
@Override
public List<ComponentPreset> listForTypes( List<ComponentPreset.Type> types ) {
blockUntilLoaded();
return listForTypes( (ComponentPreset.Type[]) types.toArray() );
}
@Override
public List<ComponentPreset> find(String manufacturer, String partNo) {
blockUntilLoaded();
List<ComponentPreset> presets = new ArrayList<ComponentPreset>();
for( ComponentPreset preset : list ) {
if ( preset.getManufacturer().getSimpleName().equals(manufacturer) && preset.getPartNo().equals(partNo) ) {
@ -136,75 +115,8 @@ public abstract class ComponentPresetDatabase extends Database<ComponentPreset>
@Override
public void setFavorite( ComponentPreset preset, ComponentPreset.Type type, boolean favorite ) {
blockUntilLoaded();
Application.getPreferences().setComponentFavorite( preset, type, favorite );
this.fireAddEvent(preset);
}
/**
* Used for loading the component preset database. This method will be called in a background
* thread to load the presets asynchronously.
*/
protected abstract void load();
/**
* Start loading the presets.
*
* @throws IllegalStateException if this method has already been called.
*/
public void startLoading() {
if (startedLoading) {
throw new IllegalStateException("Already called startLoading");
}
startedLoading = true;
if (asynchronous) {
new LoadingThread().start();
} else {
load();
}
synchronized (this) {
endedLoading = true;
this.notifyAll();
}
}
/**
* Background thread for loading the presets.
*/
private class LoadingThread extends Thread {
private LoadingThread() {
this.setName("PresetLoadingThread");
this.setPriority(MIN_PRIORITY);
}
@Override
public void run() {
load();
}
}
/**
* Block the current thread until loading of the presets has been completed.
*
* @throws IllegalStateException if startLoading() has not been called.
*/
public void blockUntilLoaded() {
inUse = true;
if (!startedLoading) {
throw new IllegalStateException("startLoading() has not been called");
}
if (!endedLoading) {
synchronized (this) {
while (!endedLoading) {
try {
this.wait();
} catch (InterruptedException e) {
logger.warn("InterruptedException occurred, ignoring", e);
}
}
}
}
}
}

View File

@ -35,8 +35,6 @@ import org.slf4j.LoggerFactory;
public class DecalRegistry {
private static Logger log = LoggerFactory.getLogger(DecalRegistry.class);
private WatchService watchService = Application.getWatchService();
DecalRegistry() {
}
@ -121,6 +119,11 @@ public class DecalRegistry {
return name != null ? name : delegate.getName();
}
@Override
public void fireChangeEvent(Object source) {
delegate.fireChangeEvent(source);
}
/**
* This function returns an InputStream backed by a byte[] containing the decal pixels.
* If it reads in the bytes from an actual file, the underlying file is closed.
@ -147,7 +150,7 @@ public class DecalRegistry {
}
@Override
public void exportImage(File file, boolean watchForChanges) throws IOException {
public void exportImage(File file) throws IOException {
try {
InputStream is = getBytes();
OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
@ -159,19 +162,6 @@ public class DecalRegistry {
this.fileSystemLocation = file;
if (watchForChanges) {
watchService.register(new FileWatcher(this.fileSystemLocation) {
@Override
public void handleEvent(WatchEvent evt) {
DecalImageImpl.this.delegate.fireChangeEvent();
//System.out.println(this.getFile() + " has changed");
}
});
}
} catch (IOException iex) {
throw new BugException(iex);
}

View File

@ -100,7 +100,7 @@ public class ExportDecalDialog extends JDialog {
private void export(DecalImage decal, File selectedFile) {
try {
decal.exportImage(selectedFile, false);
decal.exportImage(selectedFile);
} catch (IOException iex) {
String message = MessageFormat.format(trans.get("ExportDecalDialog.exception"), selectedFile.getAbsoluteFile());
JOptionPane.showMessageDialog(this, message, "", JOptionPane.ERROR_MESSAGE);

View File

@ -11,16 +11,16 @@ import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.ResourceBundleTranslator;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.BasicApplication;
import net.sf.openrocket.unit.UnitGroup;
public class Tester {
public static void main(String[] args) throws InterruptedException, InvocationTargetException {
Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
BasicApplication baseApp = new BasicApplication();
baseApp.initializeApplication();
GUIUtil.setBestLAF();
@ -33,7 +33,7 @@ public class Tester {
DoubleModel model = new DoubleModel(Math.toRadians(45), UnitGroup.UNITS_ANGLE);
DoubleModel second = new DoubleModel(Math.toRadians(30), UnitGroup.UNITS_ANGLE);
CompassPointer rose = new CompassSelector(model);
rose.setPreferredSize(new Dimension(300, 300));
rose.setSecondaryModel(second);
@ -51,11 +51,11 @@ public class Tester {
spin.setPreferredSize(new Dimension(50, 20));
panel.add(spin, "wrap para");
CompassSelectionButton button = new CompassSelectionButton(model);
panel.add(button);
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

View File

@ -52,6 +52,8 @@ import net.sf.openrocket.util.StateChangeListener;
public class AppearancePanel extends JPanel {
private static final Translator trans = Application.getTranslator();
private EditDecalHelper editDecalHelper = Application.getInjector().getInstance(EditDecalHelper.class);
private AppearanceBuilder ab;
// We hang on to the user selected appearance when switching to default appearance.
@ -269,7 +271,7 @@ public class AppearancePanel extends JPanel {
@Override
public void actionPerformed(ActionEvent e) {
try {
EditDecalHelper.editDecal(SwingUtilities.getWindowAncestor(AppearancePanel.this), document, c, ab.getImage());
editDecalHelper.editDecal(SwingUtilities.getWindowAncestor(AppearancePanel.this), document, c, ab.getImage());
} catch (EditDecalHelperException ex) {
JOptionPane.showMessageDialog(AppearancePanel.this, ex.getMessage(), "", JOptionPane.ERROR_MESSAGE);
}

View File

@ -1,19 +1,15 @@
package net.sf.openrocket.gui.preset;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.util.FileHelper;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.ResourceBundleTranslator;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.Markers;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.loader.MaterialHolder;
import net.sf.openrocket.preset.loader.RocksimComponentFileTranslator;
import net.sf.openrocket.preset.xml.OpenRocketComponentDTO;
import net.sf.openrocket.preset.xml.OpenRocketComponentSaver;
import net.sf.openrocket.startup.Application;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
@ -34,486 +30,476 @@ import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.xml.bind.JAXBException;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.util.FileHelper;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.logging.Markers;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.loader.MaterialHolder;
import net.sf.openrocket.preset.loader.RocksimComponentFileTranslator;
import net.sf.openrocket.preset.xml.OpenRocketComponentDTO;
import net.sf.openrocket.preset.xml.OpenRocketComponentSaver;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.BasicApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* A UI for editing component presets. Currently this is a standalone application - run the main within this class.
* TODO: Full I18n TODO: Save As .csv
*/
public class ComponentPresetEditor extends JPanel implements PresetResultListener {
/**
* The logger.
*/
private static final Logger log = LoggerFactory.getLogger(ComponentPresetEditor.class);
/**
* The I18N translator.
*/
private static Translator trans = null;
/**
* The table of presets.
*/
private JTable table;
/**
* The table's data model.
*/
private DataTableModel model;
private final OpenedFileContext editContext = new OpenedFileContext();
static {
trans = Application.getTranslator();
}
/**
* Create the panel.
*
* @param frame the parent window
*/
public ComponentPresetEditor(final JFrame frame) {
setLayout(new MigLayout("", "[82.00px, grow][168.00px, grow][84px, grow][117.00px, grow][][222px]",
"[346.00px, grow][29px]"));
model = new DataTableModel(new String[]{"Manufacturer", "Type", "Part No", "Description", ""});
table = new JTable(model);
table.getTableHeader().setFont(new JLabel().getFont());
//The action never gets called because the table MouseAdapter intercepts it first. Still need an empty
// instance though.
Action action = new AbstractAction() {
@Override
public void actionPerformed(final ActionEvent e) {
}
};
//Create a editor/renderer for the delete operation. Instantiation self-registers into the table.
new ButtonColumn(table, action, 4);
table.getColumnModel().getColumn(4).setMaxWidth(Icons.EDIT_DELETE.getIconWidth());
table.getColumnModel().getColumn(4).setMinWidth(Icons.EDIT_DELETE.getIconWidth());
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
table.setAutoCreateRowSorter(true);
add(scrollPane, "cell 0 0 6 1,grow");
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable target = (JTable) e.getSource();
int selectedColumn = table.getColumnModel().getColumnIndexAtX(target.getSelectedColumn());
final int targetSelectedRow = target.getSelectedRow();
if (targetSelectedRow > -1 && targetSelectedRow < model.getRowCount()) {
int selectedRow = table.getRowSorter().convertRowIndexToModel(targetSelectedRow);
if (selectedColumn == 4) {
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(ComponentPresetEditor.this,
"Do you want to delete this preset?",
"Confirm Delete", JOptionPane.YES_OPTION,
JOptionPane.QUESTION_MESSAGE)) {
model.removeRow(selectedRow);
}
}
else {
if (e.getClickCount() == 2) {
editContext.setEditingSelected(true);
new PresetEditorDialog(ComponentPresetEditor.this,
(ComponentPreset) model.getAssociatedObject(selectedRow), editContext.getMaterialsLoaded()).setVisible(true);
}
}
}
}
});
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu mnFile = new JMenu("File");
menuBar.add(mnFile);
JMenuItem mntmOpen = new JMenuItem("Open...");
mnFile.add(mntmOpen);
mntmOpen.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (model.getRowCount() > 0) {
/*
* If the table model already contains presets, ask the user if they a) want to discard those
* presets, b) save them before reading in another component file, or c) merge the read component file
* with the current contents of the table model.
*/
Object[] options = {"Save",
"Merge",
"Discard",
"Cancel"};
int n = JOptionPane.showOptionDialog(frame,
"The editor contains existing component presets. What would you like to do with them?",
"Existing Component Presets",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (n == 0) { //Save. Then remove existing rows and open.
if (saveAndHandleError()) {
model.removeAllRows();
}
else { //Save failed; bail out.
return;
}
}
else if (n == 2) { //Discard and open
model.removeAllRows();
}
else if (n == 3) { //Cancel. Bail out.
return;
}
}
//Open file dialog
openComponentFile();
}
});
JSeparator separator = new JSeparator();
mnFile.add(separator);
JMenuItem mntmSave = new JMenuItem("Save As...");
mnFile.add(mntmSave);
mntmSave.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
saveAndHandleError();
}
});
JSeparator separator_1 = new JSeparator();
mnFile.add(separator_1);
JMenuItem mntmExit = new JMenuItem("Close");
mnFile.add(mntmExit);
mntmExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Window w = SwingUtilities.getWindowAncestor(ComponentPresetEditor.this);
w.dispose();
}
});
JButton addBtn = new JButton("Add");
addBtn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
editContext.setEditingSelected(false);
new PresetEditorDialog(ComponentPresetEditor.this).setVisible(true);
}
});
add(addBtn, "cell 0 1,alignx left,aligny top");
}
/**
* Callback method from the PresetEditorDialog to notify this class when a preset has been saved. The 'save' is
* really just a call back here so the preset can be added to the master table. It's not to be confused with the
* save to disk.
*
* @param preset the new or modified preset
*/
@Override
public void notifyResult(final ComponentPreset preset) {
if (preset != null) {
DataTableModel myModel = (DataTableModel) table.getModel();
//Is this a new preset?
String description = preset.has(ComponentPreset.DESCRIPTION) ? preset.get(ComponentPreset.DESCRIPTION) :
preset.getPartNo();
if (!editContext.isEditingSelected() || table.getSelectedRow() == -1) {
myModel.addRow(new Object[]{preset.getManufacturer().getDisplayName(), preset.getType().name(),
preset.getPartNo(), description, Icons.EDIT_DELETE}, preset);
}
else {
//This is a modified preset; update all of the columns and the stored associated instance.
int row = table.getSelectedRow();
myModel.setValueAt(preset.getManufacturer().getDisplayName(), row, 0);
myModel.setValueAt(preset.getType().name(), row, 1);
myModel.setValueAt(preset.getPartNo(), row, 2);
myModel.setValueAt(description, row, 3);
myModel.associated.set(row, preset);
}
}
editContext.setEditingSelected(false);
}
/**
* Launch the test main.
*/
public static void main(String[] args) {
try {
trans = new ResourceBundleTranslator("l10n.messages");
net.sf.openrocket.startup.Application.setBaseTranslator(trans);
Application.setPreferences(new SwingPreferences());
JFrame dialog = new JFrame();
dialog.getContentPane().add(new ComponentPresetEditor(dialog));
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.pack();
dialog.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* A table model that adds associated objects to each row, allowing for easy retrieval.
*/
class DataTableModel extends DefaultTableModel {
private List<Object> associated = new ArrayList<Object>();
/**
* Constructs a <code>DefaultTableModel</code> with as many columns as there are elements in
* <code>columnNames</code> and <code>rowCount</code> of <code>null</code> object values. Each column's name
* will be taken from the <code>columnNames</code> array.
*
* @param columnNames <code>array</code> containing the names of the new columns; if this is <code>null</code>
* then the model has no columns
*
* @see #setDataVector
* @see #setValueAt
*/
DataTableModel(final Object[] columnNames) {
super(columnNames, 0);
}
public void addRow(Object[] data, Object associatedData) {
super.addRow(data);
associated.add(getRowCount() - 1, associatedData);
}
public void removeAllRows() {
for (int x = getRowCount(); x > 0; x--) {
super.removeRow(x - 1);
}
associated.clear();
}
@Override
public void removeRow(int row) {
super.removeRow(row);
associated.remove(row);
}
public Object getAssociatedObject(int row) {
return associated.get(row);
}
@Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
return false;
}
}
/**
* Open the component file. Present a chooser for the user to navigate to the file.
*
* @return true if the file was successfully opened; Note: side effect, is that the ComponentPresets read from the
* file are written to the table model.
*/
private boolean openComponentFile() {
final JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
chooser.addChoosableFileFilter(FileHelper.CSV_FILE_FILTER);
chooser.setFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
if (editContext.getLastDirectory() != null) {
chooser.setCurrentDirectory(editContext.getLastDirectory());
}
else {
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory());
}
int option = chooser.showOpenDialog(ComponentPresetEditor.this);
if (option != JFileChooser.APPROVE_OPTION) {
editContext.setOpenedFile(null);
log.info(Markers.USER_MARKER, "User decided not to open, option=" + option);
return false;
}
File file = chooser.getSelectedFile();
try {
if (file == null) {
log.info(Markers.USER_MARKER, "User did not select a file");
return false;
}
editContext.setLastDirectory(file.getParentFile());
editContext.setMaterialsLoaded(null);
List<ComponentPreset> presets = null;
if (file.getName().toLowerCase().endsWith(".orc")) {
OpenRocketComponentDTO fileContents = new OpenRocketComponentSaver().unmarshalFromOpenRocketComponent(new FileReader(file));
editContext.setMaterialsLoaded(new MaterialHolder(fileContents.asMaterialList()));
presets = fileContents.asComponentPresets();
}
else {
if (file.getName().toLowerCase().endsWith(".csv")) {
file = file.getParentFile();
}
presets = new ArrayList<ComponentPreset>();
MaterialHolder materialHolder = RocksimComponentFileTranslator.loadAll(presets, file);
editContext.setMaterialsLoaded(materialHolder);
}
if (presets != null) {
for (ComponentPreset next : presets) {
notifyResult(next);
}
editContext.setOpenedFile(file);
}
}
catch (Exception e) {
String fileName = (file == null) ? "(file is null, can't get name)" : file.getName();
JOptionPane.showMessageDialog(ComponentPresetEditor.this, "Unable to open OpenRocket component file: " +
fileName + " Invalid format. " + e.getMessage());
editContext.setOpenedFile(null);
editContext.setEditingSelected(false);
return false;
}
return true;
}
private boolean saveAndHandleError() {
try {
return saveAsORC();
}
catch (Exception e1) {
JOptionPane.showMessageDialog(ComponentPresetEditor.this, e1.getLocalizedMessage(),
"Error saving ORC file.", JOptionPane.ERROR_MESSAGE);
return false;
}
}
/**
* Save the contents of the table model as XML in .orc format.
*
* @return true if the file was written
*
* @throws JAXBException thrown if the data could not be marshaled
* @throws IOException thrown if there was a problem with writing the file
*/
private boolean saveAsORC() throws JAXBException, IOException {
File file = null;
final JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
chooser.setFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
if (editContext.getOpenedFile() != null) {
chooser.setSelectedFile(editContext.getOpenedFile());
}
else {
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory());
}
int option = chooser.showSaveDialog(ComponentPresetEditor.this);
if (option != JFileChooser.APPROVE_OPTION) {
log.info(Markers.USER_MARKER, "User decided not to save, option=" + option);
return false;
}
file = chooser.getSelectedFile();
if (file == null) {
log.info(Markers.USER_MARKER, "User did not select a file");
return false;
}
file = FileHelper.forceExtension(file, "orc");
MaterialHolder materials = new MaterialHolder();
List<ComponentPreset> presets = new ArrayList<ComponentPreset>();
for (int x = 0; x < model.getRowCount(); x++) {
ComponentPreset preset = (ComponentPreset) model.getAssociatedObject(x);
// If we don't have a material already defined for saving...
if (materials.getMaterial(preset.get(ComponentPreset.MATERIAL)) == null) {
// Check if we loaded a material with this name.
Material m = null;
if (editContext.getMaterialsLoaded() != null) {
m = editContext.getMaterialsLoaded().getMaterial(preset.get
(ComponentPreset.MATERIAL));
}
// If there was no material loaded with that name, use the component's material.
if (m == null) {
m = preset.get(ComponentPreset.MATERIAL);
}
materials.put(m);
}
presets.add(preset);
}
return FileHelper.confirmWrite(file, this) && new OpenRocketComponentSaver().save(file, new ArrayList<Material>(materials.values()), presets);
}
class OpenedFileContext {
/**
* State variable to keep track of which file was opened, in case it needs to be saved back to that file.
*/
private File openedFile = null;
/**
* Last directory; file chooser is set here so user doesn't have to keep navigating to a common area.
*/
private File lastDirectory = null;
private boolean editingSelected = false;
private MaterialHolder materialsLoaded = null;
OpenedFileContext() {
}
public File getOpenedFile() {
return openedFile;
}
public void setOpenedFile(final File theOpenedFile) {
openedFile = theOpenedFile;
}
public File getLastDirectory() {
return lastDirectory;
}
public void setLastDirectory(final File theLastDirectory) {
lastDirectory = theLastDirectory;
}
public boolean isEditingSelected() {
return editingSelected;
}
public void setEditingSelected(final boolean theEditingSelected) {
editingSelected = theEditingSelected;
}
public MaterialHolder getMaterialsLoaded() {
return materialsLoaded;
}
public void setMaterialsLoaded(final MaterialHolder theMaterialsLoaded) {
materialsLoaded = theMaterialsLoaded;
}
}
/**
* The logger.
*/
private static final Logger log = LoggerFactory.getLogger(ComponentPresetEditor.class);
/**
* The table of presets.
*/
private JTable table;
/**
* The table's data model.
*/
private DataTableModel model;
private final OpenedFileContext editContext = new OpenedFileContext();
/**
* Create the panel.
*
* @param frame the parent window
*/
public ComponentPresetEditor(final JFrame frame) {
setLayout(new MigLayout("", "[82.00px, grow][168.00px, grow][84px, grow][117.00px, grow][][222px]",
"[346.00px, grow][29px]"));
model = new DataTableModel(new String[] { "Manufacturer", "Type", "Part No", "Description", "" });
table = new JTable(model);
table.getTableHeader().setFont(new JLabel().getFont());
//The action never gets called because the table MouseAdapter intercepts it first. Still need an empty
// instance though.
Action action = new AbstractAction() {
@Override
public void actionPerformed(final ActionEvent e) {
}
};
//Create a editor/renderer for the delete operation. Instantiation self-registers into the table.
new ButtonColumn(table, action, 4);
table.getColumnModel().getColumn(4).setMaxWidth(Icons.EDIT_DELETE.getIconWidth());
table.getColumnModel().getColumn(4).setMinWidth(Icons.EDIT_DELETE.getIconWidth());
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
table.setAutoCreateRowSorter(true);
add(scrollPane, "cell 0 0 6 1,grow");
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable target = (JTable) e.getSource();
int selectedColumn = table.getColumnModel().getColumnIndexAtX(target.getSelectedColumn());
final int targetSelectedRow = target.getSelectedRow();
if (targetSelectedRow > -1 && targetSelectedRow < model.getRowCount()) {
int selectedRow = table.getRowSorter().convertRowIndexToModel(targetSelectedRow);
if (selectedColumn == 4) {
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(ComponentPresetEditor.this,
"Do you want to delete this preset?",
"Confirm Delete", JOptionPane.YES_OPTION,
JOptionPane.QUESTION_MESSAGE)) {
model.removeRow(selectedRow);
}
}
else {
if (e.getClickCount() == 2) {
editContext.setEditingSelected(true);
new PresetEditorDialog(ComponentPresetEditor.this,
(ComponentPreset) model.getAssociatedObject(selectedRow), editContext.getMaterialsLoaded()).setVisible(true);
}
}
}
}
});
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu mnFile = new JMenu("File");
menuBar.add(mnFile);
JMenuItem mntmOpen = new JMenuItem("Open...");
mnFile.add(mntmOpen);
mntmOpen.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (model.getRowCount() > 0) {
/*
* If the table model already contains presets, ask the user if they a) want to discard those
* presets, b) save them before reading in another component file, or c) merge the read component file
* with the current contents of the table model.
*/
Object[] options = { "Save",
"Merge",
"Discard",
"Cancel" };
int n = JOptionPane.showOptionDialog(frame,
"The editor contains existing component presets. What would you like to do with them?",
"Existing Component Presets",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (n == 0) { //Save. Then remove existing rows and open.
if (saveAndHandleError()) {
model.removeAllRows();
}
else { //Save failed; bail out.
return;
}
}
else if (n == 2) { //Discard and open
model.removeAllRows();
}
else if (n == 3) { //Cancel. Bail out.
return;
}
}
//Open file dialog
openComponentFile();
}
});
JSeparator separator = new JSeparator();
mnFile.add(separator);
JMenuItem mntmSave = new JMenuItem("Save As...");
mnFile.add(mntmSave);
mntmSave.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
saveAndHandleError();
}
});
JSeparator separator_1 = new JSeparator();
mnFile.add(separator_1);
JMenuItem mntmExit = new JMenuItem("Close");
mnFile.add(mntmExit);
mntmExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Window w = SwingUtilities.getWindowAncestor(ComponentPresetEditor.this);
w.dispose();
}
});
JButton addBtn = new JButton("Add");
addBtn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
editContext.setEditingSelected(false);
new PresetEditorDialog(ComponentPresetEditor.this).setVisible(true);
}
});
add(addBtn, "cell 0 1,alignx left,aligny top");
}
/**
* Callback method from the PresetEditorDialog to notify this class when a preset has been saved. The 'save' is
* really just a call back here so the preset can be added to the master table. It's not to be confused with the
* save to disk.
*
* @param preset the new or modified preset
*/
@Override
public void notifyResult(final ComponentPreset preset) {
if (preset != null) {
DataTableModel myModel = (DataTableModel) table.getModel();
//Is this a new preset?
String description = preset.has(ComponentPreset.DESCRIPTION) ? preset.get(ComponentPreset.DESCRIPTION) :
preset.getPartNo();
if (!editContext.isEditingSelected() || table.getSelectedRow() == -1) {
myModel.addRow(new Object[] { preset.getManufacturer().getDisplayName(), preset.getType().name(),
preset.getPartNo(), description, Icons.EDIT_DELETE }, preset);
}
else {
//This is a modified preset; update all of the columns and the stored associated instance.
int row = table.getSelectedRow();
myModel.setValueAt(preset.getManufacturer().getDisplayName(), row, 0);
myModel.setValueAt(preset.getType().name(), row, 1);
myModel.setValueAt(preset.getPartNo(), row, 2);
myModel.setValueAt(description, row, 3);
myModel.associated.set(row, preset);
}
}
editContext.setEditingSelected(false);
}
/**
* Launch the test main.
*/
public static void main(String[] args) {
BasicApplication app = new BasicApplication();
app.initializeApplication();
try {
// FIXME - Application.setPreferences(new SwingPreferences());
JFrame dialog = new JFrame();
dialog.getContentPane().add(new ComponentPresetEditor(dialog));
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.pack();
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* A table model that adds associated objects to each row, allowing for easy retrieval.
*/
class DataTableModel extends DefaultTableModel {
private List<Object> associated = new ArrayList<Object>();
/**
* Constructs a <code>DefaultTableModel</code> with as many columns as there are elements in
* <code>columnNames</code> and <code>rowCount</code> of <code>null</code> object values. Each column's name
* will be taken from the <code>columnNames</code> array.
*
* @param columnNames <code>array</code> containing the names of the new columns; if this is <code>null</code>
* then the model has no columns
*
* @see #setDataVector
* @see #setValueAt
*/
DataTableModel(final Object[] columnNames) {
super(columnNames, 0);
}
public void addRow(Object[] data, Object associatedData) {
super.addRow(data);
associated.add(getRowCount() - 1, associatedData);
}
public void removeAllRows() {
for (int x = getRowCount(); x > 0; x--) {
super.removeRow(x - 1);
}
associated.clear();
}
@Override
public void removeRow(int row) {
super.removeRow(row);
associated.remove(row);
}
public Object getAssociatedObject(int row) {
return associated.get(row);
}
@Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
return false;
}
}
/**
* Open the component file. Present a chooser for the user to navigate to the file.
*
* @return true if the file was successfully opened; Note: side effect, is that the ComponentPresets read from the
* file are written to the table model.
*/
private boolean openComponentFile() {
final JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
chooser.addChoosableFileFilter(FileHelper.CSV_FILE_FILTER);
chooser.setFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
if (editContext.getLastDirectory() != null) {
chooser.setCurrentDirectory(editContext.getLastDirectory());
}
else {
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory());
}
int option = chooser.showOpenDialog(ComponentPresetEditor.this);
if (option != JFileChooser.APPROVE_OPTION) {
editContext.setOpenedFile(null);
log.info(Markers.USER_MARKER, "User decided not to open, option=" + option);
return false;
}
File file = chooser.getSelectedFile();
try {
if (file == null) {
log.info(Markers.USER_MARKER, "User did not select a file");
return false;
}
editContext.setLastDirectory(file.getParentFile());
editContext.setMaterialsLoaded(null);
List<ComponentPreset> presets = null;
if (file.getName().toLowerCase().endsWith(".orc")) {
OpenRocketComponentDTO fileContents = new OpenRocketComponentSaver().unmarshalFromOpenRocketComponent(new FileReader(file));
editContext.setMaterialsLoaded(new MaterialHolder(fileContents.asMaterialList()));
presets = fileContents.asComponentPresets();
}
else {
if (file.getName().toLowerCase().endsWith(".csv")) {
file = file.getParentFile();
}
presets = new ArrayList<ComponentPreset>();
MaterialHolder materialHolder = RocksimComponentFileTranslator.loadAll(presets, file);
editContext.setMaterialsLoaded(materialHolder);
}
if (presets != null) {
for (ComponentPreset next : presets) {
notifyResult(next);
}
editContext.setOpenedFile(file);
}
} catch (Exception e) {
String fileName = (file == null) ? "(file is null, can't get name)" : file.getName();
JOptionPane.showMessageDialog(ComponentPresetEditor.this, "Unable to open OpenRocket component file: " +
fileName + " Invalid format. " + e.getMessage());
editContext.setOpenedFile(null);
editContext.setEditingSelected(false);
return false;
}
return true;
}
private boolean saveAndHandleError() {
try {
return saveAsORC();
} catch (Exception e1) {
JOptionPane.showMessageDialog(ComponentPresetEditor.this, e1.getLocalizedMessage(),
"Error saving ORC file.", JOptionPane.ERROR_MESSAGE);
return false;
}
}
/**
* Save the contents of the table model as XML in .orc format.
*
* @return true if the file was written
*
* @throws JAXBException thrown if the data could not be marshaled
* @throws IOException thrown if there was a problem with writing the file
*/
private boolean saveAsORC() throws JAXBException, IOException {
File file = null;
final JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
chooser.setFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
if (editContext.getOpenedFile() != null) {
chooser.setSelectedFile(editContext.getOpenedFile());
}
else {
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory());
}
int option = chooser.showSaveDialog(ComponentPresetEditor.this);
if (option != JFileChooser.APPROVE_OPTION) {
log.info(Markers.USER_MARKER, "User decided not to save, option=" + option);
return false;
}
file = chooser.getSelectedFile();
if (file == null) {
log.info(Markers.USER_MARKER, "User did not select a file");
return false;
}
file = FileHelper.forceExtension(file, "orc");
MaterialHolder materials = new MaterialHolder();
List<ComponentPreset> presets = new ArrayList<ComponentPreset>();
for (int x = 0; x < model.getRowCount(); x++) {
ComponentPreset preset = (ComponentPreset) model.getAssociatedObject(x);
// If we don't have a material already defined for saving...
if (materials.getMaterial(preset.get(ComponentPreset.MATERIAL)) == null) {
// Check if we loaded a material with this name.
Material m = null;
if (editContext.getMaterialsLoaded() != null) {
m = editContext.getMaterialsLoaded().getMaterial(preset.get
(ComponentPreset.MATERIAL));
}
// If there was no material loaded with that name, use the component's material.
if (m == null) {
m = preset.get(ComponentPreset.MATERIAL);
}
materials.put(m);
}
presets.add(preset);
}
return FileHelper.confirmWrite(file, this) && new OpenRocketComponentSaver().save(file, new ArrayList<Material>(materials.values()), presets);
}
class OpenedFileContext {
/**
* State variable to keep track of which file was opened, in case it needs to be saved back to that file.
*/
private File openedFile = null;
/**
* Last directory; file chooser is set here so user doesn't have to keep navigating to a common area.
*/
private File lastDirectory = null;
private boolean editingSelected = false;
private MaterialHolder materialsLoaded = null;
OpenedFileContext() {
}
public File getOpenedFile() {
return openedFile;
}
public void setOpenedFile(final File theOpenedFile) {
openedFile = theOpenedFile;
}
public File getLastDirectory() {
return lastDirectory;
}
public void setLastDirectory(final File theLastDirectory) {
lastDirectory = theLastDirectory;
}
public boolean isEditingSelected() {
return editingSelected;
}
public void setEditingSelected(final boolean theEditingSelected) {
editingSelected = theEditingSelected;
}
public MaterialHolder getMaterialsLoaded() {
return materialsLoaded;
}
public void setMaterialsLoaded(final MaterialHolder theMaterialsLoaded) {
materialsLoaded = theMaterialsLoaded;
}
}
}

View File

@ -10,12 +10,25 @@ import net.sf.openrocket.appearance.AppearanceBuilder;
import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.dialogs.EditDecalDialog;
import net.sf.openrocket.gui.watcher.FileWatcher;
import net.sf.openrocket.gui.watcher.WatchEvent;
import net.sf.openrocket.gui.watcher.WatchService;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import com.google.inject.Inject;
public class EditDecalHelper {
@Inject
private WatchService watchService;
@Inject
private Translator trans;
@Inject
private SwingPreferences prefs;
public static class EditDecalHelperException extends Exception {
private String extraMessage = "";
@ -43,12 +56,8 @@ public class EditDecalHelper {
}
private static final Translator trans = Application.getTranslator();
public void editDecal(Window parent, OpenRocketDocument doc, RocketComponent component, DecalImage decal) throws EditDecalHelperException {
private static final SwingPreferences prefs = ((SwingPreferences) Application.getPreferences());
public static void editDecal(Window parent, OpenRocketDocument doc, RocketComponent component, DecalImage decal) throws EditDecalHelperException {
boolean sysPrefSet = prefs.isDecalEditorPreferenceSet();
int usageCount = doc.countDecalUsage(decal);
@ -102,7 +111,7 @@ public class EditDecalHelper {
return newImage;
}
private static void launchEditor(boolean useSystemEditor, String commandTemplate, DecalImage decal) throws EditDecalHelperException {
private void launchEditor(boolean useSystemEditor, String commandTemplate, final DecalImage decal) throws EditDecalHelperException {
String decalId = decal.getName();
// Create Temp File.
@ -121,7 +130,18 @@ public class EditDecalHelper {
}
try {
decal.exportImage(tmpFile, true);
decal.exportImage(tmpFile);
watchService.register(new FileWatcher(tmpFile) {
@Override
public void handleEvent(WatchEvent evt) {
decal.fireChangeEvent(evt);
//System.out.println(this.getFile() + " has changed");
}
});
} catch (IOException ioex) {
String message = MessageFormat.format(trans.get("EditDecalHelper.createFileException"), tmpFile.getAbsoluteFile());
throw new EditDecalHelperException(message, ioex);

View File

@ -29,7 +29,7 @@ public class LoggingSystemSetup {
appender.setContext(context);
PatternLayoutEncoder layout = new PatternLayoutEncoder();
layout.setContext(context);
layout.setPattern("%-8relative %-5marker %-5level [%thread] %logger{2} - %message%n%caller{2, BAD}");
layout.setPattern("%-8relative %-5marker %-5level [%thread] %logger{2} - %message%n");
layout.start();
appender.setEncoder(layout);
appender.start();

View File

@ -1,19 +1,17 @@
package net.sf.openrocket.preset.loader;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.xml.OpenRocketComponentSaver;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.GuiceStartup;
import net.sf.openrocket.util.ArrayList;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintStream;
import java.io.StringReader;
import java.util.List;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.xml.OpenRocketComponentSaver;
import net.sf.openrocket.startup.BasicApplication;
import net.sf.openrocket.util.ArrayList;
public class RocksimComponentFileTranslator {
private static PrintStream LOGGER = System.err;
@ -26,6 +24,9 @@ public class RocksimComponentFileTranslator {
public static void main(String[] args) throws Exception {
BasicApplication app = new BasicApplication();
app.initializeApplication();
// How to control logging?
if (args.length < 2 || args.length > 2) {
@ -37,9 +38,6 @@ public class RocksimComponentFileTranslator {
LOGGER.println("Loading csv files from directory " + args[0]);
GuiceStartup.initializeLogging();
Application.setPreferences(new SwingPreferences());
MaterialHolder materialMap = loadAll(allPresets, new File(args[0]));
LOGGER.println("\tMarshalling to XML");
String xml = new OpenRocketComponentSaver().marshalToOpenRocketComponent(new ArrayList<Material>(materialMap.values()), allPresets);

View File

@ -3,9 +3,7 @@ package net.sf.openrocket.startup;
import net.sf.openrocket.database.ComponentPresetDao;
import net.sf.openrocket.database.motor.MotorDatabase;
import net.sf.openrocket.database.motor.ThrustCurveMotorSetDatabase;
import net.sf.openrocket.gui.watcher.WatchService;
import net.sf.openrocket.l10n.ClassBasedTranslator;
import net.sf.openrocket.l10n.DebugTranslator;
import net.sf.openrocket.l10n.ExceptionSuppressingTranslator;
import net.sf.openrocket.l10n.Translator;
@ -18,12 +16,6 @@ import com.google.inject.Injector;
*/
public final class Application {
private static Translator baseTranslator = new DebugTranslator(null);
private static ComponentPresetDao componentPresetDao;
private static Preferences preferences;
private static ExceptionHandler exceptionHandler;
private static Injector injector;
@ -40,44 +32,28 @@ public final class Application {
return false;
}
public static WatchService getWatchService() {
return Application.injector.getInstance(WatchService.class);
private static Translator getBaseTranslator() {
return injector.getInstance(Translator.class);
}
/**
* Return the translator to use for obtaining translated strings.
* @return a translator.
*/
public static Translator getTranslator() {
Translator t = baseTranslator;
Translator t = getBaseTranslator();
t = new ClassBasedTranslator(t, 1);
t = new ExceptionSuppressingTranslator(t);
return t;
}
/**
* Set the translator used in obtaining translated strings.
* @param translator the translator to set.
*/
public static void setBaseTranslator(Translator translator) {
Application.baseTranslator = translator;
}
/**
* @return the preferences
*/
public static Preferences getPreferences() {
return preferences;
return injector.getInstance(Preferences.class);
}
/**
* @param preferences the preferences to set
*/
public static void setPreferences(Preferences preferences) {
Application.preferences = preferences;
}
/**
* @return the exceptionHandler
@ -114,15 +90,12 @@ public final class Application {
}
@Deprecated
public static ComponentPresetDao getComponentPresetDao() {
return componentPresetDao;
return injector.getInstance(ComponentPresetDao.class);
}
public static void setComponentPresetDao(ComponentPresetDao componentPresetDao) {
Application.componentPresetDao = componentPresetDao;
}
public static Injector getInjector() {
return injector;
}

View File

@ -1,21 +0,0 @@
package net.sf.openrocket.startup;
import net.sf.openrocket.formatting.RocketDescriptor;
import net.sf.openrocket.formatting.RocketDescriptorImpl;
import net.sf.openrocket.gui.watcher.WatchService;
import net.sf.openrocket.gui.watcher.WatchServiceImpl;
import net.sf.openrocket.l10n.Translator;
import com.google.inject.AbstractModule;
public class ApplicationModule extends AbstractModule {
@Override
protected void configure() {
bind(Preferences.class).toInstance(Application.getPreferences());
bind(Translator.class).toInstance(Application.getTranslator());
bind(WatchService.class).to(WatchServiceImpl.class);
bind(RocketDescriptor.class).to(RocketDescriptorImpl.class);
}
}

View File

@ -1,25 +0,0 @@
package net.sf.openrocket.startup;
import net.sf.openrocket.database.motor.MotorDatabase;
import net.sf.openrocket.database.motor.ThrustCurveMotorSetDatabase;
import com.google.inject.AbstractModule;
import com.google.inject.Provider;
public class ApplicationModule2 extends AbstractModule {
private final Provider<ThrustCurveMotorSetDatabase> motorDatabaseProvider;
public ApplicationModule2(Provider<ThrustCurveMotorSetDatabase> motorDatabaseProvider) {
this.motorDatabaseProvider = motorDatabaseProvider;
}
@Override
protected void configure() {
bind(ThrustCurveMotorSetDatabase.class).toProvider(motorDatabaseProvider);
bind(MotorDatabase.class).toProvider(motorDatabaseProvider);
}
}

View File

@ -0,0 +1,28 @@
package net.sf.openrocket.startup;
import net.sf.openrocket.plugin.PluginModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* Simple class which can be used to build basic applications.
*
* It initializes the Application object with a Guice Injector configured with
* the CoreServicesModule and PluginModule.
*
* @author kruland
*
*/
public class BasicApplication {
public final void initializeApplication() {
Module applicationModule = new CoreServicesModule();
Module pluginModule = new PluginModule();
Injector injector = Guice.createInjector(applicationModule, pluginModule);
Application.setInjector(injector);
}
}

View File

@ -0,0 +1,32 @@
package net.sf.openrocket.startup;
import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.l10n.Translator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
public class BlockingComponentPresetDatabaseProvider implements Provider<ComponentPresetDatabase> {
private final static Logger log = LoggerFactory.getLogger(BlockingComponentPresetDatabaseProvider.class);
@Inject
private Translator trans;
private final ComponentPresetDatabaseLoader loader;
public BlockingComponentPresetDatabaseProvider(ComponentPresetDatabaseLoader loader) {
this.loader = loader;
}
@Override
public ComponentPresetDatabase get() {
loader.blockUntilLoaded();
return loader.getDatabase();
}
}

View File

@ -1,4 +1,4 @@
package net.sf.openrocket.gui.util;
package net.sf.openrocket.startup;
import java.awt.SplashScreen;
import java.awt.event.ActionEvent;
@ -13,8 +13,8 @@ import javax.swing.Timer;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.database.motor.ThrustCurveMotorSetDatabase;
import net.sf.openrocket.gui.main.Splash;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.MotorDatabaseLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -0,0 +1,103 @@
package net.sf.openrocket.startup;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Collection;
import java.util.List;
import net.sf.openrocket.database.AsynchronousDatabaseLoader;
import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.file.iterator.DirectoryIterator;
import net.sf.openrocket.file.iterator.FileIterator;
import net.sf.openrocket.gui.util.SimpleFileFilter;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.xml.OpenRocketComponentLoader;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ComponentPresetDatabaseLoader extends AsynchronousDatabaseLoader {
private final static Logger log = LoggerFactory.getLogger(ComponentPresetDatabaseLoader.class);
private static final String SYSTEM_PRESET_DIR = "datafiles/presets";
private int fileCount = 0;
private int presetCount = 0;
private final ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase();
public ComponentPresetDatabaseLoader() {
super(0);
}
/**
* Returns the loaded database. If the database has not fully loaded,
* this blocks until it is.
*
* @return the motor database
*/
public ComponentPresetDatabase getDatabase() {
blockUntilLoaded();
return componentPresetDao;
}
@Override
protected void loadDatabase() {
long startTime = System.currentTimeMillis();
log.info("Loading component presets from " + SYSTEM_PRESET_DIR);
FileIterator iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR, new SimpleFileFilter("", false, "ser"));
if (iterator != null) {
while (iterator.hasNext()) {
Pair<String, InputStream> f = iterator.next();
try {
ObjectInputStream ois = new ObjectInputStream(f.getV());
List<ComponentPreset> list = (List<ComponentPreset>) ois.readObject();
componentPresetDao.addAll(list);
fileCount++;
presetCount += list.size();
} catch (Exception ex) {
throw new BugException(ex);
}
}
}
SimpleFileFilter orcFilter = new SimpleFileFilter("", false, "orc");
try {
iterator = new DirectoryIterator(
((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory(),
orcFilter,
true);
} catch (IOException ioex) {
iterator = null;
log.debug("Error opening UserComponentDirectory", ioex);
}
if (iterator != null) {
while (iterator.hasNext()) {
Pair<String, InputStream> f = iterator.next();
Collection<ComponentPreset> presets = loadFile(f.getU(), f.getV());
componentPresetDao.addAll(presets);
fileCount++;
presetCount += presets.size();
}
}
long end = System.currentTimeMillis();
log.debug("Time to load presets: " + (end - startTime) + "ms " + presetCount + " loaded from " + fileCount + " files");
}
private Collection<ComponentPreset> loadFile(String fileName, InputStream stream) {
log.debug("loading from file: " + fileName);
OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
Collection<ComponentPreset> presets = loader.load(stream, fileName);
return presets;
}
}

View File

@ -1,171 +0,0 @@
package net.sf.openrocket.startup;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.file.iterator.DirectoryIterator;
import net.sf.openrocket.file.iterator.FileIterator;
import net.sf.openrocket.gui.util.SimpleFileFilter;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.xml.OpenRocketComponentLoader;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Pair;
public class ConcurrentComponentPresetDatabaseLoader {
private static final Logger log = LoggerFactory.getLogger(ConcurrentComponentPresetDatabaseLoader.class);
private static final String SYSTEM_PRESET_DIR = "datafiles/presets";
private final CountDownLatch latch = new CountDownLatch(1);
private final ComponentPresetDatabase componentPresetDao;
private final ExecutorService writerPool;
private final ExecutorService loaderPool;
private final Thread workGenerator;
private FileIterator iterator;
private long startTime;
private long fileCount = 0;
private long presetCount = 0;
ConcurrentComponentPresetDatabaseLoader( ComponentPresetDatabase componentPresetDao ) {
this.componentPresetDao = componentPresetDao;
writerPool = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r,"PresetWriterThread");
return t;
}
});
loaderPool = Executors.newFixedThreadPool(3, new ThreadFactory() {
int threadCount = 0;
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r,"PresetLoaderPool-" + threadCount++);
t.setPriority(Thread.MIN_PRIORITY);
return t;
}
});
workGenerator = new Thread( new WorkGenerator(),"PresetGeneratorThread");
}
public void load() {
startTime = System.currentTimeMillis();
workGenerator.start();
}
public void await() throws InterruptedException {
latch.await();
loaderPool.shutdown();
loaderPool.awaitTermination(200, TimeUnit.SECONDS);
writerPool.shutdown();
writerPool.awaitTermination(200, TimeUnit.SECONDS);
if ( iterator != null ) {
iterator.close();
}
long end = System.currentTimeMillis();
log.debug("Time to load presets: " + (end-startTime) + "ms " + presetCount + " loaded from " + fileCount + " files");
}
private class WorkGenerator implements Runnable {
@Override
public void run() {
// Start loading
log.info("Loading component presets from " + SYSTEM_PRESET_DIR);
iterator = DirectoryIterator.findDirectory(SYSTEM_PRESET_DIR, new SimpleFileFilter("",false,"ser"));
if (iterator != null) {
while( iterator.hasNext() ) {
Pair<String,InputStream> f = iterator.next();
try {
ObjectInputStream ois = new ObjectInputStream(f.getV());
List<ComponentPreset> list = (List<ComponentPreset>) ois.readObject();
componentPresetDao.addAll(list);
fileCount++;
presetCount+=list.size();
}
catch ( Exception ex ) {
throw new BugException(ex);
}
}
}
try {
SimpleFileFilter orcFilter = new SimpleFileFilter("", false, "orc");
iterator = new DirectoryIterator(
((SwingPreferences) Application.getPreferences()).getDefaultUserComponentDirectory(),
orcFilter,
true);
if (iterator != null) {
while( iterator.hasNext() ) {
Pair<String,InputStream> f = iterator.next();
FileLoader loader = new FileLoader( f.getV(), f.getU() );
loaderPool.execute(loader);
fileCount ++;
}
}
} catch (IOException ioex ) {
log.debug("Error opening UserComponentDirectory", ioex);
}
latch.countDown();
}
}
private class FileLoader implements Runnable {
private final InputStream is;
private final String fileName;
public FileLoader(InputStream is, String fileName) {
super();
this.is = is;
this.fileName = fileName;
}
@Override
public void run() {
OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
Collection<ComponentPreset> presets = loader.load(is, fileName);
PresetWriter writer = new PresetWriter(presets);
writerPool.execute(writer);
}
}
private class PresetWriter implements Runnable {
private final Collection<ComponentPreset> presets;
public PresetWriter(Collection<ComponentPreset> presets) {
super();
this.presets = presets;
}
@Override
public void run() {
presetCount += presets.size();
componentPresetDao.addAll(presets);
}
}
}

View File

@ -0,0 +1,19 @@
package net.sf.openrocket.startup;
import net.sf.openrocket.formatting.RocketDescriptor;
import net.sf.openrocket.formatting.RocketDescriptorImpl;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator;
import com.google.inject.AbstractModule;
public class CoreServicesModule extends AbstractModule {
@Override
protected void configure() {
bind(Preferences.class).to(SwingPreferences.class);
bind(Translator.class).toProvider(TranslatorProvider.class);
bind(RocketDescriptor.class).to(RocketDescriptorImpl.class);
}
}

View File

@ -0,0 +1,57 @@
package net.sf.openrocket.startup;
import net.sf.openrocket.database.ComponentPresetDao;
import net.sf.openrocket.database.motor.MotorDatabase;
import net.sf.openrocket.database.motor.ThrustCurveMotorSetDatabase;
import net.sf.openrocket.gui.watcher.WatchService;
import net.sf.openrocket.gui.watcher.WatchServiceImpl;
import com.google.inject.AbstractModule;
import com.google.inject.Provider;
public class GuiModule extends AbstractModule {
private final Provider<ThrustCurveMotorSetDatabase> motorDatabaseProvider;
private final Provider<? extends ComponentPresetDao> componentDatabaseProvider;
public GuiModule() {
this.componentDatabaseProvider = loadPresetComponents();
this.motorDatabaseProvider = loadMotor();
}
@Override
protected void configure() {
bind(ComponentPresetDao.class).toProvider(componentDatabaseProvider);
bind(ThrustCurveMotorSetDatabase.class).toProvider(motorDatabaseProvider);
bind(MotorDatabase.class).toProvider(motorDatabaseProvider);
bind(WatchService.class).to(WatchServiceImpl.class);
}
/**
* Start loading preset components in background thread.
*
*/
public BlockingComponentPresetDatabaseProvider loadPresetComponents() {
ComponentPresetDatabaseLoader bg = new ComponentPresetDatabaseLoader();
bg.startLoading();
BlockingComponentPresetDatabaseProvider db = new BlockingComponentPresetDatabaseProvider(bg);
return db;
}
/**
* Start loading motors in background thread.
*
* Public for Python bindings.
*
* @return a provider for the database which blocks before returning the db.
*/
public BlockingMotorDatabaseProvider loadMotor() {
MotorDatabaseLoader bg = new MotorDatabaseLoader();
bg.startLoading();
BlockingMotorDatabaseProvider db = new BlockingMotorDatabaseProvider(bg);
return db;
}
}

View File

@ -1,169 +0,0 @@
package net.sf.openrocket.startup;
import java.io.PrintStream;
import java.util.Locale;
import java.util.prefs.Preferences;
import net.sf.openrocket.gui.util.SwingPreferences;
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.LoggingSystemSetup;
import net.sf.openrocket.logging.PrintStreamToSLF4J;
import net.sf.openrocket.plugin.PluginModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* Second class in the OpenRocket startup sequence, responsible for
* IoC initialization.
*
* This class is responsible for initializing the Guice dependency injection
* mechanism, and the legacy Application class.
*
* This class must be very cautious about what classes it calls. This is because
* the loggers/translators for classes are initialized as static final members during
* class initialization. For example, this class MUST NOT use the Prefs class, because
* using it will cause LineStyle to be initialized, which then receives an invalid
* (not-yet-initialized) translator.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class GuiceStartup {
private final static Logger log = LoggerFactory.getLogger(GuiceStartup.class);
/**
* OpenRocket startup main method.
*/
public static void main(final String[] args) throws Exception {
// Check for "openrocket.debug" property before anything else
checkDebugStatus();
// Initialize logging first so we can use it
initializeLogging();
// Setup the translations
initializeL10n();
// Initialize preferences (*after* translator setup!)
Application.setPreferences(new SwingPreferences());
Injector injector = initializeGuice();
injector.getInstance(ApplicationStartup.class).runMain(args);
}
/**
* Set proper system properties if openrocket.debug is defined.
*/
private static void checkDebugStatus() {
if (System.getProperty("openrocket.debug") != null) {
setPropertyIfNotSet("openrocket.debug.menu", "true");
setPropertyIfNotSet("openrocket.debug.mutexlocation", "true");
setPropertyIfNotSet("openrocket.debug.motordigest", "true");
setPropertyIfNotSet("jogl.debug", "all");
}
}
private static void setPropertyIfNotSet(String key, String value) {
if (System.getProperty(key) == null) {
System.setProperty(key, value);
}
}
/**
* Initializes the logging system.
*/
public static void initializeLogging() {
LoggingSystemSetup.setupLoggingAppender();
if (System.getProperty("openrocket.debug") != null) {
LoggingSystemSetup.addConsoleAppender();
}
//Replace System.err with a PrintStream that logs lines to DEBUG, or VBOSE if they are indented.
//If debug info is not being output to the console then the data is both logged and written to
//stderr.
final PrintStream stdErr = System.err;
System.setErr(PrintStreamToSLF4J.getPrintStream("STDERR", stdErr));
}
/**
* Initializes the localization system.
*/
private static void initializeL10n() {
// Check for locale propery
String langcode = System.getProperty("openrocket.locale");
if (langcode != null) {
Locale l = L10N.toLocale(langcode);
log.info("Setting custom locale " + l);
Locale.setDefault(l);
} else {
// Check user-configured locale
Locale l = getUserLocale();
if (l != null) {
log.info("Setting user-selected locale " + l);
Locale.setDefault(l);
} else {
log.info("Using default locale " + Locale.getDefault());
}
}
// Setup the translator
Translator t;
t = new ResourceBundleTranslator("l10n.messages");
if (Locale.getDefault().getLanguage().equals("xx")) {
t = new DebugTranslator(t);
}
log.info("Set up translation for locale " + Locale.getDefault() +
", debug.currentFile=" + t.get("debug.currentFile"));
Application.setBaseTranslator(t);
}
private static Locale getUserLocale() {
/*
* This method MUST NOT use the Prefs class, since is causes a multitude
* of classes to be initialized. Therefore this duplicates the functionality
* of the Prefs class locally.
*/
if (System.getProperty("openrocket.debug.prefs") != null) {
return null;
}
return L10N.toLocale(Preferences.userRoot().node("OpenRocket").get("locale", null));
}
private static Injector initializeGuice() {
Module applicationModule = new ApplicationModule();
Module pluginModule = new PluginModule();
return Guice.createInjector(applicationModule, pluginModule);
}
}

View File

@ -24,9 +24,9 @@ import net.sf.openrocket.startup.jij.PluginClasspathProvider;
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class Startup {
public class JiJStartup {
private static final String STARTUP_CLASS = "net.sf.openrocket.startup.GuiceStartup";
private static final String STARTUP_CLASS = "net.sf.openrocket.startup.SwingApplication";
public static void main(String[] args) {
addClasspathUrlHandler();

View File

@ -103,7 +103,7 @@ final class OSXStartup {
// Set the dock icon to the largest icon
final Image dockIcon = Toolkit.getDefaultToolkit().getImage(
ApplicationStartup.class.getResource(ICON_RSRC));
SwingApplication.class.getResource(ICON_RSRC));
osxApp.setDockIconImage(dockIcon);
} catch (final Throwable t) {

View File

@ -22,7 +22,7 @@ import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.UniqueID;
public abstract class Preferences {
/*
* Well known string keys to preferences.
* There are other strings out there in the source as well.
@ -37,40 +37,40 @@ public abstract class Preferences {
public static final String EXPORT_EVENT_COMMENTS = "ExportEventComments";
public static final String EXPORT_COMMENT_CHARACTER = "ExportCommentCharacter";
public static final String USER_LOCAL = "locale";
public static final String PLOT_SHOW_POINTS = "ShowPlotPoints";
private static final String CHECK_UPDATES = "CheckUpdates";
public static final String LAST_UPDATE = "LastUpdateVersion";
public static final String MOTOR_DIAMETER_FILTER = "MotorDiameterMatch";
public static final String MOTOR_HIDE_SIMILAR = "MotorHideSimilar";
// Node names
public static final String PREFERRED_THRUST_CURVE_MOTOR_NODE = "preferredThrustCurveMotors";
private static final String AUTO_OPEN_LAST_DESIGN = "AUTO_OPEN_LAST_DESIGN";
/*
* ******************************************************************************************
*
* Abstract methods which must be implemented by any derived class.
*/
private static final String AUTO_OPEN_LAST_DESIGN = "AUTO_OPEN_LAST_DESIGN";
/*
* ******************************************************************************************
*
* Abstract methods which must be implemented by any derived class.
*/
public abstract boolean getBoolean(String key, boolean defaultValue);
public abstract void putBoolean(String key, boolean value);
public abstract int getInt(String key, int defaultValue);
public abstract void putInt(String key, int value);
public abstract double getDouble(String key, double defaultValue);
public abstract void putDouble(String key, double value);
public abstract String getString(String key, String defaultValue);
public abstract void putString(String key, String value);
/**
* Directory represents a way to collect multiple keys together. Implementors may
* choose to concatenate the directory with the key using some special character.
@ -80,41 +80,41 @@ public abstract class Preferences {
* @return
*/
public abstract String getString(String directory, String key, String defaultValue);
public abstract void putString(String directory, String key, String value);
/*
* ******************************************************************************************
*/
public final boolean getCheckUpdates() {
return this.getBoolean(CHECK_UPDATES, BuildProperties.getDefaultCheckUpdates());
}
public final void setCheckUpdates(boolean check) {
this.putBoolean(CHECK_UPDATES, check);
}
public final double getDefaultMach() {
// TODO: HIGH: implement custom default mach number
return 0.3;
}
/**
* Enable/Disable the auto-opening of the last edited design file on startup.
*/
public final void setAutoOpenLastDesignOnStartup(boolean enabled) {
this.putBoolean(AUTO_OPEN_LAST_DESIGN, enabled);
}
/**
* Answer if the auto-opening of the last edited design file on startup is enabled.
*
* @return true if the application should automatically open the last edited design file on startup.
*/
public final boolean isAutoOpenLastDesignOnStartupEnabled() {
return this.getBoolean(AUTO_OPEN_LAST_DESIGN, false);
}
/**
* Enable/Disable the auto-opening of the last edited design file on startup.
*/
public final void setAutoOpenLastDesignOnStartup(boolean enabled) {
this.putBoolean(AUTO_OPEN_LAST_DESIGN, enabled);
}
/**
* Answer if the auto-opening of the last edited design file on startup is enabled.
*
* @return true if the application should automatically open the last edited design file on startup.
*/
public final boolean isAutoOpenLastDesignOnStartupEnabled() {
return this.getBoolean(AUTO_OPEN_LAST_DESIGN, false);
}
/**
* Return the OpenRocket unique ID.
*
@ -128,7 +128,7 @@ public abstract class Preferences {
}
return id;
}
/**
* Returns a limited-range integer value from the preferences. If the value
* in the preferences is negative or greater than max, then the default value
@ -145,7 +145,7 @@ public abstract class Preferences {
return def;
return v;
}
/**
* Helper method that puts an integer choice value into the preferences.
*
@ -155,7 +155,7 @@ public abstract class Preferences {
public final void putChoice(String key, int value) {
this.putInt(key, value);
}
/**
* Retrieve an enum value from the user preferences.
*
@ -168,19 +168,19 @@ public abstract class Preferences {
if (def == null) {
throw new BugException("Default value cannot be null");
}
String value = getString(key, null);
if (value == null) {
return def;
}
try {
return Enum.valueOf(def.getDeclaringClass(), value);
} catch (IllegalArgumentException e) {
return def;
}
}
/**
* Store an enum value to the user preferences.
*
@ -194,12 +194,12 @@ public abstract class Preferences {
putString(key, value.name());
}
}
public Color getDefaultColor(Class<? extends RocketComponent> c) {
String color = get("componentColors", c, DEFAULT_COLORS);
String color = get("componentColors", c, StaticFieldHolder.DEFAULT_COLORS);
if (color == null)
return Color.BLACK;
Color clr = parseColor(color);
if (clr != null) {
return clr;
@ -207,28 +207,28 @@ public abstract class Preferences {
return Color.BLACK;
}
}
public final void setDefaultColor(Class<? extends RocketComponent> c, Color color) {
if (color == null)
return;
putString("componentColors", c.getSimpleName(), stringifyColor(color));
}
/**
* Retrieve a Line style for the given component.
* @param c
* @return
*/
public final LineStyle getDefaultLineStyle(Class<? extends RocketComponent> c) {
String value = get("componentStyle", c, DEFAULT_LINE_STYLES);
String value = get("componentStyle", c, StaticFieldHolder.DEFAULT_LINE_STYLES);
try {
return LineStyle.valueOf(value);
} catch (Exception e) {
return LineStyle.SOLID;
}
}
/**
* Set a default line style for the given component.
* @param c
@ -240,7 +240,7 @@ public abstract class Preferences {
return;
putString("componentStyle", c.getSimpleName(), style.name());
}
/**
* Get the default material type for the given component.
* @param componentClass
@ -250,7 +250,7 @@ public abstract class Preferences {
public Material getDefaultComponentMaterial(
Class<? extends RocketComponent> componentClass,
Material.Type type) {
String material = get("componentMaterials", componentClass, null);
if (material != null) {
try {
@ -260,18 +260,18 @@ public abstract class Preferences {
} catch (IllegalArgumentException ignore) {
}
}
switch (type) {
case LINE:
return DefaultMaterialHolder.DEFAULT_LINE_MATERIAL;
return StaticFieldHolder.DEFAULT_LINE_MATERIAL;
case SURFACE:
return DefaultMaterialHolder.DEFAULT_SURFACE_MATERIAL;
return StaticFieldHolder.DEFAULT_SURFACE_MATERIAL;
case BULK:
return DefaultMaterialHolder.DEFAULT_BULK_MATERIAL;
return StaticFieldHolder.DEFAULT_BULK_MATERIAL;
}
throw new IllegalArgumentException("Unknown material type: " + type);
}
/**
* Set the default material for a component type.
* @param componentClass
@ -279,11 +279,11 @@ public abstract class Preferences {
*/
public void setDefaultComponentMaterial(
Class<? extends RocketComponent> componentClass, Material material) {
putString("componentMaterials", componentClass.getSimpleName(),
material == null ? null : material.toStorableString());
}
/**
* get a net.sf.openrocket.util.Color object for the given key.
* @param key
@ -297,7 +297,7 @@ public abstract class Preferences {
}
return c;
}
/**
* set a net.sf.openrocket.util.Color preference value for the given key.
* @param key
@ -306,7 +306,7 @@ public abstract class Preferences {
public final void putColor(String key, Color value) {
putString(key, stringifyColor(value));
}
/**
* Helper function to convert a string representation into a net.sf.openrocket.util.Color object.
* @param color
@ -316,7 +316,7 @@ public abstract class Preferences {
if (color == null) {
return null;
}
String[] rgb = color.split(",");
if (rgb.length == 3) {
try {
@ -329,7 +329,7 @@ public abstract class Preferences {
}
return null;
}
/**
* Helper function to convert a net.sf.openrocket.util.Color object into a
* String before storing in a preference.
@ -340,7 +340,7 @@ public abstract class Preferences {
String string = color.getRed() + "," + color.getGreen() + "," + color.getBlue();
return string;
}
/**
* Special helper function which allows for a map of default values.
*
@ -355,7 +355,7 @@ public abstract class Preferences {
protected String get(String directory,
Class<? extends RocketComponent> componentClass,
Map<Class<?>, String> defaultMap) {
// Search preferences
Class<?> c = componentClass;
while (c != null && RocketComponent.class.isAssignableFrom(c)) {
@ -364,10 +364,10 @@ public abstract class Preferences {
return value;
c = c.getSuperclass();
}
if (defaultMap == null)
return null;
// Search defaults
c = componentClass;
while (RocketComponent.class.isAssignableFrom(c)) {
@ -376,50 +376,45 @@ public abstract class Preferences {
return value;
c = c.getSuperclass();
}
return null;
}
public abstract void addUserMaterial(Material m);
public abstract Set<Material> getUserMaterials();
public abstract void removeUserMaterial(Material m);
public abstract void setComponentFavorite(ComponentPreset preset, ComponentPreset.Type type, boolean favorite);
public abstract Set<String> getComponentFavorites(ComponentPreset.Type type);
/*
* Map of default line styles
*/
private static final HashMap<Class<?>, String> DEFAULT_LINE_STYLES =
new HashMap<Class<?>, String>();
static {
DEFAULT_LINE_STYLES.put(RocketComponent.class, LineStyle.SOLID.name());
DEFAULT_LINE_STYLES.put(MassObject.class, LineStyle.DASHED.name());
}
/*
* Within a holder class so they will load only when needed.
*/
private static class DefaultMaterialHolder {
private static class StaticFieldHolder {
private static final Material DEFAULT_LINE_MATERIAL = Databases.findMaterial(Material.Type.LINE, "Elastic cord (round 2 mm, 1/16 in)");
private static final Material DEFAULT_SURFACE_MATERIAL = Databases.findMaterial(Material.Type.SURFACE, "Ripstop nylon");
private static final Material DEFAULT_BULK_MATERIAL = Databases.findMaterial(Material.Type.BULK, "Cardboard");
/*
* Map of default line styles
*/
private static final HashMap<Class<?>, String> DEFAULT_LINE_STYLES = new HashMap<Class<?>, String>();
static {
DEFAULT_LINE_STYLES.put(RocketComponent.class, LineStyle.SOLID.name());
DEFAULT_LINE_STYLES.put(MassObject.class, LineStyle.DASHED.name());
}
private static final HashMap<Class<?>, String> DEFAULT_COLORS = new HashMap<Class<?>, String>();
static {
DEFAULT_COLORS.put(BodyComponent.class, "0,0,240");
DEFAULT_COLORS.put(FinSet.class, "0,0,200");
DEFAULT_COLORS.put(LaunchLug.class, "0,0,180");
DEFAULT_COLORS.put(InternalComponent.class, "170,0,100");
DEFAULT_COLORS.put(MassObject.class, "0,0,0");
DEFAULT_COLORS.put(RecoveryDevice.class, "255,0,0");
}
}
private static final HashMap<Class<?>, String> DEFAULT_COLORS =
new HashMap<Class<?>, String>();
static {
DEFAULT_COLORS.put(BodyComponent.class, "0,0,240");
DEFAULT_COLORS.put(FinSet.class, "0,0,200");
DEFAULT_COLORS.put(LaunchLug.class, "0,0,180");
DEFAULT_COLORS.put(InternalComponent.class, "170,0,100");
DEFAULT_COLORS.put(MassObject.class, "0,0,0");
DEFAULT_COLORS.put(RecoveryDevice.class, "255,0,0");
}
}

View File

@ -11,7 +11,6 @@ import net.sf.openrocket.file.iterator.DirectoryIterator;
import net.sf.openrocket.file.iterator.FileIterator;
import net.sf.openrocket.file.motor.GeneralMotorLoader;
import net.sf.openrocket.gui.util.SimpleFileFilter;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.util.Pair;
@ -27,7 +26,7 @@ public class SerializeMotors {
String inputDir = args[0];
String outputFile = args[1];
Application.setPreferences(new SwingPreferences());
//Application.setPreferences(new SwingPreferences());
File outFile = new File(outputFile);

View File

@ -12,50 +12,40 @@ import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.file.iterator.DirectoryIterator;
import net.sf.openrocket.file.iterator.FileIterator;
import net.sf.openrocket.gui.util.SimpleFileFilter;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.ResourceBundleTranslator;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.xml.OpenRocketComponentLoader;
import net.sf.openrocket.util.Pair;
public class SerializePresets {
public class SerializePresets extends BasicApplication {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
Application.setPreferences(new SwingPreferences());
Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
SerializePresets app = new SerializePresets();
app.initializeApplication();
Locale.setDefault(Locale.ENGLISH);
ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase() {
@Override
protected void load() {
FileIterator iterator = DirectoryIterator.findDirectory("resources-src/datafiles/presets", new SimpleFileFilter("", false, "orc"));
if (iterator == null) {
throw new RuntimeException("Can't find resources-src/presets directory");
}
while (iterator.hasNext()) {
Pair<String, InputStream> f = iterator.next();
String fileName = f.getU();
InputStream is = f.getV();
OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
Collection<ComponentPreset> presets = loader.load(is, fileName);
this.addAll(presets);
}
}
};
ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase();
componentPresetDao.startLoading();
FileIterator iterator = DirectoryIterator.findDirectory("resources-src/datafiles/presets", new SimpleFileFilter("", false, "orc"));
if (iterator == null) {
throw new RuntimeException("Can't find resources-src/presets directory");
}
while (iterator.hasNext()) {
Pair<String, InputStream> f = iterator.next();
String fileName = f.getU();
InputStream is = f.getV();
OpenRocketComponentLoader loader = new OpenRocketComponentLoader();
Collection<ComponentPreset> presets = loader.load(is, fileName);
componentPresetDao.addAll(presets);
}
List<ComponentPreset> list = componentPresetDao.listAll();

View File

@ -4,6 +4,7 @@ import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.PrintStream;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
@ -13,23 +14,25 @@ import net.sf.openrocket.arch.SystemInfo;
import net.sf.openrocket.arch.SystemInfo.Platform;
import net.sf.openrocket.communication.UpdateInfo;
import net.sf.openrocket.communication.UpdateInfoRetriever;
import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.database.Databases;
import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
import net.sf.openrocket.gui.main.BasicFrame;
import net.sf.openrocket.gui.main.MRUDesignFile;
import net.sf.openrocket.gui.main.Splash;
import net.sf.openrocket.gui.main.SwingExceptionHandler;
import net.sf.openrocket.gui.util.BlockingMotorDatabaseProvider;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.logging.LoggingSystemSetup;
import net.sf.openrocket.logging.PrintStreamToSLF4J;
import net.sf.openrocket.plugin.PluginModule;
import net.sf.openrocket.util.BuildProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* The second class in the OpenRocket startup sequence. This class can assume the
@ -41,27 +44,22 @@ import com.google.inject.Injector;
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class ApplicationStartup {
private final static Logger log = LoggerFactory.getLogger(ApplicationStartup.class);
@Inject
private Injector injector;
public class SwingApplication {
private final static Logger log = LoggerFactory.getLogger(SwingApplication.class);
/**
* Run when starting up OpenRocket after Application has been set up.
*
* @param args command line arguments
* OpenRocket startup main method.
*/
public void runMain(final String[] args) throws Exception {
public static void main(final String[] args) throws Exception {
// Check for "openrocket.debug" property before anything else
checkDebugStatus();
// Initialize logging first so we can use it
initializeLogging();
log.info("Starting up OpenRocket version " + BuildProperties.getVersion());
Application.setInjector(injector);
Thread.sleep(1000);
// Check that we're not running headless
log.info("Checking for graphics head");
checkHead();
@ -71,18 +69,62 @@ public class ApplicationStartup {
OSXStartup.setupOSX();
}
final SwingApplication runner = new SwingApplication();
// Run the actual startup method in the EDT since it can use progress dialogs etc.
log.info("Moving startup to EDT");
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
runInEDT(args);
runner.runInEDT(args);
}
});
log.info("Startup complete");
}
/**
* Set proper system properties if openrocket.debug is defined.
*/
private static void checkDebugStatus() {
if (System.getProperty("openrocket.debug") != null) {
setPropertyIfNotSet("openrocket.debug.menu", "true");
setPropertyIfNotSet("openrocket.debug.mutexlocation", "true");
setPropertyIfNotSet("openrocket.debug.motordigest", "true");
setPropertyIfNotSet("jogl.debug", "all");
}
}
private static void setPropertyIfNotSet(String key, String value) {
if (System.getProperty(key) == null) {
System.setProperty(key, value);
}
}
/**
* Initializes the logging system.
*/
public static void initializeLogging() {
LoggingSystemSetup.setupLoggingAppender();
if (System.getProperty("openrocket.debug") != null) {
LoggingSystemSetup.addConsoleAppender();
}
//Replace System.err with a PrintStream that logs lines to DEBUG, or VBOSE if they are indented.
//If debug info is not being output to the console then the data is both logged and written to
//stderr.
final PrintStream stdErr = System.err;
System.setErr(PrintStreamToSLF4J.getPrintStream("STDERR", stdErr));
}
private Injector initializeGuice() {
Module applicationModule = new CoreServicesModule();
GuiModule guiModule = new GuiModule();
Module pluginModule = new PluginModule();
return Guice.createInjector(applicationModule, guiModule, pluginModule);
}
/**
* Run in the EDT when starting up OpenRocket.
@ -95,13 +137,28 @@ public class ApplicationStartup {
log.info("Initializing the splash screen");
Splash.init();
// Setup the uncaught exception handler
log.info("Registering exception handler");
SwingExceptionHandler exceptionHandler = new SwingExceptionHandler();
Application.setExceptionHandler(exceptionHandler);
exceptionHandler.registerExceptionHandler();
// Load motors etc.
log.info("Loading databases");
// There are some latent dependencies in here so the guiced application
// is created in two parts. In particular, the database loading processes
// require the translator to be setup correctly.
Module applicationModule = new CoreServicesModule();
Module pluginModule = new PluginModule();
Injector injector = Guice.createInjector(applicationModule, pluginModule);
Application.setInjector(injector);
// Update injector to contain database bindings
GuiModule guiModule = new GuiModule();
Injector injector2 = injector.createChildInjector(guiModule);
Application.setInjector(injector2);
// Start update info fetching
final UpdateInfoRetriever updateInfo;
if (Application.getPreferences().getCheckUpdates()) {
@ -123,22 +180,8 @@ public class ApplicationStartup {
// Load defaults
((SwingPreferences) Application.getPreferences()).loadDefaultUnits();
// Load motors etc.
log.info("Loading databases");
loadPresetComponents();
BlockingMotorDatabaseProvider db = loadMotor();
// Update injector to contain database bindings
ApplicationModule2 module = new ApplicationModule2(db);
Injector injector2 = injector.createChildInjector(module);
Application.setInjector(injector2);
Databases.fakeMethod();
// Starting action (load files or open new document)
log.info("Opening main application window");
if (!handleCommandLine(args)) {
@ -167,46 +210,10 @@ public class ApplicationStartup {
}
/**
* Start loading preset components in background thread.
*
* Public for Python bindings.
*/
public void loadPresetComponents() {
ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase(false) {
@Override
protected void load() {
ConcurrentComponentPresetDatabaseLoader presetLoader = new ConcurrentComponentPresetDatabaseLoader(this);
presetLoader.load();
try {
presetLoader.await();
} catch (InterruptedException iex) {
}
}
};
Application.setComponentPresetDao(componentPresetDao);
componentPresetDao.startLoading();
}
/**
* Start loading motors in background thread.
*
* Public for Python bindings.
*
* @return a provider for the database which blocks before returning the db.
*/
public BlockingMotorDatabaseProvider loadMotor() {
MotorDatabaseLoader bg = injector.getInstance(MotorDatabaseLoader.class);
bg.startLoading();
BlockingMotorDatabaseProvider db = new BlockingMotorDatabaseProvider(bg);
return db;
}
/**
* Check that the JRE is not running headless.
*/
private void checkHead() {
private static void checkHead() {
if (GraphicsEnvironment.isHeadless()) {
log.error("Application is headless.");

View File

@ -0,0 +1,75 @@
package net.sf.openrocket.startup;
import java.util.Locale;
import java.util.prefs.Preferences;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Provider;
public class TranslatorProvider implements Provider<Translator> {
private final static Logger log = LoggerFactory.getLogger(TranslatorProvider.class);
@Override
public Translator get() {
// Check for locale propery
String langcode = System.getProperty("openrocket.locale");
if (langcode != null) {
Locale l = L10N.toLocale(langcode);
log.info("Setting custom locale " + l);
Locale.setDefault(l);
} else {
// Check user-configured locale
Locale l = getUserLocale();
if (l != null) {
log.info("Setting user-selected locale " + l);
Locale.setDefault(l);
} else {
log.info("Using default locale " + Locale.getDefault());
}
}
// Setup the translator
Translator t;
t = new ResourceBundleTranslator("l10n.messages");
if (Locale.getDefault().getLanguage().equals("xx")) {
t = new DebugTranslator(t);
}
log.info("Set up translation for locale " + Locale.getDefault() +
", debug.currentFile=" + t.get("debug.currentFile"));
return t;
}
private static Locale getUserLocale() {
/*
* This method MUST NOT use the Prefs class, since is causes a multitude
* of classes to be initialized. Therefore this duplicates the functionality
* of the Prefs class locally.
*/
if (System.getProperty("openrocket.debug.prefs") != null) {
return null;
}
return L10N.toLocale(Preferences.userRoot().node("OpenRocket").get("locale", null));
}
}

View File

@ -9,9 +9,7 @@ import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.GeneralRocketLoader;
import net.sf.openrocket.file.GeneralRocketSaver;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.ResourceBundleTranslator;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.BasicApplication;
/**
* Utility that loads Rocksim file formats and saves them in ORK format.
@ -75,8 +73,9 @@ public class RocksimConverter {
private static void setup() {
Locale.setDefault(Locale.US);
Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
Application.setPreferences(new SwingPreferences());
BasicApplication app = new BasicApplication();
app.initializeApplication();
//?? Application.setPreferences(new SwingPreferences());
}
}

View File

@ -1,32 +0,0 @@
package net.sf.openrocket;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.plugin.PluginModule;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.ApplicationModule;
import org.junit.BeforeClass;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
public abstract class AbstractBaseApplication {
@BeforeClass
public static void setUp() throws Exception {
Application.setInjector(initializeGuice());
}
private static Injector initializeGuice() {
Application.setPreferences(new SwingPreferences());
Module applicationModule = new ApplicationModule();
Module pluginModule = new PluginModule();
return Guice.createInjector(applicationModule, pluginModule);
}
}

View File

@ -16,6 +16,9 @@ import javax.swing.Action;
import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.database.ComponentPresetDao;
import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.database.motor.MotorDatabase;
import net.sf.openrocket.database.motor.ThrustCurveMotorSetDatabase;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
@ -23,7 +26,6 @@ import net.sf.openrocket.file.GeneralRocketLoader;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.motor.GeneralMotorLoader;
import net.sf.openrocket.gui.main.UndoRedoAction;
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;
@ -37,8 +39,9 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.FlightDataType;
import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.ApplicationModule2;
import net.sf.openrocket.startup.GuiModule;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
@ -47,15 +50,18 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.util.Modules;
/**
* This class contains various integration tests that simulate user actions that
* might be performed.
*/
@RunWith(JMock.class)
public class IntegrationTest extends AbstractBaseApplication {
public class IntegrationTest extends BaseTestCase {
Mockery context = new JUnit4Mockery();
private OpenRocketDocument document;
@ -66,25 +72,48 @@ public class IntegrationTest extends AbstractBaseApplication {
private Configuration config;
private FlightConditions conditions;
private static class EmptyComponentDbProvider implements Provider<ComponentPresetDao> {
final ComponentPresetDao db = new ComponentPresetDatabase();
@Override
public ComponentPresetDao get() {
return db;
}
}
private static class MotorDbProvider implements Provider<ThrustCurveMotorSetDatabase> {
final ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase();
public MotorDbProvider() {
db.addMotor(readMotor());
assertEquals(1, db.getMotorSets().size());
}
@Override
public ThrustCurveMotorSetDatabase get() {
return db;
}
}
@BeforeClass
public static void setupMotorDatabase() {
final ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase();
db.addMotor(readMotor());
assertEquals(1, db.getMotorSets().size());
ApplicationModule2 module = new ApplicationModule2(new Provider<ThrustCurveMotorSetDatabase>() {
Module dbOverrides = new AbstractModule() {
@Override
public ThrustCurveMotorSetDatabase get() {
return db;
protected void configure() {
bind(ComponentPresetDao.class).toProvider(new EmptyComponentDbProvider());
bind(MotorDatabase.class).toProvider(new MotorDbProvider());
}
});
Injector injector2 = Application.getInjector().createChildInjector(module);
};
Injector injector2 = Application.getInjector().createChildInjector(Modules.override(new GuiModule()).with(dbOverrides));
Application.setInjector(injector2);
Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
}
@ -306,17 +335,17 @@ public class IntegrationTest extends AbstractBaseApplication {
private void checkUndoState(String undoDesc, String redoDesc) {
if (undoDesc == null) {
assertEquals("Undo", undoAction.getValue(Action.NAME));
assertEquals("[UndoRedoAction.OpenRocketDocument.Undo]", undoAction.getValue(Action.NAME));
assertFalse(undoAction.isEnabled());
} else {
assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
assertEquals("[UndoRedoAction.OpenRocketDocument.Undo] (" + undoDesc + ")", undoAction.getValue(Action.NAME));
assertTrue(undoAction.isEnabled());
}
if (redoDesc == null) {
assertEquals("Redo", redoAction.getValue(Action.NAME));
assertEquals("[UndoRedoAction.OpenRocketDocument.Redo]", redoAction.getValue(Action.NAME));
assertFalse(redoAction.isEnabled());
} else {
assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
assertEquals("[UndoRedoAction.OpenRocketDocument.Redo] (" + redoDesc + ")", redoAction.getValue(Action.NAME));
assertTrue(redoAction.isEnabled());
}
}

View File

@ -8,7 +8,6 @@ import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import net.sf.openrocket.AbstractBaseApplication;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.OpenRocketDocumentFactory;
import net.sf.openrocket.file.DatabaseMotorFinder;
@ -18,13 +17,14 @@ import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
import org.junit.Assert;
/**
* RocksimLoader Tester.
*/
public class RocksimLoaderTest extends AbstractBaseApplication {
public class RocksimLoaderTest extends BaseTestCase {
/**
* Test a bug reported via automated bug report. I have been unable to reproduce this bug

View File

@ -6,18 +6,15 @@ package net.sf.openrocket.file.rocksim.importt;
import java.lang.reflect.Field;
import java.util.List;
import net.sf.openrocket.AbstractBaseApplication;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
import org.junit.Assert;
import org.junit.Before;
/**
* A base class for the Rocksim tests. Includes code from the junitx.addons project.
*/
public abstract class RocksimTestBase extends AbstractBaseApplication {
public abstract class RocksimTestBase extends BaseTestCase {
public void assertContains(RocketComponent child, List<RocketComponent> components) {
Assert.assertTrue("Components did not contain child", components.contains(child));

View File

@ -3,7 +3,6 @@ package net.sf.openrocket.optimization.rocketoptimization;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import net.sf.openrocket.AbstractBaseApplication;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.optimization.general.OptimizationException;
import net.sf.openrocket.optimization.general.Point;
@ -12,6 +11,7 @@ import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.unit.Value;
import net.sf.openrocket.util.Pair;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
import org.jmock.Expectations;
import org.jmock.Mockery;
@ -23,7 +23,7 @@ import org.junit.runner.RunWith;
@RunWith(JMock.class)
public class TestRocketOptimizationFunction extends AbstractBaseApplication {
public class TestRocketOptimizationFunction extends BaseTestCase {
Mockery context = new JUnit4Mockery();
@Mock

View File

@ -2,17 +2,17 @@ package net.sf.openrocket.optimization.rocketoptimization.modifiers;
import static net.sf.openrocket.util.MathUtil.EPSILON;
import static org.junit.Assert.assertEquals;
import net.sf.openrocket.AbstractBaseApplication;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.optimization.general.OptimizationException;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class TestGenericModifier extends AbstractBaseApplication {
public class TestGenericModifier extends BaseTestCase {
private TestValue value;
private GenericModifier<TestValue> gm;

View File

@ -1,8 +1,6 @@
package net.sf.openrocket.plugin;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.ApplicationModule;
import net.sf.openrocket.startup.CoreServicesModule;
import org.junit.Test;
@ -22,9 +20,7 @@ public class PluginTest {
@Test
public void testPluginModule() {
Application.setPreferences(new SwingPreferences());
Module applicationModule = new ApplicationModule();
Module applicationModule = new CoreServicesModule();
Injector injector = Guice.createInjector(applicationModule, new PluginModule());
PluginTester tester = injector.getInstance(PluginTester.class);

View File

@ -1,12 +1,12 @@
package net.sf.openrocket.simulation.customexpression;
import net.sf.openrocket.AbstractBaseApplication;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.OpenRocketDocumentFactory;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
import org.junit.Test;
public class TestExpressions extends AbstractBaseApplication {
public class TestExpressions extends BaseTestCase {
@Test
public void testExpressions() {

View File

@ -1,16 +1,34 @@
package net.sf.openrocket.util.BaseTestCase;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.DebugTranslator;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.plugin.PluginModule;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.CoreServicesModule;
import org.junit.BeforeClass;
public class BaseTestCase {
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.util.Modules;
public class BaseTestCase {
@BeforeClass
public static void setUpApplication () {
Application.setPreferences( new SwingPreferences() );
public static void setUp() throws Exception {
Module applicationModule = new CoreServicesModule();
Module debugTranslator = new AbstractModule() {
@Override
protected void configure() {
bind(Translator.class).toInstance(new DebugTranslator(null));
}
};
Module pluginModule = new PluginModule();
Injector injector = Guice.createInjector(Modules.override(applicationModule).with(debugTranslator), pluginModule);
Application.setInjector(injector);
}
}