Merge branch 'openrocket:unstable' into fix-acceleration-status

This commit is contained in:
Joe Pfeiffer 2023-10-12 12:35:32 -06:00 committed by GitHub
commit 27e668cbce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 498 additions and 35 deletions

View File

@ -5,6 +5,7 @@ OpenRocket
![GitHub release](https://img.shields.io/github/release/openrocket/openrocket.svg)
[![Github Releases (by release)](https://img.shields.io/github/downloads/openrocket/openrocket/latest/total.svg)](https://GitHub.com/openrocket/openrocket/releases/)
[![Join our Discord server!](https://img.shields.io/discord/1073297014814691328?logo=discord)](https://discord.gg/qD2G5v2FAw)
--------

View File

@ -410,6 +410,7 @@ PreferencesOptionPanel.checkbox.windowInfo.ttip = If unchecked, window informati
UITheme.Auto = Auto (detect)
UITheme.Light = Light (default)
UITheme.Dark = Dark
UITheme.DarkContrast = Dark, high-contrast
! Welcome dialog
welcome.dlg.title = Welcome to OpenRocket

View File

@ -401,6 +401,8 @@ public class OpenRocketSaver extends RocketSaver {
str += " launchrodvelocity=\"" + TextUtil.doubleToString(data.getLaunchRodVelocity()) + "\"";
if (!Double.isNaN(data.getDeploymentVelocity()))
str += " deploymentvelocity=\"" + TextUtil.doubleToString(data.getDeploymentVelocity()) + "\"";
if (!Double.isNaN(data.getOptimumDelay()))
str += " optimumdelay=\"" + TextUtil.doubleToString(data.getOptimumDelay()) + "\"";
str += ">";
writeln(str);
indent++;

View File

@ -104,6 +104,7 @@ class FlightDataHandler extends AbstractElementHandler {
double groundHitVelocity = Double.NaN;
double launchRodVelocity = Double.NaN;
double deploymentVelocity = Double.NaN;
double optimumDelay = Double.NaN;
try {
maxAltitude = DocumentConfig.stringToDouble(attributes.get("maxaltitude"));
@ -142,9 +143,13 @@ class FlightDataHandler extends AbstractElementHandler {
deploymentVelocity = DocumentConfig.stringToDouble(attributes.get("deploymentvelocity"));
} catch (NumberFormatException ignore) {
}
try {
optimumDelay = DocumentConfig.stringToDouble(attributes.get("optimumdelay"));
} catch (NumberFormatException ignore) {
}
data = new FlightData(maxAltitude, maxVelocity, maxAcceleration, maxMach,
timeToApogee, flightTime, groundHitVelocity, launchRodVelocity, deploymentVelocity);
timeToApogee, flightTime, groundHitVelocity, launchRodVelocity, deploymentVelocity, optimumDelay);
}
data.getWarningSet().addAll(warningSet);

View File

@ -51,7 +51,7 @@ public class FlightData {
private double groundHitVelocity = Double.NaN;
private double launchRodVelocity = Double.NaN;
private double deploymentVelocity = Double.NaN;
private double optimumDelay = Double.NaN;
/**
* Create a FlightData object with no content. The resulting object is mutable.
@ -74,10 +74,11 @@ public class FlightData {
* @param groundHitVelocity ground hit velocity.
* @param launchRodVelocity velocity at launch rod clearance
* @param deploymentVelocity velocity at deployment
* @param optimumDelay optimum motor ejection delay time
*/
public FlightData(double maxAltitude, double maxVelocity, double maxAcceleration,
double maxMachNumber, double timeToApogee, double flightTime,
double groundHitVelocity, double launchRodVelocity, double deploymentVelocity) {
double groundHitVelocity, double launchRodVelocity, double deploymentVelocity, double optimumDelay) {
this.maxAltitude = maxAltitude;
this.maxVelocity = maxVelocity;
this.maxAcceleration = maxAcceleration;
@ -87,6 +88,8 @@ public class FlightData {
this.groundHitVelocity = groundHitVelocity;
this.launchRodVelocity = launchRodVelocity;
this.deploymentVelocity = deploymentVelocity;
this.optimumDelay = optimumDelay;
System.out.println("optimum delay " + optimumDelay);
}
@ -188,6 +191,10 @@ public class FlightData {
return deploymentVelocity;
}
public double getOptimumDelay() {
return optimumDelay;
}
/**
* Calculate the max. altitude/velocity/acceleration, time to apogee, flight time
@ -201,7 +208,6 @@ public class FlightData {
maxAltitude = branch.getMaximum(FlightDataType.TYPE_ALTITUDE);
maxVelocity = branch.getMaximum(FlightDataType.TYPE_VELOCITY_TOTAL);
maxMachNumber = branch.getMaximum(FlightDataType.TYPE_MACH_NUMBER);
flightTime = branch.getLast(FlightDataType.TYPE_TIME);
// Time to apogee
@ -227,6 +233,7 @@ public class FlightData {
else
timeToApogee = Double.NaN;
optimumDelay = branch.getOptimumDelay();
// Launch rod velocity + deployment velocity + ground hit velocity
for (FlightEvent event : branch.getEvents()) {
@ -260,7 +267,8 @@ public class FlightData {
" timeToApogee=" + timeToApogee +
" flightTime=" + flightTime +
" groundHitVelocity=" + groundHitVelocity +
" launchRodVelocity=" + launchRodVelocity);
" launchRodVelocity=" + launchRodVelocity +
" optimumDelay=" + optimumDelay);
}

View File

@ -52,11 +52,12 @@ public class TestFlightData {
double maxAltitude = 355.1;
double maxMachNumber = 0.31;
double timeToApogee = 7.96;
double optimumDelay = 5.2;
FlightData data = new FlightData(maxAltitude, maxVelocity, maxAcceleration,
maxMachNumber, timeToApogee, flightTime,
groundHitVelocity, launchRodVelocity,
deploymentVelocity);
deploymentVelocity, optimumDelay);
WarningSet warnings = data.getWarningSet();
assertNotNull(warnings);
@ -71,6 +72,7 @@ public class TestFlightData {
assertEquals(maxAltitude, data.getMaxAltitude(), 0.00);
assertEquals(maxMachNumber, data.getMaxMachNumber(), 0.00);
assertEquals(timeToApogee, data.getTimeToApogee(), 0.00);
assertEquals(optimumDelay, data.getOptimumDelay(), 0.00);
}
/**

View File

@ -1,5 +1,8 @@
package net.sf.openrocket.gui.components;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.UITheme;
import javax.swing.BoundedRangeModel;
import javax.swing.JSlider;
import javax.swing.plaf.basic.BasicSliderUI;
@ -27,7 +30,11 @@ public class BasicSlider extends JSlider {
setOrientation(orientation);
setInverted(inverted);
setFocusable(false);
setUI(new BasicSliderUI(this));
if (UITheme.isLightTheme(GUIUtil.getUITheme())) {
setUI(new BasicSliderUI(this));
} else {
setUI(new DarkBasicSliderUI(this));
}
}
}

View File

@ -0,0 +1,51 @@
package net.sf.openrocket.gui.components;
import javax.swing.JSlider;
import javax.swing.plaf.basic.BasicSliderUI;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
/**
* BasicSliderUI for dark theme UI.
*/
public class DarkBasicSliderUI extends BasicSliderUI {
private static final Color trackColor = new Color(159, 159, 159);
private static final Color thumbColor = new Color(82, 82, 82);
private static final Color thumbBorderColor = new Color(166, 166, 166);
public DarkBasicSliderUI(JSlider b) {
super(b);
}
@Override
public void paintTrack(Graphics g) {
g.setColor(trackColor);
super.paintTrack(g);
}
@Override
public void paintThumb(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Rectangle thumbBounds = thumbRect;
int w = thumbBounds.width;
int h = thumbBounds.height;
int borderInset = 2; // Adjust this value to change the border thickness
// Draw the border
g2d.setColor(thumbBorderColor);
g2d.fillRect(thumbBounds.x, thumbBounds.y, w, h);
// Draw the thumb fill
g2d.setColor(thumbColor);
g2d.fillRect(
thumbBounds.x + borderInset - 1,
thumbBounds.y + borderInset - 1,
w - 2 * borderInset + 1,
h - 2 * borderInset + 1
);
}
}

View File

@ -9,6 +9,7 @@ import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.Border;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.components.DescriptionArea;
@ -17,6 +18,7 @@ import net.sf.openrocket.gui.components.StyledLabel.Style;
import net.sf.openrocket.gui.components.URLLabel;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.gui.util.UITheme;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BuildProperties;
@ -85,6 +87,12 @@ public class AboutDialog extends JDialog {
"Enhanced components database for OpenRocket" + href("https://github.com/dbcook/openrocket-database", true, true) +
"</center></html>";
private static Border border;
static {
initColors();
}
private String href(String url, boolean delimiters, boolean leadingSpace) {
return (leadingSpace ? " " : "") + (delimiters ? "(" : "") + "<a href=\"" + url + "\">" + url + "</a>" + (delimiters ? ")" : "");
}
@ -142,6 +150,7 @@ public class AboutDialog extends JDialog {
DescriptionArea info = new DescriptionArea(5);
info.setBorder(border);
info.setText(CREDITS);
info.setTextFont(UIManager.getFont("Label.font"));
panel.add(info, "newline, width 10px, height 250lp, pushy, grow, spanx, wrap para");
@ -170,4 +179,13 @@ public class AboutDialog extends JDialog {
GUIUtil.setDisposableDialogOptions(this, close);
}
private static void initColors() {
updateColors();
UITheme.Theme.addUIThemeChangeListener(AboutDialog::updateColors);
}
private static void updateColors() {
border = GUIUtil.getUITheme().getBorder();
}
}

View File

@ -47,6 +47,7 @@ class MotorInformationPanel extends JPanel {
private static Color NO_COMMENT_COLOR;
private static Color WITH_COMMENT_COLOR;
private static Color textColor;
private static Color dimTextColor;
private static Border border;
// Motors in set
@ -103,7 +104,7 @@ class MotorInformationPanel extends JPanel {
this.add(totalImpulseLabel, "split");
classificationLabel = new JLabel();
classificationLabel.setEnabled(false); // Gray out
classificationLabel.setForeground(dimTextColor);
this.add(classificationLabel, "gapleft unrel, wrap");
//// Avg. thrust:
@ -194,8 +195,8 @@ class MotorInformationPanel extends JPanel {
// Add the data and formatting to the plot
XYPlot plot = chart.getXYPlot();
changeLabelFont(plot.getRangeAxis(), -2);
changeLabelFont(plot.getDomainAxis(), -2);
changeLabelFont(plot.getRangeAxis(), -2, textColor);
changeLabelFont(plot.getDomainAxis(), -2, textColor);
//// Thrust curve:
TextTitle title = new TextTitle(trans.get("TCMotorSelPan.title.Thrustcurve"), this.getFont());
@ -257,6 +258,7 @@ class MotorInformationPanel extends JPanel {
NO_COMMENT_COLOR = GUIUtil.getUITheme().getDimTextColor();
WITH_COMMENT_COLOR = GUIUtil.getUITheme().getTextColor();
textColor = GUIUtil.getUITheme().getTextColor();
dimTextColor = GUIUtil.getUITheme().getDimTextColor();
border = GUIUtil.getUITheme().getBorder();
}
@ -372,10 +374,11 @@ class MotorInformationPanel extends JPanel {
comment.setCaretPosition(0);
}
void changeLabelFont(ValueAxis axis, float size) {
void changeLabelFont(ValueAxis axis, float size, Color color) {
Font font = axis.getTickLabelFont();
font = font.deriveFont(font.getSize2D() + size);
axis.setTickLabelFont(font);
axis.setTickLabelPaint(color);
}
/**

View File

@ -609,7 +609,12 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
public static Color getColor(int index) {
return (Color) CURVE_COLORS[index % CURVE_COLORS.length];
Color color = (Color) CURVE_COLORS[index % CURVE_COLORS.length];
if (UITheme.isLightTheme(GUIUtil.getUITheme())) {
return color;
} else {
return color.brighter().brighter();
}
}

View File

@ -1306,14 +1306,10 @@ public class SimulationPanel extends JPanel {
return null;
FlightData data = document.getSimulation(row).getSimulatedData();
if (data == null || data.getBranchCount() == 0)
if (data == null)
return null;
double val = data.getBranch(0).getOptimumDelay();
if (Double.isNaN(val)) {
return null;
}
return val;
return data.getOptimumDelay();
}
},
@ -1404,21 +1400,26 @@ public class SimulationPanel extends JPanel {
* Focus on the simulation table and maintain the previous row selection(s).
*/
public void takeTheSpotlight() {
simulationTable.requestFocusInWindow();
if (simulationTable.getRowCount() == 0 || simulationTable.getSelectedRows().length > 0) {
return;
}
if (previousSelection == null || previousSelection.length == 0) {
simulationTable.getSelectionModel().setSelectionInterval(0, 0);
} else {
simulationTable.clearSelection();
for (int row : previousSelection) {
if (row < 0 || row >= simulationTable.getRowCount()) {
continue;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
simulationTable.requestFocusInWindow();
if (simulationTable.getRowCount() == 0 || simulationTable.getSelectedRows().length > 0) {
return;
}
simulationTable.addRowSelectionInterval(row, row);
if (previousSelection == null || previousSelection.length == 0) {
simulationTable.getSelectionModel().setSelectionInterval(0, 0);
} else {
simulationTable.clearSelection();
for (int row : previousSelection) {
if (row < 0 || row >= simulationTable.getRowCount()) {
continue;
}
simulationTable.addRowSelectionInterval(row, row);
}
}
updateActions();
}
}
updateActions();
});
}
}

View File

@ -66,6 +66,7 @@ class SimulationOptionsPanel extends JPanel {
JMenu extensionMenuCopyExtension;
private static Color textColor;
private static Color dimTextColor;
private static Border border;
static {
@ -232,6 +233,7 @@ class SimulationOptionsPanel extends JPanel {
private static void updateColors() {
textColor = GUIUtil.getUITheme().getTextColor();
dimTextColor = GUIUtil.getUITheme().getDimTextColor();
border = GUIUtil.getUITheme().getBorder();
}
@ -349,7 +351,7 @@ class SimulationOptionsPanel extends JPanel {
if (simulation.getSimulationExtensions().isEmpty()) {
StyledLabel l = new StyledLabel(trans.get("simedtdlg.SimExt.noExtensions"), Style.ITALIC);
l.setForeground(Color.DARK_GRAY);
l.setForeground(dimTextColor);
currentExtensions.add(l, "growx, pad 5 5 5 5, wrap");
} else {
for (SimulationExtension e : simulation.getSimulationExtensions()) {

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.gui.util;
import com.github.weisj.darklaf.LafManager;
import com.github.weisj.darklaf.theme.DarculaTheme;
import com.github.weisj.darklaf.theme.OneDarkTheme;
import com.jthemedetecor.OsThemeDetector;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
@ -157,6 +158,9 @@ public class UITheme {
}
public enum Themes implements Theme {
/*
Standard light theme
*/
LIGHT {
private final String displayName = trans.get("UITheme.Light");
@ -502,8 +506,12 @@ public class UITheme {
return "tracker";
}
},
/*
Dark theme
*/
DARK {
private final String displayName = trans.get("UITheme.Dark");
@Override
public void applyTheme() {
final SwingPreferences prefs = (SwingPreferences) Application.getPreferences();
@ -537,7 +545,7 @@ public class UITheme {
@Override
public Color getDimTextColor() {
return new Color(162, 162, 162);
return new Color(182, 182, 182);
}
@Override
@ -845,6 +853,355 @@ public class UITheme {
return "tracker_dark";
}
},
/*
High-contrast dark theme
*/
DARK_CONTRAST {
private final String displayName = trans.get("UITheme.DarkContrast");
@Override
public void applyTheme() {
final SwingPreferences prefs = (SwingPreferences) Application.getPreferences();
LafManager.install(new OneDarkTheme());
setGlobalFontSize(prefs.getUIFontSize());
}
@Override
public String getDisplayName() {
return displayName;
}
@Override
public Color getBackgroundColor() {
return new Color(43, 45, 51);
}
@Override
public Color getBorderColor() {
return new Color(163, 163, 163, 204);
}
@Override
public Color getTextColor() {
return UIManager.getColor("Label.foreground");
}
@Override
public Color getDimTextColor() {
return new Color(165, 171, 184);
}
@Override
public Color getTextSelectionForegroundColor() {
return Color.WHITE;
}
@Override
public Color getTextSelectionBackgroundColor() {
return new Color(62, 108, 173);
}
@Override
public Color getWarningColor() {
return new Color(255, 173, 173);
}
@Override
public Color getDarkWarningColor() {
return new Color(255, 178, 178);
}
@Override
public Color getRowBackgroundLighterColor() {
return new Color(43, 49, 58);
}
@Override
public Color getRowBackgroundDarkerColor() {
return new Color(34, 37, 44);
}
@Override
public Color getFlightDataTextActiveColor() {
return new Color(212, 230, 255);
}
@Override
public Color getFlightDataTextInactiveColor() {
return new Color(170, 201, 255, 127);
}
@Override
public Color getMultiCompEditColor() {
return new Color(255, 165, 200);
}
@Override
public String getDefaultBodyComponentColor() {
return "150,175,255";
}
@Override
public String getDefaultTubeFinSetColor() {
return "150,184,254";
}
@Override
public String getDefaultFinSetColor() {
return "150,184,255";
}
@Override
public String getDefaultLaunchLugColor() {
return "142,153,238";
}
@Override
public String getDefaultRailButtonColor() {
return "142,153,238";
}
@Override
public String getDefaultInternalComponentColor() {
return "181,128,151";
}
@Override
public String getDefaultMassObjectColor() {
return "210,210,210";
}
@Override
public String getDefaultRecoveryDeviceColor() {
return "220,90,90";
}
@Override
public String getDefaultPodSetColor() {
return "190,190,235";
}
@Override
public String getDefaultParallelStageColor() {
return "210,180,195";
}
@Override
public Color getMotorBorderColor() {
return new Color(255, 255, 255, 200);
}
@Override
public Color getMotorFillColor() {
return new Color(0, 0, 0, 70);
}
@Override
public Color getCGColor() {
return new Color(85, 133, 253);
}
@Override
public Color getCPColor() {
return new Color(255, 72, 106);
}
@Override
public Color getURLColor() {
return new Color(171, 185, 255);
}
@Override
public Color getComponentTreeBackgroundColor() {
return getBackgroundColor();
}
@Override
public Color getComponentTreeForegroundColor() {
return getTextColor();
}
@Override
public Color getFinPointGridMajorLineColor() {
return new Color(164, 164, 224, 197);
}
@Override
public Color getFinPointGridMinorLineColor() {
return new Color(134, 134, 201, 69);
}
@Override
public Color getFinPointPointColor() {
return new Color(242, 121, 121, 255);
}
@Override
public Color getFinPointSelectedPointColor() {
return new Color(232, 78, 78, 255);
}
@Override
public Color getFinPointBodyLineColor() {
return Color.WHITE;
}
@Override
public Icon getMassOverrideIcon() {
return Icons.MASS_OVERRIDE_DARK;
}
@Override
public Icon getMassOverrideSubcomponentIcon() {
return Icons.MASS_OVERRIDE_SUBCOMPONENT_DARK;
}
@Override
public Icon getCGOverrideIcon() {
return Icons.CG_OVERRIDE_DARK;
}
@Override
public Icon getCGOverrideSubcomponentIcon() {
return Icons.CG_OVERRIDE_SUBCOMPONENT_DARK;
}
@Override
public Icon getCDOverrideIcon() {
return Icons.CD_OVERRIDE_DARK;
}
@Override
public Icon getCDOverrideSubcomponentIcon() {
return Icons.CD_OVERRIDE_SUBCOMPONENT_DARK;
}
@Override
public Border getBorder() {
return BorderFactory.createLineBorder(getBorderColor());
}
@Override
public void formatScriptTextArea(RSyntaxTextArea textArea) {
try {
org.fife.ui.rsyntaxtextarea.Theme theme = org.fife.ui.rsyntaxtextarea.Theme.load(getClass().getResourceAsStream(
"/org/fife/ui/rsyntaxtextarea/themes/monokai.xml"));
theme.apply(textArea);
} catch (IOException ioe) {
log.warn("Unable to load RSyntaxTextArea theme", ioe);
}
}
@Override
public String getComponentIconNoseCone() {
return DARK.getComponentIconNoseCone();
}
@Override
public String getComponentIconBodyTube() {
return DARK.getComponentIconBodyTube();
}
@Override
public String getComponentIconTransition() {
return DARK.getComponentIconTransition();
}
@Override
public String getComponentIconTrapezoidFinSet() {
return DARK.getComponentIconTrapezoidFinSet();
}
@Override
public String getComponentIconEllipticalFinSet() {
return DARK.getComponentIconEllipticalFinSet();
}
@Override
public String getComponentIconFreeformFinSet() {
return DARK.getComponentIconFreeformFinSet();
}
@Override
public String getComponentIconTubeFinSet() {
return DARK.getComponentIconTubeFinSet();
}
@Override
public String getComponentIconLaunchLug() {
return DARK.getComponentIconLaunchLug();
}
@Override
public String getComponentIconRailButton() {
return DARK.getComponentIconRailButton();
}
@Override
public String getComponentIconInnerTube() {
return DARK.getComponentIconInnerTube();
}
@Override
public String getComponentIconTubeCoupler() {
return DARK.getComponentIconTubeCoupler();
}
@Override
public String getComponentIconCenteringRing() {
return DARK.getComponentIconCenteringRing();
}
@Override
public String getComponentIconBulkhead() {
return DARK.getComponentIconBulkhead();
}
@Override
public String getComponentIconEngineBlock() {
return DARK.getComponentIconEngineBlock();
}
@Override
public String getComponentIconParachute() {
return DARK.getComponentIconParachute();
}
@Override
public String getComponentIconStreamer() {
return DARK.getComponentIconStreamer();
}
@Override
public String getComponentIconShockCord() {
return DARK.getComponentIconShockCord();
}
@Override
public String getComponentIconMass() {
return DARK.getComponentIconMass();
}
@Override
public String getComponentIconStage() {
return DARK.getComponentIconStage();
}
@Override
public String getComponentIconBoosters() {
return DARK.getComponentIconBoosters();
}
@Override
public String getComponentIconPods() {
return DARK.getComponentIconPods();
}
@Override
public String getComponentIconMassAltimeter() {
return DARK.getComponentIconMassAltimeter();
}
@Override
public String getComponentIconMassBattery() {
return DARK.getComponentIconMassBattery();
}
@Override
public String getComponentIconMassDeploymentCharge() {
return DARK.getComponentIconMassDeploymentCharge();
}
@Override
public String getComponentIconMassPayload() {
return DARK.getComponentIconMassPayload();
}
@Override
public String getComponentIconMassFlightComp() {
return DARK.getComponentIconMassFlightComp();
}
@Override
public String getComponentIconMassRecoveryHardware() {
return DARK.getComponentIconMassRecoveryHardware();
}
@Override
public String getComponentIconMassTracker() {
return DARK.getComponentIconMassTracker();
}
},
/*
Detect best theme based on operating system theme
*/
AUTO {
private final String displayName = trans.get("UITheme.Auto");
@ -853,7 +1210,7 @@ public class UITheme {
final OsThemeDetector detector = OsThemeDetector.getDetector();
final boolean isDarkThemeUsed = detector.isDark();
if (isDarkThemeUsed) {
return Themes.DARK;
return Themes.DARK_CONTRAST;
} else {
return Themes.LIGHT;
}