Updates for 0.9.5
[debian/openrocket] / src / net / sf / openrocket / gui / adaptors / MaterialModel.java
1 package net.sf.openrocket.gui.adaptors;
2
3
4 import java.awt.Component;
5
6 import javax.swing.AbstractListModel;
7 import javax.swing.ComboBoxModel;
8 import javax.swing.SwingUtilities;
9
10 import net.sf.openrocket.database.Database;
11 import net.sf.openrocket.database.DatabaseListener;
12 import net.sf.openrocket.database.Databases;
13 import net.sf.openrocket.gui.dialogs.CustomMaterialDialog;
14 import net.sf.openrocket.material.Material;
15 import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
16 import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
17 import net.sf.openrocket.rocketcomponent.RocketComponent;
18 import net.sf.openrocket.util.Reflection;
19
20 public class MaterialModel extends AbstractListModel implements
21                 ComboBoxModel, ComponentChangeListener, DatabaseListener<Material> {
22         
23         private static final String CUSTOM = "Custom";
24
25         
26         private final Component parentComponent;
27         
28         private final RocketComponent component;
29         private final Material.Type type;
30         private final Database<Material> database;
31         
32         private final Reflection.Method getMethod;
33         private final Reflection.Method setMethod;
34         
35         
36         public MaterialModel(Component parent, RocketComponent component, Material.Type type) {
37                 this(parent, component, type, "Material");
38         }       
39
40         public MaterialModel(Component parent, RocketComponent component, Material.Type type, 
41                         String name) {
42                 this.parentComponent = parent;
43                 this.component = component;
44                 this.type = type;
45                 
46                 switch (type) {
47                 case LINE:
48                         this.database = Databases.LINE_MATERIAL;
49                         break;
50                         
51                 case BULK:
52                         this.database = Databases.BULK_MATERIAL;
53                         break;
54                         
55                 case SURFACE:
56                         this.database = Databases.SURFACE_MATERIAL;
57                         break;
58                         
59                 default:
60                         throw new IllegalArgumentException("Unknown material type:"+type);
61                 }
62                 
63                 try {
64                         getMethod = new Reflection.Method(component.getClass().getMethod("get"+name));
65                         setMethod = new Reflection.Method(component.getClass().getMethod("set"+name,
66                                         Material.class));
67                 } catch (NoSuchMethodException e) {
68                         throw new IllegalArgumentException("get/is methods for material " +
69                                         "not present in class "+component.getClass().getCanonicalName());
70                 }
71                 
72                 component.addComponentChangeListener(this);
73                 database.addDatabaseListener(this);
74         }
75         
76         @Override
77         public Object getSelectedItem() {
78                 return getMethod.invoke(component);
79         }
80
81         @Override
82         public void setSelectedItem(Object item) {
83                 if (item == null) {
84                         // Clear selection - huh?
85                         return;
86                 }
87
88                 if (item == CUSTOM) {
89                         
90                         // Open custom material dialog in the future, after combo box has closed
91                         SwingUtilities.invokeLater(new Runnable() {
92                                 @Override
93                                 public void run() {
94                                         CustomMaterialDialog dialog = new CustomMaterialDialog(
95                                                         SwingUtilities.getWindowAncestor(parentComponent), 
96                                                         (Material) getSelectedItem(), true,
97                                                         "Define custom material");
98
99                                         dialog.setVisible(true);
100                                         
101                                         if (!dialog.getOkClicked())
102                                                 return;
103                                         
104                                         Material material = dialog.getMaterial();
105                                         setMethod.invoke(component, material);
106                                         
107                                         if (dialog.isAddSelected()) {
108                                                 database.add(material);
109                                         }
110                                 }
111                         });
112                         
113                 } else if (item instanceof Material) {
114                         
115                         setMethod.invoke(component, item);
116                         
117                 } else {
118                         throw new IllegalArgumentException("Illegal item class " + item.getClass() + 
119                                         " item=" + item);
120                 }
121         }
122
123         @Override
124         public Object getElementAt(int index) {
125                 if (index == database.size()) {
126                         return CUSTOM;
127                 } else if (index >= database.size()+1) {
128                         return null;
129                 }
130                 return database.get(index);
131         }
132
133         @Override
134         public int getSize() {
135                 return database.size() + 1;
136         }
137
138
139
140         ////////  Change listeners
141
142         @Override
143         public void componentChanged(ComponentChangeEvent e) {
144                 if (((ComponentChangeEvent)e).isMassChange()) {
145                         this.fireContentsChanged(this, 0, 0);
146                 }
147         }
148
149         @Override
150         public void elementAdded(Material element, Database<Material> source) {
151                 this.fireContentsChanged(this, 0, database.size());
152         }
153
154         @Override
155         public void elementRemoved(Material element, Database<Material> source) {
156                 this.fireContentsChanged(this, 0, database.size());
157         }
158         
159 }