Merge pull request #2275 from SiboVG/apply-copy-sim

Big cleanup of simulation table actions
This commit is contained in:
Sibo Van Gool 2023-07-31 15:47:50 +02:00 committed by GitHub
commit 596380203e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 617 additions and 601 deletions

View File

@ -16,23 +16,18 @@
debug.currentFile = messages.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Do not ask me again
RocketActions.lbl.Youcanchangedefop = You can change the default operation in the preferences.
RocketActions.showConfirmDialog.lbl1 = Delete the selected simulations?
RocketActions.showConfirmDialog.lbl2 = <html><i>This operation cannot be undone.</i>
RocketActions.showConfirmDialog.title = Delete simulations
RocketActions.DelCompAct.Delete = Delete
RocketActions.DelCompAct.ttip.Delete = Delete the selected component.
RocketActions.DelCompAct.ttip.Delete = Delete the selected components.
RocketActions.DelSimuAct.Delete = Delete
RocketActions.DelSimuAct.ttip.Delete = Delete the selected simulation.
RocketActions.DelSimuAct.ttip.Delete = Delete the selected simulations.
RocketActions.DelAct.Delete = Delete
RocketActions.DelAct.ttip.Delete = Delete the selected component or simulation.
RocketActions.DelAct.ttip.Delete = Delete the selected components or simulations.
RocketActions.CutAction.Cut = Cut
RocketActions.CutAction.ttip.Cut = Cut this component or simulation to the clipboard and delete from this design
RocketActions.CutAction.ttip.Cut = Cut these components or simulations to the clipboard and delete from this design
RocketActions.CopyAct.Copy = Copy
RocketActions.CopyAct.ttip.Copy = Copy this component (and subcomponents) to the clipboard.
RocketActions.CopyAct.ttip.Copy = Copy these components (and subcomponents) to the clipboard.
RocketActions.PasteAct.Paste = Paste
RocketActions.PasteAct.ttip.Paste = Paste the component or simulation on the clipboard to the design.
RocketActions.PasteAct.ttip.Paste = Paste the components or simulations on the clipboard to the design.
RocketActions.PasteAct.invalidPosition.msg = Invalid paste position for object '%s', ignoring pasting.
RocketActions.PasteAct.invalidPosition.title = Could not paste
RocketActions.DuplicateAct.Duplicate = Duplicate
@ -581,11 +576,21 @@ simpanel.but.ttip.editsim = Edit the selected simulation
simpanel.but.ttip.runsimu = Re-run the selected simulations
simpanel.but.ttip.deletesim = Delete the selected simulations
simpanel.pop.edit = Edit
simpanel.pop.copyValues = Copy values
simpanel.pop.edit.ttip= Edit the selected simulation(s)
simpanel.pop.cut= Cut
simpanel.pop.cut.ttip= Copy the selected simulation(s) to the clipboard and delete from this design
simpanel.pop.copy= Copy
simpanel.pop.copy.ttip= Copy the selected simulation(s) to the clipboard
simpanel.pop.paste= Paste
simpanel.pop.paste.ttip= Paste the simulation(s) on the clipboard to the design.
simpanel.pop.plot = Plot / Export
simpanel.pop.plot.ttip= Plot or Export the selected simulation(s)
simpanel.pop.run = Run
simpanel.pop.run.ttip= Run the selected simulation(s)
simpanel.pop.delete = Delete
simpanel.pop.delete.ttip= Delete the selected simulation(s)
simpanel.pop.duplicate = Duplicate
simpanel.pop.duplicate.ttip= Duplicate the selected simulation(s)
simpanel.pop.exportSimTableToCSV = Export simulation table as CSV file
simpanel.pop.exportSelectedSimsToCSV = Export simulation(s) as CSV file
simpanel.pop.exportToCSV.save.dialog.title = Save as CSV file
@ -617,6 +622,7 @@ simpanel.ttip.notSimulated = <i>Not simulated yet</i><br>Click <i><b>Run simulat
simpanel.ttip.noData = No simulation data available.
simpanel.ttip.noWarnings = <font color=\"gray\">No warnings.</font>
simpanel.ttip.warnings = <font color=\"red\">Warnings:</font>
simpanel.msg.invalidCopySelection = Invalid copy selection
! SimulationRunDialog
SimuRunDlg.title.RunSim = Running simulations\u2026

View File

@ -16,11 +16,6 @@
debug.currentFile = messages_ar.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = لا تسألني مجددا
RocketActions.lbl.Youcanchangedefop = يمكنك تغيير العملية الافتراضية في التفضيلات.
RocketActions.showConfirmDialog.lbl1 = إحذف المحاكاة المختارة؟
RocketActions.showConfirmDialog.lbl2 = <html><i>لا يمكنك التراجع عن هذه العملية.</i>
RocketActions.showConfirmDialog.title = إحذف كل المحاكاة
RocketActions.DelCompAct.Delete = إحذف
RocketActions.DelCompAct.ttip.Delete = إحذف القطعة المختارة
RocketActions.DelSimuAct.Delete = إحذف

View File

@ -16,11 +16,6 @@
debug.currentFile = messages_cs.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Prí\u0161te se me neptejte
RocketActions.lbl.Youcanchangedefop = Mu\u017Eete zmenit výchozí operaci v nastavení.
RocketActions.showConfirmDialog.lbl1 = Chcete smazat oznacenou simulaci?
RocketActions.showConfirmDialog.lbl2 = <html><i>Tuto operaci nelze vzít zpet.</i>
RocketActions.showConfirmDialog.title = Sma\u017E simulace
RocketActions.DelCompAct.Delete = Sma\u017E
RocketActions.DelCompAct.ttip.Delete = Sma\u017E oznacenou komponentu.
RocketActions.DelSimuAct.Delete = Sma\u017E

View File

@ -16,11 +16,6 @@
debug.currentFile = messages_de.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Nicht wieder fragen
RocketActions.lbl.Youcanchangedefop = Die Standardaktion kann in den Einstellungen geändert werden.
RocketActions.showConfirmDialog.lbl1 = Simulationen löschen?
RocketActions.showConfirmDialog.lbl2 = <html><i>Diese Aktion kann nicht rückgängig gemacht werden.</i>
RocketActions.showConfirmDialog.title = Simulationen löschen
RocketActions.DelCompAct.Delete = Löschen
RocketActions.DelCompAct.ttip.Delete = Die ausgewählte Komponente löschen.
RocketActions.DelSimuAct.Delete = Löschen

View File

@ -811,12 +811,6 @@ RocketActions.NewStageAct.Newstage = Nueva etapa
RocketActions.NewStageAct.ttip.Newstage = A\u00f1adir una nueva etapa al dise\u00f1o del cohete
RocketActions.PasteAct.Paste = Pegar
RocketActions.PasteAct.ttip.Paste = Pegar al portapapeles
! RocketActions
RocketActions.checkbox.Donotaskmeagain = No volver a preguntarme
RocketActions.lbl.Youcanchangedefop = Puede modificar la operaci\u00f3n por defecto con sus preferencias
RocketActions.showConfirmDialog.lbl1 = \u00bfBorrar las simulaciones seleccionadas?
RocketActions.showConfirmDialog.lbl2 = <html><i>Esta operaci\u00f3n no puede deshacerse.</i>
RocketActions.showConfirmDialog.title = Borrar simulaciones
RocketCfg.lbl.Comments = Comentarios:
RocketCfg.lbl.Designer = Dise\u00f1ador:

View File

@ -802,12 +802,6 @@ RocketActions.NewStageAct.Newstage = Nouvel \u00E9tage
RocketActions.NewStageAct.ttip.Newstage = Ajouter un nouvel \u00E9tage au projet.
RocketActions.PasteAct.Paste = Coller
RocketActions.PasteAct.ttip.Paste = Coller la pi\u00E8ce ou simulation pr\u00E9sente dans le presse papier dans le projet.
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Ne plus me demander
RocketActions.lbl.Youcanchangedefop = Vous pouvez changer le mode op\u00E9ratoire par d\u00E9faut dans les pr\u00E9ferences.
RocketActions.showConfirmDialog.lbl1 = Supprimer les simulations s\u00E9lectionn\u00E9es?
RocketActions.showConfirmDialog.lbl2 = <html><i>Cette op\u00E9ration n'est pas r\u00E9versible.</i>
RocketActions.showConfirmDialog.title = Effacer les simulations
RocketCfg.lbl.Comments = Commentaires:
RocketCfg.lbl.Designer = Concepteur:

View File

@ -16,11 +16,6 @@
debug.currentFile = messages_it.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Non chiedermelo piu'
RocketActions.lbl.Youcanchangedefop = Puoi cambiare le operazioni prestabilite in PREFERENZE.
RocketActions.showConfirmDialog.lbl1 = Cancello le simulazioni selezionate?
RocketActions.showConfirmDialog.lbl2 = <html><i>Questa operazione non puo' essere annullata.</i>
RocketActions.showConfirmDialog.title = Cancello Simulazioni
RocketActions.DelCompAct.Delete = Cancella
RocketActions.DelCompAct.ttip.Delete = Cancello il componente selezionato.
RocketActions.DelSimuAct.Delete = Cancella

View File

@ -12,11 +12,6 @@
debug.currentFile = messages_ja.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = \u6B21\u56DE\u304B\u3089\u8868\u793A\u3057\u306A\u3044
RocketActions.lbl.Youcanchangedefop = \u8A2D\u5B9A\u306E\u4E2D\u3067\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u5909\u66F4\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059
RocketActions.showConfirmDialog.lbl1 = \u9078\u629E\u3057\u305F\u30B7\u30DF\u30E5\u30EC\u30FC\u30B7\u30E7\u30F3\u3092\u6D88\u53BB\u3057\u307E\u3059\u304B\uFF1F
RocketActions.showConfirmDialog.lbl2 = <html><i>\u6D88\u53BB\u3057\u305F\u3089\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093</i>
RocketActions.showConfirmDialog.title = \u30B7\u30DF\u30E5\u30EC\u30FC\u30B7\u30E7\u30F3\u306E\u524A\u9664
RocketActions.DelCompAct.Delete = \u524A\u9664
RocketActions.DelCompAct.ttip.Delete = \u9078\u629E\u3057\u305F\u90E8\u54C1\u306E\u524A\u9664
RocketActions.DelSimuAct.Delete = \u524A\u9664

View File

@ -18,11 +18,6 @@
debug.currentFile = messages_nl.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Niet opnieuw vragen
RocketActions.lbl.Youcanchangedefop = U kan de standaardbewerking veranderen in de voorkeuren.
RocketActions.showConfirmDialog.lbl1 = Geselecteerde simulatie verwijderen?
RocketActions.showConfirmDialog.lbl2 = <html><i>Deze bewerking kan niet ongedaan worden.</i>
RocketActions.showConfirmDialog.title = Verwijder simulaties
RocketActions.DelCompAct.Delete = Verwijder
RocketActions.DelCompAct.ttip.Delete = Verwijder het geselecteerde onderdeel.
RocketActions.DelSimuAct.Delete = Verwijder

View File

@ -16,11 +16,6 @@
debug.currentFile = messages_pl.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Nie pytaj ponownie
RocketActions.lbl.Youcanchangedefop = Domy\u015Bln\u0105 operacj\u0119 mo\u017Cna zmieni\u0107 w ustawieniach.
RocketActions.showConfirmDialog.lbl1 = Usun\u0105\u0107 zaznaczone symulacje?
RocketActions.showConfirmDialog.lbl2 = <html><i>Tej operacji nie mo\u017Cna cofn\u0105\u0107.</i>
RocketActions.showConfirmDialog.title = Usu\u0144 symulacje
RocketActions.DelCompAct.Delete = Usu\u0144
RocketActions.DelCompAct.ttip.Delete = Usu\u0144 wybran\u0105 cz\u0119\u015B\u0107
RocketActions.DelSimuAct.Delete = Usu\u0144

View File

@ -786,12 +786,6 @@ RocketActions.NewStageAct.Newstage = Novo est\u00e1gio
RocketActions.NewStageAct.ttip.Newstage = Adicionar um novo est\u00e1gio ao projeto do foguete.
RocketActions.PasteAct.Paste = Colar
RocketActions.PasteAct.ttip.Paste = Cole o componente ou simula\u00e7\u00e3o na \u00e1rea da transfer\u00eancia para o projeto.
# RocketActions
RocketActions.checkbox.Donotaskmeagain = N\u00e3o me pergunte novamente
RocketActions.lbl.Youcanchangedefop = Voc\u00ea pode alterar a opera\u00e7\u00e3o padr\u00e3o em Prefer\u00eancias.
RocketActions.showConfirmDialog.lbl1 = Excluir as simula\u00e7\u00f5es selecionadas?
RocketActions.showConfirmDialog.lbl2 = <html><i>Esta opera\u00e7\u00e3o n\u00e3o poder\u00e1 ser desfeita.</i>
RocketActions.showConfirmDialog.title = Excluir simula\u00e7\u00f5es
RocketCfg.lbl.Comments = Coment\u00e1rios:
RocketCfg.lbl.Designer = Projetista:

View File

@ -16,11 +16,6 @@
debug.currentFile = messages_ru.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = \u0411\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u0441\u043F\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044C
RocketActions.lbl.Youcanchangedefop = \u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u0432 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430\u0445.
RocketActions.showConfirmDialog.lbl1 = \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0435 \u0440\u0430\u0441\u0447\u0435\u0442\u044B?
RocketActions.showConfirmDialog.lbl2 = <html><i>\u042D\u0442\u0443 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u043D\u0435\u043B\u044C\u0437\u044F \u043E\u0442\u043C\u0435\u043D\u0438\u0442\u044C.</i>
RocketActions.showConfirmDialog.title = \u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u0440\u0430\u0441\u0447\u0435\u0442\u043E\u0432
RocketActions.DelCompAct.Delete = \u0423\u0434\u0430\u043B\u0438\u0442\u044C
RocketActions.DelCompAct.ttip.Delete = \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442.
RocketActions.DelSimuAct.Delete = \u0423\u0434\u0430\u043B\u0438\u0442\u044C

View File

@ -17,12 +17,6 @@ purposes)
debug.currentFile = messages.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = Yeniden Tekrarlama
RocketActions.lbl.Youcanchangedefop = Hatal\u0131 \u00c7al\u0131\u015fmay\u0131 De\u011fi\u015ftirebilirsin
in the preferences.
RocketActions.showConfirmDialog.lbl1 = Se\u00e7ili sim\u00fclasyonlar\u0131 silmek ister misiniz?
RocketActions.showConfirmDialog.lbl2 = <html><i>Bu \u00e7al\u0131\u015fma tamamlanmad\u0131.</i>
RocketActions.showConfirmDialog.title = Sim\u00fclasyonlar\u0131 Sil
RocketActions.DelCompAct.Delete = Sil
RocketActions.DelCompAct.ttip.Delete = Se\u00e7ili par\u00e7ay\u0131 sil.
RocketActions.DelSimuAct.Delete = Sil

View File

@ -18,11 +18,6 @@
debug.currentFile = messages.properties
! RocketActions
RocketActions.checkbox.Donotaskmeagain = \u0411\u0456\u043B\u044C\u0448\u0435 \u043D\u0435 \u043F\u0438\u0442\u0430\u0442\u0438
RocketActions.lbl.Youcanchangedefop = \u0412\u0438 \u043C\u043E\u0436\u0435\u0442\u0435 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u0442\u0438\u043F\u043E\u0432\u0443 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432 \u043E\u043F\u0446\u0438\u044F\u0445.
RocketActions.showConfirmDialog.lbl1 = \u0412\u0434\u0430\u043B\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043D\u0443 \u0441\u0438\u043C\u0443\u043B\u044F\u0446\u0456\u044E?
RocketActions.showConfirmDialog.lbl2 = <html><i>\u0426\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u043D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0456\u0434\u043C\u0456\u043D\u0435\u043D\u0430.</i>
RocketActions.showConfirmDialog.title = \u0412\u0434\u0430\u043B\u0438\u0442\u0438 \u0441\u0438\u043C\u0443\u043B\u044F\u0446\u0456\u044E
RocketActions.DelCompAct.Delete = \u0412\u0434\u0430\u043B\u0438\u0442\u0438
RocketActions.DelCompAct.ttip.Delete = \u0412\u0434\u0430\u043B\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043D\u0443 \u0447\u0430\u0441\u0442\u0438\u043D\u0443.
RocketActions.DelSimuAct.Delete = \u0412\u0434\u0430\u043B\u0438\u0442\u0438

View File

@ -875,12 +875,6 @@ RocketActions.NewStageAct.Newstage = \u65B0\u5EFA\u4E00\u7EA7
RocketActions.NewStageAct.ttip.Newstage = \u5728\u8BBE\u8BA1\u4E2D\u65B0\u5EFA\u4E00\u7EA7
RocketActions.PasteAct.Paste = \u7C98\u8D34
RocketActions.PasteAct.ttip.Paste = \u5C06\u526A\u8D34\u677F\u91CC\u7684\u90E8\u4EF6\u6216\u4EFF\u771F\u7C98\u8D34\u5230\u8BE5\u8BBE\u8BA1\u4E2D
! RocketActions
RocketActions.checkbox.Donotaskmeagain = \u4E0D\u518D\u63D0\u793A
RocketActions.lbl.Youcanchangedefop = \u4F60\u53EF\u4EE5\u4FEE\u6539\u7F3A\u7701\u8BBE\u7F6E
RocketActions.showConfirmDialog.lbl1 = \u5220\u9664\u9009\u5B9A\u4EFF\u771F?
RocketActions.showConfirmDialog.lbl2 = <html><i>\u8BE5\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500</i>
RocketActions.showConfirmDialog.title = \u5220\u9664\u4EFF\u771F
RocketCfg.lbl.Comments = \u6CE8\u91CA:
RocketCfg.lbl.Designer = \u8BBE\u8BA1\u4EBA:

View File

@ -383,12 +383,7 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
* @param simulation the simulation to be added
*/
public void addSimulation(Simulation simulation) {
simulations.add(simulation);
FlightConfigurationId simId = simulation.getId();
if( !rocket.containsFlightConfigurationID( simId )){
rocket.createFlightConfiguration(simId);
}
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
addSimulation(simulation, simulations.size());
}
/**
@ -399,6 +394,10 @@ public class OpenRocketDocument implements ComponentChangeListener, StateChangeL
*/
public void addSimulation(Simulation simulation, int n) {
simulations.add(n, simulation);
FlightConfigurationId simId = simulation.getId();
if( !rocket.containsFlightConfigurationID( simId )){
rocket.createFlightConfiguration(simId);
}
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
}

View File

@ -41,7 +41,7 @@ public class SimulationPreferencesPanel extends PreferencesPanel {
confirmDelete.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
preferences.setAutoRunSimulations(confirmDelete.isSelected());
preferences.setConfirmSimDeletion(confirmDelete.isSelected());
}
});
this.add(confirmDelete, "wrap, growx, sg combos ");

View File

@ -565,12 +565,12 @@ public class BasicFrame extends JFrame {
editMenu.addSeparator();
JMenu subMenu = new JMenu(trans.get("RocketActions.Select"));
editMenu.add(subMenu);
JMenu selectSubMenu = new JMenu(trans.get("RocketActions.Select"));
editMenu.add(selectSubMenu);
item = new JMenuItem(actions.getSelectSameColorAction());
subMenu.add(item);
selectSubMenu.add(item);
item = new JMenuItem(actions.getDeselectAllAction());
subMenu.add(item);
selectSubMenu.add(item);
editMenu.addSeparator();

View File

@ -61,13 +61,13 @@ public class DesignPanel extends JSplitPane {
// Remove JTree key events that interfere with menu accelerators
InputMap im = SwingUtilities.getUIInputMap(tree, JComponent.WHEN_FOCUSED);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY), null);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY), "none");
// Highlight all child components of a stage/rocket/podset when it is selected
tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {

View File

@ -4,6 +4,7 @@ package net.sf.openrocket.gui.main;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.Serial;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -13,15 +14,13 @@ 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;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.configdialog.ComponentConfigDialog;
import net.sf.openrocket.gui.dialogs.ScaleDialog;
import net.sf.openrocket.gui.util.Icons;
@ -34,7 +33,6 @@ import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.Preferences;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Pair;
import org.slf4j.Logger;
@ -59,6 +57,7 @@ public class RocketActions {
Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx());
public static final KeyStroke EDIT_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_E,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx());
public static final KeyStroke DELETE_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
private final OpenRocketDocument document;
private final Rocket rocket;
@ -67,8 +66,6 @@ public class RocketActions {
private final SimulationPanel simulationPanel;
private final RocketAction deleteComponentAction;
private final RocketAction deleteSimulationAction;
private final RocketAction deleteAction;
private final RocketAction cutAction;
private final RocketAction copyAction;
@ -94,8 +91,6 @@ public class RocketActions {
// Add action also to updateActions()
this.deleteAction = new DeleteAction();
this.deleteComponentAction = new DeleteComponentAction();
this.deleteSimulationAction = new DeleteSimulationAction();
this.cutAction = new CutAction();
this.copyAction = new CopyAction();
this.pasteAction = new PasteAction();
@ -107,10 +102,15 @@ public class RocketActions {
this.moveUpAction = new MoveUpAction();
this.moveDownAction = new MoveDownAction();
OpenRocketClipboard.addClipboardListener(this.pasteAction);
OpenRocketClipboard.addClipboardListener(new ClipboardListener() {
@Override
public void clipboardChanged() {
updateActions();
}
});
updateActions();
// Update all actions when tree selection or rocket changes
// Update all actions when tree selection, simulation selection or rocket changes
selectionModel.addDocumentSelectionListener(new DocumentSelectionListener() {
@Override
@ -118,6 +118,12 @@ public class RocketActions {
updateActions();
}
});
simulationPanel.addSimulationTableListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
updateActions();
}
});
document.getRocket().addComponentChangeListener(new ComponentChangeListener() {
@Override
public void componentChanged(ComponentChangeEvent e) {
@ -130,12 +136,13 @@ public class RocketActions {
* Update the state of all of the actions.
*/
private void updateActions() {
deleteAction.clipboardChanged();
simulationPanel.updateActions();
editAction.clipboardChanged();
cutAction.clipboardChanged();
copyAction.clipboardChanged();
pasteAction.clipboardChanged();
deleteAction.clipboardChanged();
duplicateAction.clipboardChanged();
editAction.clipboardChanged();
selectSameColorAction.clipboardChanged();
deselectAllAction.clipboardChanged();
scaleAction.clipboardChanged();
@ -143,16 +150,8 @@ public class RocketActions {
moveDownAction.clipboardChanged();
}
public Action getDeleteComponentAction() {
return deleteAction;
}
public Action getDeleteSimulationAction() {
return deleteAction;
}
public Action getDeleteAction() {
return deleteAction;
@ -313,7 +312,7 @@ public class RocketActions {
}
private boolean isCopyable(List<RocketComponent> components) {
if (components == null || components.size() == 0) return false;
if (components == null || components.isEmpty()) return false;
for (RocketComponent component : components) {
if (!isCopyable(component)) return false;
}
@ -409,43 +408,14 @@ public class RocketActions {
private boolean isSimulationSelected() {
Simulation[] selection = selectionModel.getSelectedSimulations();
return (selection != null && selection.length > 0);
}
private boolean verifyDeleteSimulation() {
boolean verify = Application.getPreferences().getBoolean(Preferences.CONFIRM_DELETE_SIMULATION, true);
if (verify) {
JPanel panel = new JPanel(new MigLayout());
//// Do not ask me again
JCheckBox dontAsk = new JCheckBox(trans.get("RocketActions.checkbox.Donotaskmeagain"));
panel.add(dontAsk,"wrap");
//// You can change the default operation in the preferences.
panel.add(new StyledLabel(trans.get("RocketActions.lbl.Youcanchangedefop"),-2));
int ret = JOptionPane.showConfirmDialog(
parentFrame,
new Object[] {
//// Delete the selected simulations?
trans.get("RocketActions.showConfirmDialog.lbl1"),
//// <html><i>This operation cannot be undone.</i>
trans.get("RocketActions.showConfirmDialog.lbl2"),
"",
panel },
//// Delete simulations
trans.get("RocketActions.showConfirmDialog.title"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
if (ret != JOptionPane.OK_OPTION)
return false;
if (dontAsk.isSelected()) {
Application.getPreferences().putBoolean(Preferences.CONFIRM_DELETE_SIMULATION, false);
if (selection != null && selection.length > 0) {
List<RocketComponent> components = selectionModel.getSelectedComponents();
if (components != null && !components.isEmpty()) {
throw new IllegalStateException("Both simulation and component selected");
}
return true;
}
return true;
return false;
}
@ -517,130 +487,60 @@ public class RocketActions {
public abstract void clipboardChanged();
}
/**
* Action that deletes the selected component.
* Action to edit the currently selected component.
*/
private class DeleteComponentAction extends RocketAction {
private class EditAction extends RocketAction {
@Serial
private static final long serialVersionUID = 1L;
public DeleteComponentAction() {
//// Delete
this.putValue(NAME, trans.get("RocketActions.DelCompAct.Delete"));
//// Delete the selected component.
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.DelCompAct.ttip.Delete"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_D);
// this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
this.putValue(SMALL_ICON, Icons.EDIT_DELETE);
clipboardChanged();
}
@Override
public void actionPerformed(ActionEvent e) {
List<RocketComponent> components = new ArrayList<>(selectionModel.getSelectedComponents());
if (components.size() == 0) return;
components.sort(Comparator.comparing(c -> c.getParent().getChildPosition(c)));
if (components.size() == 1) {
document.addUndoPosition("Delete " + components.get(0).getComponentName());
} else {
document.addUndoPosition("Delete components");
}
for (RocketComponent component : components) {
deleteComponent(component);
}
}
private void deleteComponent(RocketComponent component) {
if (isDeletable(component)) {
ComponentConfigDialog.disposeDialog();
try {
component.getRocket().removeComponentChangeListener(ComponentConfigDialog.getDialog());
delete(component);
} catch (IllegalStateException ignored) { }
}
}
@Override
public void clipboardChanged() {
this.setEnabled(isDeletable(selectionModel.getSelectedComponent()));
}
}
/**
* Action that deletes the selected component.
*/
private class DeleteSimulationAction extends RocketAction {
private static final long serialVersionUID = 1L;
public DeleteSimulationAction() {
//// Delete
this.putValue(NAME, trans.get("RocketActions.DelSimuAct.Delete"));
//// Delete the selected simulation.
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.DelSimuAct.ttip.Delete"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_D);
// this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
this.putValue(SMALL_ICON, Icons.EDIT_DELETE);
clipboardChanged();
}
@Override
public void actionPerformed(ActionEvent e) {
Simulation[] sims = selectionModel.getSelectedSimulations();
if (sims.length > 0) {
if (verifyDeleteSimulation()) {
for (Simulation s: sims) {
document.removeSimulation(s);
}
}
}
}
@Override
public void clipboardChanged() {
this.setEnabled(isSimulationSelected());
}
}
/**
* Action that deletes the selected component.
*/
private class DeleteAction extends RocketAction {
private static final long serialVersionUID = 1L;
public DeleteAction() {
//// Delete
this.putValue(NAME, trans.get("RocketActions.DelAct.Delete"));
//// Delete the selected component or simulation.
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.DelAct.ttip.Delete"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_D);
this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
this.putValue(SMALL_ICON, Icons.EDIT_DELETE);
public EditAction() {
//// Edit
this.putValue(NAME, trans.get("RocketActions.EditAct.Edit"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_E);
this.putValue(ACCELERATOR_KEY, EDIT_KEY_STROKE);
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.EditAct.ttip.Edit"));
this.putValue(SMALL_ICON, Icons.EDIT_EDIT);
clipboardChanged();
}
@Override
public void actionPerformed(ActionEvent e) {
if (isSimulationSelected()) {
deleteSimulationAction.actionPerformed(e);
simulationPanel.getEditSimulationAction().actionPerformed(e);
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
} else {
deleteComponentAction.actionPerformed(e);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
editComponents();
// I wouldn't switch to the design tab here, because the user may be editing in the rocket view window
}
}
private void editComponents() {
List<RocketComponent> components = selectionModel.getSelectedComponents();
if (components == null || components.isEmpty()) {
return;
}
if (ComponentConfigDialog.isDialogVisible())
ComponentConfigDialog.disposeDialog();
RocketComponent component = components.get(0);
component.clearConfigListeners();
if (components.size() > 1) {
for (int i = 1; i < components.size(); i++) {
RocketComponent listener = components.get(i);
listener.clearConfigListeners(); // Make sure all the listeners are cleared (should not be possible, but just in case)
component.addConfigListener(listener);
}
}
ComponentConfigDialog.showDialog(parentFrame, document, component);
}
@Override
public void clipboardChanged() {
this.setEnabled(isDeletable(selectionModel.getSelectedComponent()) ||
isSimulationSelected());
List<RocketComponent> components = selectionModel.getSelectedComponents();
this.setEnabled(!components.isEmpty() || simulationPanel.getEditSimulationAction().isEnabled());
}
}
@ -650,14 +550,14 @@ public class RocketActions {
* Action the cuts the selected component (copies to clipboard and deletes).
*/
private class CutAction extends RocketAction {
@Serial
private static final long serialVersionUID = 1L;
public CutAction() {
//// Cut
this.putValue(NAME, trans.get("RocketActions.CutAction.Cut"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_T);
this.putValue(MNEMONIC_KEY, KeyEvent.VK_T); // Use the 't' in Cut as mnemonic
this.putValue(ACCELERATOR_KEY, CUT_KEY_STROKE);
//// Cut this component or simulation to the clipboard and remove from this design
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.CutAction.ttip.Cut"));
this.putValue(SMALL_ICON, Icons.EDIT_CUT);
clipboardChanged();
@ -665,49 +565,49 @@ public class RocketActions {
@Override
public void actionPerformed(ActionEvent e) {
if (isSimulationSelected()) {
simulationPanel.getCutSimulationAction().actionPerformed(e);
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
} else {
cutComponents();
}
}
private void cutComponents() {
List<RocketComponent> components = selectionModel.getSelectedComponents();
if (components.size() > 0) {
if (!components.isEmpty()) {
components = new ArrayList<>(components);
fillInMissingSelections(components);
components.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
}
Simulation[] sims = selectionModel.getSelectedSimulations();
if (isDeletable(components) && isCopyable(components)) {
ComponentConfigDialog.disposeDialog();
if (components.size() == 1) {
document.addUndoPosition("Cut " + components.get(0).getComponentName());
} else {
document.addUndoPosition("Cut components");
}
List<RocketComponent> copiedComponents = new LinkedList<>(copyComponentsMaintainParent(components));
copiedComponents.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
OpenRocketClipboard.setClipboard(copiedComponents);
delete(components);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
} else if (isSimulationSelected()) {
Simulation[] simsCopy = new Simulation[sims.length];
for (int i=0; i < sims.length; i++) {
simsCopy[i] = sims[i].copy();
}
OpenRocketClipboard.setClipboard(simsCopy);
for (Simulation s: sims) {
document.removeSimulation(s);
}
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
if (!(isDeletable(components) && isCopyable(components))) {
return;
}
ComponentConfigDialog.disposeDialog();
if (components.size() == 1) {
document.addUndoPosition("Cut " + components.get(0).getComponentName());
} else {
document.addUndoPosition("Cut components");
}
List<RocketComponent> copiedComponents = new LinkedList<>(copyComponentsMaintainParent(components));
copiedComponents.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
OpenRocketClipboard.setClipboard(copiedComponents);
delete(components);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
}
@Override
public void clipboardChanged() {
List<RocketComponent> components = selectionModel.getSelectedComponents();
this.setEnabled((isDeletable(components) && isCopyable(components)) || isSimulationSelected());
this.setEnabled((isDeletable(components) && isCopyable(components)) ||
simulationPanel.getCutSimulationAction().isEnabled());
}
}
@ -722,46 +622,47 @@ public class RocketActions {
public CopyAction() {
//// Copy
this.putValue(NAME, trans.get("RocketActions.CopyAct.Copy"));
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.CopyAct.ttip.Copy"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_C);
this.putValue(ACCELERATOR_KEY, COPY_KEY_STROKE);
//// Copy this component (and subcomponents) to the clipboard.
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.CopyAct.ttip.Copy"));
this.putValue(SMALL_ICON, Icons.EDIT_COPY);
clipboardChanged();
}
@Override
public void actionPerformed(ActionEvent e) {
if (isSimulationSelected()) {
simulationPanel.getCopySimulationAction().actionPerformed(e);
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
} else {
copyComponents();
}
}
private void copyComponents() {
List<RocketComponent> components = selectionModel.getSelectedComponents();
if (components.size() > 0) {
if (!components.isEmpty()) {
components = new ArrayList<>(components);
fillInMissingSelections(components);
components.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
}
Simulation[] sims = selectionModel.getSelectedSimulations();
if (isCopyable(components)) {
List<RocketComponent> copiedComponents = new LinkedList<>(copyComponentsMaintainParent(components));
copiedComponents.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
OpenRocketClipboard.setClipboard(copiedComponents);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
} else if (sims != null && sims.length > 0) {
Simulation[] simsCopy = new Simulation[sims.length];
for (int i=0; i < sims.length; i++) {
simsCopy[i] = sims[i].copy();
}
OpenRocketClipboard.setClipboard(simsCopy);
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
if (!isCopyable(components)) {
return;
}
List<RocketComponent> copiedComponents = new LinkedList<>(copyComponentsMaintainParent(components));
copiedComponents.sort(Comparator.comparing(c -> c.getParent() != null ? -c.getParent().getChildPosition(c) : 0));
OpenRocketClipboard.setClipboard(copiedComponents);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
}
@Override
public void clipboardChanged() {
this.setEnabled(isCopyable(selectionModel.getSelectedComponent()) ||
isSimulationSelected());
simulationPanel.getCopySimulationAction().isEnabled());
}
}
@ -779,9 +680,8 @@ public class RocketActions {
public PasteAction() {
//// Paste
this.putValue(NAME, trans.get("RocketActions.PasteAct.Paste"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_P);
this.putValue(MNEMONIC_KEY, KeyEvent.VK_V);
this.putValue(ACCELERATOR_KEY, PASTE_KEY_STROKE);
//// Paste the component or simulation on the clipboard to the design.
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.PasteAct.ttip.Paste"));
this.putValue(SMALL_ICON, Icons.EDIT_PASTE);
clipboardChanged();
@ -789,76 +689,67 @@ public class RocketActions {
@Override
public void actionPerformed(ActionEvent e) {
List<RocketComponent> components = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
Simulation[] sims = OpenRocketClipboard.getClipboardSimulations();
if (components.size() > 0) {
ComponentConfigDialog.disposeDialog();
List<RocketComponent> pasted = new LinkedList<>();
for (RocketComponent component : components) {
pasted.add(component.copy());
}
List<Pair<RocketComponent, Integer>> positions = getPastePositions(pasted);
if (pasted.size() == 1) {
document.addUndoPosition("Paste " + pasted.get(0).getComponentName());
} else {
document.addUndoPosition("Paste components");
}
List<RocketComponent> successfullyPasted = new LinkedList<>();
for (int i = 0; i < pasted.size(); i++) {
if (positions.get(i) == null) {
JOptionPane.showMessageDialog(null,
String.format(trans.get("RocketActions.PasteAct.invalidPosition.msg"),
pasted.get(i).getComponentName()),
trans.get("RocketActions.PasteAct.invalidPosition.title"), JOptionPane.WARNING_MESSAGE);
} else {
RocketComponent parent = positions.get(i).getU();
RocketComponent child = pasted.get(i);
if (parent != null && parent.isCompatible(child)) {
parent.addChild(child, positions.get(i).getV());
successfullyPasted.add(pasted.get(i));
} else {
log.warn("Pasted component {} is not compatible with {}", child, parent);
}
}
}
selectionModel.setSelectedComponents(successfullyPasted);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
} else if (sims != null) {
ArrayList<Simulation> copySims = new ArrayList<Simulation>();
for (Simulation s: sims) {
Simulation copy = s.duplicateSimulation(rocket);
String name = copy.getName();
if (name.matches(OpenRocketDocument.SIMULATION_NAME_PREFIX + "[0-9]+ *")) {
copy.setName(document.getNextSimulationName());
}
document.addSimulation(copy);
copySims.add(copy);
}
selectionModel.setSelectedSimulations(copySims.toArray(new Simulation[0]));
if (isSimulationSelected()) {
simulationPanel.getPasteSimulationAction().actionPerformed(e);
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
} else {
pasteComponents();
}
}
private void pasteComponents() {
List<RocketComponent> components = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
if (components.isEmpty()) {
return;
}
ComponentConfigDialog.disposeDialog();
List<RocketComponent> pasted = new LinkedList<>();
for (RocketComponent component : components) {
pasted.add(component.copy());
}
List<Pair<RocketComponent, Integer>> positions = getPastePositions(pasted);
if (pasted.size() == 1) {
document.addUndoPosition("Paste " + pasted.get(0).getComponentName());
} else {
document.addUndoPosition("Paste components");
}
List<RocketComponent> successfullyPasted = new LinkedList<>();
for (int i = 0; i < pasted.size(); i++) {
if (positions.get(i) == null) {
JOptionPane.showMessageDialog(null,
String.format(trans.get("RocketActions.PasteAct.invalidPosition.msg"),
pasted.get(i).getComponentName()),
trans.get("RocketActions.PasteAct.invalidPosition.title"), JOptionPane.WARNING_MESSAGE);
} else {
RocketComponent parent = positions.get(i).getU();
RocketComponent child = pasted.get(i);
if (parent != null && parent.isCompatible(child)) {
parent.addChild(child, positions.get(i).getV());
successfullyPasted.add(pasted.get(i));
} else {
log.warn("Pasted component {} is not compatible with {}", child, parent);
}
}
}
selectionModel.setSelectedComponents(successfullyPasted);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
}
@Override
public void clipboardChanged() {
this.setEnabled(
(getPastePositions(OpenRocketClipboard.getClipboardComponents()).size() > 0) ||
(OpenRocketClipboard.getClipboardSimulations() != null));
this.setEnabled(!getPastePositions(OpenRocketClipboard.getClipboardComponents()).isEmpty() ||
simulationPanel.getPasteSimulationAction().isEnabled());
}
}
/**
* Action that duplicates the selected component.
*/
@ -870,7 +761,6 @@ public class RocketActions {
this.putValue(NAME, trans.get("RocketActions.DuplicateAct.Duplicate"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_D);
this.putValue(ACCELERATOR_KEY, DUPLICATE_KEY_STROKE);
//// Copy this component (and subcomponents) to the clipboard.
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.DuplicateAct.ttip.Duplicate"));
this.putValue(SMALL_ICON, Icons.EDIT_DUPLICATE);
clipboardChanged();
@ -878,6 +768,15 @@ public class RocketActions {
@Override
public void actionPerformed(ActionEvent e) {
if (isSimulationSelected()) {
simulationPanel.getDuplicateSimulationAction().actionPerformed(e);
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
} else {
duplicateComponents();
}
}
private void duplicateComponents() {
List<RocketComponent> components = selectionModel.getSelectedComponents();
List<RocketComponent> topComponents = new LinkedList<>(); // Components without a parent component in <components>
if (components.size() > 0) {
@ -892,136 +791,130 @@ public class RocketActions {
topComponents.add(c);
}
}
Simulation[] sims = selectionModel.getSelectedSimulations();
if (isCopyable(components)) {
if (ComponentConfigDialog.isDialogVisible())
ComponentConfigDialog.disposeDialog();
List<RocketComponent> copiedComponents = copyComponentsMaintainParent(components);
OpenRocketClipboard.setClipboard(copiedComponents);
copiedComponents = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
List<RocketComponent> duplicateComponents = new LinkedList<>();
for (RocketComponent component : copiedComponents) {
duplicateComponents.add(component.copy());
}
List<Pair<RocketComponent, Integer>> positions = new LinkedList<>();
for (RocketComponent component : duplicateComponents) {
Pair<RocketComponent, Integer> pos;
if (RocketComponent.listContainsParent(duplicateComponents, component)) {
pos = getPastePosition(component, component.getParent());
} else {
int compIdx = duplicateComponents.indexOf(component);
RocketComponent pasteParent = topComponents.get(compIdx).getParent();
pos = getPastePosition(component, pasteParent);
}
positions.add(pos);
}
if (duplicateComponents.size() == 1) {
document.addUndoPosition("Duplicate " + duplicateComponents.get(0).getComponentName());
} else {
document.addUndoPosition("Duplicate components");
}
Collections.reverse(duplicateComponents);
Collections.reverse(positions);
for (int i = 0; i < duplicateComponents.size(); i++) {
positions.get(i).getU().addChild(duplicateComponents.get(i), positions.get(i).getV());
}
selectionModel.setSelectedComponents(duplicateComponents);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
} else if (sims != null && sims.length > 0) {
ArrayList<Simulation> copySims = new ArrayList<Simulation>();
// TODO: the undoing doesn't do anything...
if (sims.length == 1) {
document.addUndoPosition("Duplicate " + sims[0].getName());
} else {
document.addUndoPosition("Duplicate simulations");
}
for (Simulation s: sims) {
Simulation copy = s.duplicateSimulation(rocket);
String name = copy.getName();
if (name.matches(OpenRocketDocument.SIMULATION_NAME_PREFIX + "[0-9]+ *")) {
copy.setName(document.getNextSimulationName());
}
document.addSimulation(copy);
copySims.add(copy);
}
selectionModel.setSelectedSimulations(copySims.toArray(new Simulation[0]));
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
if (!isCopyable(components)) {
return;
}
if (ComponentConfigDialog.isDialogVisible())
ComponentConfigDialog.disposeDialog();
List<RocketComponent> copiedComponents = copyComponentsMaintainParent(components);
OpenRocketClipboard.setClipboard(copiedComponents);
copiedComponents = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
List<RocketComponent> duplicateComponents = new LinkedList<>();
for (RocketComponent component : copiedComponents) {
duplicateComponents.add(component.copy());
}
List<Pair<RocketComponent, Integer>> positions = new LinkedList<>();
for (RocketComponent component : duplicateComponents) {
Pair<RocketComponent, Integer> pos;
if (RocketComponent.listContainsParent(duplicateComponents, component)) {
pos = getPastePosition(component, component.getParent());
} else {
int compIdx = duplicateComponents.indexOf(component);
RocketComponent pasteParent = topComponents.get(compIdx).getParent();
pos = getPastePosition(component, pasteParent);
}
positions.add(pos);
}
if (duplicateComponents.size() == 1) {
document.addUndoPosition("Duplicate " + duplicateComponents.get(0).getComponentName());
} else {
document.addUndoPosition("Duplicate components");
}
Collections.reverse(duplicateComponents);
Collections.reverse(positions);
for (int i = 0; i < duplicateComponents.size(); i++) {
positions.get(i).getU().addChild(duplicateComponents.get(i), positions.get(i).getV());
}
selectionModel.setSelectedComponents(duplicateComponents);
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
}
@Override
public void clipboardChanged() {
this.setEnabled(isCopyable(selectionModel.getSelectedComponent()) ||
isSimulationSelected());
simulationPanel.getDuplicateSimulationAction().isEnabled());
}
}
/**
* Action to edit the currently selected component.
* Action that deletes the selected component.
*/
private class EditAction extends RocketAction {
private class DeleteAction extends RocketAction {
private static final long serialVersionUID = 1L;
public EditAction() {
//// Edit
this.putValue(NAME, trans.get("RocketActions.EditAct.Edit"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_E);
this.putValue(ACCELERATOR_KEY, EDIT_KEY_STROKE);
//// Edit the selected component.
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.EditAct.ttip.Edit"));
this.putValue(SMALL_ICON, Icons.EDIT_EDIT);
public DeleteAction() {
//// Delete
this.putValue(NAME, trans.get("RocketActions.DelAct.Delete"));
//// Delete the selected component or simulation.
this.putValue(SHORT_DESCRIPTION, trans.get("RocketActions.DelAct.ttip.Delete"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_DELETE);
this.putValue(ACCELERATOR_KEY, DELETE_KEY_STROKE);
this.putValue(SMALL_ICON, Icons.EDIT_DELETE);
clipboardChanged();
}
@Override
public void actionPerformed(ActionEvent e) {
List<RocketComponent> components = selectionModel.getSelectedComponents();
Simulation[] sims = selectionModel.getSelectedSimulations();
if (isSimulationSelected()) {
simulationPanel.getDeleteSimulationAction().actionPerformed(e);
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
} else {
deleteComponents();
}
}
if (components.size() > 0) {
if (ComponentConfigDialog.isDialogVisible())
ComponentConfigDialog.disposeDialog();
private void deleteComponents() {
List<RocketComponent> components = new ArrayList<>(selectionModel.getSelectedComponents());
if (components.size() == 0) return;
components.sort(Comparator.comparing(c -> c.getParent().getChildPosition(c)));
RocketComponent component = components.get(0);
component.clearConfigListeners();
if (components.size() > 1) {
for (int i = 1; i < components.size(); i++) {
RocketComponent listener = components.get(i);
listener.clearConfigListeners(); // Make sure all the listeners are cleared (should not be possible, but just in case)
component.addConfigListener(listener);
}
}
ComponentConfigDialog.showDialog(parentFrame, document, component);
} else if (sims != null && sims.length > 0 && (simulationPanel != null)) {
simulationPanel.editSimulation();
if (components.size() == 1) {
document.addUndoPosition("Delete " + components.get(0).getComponentName());
} else {
document.addUndoPosition("Delete components");
}
for (RocketComponent component : components) {
deleteComponent(component);
}
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
}
private void deleteComponent(RocketComponent component) {
if (isDeletable(component)) {
ComponentConfigDialog.disposeDialog();
try {
component.getRocket().removeComponentChangeListener(ComponentConfigDialog.getDialog());
delete(component);
} catch (IllegalStateException ignored) { }
}
}
@Override
public void clipboardChanged() {
List<RocketComponent> components = selectionModel.getSelectedComponents();
this.setEnabled(components.size() > 0 || isSimulationSelected());
this.setEnabled(isDeletable(selectionModel.getSelectedComponent()) ||
simulationPanel.getDeleteSimulationAction().isEnabled());
}
}
/**
* Action to select all components with the same color as the currently selected component.
*/
@ -1038,7 +931,7 @@ public class RocketActions {
@Override
public void actionPerformed(ActionEvent e) {
List<RocketComponent> components = selectionModel.getSelectedComponents();
if (components.size() == 0) {
if (components.isEmpty()) {
return;
}

View File

@ -17,10 +17,11 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.io.Serial;
import java.util.Comparator;
import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
@ -81,6 +82,8 @@ import net.sf.openrocket.util.AlphanumComparator;
import net.sf.openrocket.file.SimulationTableCSVExport;
import net.sf.openrocket.utils.TableRowTraversalPolicy;
import static net.sf.openrocket.gui.main.BasicFrame.SHORTCUT_KEY;
@SuppressWarnings("serial")
public class SimulationPanel extends JPanel {
private static final Logger log = LoggerFactory.getLogger(SimulationPanel.class);
@ -110,7 +113,9 @@ public class SimulationPanel extends JPanel {
private final JPopupMenu pm;
private final SimulationAction editSimulationAction;
private final SimulationAction copyValuesSimulationAction;
private final SimulationAction cutSimulationAction;
private final SimulationAction copySimulationAction;
private final SimulationAction pasteSimulationAction;
private final SimulationAction runSimulationAction;
private final SimulationAction plotSimulationAction;
private final SimulationAction duplicateSimulationAction;
@ -130,7 +135,9 @@ public class SimulationPanel extends JPanel {
// Simulation actions
SimulationAction newSimulationAction = new NewSimulationAction();
editSimulationAction = new EditSimulationAction();
copyValuesSimulationAction = new CopyValuesSimulationAction();
cutSimulationAction = new CutSimulationAction();
copySimulationAction = new CopySimulationAction();
pasteSimulationAction = new PasteSimulationAction();
runSimulationAction = new RunSimulationAction();
plotSimulationAction = new PlotSimulationAction();
duplicateSimulationAction = new DuplicateSimulationAction();
@ -178,6 +185,7 @@ public class SimulationPanel extends JPanel {
simulationTableModel = new SimulationTableModel();
simulationTable = new ColumnTable(simulationTableModel) {
@Serial
private static final long serialVersionUID = -5799340181229735630L;
};
ColumnTableRowSorter simulationTableSorter = new ColumnTableRowSorter(simulationTableModel);
@ -186,12 +194,22 @@ public class SimulationPanel extends JPanel {
simulationTable.setDefaultRenderer(Object.class, new JLabelRenderer());
simulationTableModel.setColumnWidths(simulationTable.getColumnModel());
simulationTable.setFillsViewportHeight(true);
simulationTable.registerKeyboardAction(copyValuesSimulationAction, "Copy", RocketActions.COPY_KEY_STROKE, JComponent.WHEN_FOCUSED);
// Unregister the default actions that would otherwise conflict with RocketActions and their acceleration keys
InputMap im = simulationTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, SHORTCUT_KEY), "none");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, SHORTCUT_KEY), "none");
// Context menu
pm = new JPopupMenu();
pm.add(editSimulationAction);
pm.add(copyValuesSimulationAction);
pm.add(cutSimulationAction);
pm.add(copySimulationAction);
pm.add(pasteSimulationAction);
pm.add(duplicateSimulationAction);
pm.add(deleteSimulationAction);
pm.addSeparator();
@ -252,7 +270,7 @@ public class SimulationPanel extends JPanel {
public void valueChanged(ListSelectionEvent event) {
if ((simulationTable.getSelectedRow() != previousSelectedRow) ||
(simulationTable.getSelectedRowCount() != previousSelectedRowCount)) {
updateButtonStates();
updateActions();
previousSelectedRow = simulationTable.getSelectedRow();
previousSelectedRowCount = simulationTable.getSelectedRowCount();
}
@ -283,7 +301,55 @@ public class SimulationPanel extends JPanel {
JScrollPane scrollpane = new JScrollPane(simulationTable);
this.add(scrollpane, "spanx, grow, wrap rel");
updateButtonStates();
updateActions();
}
/**
* Returns the action used for editing selected simulations.
* @return the action used for editing selected simulations.
*/
public SimulationAction getEditSimulationAction() {
return editSimulationAction;
}
/**
* Returns the action used for cutting selected simulations.
* @return the action used for cutting selected simulations.
*/
public SimulationAction getCutSimulationAction() {
return cutSimulationAction;
}
/**
* Returns the action used for copying selected simulations.
* @return the action used for copying selected simulations.
*/
public SimulationAction getCopySimulationAction() {
return copySimulationAction;
}
/**
* Returns the action used for pasting simulations.
* @return the action used for pasting simulations.
*/
public SimulationAction getPasteSimulationAction() {
return pasteSimulationAction;
}
/**
* Returns the action used for duplicating selected simulations.
* @return the action used for duplicating selected simulations.
*/
public SimulationAction getDuplicateSimulationAction() {
return duplicateSimulationAction;
}
/**
* Returns the action used for deleting selected simulations.
* @return the action used for deleting selected simulations.
*/
public SimulationAction getDeleteSimulationAction() {
return deleteSimulationAction;
}
public void updatePreviousSelection() {
@ -327,55 +393,62 @@ public class SimulationPanel extends JPanel {
openDialog(true, sim);
}
private void deleteSimulation() {
int[] selection = simulationTable.getSelectedRows();
if (selection.length == 0) {
private void deleteSimulations(Simulation[] sims) {
if (sims == null || sims.length == 0) {
return;
}
// Verify deletion
boolean verify = Application.getPreferences().getBoolean(Preferences.CONFIRM_DELETE_SIMULATION, true);
if (verify) {
JPanel panel = new JPanel(new MigLayout());
//// Do not ask me again
JCheckBox dontAsk = new JCheckBox(trans.get("simpanel.checkbox.donotask"));
panel.add(dontAsk, "wrap");
//// You can change the default operation in the preferences.
panel.add(new StyledLabel(trans.get("simpanel.lbl.defpref"), -2));
int ret = JOptionPane.showConfirmDialog(SimulationPanel.this,
new Object[] {
//// Delete the selected simulations?
trans.get("simpanel.dlg.lbl.DeleteSim1"),
//// <html><i>This operation cannot be undone.</i>
trans.get("simpanel.dlg.lbl.DeleteSim2"),
"",
panel },
//// Delete simulations
trans.get("simpanel.dlg.lbl.DeleteSim3"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
if (ret != JOptionPane.OK_OPTION)
return;
if (dontAsk.isSelected()) {
Application.getPreferences().putBoolean(Preferences.CONFIRM_DELETE_SIMULATION, false);
}
if (!verifyDeleteSimulation()) {
return;
}
// Delete simulations
for (int i = 0; i < selection.length; i++) {
selection[i] = simulationTable.convertRowIndexToModel(selection[i]);
}
Arrays.sort(selection);
for (int i = selection.length - 1; i >= 0; i--) {
document.removeSimulation(selection[i]);
for (Simulation sim : sims) {
document.removeSimulation(sim);
}
simulationTableModel.fireTableDataChanged();
updatePreviousSelection();
takeTheSpotlight();
}
private void deleteSimulations() {
deleteSimulations(getSelectedSimulations());
}
private boolean verifyDeleteSimulation() {
boolean verify = Application.getPreferences().getConfirmSimDeletion();
if (!verify) {
return true;
}
JPanel panel = new JPanel(new MigLayout());
//// Do not ask me again
JCheckBox dontAsk = new JCheckBox(trans.get("simpanel.checkbox.donotask"));
panel.add(dontAsk, "wrap");
//// You can change the default operation in the preferences.
panel.add(new StyledLabel(trans.get("simpanel.lbl.defpref"), -2));
int ret = JOptionPane.showConfirmDialog(SimulationPanel.this,
new Object[] {
//// Delete the selected simulations?
trans.get("simpanel.dlg.lbl.DeleteSim1"),
//// <html><i>This operation cannot be undone.</i>
trans.get("simpanel.dlg.lbl.DeleteSim2"),
"",
panel },
//// Delete simulations
trans.get("simpanel.dlg.lbl.DeleteSim3"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
if (dontAsk.isSelected()) {
Application.getPreferences().setConfirmSimDeletion(false);
}
return ret == JOptionPane.OK_OPTION;
}
private void runSimulation() {
Simulation[] sims = getSelectedSimulations();
if (sims == null) return;
@ -483,14 +556,35 @@ public class SimulationPanel extends JPanel {
return sims;
}
/**
* Full simulation copying
*/
public void copySimulationsAction() {
Simulation[] sims = getSelectedSimulations();
private void copySimulationValuesAction() {
if (sims == null || sims.length == 0)
return;
Simulation[] simsCopy = new Simulation[sims.length];
for (int i=0; i < sims.length; i++) {
simsCopy[i] = sims[i].copy();
}
OpenRocketClipboard.setClipboard(simsCopy);
copySimulationValues();
}
/**
* Only copy the simulation table values to the clipboard. (not actual Simulation copying)
*/
public void copySimulationValues() {
int numCols = simulationTable.getColumnCount();
int numRows = simulationTable.getSelectedRowCount();
int[] rowsSelected = simulationTable.getSelectedRows();
if (numRows != (rowsSelected[rowsSelected.length-1] - rowsSelected[0] + 1) || numRows != rowsSelected.length) {
JOptionPane.showMessageDialog(null, "Invalid Copy Selection", "Invalid Copy Selection", JOptionPane.ERROR_MESSAGE);
if (numRows != rowsSelected.length) {
JOptionPane.showMessageDialog(this, trans.get("simpanel.msg.invalidCopySelection"),
trans.get("simpanel.msg.invalidCopySelection"), JOptionPane.ERROR_MESSAGE);
return;
}
@ -509,7 +603,8 @@ public class SimulationPanel extends JPanel {
// Copy the values
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
valuesStr.append(simulationTable.getValueAt(rowsSelected[i], j).toString());
Object value = simulationTable.getValueAt(rowsSelected[i], j);
valuesStr.append(value == null ? "" : value.toString());
if (j < numCols-1) {
valuesStr.append("\t");
}
@ -523,20 +618,51 @@ public class SimulationPanel extends JPanel {
cb.setContents(sel, sel);
}
private void duplicateSimulation() {
Simulation[] sims = getSelectedSimulations();
if (sims == null) return;
private void pasteSimulationsAction() {
Simulation[] sims = OpenRocketClipboard.getClipboardSimulations();
if (sims == null || sims.length == 0) {
return;
}
duplicateSimulation(sims, simulationTable.getSelectedRow() + 1);
}
/**
* Duplicates the provided simulations at a certain index and selects them in the simulation table.
* @param sims The simulations to duplicate
* @param index The index to insert the simulations at (e.g. '1' to insert after the first simulation)
*/
public void duplicateSimulation(Simulation[] sims, int index) {
if (sims == null || sims.length == 0) return;
// TODO: the undoing doesn't do anything...
if (sims.length == 1) {
document.addUndoPosition("Duplicate " + sims[0].getName());
} else {
document.addUndoPosition("Duplicate simulations");
}
index = index >= 0 ? index : document.getSimulationCount();
int newIndex = index;
for (Simulation s: sims) {
Simulation copy = s.duplicateSimulation(document.getRocket());
String name = copy.getName();
if (name.matches(OpenRocketDocument.SIMULATION_NAME_PREFIX + "[0-9]+ *")) {
copy.setName(document.getNextSimulationName());
}
document.addSimulation(copy);
document.addSimulation(copy, newIndex);
newIndex++; // Ensure simulations are in the correct order
}
simulationTable.getSelectionModel().setSelectionInterval(simulationTable.getRowCount()-sims.length,simulationTable.getRowCount()-1);
simulationTableModel.fireTableDataChanged();
simulationTable.getSelectionModel().setSelectionInterval(index, newIndex-1);
}
/**
* Duplicates the provided simulations to the end and selects them in the simulation table.
* @param sims The simulations to duplicate.
*/
public void duplicateSimulation(Simulation[] sims) {
duplicateSimulation(sims, document.getSimulationCount());
}
/**
@ -550,14 +676,24 @@ public class SimulationPanel extends JPanel {
protected void doPopup(MouseEvent e) {
pm.show(e.getComponent(), e.getX(), e.getY());
}
/**
* Add a listener to the simulation table selection model.
* @param listener the listener to add.
*/
public void addSimulationTableListSelectionListener(ListSelectionListener listener) {
simulationTable.getSelectionModel().addListSelectionListener(listener);
}
private void updateButtonStates() {
public void updateActions() {
editSimulationAction.updateEnabledState();
copyValuesSimulationAction.updateEnabledState();
cutSimulationAction.updateEnabledState();
copySimulationAction.updateEnabledState();
pasteSimulationAction.updateEnabledState();
duplicateSimulationAction.updateEnabledState();
deleteSimulationAction.updateEnabledState();
runSimulationAction.updateEnabledState();
plotSimulationAction.updateEnabledState();
duplicateSimulationAction.updateEnabledState();
simTableExportAction.updateEnabledState();
selectedSimsExportAction.updateEnabledState();
}
@ -691,7 +827,7 @@ public class SimulationPanel extends JPanel {
}
}
private abstract static class SimulationAction extends AbstractAction {
public abstract static class SimulationAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public abstract void updateEnabledState();
@ -717,7 +853,8 @@ public class SimulationPanel extends JPanel {
class EditSimulationAction extends SimulationAction {
public EditSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.edit"));
this.putValue(NAME, trans.get("simpanel.pop.edit"));
this.putValue(SHORT_DESCRIPTION, trans.get("simpanel.pop.edit.ttip"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_E);
this.putValue(ACCELERATOR_KEY, RocketActions.EDIT_KEY_STROKE);
this.putValue(SMALL_ICON, Icons.EDIT_EDIT);
@ -730,21 +867,28 @@ public class SimulationPanel extends JPanel {
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() > 0);
this.setEnabled(simulationTable.getSelectedRowCount() > 0);
}
}
class CopyValuesSimulationAction extends SimulationAction {
public CopyValuesSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.copyValues"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_C);
this.putValue(ACCELERATOR_KEY, RocketActions.COPY_KEY_STROKE);
this.putValue(SMALL_ICON, Icons.EDIT_COPY);
class CutSimulationAction extends SimulationAction {
public CutSimulationAction() {
this.putValue(NAME, trans.get("simpanel.pop.cut"));
this.putValue(SHORT_DESCRIPTION, trans.get("simpanel.pop.cut.ttip"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_X);
this.putValue(ACCELERATOR_KEY, RocketActions.CUT_KEY_STROKE);
this.putValue(SMALL_ICON, Icons.EDIT_CUT);
}
@Override
public void actionPerformed(ActionEvent e) {
copySimulationValuesAction();
Simulation[] sims = getSelectedSimulations();
if (sims == null || sims.length == 0)
return;
copySimulationsAction();
deleteSimulations(sims);
}
@Override
@ -753,10 +897,93 @@ public class SimulationPanel extends JPanel {
}
}
class CopySimulationAction extends SimulationAction {
public CopySimulationAction() {
this.putValue(NAME, trans.get("simpanel.pop.copy"));
this.putValue(SHORT_DESCRIPTION, trans.get("simpanel.pop.copy.ttip"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_C);
this.putValue(ACCELERATOR_KEY, RocketActions.COPY_KEY_STROKE);
this.putValue(SMALL_ICON, Icons.EDIT_COPY);
}
@Override
public void actionPerformed(ActionEvent e) {
copySimulationsAction();
}
@Override
public void updateEnabledState() {
this.setEnabled(simulationTable.getSelectedRowCount() > 0);
}
}
class PasteSimulationAction extends SimulationAction {
public PasteSimulationAction() {
this.putValue(NAME, trans.get("simpanel.pop.paste"));
this.putValue(SHORT_DESCRIPTION, trans.get("simpanel.pop.paste.ttip"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_V);
this.putValue(ACCELERATOR_KEY, RocketActions.PASTE_KEY_STROKE);
this.putValue(SMALL_ICON, Icons.EDIT_PASTE);
}
@Override
public void actionPerformed(ActionEvent e) {
pasteSimulationsAction();
}
@Override
public void updateEnabledState() {
this.setEnabled((simulationTable.getSelectedRowCount() > 0) &&
(OpenRocketClipboard.getClipboardSimulations() != null) && (OpenRocketClipboard.getClipboardSimulations().length > 0));
}
}
class DuplicateSimulationAction extends SimulationAction {
public DuplicateSimulationAction() {
this.putValue(NAME, trans.get("simpanel.pop.duplicate"));
this.putValue(SHORT_DESCRIPTION, trans.get("simpanel.pop.duplicate.ttip"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_D);
this.putValue(ACCELERATOR_KEY, RocketActions.DUPLICATE_KEY_STROKE);
this.putValue(SMALL_ICON, Icons.EDIT_DUPLICATE);
}
@Override
public void actionPerformed(ActionEvent e) {
duplicateSimulation(getSelectedSimulations());
}
@Override
public void updateEnabledState() {
this.setEnabled(simulationTable.getSelectedRowCount() > 0);
}
}
class DeleteSimulationAction extends SimulationAction {
public DeleteSimulationAction() {
this.putValue(NAME, trans.get("simpanel.pop.delete"));
this.putValue(SHORT_DESCRIPTION, trans.get("simpanel.pop.delete.ttip"));
this.putValue(MNEMONIC_KEY, KeyEvent.VK_DELETE);
this.putValue(ACCELERATOR_KEY, RocketActions.DELETE_KEY_STROKE);
this.putValue(SMALL_ICON, Icons.EDIT_DELETE);
}
@Override
public void actionPerformed(ActionEvent e) {
deleteSimulations();
}
@Override
public void updateEnabledState() {
this.setEnabled(simulationTable.getSelectedRowCount() > 0);
}
}
class RunSimulationAction extends SimulationAction {
public RunSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.run"));
putValue(SMALL_ICON, Icons.SIM_RUN);
this.putValue(NAME, trans.get("simpanel.pop.run"));
this.putValue(SHORT_DESCRIPTION, trans.get("simpanel.pop.run.ttip"));
this.putValue(SMALL_ICON, Icons.SIM_RUN);
}
@Override
@ -766,26 +993,25 @@ public class SimulationPanel extends JPanel {
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() > 0);
this.setEnabled(simulationTable.getSelectedRowCount() > 0);
}
}
class DeleteSimulationAction extends SimulationAction {
public DeleteSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.delete"));
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
putValue(SMALL_ICON, Icons.EDIT_DELETE);
class PlotSimulationAction extends SimulationAction {
public PlotSimulationAction() {
this.putValue(NAME, trans.get("simpanel.pop.plot"));
this.putValue(SHORT_DESCRIPTION, trans.get("simpanel.pop.plot.ttip"));
this.putValue(SMALL_ICON, Icons.SIM_PLOT);
}
@Override
public void actionPerformed(ActionEvent e) {
deleteSimulation();
plotSimulation();
}
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() > 0);
this.setEnabled(simulationTable.getSelectedRowCount() == 1);
}
}
@ -795,8 +1021,8 @@ public class SimulationPanel extends JPanel {
class ExportSimulationTableAsCSVAction extends SimulationAction {
public ExportSimulationTableAsCSVAction() {
putValue(NAME, trans.get("simpanel.pop.exportSimTableToCSV"));
putValue(SMALL_ICON, Icons.SIM_TABLE_EXPORT);
this.putValue(NAME, trans.get("simpanel.pop.exportSimTableToCSV"));
this.putValue(SMALL_ICON, Icons.SIM_TABLE_EXPORT);
}
@Override
@ -806,7 +1032,7 @@ public class SimulationPanel extends JPanel {
@Override
public void updateEnabledState() {
setEnabled(simulationTableModel != null && simulationTableModel.getRowCount() > 0);
this.setEnabled(simulationTableModel != null && simulationTableModel.getRowCount() > 0);
}
}
@ -817,8 +1043,8 @@ public class SimulationPanel extends JPanel {
class ExportSelectedSimulationsAsCSVAction extends SimulationAction {
public ExportSelectedSimulationsAsCSVAction() {
putValue(NAME, trans.get("simpanel.pop.exportSelectedSimsToCSV"));
putValue(SMALL_ICON, Icons.SIM_TABLE_EXPORT);
this.putValue(NAME, trans.get("simpanel.pop.exportSelectedSimsToCSV"));
this.putValue(SMALL_ICON, Icons.SIM_TABLE_EXPORT);
}
@Override
@ -828,47 +1054,13 @@ public class SimulationPanel extends JPanel {
@Override
public void updateEnabledState() {
setEnabled(simulationTableModel != null && simulationTableModel.getRowCount() > 0 &&
this.setEnabled(simulationTableModel != null && simulationTableModel.getRowCount() > 0 &&
simulationTable.getSelectedRowCount() > 0);
}
}
class PlotSimulationAction extends SimulationAction {
public PlotSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.plot"));
putValue(SMALL_ICON, Icons.SIM_PLOT);
}
@Override
public void actionPerformed(ActionEvent e) {
plotSimulation();
}
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() == 1);
}
}
class DuplicateSimulationAction extends SimulationAction {
public DuplicateSimulationAction() {
putValue(NAME, trans.get("simpanel.pop.duplicate"));
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
putValue(ACCELERATOR_KEY, RocketActions.DUPLICATE_KEY_STROKE);
putValue(SMALL_ICON, Icons.EDIT_DUPLICATE);
}
@Override
public void actionPerformed(ActionEvent e) {
duplicateSimulation();
}
@Override
public void updateEnabledState() {
setEnabled(simulationTable.getSelectedRowCount() > 0);
}
}
public static class CellTransferable implements Transferable {
@ -1216,7 +1408,7 @@ public class SimulationPanel extends JPanel {
return;
}
if (previousSelection == null || previousSelection.length == 0) {
simulationTable.setRowSelectionInterval(0, 0);
simulationTable.getSelectionModel().setSelectionInterval(0, 0);
} else {
simulationTable.clearSelection();
for (int row : previousSelection) {
@ -1226,5 +1418,6 @@ public class SimulationPanel extends JPanel {
simulationTable.addRowSelectionInterval(row, row);
}
}
updateActions();
}
}