diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index dc4c1a47e..b5ec1534c 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -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 = This operation cannot be undone.
-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 = Not simulated yet
Click Run simulat
simpanel.ttip.noData = No simulation data available.
simpanel.ttip.noWarnings = No warnings.
simpanel.ttip.warnings = Warnings:
+simpanel.msg.invalidCopySelection = Invalid copy selection
! SimulationRunDialog
SimuRunDlg.title.RunSim = Running simulations\u2026
diff --git a/core/resources/l10n/messages_ar.properties b/core/resources/l10n/messages_ar.properties
index 96b45e6ab..65d2651d3 100644
--- a/core/resources/l10n/messages_ar.properties
+++ b/core/resources/l10n/messages_ar.properties
@@ -16,11 +16,6 @@
debug.currentFile = messages_ar.properties
! RocketActions
-RocketActions.checkbox.Donotaskmeagain = لا تسألني مجددا
-RocketActions.lbl.Youcanchangedefop = يمكنك تغيير العملية الافتراضية في التفضيلات.
-RocketActions.showConfirmDialog.lbl1 = إحذف المحاكاة المختارة؟
-RocketActions.showConfirmDialog.lbl2 = لا يمكنك التراجع عن هذه العملية.
-RocketActions.showConfirmDialog.title = إحذف كل المحاكاة
RocketActions.DelCompAct.Delete = إحذف
RocketActions.DelCompAct.ttip.Delete = إحذف القطعة المختارة
RocketActions.DelSimuAct.Delete = إحذف
diff --git a/core/resources/l10n/messages_cs.properties b/core/resources/l10n/messages_cs.properties
index 08a09dffd..27d128273 100644
--- a/core/resources/l10n/messages_cs.properties
+++ b/core/resources/l10n/messages_cs.properties
@@ -16,11 +16,6 @@
debug.currentFile = messages_cs.properties
! RocketActions
-RocketActions.checkbox.Donotaskmeagain = Pr\u0161te se me neptejte
-RocketActions.lbl.Youcanchangedefop = Mu\u017Eete zmenit vchoz operaci v nastaven.
-RocketActions.showConfirmDialog.lbl1 = Chcete smazat oznacenou simulaci?
-RocketActions.showConfirmDialog.lbl2 = Tuto operaci nelze vzt zpet.
-RocketActions.showConfirmDialog.title = Sma\u017E simulace
RocketActions.DelCompAct.Delete = Sma\u017E
RocketActions.DelCompAct.ttip.Delete = Sma\u017E oznacenou komponentu.
RocketActions.DelSimuAct.Delete = Sma\u017E
diff --git a/core/resources/l10n/messages_de.properties b/core/resources/l10n/messages_de.properties
index 0c68ebee2..908a48690 100644
--- a/core/resources/l10n/messages_de.properties
+++ b/core/resources/l10n/messages_de.properties
@@ -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 gendert werden.
-RocketActions.showConfirmDialog.lbl1 = Simulationen lschen?
-RocketActions.showConfirmDialog.lbl2 = Diese Aktion kann nicht rckgngig gemacht werden.
-RocketActions.showConfirmDialog.title = Simulationen lschen
RocketActions.DelCompAct.Delete = Lschen
RocketActions.DelCompAct.ttip.Delete = Die ausgewhlte Komponente lschen.
RocketActions.DelSimuAct.Delete = Lschen
diff --git a/core/resources/l10n/messages_es.properties b/core/resources/l10n/messages_es.properties
index 3d989be9b..30b830045 100644
--- a/core/resources/l10n/messages_es.properties
+++ b/core/resources/l10n/messages_es.properties
@@ -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 = Esta operaci\u00f3n no puede deshacerse.
-RocketActions.showConfirmDialog.title = Borrar simulaciones
RocketCfg.lbl.Comments = Comentarios:
RocketCfg.lbl.Designer = Dise\u00f1ador:
diff --git a/core/resources/l10n/messages_fr.properties b/core/resources/l10n/messages_fr.properties
index 0eff3be76..2fd925ed2 100644
--- a/core/resources/l10n/messages_fr.properties
+++ b/core/resources/l10n/messages_fr.properties
@@ -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 = Cette op\u00E9ration n'est pas r\u00E9versible.
-RocketActions.showConfirmDialog.title = Effacer les simulations
RocketCfg.lbl.Comments = Commentaires:
RocketCfg.lbl.Designer = Concepteur:
diff --git a/core/resources/l10n/messages_it.properties b/core/resources/l10n/messages_it.properties
index 55c33cc87..34980ad02 100644
--- a/core/resources/l10n/messages_it.properties
+++ b/core/resources/l10n/messages_it.properties
@@ -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 = Questa operazione non puo' essere annullata.
-RocketActions.showConfirmDialog.title = Cancello Simulazioni
RocketActions.DelCompAct.Delete = Cancella
RocketActions.DelCompAct.ttip.Delete = Cancello il componente selezionato.
RocketActions.DelSimuAct.Delete = Cancella
diff --git a/core/resources/l10n/messages_ja.properties b/core/resources/l10n/messages_ja.properties
index 947c2022a..45d5c4003 100644
--- a/core/resources/l10n/messages_ja.properties
+++ b/core/resources/l10n/messages_ja.properties
@@ -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 = \u6D88\u53BB\u3057\u305F\u3089\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093
-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
diff --git a/core/resources/l10n/messages_nl.properties b/core/resources/l10n/messages_nl.properties
index 8fb96b539..c44ec545e 100644
--- a/core/resources/l10n/messages_nl.properties
+++ b/core/resources/l10n/messages_nl.properties
@@ -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 = Deze bewerking kan niet ongedaan worden.
-RocketActions.showConfirmDialog.title = Verwijder simulaties
RocketActions.DelCompAct.Delete = Verwijder
RocketActions.DelCompAct.ttip.Delete = Verwijder het geselecteerde onderdeel.
RocketActions.DelSimuAct.Delete = Verwijder
diff --git a/core/resources/l10n/messages_pl.properties b/core/resources/l10n/messages_pl.properties
index 55577b105..cc4246b5f 100644
--- a/core/resources/l10n/messages_pl.properties
+++ b/core/resources/l10n/messages_pl.properties
@@ -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 = Tej operacji nie mo\u017Cna cofn\u0105\u0107.
- 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
diff --git a/core/resources/l10n/messages_pt.properties b/core/resources/l10n/messages_pt.properties
index b9e7669c5..b5d9d3ee9 100644
--- a/core/resources/l10n/messages_pt.properties
+++ b/core/resources/l10n/messages_pt.properties
@@ -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 = Esta opera\u00e7\u00e3o n\u00e3o poder\u00e1 ser desfeita.
-RocketActions.showConfirmDialog.title = Excluir simula\u00e7\u00f5es
RocketCfg.lbl.Comments = Coment\u00e1rios:
RocketCfg.lbl.Designer = Projetista:
diff --git a/core/resources/l10n/messages_ru.properties b/core/resources/l10n/messages_ru.properties
index 57de96180..f5622ac0c 100644
--- a/core/resources/l10n/messages_ru.properties
+++ b/core/resources/l10n/messages_ru.properties
@@ -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 = \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.
-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
diff --git a/core/resources/l10n/messages_tr.properties b/core/resources/l10n/messages_tr.properties
index 3c9c22979..f619a70c1 100644
--- a/core/resources/l10n/messages_tr.properties
+++ b/core/resources/l10n/messages_tr.properties
@@ -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 = Bu \u00e7al\u0131\u015fma tamamlanmad\u0131.
-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
diff --git a/core/resources/l10n/messages_uk_UA.properties b/core/resources/l10n/messages_uk_UA.properties
index 8a7e912d8..4fea26db2 100644
--- a/core/resources/l10n/messages_uk_UA.properties
+++ b/core/resources/l10n/messages_uk_UA.properties
@@ -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 = \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.
-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
diff --git a/core/resources/l10n/messages_zh_CN.properties b/core/resources/l10n/messages_zh_CN.properties
index b4bff94ed..05811ded0 100644
--- a/core/resources/l10n/messages_zh_CN.properties
+++ b/core/resources/l10n/messages_zh_CN.properties
@@ -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 = \u8BE5\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500
-RocketActions.showConfirmDialog.title = \u5220\u9664\u4EFF\u771F
RocketCfg.lbl.Comments = \u6CE8\u91CA:
RocketCfg.lbl.Designer = \u8BBE\u8BA1\u4EBA:
diff --git a/core/src/net/sf/openrocket/document/OpenRocketDocument.java b/core/src/net/sf/openrocket/document/OpenRocketDocument.java
index c1ea85f24..47160f751 100644
--- a/core/src/net/sf/openrocket/document/OpenRocketDocument.java
+++ b/core/src/net/sf/openrocket/document/OpenRocketDocument.java
@@ -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));
}
diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/SimulationPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/SimulationPreferencesPanel.java
index 92bb729b3..a45a68efc 100644
--- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/SimulationPreferencesPanel.java
+++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/SimulationPreferencesPanel.java
@@ -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 ");
diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
index 06e449c80..4c551e027 100644
--- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
+++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java
@@ -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();
diff --git a/swing/src/net/sf/openrocket/gui/main/DesignPanel.java b/swing/src/net/sf/openrocket/gui/main/DesignPanel.java
index b30a605ce..226c7f8c8 100644
--- a/swing/src/net/sf/openrocket/gui/main/DesignPanel.java
+++ b/swing/src/net/sf/openrocket/gui/main/DesignPanel.java
@@ -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() {
diff --git a/swing/src/net/sf/openrocket/gui/main/RocketActions.java b/swing/src/net/sf/openrocket/gui/main/RocketActions.java
index 2bfa6e9a6..aa90f9eaf 100644
--- a/swing/src/net/sf/openrocket/gui/main/RocketActions.java
+++ b/swing/src/net/sf/openrocket/gui/main/RocketActions.java
@@ -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 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"),
- //// This operation cannot be undone.
- 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 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 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 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 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 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 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 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 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 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 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 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 components = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
- Simulation[] sims = OpenRocketClipboard.getClipboardSimulations();
-
- if (components.size() > 0) {
- ComponentConfigDialog.disposeDialog();
-
- List pasted = new LinkedList<>();
- for (RocketComponent component : components) {
- pasted.add(component.copy());
- }
-
- List> positions = getPastePositions(pasted);
-
- if (pasted.size() == 1) {
- document.addUndoPosition("Paste " + pasted.get(0).getComponentName());
- } else {
- document.addUndoPosition("Paste components");
- }
-
- List 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 copySims = new ArrayList();
-
- 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 components = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
+
+ if (components.isEmpty()) {
+ return;
+ }
+ ComponentConfigDialog.disposeDialog();
+
+ List pasted = new LinkedList<>();
+ for (RocketComponent component : components) {
+ pasted.add(component.copy());
+ }
+
+ List> positions = getPastePositions(pasted);
+
+ if (pasted.size() == 1) {
+ document.addUndoPosition("Paste " + pasted.get(0).getComponentName());
+ } else {
+ document.addUndoPosition("Paste components");
+ }
+
+ List 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 components = selectionModel.getSelectedComponents();
List topComponents = new LinkedList<>(); // Components without a parent component in
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 copiedComponents = copyComponentsMaintainParent(components);
- OpenRocketClipboard.setClipboard(copiedComponents);
- copiedComponents = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
-
- List duplicateComponents = new LinkedList<>();
- for (RocketComponent component : copiedComponents) {
- duplicateComponents.add(component.copy());
- }
-
- List> positions = new LinkedList<>();
- for (RocketComponent component : duplicateComponents) {
- Pair 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 copySims = new ArrayList();
-
- // 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 copiedComponents = copyComponentsMaintainParent(components);
+ OpenRocketClipboard.setClipboard(copiedComponents);
+ copiedComponents = new LinkedList<>(OpenRocketClipboard.getClipboardComponents());
+
+ List duplicateComponents = new LinkedList<>();
+ for (RocketComponent component : copiedComponents) {
+ duplicateComponents.add(component.copy());
+ }
+
+ List> positions = new LinkedList<>();
+ for (RocketComponent component : duplicateComponents) {
+ Pair 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 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 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 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 components = selectionModel.getSelectedComponents();
- if (components.size() == 0) {
+ if (components.isEmpty()) {
return;
}
diff --git a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
index c5be48302..0bac65b69 100644
--- a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
+++ b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java
@@ -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"),
- //// This operation cannot be undone.
- 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"),
+ //// This operation cannot be undone.
+ 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();
}
}