1 package net.sf.openrocket.gui.adaptors;
4 import java.awt.Dialog;
5 import java.awt.Window;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
9 import javax.swing.AbstractListModel;
10 import javax.swing.ComboBoxModel;
11 import javax.swing.JButton;
12 import javax.swing.JCheckBox;
13 import javax.swing.JDialog;
14 import javax.swing.JLabel;
15 import javax.swing.JPanel;
16 import javax.swing.JSpinner;
17 import javax.swing.JTextField;
18 import javax.swing.SwingUtilities;
20 import net.miginfocom.swing.MigLayout;
21 import net.sf.openrocket.database.Database;
22 import net.sf.openrocket.database.DatabaseListener;
23 import net.sf.openrocket.database.Databases;
24 import net.sf.openrocket.gui.components.UnitSelector;
25 import net.sf.openrocket.material.Material;
26 import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
27 import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
28 import net.sf.openrocket.rocketcomponent.RocketComponent;
29 import net.sf.openrocket.unit.UnitGroup;
30 import net.sf.openrocket.util.Reflection;
32 public class MaterialModel extends AbstractListModel implements
33 ComboBoxModel, ComponentChangeListener, DatabaseListener<Material> {
35 private static final String CUSTOM = "Custom";
38 private final RocketComponent component;
39 private final Material.Type type;
40 private final Database<Material> database;
42 private final Reflection.Method getMethod;
43 private final Reflection.Method setMethod;
46 public MaterialModel(RocketComponent component, Material.Type type) {
47 this(component, type, "Material");
50 public MaterialModel(RocketComponent component, Material.Type type, String name) {
51 this.component = component;
56 this.database = Databases.LINE_MATERIAL;
60 this.database = Databases.BULK_MATERIAL;
64 this.database = Databases.SURFACE_MATERIAL;
68 throw new IllegalArgumentException("Unknown material type:"+type);
72 getMethod = new Reflection.Method(component.getClass().getMethod("get"+name));
73 setMethod = new Reflection.Method(component.getClass().getMethod("set"+name,
75 } catch (NoSuchMethodException e) {
76 throw new IllegalArgumentException("get/is methods for material " +
77 "not present in class "+component.getClass().getCanonicalName());
80 component.addComponentChangeListener(this);
81 database.addDatabaseListener(this);
85 public Object getSelectedItem() {
86 return getMethod.invoke(component);
90 public void setSelectedItem(Object item) {
93 // Open custom material dialog in the future, after combo box has closed
94 SwingUtilities.invokeLater(new Runnable() {
97 AddMaterialDialog dialog = new AddMaterialDialog();
98 dialog.setVisible(true);
100 if (!dialog.okClicked)
103 Material material = Material.newMaterial(type,
104 dialog.nameField.getText().trim(),
105 dialog.density.getValue(), true);
106 setMethod.invoke(component, material);
108 if (dialog.addBox.isSelected()) {
109 database.add(material);
114 } else if (item instanceof Material) {
116 setMethod.invoke(component, item);
119 throw new IllegalArgumentException("Illegal item class " + item.getClass() +
125 public Object getElementAt(int index) {
126 if (index == database.size()) {
128 } else if (index >= database.size()+1) {
131 return database.get(index);
135 public int getSize() {
136 return database.size() + 1;
141 //////// Change listeners
144 public void componentChanged(ComponentChangeEvent e) {
145 if (((ComponentChangeEvent)e).isMassChange()) {
146 this.fireContentsChanged(this, 0, 0);
151 public void elementAdded(Material element, Database<Material> source) {
152 this.fireContentsChanged(this, 0, database.size());
156 public void elementRemoved(Material element, Database<Material> source) {
157 this.fireContentsChanged(this, 0, database.size());
165 private class AddMaterialDialog extends JDialog {
167 private boolean okClicked = false;
168 private JTextField nameField;
169 private DoubleModel density;
170 private JCheckBox addBox;
172 public AddMaterialDialog() {
173 super((Window)null, "Custom material", Dialog.ModalityType.APPLICATION_MODAL);
175 Material material = (Material) getSelectedItem();
177 JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]"));
179 panel.add(new JLabel("Material name:"));
180 nameField = new JTextField(15);
181 nameField.setText(material.getName());
182 panel.add(nameField,"span 2, growx, wrap");
184 panel.add(new JLabel("Material density:"));
185 density = new DoubleModel(material.getDensity(),UnitGroup.UNITS_DENSITY_BULK,0);
186 JSpinner spinner = new JSpinner(density.getSpinnerModel());
187 panel.add(spinner, "growx");
188 panel.add(new UnitSelector(density),"wrap");
190 addBox = new JCheckBox("Add material to database");
191 panel.add(addBox,"span, wrap");
193 JButton button = new JButton("OK");
194 button.addActionListener(new ActionListener() {
196 public void actionPerformed(ActionEvent e) {
198 AddMaterialDialog.this.setVisible(false);
201 panel.add(button,"span, split, tag ok");
203 button = new JButton("Cancel");
204 button.addActionListener(new ActionListener() {
206 public void actionPerformed(ActionEvent e) {
207 AddMaterialDialog.this.setVisible(false);
210 panel.add(button,"tag cancel");
212 this.setContentPane(panel);
214 this.setAlwaysOnTop(true);
215 this.setLocationRelativeTo(null);