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.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Hashtable; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; 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.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.gui.widgets.MultiSlider; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.motor.Manufacturer; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.RocketComponent; 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 static Hashtable diameterLabels = new Hashtable(); private static double[] diameterValues = new double[] { 0, .013, .018, .024, .029, .038, .054, .075, .098, 1.000 }; static { for( int i = 0; i< diameterValues.length; i++ ) { if( i == diameterValues.length-1) { diameterLabels.put( i, new JLabel("+")); } else { diameterLabels.put( i, new JLabel(UnitGroup.UNITS_MOTOR_DIMENSIONS.toString(diameterValues[i]))); } } } private static Hashtable impulseLabels = new Hashtable(); static { int i =0; for( ImpulseClass impulseClass : ImpulseClass.values() ) { impulseLabels.put(i, new JLabel( impulseClass.name() )); i++; } } private final CheckList<Manufacturer> manufacturerCheckList; private final MotorRowFilter filter; private final JCheckBox limitLengthCheckBox; private boolean limitLength = false; private Double mountLength = null; private final JCheckBox limitDiameterCheckBox; private boolean limitDiameter = false; private Double mountDiameter = null; // Things we change the label on based on the MotorMount. private final JLabel motorMountDimension; private final MultiSlider lengthSlider; private final MultiSlider diameterSlider; public MotorFilterPanel(Collection<Manufacturer> allManufacturers, MotorRowFilter filter ) { super(new MigLayout("fill", "[grow]")); this.filter = filter; List<Manufacturer> unselectedManusFromPreferences = ((SwingPreferences) Application.getPreferences()).getExcludedMotorManufacturers(); filter.setExcludedManufacturers(unselectedManusFromPreferences); limitLength = ((SwingPreferences) Application.getPreferences()).getBoolean("motorFilterLimitLength", false); limitDiameter = ((SwingPreferences) Application.getPreferences()).getBoolean("motorFilterLimitDiameter", false); //// Hide used motor files { final JCheckBox hideUsedBox = new JCheckBox(trans.get("TCMotorSelPan.checkbox.hideUsed")); GUIUtil.changeFontSize(hideUsedBox, -1); hideUsedBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { MotorFilterPanel.this.filter.setHideUsedMotors(hideUsedBox.isSelected()); onSelectionChanged(); } }); this.add(hideUsedBox, "gapleft para, spanx, growx, wrap"); } // 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) { Collection<Manufacturer> uncheckedManufacturers = manufacturerCheckList.getUncheckedItems(); MotorFilterPanel.this.filter.setExcludedManufacturers( uncheckedManufacturers ); ((SwingPreferences) Application.getPreferences()).setExcludedMotorManufacturers(uncheckedManufacturers); 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); final MultiSlider impulseSlider = new MultiSlider(MultiSlider.HORIZONTAL,0, ImpulseClass.values().length-1,0, ImpulseClass.values().length-1); impulseSlider.setBounded(true); // thumbs cannot cross impulseSlider.setMajorTickSpacing(1); impulseSlider.setPaintTicks(true); impulseSlider.setLabelTable(impulseLabels); impulseSlider.setPaintLabels(true); impulseSlider.addChangeListener( new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { int minimpulse = impulseSlider.getValueAt(0); MotorFilterPanel.this.filter.setMinimumImpulse(ImpulseClass.values()[minimpulse]); int maximpulse = impulseSlider.getValueAt(1); MotorFilterPanel.this.filter.setMaximumImpulse(ImpulseClass.values()[maximpulse]); onSelectionChanged(); } }); sub.add( impulseSlider, "growx, wrap"); } this.add(sub,"grow, wrap"); // Motor Dimensions sub = new JPanel(new MigLayout("fill")); TitledBorder diameterTitleBorder = BorderFactory.createTitledBorder(trans.get("TCMotorSelPan.MotorSize")); GUIUtil.changeFontStyle(diameterTitleBorder, Font.BOLD); sub.setBorder(diameterTitleBorder); motorMountDimension = new JLabel(); GUIUtil.changeFontSize(motorMountDimension, -1); sub.add(motorMountDimension,"growx,wrap"); // Diameter selection { sub.add( new JLabel(trans.get("TCMotorSelPan.Diameter")), "split 2, wrap"); limitDiameterCheckBox = new JCheckBox( trans.get("TCMotorSelPan.checkbox.limitdiameter")); GUIUtil.changeFontSize(limitDiameterCheckBox, -1); limitDiameterCheckBox.setSelected(limitDiameter); limitDiameterCheckBox.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { limitDiameter = limitDiameterCheckBox.isSelected(); MotorFilterPanel.this.setLimitDiameter(); onSelectionChanged(); } }); sub.add( limitDiameterCheckBox, "gapleft para, spanx, growx, wrap" ); diameterSlider = new MultiSlider(MultiSlider.HORIZONTAL,0, diameterValues.length-1, 0, diameterValues.length-1); diameterSlider.setBounded(true); // thumbs cannot cross diameterSlider.setMajorTickSpacing(1); diameterSlider.setPaintTicks(true); diameterSlider.setLabelTable(diameterLabels); diameterSlider.setPaintLabels(true); diameterSlider.addChangeListener( new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { int minDiameter = diameterSlider.getValueAt(0); MotorFilterPanel.this.filter.setMinimumDiameter(diameterValues[minDiameter]); int maxDiameter = diameterSlider.getValueAt(1); if( maxDiameter == diameterValues.length-1 ) { MotorFilterPanel.this.filter.setMaximumDiameter(null); } else { MotorFilterPanel.this.filter.setMaximumDiameter(diameterValues[maxDiameter]); } onSelectionChanged(); } }); sub.add( diameterSlider, "growx, wrap"); } { sub.add( new JLabel(trans.get("TCMotorSelPan.Length")), "split 2, wrap"); limitLengthCheckBox = new JCheckBox( trans.get("TCMotorSelPan.checkbox.limitlength")); GUIUtil.changeFontSize(limitLengthCheckBox, -1); limitLengthCheckBox.setSelected(limitLength); limitLengthCheckBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { limitLength = limitLengthCheckBox.isSelected(); MotorFilterPanel.this.setLimitLength(); onSelectionChanged(); } }); sub.add( limitLengthCheckBox, "gapleft para, spanx, growx, wrap" ); final DoubleModel minimumLength = new DoubleModel(filter, "MinimumLength", UnitGroup.UNITS_MOTOR_DIMENSIONS, 0); final DoubleModel maximumLength = new DoubleModel(filter, "MaximumLength", UnitGroup.UNITS_MOTOR_DIMENSIONS, 0); JSpinner spin = new JSpinner(minimumLength.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); sub.add(spin, "split 5, growx"); sub.add(new UnitSelector(minimumLength), ""); lengthSlider = new MultiSlider(MultiSlider.HORIZONTAL,0, 1000, 0, 1000); lengthSlider.setBounded(true); // thumbs cannot cross lengthSlider.setMajorTickSpacing(100); lengthSlider.setPaintTicks(true); lengthSlider.setLabelTable(diameterLabels); lengthSlider.addChangeListener( new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { int minLength = lengthSlider.getValueAt(0); minimumLength.setValue(minLength/1000.0); int maxLength = lengthSlider.getValueAt(1); maximumLength.setValue(maxLength/1000.0); onSelectionChanged(); } }); minimumLength.addChangeListener( new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { lengthSlider.setValueAt(0, (int)(1000* minimumLength.getValue())); lengthSlider.setValueAt(1, (int) (1000* maximumLength.getValue())); } }); sub.add( lengthSlider, "growx"); spin = new JSpinner(maximumLength.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); sub.add(spin, "growx"); sub.add(new UnitSelector(maximumLength), "wrap"); } this.add(sub, "grow,wrap"); } public void setMotorMount( MotorMount mount ) { filter.setMotorMount(mount); onSelectionChanged(); if ( mount == null ) { // Disable diameter controls? mountLength = null; mountDiameter = null; motorMountDimension.setText(""); } else { mountLength = ((RocketComponent)mount).getLength(); mountDiameter = mount.getMotorMountDiameter(); motorMountDimension.setText( trans.get("TCMotorSelPan.MotorMountDimensions") + " " + UnitGroup.UNITS_MOTOR_DIMENSIONS.toStringUnit(mountDiameter)+ " x " + UnitGroup.UNITS_MOTOR_DIMENSIONS.toStringUnit(mountLength)); } setLimitLength(); setLimitDiameter(); } private void setLimitLength( ) { ((SwingPreferences) Application.getPreferences()).putBoolean("motorFilterLimitLength", limitLength); if ( mountLength != null & limitLength ) { lengthSlider.setValueAt(1, (int) Math.min(1000,Math.round(1000*mountLength))); } } private void setLimitDiameter( ) { ((SwingPreferences) Application.getPreferences()).putBoolean("motorFilterLimitDiameter", limitDiameter); if ( limitDiameter && mountDiameter != null) { // find the next largest diameter int i; for( i =0; i< diameterValues.length; i++ ) { if ( mountDiameter< diameterValues[i] - 0.0005 ) { break; } } if (i >= diameterValues.length ) { i--; } diameterSlider.setValueAt(1, i-1); } } public abstract void onSelectionChanged(); }