updates for 0.9.4
[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.motor.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                 table.addMouseListener(new GUIUtil.BooleanTableClickListener(table));
105                 
106                 JScrollPane scroll = new JScrollPane(table);
107                 panel.add(scroll, "w 200lp, h 150lp, grow, wrap 20lp");
108                 
109
110                 
111                 
112                 
113                 //// Motor selection
114                 
115                 label = new JLabel("<html><b>Motor configurations:</b>");
116                 panel.add(label, "spanx, gapbottom para");
117                 
118                 
119                 label = new JLabel("Configuration name:");
120                 String tip = "Leave name empty for default.";
121                 label.setToolTipText(tip);
122                 panel.add(label, "");
123                 
124                 configurationNameField = new JTextField(10);
125                 configurationNameField.setToolTipText(tip);
126                 configurationNameField.getDocument().addDocumentListener(new DocumentListener() {
127                         @Override
128                         public void changedUpdate(DocumentEvent e) {
129                                 update();
130                         }
131                         @Override
132                         public void insertUpdate(DocumentEvent e) {
133                                 update();
134                         }
135                         @Override
136                         public void removeUpdate(DocumentEvent e) {
137                                 update();
138                         }
139                         private void update() {
140                                 if (configurationNameModification != 0)
141                                         return;
142
143                                 String text = configurationNameField.getText();
144                                 if (currentID != null) {
145                                         configurationNameModification++;
146                                         rocket.setMotorConfigurationName(currentID, text);
147                                         int row = configurationTable.getSelectedRow();
148                                         configurationTableModel.fireTableCellUpdated(row, 0);
149                                         updateEnabled();
150                                         configurationNameModification--;
151                                 }
152                         }
153                 });
154                 panel.add(configurationNameField, "cell 2 1, gapright para");
155                 
156                 newConfButton = new JButton("New configuration");
157                 newConfButton.addActionListener(new ActionListener() {
158                         @Override
159                         public void actionPerformed(ActionEvent e) {
160                                 String id = rocket.newMotorConfigurationID();
161                                 rocket.getDefaultConfiguration().setMotorConfigurationID(id);
162                                 configurationTableModel.fireTableDataChanged();
163                                 updateEnabled();
164                         }
165                 });
166                 panel.add(newConfButton, "cell 3 1");
167                 
168                 removeConfButton = new JButton("Remove configuration");
169                 removeConfButton.addActionListener(new ActionListener() {
170                         @Override
171                         public void actionPerformed(ActionEvent e) {
172                                 if (currentID == null)
173                                         return;
174                                 rocket.removeMotorConfigurationID(currentID);
175                                 rocket.getDefaultConfiguration().setMotorConfigurationID(null);
176                                 configurationTableModel.fireTableDataChanged();
177                                 updateEnabled();
178                         }
179                 });
180                 panel.add(removeConfButton, "cell 4 1");
181                 
182                 
183
184                 
185                 configurationTableModel = new MotorConfigurationTableModel();
186                 configurationTable = new JTable(configurationTableModel);
187                 configurationTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
188                 configurationTable.setCellSelectionEnabled(true);
189                 
190                 configurationTable.addMouseListener(new MouseAdapter() {
191                         @Override
192                         public void mouseClicked(MouseEvent e) {
193                                 
194                                 if (e.getClickCount() == 1) {
195                                         
196                                         // Single click updates selection
197                                         updateEnabled();
198                                         
199                                 } else if (e.getClickCount() == 2) {
200                                         
201                                         // Double-click edits motor
202                                         selectMotor();
203                                         
204                                 }
205                                 
206                         }
207                 });
208                 
209
210                 scroll = new JScrollPane(configurationTable);
211                 panel.add(scroll, "cell 1 2, spanx, w 500lp, h 150lp, grow");
212                 
213                 
214                 selectMotorButton = new JButton("Select motor");
215                 selectMotorButton.addActionListener(new ActionListener() {
216                         @Override
217                         public void actionPerformed(ActionEvent e) {
218                                 selectMotor();
219                         }
220                 });
221                 panel.add(selectMotorButton, "spanx, flowx, split 2, ax 50%");
222                 
223                 
224                 removeMotorButton = new JButton("Remove motor");
225                 removeMotorButton.addActionListener(new ActionListener() {
226                         @Override
227                         public void actionPerformed(ActionEvent e) {
228                                 removeMotor();
229                         }
230                 });
231                 panel.add(removeMotorButton, "ax 50%");
232                 
233                 
234                 
235                 //// Close button
236                 
237                 JButton close = new JButton("Close");
238                 close.addActionListener(new ActionListener() {
239                         @Override
240                         public void actionPerformed(ActionEvent e) {
241                                 EditMotorConfigurationDialog.this.dispose();
242                         }
243                 });
244                 panel.add(close, "spanx, right");
245                 
246                 this.add(panel);
247                 this.validate();
248                 this.pack();
249                 
250                 updateEnabled();
251                 
252                 this.setLocationByPlatform(true);
253                 GUIUtil.setDisposableDialogOptions(this, close);
254                 
255                 // Undo description
256                 final OpenRocketDocument document = BasicFrame.findDocument(rocket);
257                 if (document != null) {
258                         document.startUndo("Edit motor configurations");
259                         this.addWindowListener(new WindowAdapter() {
260                                 @Override
261                                 public void windowClosed(WindowEvent e) {
262                                         document.stopUndo();
263                                 }
264                         });
265                 }
266         }
267
268         
269         
270         
271         private void updateEnabled() {
272                 int column = configurationTable.getSelectedColumn();
273                 int row = configurationTable.getSelectedRow();
274                 
275                 if (column < 0 || row < 0) {
276                         currentID = null;
277                         currentMount = null;
278                 } else {
279                         
280                         currentID = findID(row);
281                         if (column == 0) {
282                                 currentMount = null;
283                         } else {
284                                 currentMount = findMount(column);
285                         }
286                         rocket.getDefaultConfiguration().setMotorConfigurationID(currentID);
287                         
288                 }
289
290                 if (configurationNameModification == 0) {
291                         // Don't update name field when user is modifying it
292                         configurationNameModification++;
293                         
294                         configurationNameField.setEnabled(currentID != null);
295                         if (currentID == null) {
296                                 configurationNameField.setText("");
297                         } else {
298                                 configurationNameField.setText(rocket.getMotorConfigurationName(currentID));
299                         }
300                         
301                         configurationNameModification--;
302                 }
303                 removeConfButton.setEnabled(currentID != null);
304                 selectMotorButton.setEnabled(currentMount != null && currentID != null);
305                 removeMotorButton.setEnabled(currentMount != null && currentID != null);
306         }
307         
308
309         
310         
311         private void selectMotor() {
312                 if (currentID == null || currentMount == null)
313                         return;
314                 
315                 MotorChooserDialog dialog = new MotorChooserDialog(currentMount.getMotor(currentID),
316                                 currentMount.getMotorDelay(currentID), currentMount.getMotorMountDiameter(),
317                                 this);
318                 dialog.setVisible(true);
319                 Motor m = dialog.getSelectedMotor();
320                 double d = dialog.getSelectedDelay();
321                 
322                 if (m != null) {
323                         currentMount.setMotor(currentID, m);
324                         currentMount.setMotorDelay(currentID, d);
325                 }
326
327                 int row = configurationTable.getSelectedRow();
328                 configurationTableModel.fireTableRowsUpdated(row, row);
329                 updateEnabled();
330         }
331         
332         
333         private void removeMotor() {
334                 if (currentID == null || currentMount == null)
335                         return;
336                 
337                 currentMount.setMotor(currentID, null);
338                 
339                 int row = configurationTable.getSelectedRow();
340                 configurationTableModel.fireTableRowsUpdated(row, row);
341                 updateEnabled();
342         }
343         
344         
345         private String findID(int row) {
346                 return rocket.getMotorConfigurationIDs()[row+1];
347         }
348
349         
350         private MotorMount findMount(int column) {
351                 MotorMount mount = null;
352
353                 int count = column;
354                 for (MotorMount m: mounts) {
355                         if (m.isMotorMount())
356                                 count--;
357                         if (count <= 0) {
358                                 mount = m;
359                                 break;
360                         }
361                 }
362                 
363                 if (mount == null) {
364                         throw new IndexOutOfBoundsException("motor mount not found, column="+column);
365                 }
366                 return mount;
367         }
368
369         
370         /**
371          * The table model for selecting whether components are motor mounts or not.
372          */
373         private class MotorMountTableModel extends AbstractTableModel {
374
375                 @Override
376                 public int getColumnCount() {
377                         return 2;
378                 }
379
380                 @Override
381                 public int getRowCount() {
382                         return mounts.length;
383                 }
384                 
385                 @Override
386                 public Class<?> getColumnClass(int column) {
387                         switch (column) {
388                         case 0:
389                                 return Boolean.class;
390                                 
391                         case 1:
392                                 return String.class;
393                                 
394                         default:
395                                 throw new IndexOutOfBoundsException("column="+column);
396                         }
397                 }
398
399                 @Override
400                 public Object getValueAt(int row, int column) {
401                         switch (column) {
402                         case 0:
403                                 return new Boolean(mounts[row].isMotorMount());
404                                 
405                         case 1:
406                                 return mounts[row].toString();
407                                 
408                         default:
409                                 throw new IndexOutOfBoundsException("column="+column);
410                         }
411                 }
412                 
413                 @Override
414                 public boolean isCellEditable(int row, int column) {
415                         return column == 0;
416                 }
417                 
418                 @Override
419                 public void setValueAt(Object value, int row, int column) {
420                         if (column != 0 || !(value instanceof Boolean)) {
421                                 throw new IllegalArgumentException("column="+column+", value="+value);
422                         }
423                         
424                         mounts[row].setMotorMount((Boolean)value);
425                         configurationTableModel.fireTableStructureChanged();
426                         updateEnabled();
427                 }
428         }
429         
430         
431         
432         /**
433          * The table model for selecting and editing the motor configurations.
434          */
435         private class MotorConfigurationTableModel extends AbstractTableModel {
436                 
437                 @Override
438                 public int getColumnCount() {
439                         int count = 1;
440                         for (MotorMount m: mounts) {
441                                 if (m.isMotorMount())
442                                         count++;
443                         }
444                         return count;
445                 }
446
447                 @Override
448                 public int getRowCount() {
449                         return rocket.getMotorConfigurationIDs().length-1;
450                 }
451
452                 @Override
453                 public Object getValueAt(int row, int column) {
454                         
455                         String id = findID(row);
456
457                         if (column == 0) {
458                                 return rocket.getMotorConfigurationNameOrDescription(id);
459                         }
460                         
461                         MotorMount mount = findMount(column);
462                         Motor motor = mount.getMotor(id);
463                         if (motor == null)
464                                 return "None";
465                         
466                         String str = motor.getDesignation(mount.getMotorDelay(id)); 
467                         int count = mount.getMotorCount();
468                         if (count > 1) {
469                                 str = "" + count + "\u00d7 " + str;
470                         }
471                         return str;
472                 }
473
474
475                 @Override
476                 public String getColumnName(int column) {
477                         if (column == 0) {
478                                 return "Configuration name";
479                         }
480                         
481                         MotorMount mount = findMount(column);
482                         String name = mount.toString();
483                         int count = mount.getMotorCount();
484                         if (count > 1) {
485                                 name = name + " (\u00d7" + count + ")";
486                         }
487                         return name;
488                 }
489                 
490                 
491         }
492
493         
494         
495         
496 }