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.checkbox.hideSimilar = Hide very similar thrust curves
|
||||
TCMotorSelPan.checkbox.hideUsed = Hide motors already used in the mount
|
||||
TCMotorSelPan.btn.details = Show Details
|
||||
TCMotorSelPan.btn.filter = Filter Motors
|
||||
TCMotorSelPan.SHOW_DESCRIPTIONS.desc1 = Show all motors
|
||||
TCMotorSelPan.SHOW_DESCRIPTIONS.desc2 = Show motors with diameter less than that of the motor mount
|
||||
|
@ -1,251 +1,287 @@
|
||||
package net.sf.openrocket.gui.dialogs.motor.thrustcurve;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.gui.util.CheckList;
|
||||
import net.sf.openrocket.gui.util.GUIUtil;
|
||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.motor.Manufacturer;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
|
||||
import com.itextpdf.text.Font;
|
||||
|
||||
public abstract class MotorFilterPopupMenu extends JPopupMenu {
|
||||
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
private final CheckList<Manufacturer> manufacturerCheckList;
|
||||
|
||||
private final CheckList<ImpulseClass> impulseCheckList;
|
||||
|
||||
private final MotorRowFilter filter;
|
||||
|
||||
private int showMode = SHOW_ALL;
|
||||
|
||||
private static final int SHOW_ALL = 0;
|
||||
private static final int SHOW_SMALLER = 1;
|
||||
private static final int SHOW_EXACT = 2;
|
||||
private static final int SHOW_MAX = 2;
|
||||
|
||||
|
||||
public MotorFilterPopupMenu(Collection<Manufacturer> allManufacturers, MotorRowFilter filter ) {
|
||||
|
||||
this.filter = filter;
|
||||
|
||||
showMode = Application.getPreferences().getChoice(net.sf.openrocket.startup.Preferences.MOTOR_DIAMETER_FILTER, MotorFilterPopupMenu.SHOW_MAX, MotorFilterPopupMenu.SHOW_EXACT);
|
||||
List<Manufacturer> unselectedManusFromPreferences = ((SwingPreferences) Application.getPreferences()).getExcludedMotorManufacturers();
|
||||
|
||||
// Manufacturer selection
|
||||
JPanel sub = new JPanel(new MigLayout("fill"));
|
||||
TitledBorder border = BorderFactory.createTitledBorder(trans.get("TCurveMotorCol.MANUFACTURER"));
|
||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
||||
sub.setBorder(border);
|
||||
|
||||
JPanel root = new JPanel(new MigLayout("fill", "[grow]"));
|
||||
root.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
|
||||
|
||||
List<Manufacturer> manufacturers = new ArrayList<Manufacturer>();
|
||||
for (Manufacturer m : allManufacturers) {
|
||||
manufacturers.add(m);
|
||||
}
|
||||
|
||||
Collections.sort(manufacturers, new Comparator<Manufacturer>() {
|
||||
@Override
|
||||
public int compare(Manufacturer o1, Manufacturer o2) {
|
||||
return o1.getSimpleName().compareTo( o2.getSimpleName());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
manufacturerCheckList = new CheckList.Builder().<Manufacturer>build();
|
||||
manufacturerCheckList.setData(manufacturers);
|
||||
|
||||
manufacturerCheckList.setUncheckedItems(unselectedManusFromPreferences);
|
||||
filter.setExcludedManufacturers(unselectedManusFromPreferences);
|
||||
manufacturerCheckList.getModel().addListDataListener( new ListDataListener() {
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void intervalRemoved(ListDataEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
MotorFilterPopupMenu.this.filter.setExcludedManufacturers( manufacturerCheckList.getUncheckedItems() );
|
||||
onSelectionChanged();
|
||||
}
|
||||
});
|
||||
|
||||
sub.add(new JScrollPane(manufacturerCheckList.getList()), "grow,wrap");
|
||||
|
||||
JButton clearMotors = new JButton(trans.get("TCMotorSelPan.btn.checkNone"));
|
||||
clearMotors.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPopupMenu.this.manufacturerCheckList.clearAll();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
sub.add(clearMotors,"split 2");
|
||||
|
||||
JButton selectMotors = new JButton(trans.get("TCMotorSelPan.btn.checkAll"));
|
||||
selectMotors.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPopupMenu.this.manufacturerCheckList.checkAll();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
sub.add(selectMotors,"wrap");
|
||||
|
||||
root.add(sub,"grow, wrap");
|
||||
|
||||
// Impulse selection
|
||||
sub = new JPanel(new MigLayout("fill"));
|
||||
border = BorderFactory.createTitledBorder(trans.get("TCurveMotorCol.TOTAL_IMPULSE"));
|
||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
||||
sub.setBorder(border);
|
||||
|
||||
impulseCheckList = new CheckList.Builder().<ImpulseClass>build();
|
||||
impulseCheckList.setData(Arrays.asList(ImpulseClass.values()));
|
||||
impulseCheckList.checkAll();
|
||||
impulseCheckList.getModel().addListDataListener( new ListDataListener() {
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void intervalRemoved(ListDataEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
MotorFilterPopupMenu.this.filter.setExcludedImpulseClasses( impulseCheckList.getUncheckedItems() );
|
||||
onSelectionChanged();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
sub.add(new JScrollPane(impulseCheckList.getList()), "grow,wrap");
|
||||
|
||||
JButton clearImpulse = new JButton(trans.get("TCMotorSelPan.btn.checkNone"));
|
||||
clearImpulse.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPopupMenu.this.impulseCheckList.clearAll();
|
||||
|
||||
}
|
||||
});
|
||||
sub.add(clearImpulse,"split 2");
|
||||
|
||||
JButton selectImpulse = new JButton(trans.get("TCMotorSelPan.btn.checkAll"));
|
||||
selectImpulse.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPopupMenu.this.impulseCheckList.checkAll();
|
||||
|
||||
}
|
||||
});
|
||||
sub.add(selectImpulse,"wrap");
|
||||
|
||||
root.add(sub,"grow, wrap");
|
||||
|
||||
// Diameter selection
|
||||
|
||||
sub = new JPanel(new MigLayout("fill"));
|
||||
border = BorderFactory.createTitledBorder(trans.get("TCurveMotorCol.DIAMETER"));
|
||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
||||
sub.setBorder(border);
|
||||
|
||||
JRadioButton showAllDiametersButton = new JRadioButton( trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc1") );
|
||||
showAllDiametersButton.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showMode = SHOW_ALL;
|
||||
MotorFilterPopupMenu.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.ALL);
|
||||
onSelectionChanged();
|
||||
}
|
||||
});
|
||||
showAllDiametersButton.setSelected( showMode == SHOW_ALL);
|
||||
sub.add(showAllDiametersButton, "growx,wrap");
|
||||
|
||||
JRadioButton showSmallerDiametersButton = new JRadioButton( trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc2") );
|
||||
showSmallerDiametersButton.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showMode = SHOW_SMALLER;
|
||||
MotorFilterPopupMenu.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.SMALLER);
|
||||
onSelectionChanged();
|
||||
}
|
||||
});
|
||||
showSmallerDiametersButton.setSelected( showMode == SHOW_SMALLER);
|
||||
sub.add(showSmallerDiametersButton, "growx,wrap");
|
||||
|
||||
JRadioButton showExactDiametersButton = new JRadioButton( trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc3") );
|
||||
showExactDiametersButton.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showMode = SHOW_EXACT;
|
||||
MotorFilterPopupMenu.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.EXACT);
|
||||
onSelectionChanged();
|
||||
}
|
||||
});
|
||||
showExactDiametersButton.setSelected( showMode == SHOW_EXACT );
|
||||
sub.add(showExactDiametersButton, "growx,wrap");
|
||||
|
||||
root.add(sub, "grow,wrap");
|
||||
ButtonGroup comboGroup = new ButtonGroup();
|
||||
comboGroup.add( showAllDiametersButton );
|
||||
comboGroup.add( showSmallerDiametersButton );
|
||||
comboGroup.add( showExactDiametersButton );
|
||||
|
||||
|
||||
// Close button
|
||||
JButton closeButton = new JButton(trans.get("TCMotorSelPan.btn.close"));
|
||||
closeButton.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPopupMenu.this.onClose();
|
||||
}
|
||||
|
||||
});
|
||||
root.add(closeButton, "split 2");
|
||||
|
||||
this.add(root);
|
||||
|
||||
}
|
||||
|
||||
public void onClose() {
|
||||
|
||||
((SwingPreferences) Application.getPreferences()).setExcludedMotorManufacturers(filter.getExcludedManufacturers());
|
||||
|
||||
Application.getPreferences().putChoice("MotorDiameterMatch", showMode );
|
||||
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
public abstract void onSelectionChanged();
|
||||
|
||||
}
|
||||
package net.sf.openrocket.gui.dialogs.motor.thrustcurve;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
|
||||
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.GUIUtil;
|
||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.motor.Manufacturer;
|
||||
import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
|
||||
import com.itextpdf.text.Font;
|
||||
|
||||
public abstract class MotorFilterPanel extends JPanel {
|
||||
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
private final CheckList<Manufacturer> manufacturerCheckList;
|
||||
|
||||
private final CheckList<ImpulseClass> impulseCheckList;
|
||||
|
||||
private final MotorRowFilter filter;
|
||||
private final TitledBorder diameterTitleBorder;
|
||||
private final DoubleModel mountDiameter = new DoubleModel(1);
|
||||
|
||||
private int showMode = SHOW_ALL;
|
||||
|
||||
private static final int SHOW_ALL = 0;
|
||||
private static final int SHOW_SMALLER = 1;
|
||||
private static final int SHOW_EXACT = 2;
|
||||
private static final int SHOW_MAX = 2;
|
||||
|
||||
public MotorFilterPanel(Collection<Manufacturer> allManufacturers, MotorRowFilter filter ) {
|
||||
super(new MigLayout("fill", "[grow]"));
|
||||
this.filter = filter;
|
||||
|
||||
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();
|
||||
filter.setExcludedManufacturers(unselectedManusFromPreferences);
|
||||
|
||||
// Manufacturer selection
|
||||
JPanel sub = new JPanel(new MigLayout("fill"));
|
||||
TitledBorder border = BorderFactory.createTitledBorder(trans.get("TCurveMotorCol.MANUFACTURER"));
|
||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
||||
sub.setBorder(border);
|
||||
|
||||
this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
|
||||
|
||||
List<Manufacturer> manufacturers = new ArrayList<Manufacturer>();
|
||||
for (Manufacturer m : allManufacturers) {
|
||||
manufacturers.add(m);
|
||||
}
|
||||
|
||||
Collections.sort(manufacturers, new Comparator<Manufacturer>() {
|
||||
@Override
|
||||
public int compare(Manufacturer o1, Manufacturer o2) {
|
||||
return o1.getSimpleName().compareTo( o2.getSimpleName());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
manufacturerCheckList = new CheckList.Builder().<Manufacturer>build();
|
||||
manufacturerCheckList.setData(manufacturers);
|
||||
|
||||
manufacturerCheckList.setUncheckedItems(unselectedManusFromPreferences);
|
||||
manufacturerCheckList.getModel().addListDataListener( new ListDataListener() {
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void intervalRemoved(ListDataEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
MotorFilterPanel.this.filter.setExcludedManufacturers( manufacturerCheckList.getUncheckedItems() );
|
||||
onSelectionChanged();
|
||||
}
|
||||
});
|
||||
|
||||
sub.add(new JScrollPane(manufacturerCheckList.getList()), "grow,wrap");
|
||||
|
||||
JButton clearMotors = new JButton(trans.get("TCMotorSelPan.btn.checkNone"));
|
||||
clearMotors.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPanel.this.manufacturerCheckList.clearAll();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
sub.add(clearMotors,"split 2");
|
||||
|
||||
JButton selectMotors = new JButton(trans.get("TCMotorSelPan.btn.checkAll"));
|
||||
selectMotors.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPanel.this.manufacturerCheckList.checkAll();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
sub.add(selectMotors,"wrap");
|
||||
|
||||
this.add(sub,"grow, wrap");
|
||||
|
||||
// Impulse selection
|
||||
sub = new JPanel(new MigLayout("fill"));
|
||||
border = BorderFactory.createTitledBorder(trans.get("TCurveMotorCol.TOTAL_IMPULSE"));
|
||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
||||
sub.setBorder(border);
|
||||
|
||||
impulseCheckList = new CheckList.Builder().<ImpulseClass>build();
|
||||
impulseCheckList.setData(Arrays.asList(ImpulseClass.values()));
|
||||
impulseCheckList.checkAll();
|
||||
impulseCheckList.getModel().addListDataListener( new ListDataListener() {
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void intervalRemoved(ListDataEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
MotorFilterPanel.this.filter.setExcludedImpulseClasses( impulseCheckList.getUncheckedItems() );
|
||||
onSelectionChanged();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
sub.add(new JScrollPane(impulseCheckList.getList()), "grow,wrap");
|
||||
|
||||
JButton clearImpulse = new JButton(trans.get("TCMotorSelPan.btn.checkNone"));
|
||||
clearImpulse.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPanel.this.impulseCheckList.clearAll();
|
||||
|
||||
}
|
||||
});
|
||||
sub.add(clearImpulse,"split 2");
|
||||
|
||||
JButton selectImpulse = new JButton(trans.get("TCMotorSelPan.btn.checkAll"));
|
||||
selectImpulse.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MotorFilterPanel.this.impulseCheckList.checkAll();
|
||||
|
||||
}
|
||||
});
|
||||
sub.add(selectImpulse,"wrap");
|
||||
|
||||
this.add(sub,"grow, wrap");
|
||||
|
||||
// Diameter selection
|
||||
|
||||
sub = new JPanel(new MigLayout("fill"));
|
||||
diameterTitleBorder = BorderFactory.createTitledBorder(trans.get("TCurveMotorCol.DIAMETER"));
|
||||
GUIUtil.changeFontStyle(diameterTitleBorder, Font.BOLD);
|
||||
sub.setBorder(diameterTitleBorder);
|
||||
|
||||
JRadioButton showAllDiametersButton = new JRadioButton( trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc1") );
|
||||
showAllDiametersButton.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showMode = SHOW_ALL;
|
||||
MotorFilterPanel.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.ALL);
|
||||
saveMotorDiameterMatchPrefence();
|
||||
onSelectionChanged();
|
||||
}
|
||||
});
|
||||
showAllDiametersButton.setSelected( showMode == SHOW_ALL);
|
||||
sub.add(showAllDiametersButton, "growx,wrap");
|
||||
|
||||
JRadioButton showSmallerDiametersButton = new JRadioButton( trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc2") );
|
||||
showSmallerDiametersButton.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showMode = SHOW_SMALLER;
|
||||
MotorFilterPanel.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.SMALLER);
|
||||
saveMotorDiameterMatchPrefence();
|
||||
onSelectionChanged();
|
||||
}
|
||||
});
|
||||
showSmallerDiametersButton.setSelected( showMode == SHOW_SMALLER);
|
||||
sub.add(showSmallerDiametersButton, "growx,wrap");
|
||||
|
||||
JRadioButton showExactDiametersButton = new JRadioButton( trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc3") );
|
||||
showExactDiametersButton.addActionListener( new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showMode = SHOW_EXACT;
|
||||
MotorFilterPanel.this.filter.setDiameterControl(MotorRowFilter.DiameterFilterControl.EXACT);
|
||||
saveMotorDiameterMatchPrefence();
|
||||
onSelectionChanged();
|
||||
}
|
||||
});
|
||||
showExactDiametersButton.setSelected( showMode == SHOW_EXACT );
|
||||
sub.add(showExactDiametersButton, "growx,wrap");
|
||||
ButtonGroup comboGroup = new ButtonGroup();
|
||||
comboGroup.add( showAllDiametersButton );
|
||||
comboGroup.add( showSmallerDiametersButton );
|
||||
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");
|
||||
|
||||
sub.add(new UnitSelector(minDiameter));
|
||||
sub.add(new BasicSlider(minDiameter.getSliderModel(0,0.5, mountDiameter)), "w 100lp, wrap");
|
||||
}
|
||||
this.add(sub, "grow,wrap");
|
||||
|
||||
}
|
||||
|
||||
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()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void saveMotorDiameterMatchPrefence() {
|
||||
Application.getPreferences().putChoice("MotorDiameterMatch", showMode );
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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();
|
||||
|
||||
// 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() {
|
||||
return diameterControl;
|
||||
}
|
||||
@ -130,6 +141,13 @@ class MotorRowFilter extends RowFilter<TableModel, Integer> {
|
||||
}
|
||||
|
||||
private boolean filterByDiameter(ThrustCurveMotorSet m) {
|
||||
|
||||
if ( minimumDiameter != null ) {
|
||||
if ( m.getDiameter() <= minimumDiameter - 0.0015 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (diameter == null) {
|
||||
return true;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user