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.JDialog;
13 import javax.swing.JLabel;
14 import javax.swing.JPanel;
15 import javax.swing.JSpinner;
16 import javax.swing.JTextField;
17 import javax.swing.SwingUtilities;
18 import javax.swing.event.ChangeEvent;
19 import javax.swing.event.ChangeListener;
21 import net.miginfocom.swing.MigLayout;
22 import net.sf.openrocket.database.Database;
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.RocketComponent;
28 import net.sf.openrocket.unit.UnitGroup;
29 import net.sf.openrocket.util.Reflection;
31 public class MaterialModel extends AbstractListModel implements
32 ComboBoxModel, ChangeListener {
34 private static final String CUSTOM = "Custom";
37 private final RocketComponent component;
38 private final Material.Type type;
39 private final Database<Material> database;
41 private final Reflection.Method getMethod;
42 private final Reflection.Method setMethod;
45 public MaterialModel(RocketComponent component, Material.Type type) {
46 this(component, type, "Material");
49 public MaterialModel(RocketComponent component, Material.Type type, String name) {
50 this.component = component;
55 this.database = Databases.LINE_MATERIAL;
59 this.database = Databases.BULK_MATERIAL;
63 this.database = Databases.SURFACE_MATERIAL;
67 throw new IllegalArgumentException("Unknown material type:"+type);
71 getMethod = new Reflection.Method(component.getClass().getMethod("get"+name));
72 setMethod = new Reflection.Method(component.getClass().getMethod("set"+name,
74 } catch (NoSuchMethodException e) {
75 throw new IllegalArgumentException("get/is methods for material " +
76 "not present in class "+component.getClass().getCanonicalName());
79 component.addChangeListener(this);
80 database.addChangeListener(this);
84 public Object getSelectedItem() {
85 return getMethod.invoke(component);
89 public void setSelectedItem(Object item) {
92 // Open custom material dialog in the future, after combo box has closed
93 SwingUtilities.invokeLater(new Runnable() {
96 AddMaterialDialog dialog = new AddMaterialDialog();
97 dialog.setVisible(true);
99 if (!dialog.okClicked)
102 Material material = Material.newMaterial(type,
103 dialog.nameField.getText().trim(),
104 dialog.density.getValue());
105 setMethod.invoke(component, material);
107 // TODO: HIGH: Allow saving added material to database
108 // if (dialog.addBox.isSelected()) {
109 // database.add(material);
114 } else if (item instanceof Material) {
116 setMethod.invoke(component, item);
119 assert(false): "Should not occur";
124 public Object getElementAt(int index) {
125 if (index == database.size()) {
127 } else if (index >= database.size()+1) {
130 return database.get(index);
134 public int getSize() {
135 return database.size() + 1;
140 public void stateChanged(ChangeEvent e) {
141 if (e instanceof ComponentChangeEvent) {
142 if (((ComponentChangeEvent)e).isMassChange()) {
143 this.fireContentsChanged(this, 0, 0);
146 this.fireContentsChanged(this, 0, database.size());
153 private class AddMaterialDialog extends JDialog {
155 private boolean okClicked = false;
156 private JTextField nameField;
157 private DoubleModel density;
158 // private JCheckBox addBox;
160 public AddMaterialDialog() {
161 super((Window)null, "Custom material", Dialog.ModalityType.APPLICATION_MODAL);
163 Material material = (Material) getSelectedItem();
165 JPanel panel = new JPanel(new MigLayout("gap rel unrel","[][65lp::][30lp::]"));
167 panel.add(new JLabel("Material name:"));
168 nameField = new JTextField(15);
169 nameField.setText(material.getName());
170 panel.add(nameField,"span 2, growx, wrap");
172 panel.add(new JLabel("Material density:"));
173 density = new DoubleModel(material.getDensity(),UnitGroup.UNITS_DENSITY_BULK,0);
174 JSpinner spinner = new JSpinner(density.getSpinnerModel());
175 panel.add(spinner, "growx");
176 panel.add(new UnitSelector(density),"wrap");
178 // addBox = new JCheckBox("Add material to database");
179 // panel.add(addBox,"span, wrap");
181 JButton button = new JButton("OK");
182 button.addActionListener(new ActionListener() {
184 public void actionPerformed(ActionEvent e) {
186 AddMaterialDialog.this.setVisible(false);
189 panel.add(button,"span, split, tag ok");
191 button = new JButton("Cancel");
192 button.addActionListener(new ActionListener() {
194 public void actionPerformed(ActionEvent e) {
195 AddMaterialDialog.this.setVisible(false);
198 panel.add(button,"tag cancel");
200 this.setContentPane(panel);
202 this.setAlwaysOnTop(true);
203 this.setLocationRelativeTo(null);