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