Make ComponentPresetDao and interface with implementation in ComponentPresetDatabase. ComponentPresetDatabase extends Database so it can support listeners. PresetModel implements DatabaseListener so it updates when the user changes the favorite settings.

This commit is contained in:
Kevin Ruland 2012-04-08 02:02:46 +00:00
parent a5d5e3d500
commit d8a4372ecd
8 changed files with 259 additions and 155 deletions

View File

@ -1,73 +1,16 @@
package net.sf.openrocket.database;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import net.sf.openrocket.file.preset.PresetCSVReader;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.InvalidComponentPresetException;
import net.sf.openrocket.preset.TypedPropertyMap;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
public class ComponentPresetDao {
public interface ComponentPresetDao {
// List of all ComponentPresets
private final List<ComponentPreset> templates = new ArrayList<ComponentPreset>();
public List<ComponentPreset> listAll();
public void insert( ComponentPreset preset );
// Package scope constructor to control creation pattern.
public ComponentPresetDao() {}
public void initialize() throws IOException {
Set<String> favorites = Application.getPreferences().getComponentFavorites();
InputStream is = ComponentPresetDao.class.getResourceAsStream("/datafiles/bodytubepresets.csv");
PresetCSVReader parser = new PresetCSVReader(is);
List<TypedPropertyMap> list = parser.parse();
for( TypedPropertyMap o : list ) {
try {
ComponentPreset preset = ComponentPreset.create(o);
if ( favorites.contains(preset.preferenceKey())) {
preset.setFavorite(true);
}
this.insert(preset);
} catch ( InvalidComponentPresetException ex ) {
throw new BugException( ex );
}
}
}
public List<ComponentPreset> listAll() {
return templates;
}
public void insert( ComponentPreset preset ) {
templates.add(preset);
}
public List<ComponentPreset> listForType( ComponentPreset.Type type ) {
if ( type == null ) {
return Collections.<ComponentPreset>emptyList();
}
List<ComponentPreset> result = new ArrayList<ComponentPreset>(templates.size()/6);
for( ComponentPreset preset : templates ) {
if ( preset.get(ComponentPreset.TYPE).equals(type) ) {
result.add(preset);
}
}
return result;
}
public List<ComponentPreset> listForType( ComponentPreset.Type type );
/**
* Return a list of component presets based on the type.
@ -77,52 +20,10 @@ public class ComponentPresetDao {
* @param favorite if true, only return the favorites. otherwise return all matching.
* @return
*/
public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite ) {
public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite );
if ( !favorite ) {
return listForType(type);
}
public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type );
List<ComponentPreset> result = new ArrayList<ComponentPreset>(templates.size()/6);
for( ComponentPreset preset : templates ) {
if ( preset.isFavorite() && preset.get(ComponentPreset.TYPE).equals(type) ) {
result.add(preset);
}
}
return result;
}
public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type ) {
if( type == null || type.length == 0 ) {
return Collections.<ComponentPreset>emptyList();
}
if (type.length == 1 ) {
return listForType(type[0]);
}
List<ComponentPreset> result = new ArrayList<ComponentPreset>(templates.size()/6);
for( ComponentPreset preset : templates ) {
ComponentPreset.Type presetType = preset.get(ComponentPreset.TYPE);
typeLoop: for( int i=0; i<type.length; i++ ) {
if ( !presetType.equals(type) ) {
result.add(preset);
break typeLoop; // from inner loop.
}
}
}
return result;
}
public void setFavorite( ComponentPreset preset, boolean favorite ) {
preset.setFavorite(favorite);
Application.getPreferences().setComponentFavorite( preset, favorite );
}
public void setFavorite( ComponentPreset preset, boolean favorite );
}

View File

@ -0,0 +1,139 @@
package net.sf.openrocket.database;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import net.sf.openrocket.file.Loader;
import net.sf.openrocket.file.preset.PresetCSVReader;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.InvalidComponentPresetException;
import net.sf.openrocket.preset.TypedPropertyMap;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
public class ComponentPresetDatabase extends Database<ComponentPreset> implements ComponentPresetDao {
private static class ComponentPresetLoader implements Loader<ComponentPreset> {
@Override
public Collection<ComponentPreset> load(InputStream stream,
String filename) throws IOException {
Set<String> favorites = Application.getPreferences().getComponentFavorites();
List<ComponentPreset> returnval = new ArrayList<ComponentPreset>();
InputStream is = ComponentPresetDao.class.getResourceAsStream("/datafiles/bodytubepresets.csv");
PresetCSVReader parser = new PresetCSVReader(is);
List<TypedPropertyMap> list = parser.parse();
for( TypedPropertyMap o : list ) {
try {
ComponentPreset preset = ComponentPreset.create(o);
if ( favorites.contains(preset.preferenceKey())) {
preset.setFavorite(true);
}
returnval.add(preset);
} catch ( InvalidComponentPresetException ex ) {
throw new BugException( ex );
}
}
return returnval;
}
}
public ComponentPresetDatabase() {
super(new ComponentPresetLoader());
}
@Override
public List<ComponentPreset> listAll() {
return list;
}
@Override
public void insert( ComponentPreset preset ) {
list.add(preset);
}
@Override
public List<ComponentPreset> listForType( ComponentPreset.Type type ) {
if ( type == null ) {
return Collections.<ComponentPreset>emptyList();
}
List<ComponentPreset> result = new ArrayList<ComponentPreset>(list.size()/6);
for( ComponentPreset preset : list ) {
if ( preset.get(ComponentPreset.TYPE).equals(type) ) {
result.add(preset);
}
}
return result;
}
/**
* Return a list of component presets based on the type.
* All components returned will be of Type type.
*
* @param type
* @param favorite if true, only return the favorites. otherwise return all matching.
* @return
*/
@Override
public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite ) {
if ( !favorite ) {
return listForType(type);
}
List<ComponentPreset> result = new ArrayList<ComponentPreset>(list.size()/6);
for( ComponentPreset preset : list ) {
if ( preset.isFavorite() && preset.get(ComponentPreset.TYPE).equals(type) ) {
result.add(preset);
}
}
return result;
}
@Override
public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type ) {
if( type == null || type.length == 0 ) {
return Collections.<ComponentPreset>emptyList();
}
if (type.length == 1 ) {
return listForType(type[0]);
}
List<ComponentPreset> result = new ArrayList<ComponentPreset>(list.size()/6);
for( ComponentPreset preset : list ) {
ComponentPreset.Type presetType = preset.get(ComponentPreset.TYPE);
typeLoop: for( int i=0; i<type.length; i++ ) {
if ( !presetType.equals(type) ) {
result.add(preset);
break typeLoop; // from inner loop.
}
}
}
return result;
}
@Override
public void setFavorite( ComponentPreset preset, boolean favorite ) {
preset.setFavorite(favorite);
Application.getPreferences().setComponentFavorite( preset, favorite );
this.fireAddEvent(preset);
}
}

View File

@ -1,6 +1,7 @@
package net.sf.openrocket.database;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
@ -15,9 +16,12 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import net.sf.openrocket.file.Loader;
import net.sf.openrocket.file.iterator.DirectoryIterator;
import net.sf.openrocket.file.iterator.FileIterator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.JarUtil;
import net.sf.openrocket.util.Pair;
@ -31,7 +35,7 @@ import net.sf.openrocket.util.JarUtil;
public class Database<T extends Comparable<T>> extends AbstractSet<T> {
private static final LogHelper log = Application.getLogger();
private final List<T> list = new ArrayList<T>();
protected final List<T> list = new ArrayList<T>();
private final ArrayList<DatabaseListener<T>> listeners =
new ArrayList<DatabaseListener<T>>();
private final Loader<T> loader;
@ -126,7 +130,27 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
//////// Directory loading
public void load( String dir, final String pattern ) throws IOException {
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().matches(pattern);
}
};
FileIterator files = DirectoryIterator.findDirectory(dir, filter);
while( files != null && files.hasNext() ) {
Pair<String, InputStream> file = files.next();
try {
this.addAll(loader.load(file.getV(), file.getU()));
} catch (IOException e) {
log.warn("Error loading file " + file + ": " + e.getMessage(), e);
}
}
}
/**
* Load all files in a directory to the motor database. Only files with file

View File

@ -5,6 +5,8 @@ import java.util.List;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import net.sf.openrocket.database.Database;
import net.sf.openrocket.database.DatabaseListener;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.preset.ComponentPreset;
@ -13,7 +15,7 @@ import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
public class PresetModel extends AbstractListModel implements ComboBoxModel, ComponentChangeListener {
public class PresetModel extends AbstractListModel implements ComboBoxModel, ComponentChangeListener, DatabaseListener<ComponentPreset> {
private static final LogHelper log = Application.getLogger();
private static final Translator trans = Application.getTranslator();
@ -25,7 +27,7 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
private final RocketComponent component;
private ComponentPreset previousPreset;
private final List<ComponentPreset> presets;
private List<ComponentPreset> presets;
public PresetModel(RocketComponent component) {
presets = Application.getComponentPresetDao().listForType(component.getPresetType(), true);
@ -84,6 +86,16 @@ public class PresetModel extends AbstractListModel implements ComboBoxModel, Com
}
}
// FIXME: Make model invalidatable
@Override
public void elementAdded(ComponentPreset element, Database<ComponentPreset> source) {
presets = Application.getComponentPresetDao().listForType(component.getPresetType(), true);
this.fireContentsChanged(this, 0, getSize());
}
@Override
public void elementRemoved(ComponentPreset element, Database<ComponentPreset> source) {
presets = Application.getComponentPresetDao().listForType(component.getPresetType(), true);
this.fireContentsChanged(this, 0, getSize());
}
}

View File

@ -13,6 +13,7 @@ import javax.swing.JSpinner;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.SpinnerEditor;
import net.sf.openrocket.gui.adaptors.BooleanModel;
@ -30,23 +31,26 @@ import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
public class BodyTubeConfig extends RocketComponentConfig {
private MotorConfig motorConfigPane = null;
private DoubleModel maxLength;
private JComboBox presetComboBox;
private PresetModel presetModel;
private static final Translator trans = Application.getTranslator();
public BodyTubeConfig(OpenRocketDocument d, RocketComponent c) {
super(d, c);
JPanel panel = new JPanel(new MigLayout("gap rel unrel", "[][65lp::][30lp::][]", ""));
//// Body tube template
// FIXME: Move to proper location
panel.add(new JLabel(trans.get("PresetModel.lbl.select")));
presetComboBox = new JComboBox(new PresetModel(component));
presetModel = new PresetModel(component);
((ComponentPresetDatabase)Application.getComponentPresetDao()).addDatabaseListener(presetModel);
presetComboBox = new JComboBox(presetModel);
presetComboBox.setEditable(false);
panel.add(presetComboBox, "wrap para");
//FIXME: temporarily put the select from table button in the config dialog.
@ -72,77 +76,77 @@ public class BodyTubeConfig extends RocketComponentConfig {
panel.add( opendialog, "wrap" );
}
//// Body tube length
panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Bodytubelength")));
maxLength = new DoubleModel(2.0);
DoubleModel length = new DoubleModel(component, "Length", UnitGroup.UNITS_LENGTH, 0);
JSpinner spin = new JSpinner(length.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin, "growx");
panel.add(new UnitSelector(length), "growx");
panel.add(new BasicSlider(length.getSliderModel(0, 0.5, maxLength)), "w 100lp, wrap");
//// Body tube diameter
panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Outerdiameter")));
DoubleModel od = new DoubleModel(component, "OuterRadius", 2, UnitGroup.UNITS_LENGTH, 0);
// Diameter = 2*Radius
spin = new JSpinner(od.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin, "growx");
panel.add(new UnitSelector(od), "growx");
panel.add(new BasicSlider(od.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px");
JCheckBox check = new JCheckBox(od.getAutomaticAction());
//// Automatic
check.setText(trans.get("BodyTubecfg.checkbox.Automatic"));
panel.add(check, "skip, span 2, wrap");
//// Inner diameter
panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Innerdiameter")));
// Diameter = 2*Radius
DoubleModel m = new DoubleModel(component, "InnerRadius", 2, UnitGroup.UNITS_LENGTH, 0);
spin = new JSpinner(m.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin, "growx");
panel.add(new UnitSelector(m), "growx");
panel.add(new BasicSlider(m.getSliderModel(new DoubleModel(0), od)), "w 100lp, wrap");
//// Wall thickness
panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Wallthickness")));
m = new DoubleModel(component, "Thickness", UnitGroup.UNITS_LENGTH, 0);
spin = new JSpinner(m.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin, "growx");
panel.add(new UnitSelector(m), "growx");
panel.add(new BasicSlider(m.getSliderModel(0, 0.01)), "w 100lp, wrap 0px");
//// Filled
check = new JCheckBox(new BooleanModel(component, "Filled"));
check.setText(trans.get("BodyTubecfg.checkbox.Filled"));
panel.add(check, "skip, span 2, wrap");
//// Material
panel.add(materialPanel(new JPanel(new MigLayout()), Material.Type.BULK),
"cell 4 0, gapleft paragraph, aligny 0%, spany");
//// General and General properties
tabbedPane.insertTab(trans.get("BodyTubecfg.tab.General"), null, panel,
trans.get("BodyTubecfg.tab.Generalproperties"), 0);
@ -151,17 +155,22 @@ public class BodyTubeConfig extends RocketComponentConfig {
tabbedPane.insertTab(trans.get("BodyTubecfg.tab.Motor"), null, motorConfigPane,
trans.get("BodyTubecfg.tab.Motormountconf"), 1);
tabbedPane.setSelectedIndex(0);
}
@Override
public void updateFields() {
super.updateFields();
if (motorConfigPane != null)
motorConfigPane.updateFields();
}
@Override
public void invalidateModels() {
super.invalidateModels();
((ComponentPresetDatabase)Application.getComponentPresetDao()).removeChangeListener(presetModel);
}
}

View File

@ -76,7 +76,7 @@ public class ComponentPresetChooserDialog extends JDialog {
double v = (Double) ComponentPresetChooserDialog.this.presets.get(row).get(key);
return new Value( v, key.getUnitGroup() );
} else {
return ComponentPresetChooserDialog.this.presets.get(row);
return ComponentPresetChooserDialog.this.presets.get(row).get(key);
}
}
};

View File

@ -20,7 +20,7 @@ import net.sf.openrocket.util.BugException;
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
// FIXME - Implement clone.
public class ComponentPreset {
public class ComponentPreset implements Comparable<ComponentPreset> {
private final TypedPropertyMap properties = new TypedPropertyMap();
@ -167,6 +167,14 @@ public class ComponentPreset {
}
public Manufacturer getManufacturer() {
return properties.get(MANUFACTURER);
}
public String getPartNo() {
return properties.get(PARTNO);
}
public boolean has(Object key) {
return properties.containsKey(key);
}
@ -187,6 +195,16 @@ public class ComponentPreset {
this.favorite = favorite;
}
@Override
public int compareTo(ComponentPreset p2) {
int manuCompare = this.getManufacturer().getSimpleName().compareTo(p2.getManufacturer().getSimpleName());
if ( manuCompare != 0 )
return manuCompare;
int partNoCompare = this.getPartNo().compareTo(p2.getPartNo());
return partNoCompare;
}
@Override
public String toString() {
return get(MANUFACTURER).toString() + " " + get(PARTNO);
@ -195,4 +213,5 @@ public class ComponentPreset {
public String preferenceKey() {
return get(MANUFACTURER).toString() + "|" + get(PARTNO);
}
}

View File

@ -4,7 +4,7 @@ import java.io.PrintStream;
import java.util.Locale;
import java.util.prefs.Preferences;
import net.sf.openrocket.database.ComponentPresetDao;
import net.sf.openrocket.database.ComponentPresetDatabase;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.DebugTranslator;
import net.sf.openrocket.l10n.L10N;
@ -57,8 +57,8 @@ public class Startup {
initializeL10n();
// Must be done after localization is initialized
ComponentPresetDao componentPresetDao = new ComponentPresetDao();
componentPresetDao.initialize();
ComponentPresetDatabase componentPresetDao = new ComponentPresetDatabase();
componentPresetDao.load("datafiles", ".*csv");
Application.setComponentPresetDao( componentPresetDao );
// Continue startup in Startup2 class (where Application is already set up)