1 package net.sf.openrocket.gui.preset;
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;
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;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.List;
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
36 public class ComponentPresetPanel extends JPanel implements PresetResultListener {
41 private static final LogHelper log = Application.getLogger();
44 * The I18N translator.
46 private static ResourceBundleTranslator trans = null;
49 * The table of presets.
54 * The table's data model.
56 private DataTableModel model;
59 * Flag that indicates if an existing Preset is currently being edited.
61 private boolean editingSelected = false;
64 trans = new ResourceBundleTranslator("l10n.messages");
65 net.sf.openrocket.startup.Application.setBaseTranslator(trans);
71 public ComponentPresetPanel() {
72 setLayout(new MigLayout("", "[82.00px][168.00px][84px][117.00px][][222px]", "[346.00px][29px]"));
74 model = new DataTableModel(new String[]{"Manufacturer", "Type", "Part No", "Description"});
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");
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);
92 JButton addBtn = new JButton("Add");
93 addBtn.addMouseListener(new MouseAdapter() {
95 public void mouseClicked(MouseEvent arg0) {
96 editingSelected = false;
97 new PresetEditorDialog(ComponentPresetPanel.this).setVisible(true);
100 add(addBtn, "cell 0 1,alignx left,aligny top");
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() {
107 public void actionPerformed(final ActionEvent e) {
111 catch (JAXBException e1) {
113 e1.printStackTrace();
115 catch (IOException e1) {
117 e1.printStackTrace();
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() {
127 public void actionPerformed(final ActionEvent e) {
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
139 * @param preset the new or modified preset
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);
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);
159 editingSelected = false;
163 * Launch the test main.
165 public static void main(String[] args) {
167 Application.setPreferences(new SwingPreferences());
168 JFrame dialog = new JFrame();
169 dialog.getContentPane().add(new ComponentPresetPanel());
170 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
172 dialog.setVisible(true);
174 catch (Exception e) {
180 * A table model that adds associated objects to each row, allowing for easy retrieval.
182 class DataTableModel extends DefaultTableModel {
184 private List<Object> associated = new ArrayList<Object>();
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.
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
194 * @see #setDataVector
197 DataTableModel(final Object[] columnNames) {
198 super(columnNames, 0);
201 public void addRow(Object[] data, Object associatedData) {
203 associated.add(getRowCount() - 1, associatedData);
206 public void removeRow(int row) {
207 super.removeRow(row);
208 associated.remove(row);
211 public Object getAssociatedObject(int row) {
212 return associated.get(row);
215 public boolean isCellEditable(int rowIndex, int mColIndex) {
220 private boolean saveAsORC() throws JAXBException, IOException {
223 final JFileChooser chooser = new JFileChooser();
224 chooser.addChoosableFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
226 chooser.setFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
227 chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
229 int option = chooser.showSaveDialog(ComponentPresetPanel.this);
230 if (option != JFileChooser.APPROVE_OPTION) {
231 log.user("User decided not to save, option=" + option);
235 file = chooser.getSelectedFile();
237 log.user("User did not select a file");
241 ((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory());
243 file = FileHelper.forceExtension(file, "orc");
245 List<Material> materials = new ArrayList<Material>();
246 List<ComponentPreset> presets = new ArrayList<ComponentPreset>();
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));
256 return FileHelper.confirmWrite(file, this) && new OpenRocketComponentSaver().save(file, materials, presets);