1 package net.sf.openrocket.gui.dialogs.preferences;
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;
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;
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;
34 public class MaterialEditPanel extends JPanel {
36 private final JTable table;
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();
45 public MaterialEditPanel() {
46 super(new MigLayout("fill"));
49 // TODO: LOW: Create sorter that keeps material types always in order
50 final ColumnTableModel model = new ColumnTableModel(
52 new Column(trans.get("matedtpan.col.Material")) {
54 public Object getValueAt(int row) {
55 return getMaterial(row).getName();
59 new Column(trans.get("matedtpan.col.Type")) {
61 public Object getValueAt(int row) {
62 return getMaterial(row).getType().toString();
65 public int getDefaultWidth() {
70 new Column(trans.get("matedtpan.col.Density")) {
72 public Object getValueAt(int row) {
73 Material m = getMaterial(row);
74 double d = m.getDensity();
75 switch (m.getType()) {
77 return UnitGroup.UNITS_DENSITY_LINE.toValue(d);
80 return UnitGroup.UNITS_DENSITY_SURFACE.toValue(d);
83 return UnitGroup.UNITS_DENSITY_BULK.toValue(d);
86 throw new IllegalStateException("Material type " + m.getType());
90 public int getDefaultWidth() {
94 public Class<?> getColumnClass() {
100 public int getRowCount() {
101 return Databases.BULK_MATERIAL.size() + Databases.SURFACE_MATERIAL.size() +
102 Databases.LINE_MATERIAL.size();
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");
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() {
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();
133 this.add(addButton, "gap rel rel para para, w 70lp, split 5, flowy, growx 1, top");
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() {
141 public void actionPerformed(ActionEvent e) {
142 int sel = table.getSelectedRow();
145 sel = table.convertRowIndexToModel(sel);
146 Material m = getMaterial(sel);
148 CustomMaterialDialog dialog;
149 if (m.isUserDefined()) {
150 dialog = new CustomMaterialDialog(
151 SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
153 m, false, trans.get("matedtpan.title.Editmaterial"));
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"));
163 dialog.setVisible(true);
165 if (dialog.getOkClicked()) {
166 if (m.isUserDefined()) {
167 getDatabase(m).remove(m);
169 Material mat = dialog.getMaterial();
170 getDatabase(mat).add(mat);
171 model.fireTableDataChanged();
176 this.add(editButton, "gap rel rel para para, growx 1, top");
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() {
184 public void actionPerformed(ActionEvent e) {
185 int sel = table.getSelectedRow();
188 sel = table.convertRowIndexToModel(sel);
189 Material m = getMaterial(sel);
190 if (!m.isUserDefined())
192 getDatabase(m).remove(m);
193 model.fireTableDataChanged();
197 this.add(deleteButton, "gap rel rel para para, growx 1, top");
200 this.add(new JPanel(), "grow 1");
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() {
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"),
213 trans.get("matedtpan.title.Revertall"),
214 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
215 if (sel == JOptionPane.YES_OPTION) {
216 Iterator<Material> iterator;
218 iterator = Databases.LINE_MATERIAL.iterator();
219 while (iterator.hasNext()) {
220 if (iterator.next().isUserDefined())
224 iterator = Databases.SURFACE_MATERIAL.iterator();
225 while (iterator.hasNext()) {
226 if (iterator.next().isUserDefined())
230 iterator = Databases.BULK_MATERIAL.iterator();
231 while (iterator.hasNext()) {
232 if (iterator.next().isUserDefined())
235 model.fireTableDataChanged();
240 this.add(revertButton, "gap rel rel para para, growx 1, bottom, wrap");
243 table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
245 public void valueChanged(ListSelectionEvent e) {
249 table.addMouseListener(new MouseAdapter() {
251 public void mouseClicked(MouseEvent e) {
252 if (e.getClickCount() == 2) {
253 editButton.doClick();
258 //// <html><i>Editing materials will not affect existing
259 //// rocket designs.</i>
260 this.add(new JLabel(trans.get("matedtpan.lbl.edtmaterials")), "span");
266 private Database<Material> getDatabase(Material m) {
267 switch (m.getType()) {
269 return Databases.BULK_MATERIAL;
272 return Databases.SURFACE_MATERIAL;
275 return Databases.LINE_MATERIAL;
278 throw new IllegalArgumentException("Material type invalid, m="+m);
283 private void setButtonStates() {
284 int sel = table.getSelectedRow();
286 // Add button always enabled
287 addButton.setEnabled(true);
289 // Edit button enabled if a material is selected
290 editButton.setEnabled(sel >= 0);
292 // Delete button enabled if a user-defined material is selected
294 int modelRow = table.convertRowIndexToModel(sel);
295 deleteButton.setEnabled(getMaterial(modelRow).isUserDefined());
297 deleteButton.setEnabled(false);
300 // Revert button enabled if any user-defined material exists
301 boolean found = false;
303 for (Material m: Databases.BULK_MATERIAL) {
304 if (m.isUserDefined()) {
310 for (Material m: Databases.SURFACE_MATERIAL) {
311 if (m.isUserDefined()) {
318 for (Material m: Databases.LINE_MATERIAL) {
319 if (m.isUserDefined()) {
325 revertButton.setEnabled(found);
329 private Material getMaterial(int origRow) {
333 n = Databases.BULK_MATERIAL.size();
335 return Databases.BULK_MATERIAL.get(row);
339 n = Databases.SURFACE_MATERIAL.size();
341 return Databases.SURFACE_MATERIAL.get(row);
345 n = Databases.LINE_MATERIAL.size();
347 return Databases.LINE_MATERIAL.get(row);
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());
356 private class MaterialCellRenderer extends DefaultTableCellRenderer {
359 * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
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);
371 if (m.isUserDefined())
372 label.setForeground(table.getSelectionForeground());
374 label.setForeground(Color.GRAY);
376 if (m.isUserDefined())
377 label.setForeground(table.getForeground());
379 label.setForeground(Color.GRAY);