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:
parent
d1ea73a455
commit
ae7b2b3af1
@ -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"/>
|
||||
|
||||
|
@ -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>
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
28
core/src/net/sf/openrocket/startup/BasicApplication.java
Normal file
28
core/src/net/sf/openrocket/startup/BasicApplication.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
19
core/src/net/sf/openrocket/startup/CoreServicesModule.java
Normal file
19
core/src/net/sf/openrocket/startup/CoreServicesModule.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
57
core/src/net/sf/openrocket/startup/GuiModule.java
Normal file
57
core/src/net/sf/openrocket/startup/GuiModule.java
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.");
|
75
core/src/net/sf/openrocket/startup/TranslatorProvider.java
Normal file
75
core/src/net/sf/openrocket/startup/TranslatorProvider.java
Normal 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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user