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