Merge pull request #2557 from SiboVG/issue-2019
[#2019] Highlight selected component in CA dialog in rocket panel & Add per-instance CD column to component analysis dialog
This commit is contained in:
commit
6b88a998d4
@ -234,6 +234,10 @@ public class AerodynamicForces implements Cloneable, Monitorable {
|
|||||||
modID = new ModID();
|
modID = new ModID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the drag coefficient <b>per instance</b>.
|
||||||
|
* @return The drag coefficient.
|
||||||
|
*/
|
||||||
public double getCD() {
|
public double getCD() {
|
||||||
if (component == null)
|
if (component == null)
|
||||||
return CD;
|
return CD;
|
||||||
@ -245,6 +249,10 @@ public class AerodynamicForces implements Cloneable, Monitorable {
|
|||||||
return CD;
|
return CD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getCDTotal() {
|
||||||
|
return getCD() * component.getInstanceCount();
|
||||||
|
}
|
||||||
|
|
||||||
public void setPressureCD(double pressureCD) {
|
public void setPressureCD(double pressureCD) {
|
||||||
if (this.pressureCD == pressureCD)
|
if (this.pressureCD == pressureCD)
|
||||||
return;
|
return;
|
||||||
|
@ -39,8 +39,10 @@ public class CADataType implements Comparable<CADataType>, Groupable<CADataTypeG
|
|||||||
"CD,base", UnitGroup.UNITS_NONE, CADataTypeGroup.DRAG, 21);
|
"CD,base", UnitGroup.UNITS_NONE, CADataTypeGroup.DRAG, 21);
|
||||||
public static final CADataType FRICTION_CD = new CADataType(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.friction"),
|
public static final CADataType FRICTION_CD = new CADataType(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.friction"),
|
||||||
"CD,friction", UnitGroup.UNITS_NONE, CADataTypeGroup.DRAG, 22);
|
"CD,friction", UnitGroup.UNITS_NONE, CADataTypeGroup.DRAG, 22);
|
||||||
|
public static final CADataType PER_INSTANCE_CD = new CADataType(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.perInstance"),
|
||||||
|
"CD,instance", UnitGroup.UNITS_NONE, CADataTypeGroup.DRAG, 23);
|
||||||
public static final CADataType TOTAL_CD = new CADataType(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.total"),
|
public static final CADataType TOTAL_CD = new CADataType(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.total"),
|
||||||
"CD,total", UnitGroup.UNITS_NONE, CADataTypeGroup.DRAG, 23);
|
"CD,total", UnitGroup.UNITS_NONE, CADataTypeGroup.DRAG, 24);
|
||||||
|
|
||||||
//// Roll
|
//// Roll
|
||||||
public static final CADataType ROLL_FORCING_COEFFICIENT = new CADataType(trans.get("ComponentAnalysisGeneralTab.rollTableModel.Col.rollforc"),
|
public static final CADataType ROLL_FORCING_COEFFICIENT = new CADataType(trans.get("ComponentAnalysisGeneralTab.rollTableModel.Col.rollforc"),
|
||||||
@ -53,7 +55,7 @@ public class CADataType implements Comparable<CADataType>, Groupable<CADataTypeG
|
|||||||
|
|
||||||
public static final CADataType[] ALL_TYPES = {
|
public static final CADataType[] ALL_TYPES = {
|
||||||
CP_X, CNa,
|
CP_X, CNa,
|
||||||
PRESSURE_CD, BASE_CD, FRICTION_CD, TOTAL_CD,
|
PRESSURE_CD, BASE_CD, FRICTION_CD, PER_INSTANCE_CD, TOTAL_CD,
|
||||||
ROLL_FORCING_COEFFICIENT, ROLL_DAMPING_COEFFICIENT, TOTAL_ROLL_COEFFICIENT
|
ROLL_FORCING_COEFFICIENT, ROLL_DAMPING_COEFFICIENT, TOTAL_ROLL_COEFFICIENT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -124,9 +126,14 @@ public class CADataType implements Comparable<CADataType>, Groupable<CADataTypeG
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Doesn't make sense to calculate per-instance drag for rockets
|
||||||
|
if (component instanceof Rocket && type.equals(CADataType.PER_INSTANCE_CD)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (type.equals(CADataType.CP_X) || type.equals(CADataType.CNa) ||
|
if (type.equals(CADataType.CP_X) || type.equals(CADataType.CNa) ||
|
||||||
type.equals(CADataType.PRESSURE_CD) || type.equals(CADataType.BASE_CD) ||
|
type.equals(CADataType.PRESSURE_CD) || type.equals(CADataType.BASE_CD) ||
|
||||||
type.equals(CADataType.FRICTION_CD) || type.equals(CADataType.TOTAL_CD)) {
|
type.equals(CADataType.FRICTION_CD) || type.equals(CADataType.PER_INSTANCE_CD) || type.equals(CADataType.TOTAL_CD)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (type.equals(CADataType.ROLL_FORCING_COEFFICIENT) || type.equals(CADataType.ROLL_DAMPING_COEFFICIENT) ||
|
} else if (type.equals(CADataType.ROLL_FORCING_COEFFICIENT) || type.equals(CADataType.ROLL_DAMPING_COEFFICIENT) ||
|
||||||
type.equals(CADataType.TOTAL_ROLL_COEFFICIENT)) {
|
type.equals(CADataType.TOTAL_ROLL_COEFFICIENT)) {
|
||||||
|
@ -129,7 +129,8 @@ public class CAParameterSweep {
|
|||||||
dataBranch.setValue(CADataType.PRESSURE_CD, component, forces.getPressureCD());
|
dataBranch.setValue(CADataType.PRESSURE_CD, component, forces.getPressureCD());
|
||||||
dataBranch.setValue(CADataType.BASE_CD, component, forces.getBaseCD());
|
dataBranch.setValue(CADataType.BASE_CD, component, forces.getBaseCD());
|
||||||
dataBranch.setValue(CADataType.FRICTION_CD, component, forces.getFrictionCD());
|
dataBranch.setValue(CADataType.FRICTION_CD, component, forces.getFrictionCD());
|
||||||
dataBranch.setValue(CADataType.TOTAL_CD, component, forces.getCD());
|
dataBranch.setValue(CADataType.PER_INSTANCE_CD, component, forces.getCD());
|
||||||
|
dataBranch.setValue(CADataType.TOTAL_CD, component, forces.getCDTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component instanceof FinSet) {
|
if (component instanceof FinSet) {
|
||||||
@ -154,7 +155,8 @@ public class CAParameterSweep {
|
|||||||
dataBranch.setValue(CADataType.PRESSURE_CD, rocket, totalForces.getPressureCD());
|
dataBranch.setValue(CADataType.PRESSURE_CD, rocket, totalForces.getPressureCD());
|
||||||
dataBranch.setValue(CADataType.BASE_CD, rocket, totalForces.getBaseCD());
|
dataBranch.setValue(CADataType.BASE_CD, rocket, totalForces.getBaseCD());
|
||||||
dataBranch.setValue(CADataType.FRICTION_CD, rocket, totalForces.getFrictionCD());
|
dataBranch.setValue(CADataType.FRICTION_CD, rocket, totalForces.getFrictionCD());
|
||||||
dataBranch.setValue(CADataType.TOTAL_CD, rocket, totalForces.getCD());
|
dataBranch.setValue(CADataType.PER_INSTANCE_CD, rocket, totalForces.getCD());
|
||||||
|
dataBranch.setValue(CADataType.TOTAL_CD, rocket, totalForces.getCDTotal());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,6 +940,7 @@ ComponentAnalysisGeneralTab.dragTableModel.Col.Component = Component
|
|||||||
ComponentAnalysisGeneralTab.dragTableModel.Col.Pressure = <html>Pressure C<sub>D</sub>
|
ComponentAnalysisGeneralTab.dragTableModel.Col.Pressure = <html>Pressure C<sub>D</sub>
|
||||||
ComponentAnalysisGeneralTab.dragTableModel.Col.Base = <html>Base C<sub>D</sub>
|
ComponentAnalysisGeneralTab.dragTableModel.Col.Base = <html>Base C<sub>D</sub>
|
||||||
ComponentAnalysisGeneralTab.dragTableModel.Col.friction = <html>Friction C<sub>D</sub>
|
ComponentAnalysisGeneralTab.dragTableModel.Col.friction = <html>Friction C<sub>D</sub>
|
||||||
|
ComponentAnalysisGeneralTab.dragTableModel.Col.perInstance = <html>Per instance C<sub>D</sub>
|
||||||
ComponentAnalysisGeneralTab.dragTableModel.Col.total = <html>Total C<sub>D</sub>
|
ComponentAnalysisGeneralTab.dragTableModel.Col.total = <html>Total C<sub>D</sub>
|
||||||
ComponentAnalysisGeneralTab.dragTabchar = Drag characteristics
|
ComponentAnalysisGeneralTab.dragTabchar = Drag characteristics
|
||||||
ComponentAnalysisGeneralTab.dragTabchar.ttip = Drag characteristics
|
ComponentAnalysisGeneralTab.dragTabchar.ttip = Drag characteristics
|
||||||
|
@ -33,7 +33,7 @@ public class CAPlotTypeSelector extends PlotTypeSelector<CADataType, CADataTypeG
|
|||||||
componentSelector = new JComboBox<>(componentsForType.toArray(new RocketComponent[0]));
|
componentSelector = new JComboBox<>(componentsForType.toArray(new RocketComponent[0]));
|
||||||
componentSelector.setSelectedItem(selectedComponent);
|
componentSelector.setSelectedItem(selectedComponent);
|
||||||
configuration.setPlotDataComponent(plotIndex, selectedComponent);
|
configuration.setPlotDataComponent(plotIndex, selectedComponent);
|
||||||
this.add(componentSelector, "gapright para");
|
this.add(componentSelector, "growx, gapright para");
|
||||||
|
|
||||||
addRemoveButton();
|
addRemoveButton();
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@ -50,11 +51,19 @@ import javax.swing.SwingConstants;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import javax.swing.plaf.LabelUI;
|
||||||
|
import javax.swing.plaf.basic.BasicLabelUI;
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
|
import javax.swing.table.TableModel;
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
@ -112,8 +121,6 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
this.theta = new DoubleModel(parameters, "Theta", UnitGroup.UNITS_ANGLE, 0, 2 * Math.PI);
|
this.theta = new DoubleModel(parameters, "Theta", UnitGroup.UNITS_ANGLE, 0, 2 * Math.PI);
|
||||||
this.roll = new DoubleModel(parameters, "RollRate", UnitGroup.UNITS_ROLL);
|
this.roll = new DoubleModel(parameters, "RollRate", UnitGroup.UNITS_ROLL);
|
||||||
|
|
||||||
JTable table;
|
|
||||||
|
|
||||||
//// Wind direction:
|
//// Wind direction:
|
||||||
this.add(new JLabel(trans.get("ComponentAnalysisGeneralTab.lbl.winddir")));
|
this.add(new JLabel(trans.get("ComponentAnalysisGeneralTab.lbl.winddir")));
|
||||||
EditableSpinner spinner = new EditableSpinner(theta.getSpinnerModel());
|
EditableSpinner spinner = new EditableSpinner(theta.getSpinnerModel());
|
||||||
@ -200,7 +207,7 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
|
|
||||||
|
|
||||||
// Create the Longitudinal Stability (CM vs CP) data table
|
// Create the Longitudinal Stability (CM vs CP) data table
|
||||||
this.longitudeStabilityTableModel = new ColumnTableModel(
|
this.longitudeStabilityTableModel = new CAColumnTableModel(
|
||||||
|
|
||||||
//// Component
|
//// Component
|
||||||
new Column(trans.get("ComponentAnalysisGeneralTab.TabStability.Col.Component")) {
|
new Column(trans.get("ComponentAnalysisGeneralTab.TabStability.Col.Component")) {
|
||||||
@ -267,15 +274,24 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return stabData.size();
|
return stabData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RocketComponent getComponentForRow(int row) {
|
||||||
|
if (row < 0 || row >= getRowCount()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Object source = stabData.get(row).source;
|
||||||
|
return source instanceof RocketComponent ? (RocketComponent) source : null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
table = new ColumnTable(longitudeStabilityTableModel);
|
final JTable stabilityTable = new ColumnTable(longitudeStabilityTableModel);
|
||||||
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
stabilityTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
this.longitudeStabilityTableModel.setColumnWidths(table.getColumnModel());
|
this.longitudeStabilityTableModel.setColumnWidths(stabilityTable.getColumnModel());
|
||||||
|
|
||||||
table.setDefaultRenderer(Object.class, new StabilityCellRenderer());
|
stabilityTable.setDefaultRenderer(Object.class, new StabilityCellRenderer());
|
||||||
|
|
||||||
JScrollPane scrollpane = new JScrollPane(table);
|
JScrollPane scrollpane = new JScrollPane(stabilityTable);
|
||||||
scrollpane.setPreferredSize(new Dimension(600, 200));
|
scrollpane.setPreferredSize(new Dimension(600, 200));
|
||||||
|
|
||||||
//// Stability and Stability information
|
//// Stability and Stability information
|
||||||
@ -285,7 +301,7 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
|
|
||||||
|
|
||||||
// Create the drag data table
|
// Create the drag data table
|
||||||
this.dragTableModel = new ColumnTableModel(
|
this.dragTableModel = new CAColumnTableModel(
|
||||||
//// Component
|
//// Component
|
||||||
new Column(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.Component")) {
|
new Column(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.Component")) {
|
||||||
@Override
|
@Override
|
||||||
@ -323,11 +339,18 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
return dragData.get(row).getFrictionCD();
|
return dragData.get(row).getFrictionCD();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
//// <html>Per instance C<sub>D</sub>
|
||||||
|
new Column(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.perInstance")) {
|
||||||
|
@Override
|
||||||
|
public Object getValueAt(int row) {
|
||||||
|
return dragData.get(row).getCD();
|
||||||
|
}
|
||||||
|
},
|
||||||
//// <html>Total C<sub>D</sub>
|
//// <html>Total C<sub>D</sub>
|
||||||
new Column(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.total")) {
|
new Column(trans.get("ComponentAnalysisGeneralTab.dragTableModel.Col.total")) {
|
||||||
@Override
|
@Override
|
||||||
public Object getValueAt(int row) {
|
public Object getValueAt(int row) {
|
||||||
return dragData.get(row).getCD();
|
return dragData.get(row).getCDTotal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
@ -340,16 +363,24 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return dragData.size();
|
return dragData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RocketComponent getComponentForRow(int row) {
|
||||||
|
if (row < 0 || row >= getRowCount()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return dragData.get(row).getComponent();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
table = new JTable(dragTableModel);
|
final JTable dragTable = new JTable(dragTableModel);
|
||||||
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
dragTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
this.dragTableModel.setColumnWidths(table.getColumnModel());
|
this.dragTableModel.setColumnWidths(dragTable.getColumnModel());
|
||||||
|
|
||||||
table.setDefaultRenderer(Object.class, new DragCellRenderer());
|
dragTable.setDefaultRenderer(Object.class, new DragCellRenderer());
|
||||||
|
|
||||||
scrollpane = new JScrollPane(table);
|
scrollpane = new JScrollPane(dragTable);
|
||||||
scrollpane.setPreferredSize(new Dimension(600, 200));
|
scrollpane.setPreferredSize(new Dimension(600, 200));
|
||||||
|
|
||||||
//// Drag characteristics and Drag characteristics tooltip
|
//// Drag characteristics and Drag characteristics tooltip
|
||||||
@ -360,7 +391,7 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
|
|
||||||
|
|
||||||
// Create the roll data table
|
// Create the roll data table
|
||||||
this.rollTableModel = new ColumnTableModel(
|
this.rollTableModel = new CAColumnTableModel(
|
||||||
//// Component
|
//// Component
|
||||||
new Column(trans.get("ComponentAnalysisGeneralTab.rollTableModel.Col.component")) {
|
new Column(trans.get("ComponentAnalysisGeneralTab.rollTableModel.Col.component")) {
|
||||||
@Override
|
@Override
|
||||||
@ -403,14 +434,22 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return rollData.size();
|
return rollData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RocketComponent getComponentForRow(int row) {
|
||||||
|
if (row < 0 || row >= getRowCount()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return rollData.get(row).getComponent();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
table = new JTable(rollTableModel);
|
final JTable rollTable = new JTable(rollTableModel);
|
||||||
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
rollTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
table.setDefaultRenderer(Object.class, new RollDynamicsCellRenderer());
|
rollTable.setDefaultRenderer(Object.class, new RollDynamicsCellRenderer());
|
||||||
|
|
||||||
scrollpane = new JScrollPane(table);
|
scrollpane = new JScrollPane(rollTable);
|
||||||
scrollpane.setPreferredSize(new Dimension(600, 200));
|
scrollpane.setPreferredSize(new Dimension(600, 200));
|
||||||
|
|
||||||
//// Roll dynamics and Roll dynamics tooltip
|
//// Roll dynamics and Roll dynamics tooltip
|
||||||
@ -459,6 +498,11 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
this.roll.addChangeListener(this);
|
this.roll.addChangeListener(this);
|
||||||
this.stateChanged(null);
|
this.stateChanged(null);
|
||||||
|
|
||||||
|
// Add listeners to highlight the selected component in the rocket panel
|
||||||
|
stabilityTable.getSelectionModel().addListSelectionListener(new CAListSelectionListener(rocketPanel, stabilityTable));
|
||||||
|
dragTable.getSelectionModel().addListSelectionListener(new CAListSelectionListener(rocketPanel, dragTable));
|
||||||
|
rollTable.getSelectionModel().addListSelectionListener(new CAListSelectionListener(rocketPanel, rollTable));
|
||||||
|
|
||||||
// Remove listeners when closing window
|
// Remove listeners when closing window
|
||||||
parent.addWindowListener(new WindowAdapter() {
|
parent.addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@ -635,7 +679,8 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
private final List<?> data;
|
private final List<?> data;
|
||||||
protected final int decimalPlaces;
|
protected final int decimalPlaces;
|
||||||
|
|
||||||
private static Color backgroundColor;
|
protected static Color backgroundColor;
|
||||||
|
protected static Color foregroundColor;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
initColors();
|
initColors();
|
||||||
@ -656,6 +701,7 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
|
|
||||||
private static void updateColors() {
|
private static void updateColors() {
|
||||||
backgroundColor = GUIUtil.getUITheme().getBackgroundColor();
|
backgroundColor = GUIUtil.getUITheme().getBackgroundColor();
|
||||||
|
foregroundColor = GUIUtil.getUITheme().getTextColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -717,9 +763,13 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
|
|
||||||
private class DragCellRenderer extends CustomCellRenderer {
|
private class DragCellRenderer extends CustomCellRenderer {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final StripedLabelUI stripedUI;
|
||||||
|
private final LabelUI defaultUI;
|
||||||
|
|
||||||
public DragCellRenderer() {
|
public DragCellRenderer() {
|
||||||
super(dragData, 3);
|
super(dragData, 3);
|
||||||
|
this.stripedUI = new StripedLabelUI(1, 12);
|
||||||
|
this.defaultUI = new BasicLabelUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -727,7 +777,17 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||||
|
|
||||||
if (!isSelected && (value instanceof Double)) {
|
// Reset to default UI
|
||||||
|
label.setUI(defaultUI);
|
||||||
|
|
||||||
|
// Handle selection coloring
|
||||||
|
if (isSelected) {
|
||||||
|
label.setBackground(table.getSelectionBackground());
|
||||||
|
label.setForeground(table.getSelectionForeground());
|
||||||
|
label.setOpaque(true);
|
||||||
|
} else {
|
||||||
|
// Non-selected styling
|
||||||
|
if (value instanceof Double) {
|
||||||
double cd = (Double) value;
|
double cd = (Double) value;
|
||||||
float r = (float) (cd / 1.5);
|
float r = (float) (cd / 1.5);
|
||||||
|
|
||||||
@ -737,12 +797,33 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
|
|
||||||
label.setBackground(Color.getHSBColor(hue, sat, val));
|
label.setBackground(Color.getHSBColor(hue, sat, val));
|
||||||
label.setForeground(Color.BLACK);
|
label.setForeground(Color.BLACK);
|
||||||
|
} else {
|
||||||
|
label.setBackground(table.getBackground());
|
||||||
|
label.setForeground(table.getForeground());
|
||||||
|
}
|
||||||
|
label.setOpaque(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((row < 0) || (row >= dragData.size()))
|
// Special handling for column 4
|
||||||
return label;
|
if (column == 4) {
|
||||||
|
if (row == 0) {
|
||||||
|
label.setText("");
|
||||||
|
label.setUI(stripedUI);
|
||||||
|
if (!isSelected) {
|
||||||
|
label.setBackground(table.getBackground());
|
||||||
|
label.setForeground(table.getForeground());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
label.setText(decimalFormat(dragData.get(row).getCD()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((dragData.get(row).getComponent() instanceof Rocket) || (column == 4)) {
|
// Set font
|
||||||
|
if ((row < 0) || (row >= dragData.size())) {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dragData.get(row).getComponent() instanceof Rocket) || (column == 5)) {
|
||||||
label.setFont(boldFont);
|
label.setFont(boldFont);
|
||||||
} else {
|
} else {
|
||||||
label.setFont(normalFont);
|
label.setFont(normalFont);
|
||||||
@ -755,10 +836,46 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
protected String formatDouble(Double cd) {
|
protected String formatDouble(Double cd) {
|
||||||
final double totalCD = dragData.get(0).getCD();
|
final double totalCD = dragData.get(0).getCD();
|
||||||
|
|
||||||
DecimalFormat df = new DecimalFormat("0." + "#".repeat(Math.max(0, decimalPlaces)));
|
String cdFormatted = decimalFormat(cd);
|
||||||
String cdFormatted = df.format(cd);
|
|
||||||
return String.format(cdFormatted + " (%.0f%%)", 100 * cd / totalCD);
|
return String.format(cdFormatted + " (%.0f%%)", 100 * cd / totalCD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String decimalFormat(Double cd) {
|
||||||
|
DecimalFormat df = new DecimalFormat("0." + "#".repeat(Math.max(0, decimalPlaces)));
|
||||||
|
return df.format(cd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StripedLabelUI extends BasicLabelUI {
|
||||||
|
private final int lineWidth;
|
||||||
|
private final int lineSpacing;
|
||||||
|
|
||||||
|
public StripedLabelUI(int lineWidth, int lineSpacing) {
|
||||||
|
this.lineWidth = lineWidth;
|
||||||
|
this.lineSpacing = lineSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g, JComponent c) {
|
||||||
|
Graphics2D g2d = (Graphics2D) g.create();
|
||||||
|
int width = c.getWidth();
|
||||||
|
int height = c.getHeight();
|
||||||
|
|
||||||
|
// Paint background
|
||||||
|
g2d.setColor(c.getBackground());
|
||||||
|
g2d.fillRect(0, 0, width, height);
|
||||||
|
|
||||||
|
// Paint thin lines
|
||||||
|
g2d.setColor(c.getForeground());
|
||||||
|
g2d.setStroke(new BasicStroke(lineWidth));
|
||||||
|
for (int x = -height; x < width; x += (lineWidth + lineSpacing)) {
|
||||||
|
g2d.drawLine(x, height, x + height, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
g2d.dispose();
|
||||||
|
|
||||||
|
super.paint(g, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RollDynamicsCellRenderer extends CustomCellRenderer {
|
private class RollDynamicsCellRenderer extends CustomCellRenderer {
|
||||||
@ -767,8 +884,7 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LongitudinalStabilityRow {
|
private static class LongitudinalStabilityRow {
|
||||||
|
|
||||||
public String name;
|
public String name;
|
||||||
public Object source;
|
public Object source;
|
||||||
public double eachMass;
|
public double eachMass;
|
||||||
@ -784,6 +900,34 @@ public class ComponentAnalysisGeneralPanel extends JPanel implements StateChange
|
|||||||
cpx = Double.NaN;
|
cpx = Double.NaN;
|
||||||
cna = Double.NaN;
|
cna = Double.NaN;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract static class CAColumnTableModel extends ColumnTableModel {
|
||||||
|
public CAColumnTableModel(Column... columns) {
|
||||||
|
super(columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RocketComponent getComponentForRow(int row) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CAListSelectionListener implements ListSelectionListener {
|
||||||
|
private final RocketPanel rocketPanel;
|
||||||
|
private final JTable table;
|
||||||
|
|
||||||
|
public CAListSelectionListener(RocketPanel rocketPanel, JTable table) {
|
||||||
|
this.rocketPanel = rocketPanel;
|
||||||
|
this.table = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
TableModel model = table.getModel();
|
||||||
|
if (model instanceof CAColumnTableModel) {
|
||||||
|
RocketComponent component = ((CAColumnTableModel) model).getComponentForRow(table.getSelectedRow());
|
||||||
|
rocketPanel.setSelectedComponent(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,6 +541,15 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
valueChanged((TreeSelectionEvent) null); // updates FigureParameters
|
valueChanged((TreeSelectionEvent) null); // updates FigureParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSelectedComponent(RocketComponent component) {
|
||||||
|
if (component == null) {
|
||||||
|
selectionModel.setSelectionPath(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TreePath path = ComponentTreeModel.makeTreePath(component);
|
||||||
|
selectionModel.setSelectionPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the angle of attack used in CP calculation. NaN signifies the default value
|
* Return the angle of attack used in CP calculation. NaN signifies the default value
|
||||||
* of zero.
|
* of zero.
|
||||||
@ -672,8 +681,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
if (newClick) {
|
if (newClick) {
|
||||||
for (RocketComponent rocketComponent : clicked) {
|
for (RocketComponent rocketComponent : clicked) {
|
||||||
if (!selectedComponents.contains(rocketComponent)) {
|
if (!selectedComponents.contains(rocketComponent)) {
|
||||||
TreePath path = ComponentTreeModel.makeTreePath(rocketComponent);
|
setSelectedComponent(rocketComponent);
|
||||||
selectionModel.setSelectionPath(path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,20 +130,34 @@ public class GroupableAndSearchableComboBox<G extends Group, T extends Groupable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<G, List<T>> constructItemGroupMapFromList(List<T> items) {
|
private Map<G, List<T>> constructItemGroupMapFromList(List<T> items) {
|
||||||
Map<G, List<T>> itemGroupMap = new TreeMap<>(new Comparator<G>() {
|
Map<G, List<T>> itemGroupMap = new TreeMap<>(Comparator.comparing(Group::getPriority));
|
||||||
@Override
|
|
||||||
public int compare(G g1, G g2) {
|
|
||||||
return Integer.compare(g1.getPriority(), g2.getPriority());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (T item : items) {
|
for (T item : items) {
|
||||||
G group = item.getGroup();
|
G group = item.getGroup();
|
||||||
itemGroupMap.computeIfAbsent(group, k -> new ArrayList<>()).add(item);
|
itemGroupMap.computeIfAbsent(group, k -> new ArrayList<>()).add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort items within each group
|
||||||
|
for (List<T> groupItems : itemGroupMap.values()) {
|
||||||
|
groupItems.sort(new ItemComparator());
|
||||||
|
}
|
||||||
|
|
||||||
return itemGroupMap;
|
return itemGroupMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ItemComparator implements Comparator<T> {
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public int compare(T item1, T item2) {
|
||||||
|
if (item1 instanceof Comparable && item2 instanceof Comparable) {
|
||||||
|
return ((Comparable<T>) item1).compareTo(item2);
|
||||||
|
} else {
|
||||||
|
// Fall back to alphabetical sorting using the display string
|
||||||
|
return getDisplayString(item1).compareToIgnoreCase(getDisplayString(item2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setupMainRenderer() {
|
public void setupMainRenderer() {
|
||||||
setRenderer(new DefaultListCellRenderer() {
|
setRenderer(new DefaultListCellRenderer() {
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user