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.material.Material;
29 import net.sf.openrocket.unit.UnitGroup;
30 import net.sf.openrocket.unit.Value;
32 public class MaterialEditPanel extends JPanel {
34 private final JTable table;
36 private final JButton addButton;
37 private final JButton editButton;
38 private final JButton deleteButton;
39 private final JButton revertButton;
42 public MaterialEditPanel() {
43 super(new MigLayout("fill"));
46 // TODO: LOW: Create sorter that keeps material types always in order
47 final ColumnTableModel model = new ColumnTableModel(
48 new Column("Material") {
50 public Object getValueAt(int row) {
51 return getMaterial(row).getName();
57 public Object getValueAt(int row) {
58 return getMaterial(row).getType().toString();
61 public int getDefaultWidth() {
66 new Column("Density") {
68 public Object getValueAt(int row) {
69 Material m = getMaterial(row);
70 double d = m.getDensity();
71 switch (m.getType()) {
73 return UnitGroup.UNITS_DENSITY_LINE.toValue(d);
76 return UnitGroup.UNITS_DENSITY_SURFACE.toValue(d);
79 return UnitGroup.UNITS_DENSITY_BULK.toValue(d);
82 throw new IllegalStateException("Material type " + m.getType());
86 public int getDefaultWidth() {
90 public Class<?> getColumnClass() {
96 public int getRowCount() {
97 return Databases.BULK_MATERIAL.size() + Databases.SURFACE_MATERIAL.size() +
98 Databases.LINE_MATERIAL.size();
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");
110 addButton = new JButton("New");
111 addButton.setToolTipText("Add a new material");
112 addButton.addActionListener(new ActionListener() {
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();
127 this.add(addButton, "gap rel rel para para, w 70lp, split 5, flowy, growx 1, top");
130 editButton = new JButton("Edit");
131 editButton.setToolTipText("Edit an existing material");
132 editButton.addActionListener(new ActionListener() {
134 public void actionPerformed(ActionEvent e) {
135 int sel = table.getSelectedRow();
138 sel = table.convertRowIndexToModel(sel);
139 Material m = getMaterial(sel);
141 CustomMaterialDialog dialog;
142 if (m.isUserDefined()) {
143 dialog = new CustomMaterialDialog(
144 SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
145 m, false, "Edit material");
147 dialog = new CustomMaterialDialog(
148 SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
149 m, false, "Add a custom material",
150 "The built-in materials cannot be modified.");
153 dialog.setVisible(true);
155 if (dialog.getOkClicked()) {
156 if (m.isUserDefined()) {
157 getDatabase(m).remove(m);
159 Material mat = dialog.getMaterial();
160 getDatabase(mat).add(mat);
161 model.fireTableDataChanged();
166 this.add(editButton, "gap rel rel para para, growx 1, top");
169 deleteButton = new JButton("Delete");
170 deleteButton.setToolTipText("Delete a user-defined material");
171 deleteButton.addActionListener(new ActionListener() {
173 public void actionPerformed(ActionEvent e) {
174 int sel = table.getSelectedRow();
177 sel = table.convertRowIndexToModel(sel);
178 Material m = getMaterial(sel);
179 if (!m.isUserDefined())
181 getDatabase(m).remove(m);
182 model.fireTableDataChanged();
186 this.add(deleteButton, "gap rel rel para para, growx 1, top");
189 this.add(new JPanel(), "grow 1");
191 revertButton = new JButton("Revert all");
192 revertButton.setToolTipText("Delete all user-defined materials");
193 revertButton.addActionListener(new ActionListener() {
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;
202 iterator = Databases.LINE_MATERIAL.iterator();
203 while (iterator.hasNext()) {
204 if (iterator.next().isUserDefined())
208 iterator = Databases.SURFACE_MATERIAL.iterator();
209 while (iterator.hasNext()) {
210 if (iterator.next().isUserDefined())
214 iterator = Databases.BULK_MATERIAL.iterator();
215 while (iterator.hasNext()) {
216 if (iterator.next().isUserDefined())
219 model.fireTableDataChanged();
224 this.add(revertButton, "gap rel rel para para, growx 1, bottom, wrap");
227 table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
229 public void valueChanged(ListSelectionEvent e) {
233 table.addMouseListener(new MouseAdapter() {
235 public void mouseClicked(MouseEvent e) {
236 if (e.getClickCount() == 2) {
237 editButton.doClick();
243 this.add(new JLabel("<html><i>Editing materials will not affect existing " +
244 "rocket designs.</i>"), "span");
250 private Database<Material> getDatabase(Material m) {
251 switch (m.getType()) {
253 return Databases.BULK_MATERIAL;
256 return Databases.SURFACE_MATERIAL;
259 return Databases.LINE_MATERIAL;
262 throw new IllegalArgumentException("Material type invalid, m="+m);
267 private void setButtonStates() {
268 int sel = table.getSelectedRow();
270 // Add button always enabled
271 addButton.setEnabled(true);
273 // Edit button enabled if a material is selected
274 editButton.setEnabled(sel >= 0);
276 // Delete button enabled if a user-defined material is selected
278 int modelRow = table.convertRowIndexToModel(sel);
279 deleteButton.setEnabled(getMaterial(modelRow).isUserDefined());
281 deleteButton.setEnabled(false);
284 // Revert button enabled if any user-defined material exists
285 boolean found = false;
287 for (Material m: Databases.BULK_MATERIAL) {
288 if (m.isUserDefined()) {
294 for (Material m: Databases.SURFACE_MATERIAL) {
295 if (m.isUserDefined()) {
302 for (Material m: Databases.LINE_MATERIAL) {
303 if (m.isUserDefined()) {
309 revertButton.setEnabled(found);
313 private Material getMaterial(int origRow) {
317 n = Databases.BULK_MATERIAL.size();
319 return Databases.BULK_MATERIAL.get(row);
323 n = Databases.SURFACE_MATERIAL.size();
325 return Databases.SURFACE_MATERIAL.get(row);
329 n = Databases.LINE_MATERIAL.size();
331 return Databases.LINE_MATERIAL.get(row);
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());
340 private class MaterialCellRenderer extends DefaultTableCellRenderer {
343 * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
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);
355 if (m.isUserDefined())
356 label.setForeground(table.getSelectionForeground());
358 label.setForeground(Color.GRAY);
360 if (m.isUserDefined())
361 label.setForeground(table.getForeground());
363 label.setForeground(Color.GRAY);