updates for 0.9.4
[debian/openrocket] / src / net / sf / openrocket / gui / dialogs / preferences / MaterialEditPanel.java
1 package net.sf.openrocket.gui.dialogs.preferences;
2
3 import java.awt.Color;
4 import java.awt.Component;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.awt.event.MouseAdapter;
8 import java.awt.event.MouseEvent;
9 import java.util.Iterator;
10
11 import javax.swing.JButton;
12 import javax.swing.JLabel;
13 import javax.swing.JOptionPane;
14 import javax.swing.JPanel;
15 import javax.swing.JScrollPane;
16 import javax.swing.JTable;
17 import javax.swing.SwingUtilities;
18 import javax.swing.event.ListSelectionEvent;
19 import javax.swing.event.ListSelectionListener;
20 import javax.swing.table.DefaultTableCellRenderer;
21
22 import net.miginfocom.swing.MigLayout;
23 import net.sf.openrocket.database.Database;
24 import net.sf.openrocket.database.Databases;
25 import net.sf.openrocket.gui.adaptors.Column;
26 import net.sf.openrocket.gui.adaptors.ColumnTableModel;
27 import net.sf.openrocket.gui.dialogs.CustomMaterialDialog;
28 import net.sf.openrocket.material.Material;
29 import net.sf.openrocket.unit.UnitGroup;
30 import net.sf.openrocket.unit.Value;
31
32 public class MaterialEditPanel extends JPanel {
33
34         private final JTable table;
35         
36         private final JButton addButton;
37         private final JButton editButton;
38         private final JButton deleteButton;
39         private final JButton revertButton;
40         
41         
42         public MaterialEditPanel() {
43                 super(new MigLayout("fill"));
44                 
45                 
46                 // TODO: LOW: Create sorter that keeps material types always in order
47                 final ColumnTableModel model = new ColumnTableModel(
48                                 new Column("Material") {
49                                         @Override
50                                         public Object getValueAt(int row) {
51                                                 return getMaterial(row).getName();
52                                         }
53                                 },
54                                 
55                                 new Column("Type") {
56                                         @Override
57                                         public Object getValueAt(int row) {
58                                                 return getMaterial(row).getType().toString();
59                                         }
60                                         @Override
61                                         public int getDefaultWidth() {
62                                                 return 15;
63                                         }
64                                 },
65                                 
66                                 new Column("Density") {
67                                         @Override
68                                         public Object getValueAt(int row) {
69                                                 Material m = getMaterial(row);
70                                                 double d = m.getDensity();
71                                                 switch (m.getType()) {
72                                                 case LINE:
73                                                         return UnitGroup.UNITS_DENSITY_LINE.toValue(d);
74                                                         
75                                                 case SURFACE:
76                                                         return UnitGroup.UNITS_DENSITY_SURFACE.toValue(d);
77                                                         
78                                                 case BULK:
79                                                         return UnitGroup.UNITS_DENSITY_BULK.toValue(d);
80                                                         
81                                                 default:
82                                                         throw new IllegalStateException("Material type " + m.getType());
83                                                 }
84                                         }
85                                         @Override
86                                         public int getDefaultWidth() {
87                                                 return 15;
88                                         }
89                                         @Override
90                                         public Class<?> getColumnClass() {
91                                                 return Value.class;
92                                         }
93                                 }
94                 ) {
95                         @Override
96                         public int getRowCount() {
97                                 return Databases.BULK_MATERIAL.size() + Databases.SURFACE_MATERIAL.size() +
98                                         Databases.LINE_MATERIAL.size();
99                         }
100                 };
101                 
102                 table = new JTable(model);
103                 model.setColumnWidths(table.getColumnModel());
104                 table.setAutoCreateRowSorter(true);
105                 table.setDefaultRenderer(Object.class, new MaterialCellRenderer());
106                 this.add(new JScrollPane(table), "w 200px, h 100px, grow 100");
107                 
108                 
109                 
110                 addButton = new JButton("New");
111                 addButton.setToolTipText("Add a new material");
112                 addButton.addActionListener(new ActionListener() {
113                         @Override
114                         public void actionPerformed(ActionEvent e) {
115                                 CustomMaterialDialog dialog = new CustomMaterialDialog(
116                                                         SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
117                                                         null, false, "Add a custom material");
118                                 dialog.setVisible(true);
119                                 if (dialog.getOkClicked()) {
120                                         Material mat = dialog.getMaterial();
121                                         getDatabase(mat).add(mat);
122                                         model.fireTableDataChanged();
123                                         setButtonStates();
124                                 }
125                         }
126                 });
127                 this.add(addButton, "gap rel rel para para, w 70lp, split 5, flowy, growx 1, top");
128                 
129                 
130                 editButton = new JButton("Edit");
131                 editButton.setToolTipText("Edit an existing material");
132                 editButton.addActionListener(new ActionListener() {
133                         @Override
134                         public void actionPerformed(ActionEvent e) {
135                                 int sel = table.getSelectedRow();
136                                 if (sel < 0)
137                                         return;
138                                 sel = table.convertRowIndexToModel(sel);
139                                 Material m = getMaterial(sel);
140                                 
141                                 CustomMaterialDialog dialog;
142                                 if (m.isUserDefined()) {
143                                         dialog = new CustomMaterialDialog(
144                                                         SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
145                                                         m, false, "Edit material");
146                                 } else {
147                                         dialog = new CustomMaterialDialog(
148                                                         SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
149                                                         m, false, "Add a custom material", 
150                                                         "The built-in materials cannot be modified.");
151                                 }
152                                 
153                                 dialog.setVisible(true);
154                                 
155                                 if (dialog.getOkClicked()) {
156                                         if (m.isUserDefined()) {
157                                                 getDatabase(m).remove(m);
158                                         }
159                                         Material mat = dialog.getMaterial();
160                                         getDatabase(mat).add(mat);
161                                         model.fireTableDataChanged();
162                                         setButtonStates();
163                                 }
164                         }
165                 });
166                 this.add(editButton, "gap rel rel para para, growx 1, top");
167                 
168                 
169                 deleteButton = new JButton("Delete");
170                 deleteButton.setToolTipText("Delete a user-defined material");
171                 deleteButton.addActionListener(new ActionListener() {
172                         @Override
173                         public void actionPerformed(ActionEvent e) {
174                                 int sel = table.getSelectedRow();
175                                 if (sel < 0)
176                                         return;
177                                 sel = table.convertRowIndexToModel(sel);
178                                 Material m = getMaterial(sel);
179                                 if (!m.isUserDefined())
180                                         return;
181                                 getDatabase(m).remove(m);
182                                 model.fireTableDataChanged();
183                                 setButtonStates();
184                         }
185                 });
186                 this.add(deleteButton, "gap rel rel para para, growx 1, top");
187                 
188                 
189                 this.add(new JPanel(), "grow 1");
190                 
191                 revertButton = new JButton("Revert all");
192                 revertButton.setToolTipText("Delete all user-defined materials");
193                 revertButton.addActionListener(new ActionListener() {
194                         @Override
195                         public void actionPerformed(ActionEvent e) {
196                                 int sel = JOptionPane.showConfirmDialog(MaterialEditPanel.this, 
197                                                 "Delete all user-defined materials?", "Revert all?", 
198                                                 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
199                                 if (sel == JOptionPane.YES_OPTION) {
200                                         Iterator<Material> iterator;
201
202                                         iterator = Databases.LINE_MATERIAL.iterator();
203                                         while (iterator.hasNext()) {
204                                                 if (iterator.next().isUserDefined())
205                                                         iterator.remove();
206                                         }
207
208                                         iterator = Databases.SURFACE_MATERIAL.iterator();
209                                         while (iterator.hasNext()) {
210                                                 if (iterator.next().isUserDefined())
211                                                         iterator.remove();
212                                         }
213
214                                         iterator = Databases.BULK_MATERIAL.iterator();
215                                         while (iterator.hasNext()) {
216                                                 if (iterator.next().isUserDefined())
217                                                         iterator.remove();
218                                         }
219                                         model.fireTableDataChanged();
220                                         setButtonStates();
221                                 }
222                         }
223                 });
224                 this.add(revertButton, "gap rel rel para para, growx 1, bottom, wrap");
225                 
226                 setButtonStates();
227                 table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
228                         @Override
229                         public void valueChanged(ListSelectionEvent e) {
230                                 setButtonStates();
231                         }
232                 });
233                 table.addMouseListener(new MouseAdapter() {
234                         @Override
235                         public void mouseClicked(MouseEvent e) {
236                                 if (e.getClickCount() == 2) {
237                                         editButton.doClick();
238                                 }
239                         }
240                 });
241                 
242                 
243                 this.add(new JLabel("<html><i>Editing materials will not affect existing " +
244                                 "rocket designs.</i>"), "span");
245                 
246                 
247         }
248         
249         
250         private Database<Material> getDatabase(Material m) {
251                 switch (m.getType()) {
252                 case BULK:
253                         return Databases.BULK_MATERIAL;
254                         
255                 case SURFACE:
256                         return Databases.SURFACE_MATERIAL;
257                         
258                 case LINE:
259                         return Databases.LINE_MATERIAL;
260
261                 default:
262                         throw new IllegalArgumentException("Material type invalid, m="+m);
263                 }
264         }
265         
266         
267         private void setButtonStates() {
268                 int sel = table.getSelectedRow();
269                 
270                 // Add button always enabled
271                 addButton.setEnabled(true);
272                 
273                 // Edit button enabled if a material is selected
274                 editButton.setEnabled(sel >= 0);
275                 
276                 // Delete button enabled if a user-defined material is selected
277                 if (sel >= 0) {
278                         int modelRow = table.convertRowIndexToModel(sel);
279                         deleteButton.setEnabled(getMaterial(modelRow).isUserDefined());
280                 } else {
281                         deleteButton.setEnabled(false);
282                 }
283
284                 // Revert button enabled if any user-defined material exists
285                 boolean found = false;
286                 
287                 for (Material m: Databases.BULK_MATERIAL) {
288                         if (m.isUserDefined()) {
289                                 found = true;
290                                 break;
291                         }
292                 }
293                 if (!found) {
294                         for (Material m: Databases.SURFACE_MATERIAL) {
295                                 if (m.isUserDefined()) {
296                                         found = true;
297                                         break;
298                                 }
299                         }
300                 }
301                 if (!found) {
302                         for (Material m: Databases.LINE_MATERIAL) {
303                                 if (m.isUserDefined()) {
304                                         found = true;
305                                         break;
306                                 }
307                         }
308                 }
309                 revertButton.setEnabled(found);
310                 
311         }
312         
313         private Material getMaterial(int origRow) {
314                 int row = origRow;
315                 int n;
316                 
317                 n = Databases.BULK_MATERIAL.size();
318                 if (row < n) {
319                         return Databases.BULK_MATERIAL.get(row);
320                 }
321                 row -= n;
322                 
323                 n = Databases.SURFACE_MATERIAL.size();
324                 if (row < n) {
325                         return Databases.SURFACE_MATERIAL.get(row);
326                 }
327                 row -= n;
328                 
329                 n = Databases.LINE_MATERIAL.size();
330                 if (row < n) {
331                         return Databases.LINE_MATERIAL.get(row);
332                 }
333                 throw new IndexOutOfBoundsException("row="+origRow+" while material count" +
334                                 " bulk:" + Databases.BULK_MATERIAL.size() + 
335                                 " surface:" + Databases.SURFACE_MATERIAL.size() +
336                                 " line:" + Databases.LINE_MATERIAL.size());
337         }
338         
339         
340         private class MaterialCellRenderer extends DefaultTableCellRenderer {
341
342                 /* (non-Javadoc)
343                  * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
344                  */
345                 @Override
346                 public Component getTableCellRendererComponent(JTable table, Object value,
347                                 boolean isSelected, boolean hasFocus, int row, int column) {
348                         Component c = super.getTableCellRendererComponent(table, value, isSelected, 
349                                         hasFocus, row, column);
350                         if (c instanceof JLabel) {
351                                 JLabel label = (JLabel)c;
352                                 Material m = getMaterial(row);
353                                 
354                                 if (isSelected) {
355                                         if (m.isUserDefined())
356                                                 label.setForeground(table.getSelectionForeground());
357                                         else
358                                                 label.setForeground(Color.GRAY);
359                                 } else {
360                                         if (m.isUserDefined())
361                                                 label.setForeground(table.getForeground());
362                                         else
363                                                 label.setForeground(Color.GRAY);
364                                 }
365                         }
366                         return c;
367                 }
368                 
369         }
370
371 }