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.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;
36 public class MaterialEditPanel extends JPanel {
38 private final JTable table;
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();
47 public MaterialEditPanel() {
48 super(new MigLayout("fill"));
51 // TODO: LOW: Create sorter that keeps material types always in order
52 final ColumnTableModel model = new ColumnTableModel(
54 new Column(trans.get("matedtpan.col.Material")) {
56 public Object getValueAt(int row) {
57 return getMaterial(row).getName();
61 new Column(trans.get("matedtpan.col.Type")) {
63 public Object getValueAt(int row) {
64 return getMaterial(row).getType().toString();
68 public int getDefaultWidth() {
73 new Column(trans.get("matedtpan.col.Density")) {
75 public Object getValueAt(int row) {
76 Material m = getMaterial(row);
77 double d = m.getDensity();
78 switch (m.getType()) {
80 return UnitGroup.UNITS_DENSITY_LINE.toValue(d);
83 return UnitGroup.UNITS_DENSITY_SURFACE.toValue(d);
86 return UnitGroup.UNITS_DENSITY_BULK.toValue(d);
89 throw new IllegalStateException("Material type " + m.getType());
94 public int getDefaultWidth() {
99 public Class<?> getColumnClass() {
105 public int getRowCount() {
106 return Databases.BULK_MATERIAL.size() + Databases.SURFACE_MATERIAL.size() +
107 Databases.LINE_MATERIAL.size();
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");
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() {
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();
138 this.add(addButton, "gap rel rel para para, w 70lp, split 5, flowy, growx 1, top");
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() {
146 public void actionPerformed(ActionEvent e) {
147 int sel = table.getSelectedRow();
150 sel = table.convertRowIndexToModel(sel);
151 Material m = getMaterial(sel);
153 CustomMaterialDialog dialog;
154 if (m.isUserDefined()) {
155 dialog = new CustomMaterialDialog(
156 SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
158 m, false, trans.get("matedtpan.title.Editmaterial"));
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"));
168 dialog.setVisible(true);
170 if (dialog.getOkClicked()) {
171 if (m.isUserDefined()) {
172 getDatabase(m).remove(m);
174 Material mat = dialog.getMaterial();
175 getDatabase(mat).add(mat);
176 model.fireTableDataChanged();
181 this.add(editButton, "gap rel rel para para, growx 1, top");
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() {
189 public void actionPerformed(ActionEvent e) {
190 int sel = table.getSelectedRow();
193 sel = table.convertRowIndexToModel(sel);
194 Material m = getMaterial(sel);
195 if (!m.isUserDefined())
197 getDatabase(m).remove(m);
198 model.fireTableDataChanged();
202 this.add(deleteButton, "gap rel rel para para, growx 1, top");
205 this.add(new JPanel(), "grow 1");
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() {
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"),
218 trans.get("matedtpan.title.Revertall"),
219 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
220 if (sel == JOptionPane.YES_OPTION) {
221 Iterator<Material> iterator;
223 iterator = Databases.LINE_MATERIAL.iterator();
224 while (iterator.hasNext()) {
225 if (iterator.next().isUserDefined())
229 iterator = Databases.SURFACE_MATERIAL.iterator();
230 while (iterator.hasNext()) {
231 if (iterator.next().isUserDefined())
235 iterator = Databases.BULK_MATERIAL.iterator();
236 while (iterator.hasNext()) {
237 if (iterator.next().isUserDefined())
240 model.fireTableDataChanged();
245 this.add(revertButton, "gap rel rel para para, growx 1, bottom, wrap unrel");
248 table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
250 public void valueChanged(ListSelectionEvent e) {
254 table.addMouseListener(new MouseAdapter() {
256 public void mouseClicked(MouseEvent e) {
257 if (e.getClickCount() == 2) {
258 editButton.doClick();
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");
271 private Database<Material> getDatabase(Material m) {
272 switch (m.getType()) {
274 return Databases.BULK_MATERIAL;
277 return Databases.SURFACE_MATERIAL;
280 return Databases.LINE_MATERIAL;
283 throw new IllegalArgumentException("Material type invalid, m=" + m);
288 private void setButtonStates() {
289 int sel = table.getSelectedRow();
291 // Add button always enabled
292 addButton.setEnabled(true);
294 // Edit button enabled if a material is selected
295 editButton.setEnabled(sel >= 0);
297 // Delete button enabled if a user-defined material is selected
299 int modelRow = table.convertRowIndexToModel(sel);
300 deleteButton.setEnabled(getMaterial(modelRow).isUserDefined());
302 deleteButton.setEnabled(false);
305 // Revert button enabled if any user-defined material exists
306 boolean found = false;
308 for (Material m : Databases.BULK_MATERIAL) {
309 if (m.isUserDefined()) {
315 for (Material m : Databases.SURFACE_MATERIAL) {
316 if (m.isUserDefined()) {
323 for (Material m : Databases.LINE_MATERIAL) {
324 if (m.isUserDefined()) {
330 revertButton.setEnabled(found);
334 private Material getMaterial(int origRow) {
338 n = Databases.BULK_MATERIAL.size();
340 return Databases.BULK_MATERIAL.get(row);
344 n = Databases.SURFACE_MATERIAL.size();
346 return Databases.SURFACE_MATERIAL.get(row);
350 n = Databases.LINE_MATERIAL.size();
352 return Databases.LINE_MATERIAL.get(row);
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());
361 private class MaterialCellRenderer extends DefaultTableCellRenderer {
364 * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
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);
376 if (m.isUserDefined())
377 label.setForeground(table.getSelectionForeground());
379 label.setForeground(Color.GRAY);
381 if (m.isUserDefined())
382 label.setForeground(table.getForeground());
384 label.setForeground(Color.GRAY);