package net.sf.openrocket.gui.main.flightconfigpanel; import java.awt.CardLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableCellRenderer; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.StyledLabel.Style; import net.sf.openrocket.gui.dialogs.flightconfiguration.IgnitionSelectionDialog; import net.sf.openrocket.gui.dialogs.flightconfiguration.MotorMountConfigurationPanel; import net.sf.openrocket.gui.dialogs.motor.MotorChooserDialog; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.rocketcomponent.IgnitionConfiguration; import net.sf.openrocket.rocketcomponent.IgnitionConfiguration.IgnitionEvent; import net.sf.openrocket.rocketcomponent.MotorConfiguration; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.Chars; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Pair; public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount> { private static final String NONE = trans.get("edtmotorconfdlg.tbl.None"); private final JButton selectMotorButton, removeMotorButton, selectIgnitionButton, resetIgnitionButton; private final JPanel cards; private final static String HELP_LABEL = "help"; private final static String TABLE_LABEL = "table"; private final MotorChooserDialog motorChooserDialog; protected FlightConfigurableTableModel<MotorMount> configurationTableModel; MotorConfigurationPanel(final FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) { super(flightConfigurationPanel,rocket); motorChooserDialog = new MotorChooserDialog(SwingUtilities.getWindowAncestor(flightConfigurationPanel)); { //// Select motor mounts JPanel subpanel = new JPanel(new MigLayout("")); JLabel label = new StyledLabel(trans.get("lbl.motorMounts"), Style.BOLD); subpanel.add(label, "wrap"); MotorMountConfigurationPanel mountConfigPanel = new MotorMountConfigurationPanel(this,rocket) { @Override public void onDataChanged() { MotorConfigurationPanel.this.fireTableDataChanged(); } }; subpanel.add(mountConfigPanel, "grow"); this.add(subpanel, "split, w 200lp, growy"); } cards = new JPanel(new CardLayout()); this.add( cards ); JLabel helpText = new JLabel(trans.get("MotorConfigurationPanel.lbl.nomotors")); cards.add(helpText, HELP_LABEL ); JScrollPane scroll = new JScrollPane(table); cards.add(scroll, TABLE_LABEL ); this.add(cards, "grow, wrap"); //// Select motor selectMotorButton = new JButton(trans.get("MotorConfigurationPanel.btn.selectMotor")); selectMotorButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { selectMotor(); } }); this.add(selectMotorButton, "split, align right, sizegroup button"); //// Remove motor button removeMotorButton = new JButton(trans.get("MotorConfigurationPanel.btn.removeMotor")); removeMotorButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { removeMotor(); } }); this.add(removeMotorButton, "sizegroup button"); //// Select Ignition button selectIgnitionButton = new JButton(trans.get("MotorConfigurationPanel.btn.selectIgnition")); selectIgnitionButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { selectIgnition(); } }); this.add(selectIgnitionButton, "sizegroup button"); //// Reset Ignition button resetIgnitionButton = new JButton(trans.get("MotorConfigurationPanel.btn.resetIgnition")); resetIgnitionButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { resetIgnition(); } }); this.add(resetIgnitionButton, "sizegroup button, wrap"); updateButtonState(); } protected void showEmptyText() { ((CardLayout)cards.getLayout()).show(cards, HELP_LABEL); } protected void showContent() { ((CardLayout)cards.getLayout()).show(cards, TABLE_LABEL); } @Override protected JTable initializeTable() { //// Motor selection table. configurationTableModel = new FlightConfigurableTableModel<MotorMount>(MotorMount.class,rocket) { @Override protected boolean includeComponent(MotorMount component) { return component.isMotorMount(); } }; // Listen to changes to the table so we can disable the help text when a // motor mount is added through the edit body tube dialog. configurationTableModel.addTableModelListener( new TableModelListener() { @Override public void tableChanged(TableModelEvent e) { MotorConfigurationPanel.this.updateButtonState(); } }); JTable configurationTable = new JTable(configurationTableModel); configurationTable.getTableHeader().setReorderingAllowed(false); configurationTable.setCellSelectionEnabled(true); configurationTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); configurationTable.setDefaultRenderer(Object.class, new MotorTableCellRenderer()); configurationTable.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { updateButtonState(); int selectedColumn = table.getSelectedColumn(); if (e.getClickCount() == 2) { if (selectedColumn > 0) { selectMotor(); } } } }); return configurationTable; } protected void updateButtonState() { if( configurationTableModel.getColumnCount() > 1 ) { showContent(); String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID(); MotorMount currentMount = getSelectedComponent(); selectMotorButton.setEnabled(currentMount != null && currentID != null); removeMotorButton.setEnabled(currentMount != null && currentID != null); selectIgnitionButton.setEnabled(currentMount != null && currentID != null); resetIgnitionButton.setEnabled(currentMount != null && currentID != null); } else { showEmptyText(); selectMotorButton.setEnabled(false); removeMotorButton.setEnabled(false); selectIgnitionButton.setEnabled(false); resetIgnitionButton.setEnabled(false); } } private void selectMotor() { String id = rocket.getDefaultConfiguration().getFlightConfigurationID(); MotorMount mount = getSelectedComponent(); if (id == null || mount == null) return; MotorConfiguration config = mount.getMotorConfiguration().get(id); motorChooserDialog.setMotorMountAndConfig(mount, id); motorChooserDialog.setVisible(true); Motor m = motorChooserDialog.getSelectedMotor(); double d = motorChooserDialog.getSelectedDelay(); if (m != null) { config = new MotorConfiguration(); config.setMotor(m); config.setEjectionDelay(d); mount.getMotorConfiguration().set(id, config); } fireTableDataChanged(); } private void removeMotor() { String id = rocket.getDefaultConfiguration().getFlightConfigurationID(); MotorMount mount = getSelectedComponent(); if (id == null || mount == null) return; mount.getMotorConfiguration().resetDefault(id); fireTableDataChanged(); } private void selectIgnition() { String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID(); MotorMount currentMount = getSelectedComponent(); if (currentID == null || currentMount == null) return; IgnitionSelectionDialog dialog = new IgnitionSelectionDialog( SwingUtilities.getWindowAncestor(this.flightConfigurationPanel), rocket, currentMount); dialog.setVisible(true); fireTableDataChanged(); } private void resetIgnition() { String currentID = rocket.getDefaultConfiguration().getFlightConfigurationID(); MotorMount currentMount = getSelectedComponent(); if (currentID == null || currentMount == null) return; currentMount.getIgnitionConfiguration().resetDefault(currentID); fireTableDataChanged(); } private class MotorTableCellRenderer extends FlightConfigurablePanel<MotorMount>.FlightConfigurableCellRenderer { @Override protected JLabel format( MotorMount mount, String configId, JLabel l ) { JLabel label = new JLabel(); label.setLayout(new BoxLayout(label, BoxLayout.X_AXIS)); MotorConfiguration motorConfig = mount.getMotorConfiguration().get(configId); String motorString = getMotorSpecification(mount, motorConfig); JLabel motorDescriptionLabel = new JLabel(motorString); label.add(motorDescriptionLabel); label.add( Box.createRigidArea(new Dimension(10,0))); JLabel ignitionLabel = getIgnitionEventString(configId, mount); label.add(ignitionLabel); label.validate(); return label; } private String getMotorSpecification(MotorMount mount, MotorConfiguration motorConfig) { Motor motor = motorConfig.getMotor(); if (motor == null) return NONE; String str = motor.getDesignation(motorConfig.getEjectionDelay()); int count = getMountMultiplicity(mount); if (count > 1) { str = "" + count + Chars.TIMES + " " + str; } return str; } private int getMountMultiplicity(MotorMount mount) { RocketComponent c = (RocketComponent) mount; return c.toAbsolute(Coordinate.NUL).length; } private JLabel getIgnitionEventString(String id, MotorMount mount) { IgnitionConfiguration ignitionConfig = mount.getIgnitionConfiguration().get(id); IgnitionConfiguration.IgnitionEvent ignitionEvent = ignitionConfig.getIgnitionEvent(); Double ignitionDelay = ignitionConfig.getIgnitionDelay(); boolean isDefault = mount.getIgnitionConfiguration().isDefault(id); JLabel label = new JLabel(); String str = trans.get("MotorMount.IgnitionEvent.short." + ignitionEvent.name()); if (ignitionEvent != IgnitionEvent.NEVER && ignitionDelay > 0.001) { str = str + " + " + UnitGroup.UNITS_SHORT_TIME.toStringUnit(ignitionDelay); } if (isDefault) { shaded(label); String def = trans.get("MotorConfigurationTableModel.table.ignition.default"); str = def.replace("{0}", str); } label.setText(str); return label; } } }