updates for 0.9.3
[debian/openrocket] / src / net / sf / openrocket / gui / dialogs / EditMotorConfigurationDialog.java
1 package net.sf.openrocket.gui.dialogs;
2
3 import java.awt.Window;
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.awt.event.WindowAdapter;
9 import java.awt.event.WindowEvent;
10 import java.util.ArrayList;
11 import java.util.Iterator;
12
13 import javax.swing.JButton;
14 import javax.swing.JDialog;
15 import javax.swing.JLabel;
16 import javax.swing.JPanel;
17 import javax.swing.JScrollPane;
18 import javax.swing.JTable;
19 import javax.swing.JTextField;
20 import javax.swing.ListSelectionModel;
21 import javax.swing.event.DocumentEvent;
22 import javax.swing.event.DocumentListener;
23 import javax.swing.table.AbstractTableModel;
24 import javax.swing.table.TableColumn;
25 import javax.swing.table.TableColumnModel;
26
27 import net.miginfocom.swing.MigLayout;
28 import net.sf.openrocket.document.OpenRocketDocument;
29 import net.sf.openrocket.gui.main.BasicFrame;
30 import net.sf.openrocket.rocketcomponent.Motor;
31 import net.sf.openrocket.rocketcomponent.MotorMount;
32 import net.sf.openrocket.rocketcomponent.Rocket;
33 import net.sf.openrocket.rocketcomponent.RocketComponent;
34 import net.sf.openrocket.util.GUIUtil;
35
36 public class EditMotorConfigurationDialog extends JDialog {
37         
38         private final Rocket rocket;
39         
40         private final MotorMount[] mounts;
41
42         private final JTable configurationTable;
43         private final MotorConfigurationTableModel configurationTableModel;
44
45         
46         private final JButton newConfButton, removeConfButton;
47         private final JButton selectMotorButton, removeMotorButton;
48         private final JTextField configurationNameField;
49         
50         
51         private String currentID = null;
52         private MotorMount currentMount = null;
53         
54         // Positive when user is modifying configuration name
55         private int configurationNameModification = 0;
56         
57         public EditMotorConfigurationDialog(final Rocket rocket, Window parent) {
58                 super(parent, "Edit motor configurations");
59                 
60                 if (parent != null)
61                         this.setModalityType(ModalityType.DOCUMENT_MODAL);
62                 else
63                         this.setModalityType(ModalityType.APPLICATION_MODAL);
64                 
65                 this.rocket = rocket;
66                 
67                 ArrayList<MotorMount> mountList = new ArrayList<MotorMount>();
68                 Iterator<RocketComponent> iterator = rocket.deepIterator();
69                 while (iterator.hasNext()) {
70                         RocketComponent c = iterator.next();
71                         if (c instanceof MotorMount) {
72                                 mountList.add((MotorMount)c);
73                         }
74                 }
75                 mounts = mountList.toArray(new MotorMount[0]);
76                 
77                 
78                 
79                 JPanel panel = new JPanel(new MigLayout("fill, flowy"));
80                 
81                 
82                 ////  Motor mount selection
83                 
84                 JLabel label = new JLabel("<html><b>Motor mounts:</b>");
85                 panel.add(label, "gapbottom para");
86                 
87                 label = new JLabel("<html>Select which components function as motor mounts:");
88                 panel.add(label,"ay 100%, w 1px, growx");
89                 
90                 
91                 JTable table = new JTable(new MotorMountTableModel());
92                 table.setTableHeader(null);
93                 table.setShowVerticalLines(false);
94                 table.setRowSelectionAllowed(false);
95                 table.setColumnSelectionAllowed(false);
96                 
97                 TableColumnModel columnModel = table.getColumnModel();
98                 TableColumn col0 = columnModel.getColumn(0);
99                 int w = table.getRowHeight() + 2;
100                 col0.setMinWidth(w);
101                 col0.setPreferredWidth(w);
102                 col0.setMaxWidth(w);
103                 
104                 JScrollPane scroll = new JScrollPane(table);
105                 panel.add(scroll, "w 200lp, h 150lp, grow, wrap 20lp");
106                 
107
108                 
109                 
110                 
111                 //// Motor selection
112                 
113                 label = new JLabel("<html><b>Motor configurations:</b>");
114                 panel.add(label, "spanx, gapbottom para");
115                 
116                 
117                 label = new JLabel("Configuration name:");
118                 String tip = "Leave name empty for default.";
119                 label.setToolTipText(tip);
120                 panel.add(label, "");
121                 
122                 configurationNameField = new JTextField(10);
123                 configurationNameField.setToolTipText(tip);
124                 configurationNameField.getDocument().addDocumentListener(new DocumentListener() {
125                         @Override
126                         public void changedUpdate(DocumentEvent e) {
127                                 update();
128                         }
129                         @Override
130                         public void insertUpdate(DocumentEvent e) {
131                                 update();
132                         }
133                         @Override
134                         public void removeUpdate(DocumentEvent e) {
135                                 update();
136                         }
137                         private void update() {
138                                 if (configurationNameModification != 0)
139                                         return;
140
141                                 String text = configurationNameField.getText();
142                                 if (currentID != null) {
143                                         configurationNameModification++;
144                                         rocket.setMotorConfigurationName(currentID, text);
145                                         int row = configurationTable.getSelectedRow();
146                                         configurationTableModel.fireTableCellUpdated(row, 0);
147                                         updateEnabled();
148                                         configurationNameModification--;
149                                 }
150                         }
151                 });
152                 panel.add(configurationNameField, "cell 2 1, gapright para");
153                 
154                 newConfButton = new JButton("New configuration");
155                 newConfButton.addActionListener(new ActionListener() {
156                         @Override
157                         public void actionPerformed(ActionEvent e) {
158                                 String id = rocket.newMotorConfigurationID();
159                                 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
160                                 configurationTableModel.fireTableDataChanged();
161                                 updateEnabled();
162                         }
163                 });
164                 panel.add(newConfButton, "cell 3 1");
165                 
166                 removeConfButton = new JButton("Remove configuration");
167                 removeConfButton.addActionListener(new ActionListener() {
168                         @Override
169                         public void actionPerformed(ActionEvent e) {
170                                 if (currentID == null)
171                                         return;
172                                 rocket.removeMotorConfigurationID(currentID);
173                                 rocket.getDefaultConfiguration().setMotorConfigurationID(null);
174                                 configurationTableModel.fireTableDataChanged();
175                                 updateEnabled();
176                         }
177                 });
178                 panel.add(removeConfButton, "cell 4 1");
179                 
180                 
181
182                 
183                 configurationTableModel = new MotorConfigurationTableModel();
184                 configurationTable = new JTable(configurationTableModel);
185                 configurationTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
186                 configurationTable.setCellSelectionEnabled(true);
187                 
188                 configurationTable.addMouseListener(new MouseAdapter() {
189                         @Override
190                         public void mouseClicked(MouseEvent e) {
191                                 
192                                 if (e.getClickCount() == 1) {
193                                         
194                                         // Single click updates selection
195                                         updateEnabled();
196                                         
197                                 } else if (e.getClickCount() == 2) {
198                                         
199                                         // Double-click edits motor
200                                         selectMotor();
201                                         
202                                 }
203                                 
204                         }
205                 });
206                 
207
208                 scroll = new JScrollPane(configurationTable);
209                 panel.add(scroll, "cell 1 2, spanx, w 500lp, h 150lp, grow");
210                 
211                 
212                 selectMotorButton = new JButton("Select motor");
213                 selectMotorButton.addActionListener(new ActionListener() {
214                         @Override
215                         public void actionPerformed(ActionEvent e) {
216                                 selectMotor();
217                         }
218                 });
219                 panel.add(selectMotorButton, "spanx, flowx, split 2, ax 50%");
220                 
221                 
222                 removeMotorButton = new JButton("Remove motor");
223                 removeMotorButton.addActionListener(new ActionListener() {
224                         @Override
225                         public void actionPerformed(ActionEvent e) {
226                                 removeMotor();
227                         }
228                 });
229                 panel.add(removeMotorButton, "ax 50%");
230                 
231                 
232                 
233                 //// Close button
234                 
235                 JButton close = new JButton("Close");
236                 close.addActionListener(new ActionListener() {
237                         @Override
238                         public void actionPerformed(ActionEvent e) {
239                                 EditMotorConfigurationDialog.this.dispose();
240                         }
241                 });
242                 panel.add(close, "spanx, right");
243                 
244                 this.add(panel);
245                 this.validate();
246                 this.pack();
247                 
248                 updateEnabled();
249                 
250                 GUIUtil.installEscapeCloseOperation(this);
251                 GUIUtil.setDefaultButton(close);
252                 this.setLocationByPlatform(true);
253                 
254                 // Undo description
255                 final OpenRocketDocument document = BasicFrame.findDocument(rocket);
256                 if (document != null) {
257                         document.startUndo("Edit motor configurations");
258                         this.addWindowListener(new WindowAdapter() {
259                                 @Override
260                                 public void windowClosed(WindowEvent e) {
261                                         document.stopUndo();
262                                 }
263                         });
264                 }
265         }
266
267         
268         
269         
270         private void updateEnabled() {
271                 int column = configurationTable.getSelectedColumn();
272                 int row = configurationTable.getSelectedRow();
273                 
274                 if (column < 0 || row < 0) {
275                         currentID = null;
276                         currentMount = null;
277                 } else {
278                         
279                         currentID = findID(row);
280                         if (column == 0) {
281                                 currentMount = null;
282                         } else {
283                                 currentMount = findMount(column);
284                         }
285                         rocket.getDefaultConfiguration().setMotorConfigurationID(currentID);
286                         
287                 }
288
289                 if (configurationNameModification == 0) {
290                         // Don't update name field when user is modifying it
291                         configurationNameModification++;
292                         
293                         configurationNameField.setEnabled(currentID != null);
294                         if (currentID == null) {
295                                 configurationNameField.setText("");
296                         } else {
297                                 configurationNameField.setText(rocket.getMotorConfigurationName(currentID));
298                         }
299                         
300                         configurationNameModification--;
301                 }
302                 removeConfButton.setEnabled(currentID != null);
303                 selectMotorButton.setEnabled(currentMount != null && currentID != null);
304                 removeMotorButton.setEnabled(currentMount != null && currentID != null);
305         }
306         
307
308         
309         
310         private void selectMotor() {
311                 if (currentID == null || currentMount == null)
312                         return;
313                 
314                 MotorChooserDialog dialog = new MotorChooserDialog(currentMount.getMotor(currentID),
315                                 currentMount.getMotorDelay(currentID), currentMount.getMotorMountDiameter(),
316                                 this);
317                 dialog.setVisible(true);
318                 Motor m = dialog.getSelectedMotor();
319                 double d = dialog.getSelectedDelay();
320                 
321                 if (m != null) {
322                         currentMount.setMotor(currentID, m);
323                         currentMount.setMotorDelay(currentID, d);
324                 }
325
326                 int row = configurationTable.getSelectedRow();
327                 configurationTableModel.fireTableRowsUpdated(row, row);
328                 updateEnabled();
329         }
330         
331         
332         private void removeMotor() {
333                 if (currentID == null || currentMount == null)
334                         return;
335                 
336                 currentMount.setMotor(currentID, null);
337                 
338                 int row = configurationTable.getSelectedRow();
339                 configurationTableModel.fireTableRowsUpdated(row, row);
340                 updateEnabled();
341         }
342         
343         
344         private String findID(int row) {
345                 return rocket.getMotorConfigurationIDs()[row+1];
346         }
347
348         
349         private MotorMount findMount(int column) {
350                 MotorMount mount = null;
351
352                 int count = column;
353                 for (MotorMount m: mounts) {
354                         if (m.isMotorMount())
355                                 count--;
356                         if (count <= 0) {
357                                 mount = m;
358                                 break;
359                         }
360                 }
361                 
362                 if (mount == null) {
363                         throw new IndexOutOfBoundsException("motor mount not found, column="+column);
364                 }
365                 return mount;
366         }
367
368         
369         /**
370          * The table model for selecting whether components are motor mounts or not.
371          */
372         private class MotorMountTableModel extends AbstractTableModel {
373
374                 @Override
375                 public int getColumnCount() {
376                         return 2;
377                 }
378
379                 @Override
380                 public int getRowCount() {
381                         return mounts.length;
382                 }
383                 
384                 @Override
385                 public Class<?> getColumnClass(int column) {
386                         switch (column) {
387                         case 0:
388                                 return Boolean.class;
389                                 
390                         case 1:
391                                 return String.class;
392                                 
393                         default:
394                                 throw new IndexOutOfBoundsException("column="+column);
395                         }
396                 }
397
398                 @Override
399                 public Object getValueAt(int row, int column) {
400                         switch (column) {
401                         case 0:
402                                 return new Boolean(mounts[row].isMotorMount());
403                                 
404                         case 1:
405                                 return mounts[row].toString();
406                                 
407                         default:
408                                 throw new IndexOutOfBoundsException("column="+column);
409                         }
410                 }
411                 
412                 @Override
413                 public boolean isCellEditable(int row, int column) {
414                         return column == 0;
415                 }
416                 
417                 @Override
418                 public void setValueAt(Object value, int row, int column) {
419                         if (column != 0 || !(value instanceof Boolean)) {
420                                 throw new IllegalArgumentException("column="+column+", value="+value);
421                         }
422                         
423                         mounts[row].setMotorMount((Boolean)value);
424                         configurationTableModel.fireTableStructureChanged();
425                         updateEnabled();
426                 }
427         }
428         
429         
430         
431         /**
432          * The table model for selecting and editing the motor configurations.
433          */
434         private class MotorConfigurationTableModel extends AbstractTableModel {
435                 
436                 @Override
437                 public int getColumnCount() {
438                         int count = 1;
439                         for (MotorMount m: mounts) {
440                                 if (m.isMotorMount())
441                                         count++;
442                         }
443                         return count;
444                 }
445
446                 @Override
447                 public int getRowCount() {
448                         return rocket.getMotorConfigurationIDs().length-1;
449                 }
450
451                 @Override
452                 public Object getValueAt(int row, int column) {
453                         
454                         String id = findID(row);
455
456                         if (column == 0) {
457                                 return rocket.getMotorConfigurationNameOrDescription(id);
458                         }
459                         
460                         MotorMount mount = findMount(column);
461                         Motor motor = mount.getMotor(id);
462                         if (motor == null)
463                                 return "None";
464                         
465                         String str = motor.getDesignation(mount.getMotorDelay(id)); 
466                         int count = mount.getMotorCount();
467                         if (count > 1) {
468                                 str = "" + count + "\u00d7 " + str;
469                         }
470                         return str;
471                 }
472
473
474                 @Override
475                 public String getColumnName(int column) {
476                         if (column == 0) {
477                                 return "Configuration name";
478                         }
479                         
480                         MotorMount mount = findMount(column);
481                         String name = mount.toString();
482                         int count = mount.getMotorCount();
483                         if (count > 1) {
484                                 name = name + " (\u00d7" + count + ")";
485                         }
486                         return name;
487                 }
488                 
489                 
490         }
491
492         
493         
494         
495 }