Merge branch 'unstable' into issue-1558

# Conflicts:
#	swing/src/net/sf/openrocket/gui/main/BasicFrame.java
#	swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
This commit is contained in:
SiboVG 2022-07-28 23:27:30 +02:00
commit f90934d724
8 changed files with 426 additions and 351 deletions

View File

@ -2099,7 +2099,7 @@ ComponentPresetChooserDialog.menu.sortDesc = Sort Descending
ComponentPresetChooserDialog.menu.units = Units ComponentPresetChooserDialog.menu.units = Units
ComponentPresetChooserDialog.checkbox.showAllCompatible = Show all compatible ComponentPresetChooserDialog.checkbox.showAllCompatible = Show all compatible
ComponentPresetChooserDialog.checkbox.showLegacyCheckBox = Show Legacy Database 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<br>Directly apply a preset by double-clicking it or by selecting it and closing this window.
table.column.Favorite = Favorite table.column.Favorite = Favorite
table.column.Legacy = Legacy table.column.Legacy = Legacy
table.column.Manufacturer = Manufacturer table.column.Manufacturer = Manufacturer

View File

@ -25,6 +25,7 @@ import javax.swing.table.TableColumn;
import javax.swing.table.TableModel; import javax.swing.table.TableModel;
import net.miginfocom.swing.MigLayout; 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.GUIUtil;
import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.l10n.Translator;
@ -152,7 +153,7 @@ public class ComponentPresetChooserDialog extends JDialog {
scrollpane.setViewportView(componentSelectionTable); scrollpane.setViewportView(componentSelectionTable);
panel.add(scrollpane, "grow, width 700lp, height 300lp, pushy, spanx, wrap rel"); 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("<html>%s %s</html>", Chars.UP_ARROW, trans.get("lbl.favorites")), -1), "spanx, gapleft 5px, wrap para");
// Close buttons // Close buttons

View File

@ -77,9 +77,11 @@ public class ComponentPresetTable extends JTable {
if ( columnIndex != 0 ) { if ( columnIndex != 0 ) {
return; return;
} }
int selectedRow = ComponentPresetTable.this.getSelectedRow();
ComponentPreset preset = ComponentPresetTable.this.presets.get(rowIndex); ComponentPreset preset = ComponentPresetTable.this.presets.get(rowIndex);
Application.getComponentPresetDao().setFavorite(preset, presetType, (Boolean) aValue); Application.getComponentPresetDao().setFavorite(preset, presetType, (Boolean) aValue);
ComponentPresetTable.this.updateFavorites(); ComponentPresetTable.this.updateFavorites();
ComponentPresetTable.this.setRowSelectionInterval(selectedRow, selectedRow);
} }
@Override @Override

View File

@ -33,7 +33,7 @@ public abstract class ComponentPresetTableColumn extends TableColumn {
@Override @Override
public Object getValueFromPreset( Set<String> favorites, ComponentPreset preset ) { public Object getValueFromPreset( Set<String> favorites, ComponentPreset preset ) {
return Boolean.valueOf(favorites.contains(preset.preferenceKey())); return favorites.contains(preset.preferenceKey());
} }
} }

View File

@ -4,7 +4,9 @@ import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.io.File; import java.io.File;
@ -17,12 +19,16 @@ import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.BevelBorder; import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreePath; import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel; 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.figure3d.photo.PhotoFrame;
import net.sf.openrocket.gui.help.tours.GuidedTourSelectionDialog; import net.sf.openrocket.gui.help.tours.GuidedTourSelectionDialog;
import net.sf.openrocket.gui.main.componenttree.ComponentTree; 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.scalefigure.RocketPanel;
import net.sf.openrocket.gui.util.DummyFrameMenuOSX; import net.sf.openrocket.gui.util.DummyFrameMenuOSX;
import net.sf.openrocket.gui.util.FileHelper; 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.OpenFileWorker;
import net.sf.openrocket.gui.util.SaveFileWorker; import net.sf.openrocket.gui.util.SaveFileWorker;
import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.gui.widgets.SelectColorButton;
import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.Markers; import net.sf.openrocket.logging.Markers;
import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent; import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener; import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.PodSet;
import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application; import net.sf.openrocket.startup.Application;

View File

@ -12,6 +12,7 @@ import java.util.List;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -189,6 +190,35 @@ public class RocketActions {
return moveDownAction; 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 //////// Helper methods for the actions

View File

@ -98,351 +98,66 @@ public class SimulationPanel extends JPanel {
private final JButton plotButton; private final JButton plotButton;
private final JPopupMenu pm; 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) { public SimulationPanel(OpenRocketDocument doc) {
super(new MigLayout("fill", "[grow][][][][][][grow]")); super(new MigLayout("fill", "[grow][][][][][][grow]"));
this.document = doc; 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 //// New simulation button
{ JButton newButton = new SelectColorButton();
JButton button = new SelectColorButton(trans.get("simpanel.but.newsimulation")); RocketActions.tieActionToButtonNoIcon(newButton, newSimulationAction, trans.get("simpanel.but.newsimulation"));
//// Add a new simulation newButton.setToolTipText(trans.get("simpanel.but.ttip.newsimulation"));
button.setToolTipText(trans.get("simpanel.but.ttip.newsimulation")); this.add(newButton, "skip 1, gapright para");
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");
}
//// Edit simulation button //// Edit simulation button
editButton = new SelectColorButton(trans.get("simpanel.but.editsimulation")); editButton = new SelectColorButton();
//// Edit the selected simulation RocketActions.tieActionToButtonNoIcon(editButton, editSimulationAction, trans.get("simpanel.but.editsimulation"));
editButton.setToolTipText(trans.get("simpanel.but.ttip.editsim")); editButton.setToolTipText(trans.get("simpanel.but.ttip.editsim"));
editButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
editSimulation();
}
});
this.add(editButton, "gapright para"); this.add(editButton, "gapright para");
//// Run simulations //// Run simulations
runButton = new SelectColorButton(trans.get("simpanel.but.runsimulations")); runButton = new SelectColorButton();
//// Re-run the selected simulations RocketActions.tieActionToButtonNoIcon(runButton, runSimulationAction, trans.get("simpanel.but.runsimulations"));
runButton.setToolTipText(trans.get("simpanel.but.ttip.runsimu")); runButton.setToolTipText(trans.get("simpanel.but.ttip.runsimu"));
runButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
runSimulation();
}
});
this.add(runButton, "gapright para"); this.add(runButton, "gapright para");
//// Delete simulations button //// Delete simulations button
deleteButton = new SelectColorButton(trans.get("simpanel.but.deletesimulations")); deleteButton = new SelectColorButton();
//// Delete the selected simulations RocketActions.tieActionToButtonNoIcon(deleteButton, deleteSimulationAction, trans.get("simpanel.but.deletesimulations"));
deleteButton.setToolTipText(trans.get("simpanel.but.ttip.deletesim")); deleteButton.setToolTipText(trans.get("simpanel.but.ttip.deletesim"));
deleteButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteSimulation();
}
});
this.add(deleteButton, "gapright para"); this.add(deleteButton, "gapright para");
//// Plot / export button //// Plot / export button
plotButton = new SelectColorButton(trans.get("simpanel.but.plotexport")); plotButton = new SelectColorButton();
// button = new SelectColorButton("Plot flight"); RocketActions.tieActionToButtonNoIcon(plotButton, plotSimulationAction, trans.get("simpanel.but.plotexport"));
plotButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
plotSimulation();
}
});
this.add(plotButton, "wrap para"); this.add(plotButton, "wrap para");
//////// The simulation table //////// The simulation table
simulationTableModel = new SimulationTableModel();
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<String> 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();
}
};
// Override processKeyBinding so that the JTable does not catch // Override processKeyBinding so that the JTable does not catch
// key bindings used in menu accelerators // key bindings used in menu accelerators
simulationTable = new ColumnTable(simulationTableModel) { simulationTable = new ColumnTable(simulationTableModel) {
private static final long serialVersionUID = -5799340181229735630L; 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); ColumnTableRowSorter simulationTableSorter = new ColumnTableRowSorter(simulationTableModel);
simulationTable.setRowSorter(simulationTableSorter); simulationTable.setRowSorter(simulationTableSorter);
@ -450,14 +165,15 @@ public class SimulationPanel extends JPanel {
simulationTable.setDefaultRenderer(Object.class, new JLabelRenderer()); simulationTable.setDefaultRenderer(Object.class, new JLabelRenderer());
simulationTableModel.setColumnWidths(simulationTable.getColumnModel()); simulationTableModel.setColumnWidths(simulationTable.getColumnModel());
simulationTable.setFillsViewportHeight(true); simulationTable.setFillsViewportHeight(true);
pm = new JPopupMenu(); // Context menu
pm.add(new EditSimulationAction()); pm = new JPopupMenu();
pm.add(new DuplicateSimulationAction()); pm.add(editSimulationAction);
pm.add(new DeleteSimulationAction()); pm.add(duplicateSimulationAction);
pm.addSeparator(); pm.add(deleteSimulationAction);
pm.add(new RunSimulationAction()); pm.addSeparator();
pm.add(new PlotSimulationAction()); pm.add(runSimulationAction);
pm.add(plotSimulationAction);
// Mouse listener to act on double-clicks // Mouse listener to act on double-clicks
@ -511,11 +227,14 @@ public class SimulationPanel extends JPanel {
}); });
simulationTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { simulationTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
private int previousRow = -1; private int previousSelectedRow = -1;
private int previousSelectedRowCount = 0;
public void valueChanged(ListSelectionEvent event) { public void valueChanged(ListSelectionEvent event) {
if (simulationTable.getSelectedRow() != previousRow) { if ((simulationTable.getSelectedRow() != previousSelectedRow) ||
(simulationTable.getSelectedRowCount() != previousSelectedRowCount)) {
updateButtonStates(); updateButtonStates();
previousRow = simulationTable.getSelectedRow(); previousSelectedRow = simulationTable.getSelectedRow();
previousSelectedRowCount = simulationTable.getSelectedRowCount();
} }
} }
}); });
@ -547,6 +266,19 @@ public class SimulationPanel extends JPanel {
updateButtonStates(); 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() { private void plotSimulation() {
int selected = simulationTable.getSelectedRow(); int selected = simulationTable.getSelectedRow();
if (selected < 0) { if (selected < 0) {
@ -705,23 +437,11 @@ public class SimulationPanel extends JPanel {
} }
private void updateButtonStates() { private void updateButtonStates() {
int[] selection = simulationTable.getSelectedRows(); editSimulationAction.updateEnabledState();
if (selection.length == 0) { deleteSimulationAction.updateEnabledState();
editButton.setEnabled(false); runSimulationAction.updateEnabledState();
runButton.setEnabled(false); plotSimulationAction.updateEnabledState();
deleteButton.setEnabled(false); duplicateSimulationAction.updateEnabledState();
plotButton.setEnabled(false);
} else {
if (selection.length > 1) {
plotButton.setEnabled(false);
} else {
plotButton.setEnabled(true);
}
editButton.setEnabled(true);
runButton.setEnabled(true);
deleteButton.setEnabled(true);
}
} }
/// when the simulation tab is selected this run outdated simulated if appropriate. /// when the simulation tab is selected this run outdated simulated if appropriate.
@ -792,10 +512,33 @@ public class SimulationPanel extends JPanel {
break; break;
simulationTable.addRowSelectionInterval(row, row); 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() { public EditSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.edit")); putValue(NAME, trans.get("simpanel.pop.edit"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_E); this.putValue(MNEMONIC_KEY, KeyEvent.VK_E);
@ -807,9 +550,14 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
editSimulation(); editSimulation();
} }
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() == 1);
}
} }
class RunSimulationAction extends AbstractAction { class RunSimulationAction extends SimulationAction {
public RunSimulationAction() { public RunSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.run")); putValue(NAME, trans.get("simpanel.pop.run"));
putValue(SMALL_ICON, Icons.SIM_RUN); putValue(SMALL_ICON, Icons.SIM_RUN);
@ -819,9 +567,14 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
runSimulation(); runSimulation();
} }
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() > 0);
}
} }
class DeleteSimulationAction extends AbstractAction { class DeleteSimulationAction extends SimulationAction {
public DeleteSimulationAction() { public DeleteSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.delete")); putValue(NAME, trans.get("simpanel.pop.delete"));
putValue(MNEMONIC_KEY, KeyEvent.VK_D); putValue(MNEMONIC_KEY, KeyEvent.VK_D);
@ -833,9 +586,14 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
deleteSimulation(); deleteSimulation();
} }
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() > 0);
}
} }
class PlotSimulationAction extends AbstractAction { class PlotSimulationAction extends SimulationAction {
public PlotSimulationAction() { public PlotSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.plot")); putValue(NAME, trans.get("simpanel.pop.plot"));
putValue(SMALL_ICON, Icons.SIM_PLOT); putValue(SMALL_ICON, Icons.SIM_PLOT);
@ -845,9 +603,14 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
plotSimulation(); plotSimulation();
} }
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() == 1);
}
} }
class DuplicateSimulationAction extends AbstractAction { class DuplicateSimulationAction extends SimulationAction {
public DuplicateSimulationAction() { public DuplicateSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.duplicate")); putValue(NAME, trans.get("simpanel.pop.duplicate"));
putValue(MNEMONIC_KEY, KeyEvent.VK_D); putValue(MNEMONIC_KEY, KeyEvent.VK_D);
@ -859,7 +622,12 @@ public class SimulationPanel extends JPanel {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
duplicateSimulation(); duplicateSimulation();
} }
}
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() > 0);
}
}
public static class CellTransferable implements Transferable { public static class CellTransferable implements Transferable {
@ -972,7 +740,255 @@ public class SimulationPanel extends JPanel {
return tip; 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<String> 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();
}
} }
/** /**

View File

@ -6,6 +6,9 @@ import javax.swing.ToolTipManager;
import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.components.BasicTree; import net.sf.openrocket.gui.components.BasicTree;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class ComponentTree extends BasicTree { public class ComponentTree extends BasicTree {
@ -13,7 +16,21 @@ public class ComponentTree extends BasicTree {
public ComponentTree(OpenRocketDocument document) { public ComponentTree(OpenRocketDocument document) {
super(); super();
this.setModel(new ComponentTreeModel(document.getRocket(), this)); 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.setCellRenderer(new ComponentTreeRenderer());
this.setDragEnabled(true); this.setDragEnabled(true);