1 package net.sf.openrocket.gui.adaptors;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.awt.event.MouseAdapter;
7 import java.awt.event.MouseEvent;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.Iterator;
13 import javax.swing.ComboBoxModel;
14 import javax.swing.JButton;
15 import javax.swing.JDialog;
16 import javax.swing.JFrame;
17 import javax.swing.JLabel;
18 import javax.swing.JPanel;
19 import javax.swing.JScrollPane;
20 import javax.swing.JTable;
21 import javax.swing.JTextField;
22 import javax.swing.ListSelectionModel;
23 import javax.swing.SwingUtilities;
24 import javax.swing.event.ChangeEvent;
25 import javax.swing.event.ChangeListener;
26 import javax.swing.event.EventListenerList;
27 import javax.swing.event.ListDataEvent;
28 import javax.swing.event.ListDataListener;
29 import javax.swing.event.ListSelectionEvent;
30 import javax.swing.event.ListSelectionListener;
32 import net.miginfocom.swing.MigLayout;
33 import net.sf.openrocket.gui.ResizeLabel;
34 import net.sf.openrocket.gui.TextFieldListener;
35 import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
36 import net.sf.openrocket.rocketcomponent.Configuration;
37 import net.sf.openrocket.rocketcomponent.Motor;
38 import net.sf.openrocket.rocketcomponent.MotorMount;
39 import net.sf.openrocket.rocketcomponent.Rocket;
40 import net.sf.openrocket.rocketcomponent.RocketComponent;
41 import net.sf.openrocket.util.GUIUtil;
43 public class MotorConfigurationModel implements ComboBoxModel, ChangeListener {
45 private static final String EDIT = "Edit configurations";
48 private EventListenerList listenerList = new EventListenerList();
50 private final Configuration config;
51 private final Rocket rocket;
53 private Map<String, ID> map = new HashMap<String, ID>();
56 public MotorConfigurationModel(Configuration config) {
58 this.rocket = config.getRocket();
59 config.addChangeListener(this);
65 public Object getElementAt(int index) {
66 String[] ids = rocket.getMotorConfigurationIDs();
67 if (index < 0 || index > ids.length)
70 if (index == ids.length)
73 return get(ids[index]);
77 public int getSize() {
78 return rocket.getMotorConfigurationIDs().length + 1;
82 public Object getSelectedItem() {
83 return get(config.getMotorConfigurationID());
87 public void setSelectedItem(Object item) {
90 // Open edit dialog in the future, after combo box has closed
91 SwingUtilities.invokeLater(new Runnable() {
94 EditConfigurationDialog dialog = new EditConfigurationDialog();
95 dialog.setVisible(true);
97 if (dialog.isRowSelected()) {
98 rocket.getDefaultConfiguration().setMotorConfigurationID(
99 dialog.getSelectedID());
106 if (!(item instanceof ID))
109 ID idObject = (ID) item;
110 config.setMotorConfigurationID(idObject.getID());
115 //////////////// Event/listener handling ////////////////
119 public void addListDataListener(ListDataListener l) {
120 listenerList.add(ListDataListener.class, l);
124 public void removeListDataListener(ListDataListener l) {
125 listenerList.remove(ListDataListener.class, l);
128 protected void fireListDataEvent() {
129 Object[] listeners = listenerList.getListenerList();
130 ListDataEvent e = null;
132 for (int i = listeners.length-2; i>=0; i-=2) {
133 if (listeners[i] == ListDataListener.class) {
135 e = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, getSize());
136 ((ListDataListener) listeners[i+1]).contentsChanged(e);
143 public void stateChanged(ChangeEvent e) {
144 if (e instanceof ComponentChangeEvent) {
145 // Ignore unnecessary changes
146 if (!((ComponentChangeEvent)e).isMotorChange())
155 * The ID class is an adapter, that contains the actual configuration ID,
156 * but gives the configuration description as its String representation.
157 * The get(id) method retrieves ID objects and caches them for reuse.
160 private ID get(String id) {
161 ID idObject = map.get(id);
162 if (idObject != null)
165 idObject = new ID(id);
166 map.put(id, idObject);
172 private final String id;
174 public ID(String id) {
178 public String getID() {
183 public String toString() {
184 return rocket.getMotorConfigurationDescription(id);
189 private class EditConfigurationDialog extends JDialog {
190 private final ColumnTableModel tableModel;
191 private String[] ids;
194 private final JButton addButton;
195 private final JButton removeButton;
196 private final JTextField nameField;
198 private final JTable table;
201 public boolean isRowSelected() {
202 return selection >= 0;
205 public String getSelectedID() {
207 return ids[selection];
212 public EditConfigurationDialog() {
213 super((JFrame)null, "Edit configurations", true);
215 ids = rocket.getMotorConfigurationIDs();
218 ArrayList<Column> columnList = new ArrayList<Column>();
219 columnList.add(new Column("Name") {
221 public Object getValueAt(int row) {
222 return rocket.getMotorConfigurationDescription(ids[row]);
226 // Create columns from the motor mounts
227 Iterator<RocketComponent> iterator = rocket.deepIterator();
228 while (iterator.hasNext()) {
229 RocketComponent c = iterator.next();
230 if (!(c instanceof MotorMount))
233 final MotorMount mount = (MotorMount)c;
234 if (!mount.isMotorMount())
237 Column col = new Column(c.getName()) {
239 public Object getValueAt(int row) {
240 Motor motor = mount.getMotor(ids[row]);
243 return motor.getDesignation(mount.getMotorDelay(ids[row]));
248 tableModel = new ColumnTableModel(columnList.toArray(new Column[0])) {
250 public int getRowCount() {
258 JPanel panel = new JPanel(new MigLayout("fill","[shrink][grow]"));
261 panel.add(new JLabel("Configuration name:"), "gapright para");
262 nameField = new JTextField();
263 new TextFieldListener() {
265 public void setText(String text) {
266 if (selection < 0 || ids[selection] == null)
268 rocket.setMotorConfigurationName(ids[selection], text);
271 }.listenTo(nameField);
272 panel.add(nameField, "growx, wrap");
274 panel.add(new ResizeLabel("Leave empty for default description", -2),
275 "skip, growx, wrap para");
278 table = new JTable(tableModel);
279 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
280 table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
282 public void valueChanged(ListSelectionEvent e) {
287 // Mouse listener to act on double-clicks
288 table.addMouseListener(new MouseAdapter() {
290 public void mouseClicked(MouseEvent e) {
291 if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
292 EditConfigurationDialog.this.dispose();
299 JScrollPane scrollpane = new JScrollPane(table);
300 panel.add(scrollpane, "spanx, height 150lp, width 400lp, grow, wrap");
303 addButton = new JButton("New");
304 addButton.addActionListener(new ActionListener() {
306 public void actionPerformed(ActionEvent e) {
307 String id = rocket.newMotorConfigurationID();
308 ids = rocket.getMotorConfigurationIDs();
309 tableModel.fireTableDataChanged();
311 for (sel=0; sel < ids.length; sel++) {
312 if (id.equals(ids[sel]))
315 table.getSelectionModel().addSelectionInterval(sel, sel);
318 panel.add(addButton, "growx, spanx, split 2");
320 removeButton = new JButton("Remove");
321 removeButton.addActionListener(new ActionListener() {
323 public void actionPerformed(ActionEvent e) {
324 int sel = table.getSelectedRow();
325 if (sel < 0 || sel >= ids.length || ids[sel] == null)
327 rocket.removeMotorConfigurationID(ids[sel]);
328 ids = rocket.getMotorConfigurationIDs();
329 tableModel.fireTableDataChanged();
330 if (sel >= ids.length)
332 table.getSelectionModel().addSelectionInterval(sel, sel);
335 panel.add(removeButton, "growx, wrap para");
338 JButton close = new JButton("Close");
339 close.addActionListener(new ActionListener() {
341 public void actionPerformed(ActionEvent e) {
342 EditConfigurationDialog.this.dispose();
345 panel.add(close, "spanx, alignx 100%");
347 this.getRootPane().setDefaultButton(close);
350 this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
351 GUIUtil.installEscapeCloseOperation(this);
352 this.setLocationByPlatform(true);
361 private void fireChange() {
362 int sel = table.getSelectedRow();
363 tableModel.fireTableDataChanged();
364 table.getSelectionModel().addSelectionInterval(sel, sel);
367 private void updateSelection() {
368 selection = table.getSelectedRow();
369 if (selection < 0 || ids[selection] == null) {
370 removeButton.setEnabled(false);
371 nameField.setEnabled(false);
372 nameField.setText("");
374 removeButton.setEnabled(true);
375 nameField.setEnabled(true);
376 nameField.setText(rocket.getMotorConfigurationName(ids[selection]));