package net.sf.openrocket.gui.adaptors; import java.awt.Component; import javax.swing.AbstractListModel; import javax.swing.ComboBoxModel; import javax.swing.SwingUtilities; import net.sf.openrocket.database.Database; import net.sf.openrocket.database.DatabaseListener; import net.sf.openrocket.database.Databases; import net.sf.openrocket.gui.dialogs.CustomMaterialDialog; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.ComponentChangeListener; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.Reflection; public class MaterialModel extends AbstractListModel implements ComboBoxModel, ComponentChangeListener, DatabaseListener<Material> { private final String custom; private final Component parentUIComponent; private final RocketComponent rocketComponent; private final Material.Type type; private final Database<Material> database; private final Reflection.Method getMethod; private final Reflection.Method setMethod; private static final Translator trans = Application.getTranslator(); public MaterialModel(Component parent, RocketComponent component, Material.Type type) { //// Material //this(parent, component, type, trans.get("MaterialModel.title.Material")); this(parent, component, type, "Material"); } public MaterialModel(Component parent, RocketComponent component, Material.Type type, String name) { this.parentUIComponent = parent; this.rocketComponent = component; this.type = type; this.custom = trans.get ("Material.CUSTOM"); switch (type) { case LINE: this.database = Databases.LINE_MATERIAL; break; case BULK: this.database = Databases.BULK_MATERIAL; break; case SURFACE: this.database = Databases.SURFACE_MATERIAL; break; default: throw new IllegalArgumentException("Unknown material type:"+type); } try { getMethod = new Reflection.Method(component.getClass().getMethod("get"+name)); setMethod = new Reflection.Method(component.getClass().getMethod("set"+name, Material.class)); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("get/is methods for material " + "not present in class "+component.getClass().getCanonicalName()); } component.addComponentChangeListener(this); database.addDatabaseListener(this); } @Override public Object getSelectedItem() { return getMethod.invoke(rocketComponent); } @Override public void setSelectedItem(Object item) { if (item == null) { // Clear selection - huh? return; } if (item == custom) { // Open custom material dialog in the future, after combo box has closed SwingUtilities.invokeLater(new Runnable() { @Override public void run() { CustomMaterialDialog dialog = new CustomMaterialDialog( SwingUtilities.getWindowAncestor(parentUIComponent), (Material) getSelectedItem(), true, //// Define custom material trans.get("MaterialModel.title.Defcustmat")); dialog.setVisible(true); if (!dialog.getOkClicked()) return; Material material = dialog.getMaterial(); setMethod.invoke(rocketComponent, material); if (dialog.isAddSelected()) { database.add(material); } } }); } else if (item instanceof Material) { setMethod.invoke(rocketComponent, item); } else { throw new IllegalArgumentException("Illegal item class " + item.getClass() + " item=" + item); } } @Override public Object getElementAt(int index) { if (index == database.size()) { return custom; } else if (index >= database.size()+1) { return null; } return database.get(index); } @Override public int getSize() { return database.size() + 1; } public Material.Type getType() { return type; } //////// Change listeners @Override public void componentChanged(ComponentChangeEvent e) { if (((ComponentChangeEvent)e).isMassChange()) { this.fireContentsChanged(this, 0, 0); } } @Override public void elementAdded(Material element, Database<Material> source) { this.fireContentsChanged(this, 0, database.size()); } @Override public void elementRemoved(Material element, Database<Material> source) { this.fireContentsChanged(this, 0, database.size()); } }