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