a914df00e2d49633787612108765426f354db4e9
[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 static final String CUSTOM = "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                 
51                 switch (type) {
52                 case LINE:
53                         this.database = Databases.LINE_MATERIAL;
54                         break;
55                         
56                 case BULK:
57                         this.database = Databases.BULK_MATERIAL;
58                         break;
59                         
60                 case SURFACE:
61                         this.database = Databases.SURFACE_MATERIAL;
62                         break;
63                         
64                 default:
65                         throw new IllegalArgumentException("Unknown material type:"+type);
66                 }
67                 
68                 try {
69                         getMethod = new Reflection.Method(component.getClass().getMethod("get"+name));
70                         setMethod = new Reflection.Method(component.getClass().getMethod("set"+name,
71                                         Material.class));
72                 } catch (NoSuchMethodException e) {
73                         throw new IllegalArgumentException("get/is methods for material " +
74                                         "not present in class "+component.getClass().getCanonicalName());
75                 }
76                 
77                 component.addComponentChangeListener(this);
78                 database.addDatabaseListener(this);
79         }
80         
81         @Override
82         public Object getSelectedItem() {
83                 return getMethod.invoke(component);
84         }
85
86         @Override
87         public void setSelectedItem(Object item) {
88                 if (item == null) {
89                         // Clear selection - huh?
90                         return;
91                 }
92
93                 if (item == CUSTOM) {
94                         
95                         // Open custom material dialog in the future, after combo box has closed
96                         SwingUtilities.invokeLater(new Runnable() {
97                                 @Override
98                                 public void run() {
99                                         CustomMaterialDialog dialog = new CustomMaterialDialog(
100                                                         SwingUtilities.getWindowAncestor(parentComponent), 
101                                                         (Material) getSelectedItem(), true,
102                                                         //// Define custom material
103                                                         trans.get("MaterialModel.title.Defcustmat"));
104
105                                         dialog.setVisible(true);
106                                         
107                                         if (!dialog.getOkClicked())
108                                                 return;
109                                         
110                                         Material material = dialog.getMaterial();
111                                         setMethod.invoke(component, material);
112                                         
113                                         if (dialog.isAddSelected()) {
114                                                 database.add(material);
115                                         }
116                                 }
117                         });
118                         
119                 } else if (item instanceof Material) {
120                         
121                         setMethod.invoke(component, item);
122                         
123                 } else {
124                         throw new IllegalArgumentException("Illegal item class " + item.getClass() + 
125                                         " item=" + item);
126                 }
127         }
128
129         @Override
130         public Object getElementAt(int index) {
131                 if (index == database.size()) {
132                         return CUSTOM;
133                 } else if (index >= database.size()+1) {
134                         return null;
135                 }
136                 return database.get(index);
137         }
138
139         @Override
140         public int getSize() {
141                 return database.size() + 1;
142         }
143
144
145
146         ////////  Change listeners
147
148         @Override
149         public void componentChanged(ComponentChangeEvent e) {
150                 if (((ComponentChangeEvent)e).isMassChange()) {
151                         this.fireContentsChanged(this, 0, 0);
152                 }
153         }
154
155         @Override
156         public void elementAdded(Material element, Database<Material> source) {
157                 this.fireContentsChanged(this, 0, database.size());
158         }
159
160         @Override
161         public void elementRemoved(Material element, Database<Material> source) {
162                 this.fireContentsChanged(this, 0, database.size());
163         }
164         
165 }