diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index e70342af9..93872611c 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -2099,7 +2099,7 @@ ComponentPresetChooserDialog.menu.sortDesc = Sort Descending
ComponentPresetChooserDialog.menu.units = Units
ComponentPresetChooserDialog.checkbox.showAllCompatible = Show all compatible
ComponentPresetChooserDialog.checkbox.showLegacyCheckBox = Show Legacy Database
-ComponentPresetChooserDialog.lbl.favorites = Check to add preset to the preset drop-down menu in the component edit dialog
+ComponentPresetChooserDialog.lbl.favorites = Check to add preset to the preset drop-down menu in the component edit dialog
Directly apply a preset by double-clicking it or by selecting it and closing this window.
table.column.Favorite = Favorite
table.column.Legacy = Legacy
table.column.Manufacturer = Manufacturer
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java
index ae556b57b..3954bb3fa 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java
@@ -25,6 +25,7 @@ import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator;
@@ -152,7 +153,7 @@ public class ComponentPresetChooserDialog extends JDialog {
scrollpane.setViewportView(componentSelectionTable);
panel.add(scrollpane, "grow, width 700lp, height 300lp, pushy, spanx, wrap rel");
- panel.add(new JLabel(Chars.UP_ARROW + " " + trans.get("lbl.favorites")), "spanx, gapleft 5px, wrap para");
+ panel.add(new StyledLabel(String.format("%s %s", Chars.UP_ARROW, trans.get("lbl.favorites")), -1), "spanx, gapleft 5px, wrap para");
// Close buttons
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTable.java b/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTable.java
index c361baebf..62c1bb31b 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTable.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTable.java
@@ -77,9 +77,11 @@ public class ComponentPresetTable extends JTable {
if ( columnIndex != 0 ) {
return;
}
+ int selectedRow = ComponentPresetTable.this.getSelectedRow();
ComponentPreset preset = ComponentPresetTable.this.presets.get(rowIndex);
Application.getComponentPresetDao().setFavorite(preset, presetType, (Boolean) aValue);
ComponentPresetTable.this.updateFavorites();
+ ComponentPresetTable.this.setRowSelectionInterval(selectedRow, selectedRow);
}
@Override
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTableColumn.java b/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTableColumn.java
index 6bf137b28..04821f75d 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTableColumn.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTableColumn.java
@@ -33,7 +33,7 @@ public abstract class ComponentPresetTableColumn extends TableColumn {
@Override
public Object getValueFromPreset( Set favorites, ComponentPreset preset ) {
- return Boolean.valueOf(favorites.contains(preset.preferenceKey()));
+ return favorites.contains(preset.preferenceKey());
}
}
diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
index 533d0c45d..4c69274fa 100644
--- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
+++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
@@ -4,7 +4,9 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
@@ -17,12 +19,16 @@ import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
import javax.swing.border.BevelBorder;
+import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
@@ -54,6 +60,7 @@ import net.sf.openrocket.gui.dialogs.preferences.PreferencesDialog;
import net.sf.openrocket.gui.figure3d.photo.PhotoFrame;
import net.sf.openrocket.gui.help.tours.GuidedTourSelectionDialog;
import net.sf.openrocket.gui.main.componenttree.ComponentTree;
+import net.sf.openrocket.gui.main.flightconfigpanel.FlightConfigurationPanel;
import net.sf.openrocket.gui.scalefigure.RocketPanel;
import net.sf.openrocket.gui.util.DummyFrameMenuOSX;
import net.sf.openrocket.gui.util.FileHelper;
@@ -62,11 +69,13 @@ import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.gui.util.OpenFileWorker;
import net.sf.openrocket.gui.util.SaveFileWorker;
import net.sf.openrocket.gui.util.SwingPreferences;
+import net.sf.openrocket.gui.widgets.SelectColorButton;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.Markers;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
+import net.sf.openrocket.rocketcomponent.PodSet;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
diff --git a/swing/src/net/sf/openrocket/gui/main/RocketActions.java b/swing/src/net/sf/openrocket/gui/main/RocketActions.java
index ebf6aa1c8..070b18ee7 100644
--- a/swing/src/net/sf/openrocket/gui/main/RocketActions.java
+++ b/swing/src/net/sf/openrocket/gui/main/RocketActions.java
@@ -12,6 +12,7 @@ import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
+import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@@ -189,6 +190,35 @@ public class RocketActions {
return moveDownAction;
}
+ /**
+ * Tie an action to a JButton, without using the icon or text of the action for the button.
+ *
+ * For any smartass that wants to know why you don't just initialize the JButton with the action and then set the
+ * icon to null and set the button text: this causes a bug where the text of the icon becomes much smaller than is intended.
+ *
+ * @param button button to tie the action to
+ * @param action action to tie to the button
+ * @param text text to display on the button
+ */
+ public static void tieActionToButtonNoIcon(JButton button, Action action, String text) {
+ button.setAction(action);
+ button.setIcon(null);
+ button.setText(text);
+ }
+
+ /**
+ * Tie an action to a JButton, without using the icon of the action for the button.
+ *
+ * For any smartass that wants to know why you don't just initialize the JButton with the action and then set the
+ * icon to null: this causes a bug where the text of the icon becomes much smaller than is intended.
+ *
+ * @param button button to tie the action to
+ * @param action action to tie to the button
+ */
+ public static void tieActionToButtonNoIcon(JButton button, Action action) {
+ button.setAction(action);
+ button.setIcon(null);
+ }
//////// Helper methods for the actions
diff --git a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
index 22b2a62c6..e4260e479 100644
--- a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
+++ b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
@@ -98,351 +98,66 @@ public class SimulationPanel extends JPanel {
private final JButton plotButton;
private final JPopupMenu pm;
+ private final SimulationAction editSimulationAction;
+ private final SimulationAction runSimulationAction;
+ private final SimulationAction plotSimulationAction;
+ private final SimulationAction duplicateSimulationAction;
+ private final SimulationAction deleteSimulationAction;
+
public SimulationPanel(OpenRocketDocument doc) {
super(new MigLayout("fill", "[grow][][][][][][grow]"));
this.document = doc;
+ // Simulation actions
+ SimulationAction newSimulationAction = new NewSimulationAction();
+ editSimulationAction = new EditSimulationAction();
+ runSimulationAction = new RunSimulationAction();
+ plotSimulationAction = new PlotSimulationAction();
+ duplicateSimulationAction = new DuplicateSimulationAction();
+ deleteSimulationAction = new DeleteSimulationAction();
- //////// The simulation action buttons
+ //////// The simulation action buttons ////////
//// New simulation button
- {
- JButton button = new SelectColorButton(trans.get("simpanel.but.newsimulation"));
- //// Add a new simulation
- button.setToolTipText(trans.get("simpanel.but.ttip.newsimulation"));
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- Simulation sim = new Simulation(document.getRocket());
- sim.setName(document.getNextSimulationName());
-
- int n = document.getSimulationCount();
- document.addSimulation(sim);
- simulationTableModel.fireTableDataChanged();
- simulationTable.clearSelection();
- simulationTable.addRowSelectionInterval(n, n);
-
- openDialog(false, sim);
- }
- });
- this.add(button, "skip 1, gapright para");
- }
+ JButton newButton = new SelectColorButton();
+ RocketActions.tieActionToButtonNoIcon(newButton, newSimulationAction, trans.get("simpanel.but.newsimulation"));
+ newButton.setToolTipText(trans.get("simpanel.but.ttip.newsimulation"));
+ this.add(newButton, "skip 1, gapright para");
//// Edit simulation button
- editButton = new SelectColorButton(trans.get("simpanel.but.editsimulation"));
- //// Edit the selected simulation
+ editButton = new SelectColorButton();
+ RocketActions.tieActionToButtonNoIcon(editButton, editSimulationAction, trans.get("simpanel.but.editsimulation"));
editButton.setToolTipText(trans.get("simpanel.but.ttip.editsim"));
- editButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- editSimulation();
- }
- });
this.add(editButton, "gapright para");
//// Run simulations
- runButton = new SelectColorButton(trans.get("simpanel.but.runsimulations"));
- //// Re-run the selected simulations
+ runButton = new SelectColorButton();
+ RocketActions.tieActionToButtonNoIcon(runButton, runSimulationAction, trans.get("simpanel.but.runsimulations"));
runButton.setToolTipText(trans.get("simpanel.but.ttip.runsimu"));
- runButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- runSimulation();
- }
- });
this.add(runButton, "gapright para");
//// Delete simulations button
- deleteButton = new SelectColorButton(trans.get("simpanel.but.deletesimulations"));
- //// Delete the selected simulations
+ deleteButton = new SelectColorButton();
+ RocketActions.tieActionToButtonNoIcon(deleteButton, deleteSimulationAction, trans.get("simpanel.but.deletesimulations"));
deleteButton.setToolTipText(trans.get("simpanel.but.ttip.deletesim"));
- deleteButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- deleteSimulation();
- }
- });
this.add(deleteButton, "gapright para");
//// Plot / export button
- plotButton = new SelectColorButton(trans.get("simpanel.but.plotexport"));
- // button = new SelectColorButton("Plot flight");
- plotButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- plotSimulation();
- }
- });
+ plotButton = new SelectColorButton();
+ RocketActions.tieActionToButtonNoIcon(plotButton, plotSimulationAction, trans.get("simpanel.but.plotexport"));
this.add(plotButton, "wrap para");
//////// The simulation table
-
- simulationTableModel = new ColumnTableModel(
-
- //// Status and warning column
- new Column("") {
- private JLabel label = null;
-
- @Override
- public Object getValueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- // Initialize the label
- if (label == null) {
- label = new StyledLabel(2f);
- label.setIconTextGap(1);
- // label.setFont(label.getFont().deriveFont(Font.BOLD));
- }
-
- // Set simulation status icon
- Simulation.Status status = document.getSimulation(row).getStatus();
- label.setIcon(Icons.SIMULATION_STATUS_ICON_MAP.get(status));
-
-
- // Set warning marker
- if (status == Simulation.Status.NOT_SIMULATED ||
- status == Simulation.Status.EXTERNAL) {
-
- label.setText("");
-
- } else {
-
- WarningSet w = document.getSimulation(row).getSimulatedWarnings();
- if (w == null) {
- label.setText("");
- } else if (w.isEmpty()) {
- label.setForeground(OK_COLOR);
- label.setText(OK_TEXT);
- } else {
- label.setForeground(WARNING_COLOR);
- label.setText(WARNING_TEXT);
- }
- }
-
- return label;
- }
-
- @Override
- public int getExactWidth() {
- return 36;
- }
-
- @Override
- public Class> getColumnClass() {
- return JLabel.class;
- }
- },
-
- //// Simulation name
- //// Name
- new Column(trans.get("simpanel.col.Name")) {
- @Override
- public Object getValueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
- return document.getSimulation(row).getName();
- }
-
- @Override
- public int getDefaultWidth() {
- return 125;
- }
-
- @Override
- public Comparator getComparator() {
- return new AlphanumComparator();
- }
- },
-
- //// Simulation configuration
- new Column(trans.get("simpanel.col.Configuration")) {
- @Override
- public Object getValueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount()){
- return null;
- }
-
- Rocket rkt = document.getRocket();
- FlightConfigurationId fcid = document.getSimulation(row).getId();
- return descriptor.format( rkt, fcid);
- }
-
- @Override
- public int getDefaultWidth() {
- return 125;
- }
- },
-
- //// Launch rod velocity
- new ValueColumn(trans.get("simpanel.col.Velocityoffrod"), UnitGroup.UNITS_VELOCITY) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null)
- return null;
-
- return data.getLaunchRodVelocity();
- }
-
- },
-
- //// Apogee
- new ValueColumn(trans.get("simpanel.col.Apogee"), UnitGroup.UNITS_DISTANCE) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null)
- return null;
-
- return data.getMaxAltitude();
- }
- },
-
- //// Velocity at deployment
- new ValueColumn(trans.get("simpanel.col.Velocityatdeploy"), UnitGroup.UNITS_VELOCITY) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null)
- return null;
-
- return data.getDeploymentVelocity();
- }
- },
-
- //// Deployment Time from Apogee
- new ValueColumn(trans.get("simpanel.col.OptimumCoastTime"),
- trans.get("simpanel.col.OptimumCoastTime.ttip"),
- UnitGroup.UNITS_SHORT_TIME) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null || data.getBranchCount() == 0)
- return null;
-
- double val = data.getBranch(0).getOptimumDelay();
- if ( Double.isNaN(val) ) {
- return null;
- }
- return val;
- }
- },
-
- //// Maximum velocity
- new ValueColumn(trans.get("simpanel.col.Maxvelocity"), UnitGroup.UNITS_VELOCITY) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null)
- return null;
-
- return data.getMaxVelocity();
- }
- },
-
- //// Maximum acceleration
- new ValueColumn(trans.get("simpanel.col.Maxacceleration"), UnitGroup.UNITS_ACCELERATION) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null)
- return null;
-
- return data.getMaxAcceleration();
- }
- },
-
- //// Time to apogee
- new ValueColumn(trans.get("simpanel.col.Timetoapogee"), UnitGroup.UNITS_FLIGHT_TIME) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null)
- return null;
-
- return data.getTimeToApogee();
- }
- },
-
- //// Flight time
- new ValueColumn(trans.get("simpanel.col.Flighttime"), UnitGroup.UNITS_FLIGHT_TIME) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null)
- return null;
-
- return data.getFlightTime();
- }
- },
-
- //// Ground hit velocity
- new ValueColumn(trans.get("simpanel.col.Groundhitvelocity"), UnitGroup.UNITS_VELOCITY) {
- @Override
- public Double valueAt(int row) {
- if (row < 0 || row >= document.getSimulationCount())
- return null;
-
- FlightData data = document.getSimulation(row).getSimulatedData();
- if (data == null)
- return null;
-
- return data.getGroundHitVelocity();
- }
- }
-
- ) {
-
- private static final long serialVersionUID = 8686456963492628476L;
-
- @Override
- public int getRowCount() {
- return document.getSimulationCount();
- }
- };
+ simulationTableModel = new SimulationTableModel();
// Override processKeyBinding so that the JTable does not catch
// key bindings used in menu accelerators
simulationTable = new ColumnTable(simulationTableModel) {
-
private static final long serialVersionUID = -5799340181229735630L;
-
- @Override
- protected boolean processKeyBinding(KeyStroke ks,
- KeyEvent e,
- int condition,
- boolean pressed) {
- return false;
- }
};
ColumnTableRowSorter simulationTableSorter = new ColumnTableRowSorter(simulationTableModel);
simulationTable.setRowSorter(simulationTableSorter);
@@ -450,14 +165,15 @@ public class SimulationPanel extends JPanel {
simulationTable.setDefaultRenderer(Object.class, new JLabelRenderer());
simulationTableModel.setColumnWidths(simulationTable.getColumnModel());
simulationTable.setFillsViewportHeight(true);
-
- pm = new JPopupMenu();
- pm.add(new EditSimulationAction());
- pm.add(new DuplicateSimulationAction());
- pm.add(new DeleteSimulationAction());
- pm.addSeparator();
- pm.add(new RunSimulationAction());
- pm.add(new PlotSimulationAction());
+
+ // Context menu
+ pm = new JPopupMenu();
+ pm.add(editSimulationAction);
+ pm.add(duplicateSimulationAction);
+ pm.add(deleteSimulationAction);
+ pm.addSeparator();
+ pm.add(runSimulationAction);
+ pm.add(plotSimulationAction);
// Mouse listener to act on double-clicks
@@ -511,11 +227,14 @@ public class SimulationPanel extends JPanel {
});
simulationTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
- private int previousRow = -1;
+ private int previousSelectedRow = -1;
+ private int previousSelectedRowCount = 0;
public void valueChanged(ListSelectionEvent event) {
- if (simulationTable.getSelectedRow() != previousRow) {
+ if ((simulationTable.getSelectedRow() != previousSelectedRow) ||
+ (simulationTable.getSelectedRowCount() != previousSelectedRowCount)) {
updateButtonStates();
- previousRow = simulationTable.getSelectedRow();
+ previousSelectedRow = simulationTable.getSelectedRow();
+ previousSelectedRowCount = simulationTable.getSelectedRowCount();
}
}
});
@@ -547,6 +266,19 @@ public class SimulationPanel extends JPanel {
updateButtonStates();
}
+ private void newSimulation() {
+ Simulation sim = new Simulation(document.getRocket());
+ sim.setName(document.getNextSimulationName());
+
+ int n = document.getSimulationCount();
+ document.addSimulation(sim);
+ simulationTableModel.fireTableDataChanged();
+ simulationTable.clearSelection();
+ simulationTable.addRowSelectionInterval(n, n);
+
+ openDialog(false, sim);
+ }
+
private void plotSimulation() {
int selected = simulationTable.getSelectedRow();
if (selected < 0) {
@@ -705,23 +437,11 @@ public class SimulationPanel extends JPanel {
}
private void updateButtonStates() {
- int[] selection = simulationTable.getSelectedRows();
- if (selection.length == 0) {
- editButton.setEnabled(false);
- runButton.setEnabled(false);
- deleteButton.setEnabled(false);
- plotButton.setEnabled(false);
- } else {
- if (selection.length > 1) {
- plotButton.setEnabled(false);
- } else {
- plotButton.setEnabled(true);
- }
- editButton.setEnabled(true);
- runButton.setEnabled(true);
- deleteButton.setEnabled(true);
- }
-
+ editSimulationAction.updateEnabledState();
+ deleteSimulationAction.updateEnabledState();
+ runSimulationAction.updateEnabledState();
+ plotSimulationAction.updateEnabledState();
+ duplicateSimulationAction.updateEnabledState();
}
/// when the simulation tab is selected this run outdated simulated if appropriate.
@@ -792,10 +512,33 @@ public class SimulationPanel extends JPanel {
break;
simulationTable.addRowSelectionInterval(row, row);
}
- simulationTable.requestFocusInWindow();
}
- class EditSimulationAction extends AbstractAction {
+ private abstract static class SimulationAction extends AbstractAction {
+ private static final long serialVersionUID = 1L;
+
+ public abstract void updateEnabledState();
+ }
+
+ class NewSimulationAction extends SimulationAction {
+ public NewSimulationAction() {
+ putValue(NAME, trans.get("simpanel.but.newsimulation"));
+ this.putValue(MNEMONIC_KEY, KeyEvent.VK_N);
+ this.putValue(SMALL_ICON, Icons.FILE_NEW);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ newSimulation();
+ }
+
+ @Override
+ public void updateEnabledState() {
+ setEnabled(true);
+ }
+ }
+
+ class EditSimulationAction extends SimulationAction {
public EditSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.edit"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_E);
@@ -807,9 +550,14 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) {
editSimulation();
}
+
+ @Override
+ public void updateEnabledState() {
+ setEnabled(simulationTable.getSelectedRowCount() == 1);
+ }
}
- class RunSimulationAction extends AbstractAction {
+ class RunSimulationAction extends SimulationAction {
public RunSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.run"));
putValue(SMALL_ICON, Icons.SIM_RUN);
@@ -819,9 +567,14 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) {
runSimulation();
}
+
+ @Override
+ public void updateEnabledState() {
+ setEnabled(simulationTable.getSelectedRowCount() > 0);
+ }
}
- class DeleteSimulationAction extends AbstractAction {
+ class DeleteSimulationAction extends SimulationAction {
public DeleteSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.delete"));
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
@@ -833,9 +586,14 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) {
deleteSimulation();
}
+
+ @Override
+ public void updateEnabledState() {
+ setEnabled(simulationTable.getSelectedRowCount() > 0);
+ }
}
- class PlotSimulationAction extends AbstractAction {
+ class PlotSimulationAction extends SimulationAction {
public PlotSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.plot"));
putValue(SMALL_ICON, Icons.SIM_PLOT);
@@ -845,9 +603,14 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) {
plotSimulation();
}
+
+ @Override
+ public void updateEnabledState() {
+ setEnabled(simulationTable.getSelectedRowCount() == 1);
+ }
}
- class DuplicateSimulationAction extends AbstractAction {
+ class DuplicateSimulationAction extends SimulationAction {
public DuplicateSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.duplicate"));
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
@@ -859,7 +622,12 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) {
duplicateSimulation();
}
- }
+
+ @Override
+ public void updateEnabledState() {
+ setEnabled(simulationTable.getSelectedRowCount() > 0);
+ }
+ }
public static class CellTransferable implements Transferable {
@@ -972,7 +740,255 @@ public class SimulationPanel extends JPanel {
return tip;
}
+ }
+ private class SimulationTableModel extends ColumnTableModel {
+ private static final long serialVersionUID = 8686456963492628476L;
+
+ public SimulationTableModel() {
+ super(
+ //// Status and warning column
+ new Column("") {
+ private JLabel label = null;
+
+ @Override
+ public Object getValueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ // Initialize the label
+ if (label == null) {
+ label = new StyledLabel(2f);
+ label.setIconTextGap(1);
+ // label.setFont(label.getFont().deriveFont(Font.BOLD));
+ }
+
+ // Set simulation status icon
+ Simulation.Status status = document.getSimulation(row).getStatus();
+ label.setIcon(Icons.SIMULATION_STATUS_ICON_MAP.get(status));
+
+
+ // Set warning marker
+ if (status == Simulation.Status.NOT_SIMULATED ||
+ status == Simulation.Status.EXTERNAL) {
+
+ label.setText("");
+
+ } else {
+
+ WarningSet w = document.getSimulation(row).getSimulatedWarnings();
+ if (w == null) {
+ label.setText("");
+ } else if (w.isEmpty()) {
+ label.setForeground(OK_COLOR);
+ label.setText(OK_TEXT);
+ } else {
+ label.setForeground(WARNING_COLOR);
+ label.setText(WARNING_TEXT);
+ }
+ }
+
+ return label;
+ }
+
+ @Override
+ public int getExactWidth() {
+ return 36;
+ }
+
+ @Override
+ public Class> getColumnClass() {
+ return JLabel.class;
+ }
+ },
+
+ //// Simulation name
+ //// Name
+ new Column(trans.get("simpanel.col.Name")) {
+ @Override
+ public Object getValueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+ return document.getSimulation(row).getName();
+ }
+
+ @Override
+ public int getDefaultWidth() {
+ return 125;
+ }
+
+ @Override
+ public Comparator getComparator() {
+ return new AlphanumComparator();
+ }
+ },
+
+ //// Simulation configuration
+ new Column(trans.get("simpanel.col.Configuration")) {
+ @Override
+ public Object getValueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount()) {
+ return null;
+ }
+
+ Rocket rkt = document.getRocket();
+ FlightConfigurationId fcid = document.getSimulation(row).getId();
+ return descriptor.format(rkt, fcid);
+ }
+
+ @Override
+ public int getDefaultWidth() {
+ return 125;
+ }
+ },
+
+ //// Launch rod velocity
+ new ValueColumn(trans.get("simpanel.col.Velocityoffrod"), UnitGroup.UNITS_VELOCITY) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null)
+ return null;
+
+ return data.getLaunchRodVelocity();
+ }
+
+ },
+
+ //// Apogee
+ new ValueColumn(trans.get("simpanel.col.Apogee"), UnitGroup.UNITS_DISTANCE) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null)
+ return null;
+
+ return data.getMaxAltitude();
+ }
+ },
+
+ //// Velocity at deployment
+ new ValueColumn(trans.get("simpanel.col.Velocityatdeploy"), UnitGroup.UNITS_VELOCITY) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null)
+ return null;
+
+ return data.getDeploymentVelocity();
+ }
+ },
+
+ //// Deployment Time from Apogee
+ new ValueColumn(trans.get("simpanel.col.OptimumCoastTime"),
+ trans.get("simpanel.col.OptimumCoastTime.ttip"), UnitGroup.UNITS_SHORT_TIME) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null || data.getBranchCount() == 0)
+ return null;
+
+ double val = data.getBranch(0).getOptimumDelay();
+ if (Double.isNaN(val)) {
+ return null;
+ }
+ return val;
+ }
+ },
+
+ //// Maximum velocity
+ new ValueColumn(trans.get("simpanel.col.Maxvelocity"), UnitGroup.UNITS_VELOCITY) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null)
+ return null;
+
+ return data.getMaxVelocity();
+ }
+ },
+
+ //// Maximum acceleration
+ new ValueColumn(trans.get("simpanel.col.Maxacceleration"), UnitGroup.UNITS_ACCELERATION) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null)
+ return null;
+
+ return data.getMaxAcceleration();
+ }
+ },
+
+ //// Time to apogee
+ new ValueColumn(trans.get("simpanel.col.Timetoapogee"), UnitGroup.UNITS_FLIGHT_TIME) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null)
+ return null;
+
+ return data.getTimeToApogee();
+ }
+ },
+
+ //// Flight time
+ new ValueColumn(trans.get("simpanel.col.Flighttime"), UnitGroup.UNITS_FLIGHT_TIME) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null)
+ return null;
+
+ return data.getFlightTime();
+ }
+ },
+
+ //// Ground hit velocity
+ new ValueColumn(trans.get("simpanel.col.Groundhitvelocity"), UnitGroup.UNITS_VELOCITY) {
+ @Override
+ public Double valueAt(int row) {
+ if (row < 0 || row >= document.getSimulationCount())
+ return null;
+
+ FlightData data = document.getSimulation(row).getSimulatedData();
+ if (data == null)
+ return null;
+
+ return data.getGroundHitVelocity();
+ }
+ }
+ );
+ }
+
+ @Override
+ public int getRowCount() {
+ return document.getSimulationCount();
+ }
}
/**
diff --git a/swing/src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java b/swing/src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java
index a02e626f9..a638ba8d0 100644
--- a/swing/src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java
+++ b/swing/src/net/sf/openrocket/gui/main/componenttree/ComponentTree.java
@@ -6,6 +6,9 @@ import javax.swing.ToolTipManager;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.components.BasicTree;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
@SuppressWarnings("serial")
public class ComponentTree extends BasicTree {
@@ -13,7 +16,21 @@ public class ComponentTree extends BasicTree {
public ComponentTree(OpenRocketDocument document) {
super();
this.setModel(new ComponentTreeModel(document.getRocket(), this));
-
+
+ addKeyListener(new KeyListener() {
+ @Override
+ public void keyTyped(KeyEvent e) { }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if ((e.getKeyCode() == KeyEvent.VK_A) && ((e.getModifiersEx() & KeyEvent.META_DOWN_MASK) != 0)) {
+ setSelectionInterval(1, getRowCount()); // Don't select the rocket (row 0)
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) { }
+ });
this.setCellRenderer(new ComponentTreeRenderer());
this.setDragEnabled(true);