updates for 0.9.4
[debian/openrocket] / src / net / sf / openrocket / gui / dialogs / preferences / MaterialEditPanel.java
diff --git a/src/net/sf/openrocket/gui/dialogs/preferences/MaterialEditPanel.java b/src/net/sf/openrocket/gui/dialogs/preferences/MaterialEditPanel.java
new file mode 100644 (file)
index 0000000..e6d66f4
--- /dev/null
@@ -0,0 +1,371 @@
+package net.sf.openrocket.gui.dialogs.preferences;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Iterator;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.DefaultTableCellRenderer;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.database.Database;
+import net.sf.openrocket.database.Databases;
+import net.sf.openrocket.gui.adaptors.Column;
+import net.sf.openrocket.gui.adaptors.ColumnTableModel;
+import net.sf.openrocket.gui.dialogs.CustomMaterialDialog;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.unit.Value;
+
+public class MaterialEditPanel extends JPanel {
+
+       private final JTable table;
+       
+       private final JButton addButton;
+       private final JButton editButton;
+       private final JButton deleteButton;
+       private final JButton revertButton;
+       
+       
+       public MaterialEditPanel() {
+               super(new MigLayout("fill"));
+               
+               
+               // TODO: LOW: Create sorter that keeps material types always in order
+               final ColumnTableModel model = new ColumnTableModel(
+                               new Column("Material") {
+                                       @Override
+                                       public Object getValueAt(int row) {
+                                               return getMaterial(row).getName();
+                                       }
+                               },
+                               
+                               new Column("Type") {
+                                       @Override
+                                       public Object getValueAt(int row) {
+                                               return getMaterial(row).getType().toString();
+                                       }
+                                       @Override
+                                       public int getDefaultWidth() {
+                                               return 15;
+                                       }
+                               },
+                               
+                               new Column("Density") {
+                                       @Override
+                                       public Object getValueAt(int row) {
+                                               Material m = getMaterial(row);
+                                               double d = m.getDensity();
+                                               switch (m.getType()) {
+                                               case LINE:
+                                                       return UnitGroup.UNITS_DENSITY_LINE.toValue(d);
+                                                       
+                                               case SURFACE:
+                                                       return UnitGroup.UNITS_DENSITY_SURFACE.toValue(d);
+                                                       
+                                               case BULK:
+                                                       return UnitGroup.UNITS_DENSITY_BULK.toValue(d);
+                                                       
+                                               default:
+                                                       throw new IllegalStateException("Material type " + m.getType());
+                                               }
+                                       }
+                                       @Override
+                                       public int getDefaultWidth() {
+                                               return 15;
+                                       }
+                                       @Override
+                                       public Class<?> getColumnClass() {
+                                               return Value.class;
+                                       }
+                               }
+               ) {
+                       @Override
+                       public int getRowCount() {
+                               return Databases.BULK_MATERIAL.size() + Databases.SURFACE_MATERIAL.size() +
+                                       Databases.LINE_MATERIAL.size();
+                       }
+               };
+               
+               table = new JTable(model);
+               model.setColumnWidths(table.getColumnModel());
+               table.setAutoCreateRowSorter(true);
+               table.setDefaultRenderer(Object.class, new MaterialCellRenderer());
+               this.add(new JScrollPane(table), "w 200px, h 100px, grow 100");
+               
+               
+               
+               addButton = new JButton("New");
+               addButton.setToolTipText("Add a new material");
+               addButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               CustomMaterialDialog dialog = new CustomMaterialDialog(
+                                                       SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
+                                                       null, false, "Add a custom material");
+                               dialog.setVisible(true);
+                               if (dialog.getOkClicked()) {
+                                       Material mat = dialog.getMaterial();
+                                       getDatabase(mat).add(mat);
+                                       model.fireTableDataChanged();
+                                       setButtonStates();
+                               }
+                       }
+               });
+               this.add(addButton, "gap rel rel para para, w 70lp, split 5, flowy, growx 1, top");
+               
+               
+               editButton = new JButton("Edit");
+               editButton.setToolTipText("Edit an existing material");
+               editButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               int sel = table.getSelectedRow();
+                               if (sel < 0)
+                                       return;
+                               sel = table.convertRowIndexToModel(sel);
+                               Material m = getMaterial(sel);
+                               
+                               CustomMaterialDialog dialog;
+                               if (m.isUserDefined()) {
+                                       dialog = new CustomMaterialDialog(
+                                                       SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
+                                                       m, false, "Edit material");
+                               } else {
+                                       dialog = new CustomMaterialDialog(
+                                                       SwingUtilities.getWindowAncestor(MaterialEditPanel.this),
+                                                       m, false, "Add a custom material", 
+                                                       "The built-in materials cannot be modified.");
+                               }
+                               
+                               dialog.setVisible(true);
+                               
+                               if (dialog.getOkClicked()) {
+                                       if (m.isUserDefined()) {
+                                               getDatabase(m).remove(m);
+                                       }
+                                       Material mat = dialog.getMaterial();
+                                       getDatabase(mat).add(mat);
+                                       model.fireTableDataChanged();
+                                       setButtonStates();
+                               }
+                       }
+               });
+               this.add(editButton, "gap rel rel para para, growx 1, top");
+               
+               
+               deleteButton = new JButton("Delete");
+               deleteButton.setToolTipText("Delete a user-defined material");
+               deleteButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               int sel = table.getSelectedRow();
+                               if (sel < 0)
+                                       return;
+                               sel = table.convertRowIndexToModel(sel);
+                               Material m = getMaterial(sel);
+                               if (!m.isUserDefined())
+                                       return;
+                               getDatabase(m).remove(m);
+                               model.fireTableDataChanged();
+                               setButtonStates();
+                       }
+               });
+               this.add(deleteButton, "gap rel rel para para, growx 1, top");
+               
+               
+               this.add(new JPanel(), "grow 1");
+               
+               revertButton = new JButton("Revert all");
+               revertButton.setToolTipText("Delete all user-defined materials");
+               revertButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               int sel = JOptionPane.showConfirmDialog(MaterialEditPanel.this, 
+                                               "Delete all user-defined materials?", "Revert all?", 
+                                               JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
+                               if (sel == JOptionPane.YES_OPTION) {
+                                       Iterator<Material> iterator;
+
+                                       iterator = Databases.LINE_MATERIAL.iterator();
+                                       while (iterator.hasNext()) {
+                                               if (iterator.next().isUserDefined())
+                                                       iterator.remove();
+                                       }
+
+                                       iterator = Databases.SURFACE_MATERIAL.iterator();
+                                       while (iterator.hasNext()) {
+                                               if (iterator.next().isUserDefined())
+                                                       iterator.remove();
+                                       }
+
+                                       iterator = Databases.BULK_MATERIAL.iterator();
+                                       while (iterator.hasNext()) {
+                                               if (iterator.next().isUserDefined())
+                                                       iterator.remove();
+                                       }
+                                       model.fireTableDataChanged();
+                                       setButtonStates();
+                               }
+                       }
+               });
+               this.add(revertButton, "gap rel rel para para, growx 1, bottom, wrap");
+               
+               setButtonStates();
+               table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+                       @Override
+                       public void valueChanged(ListSelectionEvent e) {
+                               setButtonStates();
+                       }
+               });
+               table.addMouseListener(new MouseAdapter() {
+                       @Override
+                       public void mouseClicked(MouseEvent e) {
+                               if (e.getClickCount() == 2) {
+                                       editButton.doClick();
+                               }
+                       }
+               });
+               
+               
+               this.add(new JLabel("<html><i>Editing materials will not affect existing " +
+                               "rocket designs.</i>"), "span");
+               
+               
+       }
+       
+       
+       private Database<Material> getDatabase(Material m) {
+               switch (m.getType()) {
+               case BULK:
+                       return Databases.BULK_MATERIAL;
+                       
+               case SURFACE:
+                       return Databases.SURFACE_MATERIAL;
+                       
+               case LINE:
+                       return Databases.LINE_MATERIAL;
+
+               default:
+                       throw new IllegalArgumentException("Material type invalid, m="+m);
+               }
+       }
+       
+       
+       private void setButtonStates() {
+               int sel = table.getSelectedRow();
+               
+               // Add button always enabled
+               addButton.setEnabled(true);
+               
+               // Edit button enabled if a material is selected
+               editButton.setEnabled(sel >= 0);
+               
+               // Delete button enabled if a user-defined material is selected
+               if (sel >= 0) {
+                       int modelRow = table.convertRowIndexToModel(sel);
+                       deleteButton.setEnabled(getMaterial(modelRow).isUserDefined());
+               } else {
+                       deleteButton.setEnabled(false);
+               }
+
+               // Revert button enabled if any user-defined material exists
+               boolean found = false;
+               
+               for (Material m: Databases.BULK_MATERIAL) {
+                       if (m.isUserDefined()) {
+                               found = true;
+                               break;
+                       }
+               }
+               if (!found) {
+                       for (Material m: Databases.SURFACE_MATERIAL) {
+                               if (m.isUserDefined()) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+               }
+               if (!found) {
+                       for (Material m: Databases.LINE_MATERIAL) {
+                               if (m.isUserDefined()) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+               }
+               revertButton.setEnabled(found);
+               
+       }
+       
+       private Material getMaterial(int origRow) {
+               int row = origRow;
+               int n;
+               
+               n = Databases.BULK_MATERIAL.size();
+               if (row < n) {
+                       return Databases.BULK_MATERIAL.get(row);
+               }
+               row -= n;
+               
+               n = Databases.SURFACE_MATERIAL.size();
+               if (row < n) {
+                       return Databases.SURFACE_MATERIAL.get(row);
+               }
+               row -= n;
+               
+               n = Databases.LINE_MATERIAL.size();
+               if (row < n) {
+                       return Databases.LINE_MATERIAL.get(row);
+               }
+               throw new IndexOutOfBoundsException("row="+origRow+" while material count" +
+                               " bulk:" + Databases.BULK_MATERIAL.size() + 
+                               " surface:" + Databases.SURFACE_MATERIAL.size() +
+                               " line:" + Databases.LINE_MATERIAL.size());
+       }
+       
+       
+       private class MaterialCellRenderer extends DefaultTableCellRenderer {
+
+               /* (non-Javadoc)
+                * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
+                */
+               @Override
+               public Component getTableCellRendererComponent(JTable table, Object value,
+                               boolean isSelected, boolean hasFocus, int row, int column) {
+                       Component c = super.getTableCellRendererComponent(table, value, isSelected, 
+                                       hasFocus, row, column);
+                       if (c instanceof JLabel) {
+                               JLabel label = (JLabel)c;
+                               Material m = getMaterial(row);
+                               
+                               if (isSelected) {
+                                       if (m.isUserDefined())
+                                               label.setForeground(table.getSelectionForeground());
+                                       else
+                                               label.setForeground(Color.GRAY);
+                               } else {
+                                       if (m.isUserDefined())
+                                               label.setForeground(table.getForeground());
+                                       else
+                                               label.setForeground(Color.GRAY);
+                               }
+                       }
+                       return c;
+               }
+               
+       }
+
+}