a42d8a944fcf17f521781ffb58b501521c3894ae
[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                 GUIUtil.installEscapeCloseOperation(this);
253                 GUIUtil.setDefaultButton(close);
254                 this.setLocationByPlatform(true);
255                 
256                 // Undo description
257                 final OpenRocketDocument document = BasicFrame.findDocument(rocket);
258                 if (document != null) {
259                         document.startUndo("Edit motor configurations");
260                         this.addWindowListener(new WindowAdapter() {
261                                 @Override
262                                 public void windowClosed(WindowEvent e) {
263                                         document.stopUndo();
264                                 }
265                         });
266                 }
267         }
268
269         
270         
271         
272         private void updateEnabled() {
273                 int column = configurationTable.getSelectedColumn();
274                 int row = configurationTable.getSelectedRow();
275                 
276                 if (column < 0 || row < 0) {
277                         currentID = null;
278                         currentMount = null;
279                 } else {
280                         
281                         currentID = findID(row);
282                         if (column == 0) {
283                                 currentMount = null;
284                         } else {
285                                 currentMount = findMount(column);
286                         }
287                         rocket.getDefaultConfiguration().setMotorConfigurationID(currentID);
288                         
289                 }
290
291                 if (configurationNameModification == 0) {
292                         // Don't update name field when user is modifying it
293                         configurationNameModification++;
294                         
295                         configurationNameField.setEnabled(currentID != null);
296                         if (currentID == null) {
297                                 configurationNameField.setText("");
298                         } else {
299                                 configurationNameField.setText(rocket.getMotorConfigurationName(currentID));
300                         }
301                         
302                         configurationNameModification--;
303                 }
304                 removeConfButton.setEnabled(currentID != null);
305                 selectMotorButton.setEnabled(currentMount != null && currentID != null);
306                 removeMotorButton.setEnabled(currentMount != null && currentID != null);
307         }
308         
309
310         
311         
312         private void selectMotor() {
313                 if (currentID == null || currentMount == null)
314                         return;
315                 
316                 MotorChooserDialog dialog = new MotorChooserDialog(currentMount.getMotor(currentID),
317                                 currentMount.getMotorDelay(currentID), currentMount.getMotorMountDiameter(),
318                                 this);
319                 dialog.setVisible(true);
320                 Motor m = dialog.getSelectedMotor();
321                 double d = dialog.getSelectedDelay();
322                 
323                 if (m != null) {
324                         currentMount.setMotor(currentID, m);
325                         currentMount.setMotorDelay(currentID, d);
326                 }
327
328                 int row = configurationTable.getSelectedRow();
329                 configurationTableModel.fireTableRowsUpdated(row, row);
330                 updateEnabled();
331         }
332         
333         
334         private void removeMotor() {
335                 if (currentID == null || currentMount == null)
336                         return;
337                 
338                 currentMount.setMotor(currentID, null);
339                 
340                 int row = configurationTable.getSelectedRow();
341                 configurationTableModel.fireTableRowsUpdated(row, row);
342                 updateEnabled();
343         }
344         
345         
346         private String findID(int row) {
347                 return rocket.getMotorConfigurationIDs()[row+1];
348         }
349
350         
351         private MotorMount findMount(int column) {
352                 MotorMount mount = null;
353
354                 int count = column;
355                 for (MotorMount m: mounts) {
356                         if (m.isMotorMount())
357                                 count--;
358                         if (count <= 0) {
359                                 mount = m;
360                                 break;
361                         }
362                 }
363                 
364                 if (mount == null) {
365                         throw new IndexOutOfBoundsException("motor mount not found, column="+column);
366                 }
367                 return mount;
368         }
369
370         
371         /**
372          * The table model for selecting whether components are motor mounts or not.
373          */
374         private class MotorMountTableModel extends AbstractTableModel {
375
376                 @Override
377                 public int getColumnCount() {
378                         return 2;
379                 }
380
381                 @Override
382                 public int getRowCount() {
383                         return mounts.length;
384                 }
385                 
386                 @Override
387                 public Class<?> getColumnClass(int column) {
388                         switch (column) {
389                         case 0:
390                                 return Boolean.class;
391                                 
392                         case 1:
393                                 return String.class;
394                                 
395                         default:
396                                 throw new IndexOutOfBoundsException("column="+column);
397                         }
398                 }
399
400                 @Override
401                 public Object getValueAt(int row, int column) {
402                         switch (column) {
403                         case 0:
404                                 return new Boolean(mounts[row].isMotorMount());
405                                 
406                         case 1:
407                                 return mounts[row].toString();
408                                 
409                         default:
410                                 throw new IndexOutOfBoundsException("column="+column);
411                         }
412                 }
413                 
414                 @Override
415                 public boolean isCellEditable(int row, int column) {
416                         return column == 0;
417                 }
418                 
419                 @Override
420                 public void setValueAt(Object value, int row, int column) {
421                         if (column != 0 || !(value instanceof Boolean)) {
422                                 throw new IllegalArgumentException("column="+column+", value="+value);
423                         }
424                         
425                         mounts[row].setMotorMount((Boolean)value);
426                         configurationTableModel.fireTableStructureChanged();
427                         updateEnabled();
428                 }
429         }
430         
431         
432         
433         /**
434          * The table model for selecting and editing the motor configurations.
435          */
436         private class MotorConfigurationTableModel extends AbstractTableModel {
437                 
438                 @Override
439                 public int getColumnCount() {
440                         int count = 1;
441                         for (MotorMount m: mounts) {
442                                 if (m.isMotorMount())
443                                         count++;
444                         }
445                         return count;
446                 }
447
448                 @Override
449                 public int getRowCount() {
450                         return rocket.getMotorConfigurationIDs().length-1;
451                 }
452
453                 @Override
454                 public Object getValueAt(int row, int column) {
455                         
456                         String id = findID(row);
457
458                         if (column == 0) {
459                                 return rocket.getMotorConfigurationNameOrDescription(id);
460                         }
461                         
462                         MotorMount mount = findMount(column);
463                         Motor motor = mount.getMotor(id);
464                         if (motor == null)
465                                 return "None";
466                         
467                         String str = motor.getDesignation(mount.getMotorDelay(id)); 
468                         int count = mount.getMotorCount();
469                         if (count > 1) {
470                                 str = "" + count + "\u00d7 " + str;
471                         }
472                         return str;
473                 }
474
475
476                 @Override
477                 public String getColumnName(int column) {
478                         if (column == 0) {
479                                 return "Configuration name";
480                         }
481                         
482                         MotorMount mount = findMount(column);
483                         String name = mount.toString();
484                         int count = mount.getMotorCount();
485                         if (count > 1) {
486                                 name = name + " (\u00d7" + count + ")";
487                         }
488                         return name;
489                 }
490                 
491                 
492         }
493
494         
495         
496         
497 }