Rework the thrustcurve motor filter and information. They now share
tabs on the MotorSelectionPanel. Added Minimum Motor diameter to the motor filter.
This commit is contained in:
parent
32817f2cb1
commit
e6755e0e84
@ -1088,6 +1088,7 @@ StorageOptChooser.lbl.Saveopt = Save options
|
|||||||
TCMotorSelPan.lbl.Selrocketmotor = Select rocket motor:
|
TCMotorSelPan.lbl.Selrocketmotor = Select rocket motor:
|
||||||
TCMotorSelPan.checkbox.hideSimilar = Hide very similar thrust curves
|
TCMotorSelPan.checkbox.hideSimilar = Hide very similar thrust curves
|
||||||
TCMotorSelPan.checkbox.hideUsed = Hide motors already used in the mount
|
TCMotorSelPan.checkbox.hideUsed = Hide motors already used in the mount
|
||||||
|
TCMotorSelPan.btn.details = Show Details
|
||||||
TCMotorSelPan.btn.filter = Filter Motors
|
TCMotorSelPan.btn.filter = Filter Motors
|
||||||
TCMotorSelPan.SHOW_DESCRIPTIONS.desc1 = Show all motors
|
TCMotorSelPan.SHOW_DESCRIPTIONS.desc1 = Show all motors
|
||||||
TCMotorSelPan.SHOW_DESCRIPTIONS.desc2 = Show motors with diameter less than that of the motor mount
|
TCMotorSelPan.SHOW_DESCRIPTIONS.desc2 = Show motors with diameter less than that of the motor mount
|
||||||
|
@ -12,25 +12,34 @@ import java.util.List;
|
|||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.ButtonGroup;
|
import javax.swing.ButtonGroup;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JPopupMenu;
|
|
||||||
import javax.swing.JRadioButton;
|
import javax.swing.JRadioButton;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
import javax.swing.border.TitledBorder;
|
import javax.swing.border.TitledBorder;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
import javax.swing.event.ListDataEvent;
|
import javax.swing.event.ListDataEvent;
|
||||||
import javax.swing.event.ListDataListener;
|
import javax.swing.event.ListDataListener;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import net.sf.openrocket.gui.SpinnerEditor;
|
||||||
|
import net.sf.openrocket.gui.adaptors.DoubleModel;
|
||||||
|
import net.sf.openrocket.gui.components.BasicSlider;
|
||||||
|
import net.sf.openrocket.gui.components.UnitSelector;
|
||||||
import net.sf.openrocket.gui.util.CheckList;
|
import net.sf.openrocket.gui.util.CheckList;
|
||||||
import net.sf.openrocket.gui.util.GUIUtil;
|
import net.sf.openrocket.gui.util.GUIUtil;
|
||||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.motor.Manufacturer;
|
import net.sf.openrocket.motor.Manufacturer;
|
||||||
|
import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
|
import net.sf.openrocket.unit.UnitGroup;
|
||||||
|
|
||||||
import com.itextpdf.text.Font;
|
import com.itextpdf.text.Font;
|
||||||
|
|
||||||
public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
public abstract class MotorFilterPanel extends JPanel {
|
||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
@ -39,6 +48,8 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
private final CheckList<ImpulseClass> impulseCheckList;
|
private final CheckList<ImpulseClass> impulseCheckList;
|
||||||
|
|
||||||
private final MotorRowFilter filter;
|
private final MotorRowFilter filter;
|
||||||
|
private final TitledBorder diameterTitleBorder;
|
||||||
|
private final DoubleModel mountDiameter = new DoubleModel(1);
|
||||||
|
|
||||||
private int showMode = SHOW_ALL;
|
private int showMode = SHOW_ALL;
|
||||||
|
|
||||||
@ -47,13 +58,24 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
private static final int SHOW_EXACT = 2;
|
private static final int SHOW_EXACT = 2;
|
||||||
private static final int SHOW_MAX = 2;
|
private static final int SHOW_MAX = 2;
|
||||||
|
|
||||||
|
public MotorFilterPanel(Collection<Manufacturer> allManufacturers, MotorRowFilter filter ) {
|
||||||
public MotorFilterPopupMenu(Collection<Manufacturer> allManufacturers, MotorRowFilter filter ) {
|
super(new MigLayout("fill", "[grow]"));
|
||||||
|
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
|
||||||
showMode = Application.getPreferences().getChoice(net.sf.openrocket.startup.Preferences.MOTOR_DIAMETER_FILTER, MotorFilterPopupMenu.SHOW_MAX, MotorFilterPopupMenu.SHOW_EXACT);
|
showMode = Application.getPreferences().getChoice(net.sf.openrocket.startup.Preferences.MOTOR_DIAMETER_FILTER, MotorFilterPanel.SHOW_MAX, MotorFilterPanel.SHOW_EXACT);
|
||||||
|
switch( showMode ) {
|
||||||
|
case SHOW_ALL:
|
||||||
|
filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.ALL);
|
||||||
|
break;
|
||||||
|
case SHOW_EXACT:
|
||||||
|
filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.EXACT);
|
||||||
|
break;
|
||||||
|
case SHOW_SMALLER:
|
||||||
|
filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.SMALLER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
List<Manufacturer> unselectedManusFromPreferences = ((SwingPreferences) Application.getPreferences()).getExcludedMotorManufacturers();
|
List<Manufacturer> unselectedManusFromPreferences = ((SwingPreferences) Application.getPreferences()).getExcludedMotorManufacturers();
|
||||||
|
filter.setExcludedManufacturers(unselectedManusFromPreferences);
|
||||||
|
|
||||||
// Manufacturer selection
|
// Manufacturer selection
|
||||||
JPanel sub = new JPanel(new MigLayout("fill"));
|
JPanel sub = new JPanel(new MigLayout("fill"));
|
||||||
@ -61,8 +83,7 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
GUIUtil.changeFontStyle(border, Font.BOLD);
|
||||||
sub.setBorder(border);
|
sub.setBorder(border);
|
||||||
|
|
||||||
JPanel root = new JPanel(new MigLayout("fill", "[grow]"));
|
this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
|
||||||
root.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
|
|
||||||
|
|
||||||
List<Manufacturer> manufacturers = new ArrayList<Manufacturer>();
|
List<Manufacturer> manufacturers = new ArrayList<Manufacturer>();
|
||||||
for (Manufacturer m : allManufacturers) {
|
for (Manufacturer m : allManufacturers) {
|
||||||
@ -81,7 +102,6 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
manufacturerCheckList.setData(manufacturers);
|
manufacturerCheckList.setData(manufacturers);
|
||||||
|
|
||||||
manufacturerCheckList.setUncheckedItems(unselectedManusFromPreferences);
|
manufacturerCheckList.setUncheckedItems(unselectedManusFromPreferences);
|
||||||
filter.setExcludedManufacturers(unselectedManusFromPreferences);
|
|
||||||
manufacturerCheckList.getModel().addListDataListener( new ListDataListener() {
|
manufacturerCheckList.getModel().addListDataListener( new ListDataListener() {
|
||||||
@Override
|
@Override
|
||||||
public void intervalAdded(ListDataEvent e) {
|
public void intervalAdded(ListDataEvent e) {
|
||||||
@ -92,7 +112,7 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contentsChanged(ListDataEvent e) {
|
public void contentsChanged(ListDataEvent e) {
|
||||||
MotorFilterPopupMenu.this.filter.setExcludedManufacturers( manufacturerCheckList.getUncheckedItems() );
|
MotorFilterPanel.this.filter.setExcludedManufacturers( manufacturerCheckList.getUncheckedItems() );
|
||||||
onSelectionChanged();
|
onSelectionChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -103,7 +123,7 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
clearMotors.addActionListener( new ActionListener() {
|
clearMotors.addActionListener( new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
MotorFilterPopupMenu.this.manufacturerCheckList.clearAll();
|
MotorFilterPanel.this.manufacturerCheckList.clearAll();
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -114,14 +134,14 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
selectMotors.addActionListener( new ActionListener() {
|
selectMotors.addActionListener( new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
MotorFilterPopupMenu.this.manufacturerCheckList.checkAll();
|
MotorFilterPanel.this.manufacturerCheckList.checkAll();
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
sub.add(selectMotors,"wrap");
|
sub.add(selectMotors,"wrap");
|
||||||
|
|
||||||
root.add(sub,"grow, wrap");
|
this.add(sub,"grow, wrap");
|
||||||
|
|
||||||
// Impulse selection
|
// Impulse selection
|
||||||
sub = new JPanel(new MigLayout("fill"));
|
sub = new JPanel(new MigLayout("fill"));
|
||||||
@ -141,7 +161,7 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void contentsChanged(ListDataEvent e) {
|
public void contentsChanged(ListDataEvent e) {
|
||||||
MotorFilterPopupMenu.this.filter.setExcludedImpulseClasses( impulseCheckList.getUncheckedItems() );
|
MotorFilterPanel.this.filter.setExcludedImpulseClasses( impulseCheckList.getUncheckedItems() );
|
||||||
onSelectionChanged();
|
onSelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +173,7 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
clearImpulse.addActionListener( new ActionListener() {
|
clearImpulse.addActionListener( new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
MotorFilterPopupMenu.this.impulseCheckList.clearAll();
|
MotorFilterPanel.this.impulseCheckList.clearAll();
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -163,27 +183,28 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
selectImpulse.addActionListener( new ActionListener() {
|
selectImpulse.addActionListener( new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
MotorFilterPopupMenu.this.impulseCheckList.checkAll();
|
MotorFilterPanel.this.impulseCheckList.checkAll();
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
sub.add(selectImpulse,"wrap");
|
sub.add(selectImpulse,"wrap");
|
||||||
|
|
||||||
root.add(sub,"grow, wrap");
|
this.add(sub,"grow, wrap");
|
||||||
|
|
||||||
// Diameter selection
|
// Diameter selection
|
||||||
|
|
||||||
sub = new JPanel(new MigLayout("fill"));
|
sub = new JPanel(new MigLayout("fill"));
|
||||||
border = BorderFactory.createTitledBorder(trans.get("TCurveMotorCol.DIAMETER"));
|
diameterTitleBorder = BorderFactory.createTitledBorder(trans.get("TCurveMotorCol.DIAMETER"));
|
||||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
GUIUtil.changeFontStyle(diameterTitleBorder, Font.BOLD);
|
||||||
sub.setBorder(border);
|
sub.setBorder(diameterTitleBorder);
|
||||||
|
|
||||||
JRadioButton showAllDiametersButton = new JRadioButton( trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc1") );
|
JRadioButton showAllDiametersButton = new JRadioButton( trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc1") );
|
||||||
showAllDiametersButton.addActionListener( new ActionListener() {
|
showAllDiametersButton.addActionListener( new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
showMode = SHOW_ALL;
|
showMode = SHOW_ALL;
|
||||||
MotorFilterPopupMenu.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.ALL);
|
MotorFilterPanel.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.ALL);
|
||||||
|
saveMotorDiameterMatchPrefence();
|
||||||
onSelectionChanged();
|
onSelectionChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -195,7 +216,8 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
showMode = SHOW_SMALLER;
|
showMode = SHOW_SMALLER;
|
||||||
MotorFilterPopupMenu.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.SMALLER);
|
MotorFilterPanel.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.SMALLER);
|
||||||
|
saveMotorDiameterMatchPrefence();
|
||||||
onSelectionChanged();
|
onSelectionChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -207,43 +229,57 @@ public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
showMode = SHOW_EXACT;
|
showMode = SHOW_EXACT;
|
||||||
MotorFilterPopupMenu.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.EXACT);
|
MotorFilterPanel.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.EXACT);
|
||||||
|
saveMotorDiameterMatchPrefence();
|
||||||
onSelectionChanged();
|
onSelectionChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
showExactDiametersButton.setSelected( showMode == SHOW_EXACT );
|
showExactDiametersButton.setSelected( showMode == SHOW_EXACT );
|
||||||
sub.add(showExactDiametersButton, "growx,wrap");
|
sub.add(showExactDiametersButton, "growx,wrap");
|
||||||
|
|
||||||
root.add(sub, "grow,wrap");
|
|
||||||
ButtonGroup comboGroup = new ButtonGroup();
|
ButtonGroup comboGroup = new ButtonGroup();
|
||||||
comboGroup.add( showAllDiametersButton );
|
comboGroup.add( showAllDiametersButton );
|
||||||
comboGroup.add( showSmallerDiametersButton );
|
comboGroup.add( showSmallerDiametersButton );
|
||||||
comboGroup.add( showExactDiametersButton );
|
comboGroup.add( showExactDiametersButton );
|
||||||
|
|
||||||
|
{
|
||||||
|
sub.add( new JLabel("Minimum diameter"), "split 4");
|
||||||
|
final DoubleModel minDiameter = new DoubleModel(0, UnitGroup.UNITS_MOTOR_DIMENSIONS, 0, .2);
|
||||||
|
minDiameter.addChangeListener( new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
MotorFilterPanel.this.filter.setMinimumDiameter(minDiameter.getValue());
|
||||||
|
onSelectionChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
JSpinner spin = new JSpinner(minDiameter.getSpinnerModel());
|
||||||
|
spin.setEditor(new SpinnerEditor(spin));
|
||||||
|
sub.add(spin, "growx");
|
||||||
|
|
||||||
// Close button
|
sub.add(new UnitSelector(minDiameter));
|
||||||
JButton closeButton = new JButton(trans.get("TCMotorSelPan.btn.close"));
|
sub.add(new BasicSlider(minDiameter.getSliderModel(0,0.5, mountDiameter)), "w 100lp, wrap");
|
||||||
closeButton.addActionListener(new ActionListener() {
|
}
|
||||||
|
this.add(sub, "grow,wrap");
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
MotorFilterPopupMenu.this.onClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
root.add(closeButton, "split 2");
|
|
||||||
|
|
||||||
this.add(root);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClose() {
|
public void setMotorMount( MotorMount mount ) {
|
||||||
|
filter.setMotorMount(mount);
|
||||||
|
onSelectionChanged();
|
||||||
|
if ( mount == null ) {
|
||||||
|
// Disable diameter controls?
|
||||||
|
diameterTitleBorder.setTitle(trans.get("TCurveMotorCol.DIAMETER"));
|
||||||
|
mountDiameter.setValue(1.0);
|
||||||
|
} else {
|
||||||
|
mountDiameter.setValue(mount.getMotorMountDiameter());
|
||||||
|
diameterTitleBorder.setTitle(trans.get("TCurveMotorCol.DIAMETER") + " "
|
||||||
|
+ trans.get("TCMotorSelPan.lbl.Motormountdia") + " " +
|
||||||
|
UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit().toStringUnit(mount.getMotorMountDiameter()));
|
||||||
|
|
||||||
((SwingPreferences) Application.getPreferences()).setExcludedMotorManufacturers(filter.getExcludedManufacturers());
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveMotorDiameterMatchPrefence() {
|
||||||
Application.getPreferences().putChoice("MotorDiameterMatch", showMode );
|
Application.getPreferences().putChoice("MotorDiameterMatch", showMode );
|
||||||
|
|
||||||
setVisible(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void onSelectionChanged();
|
public abstract void onSelectionChanged();
|
@ -0,0 +1,315 @@
|
|||||||
|
package net.sf.openrocket.gui.dialogs.motor.thrustcurve;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Cursor;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JLayeredPane;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JTextArea;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import net.sf.openrocket.gui.util.GUIUtil;
|
||||||
|
import net.sf.openrocket.gui.util.Icons;
|
||||||
|
import net.sf.openrocket.l10n.Translator;
|
||||||
|
import net.sf.openrocket.motor.ThrustCurveMotor;
|
||||||
|
import net.sf.openrocket.startup.Application;
|
||||||
|
import net.sf.openrocket.unit.UnitGroup;
|
||||||
|
|
||||||
|
import org.jfree.chart.ChartFactory;
|
||||||
|
import org.jfree.chart.ChartPanel;
|
||||||
|
import org.jfree.chart.JFreeChart;
|
||||||
|
import org.jfree.chart.axis.ValueAxis;
|
||||||
|
import org.jfree.chart.plot.PlotOrientation;
|
||||||
|
import org.jfree.chart.plot.XYPlot;
|
||||||
|
import org.jfree.chart.title.TextTitle;
|
||||||
|
import org.jfree.data.xy.XYSeries;
|
||||||
|
import org.jfree.data.xy.XYSeriesCollection;
|
||||||
|
|
||||||
|
class MotorInformationPanel extends JPanel {
|
||||||
|
|
||||||
|
private static final int ZOOM_ICON_POSITION_NEGATIVE_X = 50;
|
||||||
|
private static final int ZOOM_ICON_POSITION_POSITIVE_Y = 12;
|
||||||
|
|
||||||
|
private static final Color NO_COMMENT_COLOR = Color.GRAY;
|
||||||
|
private static final Color WITH_COMMENT_COLOR = Color.BLACK;
|
||||||
|
|
||||||
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
|
// Motors in set
|
||||||
|
private List<ThrustCurveMotor> selectedMotorSet;
|
||||||
|
// Selected motor
|
||||||
|
private ThrustCurveMotor selectedMotor;
|
||||||
|
|
||||||
|
private final JLabel totalImpulseLabel;
|
||||||
|
private final JLabel classificationLabel;
|
||||||
|
private final JLabel avgThrustLabel;
|
||||||
|
private final JLabel maxThrustLabel;
|
||||||
|
private final JLabel burnTimeLabel;
|
||||||
|
private final JLabel launchMassLabel;
|
||||||
|
private final JLabel emptyMassLabel;
|
||||||
|
private final JLabel dataPointsLabel;
|
||||||
|
private final JLabel digestLabel;
|
||||||
|
|
||||||
|
private final JTextArea comment;
|
||||||
|
private final Font noCommentFont;
|
||||||
|
private final Font withCommentFont;
|
||||||
|
|
||||||
|
private final JFreeChart chart;
|
||||||
|
private final ChartPanel chartPanel;
|
||||||
|
private final JLabel zoomIcon;
|
||||||
|
|
||||||
|
public MotorInformationPanel() {
|
||||||
|
super(new MigLayout("fill"));
|
||||||
|
|
||||||
|
// Thrust curve info
|
||||||
|
//// Total impulse:
|
||||||
|
{
|
||||||
|
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Totalimpulse")));
|
||||||
|
totalImpulseLabel = new JLabel();
|
||||||
|
this.add(totalImpulseLabel, "split");
|
||||||
|
|
||||||
|
classificationLabel = new JLabel();
|
||||||
|
classificationLabel.setEnabled(false); // Gray out
|
||||||
|
this.add(classificationLabel, "gapleft unrel, wrap");
|
||||||
|
|
||||||
|
//// Avg. thrust:
|
||||||
|
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Avgthrust")));
|
||||||
|
avgThrustLabel = new JLabel();
|
||||||
|
this.add(avgThrustLabel, "wrap");
|
||||||
|
|
||||||
|
//// Max. thrust:
|
||||||
|
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Maxthrust")));
|
||||||
|
maxThrustLabel = new JLabel();
|
||||||
|
this.add(maxThrustLabel, "wrap");
|
||||||
|
|
||||||
|
//// Burn time:
|
||||||
|
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Burntime")));
|
||||||
|
burnTimeLabel = new JLabel();
|
||||||
|
this.add(burnTimeLabel, "wrap");
|
||||||
|
|
||||||
|
//// Launch mass:
|
||||||
|
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Launchmass")));
|
||||||
|
launchMassLabel = new JLabel();
|
||||||
|
this.add(launchMassLabel, "wrap");
|
||||||
|
|
||||||
|
//// Empty mass:
|
||||||
|
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Emptymass")));
|
||||||
|
emptyMassLabel = new JLabel();
|
||||||
|
this.add(emptyMassLabel, "wrap");
|
||||||
|
|
||||||
|
//// Data points:
|
||||||
|
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Datapoints")));
|
||||||
|
dataPointsLabel = new JLabel();
|
||||||
|
this.add(dataPointsLabel, "wrap para");
|
||||||
|
|
||||||
|
if (System.getProperty("openrocket.debug.motordigest") != null) {
|
||||||
|
//// Digest:
|
||||||
|
this.add(new JLabel(trans.get("TCMotorSelPan.lbl.Digest")));
|
||||||
|
digestLabel = new JLabel();
|
||||||
|
this.add(digestLabel, "w :300:, wrap para");
|
||||||
|
} else {
|
||||||
|
digestLabel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
comment = new JTextArea(5, 5);
|
||||||
|
GUIUtil.changeFontSize(comment, -2);
|
||||||
|
withCommentFont = comment.getFont();
|
||||||
|
noCommentFont = withCommentFont.deriveFont(Font.ITALIC);
|
||||||
|
comment.setLineWrap(true);
|
||||||
|
comment.setWrapStyleWord(true);
|
||||||
|
comment.setEditable(false);
|
||||||
|
JScrollPane scrollpane = new JScrollPane(comment);
|
||||||
|
this.add(scrollpane, "spanx, growx, wrap para");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thrust curve plot
|
||||||
|
{
|
||||||
|
chart = ChartFactory.createXYLineChart(
|
||||||
|
null, // title
|
||||||
|
null, // xAxisLabel
|
||||||
|
null, // yAxisLabel
|
||||||
|
null, // dataset
|
||||||
|
PlotOrientation.VERTICAL,
|
||||||
|
false, // legend
|
||||||
|
false, // tooltips
|
||||||
|
false // urls
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the data and formatting to the plot
|
||||||
|
XYPlot plot = chart.getXYPlot();
|
||||||
|
|
||||||
|
changeLabelFont(plot.getRangeAxis(), -2);
|
||||||
|
changeLabelFont(plot.getDomainAxis(), -2);
|
||||||
|
|
||||||
|
//// Thrust curve:
|
||||||
|
chart.setTitle(new TextTitle(trans.get("TCMotorSelPan.title.Thrustcurve"), this.getFont()));
|
||||||
|
chart.setBackgroundPaint(this.getBackground());
|
||||||
|
plot.setBackgroundPaint(Color.WHITE);
|
||||||
|
plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
|
||||||
|
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
|
||||||
|
|
||||||
|
chartPanel = new ChartPanel(chart,
|
||||||
|
false, // properties
|
||||||
|
false, // save
|
||||||
|
false, // print
|
||||||
|
false, // zoom
|
||||||
|
false); // tooltips
|
||||||
|
chartPanel.setMouseZoomable(false);
|
||||||
|
chartPanel.setPopupMenu(null);
|
||||||
|
chartPanel.setMouseWheelEnabled(false);
|
||||||
|
chartPanel.setRangeZoomable(false);
|
||||||
|
chartPanel.setDomainZoomable(false);
|
||||||
|
|
||||||
|
chartPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||||
|
chartPanel.addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
if (selectedMotor == null || selectedMotorSet == null)
|
||||||
|
return;
|
||||||
|
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||||
|
// Open plot dialog
|
||||||
|
ThrustCurveMotorPlotDialog plotDialog = new ThrustCurveMotorPlotDialog(selectedMotorSet,
|
||||||
|
selectedMotorSet.indexOf(selectedMotor),
|
||||||
|
SwingUtilities.getWindowAncestor(MotorInformationPanel.this));
|
||||||
|
plotDialog.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JLayeredPane layer = new CustomLayeredPane();
|
||||||
|
|
||||||
|
layer.setBorder(BorderFactory.createLineBorder(Color.BLUE));
|
||||||
|
|
||||||
|
layer.add(chartPanel, (Integer) 0);
|
||||||
|
|
||||||
|
zoomIcon = new JLabel(Icons.ZOOM_IN);
|
||||||
|
zoomIcon.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||||
|
layer.add(zoomIcon, (Integer) 1);
|
||||||
|
|
||||||
|
this.add(layer, "width 300:300:, height 180:180:, grow, spanx");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearData() {
|
||||||
|
totalImpulseLabel.setText("");
|
||||||
|
totalImpulseLabel.setToolTipText(null);
|
||||||
|
classificationLabel.setText("");
|
||||||
|
classificationLabel.setToolTipText(null);
|
||||||
|
avgThrustLabel.setText("");
|
||||||
|
maxThrustLabel.setText("");
|
||||||
|
burnTimeLabel.setText("");
|
||||||
|
launchMassLabel.setText("");
|
||||||
|
emptyMassLabel.setText("");
|
||||||
|
dataPointsLabel.setText("");
|
||||||
|
if (digestLabel != null) {
|
||||||
|
digestLabel.setText("");
|
||||||
|
}
|
||||||
|
setComment("");
|
||||||
|
chart.getXYPlot().setDataset(new XYSeriesCollection());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateData( List<ThrustCurveMotor> motors, ThrustCurveMotor selectedMotor ) {
|
||||||
|
|
||||||
|
this.selectedMotorSet = motors;
|
||||||
|
this.selectedMotor = selectedMotor;
|
||||||
|
|
||||||
|
// Update thrust curve data
|
||||||
|
double impulse = selectedMotor.getTotalImpulseEstimate();
|
||||||
|
MotorClass mc = MotorClass.getMotorClass(impulse);
|
||||||
|
totalImpulseLabel.setText(UnitGroup.UNITS_IMPULSE.getDefaultUnit().toStringUnit(impulse));
|
||||||
|
classificationLabel.setText("(" + mc.getDescription(impulse) + ")");
|
||||||
|
totalImpulseLabel.setToolTipText(mc.getClassDescription());
|
||||||
|
classificationLabel.setToolTipText(mc.getClassDescription());
|
||||||
|
|
||||||
|
avgThrustLabel.setText(UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit(
|
||||||
|
selectedMotor.getAverageThrustEstimate()));
|
||||||
|
maxThrustLabel.setText(UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit(
|
||||||
|
selectedMotor.getMaxThrustEstimate()));
|
||||||
|
burnTimeLabel.setText(UnitGroup.UNITS_SHORT_TIME.getDefaultUnit().toStringUnit(
|
||||||
|
selectedMotor.getBurnTimeEstimate()));
|
||||||
|
launchMassLabel.setText(UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
|
||||||
|
selectedMotor.getLaunchCG().weight));
|
||||||
|
emptyMassLabel.setText(UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
|
||||||
|
selectedMotor.getEmptyCG().weight));
|
||||||
|
dataPointsLabel.setText("" + (selectedMotor.getTimePoints().length - 1));
|
||||||
|
if (digestLabel != null) {
|
||||||
|
digestLabel.setText(selectedMotor.getDigest());
|
||||||
|
}
|
||||||
|
|
||||||
|
setComment(selectedMotor.getDescription());
|
||||||
|
|
||||||
|
// Update the plot
|
||||||
|
XYPlot plot = chart.getXYPlot();
|
||||||
|
final int index = motors.indexOf(selectedMotor);
|
||||||
|
|
||||||
|
XYSeriesCollection dataset = new XYSeriesCollection();
|
||||||
|
for (int i = 0; i < motors.size(); i++) {
|
||||||
|
ThrustCurveMotor m = motors.get(i);
|
||||||
|
|
||||||
|
//// Thrust
|
||||||
|
XYSeries series = new XYSeries(trans.get("TCMotorSelPan.title.Thrust") + " (" + i + ")");
|
||||||
|
double[] time = m.getTimePoints();
|
||||||
|
double[] thrust = m.getThrustPoints();
|
||||||
|
|
||||||
|
for (int j = 0; j < time.length; j++) {
|
||||||
|
series.add(time[j], thrust[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataset.addSeries(series);
|
||||||
|
|
||||||
|
boolean selected = (i == index);
|
||||||
|
plot.getRenderer().setSeriesStroke(i, new BasicStroke(selected ? 3 : 1));
|
||||||
|
plot.getRenderer().setSeriesPaint(i, ThrustCurveMotorSelectionPanel.getColor(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
plot.setDataset(dataset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setComment(String s) {
|
||||||
|
s = s.trim();
|
||||||
|
if (s.length() == 0) {
|
||||||
|
//// No description available.
|
||||||
|
comment.setText(trans.get("TCMotorSelPan.noDescription"));
|
||||||
|
comment.setFont(noCommentFont);
|
||||||
|
comment.setForeground(NO_COMMENT_COLOR);
|
||||||
|
} else {
|
||||||
|
comment.setText(s);
|
||||||
|
comment.setFont(withCommentFont);
|
||||||
|
comment.setForeground(WITH_COMMENT_COLOR);
|
||||||
|
}
|
||||||
|
comment.setCaretPosition(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeLabelFont(ValueAxis axis, float size) {
|
||||||
|
Font font = axis.getTickLabelFont();
|
||||||
|
font = font.deriveFont(font.getSize2D() + size);
|
||||||
|
axis.setTickLabelFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom layered pane that sets the bounds of the components on every layout.
|
||||||
|
*/
|
||||||
|
public class CustomLayeredPane extends JLayeredPane {
|
||||||
|
@Override
|
||||||
|
public void doLayout() {
|
||||||
|
synchronized (getTreeLock()) {
|
||||||
|
int w = getWidth();
|
||||||
|
int h = getHeight();
|
||||||
|
chartPanel.setBounds(0, 0, w, h);
|
||||||
|
zoomIcon.setBounds(w - ZOOM_ICON_POSITION_NEGATIVE_X, ZOOM_ICON_POSITION_POSITIVE_Y, 50, 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -35,7 +35,10 @@ class MotorRowFilter extends RowFilter<TableModel, Integer> {
|
|||||||
|
|
||||||
// things which can be changed to modify filter behavior
|
// things which can be changed to modify filter behavior
|
||||||
|
|
||||||
// Collection of strings which match text in the moto
|
// Limit motors based on minimum diameter
|
||||||
|
private Double minimumDiameter;
|
||||||
|
|
||||||
|
// Collection of strings which match text in the motor
|
||||||
private List<String> searchTerms = Collections.<String> emptyList();
|
private List<String> searchTerms = Collections.<String> emptyList();
|
||||||
|
|
||||||
// Limit motors based on diameter of the motor mount
|
// Limit motors based on diameter of the motor mount
|
||||||
@ -76,6 +79,14 @@ class MotorRowFilter extends RowFilter<TableModel, Integer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Double getMinimumDiameter() {
|
||||||
|
return minimumDiameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMinimumDiameter(Double minimumDiameter) {
|
||||||
|
this.minimumDiameter = minimumDiameter;
|
||||||
|
}
|
||||||
|
|
||||||
DiameterFilterControl getDiameterControl() {
|
DiameterFilterControl getDiameterControl() {
|
||||||
return diameterControl;
|
return diameterControl;
|
||||||
}
|
}
|
||||||
@ -130,6 +141,13 @@ class MotorRowFilter extends RowFilter<TableModel, Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean filterByDiameter(ThrustCurveMotorSet m) {
|
private boolean filterByDiameter(ThrustCurveMotorSet m) {
|
||||||
|
|
||||||
|
if ( minimumDiameter != null ) {
|
||||||
|
if ( m.getDiameter() <= minimumDiameter - 0.0015 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (diameter == null) {
|
if (diameter == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package net.sf.openrocket.gui.dialogs.motor.thrustcurve;
|
package net.sf.openrocket.gui.dialogs.motor.thrustcurve;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Cursor;
|
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
@ -20,26 +18,24 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
|
||||||
import javax.swing.DefaultComboBoxModel;
|
import javax.swing.DefaultComboBoxModel;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JLayeredPane;
|
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSeparator;
|
import javax.swing.JSeparator;
|
||||||
|
import javax.swing.JTabbedPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.JTextArea;
|
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import javax.swing.ListCellRenderer;
|
import javax.swing.ListCellRenderer;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.RowSorter;
|
import javax.swing.RowSorter;
|
||||||
import javax.swing.SortOrder;
|
import javax.swing.SortOrder;
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
@ -50,11 +46,9 @@ import javax.swing.table.TableRowSorter;
|
|||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import net.sf.openrocket.database.motor.ThrustCurveMotorSet;
|
import net.sf.openrocket.database.motor.ThrustCurveMotorSet;
|
||||||
import net.sf.openrocket.gui.components.StyledLabel;
|
import net.sf.openrocket.gui.components.StyledLabel;
|
||||||
import net.sf.openrocket.gui.components.StyledLabel.Style;
|
|
||||||
import net.sf.openrocket.gui.dialogs.motor.CloseableDialog;
|
import net.sf.openrocket.gui.dialogs.motor.CloseableDialog;
|
||||||
import net.sf.openrocket.gui.dialogs.motor.MotorSelector;
|
import net.sf.openrocket.gui.dialogs.motor.MotorSelector;
|
||||||
import net.sf.openrocket.gui.util.GUIUtil;
|
import net.sf.openrocket.gui.util.GUIUtil;
|
||||||
import net.sf.openrocket.gui.util.Icons;
|
|
||||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.logging.Markers;
|
import net.sf.openrocket.logging.Markers;
|
||||||
@ -69,15 +63,7 @@ import net.sf.openrocket.util.BugException;
|
|||||||
import net.sf.openrocket.utils.MotorCorrelation;
|
import net.sf.openrocket.utils.MotorCorrelation;
|
||||||
|
|
||||||
import org.jfree.chart.ChartColor;
|
import org.jfree.chart.ChartColor;
|
||||||
import org.jfree.chart.ChartFactory;
|
|
||||||
import org.jfree.chart.ChartPanel;
|
|
||||||
import org.jfree.chart.JFreeChart;
|
|
||||||
import org.jfree.chart.axis.ValueAxis;
|
import org.jfree.chart.axis.ValueAxis;
|
||||||
import org.jfree.chart.plot.PlotOrientation;
|
|
||||||
import org.jfree.chart.plot.XYPlot;
|
|
||||||
import org.jfree.chart.title.TextTitle;
|
|
||||||
import org.jfree.data.xy.XYSeries;
|
|
||||||
import org.jfree.data.xy.XYSeriesCollection;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -88,21 +74,15 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
|
|
||||||
private static final double MOTOR_SIMILARITY_THRESHOLD = 0.95;
|
private static final double MOTOR_SIMILARITY_THRESHOLD = 0.95;
|
||||||
|
|
||||||
private static final int ZOOM_ICON_POSITION_NEGATIVE_X = 50;
|
|
||||||
private static final int ZOOM_ICON_POSITION_POSITIVE_Y = 12;
|
|
||||||
|
|
||||||
private static final Paint[] CURVE_COLORS = ChartColor.createDefaultPaintArray();
|
private static final Paint[] CURVE_COLORS = ChartColor.createDefaultPaintArray();
|
||||||
|
|
||||||
private static final Color NO_COMMENT_COLOR = Color.GRAY;
|
|
||||||
private static final Color WITH_COMMENT_COLOR = Color.BLACK;
|
|
||||||
|
|
||||||
private static final ThrustCurveMotorComparator MOTOR_COMPARATOR = new ThrustCurveMotorComparator();
|
private static final ThrustCurveMotorComparator MOTOR_COMPARATOR = new ThrustCurveMotorComparator();
|
||||||
|
|
||||||
private List<ThrustCurveMotorSet> database;
|
private List<ThrustCurveMotorSet> database;
|
||||||
|
|
||||||
private CloseableDialog dialog = null;
|
private CloseableDialog dialog = null;
|
||||||
|
|
||||||
final ThrustCurveMotorDatabaseModel model;
|
private final ThrustCurveMotorDatabaseModel model;
|
||||||
private final JTable table;
|
private final JTable table;
|
||||||
private final TableRowSorter<TableModel> sorter;
|
private final TableRowSorter<TableModel> sorter;
|
||||||
private final MotorRowFilter rowFilter;
|
private final MotorRowFilter rowFilter;
|
||||||
@ -110,33 +90,15 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
private final JCheckBox hideSimilarBox;
|
private final JCheckBox hideSimilarBox;
|
||||||
|
|
||||||
private final JTextField searchField;
|
private final JTextField searchField;
|
||||||
String[] searchTerms = new String[0];
|
|
||||||
|
|
||||||
private final StyledLabel diameterLabel;
|
|
||||||
private final JLabel curveSelectionLabel;
|
private final JLabel curveSelectionLabel;
|
||||||
private final JComboBox curveSelectionBox;
|
private final JComboBox curveSelectionBox;
|
||||||
private final DefaultComboBoxModel curveSelectionModel;
|
private final DefaultComboBoxModel curveSelectionModel;
|
||||||
|
|
||||||
private final JLabel totalImpulseLabel;
|
|
||||||
private final JLabel classificationLabel;
|
|
||||||
private final JLabel avgThrustLabel;
|
|
||||||
private final JLabel maxThrustLabel;
|
|
||||||
private final JLabel burnTimeLabel;
|
|
||||||
private final JLabel launchMassLabel;
|
|
||||||
private final JLabel emptyMassLabel;
|
|
||||||
private final JLabel dataPointsLabel;
|
|
||||||
private final JLabel digestLabel;
|
|
||||||
|
|
||||||
private final JTextArea comment;
|
|
||||||
private final Font noCommentFont;
|
|
||||||
private final Font withCommentFont;
|
|
||||||
|
|
||||||
private final JFreeChart chart;
|
|
||||||
private final ChartPanel chartPanel;
|
|
||||||
private final JLabel zoomIcon;
|
|
||||||
|
|
||||||
private final JComboBox delayBox;
|
private final JComboBox delayBox;
|
||||||
|
|
||||||
|
private final MotorInformationPanel motorInformationPanel;
|
||||||
|
private final MotorFilterPanel motorFilterPanel;
|
||||||
|
|
||||||
private ThrustCurveMotor selectedMotor;
|
private ThrustCurveMotor selectedMotor;
|
||||||
private ThrustCurveMotorSet selectedMotorSet;
|
private ThrustCurveMotorSet selectedMotorSet;
|
||||||
private double selectedDelay;
|
private double selectedDelay;
|
||||||
@ -157,167 +119,197 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
super(new MigLayout("fill", "[grow][]"));
|
super(new MigLayout("fill", "[grow][]"));
|
||||||
|
|
||||||
// Construct the database (adding the current motor if not in the db already)
|
// Construct the database (adding the current motor if not in the db already)
|
||||||
List<ThrustCurveMotorSet> db;
|
database = Application.getThrustCurveMotorSetDatabase().getMotorSets();
|
||||||
db = Application.getThrustCurveMotorSetDatabase().getMotorSets();
|
|
||||||
|
|
||||||
database = db;
|
|
||||||
|
|
||||||
model = new ThrustCurveMotorDatabaseModel(database);
|
model = new ThrustCurveMotorDatabaseModel(database);
|
||||||
rowFilter = new MotorRowFilter(model);
|
rowFilter = new MotorRowFilter(model);
|
||||||
|
motorInformationPanel = new MotorInformationPanel();
|
||||||
|
|
||||||
//// GUI
|
//// MotorFilter
|
||||||
|
|
||||||
JPanel panel;
|
|
||||||
JLabel label;
|
|
||||||
|
|
||||||
panel = new JPanel(new MigLayout("fill"));
|
|
||||||
this.add(panel, "grow");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Selection label
|
|
||||||
//// Select rocket motor:
|
|
||||||
label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Selrocketmotor"), Style.BOLD);
|
|
||||||
panel.add(label, "spanx, wrap para");
|
|
||||||
|
|
||||||
// Search field
|
|
||||||
//// Search:
|
|
||||||
label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Search"));
|
|
||||||
panel.add(label, "split");
|
|
||||||
|
|
||||||
searchField = new JTextField();
|
|
||||||
searchField.getDocument().addDocumentListener(new DocumentListener() {
|
|
||||||
@Override
|
|
||||||
public void changedUpdate(DocumentEvent e) {
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insertUpdate(DocumentEvent e) {
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeUpdate(DocumentEvent e) {
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update() {
|
|
||||||
String text = searchField.getText().trim();
|
|
||||||
String[] split = text.split("\\s+");
|
|
||||||
rowFilter.setSearchTerms(Arrays.asList(split));
|
|
||||||
sorter.sort();
|
|
||||||
scrollSelectionVisible();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
panel.add(searchField, "growx");
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// Find all the manufacturers:
|
// Find all the manufacturers:
|
||||||
Set<Manufacturer> allManufacturers = new HashSet<Manufacturer>();
|
Set<Manufacturer> allManufacturers = new HashSet<Manufacturer>();
|
||||||
for (ThrustCurveMotorSet s : database) {
|
for (ThrustCurveMotorSet s : database) {
|
||||||
allManufacturers.add(s.getManufacturer());
|
allManufacturers.add(s.getManufacturer());
|
||||||
}
|
}
|
||||||
|
|
||||||
final MotorFilterPopupMenu popup = new MotorFilterPopupMenu(allManufacturers, rowFilter) {
|
motorFilterPanel = new MotorFilterPanel(allManufacturers, rowFilter) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSelectionChanged() {
|
public void onSelectionChanged() {
|
||||||
sorter.sort();
|
sorter.sort();
|
||||||
scrollSelectionVisible();
|
scrollSelectionVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JButton manuFilter = new JButton(trans.get("TCMotorSelPan.btn.filter"));
|
}
|
||||||
manuFilter.addMouseListener(new MouseListener() {
|
|
||||||
|
|
||||||
|
//// GUI
|
||||||
|
JPanel panel = new JPanel(new MigLayout("fill","[][grow][]"));
|
||||||
|
this.add(panel, "grow");
|
||||||
|
|
||||||
|
//// Select thrust curve:
|
||||||
|
{
|
||||||
|
curveSelectionLabel = new JLabel(trans.get("TCMotorSelPan.lbl.Selectthrustcurve"));
|
||||||
|
panel.add(curveSelectionLabel);
|
||||||
|
|
||||||
|
curveSelectionModel = new DefaultComboBoxModel();
|
||||||
|
curveSelectionBox = new JComboBox(curveSelectionModel);
|
||||||
|
curveSelectionBox.setRenderer(new CurveSelectionRenderer(curveSelectionBox.getRenderer()));
|
||||||
|
curveSelectionBox.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Object value = curveSelectionBox.getSelectedItem();
|
||||||
|
if (value != null) {
|
||||||
|
select(((MotorHolder) value).getMotor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
panel.add(curveSelectionBox, "growx");
|
||||||
|
|
||||||
|
final JPopupMenu popup = new JPopupMenu();
|
||||||
|
popup.add( motorInformationPanel );
|
||||||
|
JButton showDetailsButton = new JButton(trans.get("TCMotorSelPan.btn.details"));
|
||||||
|
showDetailsButton.addMouseListener(new MouseListener() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered(MouseEvent e) {
|
public void mouseEntered(MouseEvent e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseExited(MouseEvent e) {
|
public void mouseExited(MouseEvent e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
panel.add(manuFilter, "gapleft para, wrap para");
|
panel.add(showDetailsButton, "gapleft para, wrap");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Motor selection table
|
// Ejection charge delay:
|
||||||
table = new JTable(model);
|
|
||||||
|
|
||||||
|
|
||||||
// Set comparators and widths
|
|
||||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
|
||||||
sorter = new TableRowSorter<TableModel>(model);
|
|
||||||
for (int i = 0; i < ThrustCurveMotorColumns.values().length; i++) {
|
|
||||||
ThrustCurveMotorColumns column = ThrustCurveMotorColumns.values()[i];
|
|
||||||
sorter.setComparator(i, column.getComparator());
|
|
||||||
table.getColumnModel().getColumn(i).setPreferredWidth(column.getWidth());
|
|
||||||
}
|
|
||||||
table.setRowSorter(sorter);
|
|
||||||
// force initial sort order to by diameter, total impulse, manufacturer
|
|
||||||
{
|
{
|
||||||
RowSorter.SortKey[] sortKeys = {
|
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Ejectionchargedelay")));
|
||||||
new RowSorter.SortKey(ThrustCurveMotorColumns.DIAMETER.ordinal(), SortOrder.ASCENDING),
|
|
||||||
new RowSorter.SortKey(ThrustCurveMotorColumns.TOTAL_IMPULSE.ordinal(), SortOrder.ASCENDING),
|
delayBox = new JComboBox();
|
||||||
new RowSorter.SortKey(ThrustCurveMotorColumns.MANUFACTURER.ordinal(), SortOrder.ASCENDING)
|
delayBox.setEditable(true);
|
||||||
};
|
delayBox.addActionListener(new ActionListener() {
|
||||||
sorter.setSortKeys(Arrays.asList(sortKeys));
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
JComboBox cb = (JComboBox) e.getSource();
|
||||||
|
String sel = (String) cb.getSelectedItem();
|
||||||
|
//// None
|
||||||
|
if (sel.equalsIgnoreCase(trans.get("TCMotorSelPan.equalsIgnoreCase.None"))) {
|
||||||
|
selectedDelay = Motor.PLUGGED;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
selectedDelay = Double.parseDouble(sel);
|
||||||
|
} catch (NumberFormatException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setDelays(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
panel.add(delayBox, "growx");
|
||||||
|
//// (Number of seconds or \"None\")
|
||||||
|
panel.add(new StyledLabel(trans.get("TCMotorSelPan.lbl.NumberofsecondsorNone"), -3), "wrap para");
|
||||||
|
setDelays(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
sorter.setRowFilter(rowFilter);
|
// Search field
|
||||||
|
{
|
||||||
// Set selection and double-click listeners
|
//// Search:
|
||||||
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
StyledLabel label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Search"));
|
||||||
@Override
|
panel.add(label);
|
||||||
public void valueChanged(ListSelectionEvent e) {
|
searchField = new JTextField();
|
||||||
int row = table.getSelectedRow();
|
searchField.getDocument().addDocumentListener(new DocumentListener() {
|
||||||
if (row >= 0) {
|
@Override
|
||||||
row = table.convertRowIndexToModel(row);
|
public void changedUpdate(DocumentEvent e) {
|
||||||
ThrustCurveMotorSet motorSet = model.getMotorSet(row);
|
update();
|
||||||
log.info(Markers.USER_MARKER, "Selected table row " + row + ": " + motorSet);
|
|
||||||
if (motorSet != selectedMotorSet) {
|
|
||||||
select(selectMotor(motorSet));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.info(Markers.USER_MARKER, "Selected table row " + row + ", nothing selected");
|
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
private void update() {
|
||||||
|
String text = searchField.getText().trim();
|
||||||
|
String[] split = text.split("\\s+");
|
||||||
|
rowFilter.setSearchTerms(Arrays.asList(split));
|
||||||
|
sorter.sort();
|
||||||
|
scrollSelectionVisible();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
panel.add(searchField, "span, growx, wrap");
|
||||||
|
}
|
||||||
|
|
||||||
|
//// Motor selection table
|
||||||
|
{
|
||||||
|
table = new JTable(model);
|
||||||
|
|
||||||
|
// Set comparators and widths
|
||||||
|
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
sorter = new TableRowSorter<TableModel>(model);
|
||||||
|
for (int i = 0; i < ThrustCurveMotorColumns.values().length; i++) {
|
||||||
|
ThrustCurveMotorColumns column = ThrustCurveMotorColumns.values()[i];
|
||||||
|
sorter.setComparator(i, column.getComparator());
|
||||||
|
table.getColumnModel().getColumn(i).setPreferredWidth(column.getWidth());
|
||||||
}
|
}
|
||||||
});
|
table.setRowSorter(sorter);
|
||||||
table.addMouseListener(new MouseAdapter() {
|
// force initial sort order to by diameter, total impulse, manufacturer
|
||||||
@Override
|
{
|
||||||
public void mouseClicked(MouseEvent e) {
|
RowSorter.SortKey[] sortKeys = {
|
||||||
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
|
new RowSorter.SortKey(ThrustCurveMotorColumns.DIAMETER.ordinal(), SortOrder.ASCENDING),
|
||||||
if (dialog != null) {
|
new RowSorter.SortKey(ThrustCurveMotorColumns.TOTAL_IMPULSE.ordinal(), SortOrder.ASCENDING),
|
||||||
dialog.close(true);
|
new RowSorter.SortKey(ThrustCurveMotorColumns.MANUFACTURER.ordinal(), SortOrder.ASCENDING)
|
||||||
|
};
|
||||||
|
sorter.setSortKeys(Arrays.asList(sortKeys));
|
||||||
|
}
|
||||||
|
|
||||||
|
sorter.setRowFilter(rowFilter);
|
||||||
|
|
||||||
|
// Set selection and double-click listeners
|
||||||
|
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
int row = table.getSelectedRow();
|
||||||
|
if (row >= 0) {
|
||||||
|
row = table.convertRowIndexToModel(row);
|
||||||
|
ThrustCurveMotorSet motorSet = model.getMotorSet(row);
|
||||||
|
log.info(Markers.USER_MARKER, "Selected table row " + row + ": " + motorSet);
|
||||||
|
if (motorSet != selectedMotorSet) {
|
||||||
|
select(selectMotor(motorSet));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.info(Markers.USER_MARKER, "Selected table row " + row + ", nothing selected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
table.addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog.close(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JScrollPane scrollpane = new JScrollPane();
|
||||||
|
scrollpane.setViewportView(table);
|
||||||
|
panel.add(scrollpane, "grow, width :500:, height :300:, spanx, wrap para");
|
||||||
|
|
||||||
JScrollPane scrollpane = new JScrollPane();
|
}
|
||||||
scrollpane.setViewportView(table);
|
|
||||||
panel.add(scrollpane, "grow, width :500:, height :300:, spanx, wrap para");
|
|
||||||
|
|
||||||
|
//// Hide used motor files
|
||||||
{
|
{
|
||||||
final JCheckBox hideUsedBox = new JCheckBox(trans.get("TCMotorSelPan.checkbox.hideUsed"));
|
final JCheckBox hideUsedBox = new JCheckBox(trans.get("TCMotorSelPan.checkbox.hideUsed"));
|
||||||
GUIUtil.changeFontSize(hideUsedBox, -1);
|
GUIUtil.changeFontSize(hideUsedBox, -1);
|
||||||
@ -332,214 +324,33 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
panel.add(hideUsedBox, "gapleft para, spanx, growx, wrap para");
|
panel.add(hideUsedBox, "gapleft para, spanx, growx, wrap para");
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollSelectionVisible();
|
|
||||||
|
|
||||||
//// Hide very similar thrust curves
|
//// Hide very similar thrust curves
|
||||||
hideSimilarBox = new JCheckBox(trans.get("TCMotorSelPan.checkbox.hideSimilar"));
|
{
|
||||||
GUIUtil.changeFontSize(hideSimilarBox, -1);
|
hideSimilarBox = new JCheckBox(trans.get("TCMotorSelPan.checkbox.hideSimilar"));
|
||||||
hideSimilarBox.setSelected(Application.getPreferences().getBoolean(net.sf.openrocket.startup.Preferences.MOTOR_HIDE_SIMILAR, true));
|
GUIUtil.changeFontSize(hideSimilarBox, -1);
|
||||||
hideSimilarBox.addActionListener(new ActionListener() {
|
hideSimilarBox.setSelected(Application.getPreferences().getBoolean(net.sf.openrocket.startup.Preferences.MOTOR_HIDE_SIMILAR, true));
|
||||||
@Override
|
hideSimilarBox.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
@Override
|
||||||
Application.getPreferences().putBoolean(net.sf.openrocket.startup.Preferences.MOTOR_HIDE_SIMILAR, hideSimilarBox.isSelected());
|
public void actionPerformed(ActionEvent e) {
|
||||||
updateData();
|
Application.getPreferences().putBoolean(net.sf.openrocket.startup.Preferences.MOTOR_HIDE_SIMILAR, hideSimilarBox.isSelected());
|
||||||
}
|
updateData();
|
||||||
});
|
}
|
||||||
panel.add(hideSimilarBox, "gapleft para, spanx, growx, wrap para");
|
});
|
||||||
|
panel.add(hideSimilarBox, "gapleft para, spanx, growx, wrap para");
|
||||||
// Motor mount diameter label
|
}
|
||||||
//// Motor mount diameter:
|
|
||||||
diameterLabel = new StyledLabel();
|
|
||||||
panel.add(label, "gapright 30lp, spanx, split");
|
|
||||||
|
|
||||||
// Vertical split
|
// Vertical split
|
||||||
this.add(panel, "grow");
|
this.add(panel, "grow");
|
||||||
this.add(new JSeparator(JSeparator.VERTICAL), "growy, gap para para");
|
this.add(new JSeparator(JSeparator.VERTICAL), "growy, gap para para");
|
||||||
panel = new JPanel(new MigLayout("fill"));
|
|
||||||
|
|
||||||
|
JTabbedPane rightSide = new JTabbedPane();
|
||||||
|
rightSide.add(trans.get("TCMotorSelPan.btn.filter"), motorFilterPanel);
|
||||||
|
rightSide.add(trans.get("TCMotorSelPan.btn.details"), motorInformationPanel);
|
||||||
|
|
||||||
|
this.add(rightSide);
|
||||||
// Thrust curve selection
|
|
||||||
//// Select thrust curve:
|
|
||||||
curveSelectionLabel = new JLabel(trans.get("TCMotorSelPan.lbl.Selectthrustcurve"));
|
|
||||||
panel.add(curveSelectionLabel);
|
|
||||||
|
|
||||||
curveSelectionModel = new DefaultComboBoxModel();
|
|
||||||
curveSelectionBox = new JComboBox(curveSelectionModel);
|
|
||||||
curveSelectionBox.setRenderer(new CurveSelectionRenderer(curveSelectionBox.getRenderer()));
|
|
||||||
curveSelectionBox.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
Object value = curveSelectionBox.getSelectedItem();
|
|
||||||
if (value != null) {
|
|
||||||
select(((MotorHolder) value).getMotor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
panel.add(curveSelectionBox, "growx, wrap para");
|
|
||||||
|
|
||||||
// Ejection charge delay:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Ejectionchargedelay")));
|
|
||||||
|
|
||||||
delayBox = new JComboBox();
|
|
||||||
delayBox.setEditable(true);
|
|
||||||
delayBox.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
JComboBox cb = (JComboBox) e.getSource();
|
|
||||||
String sel = (String) cb.getSelectedItem();
|
|
||||||
//// None
|
|
||||||
if (sel.equalsIgnoreCase(trans.get("TCMotorSelPan.equalsIgnoreCase.None"))) {
|
|
||||||
selectedDelay = Motor.PLUGGED;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
selectedDelay = Double.parseDouble(sel);
|
|
||||||
} catch (NumberFormatException ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setDelays(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
panel.add(delayBox, "growx, wrap rel");
|
|
||||||
//// (Number of seconds or \"None\")
|
|
||||||
panel.add(new StyledLabel(trans.get("TCMotorSelPan.lbl.NumberofsecondsorNone"), -3), "skip, wrap para");
|
|
||||||
setDelays(false);
|
|
||||||
|
|
||||||
|
|
||||||
panel.add(new JSeparator(), "spanx, growx, wrap para");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Thrust curve info
|
|
||||||
//// Total impulse:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Totalimpulse")));
|
|
||||||
totalImpulseLabel = new JLabel();
|
|
||||||
panel.add(totalImpulseLabel, "split");
|
|
||||||
classificationLabel = new JLabel();
|
|
||||||
classificationLabel.setEnabled(false); // Gray out
|
|
||||||
panel.add(classificationLabel, "gapleft unrel, wrap");
|
|
||||||
|
|
||||||
//// Avg. thrust:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Avgthrust")));
|
|
||||||
avgThrustLabel = new JLabel();
|
|
||||||
panel.add(avgThrustLabel, "wrap");
|
|
||||||
|
|
||||||
//// Max. thrust:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Maxthrust")));
|
|
||||||
maxThrustLabel = new JLabel();
|
|
||||||
panel.add(maxThrustLabel, "wrap");
|
|
||||||
|
|
||||||
//// Burn time:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Burntime")));
|
|
||||||
burnTimeLabel = new JLabel();
|
|
||||||
panel.add(burnTimeLabel, "wrap");
|
|
||||||
|
|
||||||
//// Launch mass:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Launchmass")));
|
|
||||||
launchMassLabel = new JLabel();
|
|
||||||
panel.add(launchMassLabel, "wrap");
|
|
||||||
|
|
||||||
//// Empty mass:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Emptymass")));
|
|
||||||
emptyMassLabel = new JLabel();
|
|
||||||
panel.add(emptyMassLabel, "wrap");
|
|
||||||
|
|
||||||
//// Data points:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Datapoints")));
|
|
||||||
dataPointsLabel = new JLabel();
|
|
||||||
panel.add(dataPointsLabel, "wrap para");
|
|
||||||
|
|
||||||
if (System.getProperty("openrocket.debug.motordigest") != null) {
|
|
||||||
//// Digest:
|
|
||||||
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Digest")));
|
|
||||||
digestLabel = new JLabel();
|
|
||||||
panel.add(digestLabel, "w :300:, wrap para");
|
|
||||||
} else {
|
|
||||||
digestLabel = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
comment = new JTextArea(5, 5);
|
|
||||||
GUIUtil.changeFontSize(comment, -2);
|
|
||||||
withCommentFont = comment.getFont();
|
|
||||||
noCommentFont = withCommentFont.deriveFont(Font.ITALIC);
|
|
||||||
comment.setLineWrap(true);
|
|
||||||
comment.setWrapStyleWord(true);
|
|
||||||
comment.setEditable(false);
|
|
||||||
scrollpane = new JScrollPane(comment);
|
|
||||||
panel.add(scrollpane, "spanx, growx, wrap para");
|
|
||||||
|
|
||||||
// Thrust curve plot
|
|
||||||
chart = ChartFactory.createXYLineChart(
|
|
||||||
null, // title
|
|
||||||
null, // xAxisLabel
|
|
||||||
null, // yAxisLabel
|
|
||||||
null, // dataset
|
|
||||||
PlotOrientation.VERTICAL,
|
|
||||||
false, // legend
|
|
||||||
false, // tooltips
|
|
||||||
false // urls
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Add the data and formatting to the plot
|
|
||||||
XYPlot plot = chart.getXYPlot();
|
|
||||||
|
|
||||||
changeLabelFont(plot.getRangeAxis(), -2);
|
|
||||||
changeLabelFont(plot.getDomainAxis(), -2);
|
|
||||||
|
|
||||||
//// Thrust curve:
|
|
||||||
chart.setTitle(new TextTitle(trans.get("TCMotorSelPan.title.Thrustcurve"), this.getFont()));
|
|
||||||
chart.setBackgroundPaint(this.getBackground());
|
|
||||||
plot.setBackgroundPaint(Color.WHITE);
|
|
||||||
plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
|
|
||||||
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
|
|
||||||
|
|
||||||
chartPanel = new ChartPanel(chart,
|
|
||||||
false, // properties
|
|
||||||
false, // save
|
|
||||||
false, // print
|
|
||||||
false, // zoom
|
|
||||||
false); // tooltips
|
|
||||||
chartPanel.setMouseZoomable(false);
|
|
||||||
chartPanel.setPopupMenu(null);
|
|
||||||
chartPanel.setMouseWheelEnabled(false);
|
|
||||||
chartPanel.setRangeZoomable(false);
|
|
||||||
chartPanel.setDomainZoomable(false);
|
|
||||||
|
|
||||||
chartPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
|
||||||
chartPanel.addMouseListener(new MouseAdapter() {
|
|
||||||
@Override
|
|
||||||
public void mouseClicked(MouseEvent e) {
|
|
||||||
if (selectedMotor == null || selectedMotorSet == null)
|
|
||||||
return;
|
|
||||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
|
||||||
// Open plot dialog
|
|
||||||
List<ThrustCurveMotor> motors = getFilteredCurves();
|
|
||||||
ThrustCurveMotorPlotDialog plotDialog = new ThrustCurveMotorPlotDialog(motors,
|
|
||||||
motors.indexOf(selectedMotor),
|
|
||||||
SwingUtilities.getWindowAncestor(ThrustCurveMotorSelectionPanel.this));
|
|
||||||
plotDialog.setVisible(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
JLayeredPane layer = new CustomLayeredPane();
|
|
||||||
|
|
||||||
layer.setBorder(BorderFactory.createLineBorder(Color.BLUE));
|
|
||||||
|
|
||||||
layer.add(chartPanel, (Integer) 0);
|
|
||||||
|
|
||||||
zoomIcon = new JLabel(Icons.ZOOM_IN);
|
|
||||||
zoomIcon.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
|
||||||
layer.add(zoomIcon, (Integer) 1);
|
|
||||||
|
|
||||||
|
|
||||||
panel.add(layer, "width 300:300:, height 180:180:, grow, spanx");
|
|
||||||
|
|
||||||
this.add(panel, "grow");
|
|
||||||
|
|
||||||
// Update the panel data
|
// Update the panel data
|
||||||
|
scrollSelectionVisible();
|
||||||
updateData();
|
updateData();
|
||||||
setDelays(false);
|
setDelays(false);
|
||||||
|
|
||||||
@ -548,6 +359,10 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
public void setMotorMountAndConfig( MotorMount mount, String currentConfig ) {
|
public void setMotorMountAndConfig( MotorMount mount, String currentConfig ) {
|
||||||
double diameter = 0;
|
double diameter = 0;
|
||||||
|
|
||||||
|
if ( mount != null ) {
|
||||||
|
diameter = mount.getMotorMountDiameter();
|
||||||
|
}
|
||||||
|
|
||||||
if (currentConfig != null && mount != null) {
|
if (currentConfig != null && mount != null) {
|
||||||
MotorConfiguration motorConf = mount.getMotorConfiguration().get(currentConfig);
|
MotorConfiguration motorConf = mount.getMotorConfiguration().get(currentConfig);
|
||||||
selectedMotor = (ThrustCurveMotor) motorConf.getMotor();
|
selectedMotor = (ThrustCurveMotor) motorConf.getMotor();
|
||||||
@ -576,10 +391,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
updateData();
|
updateData();
|
||||||
setDelays(true);
|
setDelays(true);
|
||||||
|
|
||||||
diameterLabel.setText(trans.get("TCMotorSelPan.lbl.Motormountdia") + " " +
|
motorFilterPanel.setMotorMount(mount);
|
||||||
UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit().toStringUnit(0));
|
|
||||||
|
|
||||||
rowFilter.setMotorMount(mount);
|
|
||||||
scrollSelectionVisible();
|
scrollSelectionVisible();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -629,13 +441,6 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void changeLabelFont(ValueAxis axis, float size) {
|
|
||||||
Font font = axis.getTickLabelFont();
|
|
||||||
font = font.deriveFont(font.getSize2D() + size);
|
|
||||||
axis.setTickLabelFont(font);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a different motor is selected from within the panel.
|
* Called when a different motor is selected from within the panel.
|
||||||
*/
|
*/
|
||||||
@ -666,30 +471,14 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
curveSelectionModel.removeAllElements();
|
curveSelectionModel.removeAllElements();
|
||||||
curveSelectionBox.setEnabled(false);
|
curveSelectionBox.setEnabled(false);
|
||||||
curveSelectionLabel.setEnabled(false);
|
curveSelectionLabel.setEnabled(false);
|
||||||
totalImpulseLabel.setText("");
|
motorInformationPanel.clearData();
|
||||||
totalImpulseLabel.setToolTipText(null);
|
|
||||||
classificationLabel.setText("");
|
|
||||||
classificationLabel.setToolTipText(null);
|
|
||||||
avgThrustLabel.setText("");
|
|
||||||
maxThrustLabel.setText("");
|
|
||||||
burnTimeLabel.setText("");
|
|
||||||
launchMassLabel.setText("");
|
|
||||||
emptyMassLabel.setText("");
|
|
||||||
dataPointsLabel.setText("");
|
|
||||||
if (digestLabel != null) {
|
|
||||||
digestLabel.setText("");
|
|
||||||
}
|
|
||||||
setComment("");
|
|
||||||
chart.getXYPlot().setDataset(new XYSeriesCollection());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check which thrust curves to display
|
// Check which thrust curves to display
|
||||||
List<ThrustCurveMotor> motors = getFilteredCurves();
|
List<ThrustCurveMotor> motors = getFilteredCurves();
|
||||||
final int index = motors.indexOf(selectedMotor);
|
final int index = motors.indexOf(selectedMotor);
|
||||||
|
|
||||||
|
|
||||||
// Update the thrust curve selection box
|
// Update the thrust curve selection box
|
||||||
curveSelectionModel.removeAllElements();
|
curveSelectionModel.removeAllElements();
|
||||||
for (int i = 0; i < motors.size(); i++) {
|
for (int i = 0; i < motors.size(); i++) {
|
||||||
@ -705,60 +494,11 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
curveSelectionLabel.setEnabled(false);
|
curveSelectionLabel.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
motorInformationPanel.updateData(motors, selectedMotor);
|
||||||
|
|
||||||
// Update thrust curve data
|
|
||||||
double impulse = selectedMotor.getTotalImpulseEstimate();
|
|
||||||
MotorClass mc = MotorClass.getMotorClass(impulse);
|
|
||||||
totalImpulseLabel.setText(UnitGroup.UNITS_IMPULSE.getDefaultUnit().toStringUnit(impulse));
|
|
||||||
classificationLabel.setText("(" + mc.getDescription(impulse) + ")");
|
|
||||||
totalImpulseLabel.setToolTipText(mc.getClassDescription());
|
|
||||||
classificationLabel.setToolTipText(mc.getClassDescription());
|
|
||||||
|
|
||||||
avgThrustLabel.setText(UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit(
|
|
||||||
selectedMotor.getAverageThrustEstimate()));
|
|
||||||
maxThrustLabel.setText(UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit(
|
|
||||||
selectedMotor.getMaxThrustEstimate()));
|
|
||||||
burnTimeLabel.setText(UnitGroup.UNITS_SHORT_TIME.getDefaultUnit().toStringUnit(
|
|
||||||
selectedMotor.getBurnTimeEstimate()));
|
|
||||||
launchMassLabel.setText(UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
|
|
||||||
selectedMotor.getLaunchCG().weight));
|
|
||||||
emptyMassLabel.setText(UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
|
|
||||||
selectedMotor.getEmptyCG().weight));
|
|
||||||
dataPointsLabel.setText("" + (selectedMotor.getTimePoints().length - 1));
|
|
||||||
if (digestLabel != null) {
|
|
||||||
digestLabel.setText(selectedMotor.getDigest());
|
|
||||||
}
|
|
||||||
|
|
||||||
setComment(selectedMotor.getDescription());
|
|
||||||
|
|
||||||
|
|
||||||
// Update the plot
|
|
||||||
XYPlot plot = chart.getXYPlot();
|
|
||||||
|
|
||||||
XYSeriesCollection dataset = new XYSeriesCollection();
|
|
||||||
for (int i = 0; i < motors.size(); i++) {
|
|
||||||
ThrustCurveMotor m = motors.get(i);
|
|
||||||
|
|
||||||
//// Thrust
|
|
||||||
XYSeries series = new XYSeries(trans.get("TCMotorSelPan.title.Thrust") + " (" + i + ")");
|
|
||||||
double[] time = m.getTimePoints();
|
|
||||||
double[] thrust = m.getThrustPoints();
|
|
||||||
|
|
||||||
for (int j = 0; j < time.length; j++) {
|
|
||||||
series.add(time[j], thrust[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
dataset.addSeries(series);
|
|
||||||
|
|
||||||
boolean selected = (i == index);
|
|
||||||
plot.getRenderer().setSeriesStroke(i, new BasicStroke(selected ? 3 : 1));
|
|
||||||
plot.getRenderer().setSeriesPaint(i, getColor(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
plot.setDataset(dataset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ThrustCurveMotor> getFilteredCurves() {
|
List<ThrustCurveMotor> getFilteredCurves() {
|
||||||
List<ThrustCurveMotor> motors = selectedMotorSet.getMotors();
|
List<ThrustCurveMotor> motors = selectedMotorSet.getMotors();
|
||||||
if (hideSimilarBox.isSelected()) {
|
if (hideSimilarBox.isSelected()) {
|
||||||
List<ThrustCurveMotor> filtered = new ArrayList<ThrustCurveMotor>(motors.size());
|
List<ThrustCurveMotor> filtered = new ArrayList<ThrustCurveMotor>(motors.size());
|
||||||
@ -784,21 +524,6 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setComment(String s) {
|
|
||||||
s = s.trim();
|
|
||||||
if (s.length() == 0) {
|
|
||||||
//// No description available.
|
|
||||||
comment.setText(trans.get("TCMotorSelPan.noDescription"));
|
|
||||||
comment.setFont(noCommentFont);
|
|
||||||
comment.setForeground(NO_COMMENT_COLOR);
|
|
||||||
} else {
|
|
||||||
comment.setText(s);
|
|
||||||
comment.setFont(withCommentFont);
|
|
||||||
comment.setForeground(WITH_COMMENT_COLOR);
|
|
||||||
}
|
|
||||||
comment.setCaretPosition(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scrollSelectionVisible() {
|
private void scrollSelectionVisible() {
|
||||||
if (selectedMotorSet != null) {
|
if (selectedMotorSet != null) {
|
||||||
int index = table.convertRowIndexToView(model.getIndex(selectedMotorSet));
|
int index = table.convertRowIndexToView(model.getIndex(selectedMotorSet));
|
||||||
@ -920,9 +645,6 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
|
|
||||||
|
|
||||||
@ -950,18 +672,4 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom layered pane that sets the bounds of the components on every layout.
|
|
||||||
*/
|
|
||||||
public class CustomLayeredPane extends JLayeredPane {
|
|
||||||
@Override
|
|
||||||
public void doLayout() {
|
|
||||||
synchronized (getTreeLock()) {
|
|
||||||
int w = getWidth();
|
|
||||||
int h = getHeight();
|
|
||||||
chartPanel.setBounds(0, 0, w, h);
|
|
||||||
zoomIcon.setBounds(w - ZOOM_ICON_POSITION_NEGATIVE_X, ZOOM_ICON_POSITION_POSITIVE_Y, 50, 50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user