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