Merge branch 'unstable' into issue-1001

This commit is contained in:
Joe Pfeiffer 2021-10-15 08:50:36 -06:00 committed by GitHub
commit 2c9877b68b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 999 additions and 448 deletions

View File

@ -90,12 +90,13 @@ dlg.but.cancel = Cancel
dlg.but.close = Close
! General file type names
filetypes.pdf = PDF files (*.pdf)
BasicFrame.SimpleFileFilter1 = All rocket designs (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket designs (*.ork)
BasicFrame.SimpleFileFilter3 = RockSim designs (*.rkt)
BasicFrame.SimpleFileFilter4 = OpenRocket presets (*.orc)
filetypes.images = Image files
FileHelper.CSV_FILTER = Comma Separated Files (*.csv)
FileHelper.PDF_FILTER = PDF files (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = All rocket designs (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket designs (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim designs (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket presets (*.orc)
FileHelper.IMAGES = Image files
! About Dialog
@ -515,7 +516,6 @@ RK4SimulationStepper.error.valuesTooLarge = Simulation values exceeded limits.
SimulationModifierTree.OptimizationParameters = Optimization Parameters
! SimulationExportPanel
SimExpPan.desc = Comma Separated Files (*.csv)
SimExpPan.border.Vartoexport = Variables to export
SimExpPan.border.Stage = Stage to export
SimExpPan.but.Selectall = Select all
@ -769,6 +769,9 @@ BodyTubecfg.tab.Generalproperties = General properties
BodyTubecfg.tab.Motor = Motor
BodyTubecfg.tab.Motormountconf = Motor mount configuration
BodyTubecfg.checkbox.Automatic = Automatic
BodyTubecfg.checkbox.ttip.Automatic = Use the diameter of the previous/next component
BodyTubecfg.checkbox.ttip.Automatic_noReferenceComponent = There is no previous/next component to take the diameter of
BodyTubecfg.checkbox.ttip.Automatic_alreadyAuto = The previous/next component already has its auto setting turned on
BodyTubecfg.checkbox.Filled = Filled
! FinSetConfig
@ -948,6 +951,7 @@ FreeformFinSetConfig.lbl.doubleClick2 = to edit
FreeformFinSetConfig.lbl.clickDrag = Click+drag: Add and move points
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+click: Remove point
FreeformFinSetConfig.lbl.scaleFin = Scale Fin
FreeformFinSetConfig.lbl.exportCSV = Export CSV
!TubeFinSetConfig
TubeFinSetCfg.lbl.Nbroffins = Number of fins:
@ -1038,6 +1042,9 @@ NoseConeCfg.lbl.Shapeparam = Shape parameter:
NoseConeCfg.lbl.Noseconelength = Nose cone length:
NoseConeCfg.lbl.Basediam = Base diameter:
NoseConeCfg.checkbox.Automatic = Automatic
NoseConeCfg.checkbox.ttip.Automatic = Use the diameter of the next component
NoseConeCfg.checkbox.ttip.Automatic_noReferenceComponent = There is no next component to take the diameter of
NoseConeCfg.checkbox.ttip.Automatic_alreadyAuto = The next component already has its auto setting turned on
NoseConeCfg.lbl.Wallthickness = Wall thickness:
NoseConeCfg.checkbox.Filled = Filled
NoseConeCfg.tab.General = General
@ -1139,6 +1146,9 @@ TransitionCfg.lbl.Shapeparam = Shape parameter:
TransitionCfg.lbl.Transitionlength = Transition length:
TransitionCfg.lbl.Forediam = Fore diameter:
TransitionCfg.checkbox.Automatic = Automatic
TransitionCfg.checkbox.ttip.Automatic = Use the diameter of the previous/next component
TransitionCfg.checkbox.ttip.Automatic_noReferenceComponent = There is no previous/next component to take the diameter of
TransitionCfg.checkbox.ttip.Automatic_alreadyAuto = The previous/next component already has its auto setting turned on
TransitionCfg.lbl.Aftdiam = Aft diameter:
TransitionCfg.lbl.Wallthickness = Wall thickness:
TransitionCfg.checkbox.Filled = Filled
@ -1215,6 +1225,7 @@ TCMotorSelPan.lbl.Selectthrustcurve = Select thrust curve:
TCMotorSelPan.lbl.Ejectionchargedelay = Ejection charge delay:
TCMotorSelPan.equalsIgnoreCase.None = None
TCMotorSelPan.lbl.NumberofsecondsorNone = (Number of seconds or \"None\")
TCMotorSelPan.lbl.Designation = Designation:
TCMotorSelPan.lbl.Totalimpulse = Total impulse:
TCMotorSelPan.lbl.Avgthrust = Avg. thrust:
TCMotorSelPan.lbl.Maxthrust = Max. thrust:
@ -1591,7 +1602,7 @@ FlightEvent.Type.EXCEPTION = Exception
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Manufacturer
TCurveMotorCol.DESIGNATION = Designation
TCurveMotorCol.COMMON_NAME = Name
TCurveMotorCol.CASEINFO = Case
TCurveMotorCol.DIAMETER = Diameter
TCurveMotorCol.LENGTH = Length

View File

@ -57,9 +57,10 @@ RocketPanel.lbl.infoMessage = <html>Stiskni k oznacen
! BasicFrame
BasicFrame.SimpleFileFilter1 = V\u0161echny návrhy raket (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = Návrhy OpenRocket (*.ork)
BasicFrame.SimpleFileFilter3 = Návrhy RockSim (*.rkt)
FileHelper.ALL_DESIGNS_FILTER = V\u0161echny návrhy raket (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = Návrhy OpenRocket (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = Návrhy RockSim (*.rkt)
FileHelper.CSV_FILTER = Soubory s cárkovým oddelovacem (*.csv)
BasicFrame.tab.Rocketdesign = Návrh rakety
BasicFrame.tab.Flightsim = Letová simulace
BasicFrame.title.Addnewcomp = Pridej novou komponentu
@ -94,7 +95,7 @@ dlg.but.close = Zavr
! General file type names
filetypes.pdf = Soubory PDF
FileHelper.PDF_FILTER = Soubory PDF
! About Dialog
@ -410,7 +411,6 @@ RK4SimulationStepper.error.valuesTooLarge = Hodnoty simulace prekrocily limity.
! SimulationExportPanel
SimExpPan.desc = Soubory s cárkovým oddelovacem (*.csv)
SimExpPan.border.Vartoexport = Promenné k exportu
SimExpPan.but.Selectall = Oznac v\u0161e
SimExpPan.but.Selectnone = Nic neoznacuj
@ -945,6 +945,7 @@ TCMotorSelPan.lbl.Selectthrustcurve = Vyber v
TCMotorSelPan.lbl.Ejectionchargedelay = Oddelovací zpo\u017Edení:
TCMotorSelPan.equalsIgnoreCase.None = Nic
TCMotorSelPan.lbl.NumberofsecondsorNone = (Pocet sekund nebo \"Nic\")
TCMotorSelPan.lbl.Designation = Pojmenování:
TCMotorSelPan.lbl.Totalimpulse = Celkový impulse:
TCMotorSelPan.lbl.Avgthrust = Prumerný tah:
TCMotorSelPan.lbl.Maxthrust = Maximální tah:
@ -1214,7 +1215,8 @@ FlightEvent.Type.ALTITUDE = Zmena v
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Výrobce
TCurveMotorCol.DESIGNATION = Pojmenování
TCurveMotorCol.COMMON_NAME = Jméno
! TCurveMotorCol.DESIGNATION = Pojmenování
TCurveMotorCol.TYPE = Druh
TCurveMotorCol.DIAMETER = Prumer
TCurveMotorCol.LENGTH = Délka

View File

@ -90,12 +90,13 @@ dlg.but.close = Schlie
! General file type names
filetypes.pdf = PDF files
BasicFrame.SimpleFileFilter1 = Alle Raketendesigns (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket Designs (*.ork)
BasicFrame.SimpleFileFilter3 = RockSim Designs (*.rkt)
BasicFrame.SimpleFileFilter4 = OpenRocket presets (*.orc)
filetypes.images = Image files
FileHelper.PDF_FILTER = PDF files
FileHelper.ALL_DESIGNS_FILTER = Alle Raketendesigns (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket Designs (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim Designs (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket presets (*.orc)
FileHelper.IMAGES = Image files
FileHelper.CSV_FILTER = Komma getrennte Werte (*.csv)
! About Dialog
@ -413,7 +414,6 @@ RK4SimulationStepper.error.valuesTooLarge = Simulationswerte
! SimulationExportPanel
SimExpPan.desc = Komma getrennte Werte (*.csv)
SimExpPan.border.Vartoexport = zu exportierende Variablen
SimExpPan.but.Selectall = Alle auswählen
SimExpPan.but.Selectnone = Keine auswählen
@ -1002,6 +1002,7 @@ TCMotorSelPan.lbl.Selectthrustcurve = Schubkurve ausw
TCMotorSelPan.lbl.Ejectionchargedelay = Verzögerung der Ausstoßladung:
TCMotorSelPan.equalsIgnoreCase.None = keine
TCMotorSelPan.lbl.NumberofsecondsorNone = (Anzahl der Sekunden oder \«keine\«)
TCMotorSelPan.lbl.Designation = Bezeichnung:
TCMotorSelPan.lbl.Totalimpulse = Gesamtimpuls:
TCMotorSelPan.lbl.Avgthrust = Durchschn. Schub:
TCMotorSelPan.lbl.Maxthrust = max. Schub
@ -1273,7 +1274,8 @@ FlightEvent.Type.ALTITUDE = H
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Hersteller
TCurveMotorCol.DESIGNATION = Bezeichnung
TCurveMotorCol.COMMON_NAME = Name
! TCurveMotorCol.DESIGNATION = Bezeichnung
TCurveMotorCol.TYPE = Typ
TCurveMotorCol.DIAMETER = Durchmesser
TCurveMotorCol.LENGTH = Länge

View File

@ -42,10 +42,11 @@ AppearanceCfg.lbl.texture.repeat = Aspecto:
AppearanceCfg.lbl.texture.rotation = Rotaci\u00f3n:
AppearanceCfg.lbl.texture.scale = Escala:
BasicFrame.SimpleFileFilter1 = Todos los dise\u00f1os de cohete(*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = Dise\u00f1os OpenRocket (*.ork)
BasicFrame.SimpleFileFilter3 = Dise\u00f1os RockSim (*.rkt)
BasicFrame.SimpleFileFilter4 = Preajustes OpenRocket (*.orc)
FileHelper.ALL_DESIGNS_FILTER = Todos los dise\u00f1os de cohete(*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = Dise\u00f1os OpenRocket (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = Dise\u00f1os RockSim (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = Preajustes OpenRocket (*.orc)
FileHelper.CSV_FILTER = Documentos separados por comas (*.csv)
BasicFrame.StageName.Sustainer = Etapa principal
BasicFrame.WarningDialog.title = Alertas al abrir el archivo
BasicFrame.WarningDialog.txt1 = Mientras se abr\u00eda el archivo, se encontraron los siguiente problemas
@ -991,7 +992,6 @@ SimExpPan.checkbox.ttip.Incflightevents = Incluye una l\u00ednea de comentario
SimExpPan.checkbox.ttip.Includefielddesc = Incluye una l\u00ednea de comentario con las descripciones de las variables exportadas.
SimExpPan.checkbox.ttip.Includesimudesc = Incluye un comentario en el inicio del documento describiendo la simulaci\u00f3n.
! SimulationExportPanel
SimExpPan.desc = Documentos separados por comas (*.csv)
SimExpPan.lbl.Commentchar = Caracter de comentario:
SimExpPan.lbl.Fieldsepstr = Caracter separador de campo:
SimExpPan.lbl.longA1 = <html>Caracter para separar campos en el documento exportado.<br>
@ -1110,6 +1110,7 @@ StreamerCfg.tab.Radialpos = Posici\u00f3n radial
StreamerCfg.tab.ttip.General = Propiedades generales
StreamerCfg.tab.ttip.Radialpos = Configuraci\u00f3n de posici\u00f3n radial
! ThrustCurveMotorSelectionPanel
TCMotorSelPan.Diameter = Di\u00e1metro
TCMotorSelPan.Length = Longitud
TCMotorSelPan.MotorMountDimensions = Dimensiones del porta motor:
@ -1140,8 +1141,8 @@ TCMotorSelPan.lbl.Motormountdia = Di\u00e1metro del porta motor:
TCMotorSelPan.lbl.NumberofsecondsorNone = (segundos)
TCMotorSelPan.lbl.Search = Buscar:
TCMotorSelPan.lbl.Selectthrustcurve = Seleccione curva de empuje:
! ThrustCurveMotorSelectionPanel
TCMotorSelPan.lbl.Selrocketmotor = Seleccione el motor del cohete:
TCMotorSelPan.lbl.Designation = Designaci\u00f3n
TCMotorSelPan.lbl.Totalimpulse = Impulso total:
TCMotorSelPan.noDescription = No hay una descripci\u00f3n disponible
TCMotorSelPan.title.Thrust = Empuje
@ -1156,10 +1157,11 @@ TCurveMotor.ttip.length = Longitud:
TCurveMotor.ttip.maxThrust = Empuje m\u00e1ximo:
TCurveMotor.ttip.totalImpulse = Impulso total:
TCurveMotorCol.DESIGNATION = Designaci\u00f3n
! ThrustCurveMotorColumns
TCurveMotorCol.COMMON_NAME = Nombre
! TCurveMotorCol.DESIGNATION = Designaci\u00f3n
TCurveMotorCol.DIAMETER = Di\u00e1metro
TCurveMotorCol.LENGTH = Longitud
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Fabricante
TCurveMotorCol.TOTAL_IMPULSE = Impulso total
TCurveMotorCol.TYPE = Tipo
@ -1422,9 +1424,9 @@ exdesigndlg.lbl.Examplesnotfound = Ejemplos no encontrados
exdesigndlg.lbl.Openexampledesign = Abrir un dise\u00f1o de ejemplo
exdesigndlg.lbl.Selectexample = Dise\u00f1os de ejemplo:
filetypes.images = Archivos de imagen
FileHelper.IMAGES = Archivos de imagen
! General file type names
filetypes.pdf = Archivos PDF
FileHelper.PDF_FILTER = Archivos PDF
main.menu.analyze = Analizar
main.menu.analyze.componentAnalysis = An\u00e1lisis de los componentes

View File

@ -39,10 +39,11 @@ AppearanceCfg.lbl.texture.repeat = R\u00E9p\u00E9ter:
AppearanceCfg.lbl.texture.rotation = Rotation:
AppearanceCfg.lbl.texture.scale = Echelle:
BasicFrame.SimpleFileFilter1 = Tous les fichiers fus\u00E9e (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = Fichiers OpenRocket (*.ork)
BasicFrame.SimpleFileFilter3 = Fichiers RockSim (*.rkt)
BasicFrame.SimpleFileFilter4 = Pi\u00E8ces OpenRocket pr\u00E9configur\u00E9es (*.orc)
FileHelper.ALL_DESIGNS_FILTER = Tous les fichiers fus\u00E9e (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = Fichiers OpenRocket (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = Fichiers RockSim (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = Pi\u00E8ces OpenRocket pr\u00E9configur\u00E9es (*.orc)
FileHelper.CSV_FILTER = Fichiers dont les donn\u00E9es sont s\u00E9par\u00E9es par une virgule (*.csv)
BasicFrame.StageName.Sustainer = Sustainer
BasicFrame.WarningDialog.title = Avertissement lors de l'ouverture du fichier
BasicFrame.WarningDialog.txt1 = Les probl\u00E8mes suivant sont survenus lors de l'ouverture de
@ -983,7 +984,6 @@ SimExpPan.checkbox.ttip.Incflightevents = Inclure une ligne de commentaire pour
SimExpPan.checkbox.ttip.Includefielddesc = Inclure une ligne de commentaire avec la description des variables export\u00E9es.
SimExpPan.checkbox.ttip.Includesimudesc = Inclure un commentaire au d\u00E9but du fichier pour d\u00E9crire la simulation.
! SimulationExportPanel
SimExpPan.desc = Fichiers dont les donn\u00E9es sont s\u00E9par\u00E9es par une virgule (*.csv)
SimExpPan.lbl.Commentchar = Symbole pour les commentaires:
SimExpPan.lbl.Fieldsepstr = S\u00E9parateur de champ:
SimExpPan.lbl.longA1 = <html>La cha\u00EEne utilis\u00E9e pour s\u00E9parer les champs dans le fichier export\u00E9.<br>
@ -1104,6 +1104,7 @@ StreamerCfg.tab.Radialpos = Position sur le p\u00E9rim\u00E8tre
StreamerCfg.tab.ttip.General = Propri\u00E9t\u00E9s g\u00E9n\u00E9rales
StreamerCfg.tab.ttip.Radialpos = Configuration de la position sur le p\u00E9rim\u00E8tre
! ThrustCurveMotorSelectionPanel
TCMotorSelPan.Diameter = Diametre
TCMotorSelPan.Length = Longueur
TCMotorSelPan.MotorMountDimensions = Dimentions du porte moteur:
@ -1134,8 +1135,8 @@ TCMotorSelPan.lbl.Motormountdia = Diam\u00E8tre du tube porte moteur:
TCMotorSelPan.lbl.NumberofsecondsorNone = (Nombre de secondes ou "Aucun")
TCMotorSelPan.lbl.Search = Rechercher:
TCMotorSelPan.lbl.Selectthrustcurve = Choisir la courbe de pouss\u00E9e:
! ThrustCurveMotorSelectionPanel
TCMotorSelPan.lbl.Selrocketmotor = Choisir le moteur fus\u00E9e:
TCMotorSelPan.lbl.Designation = D\u00E9signation
TCMotorSelPan.lbl.Totalimpulse = Impulsion totale:
TCMotorSelPan.noDescription = Aucune description disponible
TCMotorSelPan.title.Thrust = Pouss\u00E9e
@ -1150,10 +1151,11 @@ TCurveMotor.ttip.length = Longueur:
TCurveMotor.ttip.maxThrust = Pouss\u00E9e Maximum:
TCurveMotor.ttip.totalImpulse = Impulsion Totale:
TCurveMotorCol.DESIGNATION = D\u00E9signation
! ThrustCurveMotorColumns
TCurveMotorCol.COMMON_NAME = Nom
! TCurveMotorCol.DESIGNATION = D\u00E9signation
TCurveMotorCol.DIAMETER = Diam\u00E8tre
TCurveMotorCol.LENGTH = Longueur
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Fabricant
TCurveMotorCol.TOTAL_IMPULSE = Impultion total
TCurveMotorCol.TYPE = Type
@ -1416,9 +1418,9 @@ exdesigndlg.lbl.Examplesnotfound = Exemples non trouv\u00E9s
exdesigndlg.lbl.Openexampledesign = Ouvrir un exemple de projet
exdesigndlg.lbl.Selectexample = Choisir l'exemple de projet \u00E0 ouvrir:
filetypes.images = Fichiers Image
FileHelper.IMAGES = Fichiers Image
! General file type names
filetypes.pdf = fichier PDF
FileHelper.PDF_FILTER = fichier PDF
main.menu.analyze = Analyse
main.menu.analyze.componentAnalysis = Analyse des Pi\u00E8ces

View File

@ -92,12 +92,13 @@ dlg.but.close = Chiudi
! General file type names
filetypes.pdf = PDF files
BasicFrame.SimpleFileFilter1 = Tutti i disegni di razzi (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = Disegni di OpenRocket (*.ork)
BasicFrame.SimpleFileFilter3 = Disegni di RockSim (*.rkt)
BasicFrame.SimpleFileFilter4 = OpenRocket presets (*.orc)
filetypes.images = Image files
FileHelper.PDF_FILTER = PDF files
FileHelper.ALL_DESIGNS_FILTER = Tutti i disegni di razzi (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = Disegni di OpenRocket (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = Disegni di RockSim (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket presets (*.orc)
FileHelper.IMAGES = Image files
FileHelper.CSV_FILTER = Valori separati da virgola (*.csv)
! About Dialog
@ -415,7 +416,6 @@ RK4SimulationStepper.error.valuesTooLarge = I valori di simulazione anno eccedut
! SimulationExportPanel
SimExpPan.desc = Valori separati da virgola (*.csv)
SimExpPan.border.Vartoexport = Variabili da esportare
SimExpPan.but.Selectall = Seleziona tutto
SimExpPan.but.Selectnone = Deseleziona tutto
@ -1004,6 +1004,7 @@ TCMotorSelPan.lbl.Selectthrustcurve = Seleziona la curva di spinta:
TCMotorSelPan.lbl.Ejectionchargedelay = Ritardo della carica di espulsione:
TCMotorSelPan.equalsIgnoreCase.None = Nessun
TCMotorSelPan.lbl.NumberofsecondsorNone = (Numero di secondi o \"Nessuno\")
TCMotorSelPan.lbl.Designation = Classe:
TCMotorSelPan.lbl.Totalimpulse = Impulso totale:
TCMotorSelPan.lbl.Avgthrust = Spinta media:
TCMotorSelPan.lbl.Maxthrust = Spinta max.:
@ -1277,7 +1278,8 @@ FlightEvent.Type.ALTITUDE = Cambio altitudine
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Produttore
TCurveMotorCol.DESIGNATION = Classe
TCurveMotorCol.COMMON_NAME = Nome
! TCurveMotorCol.DESIGNATION = Classe
TCurveMotorCol.TYPE = Tipo
TCurveMotorCol.DIAMETER = Diametro
TCurveMotorCol.LENGTH = Lunghezza

View File

@ -86,12 +86,13 @@ dlg.but.cancel = \u30AD\u30E3\u30F3\u30BB\u30EB
dlg.but.close = \u9589\u3058\u308B
! General file type names
filetypes.pdf = PDF files (*.pdf)
BasicFrame.SimpleFileFilter1 = All rocket designs (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket designs (*.ork)
BasicFrame.SimpleFileFilter3 = RockSim designs (*.rkt)
BasicFrame.SimpleFileFilter4 = OpenRocket presets (*.orc)
filetypes.images = \u753B\u50CF\u30D5\u30A1\u30A4\u30EB
FileHelper.PDF_FILTER = PDF files (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = All rocket designs (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket designs (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim designs (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket presets (*.orc)
FileHelper.IMAGES = \u753B\u50CF\u30D5\u30A1\u30A4\u30EB
FileHelper.CSV_FILTER = Comma Separated Files (*.csv)
! About Dialog
@ -421,7 +422,6 @@ RK4SimulationStepper.error.valuesTooLarge = \u30B7\u30DF\u30E5\u30EC\u30FC\u30B
SimulationModifierTree.OptimizationParameters = \u6700\u9069\u5316\u30D1\u30E9\u30E1\u30FC\u30BF
! SimulationExportPanel
SimExpPan.desc = Comma Separated Files (*.csv)
SimExpPan.border.Vartoexport = \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3059\u308B\u5909\u6570
SimExpPan.but.Selectall = \u5168\u3066\u9078\u629E
SimExpPan.but.Selectnone = \u5168\u3066\u975E\u9078\u629E
@ -1035,6 +1035,7 @@ TCMotorSelPan.lbl.Selectthrustcurve = \u63A8\u529B\u5C65\u6B74\uFF1A
TCMotorSelPan.lbl.Ejectionchargedelay = Ejection charge delay:
TCMotorSelPan.equalsIgnoreCase.None = None
TCMotorSelPan.lbl.NumberofsecondsorNone = (Number of seconds or \"None\")
TCMotorSelPan.lbl.Designation = \u8A18\u53F7
TCMotorSelPan.lbl.Totalimpulse = \u30C8\u30FC\u30BF\u30EB\u30A4\u30F3\u30D1\u30EB\u30B9\uFF1A
TCMotorSelPan.lbl.Avgthrust = \u5E73\u5747\u63A8\u529B\uFF1A
TCMotorSelPan.lbl.Maxthrust = \u6700\u5927\u63A8\u529B\uFF1A
@ -1326,7 +1327,8 @@ FlightEvent.Type.ALTITUDE = \u59FF\u52E2\u5909\u66F4
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = \u30E1\u30FC\u30AB\u30FC
TCurveMotorCol.DESIGNATION = \u8A18\u53F7
! TCurveMotorCol.DESIGNATION = \u8A18\u53F7
TCurveMotorCol.COMMON_NAME = \u8A18\u53F7
TCurveMotorCol.TYPE = \u30BF\u30A4\u30D7
TCurveMotorCol.DIAMETER = \u76F4\u5F84
TCurveMotorCol.LENGTH = \u9577\u3055

View File

@ -92,12 +92,13 @@ dlg.but.cancel = Annuleer
dlg.but.close = Sluit
! General file type names
filetypes.pdf = PDF-bestanden (*.pdf)
BasicFrame.SimpleFileFilter1 = Alle raketontwerpen (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket-ontwerpen (*.ork)
BasicFrame.SimpleFileFilter3 = RockSim-ontwerpen (*.rkt)
BasicFrame.SimpleFileFilter4 = OpenRocket-presets (*.orc)
filetypes.images = Afbeelding-bestanden
FileHelper.PDF_FILTER = PDF-bestanden (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = Alle raketontwerpen (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket-ontwerpen (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim-ontwerpen (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket-presets (*.orc)
FileHelper.IMAGES = Afbeelding-bestanden
FileHelper.CSV_FILTER = Komma-gescheiden bestanden (*.csv)
! About Dialog
@ -513,7 +514,6 @@ RK4SimulationStepper.error.valuesTooLarge = Simulatiewaarden overschreden limiet
SimulationModifierTree.OptimizationParameters = Optimalisatieparameters
! SimulationExportPanel
SimExpPan.desc = Komma-gescheiden bestanden (*.csv)
SimExpPan.border.Vartoexport = Variabelen om te exporteren
SimExpPan.border.Stage = Trap om te exporteren
SimExpPan.but.Selectall = Selecteer alles
@ -1201,6 +1201,7 @@ TCMotorSelPan.lbl.Selectthrustcurve = Selecteer stuwkrachtcurve:
TCMotorSelPan.lbl.Ejectionchargedelay = Vertraging schietlading:
TCMotorSelPan.equalsIgnoreCase.None = Geen
TCMotorSelPan.lbl.NumberofsecondsorNone = (Aantal seconden of \"Geen\")
TCMotorSelPan.lbl.Designation = Benaming
TCMotorSelPan.lbl.Totalimpulse = Totale impuls:
TCMotorSelPan.lbl.Avgthrust = Gemiddelde stuwkracht:
TCMotorSelPan.lbl.Maxthrust = Max. stuwkracht:
@ -1576,7 +1577,8 @@ FlightEvent.Type.EXCEPTION = Uitzondering
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Fabrikant
TCurveMotorCol.DESIGNATION = Benaming
TCurveMotorCol.COMMON_NAME = Naam
! TCurveMotorCol.DESIGNATION = Benaming
TCurveMotorCol.CASEINFO = Behuizing
TCurveMotorCol.DIAMETER = Diameter
TCurveMotorCol.LENGTH = Lengte

View File

@ -91,12 +91,13 @@
! General file type names
filetypes.pdf = Pliki PDF (*.pdf)
BasicFrame.SimpleFileFilter1 = Wszystkie projekty rakiet (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = Projekty OpenRocket (*.ork; *.rkt)
BasicFrame.SimpleFileFilter3 = Projekty RockSim (*.rkt)
BasicFrame.SimpleFileFilter4 = Ustawienia OpenRocket (*.orc)
filetypes.images = Pliki obrazów
FileHelper.PDF_FILTER = Pliki PDF (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = Wszystkie projekty rakiet (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = Projekty OpenRocket (*.ork; *.rkt)
FileHelper.ROCKSIM_DESIGN_FILTER = Projekty RockSim (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = Ustawienia OpenRocket (*.orc)
FileHelper.IMAGES = Pliki obrazów
FileHelper.CSV_FILTER = Pliki rozdzielone przecinkiem (*.csv)
! About Dialog
@ -412,7 +413,6 @@
! SimulationExportPanel
SimExpPan.desc = Pliki rozdzielone przecinkiem (*.csv)
SimExpPan.border.Vartoexport = Zmienne do wyeksportowania
SimExpPan.but.Selectall = Wybierz wszystko
SimExpPan.but.Selectnone = Odznacz wszystko
@ -947,6 +947,7 @@
TCMotorSelPan.lbl.Ejectionchargedelay = Opó\u017Anienie odpalenia \u0142adunku odrzucaj\u0105cego:
TCMotorSelPan.equalsIgnoreCase.None = \u017Badne
TCMotorSelPan.lbl.NumberofsecondsorNone = (liczba sekund lub \"Brak\")
TCMotorSelPan.lbl.Designation = Oznaczenie:
TCMotorSelPan.lbl.Totalimpulse = Ca\u0142kowity impuls:
TCMotorSelPan.lbl.Avgthrust = \u015Arednia si\u0142a ci\u0105gu:
TCMotorSelPan.lbl.Maxthrust = Maks. si\u0142a ci\u0105gu:
@ -1218,7 +1219,8 @@
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Producent
TCurveMotorCol.DESIGNATION = Oznaczenie
TCurveMotorCol.COMMON_NAME = Nazwa
! TCurveMotorCol.DESIGNATION = Oznaczenie
TCurveMotorCol.TYPE = Typ
TCurveMotorCol.DIAMETER = \u015Arednica
TCurveMotorCol.LENGTH = D\u0142ugo\u015B\u0107

View File

@ -33,10 +33,11 @@ AppearanceCfg.lbl.texture.repeat = Repetir:
AppearanceCfg.lbl.texture.rotation = Rota\u00e7\u00e3o:
AppearanceCfg.lbl.texture.scale = Escala:
BasicFrame.SimpleFileFilter1 = Todos os projetos dos foguetes (*.ork; *.rtk)
BasicFrame.SimpleFileFilter2 = Projetos OpenRocket (*.ork)
BasicFrame.SimpleFileFilter3 = Desenhos RockSim (*.rtk)
BasicFrame.SimpleFileFilter4 = Pr\u00e9-defini\u00e7\u00f5es OpenRocket (*.orc)
FileHelper.ALL_DESIGNS_FILTER = Todos os projetos dos foguetes (*.ork; *.rtk)
FileHelper.OPENROCKET_DESIGN_FILTER = Projetos OpenRocket (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = Desenhos RockSim (*.rtk)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = Pr\u00e9-defini\u00e7\u00f5es OpenRocket (*.orc)
FileHelper.CSV_FILTER = Arquivos Separados por V\u00edrgulas (*.csv)
BasicFrame.StageName.Sustainer = Sustentador
BasicFrame.WarningDialog.title = Avisos ao abrir arquivo
BasicFrame.WarningDialog.txt1 = Os seguintes problemas foram encontrados durante a abertura
@ -966,7 +967,6 @@ SimExpPan.checkbox.ttip.Incflightevents = Incluir uma linha de coment\u00e1rio
SimExpPan.checkbox.ttip.Includefielddesc = Incluir uma linha de coment\u00e1rio com as descri\u00e7\u00f5es das vari\u00e1veis exportadas.
SimExpPan.checkbox.ttip.Includesimudesc = Incluir um coment\u00e1rio no come\u00e7o do arquivo descrevendo a simula\u00e7\u00e3o.
# SimulationExportPanel
SimExpPan.desc = Arquivos Separados por V\u00edrgulas (*.csv)
SimExpPan.lbl.Commentchar = Caracter de coment\u00e1rio:
SimExpPan.lbl.Fieldsepstr = Caracteres separadores de campo:
SimExpPan.lbl.longA1 = <html>Cadeia de caracteres utilizada para separar os campos no arquivo exportado.<br>
@ -1081,6 +1081,7 @@ StreamerCfg.tab.Radialpos = Posi\u00e7\u00e3o radial
StreamerCfg.tab.ttip.General = Propriedades gerais
StreamerCfg.tab.ttip.Radialpos = Configura\u00e7\u00e3o posi\u00e7\u00e3o radial
# ThrustCurveMotorSelectionPanel
TCMotorSelPan.SHOW_DESCRIPTIONS.desc1 = Mostrar todos os motores
TCMotorSelPan.SHOW_DESCRIPTIONS.desc2 = Mostrar motores com um di\u00e2metro menor do que a montagem do motor
TCMotorSelPan.SHOW_DESCRIPTIONS.desc3 = Mostrar motores com um di\u00e2metro igual ao da montagem do motor
@ -1099,8 +1100,8 @@ TCMotorSelPan.lbl.Motormountdia = Di\u00e2metro da montagem do motor:
TCMotorSelPan.lbl.NumberofsecondsorNone = (N\u00famero de segundos ou "Nenhum")
TCMotorSelPan.lbl.Search = Pesquisar:
TCMotorSelPan.lbl.Selectthrustcurve = Selecione curva de empuxo:
# ThrustCurveMotorSelectionPanel
TCMotorSelPan.lbl.Selrocketmotor = Selecione motor do foguete:
TCMotorSelPan.lbl.Designation = Designa\u00e7\u00e3o
TCMotorSelPan.lbl.Totalimpulse = Impulso total:
TCMotorSelPan.noDescription = Nenhuma descri\u00e7\u00e3o dispon\u00edvel.
TCMotorSelPan.title.Thrust = Impulso
@ -1115,10 +1116,11 @@ TCurveMotor.ttip.length = Comprimento:
TCurveMotor.ttip.maxThrust = M\u00e1ximo de impulso:
TCurveMotor.ttip.totalImpulse = Impulso total:
TCurveMotorCol.DESIGNATION = Designa\u00e7\u00e3o
# ThrustCurveMotorColumns
TCurveMotorCol.COMMON_NAME = Nome
! TCurveMotorCol.DESIGNATION = Designa\u00e7\u00e3o
TCurveMotorCol.DIAMETER = Di\u00e2metro
TCurveMotorCol.LENGTH = Comprimento
# ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Fabricante
TCurveMotorCol.TYPE = Tipo
@ -1378,9 +1380,9 @@ exdesigndlg.lbl.Examplesnotfound = Exemplos n\u00e3o encontrados
exdesigndlg.lbl.Openexampledesign = Abrir exemplo de projeto
exdesigndlg.lbl.Selectexample = Selecione projeto de exemplo para abrir:
filetypes.images = Arquivos de imagem
FileHelper.IMAGES = Arquivos de imagem
# General file type names
filetypes.pdf = Arquivos PDF (*.pdf)
FileHelper.PDF_FILTER = Arquivos PDF (*.pdf)
main.menu.analyze = Analisar
main.menu.analyze.componentAnalysis = An\u00e1lise dos componentes

View File

@ -91,12 +91,13 @@ dlg.but.cancel = \u041e\u0442\u043c\u0435\u043d\u0430
dlg.but.close = \u0417\u0430\u043a\u0440\u044b\u0442\u044c
! General file type names
filetypes.pdf = \u0424\u0430\u0439\u043b\u044b PDF (*.pdf)
BasicFrame.SimpleFileFilter1 = \u0412\u0441\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0440\u0430\u043a\u0435\u0442 (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = \u0424\u0430\u0439\u043b\u044b OpenRocket (*.ork)
BasicFrame.SimpleFileFilter3 = \u0424\u0430\u0439\u043b\u044b RockSim (*.rkt)
BasicFrame.SimpleFileFilter4 = \u0417\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u0438 OpenRocket (*.orc)
filetypes.images = \u0424\u0430\u0439\u043b\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439
FileHelper.PDF_FILTER = \u0424\u0430\u0439\u043b\u044b PDF (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = \u0412\u0441\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0440\u0430\u043a\u0435\u0442 (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = \u0424\u0430\u0439\u043b\u044b OpenRocket (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = \u0424\u0430\u0439\u043b\u044b RockSim (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = \u0417\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u0438 OpenRocket (*.orc)
FileHelper.IMAGES = \u0424\u0430\u0439\u043b\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439
FileHelper.CSV_FILTER = \u0422\u0435\u043a\u0441\u0442, \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u044f\u0442\u044b\u043c\u0438 (*.csv)
! About Dialog
@ -465,7 +466,6 @@ RK4SimulationStepper.error.valuesTooLarge = \u0417\u043d\u0430\u0447\u0435\u043d
SimulationModifierTree.OptimizationParameters = \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b
! SimulationExportPanel
SimExpPan.desc = \u0422\u0435\u043a\u0441\u0442, \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u044f\u0442\u044b\u043c\u0438 (*.csv)
SimExpPan.border.Vartoexport = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435
SimExpPan.border.Stage = \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0443\u043f\u0435\u043d\u044c
SimExpPan.but.Selectall = \u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435
@ -1103,6 +1103,7 @@ TCMotorSelPan.lbl.Selectthrustcurve = \u0412\u044b\u0431\u043e\u0440 \u043f\u044
TCMotorSelPan.lbl.Ejectionchargedelay = \u0417\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u0432\u044b\u0431\u0440\u043e\u0441\u0430 \u0437\u0430\u0440\u044f\u0434\u0430:
TCMotorSelPan.equalsIgnoreCase.None = \u041d\u0435\u0442
TCMotorSelPan.lbl.NumberofsecondsorNone = (\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0435\u043a\u0443\u043d\u0434 \u0438\u043b\u0438 "\u041d\u0435\u0442")
TCMotorSelPan.lbl.Designation = \u041e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:
TCMotorSelPan.lbl.Totalimpulse = \u041e\u0431\u0449\u0438\u0439 \u0438\u043c\u043f\u0443\u043b\u044c\u0441:
TCMotorSelPan.lbl.Avgthrust = \u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0442\u044f\u0433\u0430:
TCMotorSelPan.lbl.Maxthrust = \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0442\u044f\u0433\u0430:
@ -1417,7 +1418,8 @@ FlightEvent.Type.EXCEPTION = \u041e\u0448\u0438\u0431\u043a\u0430
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c
TCurveMotorCol.DESIGNATION = \u041e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435
TCurveMotorCol.COMMON_NAME = \u041e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435
! TCurveMotorCol.DESIGNATION = \u041e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435
TCurveMotorCol.TYPE = \u0422\u0438\u043f
TCurveMotorCol.DIAMETER = \u0414\u0438\u0430\u043c\u0435\u0442\u0440
TCurveMotorCol.LENGTH = \u0414\u043b\u0438\u043d\u0430

View File

@ -99,12 +99,12 @@ dlg.but.ok = Tamam
dlg.but.cancel = \u00c7\u0131k\u0131\u015f
dlg.but.close = Kapat
! General file type names
filetypes.pdf = PDF files (*.pdf)
BasicFrame.SimpleFileFilter1 = All rocket designs (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket designs (*.ork)
BasicFrame.SimpleFileFilter3 = RockSim designs (*.rkt)
BasicFrame.SimpleFileFilter4 = OpenRocket presets (*.orc)
filetypes.images = Resim Dosyalar\u0131
FileHelper.PDF_FILTER = PDF files (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = All rocket designs (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket designs (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim designs (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket presets (*.orc)
FileHelper.IMAGES = Resim Dosyalar\u0131
! Diyolog Hakk\u0131nda

View File

@ -93,12 +93,13 @@ dlg.but.cancel = Cancel
dlg.but.close = Close
! General file type names
filetypes.pdf = PDF files (*.pdf)
BasicFrame.SimpleFileFilter1 = All rocket designs (*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket designs (*.ork)
BasicFrame.SimpleFileFilter3 = RockSim designs (*.rkt)
BasicFrame.SimpleFileFilter4 = OpenRocket presets (*.orc)
filetypes.images = Image files
FileHelper.PDF_FILTER = PDF files (*.pdf)
FileHelper.ALL_DESIGNS_FILTER = All rocket designs (*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket designs (*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim designs (*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket presets (*.orc)
FileHelper.IMAGES = Image files
FileHelper.CSV_FILTER = Comma Separated Files (*.csv)
! About Dialog
@ -469,7 +470,6 @@ RK4SimulationStepper.error.valuesTooLarge = Simulation values exceeded limits.
SimulationModifierTree.OptimizationParameters = Optimization Parameters
! SimulationExportPanel
SimExpPan.desc = Comma Separated Files (*.csv)
SimExpPan.border.Vartoexport = Variables to export
SimExpPan.border.Stage = Stage to export
SimExpPan.but.Selectall = Select all
@ -1108,6 +1108,7 @@ TCMotorSelPan.lbl.Selectthrustcurve = Select thrust curve:
TCMotorSelPan.lbl.Ejectionchargedelay = Ejection charge delay:
TCMotorSelPan.equalsIgnoreCase.None = None
TCMotorSelPan.lbl.NumberofsecondsorNone = (Number of seconds or \"None\")
TCMotorSelPan.lbl.Designation = Designation:
TCMotorSelPan.lbl.Totalimpulse = Total impulse:
TCMotorSelPan.lbl.Avgthrust = Avg. thrust:
TCMotorSelPan.lbl.Maxthrust = Max. thrust:
@ -1423,7 +1424,8 @@ FlightEvent.Type.EXCEPTION = Exception
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = Manufacturer
TCurveMotorCol.DESIGNATION = Designation
TCurveMotorCol.COMMON_NAME = Name
! TCurveMotorCol.DESIGNATION = Designation
TCurveMotorCol.TYPE = Type
TCurveMotorCol.DIAMETER = Diameter
TCurveMotorCol.LENGTH = Length

View File

@ -47,10 +47,11 @@ BasicEventSimulationEngine.error.earlyMotorBurnout = \u53D1\u52A8\u673A\u8D77\u9
BasicEventSimulationEngine.error.noIgnition = \u53D1\u52A8\u673A\u672A\u70B9\u706B
BasicEventSimulationEngine.error.noMotorsDefined = \u53D1\u52A8\u673A\u672A\u5B9A\u4E49
BasicFrame.SimpleFileFilter1 = \u652F\u6301\u7684\u706B\u7BAD\u8BBE\u8BA1\u7A3F(*.ork; *.rkt)
BasicFrame.SimpleFileFilter2 = OpenRocket\u8BBE\u8BA1\u7A3F(*.ork)
BasicFrame.SimpleFileFilter3 = RockSim\u8BBE\u8BA1\u7A3F(*.rkt)
BasicFrame.SimpleFileFilter4 = OpenRocket\u914D\u7F6E(*.orc)
FileHelper.ALL_DESIGNS_FILTER = \u652F\u6301\u7684\u706B\u7BAD\u8BBE\u8BA1\u7A3F(*.ork; *.rkt)
FileHelper.OPENROCKET_DESIGN_FILTER = OpenRocket\u8BBE\u8BA1\u7A3F(*.ork)
FileHelper.ROCKSIM_DESIGN_FILTER = RockSim\u8BBE\u8BA1\u7A3F(*.rkt)
FileHelper.OPEN_ROCKET_COMPONENT_FILTER = OpenRocket\u914D\u7F6E(*.orc)
FileHelper.CSV_FILTER = CSV\u6570\u636E\u6587\u4EF6 (*.csv)
BasicFrame.StageName.Sustainer = \u4E3B\u53D1\u52A8\u673A
BasicFrame.WarningDialog.title = \u6253\u5F00\u6587\u4EF6\u65F6\u8B66\u544A
BasicFrame.WarningDialog.txt1 = \u6253\u5F00\u8BBE\u8BA1\u7A3F\u65F6\u9047\u5230\u4EE5\u4E0B\u95EE\u9898
@ -1047,7 +1048,6 @@ SimExpPan.checkbox.ttip.Incflightevents = \u6CE8\u91CA\u884C\u7528\u4E8E\u63CF\
SimExpPan.checkbox.ttip.Includefielddesc = \u6CE8\u91CA\u884C\u7528\u4E8E\u63CF\u8FF0\u8F93\u51FA\u53D8\u91CF.
SimExpPan.checkbox.ttip.Includesimudesc = \u5728\u6587\u4EF6\u5934\u52A0\u4E0A\u6CE8\u91CA\u884C\u7528\u4E8E\u63CF\u8FF0\u4EFF\u771F\u5185\u5BB9.
! SimulationExportPanel
SimExpPan.desc = CSV\u6570\u636E\u6587\u4EF6 (*.csv)
SimExpPan.lbl.Commentchar = \u6CE8\u91CA\u6807\u8BC6\u7B26:
SimExpPan.lbl.Fieldsepstr = \u6570\u636E\u5206\u9694\u5B57\u7B26\u4E32:
SimExpPan.lbl.longA1 = <html>\u5B57\u7B26\u4E32\u7528\u4E8E\u5206\u9694\u8F93\u51FA\u6587\u4EF6\u4E2D\u7684\u6570\u636E\u57DF.<br>
@ -1177,6 +1177,7 @@ StreamerCfg.tab.Radialpos = \u5F84\u5411\u4F4D\u7F6E
StreamerCfg.tab.ttip.General = \u5E38\u89C4\u5C5E\u6027
StreamerCfg.tab.ttip.Radialpos = \u5F84\u5411\u4F4D\u7F6E\u8BBE\u7F6E
! ThrustCurveMotorSelectionPanel
TCMotorSelPan.Diameter = \u76F4\u5F84
TCMotorSelPan.Length = \u957F\u5EA6
TCMotorSelPan.MotorMountDimensions = \u53D1\u52A8\u673A\u5EA7\u5C3A\u5BF8:
@ -1203,8 +1204,8 @@ TCMotorSelPan.lbl.Maxthrust = \u6700\u5927\u63A8\u529B:
TCMotorSelPan.lbl.NumberofsecondsorNone = (\u79D2\u6570\u6216"\u65E0")
TCMotorSelPan.lbl.Search = \u641C\u7D22:
TCMotorSelPan.lbl.Selectthrustcurve = \u9009\u62E9\u63A8\u529B\u66F2\u7EBF:
! ThrustCurveMotorSelectionPanel
TCMotorSelPan.lbl.Selrocketmotor = \u9009\u62E9\u706B\u7BAD\u53D1\u52A8\u673A:
TCMotorSelPan.lbl.Designation = \u540D\u79F0:
TCMotorSelPan.lbl.Totalimpulse = \u603B\u51B2\u91CF:
TCMotorSelPan.noDescription = \u63CF\u8FF0\u4E0D\u53EF\u7528.
TCMotorSelPan.title.Thrust = \u63A8\u529B
@ -1219,10 +1220,11 @@ TCurveMotor.ttip.length = \u957F\u5EA6:
TCurveMotor.ttip.maxThrust = \u6700\u5927\u63A8\u529B:
TCurveMotor.ttip.totalImpulse = \u603B\u51B2\u529B:
TCurveMotorCol.DESIGNATION = \u540D\u79F0
! ThrustCurveMotorColumns
TCurveMotorCol.COMMON_NAME = \u540D\u79F0
! TCurveMotorCol.DESIGNATION = \u540D\u79F0
TCurveMotorCol.DIAMETER = \u76F4\u5F84
TCurveMotorCol.LENGTH = \u957F\u5EA6
! ThrustCurveMotorColumns
TCurveMotorCol.MANUFACTURER = \u5236\u9020\u5546
TCurveMotorCol.TOTAL_IMPULSE = \u603B\u51B2
TCurveMotorCol.TYPE = \u7C7B\u578B
@ -1497,9 +1499,9 @@ exdesigndlg.lbl.Examplesnotfound = \u8303\u4F8B\u672A\u627E\u5230
exdesigndlg.lbl.Openexampledesign = \u6253\u5F00\u8303\u4F8B\u8BBE\u8BA1\u7A3F
exdesigndlg.lbl.Selectexample = \u9009\u62E9\u8303\u4F8B\u8BBE\u8BA1\u7A3F:
filetypes.images = \u56FE\u50CF\u6587\u4EF6
FileHelper.IMAGES = \u56FE\u50CF\u6587\u4EF6
! General file type names
filetypes.pdf = PDF \u6587\u4EF6 (*.pdf)
FileHelper.PDF_FILTER = PDF \u6587\u4EF6 (*.pdf)
generalprefs.languages.default = \u7CFB\u7EDF\u9ED8\u8BA4
generalprefs.lbl.language = \u754C\u9762\u8BED\u8A00

View File

@ -38,8 +38,8 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
private final List<Double> delays = new ArrayList<Double>();
private Manufacturer manufacturer = null;
private String commonName = null;
private String designation = null;
private String simplifiedDesignation = null;
private double diameter = -1;
private double length = -1;
private long totalImpulse = 0;
@ -57,7 +57,6 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
checkFirstInsertion(motor);
verifyMotor(motor);
updateType(motor);
checkChangeSimplifiedDesignation(motor);
addStandardDelays(motor);
if(!checkMotorOverwrite(motor)){
motors.add(motor);
@ -144,23 +143,6 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
Collections.sort(delays);
}
/**
* checks if simplified designation should be changed with the given motor
* @param motor the motor to be checked with
*/
private void checkChangeSimplifiedDesignation(ThrustCurveMotor motor) {
// Change the simplified designation if necessary
if (!designation.equalsIgnoreCase(motor.getDesignation().trim())) {
designation = simplifiedDesignation;
}
if (caseInfo == null) {
caseInfo = motor.getCaseInfo();
}
}
/**
* checks if the cached type should be changed with the given motor
* if it's hybrid, delays will be added
@ -206,7 +188,7 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
if (motors.isEmpty()) {
manufacturer = motor.getManufacturer();
designation = motor.getDesignation();
simplifiedDesignation = simplifyDesignation(designation);
commonName = motor.getCommonName();
diameter = motor.getDiameter();
length = motor.getLength();
totalImpulse = Math.round((motor.getTotalImpulseEstimate()));
@ -239,14 +221,14 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
return false;
}
if (!simplifiedDesignation.equalsIgnoreCase(simplifyDesignation(m.getDesignation())))
if (!commonName.equalsIgnoreCase(m.getCommonName()))
return false;
if (caseInfo != null && !caseInfo.equalsIgnoreCase(m.getCaseInfo()))
return false;
return true;
}
}
/**
* returns a new list with the stored motors
@ -283,11 +265,17 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
public Manufacturer getManufacturer() {
return manufacturer;
}
/**
* Return the designation of this motor type. This is either the exact or simplified
* designation, depending on what motors have been added.
* Return the common name of this motor type.
* @return the common name
*/
public String getCommonName() {
return commonName;
}
/**
* Return the designation of this motor type.
* @return the designation
*/
public String getDesignation() {
@ -352,25 +340,6 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
return "ThrustCurveMotorSet[" + manufacturer + " " + designation +
", type=" + type + ", count=" + motors.size() + "]";
}
private static final Pattern SIMPLIFY_PATTERN = Pattern.compile("^[0-9]*[ -]*([A-Z][0-9]+).*");
/**
* Simplify a motor designation, if possible. This attempts to reduce the designation
* into a simple letter + number notation for the impulse class and average thrust.
*
* @param str the designation to simplify
* @return the simplified designation, or the string itself if the format was not detected
*/
public static String simplifyDesignation(String str) {
str = str.trim();
Matcher m = SIMPLIFY_PATTERN.matcher(str);
if (m.matches()) {
return m.group(1);
} else {
return str.replaceAll("\\s", "");
}
}
/**
* Comparator for deciding in which order to display matching motors.
@ -379,11 +348,12 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
@Override
public int compare(ThrustCurveMotor o1, ThrustCurveMotor o2) {
// 1. Designation
if (!o1.getDesignation().equals(o2.getDesignation())) {
return o1.getDesignation().compareTo(o2.getDesignation());
}
// 2. Number of data points (more is better)
if (o1.getSampleSize() != o2.getSampleSize()) {
return o2.getSampleSize() - o1.getSampleSize();

View File

@ -44,7 +44,9 @@ public class ThrustCurveMotorSetDatabase implements MotorDatabase {
matchDescription = false;
else if (manufacturer != null && !m.getManufacturer().matches(manufacturer))
matchDescription = false;
else if (designation != null && !designation.equalsIgnoreCase(m.getDesignation()))
else if (designation != null &&
!designation.equalsIgnoreCase(m.getDesignation()) &&
!designation.equalsIgnoreCase(m.getCommonName()))
matchDescription = false;
else if (!Double.isNaN(diameter) && (Math.abs(diameter - m.getDiameter()) > 0.005))
matchDescription = false;

View File

@ -810,7 +810,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
listeners.remove(listener);
}
protected void fireDocumentChangeEvent(DocumentChangeEvent event) {
public void fireDocumentChangeEvent(DocumentChangeEvent event) {
DocumentChangeListener[] array = listeners.toArray(new DocumentChangeListener[0]);
for (DocumentChangeListener l : array) {
l.documentChanged(event);

View File

@ -152,7 +152,7 @@ class DocumentConfig {
// BodyTube
setters.put("BodyTube:radius", new DoubleSetter(
Reflection.findMethod(BodyTube.class, "setOuterRadius", double.class),
"auto",
"auto", " ",
Reflection.findMethod(BodyTube.class, "setOuterRadiusAutomatic", boolean.class)));
// Parallel Stage
@ -204,11 +204,11 @@ class DocumentConfig {
setters.put("Transition:foreradius", new DoubleSetter(
Reflection.findMethod(Transition.class, "setForeRadius", double.class),
"auto",
"auto", " ",
Reflection.findMethod(Transition.class, "setForeRadiusAutomatic", boolean.class)));
setters.put("Transition:aftradius", new DoubleSetter(
Reflection.findMethod(Transition.class, "setAftRadius", double.class),
"auto",
"auto", " ",
Reflection.findMethod(Transition.class, "setAftRadiusAutomatic", boolean.class)));
setters.put("Transition:foreshoulderradius", new DoubleSetter(

View File

@ -1,6 +1,8 @@
package net.sf.openrocket.file.openrocket.importt;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Objects;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
@ -17,6 +19,7 @@ class DoubleSetter implements Setter {
private final String specialString;
private final Reflection.Method specialMethod;
private final double multiplier;
private String separator;
/**
* Set only the double value.
@ -59,6 +62,23 @@ class DoubleSetter implements Setter {
this.specialMethod = specialMethod;
this.multiplier = 1.0;
}
/**
* Set the double value, or if the value equals the special string, use the
* special setter and set it to true. If the input string contains more information
* besides the special string, you can specify which separator should be used for
* this extra information. The part before the separator is then the special string
* and the part after the separator is the set value.
*
* @param set double setter.
* @param special special string
* @param specialMethod boolean setter.
*/
public DoubleSetter(Reflection.Method set, String special, String separator,
Reflection.Method specialMethod) {
this(set, special, specialMethod);
this.separator = separator;
}
/**
@ -80,26 +100,39 @@ class DoubleSetter implements Setter {
WarningSet warnings) {
s = s.trim();
// Check for special case
if (specialMethod != null && s.equalsIgnoreCase(specialString)) {
specialMethod.invoke(c, true);
return;
String special = s;
String data = s;
String[] args = null;
// Extract special string and data if s contains multiple data elements, separated by separator
if (separator != null) {
args = s.split(this.separator);
if (args.length > 1) {
special = args[0];
data = String.join(separator, Arrays.copyOfRange(args, 1, args.length));
}
}
// Normal case
try {
double d = Double.parseDouble(s);
if (configGetter == null) {
setMethod.invoke(c, d * multiplier);
} else {
FlightConfigurableParameterSet<?> config = (FlightConfigurableParameterSet<?>) configGetter.invoke(c);
Object obj = config.getDefault();
setMethod.invoke(obj, d * multiplier);
if (!special.equalsIgnoreCase(specialString) || (args != null && args.length > 1)) {
try {
double d = Double.parseDouble(data);
if (configGetter == null) {
setMethod.invoke(c, d * multiplier);
} else {
FlightConfigurableParameterSet<?> config = (FlightConfigurableParameterSet<?>) configGetter.invoke(c);
Object obj = config.getDefault();
setMethod.invoke(obj, d * multiplier);
}
} catch (NumberFormatException e) {
warnings.add(Warning.FILE_INVALID_PARAMETER + " data: '" + data + "' - " + c.getName());
}
} catch (NumberFormatException e) {
warnings.add(Warning.FILE_INVALID_PARAMETER);
}
// Check for special case
if (specialMethod != null && special.equalsIgnoreCase(specialString)) {
specialMethod.invoke(c, true);
}
}
}

View File

@ -22,8 +22,9 @@ public class BodyTubeSaver extends SymmetricComponentSaver {
super.addParams(c, elements);
net.sf.openrocket.rocketcomponent.BodyTube tube = (net.sf.openrocket.rocketcomponent.BodyTube) c;
if (tube.isOuterRadiusAutomatic())
elements.add("<radius>auto</radius>");
if (tube.isOuterRadiusAutomatic()) {
elements.add("<radius>auto " + tube.getOuterRadiusNoAutomatic() + "</radius>");
}
else
elements.add("<radius>" + tube.getOuterRadius() + "</radius>");

View File

@ -45,13 +45,13 @@ public class TransitionSaver extends SymmetricComponentSaver {
if (!nosecone) {
if (trans.isForeRadiusAutomatic())
elements.add("<foreradius>auto</foreradius>");
elements.add("<foreradius>auto " + trans.getForeRadiusNoAutomatic() + "</foreradius>");
else
elements.add("<foreradius>" + trans.getForeRadius() + "</foreradius>");
}
if (trans.isAftRadiusAutomatic())
elements.add("<aftradius>auto</aftradius>");
elements.add("<aftradius>auto " + trans.getAftRadiusNoAutomatic() + "</aftradius>");
else
elements.add("<aftradius>" + trans.getAftRadius() + "</aftradius>");

View File

@ -18,10 +18,20 @@ public abstract class InterpolatingAtmosphericModel implements AtmosphericModel
if (levels == null)
computeLayers();
if (altitude <= 0)
if (altitude <= 0) {
// TODO: LOW: levels[0] returned null in some cases, see GitHub issue #952 for more information
if (levels[0] == null) {
computeLayers();
}
return levels[0];
if (altitude >= DELTA * (levels.length - 1))
}
if (altitude >= DELTA * (levels.length - 1)) {
// TODO: LOW: levels[levels.length - 1] returned null in some cases, see GitHub issue #952 for more information
if (levels[levels.length - 1] == null) {
computeLayers();
}
return levels[levels.length - 1];
}
int n = (int) (altitude / DELTA);
double d = (altitude - n * DELTA) / DELTA;

View File

@ -90,4 +90,4 @@ public class DesignationComparator implements Comparator<String> {
return COLLATOR.compare(o1, o2);
}
}
}
}

View File

@ -74,6 +74,28 @@ public interface Motor {
public Type getMotorType();
/**
* Return the motor code
*
* @return the code
*/
public String getCode();
/**
* Return the common name of the motor.
*
* @return the common name
*/
public String getCommonName();
/**
* Return the common name of the motor, including a delay.
*
* @param delay the delay of the motor.
* @return common name with delay.
*/
public String getCommonName(double delay);
/**
* Return the designation of the motor.
*

View File

@ -62,11 +62,11 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
return ignitionOveride;
}
public String toMotorDesignation(){
public String toMotorCommonName(){
if( motor == null ){
return trans.get("empty");
}else{
return this.motor.getDesignation(this.getEjectionDelay());
return this.motor.getCommonName(this.getEjectionDelay());
}
}
@ -115,6 +115,8 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
public void useDefaultIgnition() {
this.ignitionOveride = false;
setIgnitionDelay(0);
setIgnitionEvent(IgnitionEvent.AUTOMATIC);
}
public double getIgnitionDelay() {
@ -235,7 +237,7 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
}
public String toDescription(){
return ( this.toMotorDesignation()+
return ( this.toMotorCommonName()+
" in: "+mount.getDebugName()+
" ign@: "+this.toIgnitionDescription() );
}
@ -251,7 +253,7 @@ public class MotorConfiguration implements FlightConfigurableParameter<MotorConf
mount.getDebugName(),
fcid.toShortKey(),
mid.toDebug(),
toMotorDesignation(),
toMotorCommonName(),
toIgnitionDescription() ));
return buf.toString();

View File

@ -58,7 +58,7 @@ public class MotorConfigurationSet extends FlightConfigurableParameterSet<MotorC
loopFCID.toShortKey(),
curConfig.getFCID().toShortKey(),
curConfig.getMID().toShortKey(),
curConfig.toMotorDesignation(),
curConfig.toMotorCommonName(),
curConfig.toIgnitionDescription() ));
}

View File

@ -4,6 +4,8 @@ import java.io.Serializable;
import java.text.Collator;
import java.util.Arrays;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -33,7 +35,10 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
private String digest = "";
private Manufacturer manufacturer = Manufacturer.getManufacturer("Unknown");
private String code = "";
private String commonName = "";
private String designation = "";
private String description = "";
private Motor.Type type = Motor.Type.UNKNOWN;
private double[] delays = {};
@ -74,6 +79,16 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
motor.description = d;
return this;
}
public Builder setCode(String c) {
motor.code = c;
return this;
}
public Builder setCommonName(String n) {
motor.commonName = n;
return this;
}
public Builder setDesignation(String d) {
motor.designation = d;
@ -130,10 +145,28 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
return this;
}
public Builder setAvailablity(boolean avail) {
public Builder setAvailability(boolean avail) {
motor.available = avail;
return this;
}
/**
* Simplify a motor designation, if possible. This attempts to reduce the designation
* into a simple letter + number notation for the impulse class and average thrust.
*
* @param str the designation to simplify
* @return the simplified designation, or the string itself if the format was not detected
*/
private static final Pattern SIMPLIFY_PATTERN = Pattern.compile("^[0-9]*[ -]*([A-Z][0-9]+).*");
public static String simplifyDesignation(String str) {
str = str.trim();
Matcher m = SIMPLIFY_PATTERN.matcher(str);
if (m.matches()) {
return m.group(1);
} else {
return str.replaceAll("\\s", "");
}
}
public ThrustCurveMotor build() {
// Check argument validity
@ -202,6 +235,19 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
motor.unitRotationalInertia = Inertia.filledCylinderRotational( motor.diameter / 2);
motor.unitLongitudinalInertia = Inertia.filledCylinderLongitudinal( motor.diameter / 2, motor.length);
// If I don't have a motor designation (will be the case if I read the thrustcurve from a file)
// use the motor code
if (motor.designation.equals("")) {
motor.designation = motor.code;
}
// If I don't have a motor common name (will be the case if I read the thrustcurve from a flle)
// apply the motor code simplification heuristics to generate a common name
if (motor.commonName.equals("")) {
motor.commonName = simplifyDesignation(motor.designation);
}
motor.computeStatistics();
return motor;
@ -440,6 +486,21 @@ public class ThrustCurveMotor implements Motor, Comparable<ThrustCurveMotor>, Se
public double getUnitIzz(){
return this.unitLongitudinalInertia;
}
@Override
public String getCode() {
return code;
}
@Override
public String getCommonName() {
return commonName;
}
@Override
public String getCommonName(double delay) {
return commonName + "-" + getDelayString(delay);
}
@Override
public String getDesignation() {

View File

@ -1,10 +1,7 @@
package net.sf.openrocket.rocketcomponent;
import java.util.EventObject;
import java.util.Iterator;
import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
@ -25,6 +22,8 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
private double outerRadius = 0;
private boolean autoRadius = false; // Radius chosen automatically based on parent component
private SymmetricComponent refComp = null; // Reference component that is used for the autoRadius
// When changing the inner radius, thickness is modified
private double overhang = 0;
@ -79,13 +78,17 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
// Return auto radius from front or rear
double r = -1;
SymmetricComponent c = this.getPreviousSymmetricComponent();
if (c != null) {
// Don't use the radius of a component who already has its auto diameter enabled
if (c != null && !c.usesNextCompAutomatic()) {
r = c.getFrontAutoRadius();
refComp = c;
}
if (r < 0) {
c = this.getNextSymmetricComponent();
if (c != null) {
// Don't use the radius of a component who already has its auto diameter enabled
if (c != null && !c.usesPreviousCompAutomatic()) {
r = c.getRearAutoRadius();
refComp = c;
}
}
if (r < 0)
@ -94,6 +97,14 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
}
return outerRadius;
}
/**
* Return the outer radius that was manually entered, so not the value that the component received from automatic
* outer radius.
*/
public double getOuterRadiusNoAutomatic() {
return outerRadius;
}
/**
* Set the outer radius of the body tube. If the radius is less than the wall thickness,
@ -136,8 +147,17 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
clearPreset();
}
@Override
public boolean usesPreviousCompAutomatic() {
return isOuterRadiusAutomatic() && refComp == getPreviousSymmetricComponent();
}
@Override
public boolean usesNextCompAutomatic() {
return isOuterRadiusAutomatic() && refComp == getNextSymmetricComponent();
}
@Override
protected void loadFromPreset(ComponentPreset preset) {
this.autoRadius = false;

View File

@ -8,6 +8,8 @@ import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Pair;
import java.util.Objects;
public class DeploymentConfiguration implements FlightConfigurableParameter<DeploymentConfiguration> {
@ -154,5 +156,17 @@ public class DeploymentConfiguration implements FlightConfigurableParameter<Depl
@Override
public void update(){
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DeploymentConfiguration that = (DeploymentConfiguration) o;
return Double.compare(that.deployAltitude, deployAltitude) == 0 && Double.compare(that.deployDelay, deployDelay) == 0 && deployEvent == that.deployEvent;
}
@Override
public int hashCode() {
return Objects.hash(deployEvent, deployAltitude, deployDelay);
}
}

View File

@ -441,7 +441,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
}
if( ! motorConfig.isEmpty()){
buff.append(motorConfig.toMotorDesignation());
buff.append(motorConfig.toMotorCommonName());
++activeMotorCount;
}
}

View File

@ -69,7 +69,12 @@ public class NoseCone extends Transition implements InsideColorComponent {
public void setForeRadiusAutomatic(boolean b) {
// No-op
}
@Override
public boolean usesPreviousCompAutomatic() {
return false;
}
@Override
public double getForeShoulderLength() {
return 0;

View File

@ -5,6 +5,8 @@ import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.MathUtil;
import java.util.Objects;
public class StageSeparationConfiguration implements FlightConfigurableParameter<StageSeparationConfiguration> {
public static enum SeparationEvent {
@ -144,8 +146,20 @@ public class StageSeparationConfiguration implements FlightConfigurableParameter
clone.separationDelay = this.separationDelay;
return clone;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StageSeparationConfiguration that = (StageSeparationConfiguration) o;
return Double.compare(that.separationDelay, separationDelay) == 0 && separationEvent == that.separationEvent;
}
@Override
public int hashCode() {
return Objects.hash(separationEvent, separationDelay);
}
private void fireChangeEvent() {
}

View File

@ -644,5 +644,15 @@ public abstract class SymmetricComponent extends BodyComponent implements BoxBou
}
return null;
}
/**
* Checks whether the component uses the previous symmetric component for its auto diameter.
*/
public abstract boolean usesPreviousCompAutomatic();
/**
* Checks whether the component uses the next symmetric component for its auto diameter.
*/
public abstract boolean usesNextCompAutomatic();
}

View File

@ -94,6 +94,14 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
return foreRadius;
}
/**
* Return the fore radius that was manually entered, so not the value that the component received from automatic
* fore radius.
*/
public double getForeRadiusNoAutomatic() {
return foreRadius;
}
public void setForeRadius(double radius) {
if ((this.foreRadius == radius) && (autoForeRadius == false))
return;
@ -142,7 +150,13 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
return aftRadius;
}
/**
* Return the aft radius that was manually entered, so not the value that the component received from automatic
* zft radius.
*/
public double getAftRadiusNoAutomatic() {
return aftRadius;
}
public void setAftRadius(double radius) {
if ((this.aftRadius == radius) && (autoAftRadius2 == false))
@ -192,7 +206,15 @@ public class Transition extends SymmetricComponent implements InsideColorCompone
return getForeRadius();
}
@Override
public boolean usesPreviousCompAutomatic() {
return isForeRadiusAutomatic();
}
@Override
public boolean usesNextCompAutomatic() {
return isAftRadiusAutomatic();
}
//////// Type & shape /////////

View File

@ -259,7 +259,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
private boolean handleEvents() throws SimulationException {
boolean ret = true;
FlightEvent event;
log.trace("HandleEvents: current branch = " + currentStatus.getFlightData().getBranchName());
for (event = nextEvent(); event != null; event = nextEvent()) {
log.trace("Obtained event from queue: " + event.toString());
@ -300,7 +300,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
// Ignore events for components that are no longer attached to the rocket
if (event.getSource() != null && event.getSource().getParent() != null &&
!currentStatus.getConfiguration().isComponentActive(event.getSource())) {
log.trace("Ignoring event from unattached componenent");
log.trace("Ignoring event from unattached component");
continue;
}
@ -332,6 +332,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
// Check for recovery device deployment, add events to queue
// TODO: LOW: check if deprecated function getActiveComponents needs to be replaced
for (RocketComponent c : currentStatus.getConfiguration().getActiveComponents()) {
if (!(c instanceof RecoveryDevice))
continue;
@ -532,7 +533,8 @@ public class BasicEventSimulationEngine implements SimulationEngine {
}
}
// TODO : FUTURE : do not hard code the 1200 (maybe even make it configurable by the user)
if( 1200 < currentStatus.getSimulationTime() ){
ret = false;
log.error("Simulation hit max time (1200s): aborting.");

View File

@ -220,7 +220,7 @@ public class FlightData {
timeToApogee = Double.NaN;
// Launch rod velocity
// Launch rod velocity + deployment velocity + ground hit velocity
for (FlightEvent event : branch.getEvents()) {
if (event.getType() == FlightEvent.Type.LAUNCHROD) {
double t = event.getTime();

View File

@ -0,0 +1,29 @@
package net.sf.openrocket.simulation.listeners.system;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
/**
* A simulation listeners that ends the simulation when the ground is hit.
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public class GroundHitListener extends AbstractSimulationListener {
public static final GroundHitListener INSTANCE = new GroundHitListener();
@Override
public boolean handleFlightEvent(SimulationStatus status, FlightEvent event) {
if (event.getType() == FlightEvent.Type.GROUND_HIT) {
status.getEventQueue().add(new FlightEvent(FlightEvent.Type.SIMULATION_END, status.getSimulationTime()));
}
return true;
}
@Override
public boolean isSystemListener() {
return true;
}
}

View File

@ -133,14 +133,12 @@ public class SerializeThrustcurveMotors {
builder.setDiameter(mi.getDiameter() / 1000.0);
builder.setLength(mi.getLength() / 1000.0);
builder.setMotorType(type);
builder.setCommonName(mi.getCommon_name());
builder.setDesignation(mi.getDesignation());
if ("OOP".equals(mi.getAvailiability())) {
builder.setDesignation(mi.getDesignation());
builder.setAvailablity(false);
} else if (mi.getDesignation().startsWith("Micro")) {
builder.setDesignation(mi.getDesignation());
} else {
builder.setDesignation(mi.getCommon_name());
if ("OOP".equals(mi.getAvailability())) {
builder.setAvailability(false);
}
allMotors.add(builder.build());

View File

@ -270,7 +270,7 @@ public class TCMotor implements Cloneable {
this.updated_on = updated_on;
}
public String getAvailiability() {
public String getAvailability() {
return availability;
}

View File

@ -22,6 +22,7 @@ public class ThrustCurveMotorSetTest {
private static final ThrustCurveMotor motor1 = new ThrustCurveMotor.Builder()
.setManufacturer(Manufacturer.getManufacturer("A"))
.setCommonName("F12")
.setDesignation("F12X")
.setDescription("Desc")
.setMotorType(Motor.Type.UNKNOWN)
@ -36,6 +37,7 @@ public class ThrustCurveMotorSetTest {
private static final ThrustCurveMotor motor2 = new ThrustCurveMotor.Builder()
.setManufacturer(Manufacturer.getManufacturer("A"))
.setCommonName("F12")
.setDesignation("F12H")
.setDescription("Desc")
.setMotorType(Motor.Type.SINGLE)
@ -50,7 +52,7 @@ public class ThrustCurveMotorSetTest {
private static final ThrustCurveMotor motor3 = new ThrustCurveMotor.Builder()
.setManufacturer(Manufacturer.getManufacturer("A"))
.setDesignation("F12")
.setCode("F12")
.setDescription("Desc")
.setMotorType(Motor.Type.UNKNOWN)
.setStandardDelays(new double[] { 0, Motor.PLUGGED_DELAY })
@ -65,7 +67,7 @@ public class ThrustCurveMotorSetTest {
private static final ThrustCurveMotor motor4 = new ThrustCurveMotor.Builder()
.setManufacturer(Manufacturer.getManufacturer("A"))
.setDesignation("F12")
.setDesignation("Desc")
.setDescription("Desc")
.setMotorType(Motor.Type.HYBRID)
.setStandardDelays(new double[] { 0 })
.setDiameter(0.024)
@ -75,20 +77,7 @@ public class ThrustCurveMotorSetTest {
.setCGPoints(new Coordinate[] { Coordinate.NUL, Coordinate.NUL, Coordinate.NUL })
.setDigest("digestD")
.build();
@Test
public void testSimplifyDesignation() {
assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("J115"));
assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation(" J115 "));
assertEquals("H115", ThrustCurveMotorSet.simplifyDesignation("241H115-KS"));
assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("384 J115"));
assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("384-J115"));
assertEquals("A2", ThrustCurveMotorSet.simplifyDesignation("A2T"));
assertEquals("1/2A2T", ThrustCurveMotorSet.simplifyDesignation("1/2A2T"));
assertEquals("MicroMaxxII", ThrustCurveMotorSet.simplifyDesignation("Micro Maxx II"));
}
@Test
public void testAdding() {
ThrustCurveMotorSet set = new ThrustCurveMotorSet();
@ -108,7 +97,7 @@ public class ThrustCurveMotorSetTest {
assertEquals(1, set.getMotors().size());
assertEquals(motor1, set.getMotors().get(0));
assertEquals(Collections.emptyList(), set.getDelays());
// Add motor1 again
assertTrue(set.matches(motor1));
set.addMotor(motor1);
@ -120,12 +109,12 @@ public class ThrustCurveMotorSetTest {
assertEquals(1, set.getMotors().size());
assertEquals(motor1, set.getMotors().get(0));
assertEquals(Collections.emptyList(), set.getDelays());
// Add motor2
assertTrue(set.matches(motor2));
set.addMotor(motor2);
assertEquals(motor1.getManufacturer(), set.getManufacturer());
assertEquals(motor3.getDesignation(), set.getDesignation());
assertEquals(motor3.getCommonName(), set.getCommonName());
assertEquals(Motor.Type.SINGLE, set.getType());
assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
assertEquals(motor1.getLength(), set.getLength(), 0.00001);
@ -133,21 +122,26 @@ public class ThrustCurveMotorSetTest {
assertEquals(motor2, set.getMotors().get(0));
assertEquals(motor1, set.getMotors().get(1));
assertEquals(Arrays.asList(5.0), set.getDelays());
// Add motor3
assertTrue(set.matches(motor3));
set.addMotor(motor3);
assertEquals(motor1.getManufacturer(), set.getManufacturer());
assertEquals(motor3.getDesignation(), set.getDesignation());
assertEquals(motor3.getCommonName(), set.getCommonName());
assertEquals(Motor.Type.SINGLE, set.getType());
assertEquals(motor1.getDiameter(), set.getDiameter(), 0.00001);
assertEquals(motor1.getLength(), set.getLength(), 0.00001);
assertEquals(3, set.getMotors().size());
System.out.println("motor set");
System.out.println(set.getMotors());
System.out.println(motor3);
System.out.println(motor2);
System.out.println(motor1);
assertEquals(motor3, set.getMotors().get(0));
assertEquals(motor2, set.getMotors().get(1));
assertEquals(motor1, set.getMotors().get(2));
assertEquals(Arrays.asList(0.0, 5.0, Motor.PLUGGED_DELAY), set.getDelays());
// Test that adding motor4 fails
assertFalse(set.matches(motor4));
try {

View File

@ -186,4 +186,16 @@ public class ThrustCurveMotorTest {
}
@Test
public void testSimplifyDesignation() {
assertEquals("J115", ThrustCurveMotor.Builder.simplifyDesignation("J115"));
assertEquals("J115", ThrustCurveMotor.Builder.simplifyDesignation(" J115 "));
assertEquals("H115", ThrustCurveMotor.Builder.simplifyDesignation("241H115-KS"));
assertEquals("J115", ThrustCurveMotor.Builder.simplifyDesignation("384 J115"));
assertEquals("J115", ThrustCurveMotor.Builder.simplifyDesignation("384-J115"));
assertEquals("A2", ThrustCurveMotor.Builder.simplifyDesignation("A2T"));
assertEquals("1/2A2T", ThrustCurveMotor.Builder.simplifyDesignation("1/2A2T"));
assertEquals("MicroMaxxII", ThrustCurveMotor.Builder.simplifyDesignation("Micro Maxx II"));
}
}

View File

@ -194,7 +194,7 @@ public class SimulationExportPanel extends JPanel {
private void doExport() {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(FileHelper.CSV_FILE_FILTER);
chooser.setFileFilter(FileHelper.CSV_FILTER);
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION)
@ -204,7 +204,7 @@ public class SimulationExportPanel extends JPanel {
if (file == null)
return;
file = FileHelper.ensureExtension(file, "csv");
file = FileHelper.forceExtension(file, "csv");
if (!FileHelper.confirmWrite(file, this)) {
return;
}

View File

@ -15,8 +15,10 @@ import net.sf.openrocket.gui.components.BasicSlider;
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
@ -24,6 +26,7 @@ import net.sf.openrocket.unit.UnitGroup;
public class BodyTubeConfig extends RocketComponentConfig {
private DoubleModel maxLength;
private final JCheckBox checkAutoOuterRadius;
private static final Translator trans = Application.getTranslator();
public BodyTubeConfig(OpenRocketDocument d, RocketComponent c) {
@ -58,9 +61,10 @@ public class BodyTubeConfig extends RocketComponentConfig {
//// Automatic
javax.swing.Action outerAutoAction = od.getAutomaticAction();
JCheckBox check = new JCheckBox(outerAutoAction);
check.setText(trans.get("BodyTubecfg.checkbox.Automatic"));
panel.add(check, "skip, span 2, wrap");
checkAutoOuterRadius = new JCheckBox(outerAutoAction);
checkAutoOuterRadius.setText(trans.get("BodyTubecfg.checkbox.Automatic"));
panel.add(checkAutoOuterRadius, "skip, span 2, wrap");
updateCheckboxAutoAftRadius();
//// Inner diameter
panel.add(new JLabel(trans.get("BodyTubecfg.lbl.Innerdiameter")));
@ -87,7 +91,7 @@ public class BodyTubeConfig extends RocketComponentConfig {
panel.add(new BasicSlider(thicknessModel.getSliderModel(0, 0.01)), "w 100lp, wrap 0px");
//// Filled
check = new JCheckBox(new BooleanModel(component, "Filled"));
JCheckBox check = new JCheckBox(new BooleanModel(component, "Filled"));
check.setText(trans.get("BodyTubecfg.checkbox.Filled"));
panel.add(check, "skip, span 2, wrap");
@ -113,4 +117,33 @@ public class BodyTubeConfig extends RocketComponentConfig {
super.updateFields();
}
/**
* Sets the checkAutoOuterRadius checkbox's enabled state and tooltip text, based on the state of its previous
* component. If there is no next and previous symmetric component, the checkAutoOuterRadius checkbox is disabled.
* If there is still a next or previous component which does not have its auto state enabled, meaning it can still
* serve as a reference component for this component, the auto checkbox is enabled.
*/
private void updateCheckboxAutoAftRadius() {
if (component == null || checkAutoOuterRadius == null) return;
// Disable check button if there is no component to get the diameter from
SymmetricComponent prevComp = ((BodyTube) component).getPreviousSymmetricComponent();
SymmetricComponent nextComp = ((BodyTube) component).getNextSymmetricComponent();
if (prevComp == null && nextComp == null) {
checkAutoOuterRadius.setEnabled(false);
((BodyTube) component).setOuterRadiusAutomatic(false);
checkAutoOuterRadius.setToolTipText(trans.get("BodyTubecfg.checkbox.ttip.Automatic_noReferenceComponent"));
return;
}
if (!(prevComp != null && nextComp == null && prevComp.usesNextCompAutomatic()) &&
!(nextComp != null && prevComp == null && nextComp.usesPreviousCompAutomatic()) &&
!(nextComp != null && prevComp != null && prevComp.usesNextCompAutomatic() && nextComp.usesPreviousCompAutomatic())) {
checkAutoOuterRadius.setEnabled(true);
checkAutoOuterRadius.setToolTipText(trans.get("BodyTubecfg.checkbox.ttip.Automatic"));
} else {
checkAutoOuterRadius.setEnabled(false);
((BodyTube) component).setOuterRadiusAutomatic(false);
checkAutoOuterRadius.setToolTipText(trans.get("BodyTubecfg.checkbox.ttip.Automatic_alreadyAuto"));
}
}
}

View File

@ -1,6 +1,5 @@
package net.sf.openrocket.gui.configdialog;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
@ -18,7 +17,6 @@ import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComboBox;
@ -35,7 +33,6 @@ import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import net.sf.openrocket.util.MathUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -253,17 +250,22 @@ public class FreeformFinSetConfig extends FinSetConfig {
// panel.add(new JLabel("Coordinates:"), "aligny bottom, alignx 50%");
// panel.add(new JLabel(" View:"), "wrap, aligny bottom");
JButton exportCsvButton = new SelectColorButton("Export CSV");
JButton exportCsvButton = new SelectColorButton(trans.get("FreeformFinSetConfig.lbl.exportCSV"));
exportCsvButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
log.info(Markers.USER_MARKER, "Export CSV free-form fin");
JFileChooser chooser = new JFileChooser();
// Demonstrate "Save" dialog:
chooser.setFileFilter(FileHelper.CSV_FILTER);
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
if (JFileChooser.APPROVE_OPTION == chooser.showSaveDialog(FreeformFinSetConfig.this)){
File selectedFile= chooser.getSelectedFile();
selectedFile = FileHelper.forceExtension(selectedFile, "csv");
if (!FileHelper.confirmWrite(selectedFile, panel)) {
return;
}
FreeformFinSetConfig.writeCSVFile(table, selectedFile);
}

View File

@ -23,6 +23,7 @@ import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
@ -36,6 +37,7 @@ public class NoseConeConfig extends RocketComponentConfig {
private JLabel shapeLabel;
private JSpinner shapeSpinner;
private JSlider shapeSlider;
private final JCheckBox checkAutoAftRadius;
private static final Translator trans = Application.getTranslator();
// Prepended to the description from NoseCone.DESCRIPTIONS
@ -109,10 +111,11 @@ public class NoseConeConfig extends RocketComponentConfig {
panel.add(new UnitSelector(aftRadiusModel), "growx");
panel.add(new BasicSlider(aftRadiusModel.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px");
JCheckBox check = new JCheckBox(aftRadiusModel.getAutomaticAction());
checkAutoAftRadius = new JCheckBox(aftRadiusModel.getAutomaticAction());
//// Automatic
check.setText(trans.get("NoseConeCfg.checkbox.Automatic"));
panel.add(check, "skip, span 2, wrap");
checkAutoAftRadius.setText(trans.get("NoseConeCfg.checkbox.Automatic"));
panel.add(checkAutoAftRadius, "skip, span 2, wrap");
updateCheckboxAutoAftRadius();
}
{//// Wall thickness:
@ -165,6 +168,30 @@ public class NoseConeConfig extends RocketComponentConfig {
shapeSpinner.setEnabled(e);
shapeSlider.setEnabled(e);
}
/**
* Sets the checkAutoAftRadius checkbox's enabled state and tooltip text, based on the state of its next component.
* If there is no next symmetric component or if that component already has its auto checkbox checked, the
* checkAutoAftRadius checkbox is disabled.
*/
private void updateCheckboxAutoAftRadius() {
if (component == null || checkAutoAftRadius == null) return;
// Disable check button if there is no component to get the diameter from
SymmetricComponent nextComp = ((NoseCone) component).getNextSymmetricComponent();
if (nextComp == null) {
checkAutoAftRadius.setEnabled(false);
((NoseCone) component).setAftRadiusAutomatic(false);
checkAutoAftRadius.setToolTipText(trans.get("NoseConeCfg.checkbox.ttip.Automatic_noReferenceComponent"));
return;
}
if (!nextComp.usesPreviousCompAutomatic()) {
checkAutoAftRadius.setEnabled(true);
checkAutoAftRadius.setToolTipText(trans.get("NoseConeCfg.checkbox.ttip.Automatic"));
} else {
checkAutoAftRadius.setEnabled(false);
((NoseCone) component).setAftRadiusAutomatic(false);
checkAutoAftRadius.setToolTipText(trans.get("NoseConeCfg.checkbox.ttip.Automatic_alreadyAuto"));
}
}
}

View File

@ -21,6 +21,7 @@ import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
@ -35,6 +36,8 @@ public class TransitionConfig extends RocketComponentConfig {
private JLabel shapeLabel;
private JSpinner shapeSpinner;
private BasicSlider shapeSlider;
private final JCheckBox checkAutoAftRadius;
private final JCheckBox checkAutoForeRadius;
private DescriptionArea description;
@ -120,10 +123,11 @@ public class TransitionConfig extends RocketComponentConfig {
panel.add(new UnitSelector(foreRadiusModel), "growx");
panel.add(new BasicSlider(foreRadiusModel.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px");
final JCheckBox checkbox = new JCheckBox(foreRadiusModel.getAutomaticAction());
checkAutoForeRadius = new JCheckBox(foreRadiusModel.getAutomaticAction());
//// Automatic
checkbox.setText(trans.get("TransitionCfg.checkbox.Automatic"));
panel.add(checkbox, "skip, span 2, wrap");
checkAutoForeRadius.setText(trans.get("TransitionCfg.checkbox.Automatic"));
panel.add(checkAutoForeRadius, "skip, span 2, wrap");
updateCheckboxAutoForeRadius();
}
{ //// Aft diameter:
@ -139,10 +143,11 @@ public class TransitionConfig extends RocketComponentConfig {
panel.add(new UnitSelector(aftRadiusModel), "growx");
panel.add(new BasicSlider(aftRadiusModel.getSliderModel(0, 0.04, 0.2)), "w 100lp, wrap 0px");
final JCheckBox aftRadiusCheckbox = new JCheckBox(aftRadiusModel.getAutomaticAction());
checkAutoAftRadius = new JCheckBox(aftRadiusModel.getAutomaticAction());
//// Automatic
aftRadiusCheckbox.setText(trans.get("TransitionCfg.checkbox.Automatic"));
panel.add(aftRadiusCheckbox, "skip, span 2, wrap");
checkAutoAftRadius.setText(trans.get("TransitionCfg.checkbox.Automatic"));
panel.add(checkAutoAftRadius, "skip, span 2, wrap");
updateCheckboxAutoAftRadius();
}
{ /// Wall thickness:
@ -194,5 +199,57 @@ public class TransitionConfig extends RocketComponentConfig {
shapeSpinner.setEnabled(e);
shapeSlider.setEnabled(e);
}
/**
* Sets the checkAutoAftRadius checkbox's enabled state and tooltip text, based on the state of its next component.
* If there is no next symmetric component or if that component already has its auto checkbox checked, the
* checkAutoAftRadius checkbox is disabled.
*/
private void updateCheckboxAutoAftRadius() {
if (component == null || checkAutoAftRadius == null) return;
// Disable check button if there is no component to get the diameter from
SymmetricComponent nextComp = ((Transition) component).getNextSymmetricComponent();
if (nextComp == null) {
checkAutoAftRadius.setEnabled(false);
((Transition) component).setAftRadiusAutomatic(false);
checkAutoAftRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic_noReferenceComponent"));
return;
}
if (!nextComp.usesPreviousCompAutomatic()) {
checkAutoAftRadius.setEnabled(true);
checkAutoAftRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic"));
} else {
checkAutoAftRadius.setEnabled(false);
((Transition) component).setAftRadiusAutomatic(false);
checkAutoAftRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic_alreadyAuto"));
}
}
/**
* Sets the checkAutoForeRadius checkbox's enabled state and tooltip text, based on the state of its next component.
* If there is no next symmetric component or if that component already has its auto checkbox checked, the
* checkAutoForeRadius checkbox is disabled.
*/
private void updateCheckboxAutoForeRadius() {
if (component == null || checkAutoForeRadius == null) return;
// Disable check button if there is no component to get the diameter from
SymmetricComponent prevComp = ((Transition) component).getPreviousSymmetricComponent();
if (prevComp == null) {
checkAutoForeRadius.setEnabled(false);
((Transition) component).setForeRadiusAutomatic(false);
checkAutoForeRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic_noReferenceComponent"));
return;
}
if (!prevComp.usesNextCompAutomatic()) {
checkAutoForeRadius.setEnabled(true);
checkAutoForeRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic"));
} else {
checkAutoForeRadius.setEnabled(false);
((Transition) component).setForeRadiusAutomatic(false);
checkAutoForeRadius.setToolTipText(trans.get("TransitionCfg.checkbox.ttip.Automatic_alreadyAuto"));
}
}
}

View File

@ -380,7 +380,7 @@ public class PrintDialog extends JDialog implements TreeSelectionListener {
File file = chooser.getSelectedFile();
if (returnVal == JFileChooser.APPROVE_OPTION && file != null) {
file = FileHelper.ensureExtension(file, "pdf");
file = FileHelper.forceExtension(file, "pdf");
if (!FileHelper.confirmWrite(file, this)) {
return false;
}

View File

@ -7,6 +7,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.JButton;
import javax.swing.JCheckBox;
@ -56,112 +58,118 @@ public class ScaleDialog extends JDialog {
* Scaler implementations
*
* Each scaled value (except override cg/mass) is defined using a Scaler instance.
* There are two scaler instances; one for when the offset distances (axial/radial offset) don't need to be scaled
* together with the other dimensions and one for when the offsets do need to scale.
*/
private static final Map<Class<? extends RocketComponent>, List<Scaler>> SCALERS =
private static final Map<Class<? extends RocketComponent>, List<Scaler>> SCALERS_NO_OFFSET =
new HashMap<Class<? extends RocketComponent>, List<Scaler>>();
private static final Map<Class<? extends RocketComponent>, List<Scaler>> SCALERS_OFFSET =
new HashMap<Class<? extends RocketComponent>, List<Scaler>>();
static {
List<Scaler> list;
// RocketComponent
addScaler(RocketComponent.class, "AxialOffset");
SCALERS.get(RocketComponent.class).add(new OverrideScaler());
addScaler(RocketComponent.class, "AxialOffset", SCALERS_OFFSET);
SCALERS_OFFSET.get(RocketComponent.class).add(new OverrideScaler());
// ComponentAssembly
addScaler(ParallelStage.class, "RadiusOffset");
addScaler(PodSet.class, "RadiusOffset");
addScaler(ParallelStage.class, "RadiusOffset", SCALERS_OFFSET);
addScaler(PodSet.class, "RadiusOffset", SCALERS_OFFSET);
// BodyComponent
addScaler(BodyComponent.class, "Length");
addScaler(BodyComponent.class, "Length", SCALERS_NO_OFFSET);
// SymmetricComponent
addScaler(SymmetricComponent.class, "Thickness", "isFilled");
addScaler(SymmetricComponent.class, "Thickness", "isFilled", SCALERS_NO_OFFSET);
// Transition + Nose cone
addScaler(Transition.class, "ForeRadius", "isForeRadiusAutomatic");
addScaler(Transition.class, "AftRadius", "isAftRadiusAutomatic");
addScaler(Transition.class, "ForeShoulderRadius");
addScaler(Transition.class, "ForeShoulderThickness");
addScaler(Transition.class, "ForeShoulderLength");
addScaler(Transition.class, "AftShoulderRadius");
addScaler(Transition.class, "AftShoulderThickness");
addScaler(Transition.class, "AftShoulderLength");
addScaler(Transition.class, "ForeRadius", "isForeRadiusAutomatic", SCALERS_NO_OFFSET);
addScaler(Transition.class, "AftRadius", "isAftRadiusAutomatic", SCALERS_NO_OFFSET);
addScaler(Transition.class, "ForeShoulderRadius", SCALERS_NO_OFFSET);
addScaler(Transition.class, "ForeShoulderThickness", SCALERS_NO_OFFSET);
addScaler(Transition.class, "ForeShoulderLength", SCALERS_NO_OFFSET);
addScaler(Transition.class, "AftShoulderRadius", SCALERS_NO_OFFSET);
addScaler(Transition.class, "AftShoulderThickness", SCALERS_NO_OFFSET);
addScaler(Transition.class, "AftShoulderLength", SCALERS_NO_OFFSET);
// Body tube
addScaler(BodyTube.class, "OuterRadius", "isOuterRadiusAutomatic");
addScaler(BodyTube.class, "MotorOverhang");
addScaler(BodyTube.class, "OuterRadius", "isOuterRadiusAutomatic", SCALERS_NO_OFFSET);
addScaler(BodyTube.class, "MotorOverhang", SCALERS_NO_OFFSET);
// Launch lug
addScaler(LaunchLug.class, "OuterRadius");
addScaler(LaunchLug.class, "Thickness");
addScaler(LaunchLug.class, "Length");
addScaler(LaunchLug.class, "OuterRadius", SCALERS_NO_OFFSET);
addScaler(LaunchLug.class, "Thickness", SCALERS_NO_OFFSET);
addScaler(LaunchLug.class, "Length", SCALERS_NO_OFFSET);
// FinSet
addScaler(FinSet.class, "Thickness");
addScaler(FinSet.class, "TabHeight");
addScaler(FinSet.class, "TabLength");
addScaler(FinSet.class, "TabOffset");
addScaler(FinSet.class, "Thickness", SCALERS_NO_OFFSET);
addScaler(FinSet.class, "TabHeight", SCALERS_NO_OFFSET);
addScaler(FinSet.class, "TabLength", SCALERS_NO_OFFSET);
addScaler(FinSet.class, "TabOffset", SCALERS_NO_OFFSET);
// TrapezoidFinSet
addScaler(TrapezoidFinSet.class, "Sweep");
addScaler(TrapezoidFinSet.class, "RootChord");
addScaler(TrapezoidFinSet.class, "TipChord");
addScaler(TrapezoidFinSet.class, "Height");
addScaler(TrapezoidFinSet.class, "Sweep", SCALERS_NO_OFFSET);
addScaler(TrapezoidFinSet.class, "RootChord", SCALERS_NO_OFFSET);
addScaler(TrapezoidFinSet.class, "TipChord", SCALERS_NO_OFFSET);
addScaler(TrapezoidFinSet.class, "Height", SCALERS_NO_OFFSET);
// EllipticalFinSet
addScaler(EllipticalFinSet.class, "Length");
addScaler(EllipticalFinSet.class, "Height");
addScaler(EllipticalFinSet.class, "Length", SCALERS_NO_OFFSET);
addScaler(EllipticalFinSet.class, "Height", SCALERS_NO_OFFSET);
// FreeformFinSet
list = new ArrayList<ScaleDialog.Scaler>(1);
list.add(new FreeformFinSetScaler());
SCALERS.put(FreeformFinSet.class, list);
SCALERS_NO_OFFSET.put(FreeformFinSet.class, list);
// MassObject
addScaler(MassObject.class, "Length");
addScaler(MassObject.class, "Radius");
addScaler(MassObject.class, "RadialPosition");
addScaler(MassObject.class, "Length", SCALERS_NO_OFFSET);
addScaler(MassObject.class, "Radius", SCALERS_NO_OFFSET);
addScaler(MassObject.class, "RadialPosition", SCALERS_OFFSET);
// MassComponent
list = new ArrayList<ScaleDialog.Scaler>(1);
list.add(new MassComponentScaler());
SCALERS.put(MassComponent.class, list);
SCALERS_NO_OFFSET.put(MassComponent.class, list);
// Parachute
addScaler(Parachute.class, "Diameter");
addScaler(Parachute.class, "LineLength");
addScaler(Parachute.class, "Diameter", SCALERS_NO_OFFSET);
addScaler(Parachute.class, "LineLength", SCALERS_NO_OFFSET);
// Streamer
addScaler(Streamer.class, "StripLength");
addScaler(Streamer.class, "StripWidth");
addScaler(Streamer.class, "StripLength", SCALERS_NO_OFFSET);
addScaler(Streamer.class, "StripWidth", SCALERS_NO_OFFSET);
// ShockCord
addScaler(ShockCord.class, "CordLength");
addScaler(ShockCord.class, "CordLength", SCALERS_NO_OFFSET);
// RingComponent
addScaler(RingComponent.class, "Length");
addScaler(RingComponent.class, "RadialPosition");
addScaler(RingComponent.class, "Length", SCALERS_NO_OFFSET);
addScaler(RingComponent.class, "RadialPosition", SCALERS_OFFSET);
// ThicknessRingComponent
addScaler(ThicknessRingComponent.class, "OuterRadius", "isOuterRadiusAutomatic");
addScaler(ThicknessRingComponent.class, "Thickness");
addScaler(ThicknessRingComponent.class, "OuterRadius", "isOuterRadiusAutomatic", SCALERS_NO_OFFSET);
addScaler(ThicknessRingComponent.class, "Thickness", SCALERS_NO_OFFSET);
// InnerTube
addScaler(InnerTube.class, "MotorOverhang");
addScaler(InnerTube.class, "MotorOverhang", SCALERS_NO_OFFSET);
// RadiusRingComponent
addScaler(RadiusRingComponent.class, "OuterRadius", "isOuterRadiusAutomatic");
addScaler(RadiusRingComponent.class, "InnerRadius", "isInnerRadiusAutomatic");
addScaler(RadiusRingComponent.class, "OuterRadius", "isOuterRadiusAutomatic", SCALERS_NO_OFFSET);
addScaler(RadiusRingComponent.class, "InnerRadius", "isInnerRadiusAutomatic", SCALERS_NO_OFFSET);
}
private static void addScaler(Class<? extends RocketComponent> componentClass, String methodName) {
addScaler(componentClass, methodName, null);
private static void addScaler(Class<? extends RocketComponent> componentClass, String methodName,
Map<Class<? extends RocketComponent>, List<Scaler>> scaler) {
addScaler(componentClass, methodName, null, scaler);
}
private static void addScaler(Class<? extends RocketComponent> componentClass, String methodName, String autoMethodName) {
List<Scaler> list = SCALERS.get(componentClass);
private static void addScaler(Class<? extends RocketComponent> componentClass, String methodName, String autoMethodName,
Map<Class<? extends RocketComponent>, List<Scaler>> scaler) {
List<Scaler> list = scaler.get(componentClass);
if (list == null) {
list = new ArrayList<ScaleDialog.Scaler>();
SCALERS.put(componentClass, list);
scaler.put(componentClass, list);
}
list.add(new GeneralScaler(componentClass, methodName, autoMethodName));
}
@ -447,7 +455,7 @@ public class ScaleDialog extends JDialog {
try {
document.startUndo(trans.get("undo.scaleRocket"));
for (RocketComponent c : document.getRocket()) {
scale(c, mul, scaleMass);
scale(c, mul, scaleMass, true);
}
} finally {
document.stopUndo();
@ -458,8 +466,9 @@ public class ScaleDialog extends JDialog {
// Scale component and subcomponents
try {
document.startUndo(trans.get("undo.scaleComponents"));
for (RocketComponent c : selection) {
scale(c, mul, scaleMass);
scale(selection, mul, scaleMass, false);
for (RocketComponent c : selection.getChildren()) {
scale(c, mul, scaleMass, true);
}
} finally {
document.stopUndo();
@ -470,7 +479,7 @@ public class ScaleDialog extends JDialog {
// Scale only the selected component
try {
document.startUndo(trans.get("undo.scaleComponent"));
scale(selection, mul, scaleMass);
scale(selection, mul, scaleMass, false);
} finally {
document.stopUndo();
}
@ -479,16 +488,28 @@ public class ScaleDialog extends JDialog {
throw new BugException("Unknown item selected, item=" + item);
}
}
/**
* Perform scaling on a single component.
* @param component component to be scaled
* @param mul scaling factor
* @param scaleMass flag to check if the mass should be scaled as well
* @param scaleOffset flag to check if the axial/radial offsets should be scaled as well
*/
private void scale(RocketComponent component, double mul, boolean scaleMass) {
private void scale(RocketComponent component, double mul, boolean scaleMass, boolean scaleOffset) {
Class<?> clazz = component.getClass();
while (clazz != null) {
List<Scaler> list = SCALERS.get(clazz);
List<Scaler> list = null;
if (scaleOffset) {
Stream<Scaler> strm_no_offset = SCALERS_NO_OFFSET.get(clazz) == null ? Stream.empty() : SCALERS_NO_OFFSET.get(clazz).stream();
Stream<Scaler> strm_offset = SCALERS_OFFSET.get(clazz) == null ? Stream.empty() : SCALERS_OFFSET.get(clazz).stream();
list = Stream.concat(strm_no_offset, strm_offset).distinct().collect(Collectors.toList());
}
else {
list = SCALERS_NO_OFFSET.get(clazz);
}
if (list != null) {
for (Scaler s : list) {
s.scale(component, mul, scaleMass);

View File

@ -22,7 +22,7 @@ class MotorHolder {
@Override
public String toString() {
return motor.getDesignation();
return motor.getCommonName();
}
@Override

View File

@ -50,7 +50,8 @@ class MotorInformationPanel extends JPanel {
private List<ThrustCurveMotor> selectedMotorSet;
// Selected motor
private ThrustCurveMotor selectedMotor;
private final JLabel designationLabel;
private final JLabel totalImpulseLabel;
private final JLabel classificationLabel;
private final JLabel avgThrustLabel;
@ -76,8 +77,13 @@ class MotorInformationPanel extends JPanel {
super(new MigLayout("fill"));
// Thrust curve info
//// Total impulse:
{
//// Designation
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Designation")));
designationLabel = new JLabel();
this.add(designationLabel, "wrap");
//// Total impulse:
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Totalimpulse")));
totalImpulseLabel = new JLabel();
this.add(totalImpulseLabel, "split");
@ -223,6 +229,7 @@ class MotorInformationPanel extends JPanel {
public void clearData() {
selectedMotor = null;
selectedMotorSet = null;
designationLabel.setText("");
totalImpulseLabel.setText("");
totalImpulseLabel.setToolTipText(null);
classificationLabel.setText("");
@ -254,6 +261,7 @@ class MotorInformationPanel extends JPanel {
this.selectedMotor = selectedMotor;
// Update thrust curve data
designationLabel.setText(selectedMotor.getDesignation());
double impulse = selectedMotor.getTotalImpulseEstimate();
MotorClass mc = MotorClass.getMotorClass(impulse);
totalImpulseLabel.setText(UnitGroup.UNITS_IMPULSE.getDefaultUnit().toStringUnit(impulse));

View File

@ -30,11 +30,11 @@ enum ThrustCurveMotorColumns {
return Collator.getInstance();
}
},
//// Designation
DESIGNATION("TCurveMotorCol.DESIGNATION") {
//// Common name
COMMON_NAME("TCurveMotorCol.COMMON_NAME") {
@Override
public String getValue(ThrustCurveMotorSet m) {
return m.getDesignation();
return m.getCommonName();
}
@Override

View File

@ -48,8 +48,6 @@ import javax.swing.table.TableColumnModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import net.sf.openrocket.optimization.rocketoptimization.modifiers.GenericComponentModifier;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -1112,7 +1110,7 @@ public class GeneralOptimizationDialog extends JDialog {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(FileHelper.CSV_FILE_FILTER);
chooser.setFileFilter(FileHelper.CSV_FILTER);
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
chooser.setAccessory(csvOptions);
@ -1123,7 +1121,7 @@ public class GeneralOptimizationDialog extends JDialog {
if (file == null)
return;
file = FileHelper.ensureExtension(file, "csv");
file = FileHelper.forceExtension(file, "csv");
if (!FileHelper.confirmWrite(file, this)) {
return;
}

View File

@ -221,7 +221,7 @@ public class BasicFrame extends JFrame {
// Bottom segment, rocket figure
rocketpanel = new RocketPanel(document);
rocketpanel = new RocketPanel(document, this);
vertical.setBottomComponent(rocketpanel);
rocketpanel.setSelectionModel(tree.getSelectionModel());
@ -1099,6 +1099,9 @@ public class BasicFrame extends JFrame {
tabbedPane.setSelectedIndex(tab);
}
public int getSelectedTab() {
return tabbedPane.getSelectedIndex();
}
private void openAction() {

View File

@ -576,7 +576,7 @@ public class SimulationPanel extends JPanel {
public void documentChanged(DocumentChangeEvent event) {
if (!(event instanceof SimulationChangeEvent))
return;
simulationTableModel.fireTableDataChanged();
fireMaintainSelection();
}
});

View File

@ -54,10 +54,14 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
synchronizeConfigurationSelection();
}
public void fireTableDataChanged() {
/**
* Update the data in the table, with component change event type {cce}
* @param cce index of the ComponentChangeEvent to use (e.g. ComponentChangeEvent.NONFUNCTIONAL_CHANGE)
*/
public void fireTableDataChanged(int cce) {
int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn();
this.rocket.fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
this.rocket.fireComponentChangeEvent(cce);
((AbstractTableModel)table.getModel()).fireTableDataChanged();
restoreSelection(selectedRow,selectedColumn);
updateButtonState();

View File

@ -15,6 +15,7 @@ import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.gui.dialogs.flightconfiguration.RenameConfigDialog;
import net.sf.openrocket.gui.main.BasicFrame;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.FlightConfigurableComponent;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
@ -79,7 +80,7 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
int lastCol = motorConfigurationPanel.table.getColumnCount() - 1;
motorConfigurationPanel.table.setRowSelectionInterval(lastRow, lastRow);
motorConfigurationPanel.table.setColumnSelectionInterval(lastCol, lastCol);
configurationChanged();
configurationChanged(ComponentChangeEvent.MOTOR_CHANGE);
}
});
@ -91,7 +92,7 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
@Override
public void actionPerformed(ActionEvent e) {
renameConfiguration();
configurationChanged();
configurationChanged(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
}
});
this.add(renameConfButton,"gapright para");
@ -101,7 +102,7 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
@Override
public void actionPerformed(ActionEvent e) {
removeConfiguration();
configurationChanged();
configurationChanged(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
}
});
this.add(removeConfButton,"gapright para");
@ -111,7 +112,7 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
@Override
public void actionPerformed(ActionEvent e) {
addOrCopyConfiguration(true);
configurationChanged();
configurationChanged(ComponentChangeEvent.MOTOR_CHANGE);
}
});
this.add(copyConfButton, "wrap");
@ -172,13 +173,13 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
if (currentId == null)
return;
document.removeFlightConfigurationAndSimulations(currentId);
configurationChanged();
configurationChanged(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
}
private void configurationChanged() {
motorConfigurationPanel.fireTableDataChanged();
recoveryConfigurationPanel.fireTableDataChanged();
separationConfigurationPanel.fireTableDataChanged();
private void configurationChanged(int cce) {
motorConfigurationPanel.fireTableDataChanged(cce);
recoveryConfigurationPanel.fireTableDataChanged(cce);
separationConfigurationPanel.fireTableDataChanged(cce);
}
private void updateButtonState() {

View File

@ -37,6 +37,7 @@ import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.Chars;
@ -214,20 +215,25 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
throw new IllegalStateException("Attempting to set a motor on the default FCID.");
}
double initDelay = curMount.getMotorConfig(fcid).getEjectionDelay();
motorChooserDialog.setMotorMountAndConfig( fcid, curMount );
motorChooserDialog.setVisible(true);
Motor mtr = motorChooserDialog.getSelectedMotor();
double d = motorChooserDialog.getSelectedDelay();
if (mtr != null) {
if (mtr == curMount.getMotorConfig(fcid).getMotor() && d == initDelay) {
return;
}
final MotorConfiguration templateConfig = curMount.getMotorConfig(fcid);
final MotorConfiguration newConfig = new MotorConfiguration( curMount, fcid, templateConfig);
newConfig.setMotor(mtr);
newConfig.setEjectionDelay(d);
curMount.setMotorConfig( newConfig, fcid);
}
fireTableDataChanged();
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE);
}
}
private void removeMotor() {
@ -239,24 +245,30 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
curMount.setMotorConfig( null, fcid);
fireTableDataChanged();
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE);
}
private void selectIgnition() {
MotorMount curMount = getSelectedComponent();
FlightConfigurationId fcid= getSelectedConfigurationId();
if ( (null == fcid )||( null == curMount )){
return;
}
MotorMount curMount = getSelectedComponent();
FlightConfigurationId fcid = getSelectedConfigurationId();
if ((null == fcid) || (null == curMount)) {
return;
}
MotorConfiguration curInstance = curMount.getMotorConfig(fcid);
IgnitionEvent initialIgnitionEvent = curInstance.getIgnitionEvent();
double initialIgnitionDelay = curInstance.getIgnitionDelay();
// this call also performs the update changes
IgnitionSelectionDialog ignitionDialog = new IgnitionSelectionDialog(
SwingUtilities.getWindowAncestor(this.flightConfigurationPanel),
fcid,
curMount);
ignitionDialog.setVisible(true);
fireTableDataChanged();
if (!initialIgnitionEvent.equals(curInstance.getIgnitionEvent()) || (initialIgnitionDelay != curInstance.getIgnitionDelay())) {
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE);
}
}
@ -267,10 +279,14 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
return;
}
MotorConfiguration curInstance = curMount.getMotorConfig(fcid);
IgnitionEvent initialIgnitionEvent = curInstance.getIgnitionEvent();
double initialIgnitionDelay = curInstance.getIgnitionDelay();
curInstance.useDefaultIgnition();
fireTableDataChanged();
if (!initialIgnitionEvent.equals(curInstance.getIgnitionEvent()) || (initialIgnitionDelay != curInstance.getIgnitionDelay())) {
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE);
}
}
@ -304,7 +320,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
throw new NullPointerException("Motor has a null mount... this should never happen: "+curMotorInstance.getID());
}
String str = motor.getDesignation(curMotorInstance.getEjectionDelay());
String str = motor.getCommonName(curMotorInstance.getEjectionDelay());
int count = mount.getInstanceCount();
if (count > 1) {
str = "" + count + Chars.TIMES + " " + str;

View File

@ -99,22 +99,31 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
private void selectDeployment() {
RecoveryDevice c = getSelectedComponent();
if (c == null) {
FlightConfigurationId fcid = getSelectedConfigurationId();
if ((c == null) || (fcid == null)) {
return;
}
DeploymentConfiguration initialConfig = c.getDeploymentConfigurations().get(fcid).copy(fcid);
JDialog d = new DeploymentSelectionDialog(SwingUtilities.getWindowAncestor(this), rocket, c);
d.setVisible(true);
fireTableDataChanged();
if (!initialConfig.equals(c.getDeploymentConfigurations().get(fcid))) {
fireTableDataChanged(ComponentChangeEvent.AERODYNAMIC_CHANGE);
}
}
private void resetDeployment() {
RecoveryDevice c = getSelectedComponent();
if (c == null) {
FlightConfigurationId fcid = getSelectedConfigurationId();
if ((c == null) || (fcid == null)) {
return;
}
DeploymentConfiguration initialConfig = c.getDeploymentConfigurations().get(fcid).copy(fcid);
FlightConfigurationId id = rocket.getSelectedConfiguration().getFlightConfigurationID();
c.getDeploymentConfigurations().reset(id);
fireTableDataChanged();
if (!initialConfig.equals(c.getDeploymentConfigurations().get(fcid))) {
fireTableDataChanged(ComponentChangeEvent.AERODYNAMIC_CHANGE);
}
}
public void updateButtonState() {

View File

@ -47,7 +47,7 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
selectSeparationButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
selectDeployment();
selectSeparation();
}
});
this.add(selectSeparationButton, "split, align right, sizegroup button");
@ -58,7 +58,7 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
resetDeploymentButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
resetDeployment();
resetSeparation();
}
});
this.add(resetDeploymentButton, "sizegroup button, wrap");
@ -95,7 +95,7 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
updateButtonState();
if (e.getClickCount() == 2) {
// Double-click edits
selectDeployment();
selectSeparation();
}
}
});
@ -104,27 +104,35 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
return separationTable;
}
private void selectDeployment() {
private void selectSeparation() {
AxialStage stage = getSelectedComponent();
if (stage == null) {
FlightConfigurationId fcid = getSelectedConfigurationId();
if ((stage == null) || (fcid == null)) {
return;
}
StageSeparationConfiguration initialConfig = stage.getSeparationConfigurations().get(fcid).copy(fcid);
JDialog d = new SeparationSelectionDialog(SwingUtilities.getWindowAncestor(this), rocket, stage);
d.setVisible(true);
fireTableDataChanged();
if (!initialConfig.equals(stage.getSeparationConfigurations().get(fcid))) {
fireTableDataChanged(ComponentChangeEvent.AEROMASS_CHANGE);
}
}
private void resetDeployment() {
private void resetSeparation() {
AxialStage stage = getSelectedComponent();
if (stage == null) {
FlightConfigurationId fcid = getSelectedConfigurationId();
if ((stage == null) || (fcid == null)) {
return;
}
StageSeparationConfiguration initialConfig = stage.getSeparationConfigurations().get(fcid).copy(fcid);
// why?
FlightConfigurationId id = rocket.getSelectedConfiguration().getFlightConfigurationID();
stage.getSeparationConfigurations().reset(id);
fireTableDataChanged();
if (!initialConfig.equals(stage.getSeparationConfigurations().get(fcid))) {
fireTableDataChanged(ComponentChangeEvent.AEROMASS_CHANGE);
}
}
public void updateButtonState() {
boolean componentSelected = getSelectedComponent() != null;

View File

@ -8,22 +8,15 @@ import java.awt.Point;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
@ -38,6 +31,7 @@ import net.sf.openrocket.aerodynamics.FlightConditions;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.document.events.SimulationChangeEvent;
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.components.BasicSlider;
import net.sf.openrocket.gui.components.ConfigurationComboBox;
@ -49,6 +43,7 @@ import net.sf.openrocket.gui.figureelements.CGCaret;
import net.sf.openrocket.gui.figureelements.CPCaret;
import net.sf.openrocket.gui.figureelements.Caret;
import net.sf.openrocket.gui.figureelements.RocketInfo;
import net.sf.openrocket.gui.main.BasicFrame;
import net.sf.openrocket.gui.main.componenttree.ComponentTreeModel;
import net.sf.openrocket.gui.simulation.SimulationWorker;
import net.sf.openrocket.gui.util.SwingPreferences;
@ -63,10 +58,12 @@ import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.simulation.FlightData;
import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.customexpression.CustomExpression;
import net.sf.openrocket.simulation.customexpression.CustomExpressionSimulationListener;
import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.simulation.listeners.SimulationListener;
import net.sf.openrocket.simulation.listeners.system.ApogeeEndListener;
import net.sf.openrocket.simulation.listeners.system.GroundHitListener;
import net.sf.openrocket.simulation.listeners.system.InterruptListener;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
@ -75,11 +72,13 @@ import net.sf.openrocket.util.Chars;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.StateChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A JPanel that contains a RocketFigure and buttons to manipulate the figure.
*
* A JPanel that contains a RocketFigure and buttons to manipulate the figure.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
* @author Bill Kuker <bkuker@billkuker.com>
*/
@ -87,6 +86,7 @@ import net.sf.openrocket.util.StateChangeListener;
public class RocketPanel extends JPanel implements TreeSelectionListener, ChangeSource {
private static final Translator trans = Application.getTranslator();
private static final Logger log = LoggerFactory.getLogger(RocketPanel.class);
public enum VIEW_TYPE {
SideView(false, RocketFigure.VIEW_SIDE),
@ -128,7 +128,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
/* Calculation of CP and CG */
private AerodynamicCalculator aerodynamicCalculator;
private final OpenRocketDocument document;
private Caret extraCP = null;
@ -148,13 +148,16 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
private List<EventListener> listeners = new ArrayList<EventListener>();
// Store the basic frame to know which tab is selected (Rocket design, Motors & Configuration, Flight simulations)
private final BasicFrame basicFrame;
/**
* The executor service used for running the background simulations.
* This uses a fixed-sized thread pool for all background simulations
* with all threads in daemon mode and with minimum priority.
*/
private static final Executor backgroundSimulationExecutor;
private static final ExecutorService backgroundSimulationExecutor;
static {
backgroundSimulationExecutor = Executors.newFixedThreadPool(SwingPreferences.getMaxThreadCount(),
new ThreadFactory() {
@ -170,13 +173,17 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
});
}
public OpenRocketDocument getDocument(){
return this.document;
}
public RocketPanel(OpenRocketDocument document) {
this(document, null);
}
public RocketPanel(OpenRocketDocument document, BasicFrame basicFrame) {
this.document = document;
this.basicFrame = basicFrame;
Rocket rkt = document.getRocket();
@ -216,6 +223,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
rkt.addComponentChangeListener(new ComponentChangeListener() {
@Override
public void componentChanged(ComponentChangeEvent e) {
updateExtras();
if (is3d) {
if (e.isTextureChange()) {
figure3d.flushTextureCaches();
@ -367,7 +375,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
/**
* Get the center of pressure figure element.
*
*
* @return center of pressure info
*/
public Caret getExtraCP() {
@ -376,7 +384,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
/**
* Get the center of gravity figure element.
*
*
* @return center of gravity info
*/
public Caret getExtraCG() {
@ -385,7 +393,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
/**
* Get the extra text figure element.
*
*
* @return extra text that contains info about the rocket design
*/
public RocketInfo getExtraText() {
@ -490,12 +498,12 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
/**
* Handle clicking on figure shapes. The functioning is the following:
*
*
* Get the components clicked.
* If no component is clicked, do nothing.
* If the currently selected component is in the set, keep it,
* unless the selector specified is pressed. If it is pressed, cycle to
* the next component. Otherwise select the first component in the list.
* If the currently selected component is in the set, keep it,
* unless the selector specified is pressed. If it is pressed, cycle to
* the next component. Otherwise select the first component in the list.
*/
public static final int CYCLE_SELECTION_MODIFIER = InputEvent.SHIFT_DOWN_MASK;
@ -557,7 +565,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
/**
* Updates the extra data included in the figure. Currently this includes
* the CP and CG carets.
* the CP and CG carets. Also start the background simulator.
*/
private WarningSet warnings = new WarningSet();
@ -645,7 +653,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
figure3d.setCG(new Coordinate(Double.NaN, Double.NaN));
figure3d.setCP(new Coordinate(Double.NaN, Double.NaN));
}
if (figure.getType() == RocketPanel.VIEW_TYPE.SideView && length > 0) {
extraCP.setPosition(cpx, cpy);
extraCG.setPosition(cgx, cgy);
@ -683,35 +691,120 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
return;
}
// Start calculation process
if(((SwingPreferences) Application.getPreferences()).computeFlightInBackground()){
extraText.setCalculatingData(true);
// Update simulations
if (Application.getPreferences().getAutoRunSimulations()) {
// Update only current flight config simulation when you are not in the simulations tab
updateSims(this.basicFrame != null && this.basicFrame.getSelectedTab() == BasicFrame.SIMULATION_TAB);
}
else {
// Always update the simulation of the current configuration
updateSims(false);
}
Rocket duplicate = (Rocket) document.getRocket().copy();
// Update flight data and add flight data update trigger upon simulation changes
for (Simulation sim : document.getSimulations()) {
sim.addChangeListener(new StateChangeListener() {
@Override
public void stateChanged(EventObject e) {
if (updateFlightData(sim)) {
updateFigures();
}
}
});
if (updateFlightData(sim)) {
break;
}
}
}
// find a Simulation based on the current flight configuration
FlightConfigurationId curID = curConfig.getFlightConfigurationID();
Simulation simulation = null;
for (Simulation sim : document.getSimulations()) {
/**
* Updates the simulations. If *currentConfig* is false, only update the simulation of the current flight
* configuration. If it is true, update all the simulations.
*
* @param updateAllSims flag to check whether to update all the simulations (true) or only the current
* flight config sim (false)
*/
private void updateSims(boolean updateAllSims) {
// Stop previous computation (if any)
stopBackgroundSimulation();
FlightConfigurationId curID = document.getSelectedConfiguration().getFlightConfigurationID();
extraText.setCalculatingData(true);
Rocket duplicate = (Rocket)document.getRocket().copy();
// Re-run the present simulation(s)
List<Simulation> sims = new LinkedList<>();
for (Simulation sim : document.getSimulations()) {
if (sim.getStatus() == Simulation.Status.UPTODATE || sim.getStatus() == Simulation.Status.LOADED
|| !document.getRocket().getFlightConfiguration(sim.getFlightConfigurationId()).hasMotors())
continue;
// Find a Simulation based on the current flight configuration
if (!updateAllSims) {
if (sim.getFlightConfigurationId().compareTo(curID) == 0) {
simulation = sim;
sims.add(sim);
break;
}
}
// I *think* every FlightConfiguration has at least one associated simulation; just in case I'm wrong,
// if there isn't one we'll create a new simulation to update the statistics in the panel using the
// default simulation conditions
if (simulation == null) {
System.out.println("creating new simulation");
simulation = ((SwingPreferences) Application.getPreferences()).getBackgroundSimulation(duplicate);
simulation.setFlightConfigurationId( document.getSelectedConfiguration().getId());
} else
System.out.println("using pre-existing simulation");
backgroundSimulationWorker = new BackgroundSimulationWorker(document, simulation);
backgroundSimulationExecutor.execute(backgroundSimulationWorker);
else {
sims.add(sim);
}
}
runBackgroundSimulations(sims, duplicate);
}
/**
* Update the flight data text with the data of {sim}. Only update if sim is the simulation of the current flight
* configuration.
* @param sim: simulation from which the flight data is taken
* @return true if the flight data was updated, false if not
*/
private boolean updateFlightData(Simulation sim) {
FlightConfigurationId curID = document.getSelectedConfiguration().getFlightConfigurationID();
if (sim.getFlightConfigurationId().compareTo(curID) == 0) {
if (sim.hasSimulationData()) {
extraText.setFlightData(sim.getSimulatedData());
} else {
extraText.setFlightData(FlightData.NaN_DATA);
}
return true;
}
return false;
}
/**
* Runs a new background simulation for simulations *sims*. It will run all the simulations in sims sequentially
* in the background.
*
* @param sims simulations which should be run
* @param rkt rocket for which the simulations are run
*/
private void runBackgroundSimulations(List<Simulation> sims, Rocket rkt) {
if (sims.size() == 0) {
extraText.setCalculatingData(false);
for (Simulation sim : document.getSimulations()) {
if (updateFlightData(sim)) {
return;
}
}
extraText.setFlightData(FlightData.NaN_DATA);
return;
}
// I *think* every FlightConfiguration has at least one associated simulation; just in case I'm wrong,
// if there isn't one we'll create a new simulation to update the statistics in the panel using the
// default simulation conditions
for (Simulation sim : sims) {
if (sim == null) {
log.info("creating new simulation");
sim = ((SwingPreferences) Application.getPreferences()).getBackgroundSimulation(rkt);
sim.setFlightConfigurationId(document.getSelectedConfiguration().getId());
} else
log.info("using pre-existing simulation");
}
backgroundSimulationWorker = new BackgroundSimulationWorker(document, sims);
backgroundSimulationExecutor.execute(backgroundSimulationWorker);
}
/**
@ -732,16 +825,20 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
private class BackgroundSimulationWorker extends SimulationWorker {
private final CustomExpressionSimulationListener exprListener;
private final OpenRocketDocument doc;
private List<Simulation> sims;
public BackgroundSimulationWorker(OpenRocketDocument doc, Simulation sim) {
super(sim);
public BackgroundSimulationWorker(OpenRocketDocument doc, List<Simulation> sims) {
super(sims.get(0));
this.sims = sims;
this.doc = doc;
List<CustomExpression> exprs = doc.getCustomExpressions();
exprListener = new CustomExpressionSimulationListener(exprs);
}
@Override
protected FlightData doInBackground() {
extraText.setCalculatingData(true);
// Pause a little while to allow faster UI reaction
try {
Thread.sleep(300);
@ -749,7 +846,6 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
}
if (isCancelled() || backgroundSimulationWorker != this)
return null;
return super.doInBackground();
}
@ -758,19 +854,27 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
// Do nothing if cancelled
if (isCancelled() || backgroundSimulationWorker != this)
return;
backgroundSimulationWorker = null;
extraText.setFlightData(simulation.getSimulatedData());
// Only set the flight data information of the current flight configuration
extraText.setCalculatingData(false);
figure.repaint();
figure3d.repaint();
document.fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
// Run the new simulation after this one has ended
this.sims.remove(0);
if (this.sims.size() > 0) {
backgroundSimulationWorker = new BackgroundSimulationWorker(this.doc, this.sims);
backgroundSimulationExecutor.execute(backgroundSimulationWorker);
}
}
@Override
protected SimulationListener[] getExtraListeners() {
return new SimulationListener[] {
InterruptListener.INSTANCE,
ApogeeEndListener.INSTANCE,
GroundHitListener.INSTANCE,
exprListener };
}
@ -813,7 +917,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
}
/**
* Updates the selection in the FigureParameters and repaints the figure.
* Updates the selection in the FigureParameters and repaints the figure.
* Ignores the event itself.
*/
@Override
@ -868,5 +972,5 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
// putValue(Action.SELECTED_KEY, figure.getType() == type && !is3d);
// }
// }
}

View File

@ -220,7 +220,7 @@ public class SimulationExportPanel extends JPanel {
public boolean doExport() {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(FileHelper.CSV_FILE_FILTER);
chooser.setFileFilter(FileHelper.CSV_FILTER);
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION)
@ -230,7 +230,7 @@ public class SimulationExportPanel extends JPanel {
if (file == null)
return false;
file = FileHelper.ensureExtension(file, "csv");
file = FileHelper.forceExtension(file, "csv");
if (!FileHelper.confirmWrite(file, this)) {
return false;
}

View File

@ -29,33 +29,32 @@ public final class FileHelper {
private static final Logger log = LoggerFactory.getLogger(FileHelper.class);
private static final Translator trans = Application.getTranslator();
// TODO: HIGH: Rename translation keys
/** File filter for any rocket designs (*.ork, *.rkt) */
public static final FileFilter ALL_DESIGNS_FILTER =
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter1"),
new SimpleFileFilter(trans.get("FileHelper.ALL_DESIGNS_FILTER"),
".ork", ".ork.gz", ".rkt", ".rkt.gz");
/** File filter for OpenRocket designs (*.ork) */
public static final FileFilter OPENROCKET_DESIGN_FILTER =
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter2"), ".ork", ".ork.gz");
new SimpleFileFilter(trans.get("FileHelper.OPENROCKET_DESIGN_FILTER"), ".ork", ".ork.gz");
/** File filter for RockSim designs (*.rkt) */
public static final FileFilter ROCKSIM_DESIGN_FILTER =
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter3"), ".rkt", ".rkt.gz");
new SimpleFileFilter(trans.get("FileHelper.ROCKSIM_DESIGN_FILTER"), ".rkt", ".rkt.gz");
/** File filter for OpenRocket components and presets (*.orc) */
public static final FileFilter OPEN_ROCKET_COMPONENT_FILTER =
new SimpleFileFilter(trans.get("BasicFrame.SimpleFileFilter4"), ".orc", ".orc.gz");
new SimpleFileFilter(trans.get("FileHelper.OPEN_ROCKET_COMPONENT_FILTER"), ".orc", ".orc.gz");
/** File filter for PDF files (*.pdf) */
public static final FileFilter PDF_FILTER =
new SimpleFileFilter(trans.get("filetypes.pdf"), ".pdf");
new SimpleFileFilter(trans.get("FileHelper.PDF_FILTER"), ".pdf");
/** File filter for CSV files (*.csv) */
public static final FileFilter CSV_FILE_FILTER =
new SimpleFileFilter(trans.get("SimExpPan.desc"), ".csv");
public static final FileFilter CSV_FILTER =
new SimpleFileFilter(trans.get("FileHelper.CSV_FILTER"), ".csv");
@ -73,7 +72,7 @@ public final class FileHelper {
Arrays.sort(extensions);
StringBuilder sb = new StringBuilder();
sb.append(trans.get("filetypes.images"));
sb.append(trans.get("FileHelper.IMAGES"));
sb.append(" (");
for (int i = 0; i < extensions.length; i++) {
sb.append("*.").append(extensions[i]);
@ -120,7 +119,12 @@ public final class FileHelper {
if ( original == null ) {
return null;
}
if (!original.getName().toLowerCase(Locale.ENGLISH).endsWith(extension.toLowerCase(Locale.ENGLISH))) {
int index = original.getName().lastIndexOf('.');
String original_extension = "";
if (index > 0) {
original_extension = original.getName().substring(index + 1);
}
if (!original_extension.toLowerCase(Locale.ENGLISH).equals(extension.toLowerCase(Locale.ENGLISH))) {
log.debug("File name does not contain extension, adding '" + extension + "'");
String name = original.getAbsolutePath();
if (extension.startsWith(".")) {

View File

@ -325,7 +325,7 @@ public class ComponentPresetEditor extends JPanel implements PresetResultListene
private boolean openComponentFile() {
final JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
chooser.addChoosableFileFilter(FileHelper.CSV_FILE_FILTER);
chooser.addChoosableFileFilter(FileHelper.CSV_FILTER);
chooser.setFileFilter(FileHelper.OPEN_ROCKET_COMPONENT_FILTER);
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
if (editContext.getLastDirectory() != null) {