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