]> git.gag.com Git - debian/openrocket/blob - core/src/net/sf/openrocket/gui/preset/ComponentPresetPanel.java
Added delete button to preset row in table.
[debian/openrocket] / core / src / net / sf / openrocket / gui / preset / ComponentPresetPanel.java
1 package net.sf.openrocket.gui.preset;
2
3 import net.miginfocom.swing.MigLayout;
4 import net.sf.openrocket.gui.util.FileHelper;
5 import net.sf.openrocket.gui.util.Icons;
6 import net.sf.openrocket.gui.util.SwingPreferences;
7 import net.sf.openrocket.l10n.ResourceBundleTranslator;
8 import net.sf.openrocket.logging.LogHelper;
9 import net.sf.openrocket.material.Material;
10 import net.sf.openrocket.preset.ComponentPreset;
11 import net.sf.openrocket.preset.xml.OpenRocketComponentSaver;
12 import net.sf.openrocket.startup.Application;
13
14 import javax.swing.AbstractAction;
15 import javax.swing.Action;
16 import javax.swing.JButton;
17 import javax.swing.JDialog;
18 import javax.swing.JFileChooser;
19 import javax.swing.JFrame;
20 import javax.swing.JLabel;
21 import javax.swing.JOptionPane;
22 import javax.swing.JPanel;
23 import javax.swing.JScrollPane;
24 import javax.swing.JTable;
25 import javax.swing.SwingConstants;
26 import javax.swing.table.DefaultTableModel;
27 import javax.xml.bind.JAXBException;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ActionListener;
30 import java.awt.event.MouseAdapter;
31 import java.awt.event.MouseEvent;
32 import java.io.File;
33 import java.io.IOException;
34 import java.util.ArrayList;
35 import java.util.List;
36
37 /**
38  * A UI for editing component presets.  Currently this is a standalone application - run the main within this class.
39  * TODO: Full I18n
40  * TODO: Open .orc for editing
41  * TODO: Open .csv
42  * TODO: Save As .csv
43  * TODO: Menu
44  */
45 public class ComponentPresetPanel extends JPanel implements PresetResultListener {
46
47     /**
48      * The logger.
49      */
50     private static final LogHelper log = Application.getLogger();
51
52     /**
53      * The I18N translator.
54      */
55     private static ResourceBundleTranslator trans = null;
56
57     /**
58      * The table of presets.
59      */
60     private JTable table;
61
62     /**
63      * The table's data model.
64      */
65     private DataTableModel model;
66
67     /**
68      * Flag that indicates if an existing Preset is currently being edited.
69      */
70     private boolean editingSelected = false;
71
72     static {
73         trans = new ResourceBundleTranslator("l10n.messages");
74         net.sf.openrocket.startup.Application.setBaseTranslator(trans);
75     }
76
77     /**
78      * Create the panel.
79      */
80     public ComponentPresetPanel() {
81         setLayout(new MigLayout("", "[82.00px][168.00px][84px][117.00px][][222px]", "[346.00px][29px]"));
82
83         model = new DataTableModel(new String[]{"Manufacturer", "Type", "Part No", "Description", ""});
84
85         table = new JTable(model);
86         table.getTableHeader().setFont(new JLabel().getFont());
87         //The action never gets called because the table MouseAdapter intercepts it first.  Still need an empty
88         // instance though.
89         Action action = new AbstractAction() {
90             @Override
91             public void actionPerformed(final ActionEvent e) {
92             }
93         };
94         //Create a editor/renderer for the delete operation.  Instantiation self-registers into the table.
95         new ButtonColumn(table, action, 4);
96         table.getColumnModel().getColumn(4).setMaxWidth(Icons.EDIT_DELETE.getIconWidth());
97         table.getColumnModel().getColumn(4).setMinWidth(Icons.EDIT_DELETE.getIconWidth());
98
99         JScrollPane scrollPane = new JScrollPane(table);
100         table.setFillsViewportHeight(true);
101         table.setAutoCreateRowSorter(true);
102         add(scrollPane, "cell 0 0 6 1,grow");
103
104         table.addMouseListener(new MouseAdapter() {
105             public void mouseClicked(MouseEvent e) {
106                 JTable target = (JTable) e.getSource();
107                 if (target.getSelectedColumn() == 4) {
108                     if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(ComponentPresetPanel.this,
109                             "Do you want to delete this preset?",
110                             "Confirm Delete", JOptionPane.YES_OPTION,
111                             JOptionPane.QUESTION_MESSAGE)) {
112                         model.removeRow(target.getSelectedRow());
113                     }
114                 }
115                 else {
116                     if (e.getClickCount() == 2) {
117                         int row = target.getSelectedRow();
118                         editingSelected = true;
119                         new PresetEditorDialog(ComponentPresetPanel.this, (ComponentPreset) model.getAssociatedObject(row)).setVisible(true);
120                     }
121                 }
122             }
123         });
124         JButton addBtn = new JButton("Add");
125         addBtn.addMouseListener(new MouseAdapter() {
126             @Override
127             public void mouseClicked(MouseEvent arg0) {
128                 editingSelected = false;
129                 new PresetEditorDialog(ComponentPresetPanel.this).setVisible(true);
130             }
131         });
132         add(addBtn, "cell 0 1,alignx left,aligny top");
133
134         JButton saveBtn = new JButton("Save...");
135         saveBtn.setHorizontalAlignment(SwingConstants.RIGHT);
136         add(saveBtn, "flowx,cell 5 1,alignx right,aligny center");
137         saveBtn.addActionListener(new ActionListener() {
138             @Override
139             public void actionPerformed(final ActionEvent e) {
140                 try {
141                     saveAsORC();
142                 }
143                 catch (Exception e1) {
144                     JOptionPane.showMessageDialog(ComponentPresetPanel.this, e1.getLocalizedMessage(),
145                             "Error saving ORC file.", JOptionPane.ERROR_MESSAGE);
146                 }
147             }
148         });
149
150         JButton cancelBtn = new JButton("Cancel");
151         cancelBtn.setHorizontalAlignment(SwingConstants.RIGHT);
152         add(cancelBtn, "cell 5 1,alignx right,aligny top");
153         cancelBtn.addActionListener(new ActionListener() {
154             @Override
155             public void actionPerformed(final ActionEvent e) {
156                 System.exit(0);
157             }
158         });
159
160     }
161
162     /**
163      * Callback method from the PresetEditorDialog to notify this class when a preset has been saved.  The 'save' is
164      * really just a call back here so the preset can be added to the master table.  It's not to be confused with the
165      * save to disk.
166      *
167      * @param preset the new or modified preset
168      */
169     @Override
170     public void notifyResult(final ComponentPreset preset) {
171         if (preset != null) {
172             DataTableModel model = (DataTableModel) table.getModel();
173             //Is this a new preset?
174             if (!editingSelected) {
175                 model.addRow(new Object[]{preset.getManufacturer().getDisplayName(), preset.getType().name(),
176                         preset.getPartNo(), preset.get(ComponentPreset.DESCRIPTION), Icons.EDIT_DELETE}, preset);
177             }
178             else {
179                 //This is a modified preset; update all of the columns and the stored associated instance.
180                 int row = table.getSelectedRow();
181                 model.setValueAt(preset.getManufacturer().getDisplayName(), row, 0);
182                 model.setValueAt(preset.getType().name(), row, 1);
183                 model.setValueAt(preset.getPartNo(), row, 2);
184                 model.setValueAt(preset.get(ComponentPreset.DESCRIPTION), row, 3);
185                 model.associated.set(row, preset);
186             }
187         }
188         editingSelected = false;
189     }
190
191     /**
192      * Launch the test main.
193      */
194     public static void main(String[] args) {
195         try {
196             Application.setPreferences(new SwingPreferences());
197             JFrame dialog = new JFrame();
198             dialog.getContentPane().add(new ComponentPresetPanel());
199             dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
200             dialog.pack();
201             dialog.setVisible(true);
202         }
203         catch (Exception e) {
204             e.printStackTrace();
205         }
206     }
207
208     /**
209      * A table model that adds associated objects to each row, allowing for easy retrieval.
210      */
211     class DataTableModel extends DefaultTableModel {
212
213         private List<Object> associated = new ArrayList<Object>();
214
215         /**
216          * Constructs a <code>DefaultTableModel</code> with as many columns as there are elements in
217          * <code>columnNames</code> and <code>rowCount</code> of <code>null</code> object values.  Each column's name
218          * will be taken from the <code>columnNames</code> array.
219          *
220          * @param columnNames <code>array</code> containing the names of the new columns; if this is <code>null</code>
221          *                    then the model has no columns
222          *
223          * @see #setDataVector
224          * @see #setValueAt
225          */
226         DataTableModel(final Object[] columnNames) {
227             super(columnNames, 0);
228         }
229
230         public void addRow(Object[] data, Object associatedData) {
231             super.addRow(data);
232             associated.add(getRowCount() - 1, associatedData);
233         }
234
235         public void removeRow(int row) {
236             super.removeRow(row);
237             associated.remove(row);
238         }
239
240         public Object getAssociatedObject(int row) {
241             return associated.get(row);
242         }
243
244         public boolean isCellEditable(int rowIndex, int mColIndex) {
245             return false;
246         }
247     }
248
249     private boolean saveAsORC() throws JAXBException, IOException {
250         File file = null;
251
252         final JFileChooser chooser = new JFileChooser();
253         chooser.addChoosableFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
254
255         chooser.setFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
256         chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
257
258         int option = chooser.showSaveDialog(ComponentPresetPanel.this);
259         if (option != JFileChooser.APPROVE_OPTION) {
260             log.user("User decided not to save, option=" + option);
261             return false;
262         }
263
264         file = chooser.getSelectedFile();
265         if (file == null) {
266             log.user("User did not select a file");
267             return false;
268         }
269
270         ((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
271
272         file = FileHelper.forceExtension(file, "orc");
273
274         List<Material> materials = new ArrayList<Material>();
275         List<ComponentPreset> presets = new ArrayList<ComponentPreset>();
276
277         for (int x = 0; x < model.getRowCount(); x++) {
278             ComponentPreset preset = (ComponentPreset) model.getAssociatedObject(x);
279             if (!materials.contains(preset.get(ComponentPreset.MATERIAL))) {
280                 materials.add(preset.get(ComponentPreset.MATERIAL));
281             }
282             presets.add(preset);
283         }
284
285         return FileHelper.confirmWrite(file, this) && new OpenRocketComponentSaver().save(file, materials, presets);
286     }
287 }