From a2b6c63f0bd7bef0ed0a09a0b826719956a1b56a Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 21 Dec 2022 23:09:40 +0100 Subject: [PATCH 1/5] [#1893] Add rocket top view --- core/resources/l10n/messages.properties | 1 + .../gui/scalefigure/RocketFigure.java | 38 +++++++++++-------- .../gui/scalefigure/RocketPanel.java | 4 +- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index e1e9dd23d..e7aad6af7 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -49,6 +49,7 @@ RocketActions.MoveDownAct.Movedown = Move down RocketActions.MoveDownAct.ttip.Movedown = Move this component downwards. ! RocketPanel +RocketPanel.FigTypeAct.TopView = Top view RocketPanel.FigTypeAct.SideView = Side view RocketPanel.FigTypeAct.BackView = Back view RocketPanel.FigTypeAct.Figure3D = 3D Figure diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index 1c0925ed6..72e67daea 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -58,9 +58,10 @@ public class RocketFigure extends AbstractScaleFigure { private static final String ROCKET_FIGURE_PACKAGE = "net.sf.openrocket.gui.rocketfigure"; private static final String ROCKET_FIGURE_SUFFIX = "Shapes"; - - public static final int VIEW_SIDE=0; - public static final int VIEW_BACK=1; + + public static final int VIEW_SIDE = 0; + public static final int VIEW_TOP = 1; + public static final int VIEW_BACK = 2; // Width for drawing normal and selected components public static final double NORMAL_WIDTH = 1.0; @@ -130,10 +131,6 @@ public class RocketFigure extends AbstractScaleFigure { return rotation; } - public Transformation getRotateTransformation() { - return axialRotation; - } - public void setRotation(double rot) { if (MathUtil.equals(rotation, rot)) return; @@ -142,6 +139,14 @@ public class RocketFigure extends AbstractScaleFigure { updateFigure(); fireChangeEvent(); } + + private Transformation getFigureRotation() { + if (currentViewType == RocketPanel.VIEW_TYPE.TopView) { + return this.axialRotation.applyTransformation(Transformation.rotate_x(-Math.PI / 2)); + } else { + return this.axialRotation; + } + } public RocketPanel.VIEW_TYPE getType() { @@ -149,7 +154,7 @@ public class RocketFigure extends AbstractScaleFigure { } public void setType(final RocketPanel.VIEW_TYPE type) { - if (type != RocketPanel.VIEW_TYPE.BackView && type != RocketPanel.VIEW_TYPE.SideView) { + if (type != RocketPanel.VIEW_TYPE.BackView && type != RocketPanel.VIEW_TYPE.SideView && type != RocketPanel.VIEW_TYPE.TopView) { throw new IllegalArgumentException("Illegal type: " + type); } if (this.currentViewType == type) @@ -201,7 +206,7 @@ public class RocketFigure extends AbstractScaleFigure { AffineTransform baseTransform = g2.getTransform(); PriorityQueue figureShapes; - if (currentViewType == RocketPanel.VIEW_TYPE.SideView) + if (currentViewType == RocketPanel.VIEW_TYPE.SideView || currentViewType == RocketPanel.VIEW_TYPE.TopView) figureShapes = figureShapes_side; else if (currentViewType == RocketPanel.VIEW_TYPE.BackView) figureShapes = figureShapes_back; @@ -300,11 +305,11 @@ public class RocketFigure extends AbstractScaleFigure { // System.err.println(String.format(" mount instance: %s => %s", curMountLocation.toString(), curMotorLocation.toString() )); // rotate by figure's axial rotation: - curMotorLocation = this.axialRotation.transform(curMotorLocation); + curMotorLocation = getFigureRotation().transform(curMotorLocation); { Shape s; - if (currentViewType == RocketPanel.VIEW_TYPE.SideView) { + if (currentViewType == RocketPanel.VIEW_TYPE.SideView || currentViewType == RocketPanel.VIEW_TYPE.TopView) { s = new Rectangle2D.Double(curMotorLocation.x, (curMotorLocation.y - motorRadius), motorLength, @@ -354,7 +359,7 @@ public class RocketFigure extends AbstractScaleFigure { LinkedHashSet l = new LinkedHashSet(); PriorityQueue figureShapes; - if (currentViewType == RocketPanel.VIEW_TYPE.SideView) + if (currentViewType == RocketPanel.VIEW_TYPE.SideView || currentViewType == RocketPanel.VIEW_TYPE.TopView) figureShapes = figureShapes_side; else if (currentViewType == RocketPanel.VIEW_TYPE.BackView) figureShapes = figureShapes_back; @@ -399,7 +404,7 @@ public class RocketFigure extends AbstractScaleFigure { final ArrayList contextList = entry.getValue(); for (InstanceContext context : contextList) { - final Transformation currentTransform = this.axialRotation.applyTransformation(context.transform); + final Transformation currentTransform = getFigureRotation().applyTransformation(context.transform); allShapes = addThisShape(allShapes, this.currentViewType, comp, currentTransform); } } @@ -432,9 +437,10 @@ public class RocketFigure extends AbstractScaleFigure { // Find the appropriate method switch (viewType) { case SideView: + case TopView: m = Reflection.findMethod(ROCKET_FIGURE_PACKAGE, component, ROCKET_FIGURE_SUFFIX, "getShapesSide", RocketComponent.class, Transformation.class); - break; + break; case BackView: m = Reflection.findMethod(ROCKET_FIGURE_PACKAGE, component, ROCKET_FIGURE_SUFFIX, "getShapesBack", @@ -503,6 +509,7 @@ public class RocketFigure extends AbstractScaleFigure { switch (currentViewType) { case SideView: + case TopView: subjectBounds_m = new Rectangle2D.Double(bounds.min.x, -maxR, bounds.span().x, 2 * maxR); break; case BackView: @@ -528,9 +535,8 @@ public class RocketFigure extends AbstractScaleFigure { if (currentViewType == RocketPanel.VIEW_TYPE.BackView){ final int newOriginX = mid_x; final int newOriginY = borderThickness_px.height + getHeight() / 2; - originLocation_px = new Point(newOriginX, newOriginY); - }else if (currentViewType == RocketPanel.VIEW_TYPE.SideView){ + } else if (currentViewType == RocketPanel.VIEW_TYPE.SideView || currentViewType == RocketPanel.VIEW_TYPE.TopView) { final int newOriginX = mid_x - (subjectWidth / 2) - (int)(subjectBounds_m.getMinX() * scale); final int newOriginY = Math.max(getHeight(), subjectHeight + 2*borderThickness_px.height )/ 2; originLocation_px = new Point(newOriginX, newOriginY); diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index 5a61fd46e..7b1971655 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -93,6 +93,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change public enum VIEW_TYPE { SideView(false, RocketFigure.VIEW_SIDE), + TopView(false, RocketFigure.VIEW_TOP), BackView(false, RocketFigure.VIEW_BACK), Figure3D(true, RocketFigure3d.TYPE_FIGURE), Unfinished(true, RocketFigure3d.TYPE_UNFINISHED), @@ -773,7 +774,8 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change figure3d.setCP(new Coordinate(Double.NaN, Double.NaN)); } - if (figure.getType() == RocketPanel.VIEW_TYPE.SideView && length > 0) { + if (length > 0 && + ((figure.getType() == RocketPanel.VIEW_TYPE.TopView) || (figure.getType() == RocketPanel.VIEW_TYPE.SideView))) { extraCP.setPosition(cpx, cpy); extraCG.setPosition(cgx, cgy); } else { From 98cc674d5ab258b2d3bcaf6c96669e0c2c1be3d9 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Thu, 22 Dec 2022 00:14:23 +0100 Subject: [PATCH 2/5] Add translation for top view --- core/resources/l10n/messages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index e7aad6af7..86844e7a9 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -49,8 +49,8 @@ RocketActions.MoveDownAct.Movedown = Move down RocketActions.MoveDownAct.ttip.Movedown = Move this component downwards. ! RocketPanel -RocketPanel.FigTypeAct.TopView = Top view RocketPanel.FigTypeAct.SideView = Side view +RocketPanel.FigTypeAct.TopView = Top view RocketPanel.FigTypeAct.BackView = Back view RocketPanel.FigTypeAct.Figure3D = 3D Figure RocketPanel.FigTypeAct.Finished = 3D Finished From 41260d7ee9caa898dbb81c1487ff29720c6ee83b Mon Sep 17 00:00:00 2001 From: SiboVG Date: Thu, 22 Dec 2022 00:25:33 +0100 Subject: [PATCH 3/5] Increase flight event time margin --- core/test/net/sf/openrocket/simulation/FlightEventsTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java index 2dc047a22..4aa1df57f 100644 --- a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java +++ b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java @@ -66,7 +66,7 @@ public class FlightEventsTest extends BaseTestCase { // Test that the event times are correct for (int i = 0; i < expectedEventTimes.length; i++) { assertEquals(" Flight type " + expectedEventTypes[i] + " has wrong time", - expectedEventTimes[i], eventList.get(i).getTime(), 0.001); + expectedEventTimes[i], eventList.get(i).getTime(), 0.002); } @@ -142,7 +142,7 @@ public class FlightEventsTest extends BaseTestCase { // Test that the event times are correct for (int i = 0; i < expectedEventTimes.length; i++) { assertEquals(" Flight type " + expectedEventTypes[i] + " has wrong time", - expectedEventTimes[i], eventList.get(i).getTime(), 0.001); + expectedEventTimes[i], eventList.get(i).getTime(), 0.002); } // Test that the event sources are correct From a9442986241f52128a878096de4eba8724c49640 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Thu, 22 Dec 2022 22:25:21 +0100 Subject: [PATCH 4/5] Add horizontal separator in view type combobox between 2D and 3D viewtypes --- .../gui/scalefigure/RocketPanel.java | 73 +++++++++---------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index 7b1971655..2709b9509 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -2,6 +2,7 @@ package net.sf.openrocket.gui.scalefigure; import java.awt.BorderLayout; +import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.Point; @@ -91,10 +92,12 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change private static final Translator trans = Application.getTranslator(); private static final Logger log = LoggerFactory.getLogger(RocketPanel.class); + private static final String VIEW_TYPE_SEPARATOR = "__SEPARATOR__"; // Dummy string to indicate a horizontal separator item in the view type combobox public enum VIEW_TYPE { SideView(false, RocketFigure.VIEW_SIDE), TopView(false, RocketFigure.VIEW_TOP), BackView(false, RocketFigure.VIEW_BACK), + SEPARATOR(false, -248), // Horizontal combobox separator dummy item Figure3D(true, RocketFigure3d.TYPE_FIGURE), Unfinished(true, RocketFigure3d.TYPE_UNFINISHED), Finished(true, RocketFigure3d.TYPE_FINISHED); @@ -109,6 +112,9 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change @Override public String toString() { + if (type == -248) { + return VIEW_TYPE_SEPARATOR; + } return trans.get("RocketPanel.FigTypeAct." + super.toString()); } @@ -313,8 +319,12 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change @Override public void setSelectedItem(Object o) { - super.setSelectedItem(o); VIEW_TYPE v = (VIEW_TYPE) o; + if (v == VIEW_TYPE.SEPARATOR) { + return; + } + + super.setSelectedItem(o); if (v.is3d) { figure3d.setType(v.type); go3D(); @@ -326,7 +336,9 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change } }; ribbon.add(new JLabel(trans.get("RocketPanel.lbl.ViewType")), "cell 0 0"); - ribbon.add(new JComboBox(cm), "cell 0 1"); + final JComboBox viewSelector = new JComboBox(cm); + viewSelector.setRenderer(new SeparatorComboBoxRenderer(viewSelector.getRenderer())); + ribbon.add(viewSelector, "cell 0 1"); // Zoom level selector scaleSelector = new ScaleSelector(scrollPane); @@ -1063,40 +1075,27 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change figure3d.setSelection(components); } - // /** - // * An Action that shows whether the figure type is the - // type - // * given in the constructor. - // * - // * @author Sampo Niskanen - // */ - // private class FigureTypeAction extends AbstractAction implements - // StateChangeListener { - // private static final long serialVersionUID = 1L; - // private final VIEW_TYPE type; - // - // public FigureTypeAction(VIEW_TYPE type) { - // this.type = type; - // stateChanged(null); - // figure.addChangeListener(this); - // } - // - // @Override - // public void actionPerformed(ActionEvent e) { - // boolean state = (Boolean) getValue(Action.SELECTED_KEY); - // if (state == true) { - // // This view has been selected - // figure.setType(type); - // go2D(); - // updateExtras(); - // } - // stateChanged(null); - // } - // - // @Override - // public void stateChanged(EventObject e) { - // putValue(Action.SELECTED_KEY, figure.getType() == type && !is3d); - // } - // } + /** + * Custom combobox renderer that supports the display of horizontal separators between items. + * ComboBox objects with the text {@link VIEW_TYPE_SEPARATOR} objects in the combobox are replaced by a separator object. + */ + private static class SeparatorComboBoxRenderer extends JLabel implements ListCellRenderer { + private final JSeparator separator; + private final ListCellRenderer defaultRenderer; + + public SeparatorComboBoxRenderer(ListCellRenderer defaultRenderer) { + this.defaultRenderer = defaultRenderer; + this.separator = new JSeparator(JSeparator.HORIZONTAL); + } + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + String str = (value == null) ? "" : value.toString(); + if (VIEW_TYPE_SEPARATOR.equals(str)) { + return separator; + }; + return defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + } } From 16ec1ad48fb4e5b4649ba6077a32d225d6b6e639 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sun, 25 Dec 2022 10:41:01 +0100 Subject: [PATCH 5/5] Set top view above side view --- .../customexpression/VariableTableModel.java | 2 +- .../gui/scalefigure/RocketFigure.java | 6 +++--- .../openrocket/gui/scalefigure/RocketPanel.java | 17 ++++++++++++++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/customexpression/VariableTableModel.java b/swing/src/net/sf/openrocket/gui/customexpression/VariableTableModel.java index 490b8e68f..21147e703 100644 --- a/swing/src/net/sf/openrocket/gui/customexpression/VariableTableModel.java +++ b/swing/src/net/sf/openrocket/gui/customexpression/VariableTableModel.java @@ -31,7 +31,7 @@ public class VariableTableModel extends AbstractTableModel { //Collections.addAll(types, FlightDataType.ALL_TYPES); //for (CustomExpression expression : doc.getCustomExpressions()){ - // types.add(expression.getType()); + // types.add(expression.getCurrentViewType()); //} } diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index 72e67daea..0f62a28f7 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -59,8 +59,8 @@ public class RocketFigure extends AbstractScaleFigure { private static final String ROCKET_FIGURE_PACKAGE = "net.sf.openrocket.gui.rocketfigure"; private static final String ROCKET_FIGURE_SUFFIX = "Shapes"; - public static final int VIEW_SIDE = 0; - public static final int VIEW_TOP = 1; + public static final int VIEW_TOP = 0; + public static final int VIEW_SIDE = 1; public static final int VIEW_BACK = 2; // Width for drawing normal and selected components @@ -149,7 +149,7 @@ public class RocketFigure extends AbstractScaleFigure { } - public RocketPanel.VIEW_TYPE getType() { + public RocketPanel.VIEW_TYPE getCurrentViewType() { return currentViewType; } diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index 2709b9509..386aa4de6 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -94,8 +94,8 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change private static final String VIEW_TYPE_SEPARATOR = "__SEPARATOR__"; // Dummy string to indicate a horizontal separator item in the view type combobox public enum VIEW_TYPE { - SideView(false, RocketFigure.VIEW_SIDE), TopView(false, RocketFigure.VIEW_TOP), + SideView(false, RocketFigure.VIEW_SIDE), BackView(false, RocketFigure.VIEW_BACK), SEPARATOR(false, -248), // Horizontal combobox separator dummy item Figure3D(true, RocketFigure3d.TYPE_FIGURE), @@ -118,6 +118,10 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change return trans.get("RocketPanel.FigTypeAct." + super.toString()); } + public static VIEW_TYPE getDefaultViewType() { + return SideView; + } + } private boolean is3d; @@ -315,7 +319,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change JPanel ribbon = new JPanel(new MigLayout("insets 0, fill")); // View Type drop-down - ComboBoxModel cm = new DefaultComboBoxModel(VIEW_TYPE.values()) { + ComboBoxModel cm = new ViewTypeComboBoxModel(VIEW_TYPE.values(), VIEW_TYPE.getDefaultViewType()) { @Override public void setSelectedItem(Object o) { @@ -787,7 +791,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change } if (length > 0 && - ((figure.getType() == RocketPanel.VIEW_TYPE.TopView) || (figure.getType() == RocketPanel.VIEW_TYPE.SideView))) { + ((figure.getCurrentViewType() == RocketPanel.VIEW_TYPE.TopView) || (figure.getCurrentViewType() == RocketPanel.VIEW_TYPE.SideView))) { extraCP.setPosition(cpx, cpy); extraCG.setPosition(cgx, cgy); } else { @@ -1075,6 +1079,13 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change figure3d.setSelection(components); } + private static class ViewTypeComboBoxModel extends DefaultComboBoxModel { + public ViewTypeComboBoxModel(VIEW_TYPE[] items, VIEW_TYPE initialItem) { + super(items); + super.setSelectedItem(initialItem); + } + } + /** * Custom combobox renderer that supports the display of horizontal separators between items. * ComboBox objects with the text {@link VIEW_TYPE_SEPARATOR} objects in the combobox are replaced by a separator object.