From 7f8091bf1080836f45fa6740e80be1e27e2218f8 Mon Sep 17 00:00:00 2001 From: kruland2607 Date: Mon, 16 Apr 2012 19:17:17 +0000 Subject: [PATCH] Added filter check boxes to limit the displayed components based on fitting with the previous or next component. git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@560 180e2498-e6e9-4542-8430-84ac67f01cd8 --- core/resources/l10n/messages.properties | 2 + .../preset/ComponentPresetChooserDialog.java | 185 +++++++++++++++--- .../preset/ComponentPresetRowFilter.java | 34 ++++ 3 files changed, 189 insertions(+), 32 deletions(-) create mode 100644 core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetRowFilter.java diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 501aa555..43c4beae 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -1591,6 +1591,8 @@ PresetModel.lbl.database = From database... ! Component Preset Chooser Dialog ComponentPresetChooserDialog.title = Choose component preset ComponentPresetChooserDialog.filter.label = Filter: +ComponentPresetChooserDialog.checkbox.filterAftDiameter = Match aft diameter +ComponentPresetChooserDialog.checkbox.filterForeDiameter = Match fore diameter table.column.Favorite = Favorite table.column.Manufacturer = Manufacturer table.column.PartNo = Part Number diff --git a/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java index c6a917f6..c2a6ccb0 100644 --- a/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java +++ b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java @@ -5,9 +5,13 @@ import java.awt.Dialog; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; import java.util.List; import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; @@ -28,7 +32,9 @@ import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.preset.TypedKey; +import net.sf.openrocket.rocketcomponent.InternalComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.SymmetricComponent; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.Value; @@ -36,10 +42,21 @@ public class ComponentPresetChooserDialog extends JDialog { private static final Translator trans = Application.getTranslator(); + private final RocketComponent component; + private final JTable componentSelectionTable; private final TableRowSorter sorter; private final JTextField filterText; + private final JCheckBox foreDiameterFilterCheckBox; + private final JCheckBox aftDiameterFilterCheckBox; + /* + * outerDiamtereColumnIndex is the index of the column associated with the OUTER_DIAMETER + * field. This index is needed by the matchOuterDiameterCheckBox to implement filtering. + */ + int aftDiameterColumnIndex = -1; + int foreDiameterColumnIndex = -1; + private final List presets; private boolean okClicked = false; @@ -47,31 +64,15 @@ public class ComponentPresetChooserDialog extends JDialog { public ComponentPresetChooserDialog(Window owner, RocketComponent component) { super(owner, trans.get("title"), Dialog.ModalityType.APPLICATION_MODAL); + this.component = component; final TypedKey[] columnKeys = component.getPresetType().getDisplayedColumns(); - + presets = Application.getComponentPresetDao().listForType(component.getPresetType()); - - JPanel panel = new JPanel(new MigLayout("fill")); - JLabel filterLabel = new JLabel(trans.get("ComponentPresetChooserDialog.filter.label")); - panel.add(filterLabel); - filterText = new JTextField(15); - panel.add(filterText,"growx, growy 0, wrap"); - filterText.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void changedUpdate(DocumentEvent e) { - newFilter(filterText.getText()); - } - @Override - public void insertUpdate(DocumentEvent e) { - newFilter(filterText.getText()); - } - @Override - public void removeUpdate(DocumentEvent e) { - newFilter(filterText.getText()); - } - }); - + + /* + * Set up the Column Table model + */ final Column[] columns = new Column[columnKeys.length+1]; columns[0] = new Column(trans.get("table.column.Favorite") ) { @@ -91,9 +92,18 @@ public class ComponentPresetChooserDialog extends JDialog { } }; + for (int i = 0; i < columnKeys.length; i++) { final TypedKey key = columnKeys[i]; - columns[i+1] = new Column(trans.get("table.column." + columnKeys[i].getName())) { + if ( key == ComponentPreset.OUTER_DIAMETER ) { + // magic +1 is because we have inserted the column for favorites above. + aftDiameterColumnIndex = i+1; + } + if ( key == ComponentPreset.FORE_OUTER_DIAMETER ) { + // magic +1 is because we have inserted the column for favorites above. + foreDiameterColumnIndex = i+1; + } + columns[i+1] = new Column(trans.get("table.column." + key.getName())) { @Override public Object getValueAt(int row) { ComponentPreset preset = ComponentPresetChooserDialog.this.presets.get(row); @@ -110,6 +120,18 @@ public class ComponentPresetChooserDialog extends JDialog { }; } + /* + * perhaps there is a better way for this. + * + * This check basically says that if a component does not have a fore diameter, use the + * outer_diameter when filtering. The problem this introduced is when this dialog is + * created for nose cones (which are aft of a body tube), you will be given the option + * to filter based on matching fore diameter. + */ + if ( foreDiameterColumnIndex < 0 ) { + foreDiameterColumnIndex = aftDiameterColumnIndex; + } + ColumnTableModel tableModel = new ColumnTableModel(columns) { @Override public int getRowCount() { @@ -123,6 +145,66 @@ public class ComponentPresetChooserDialog extends JDialog { }; + + /* + * Add filter by text. + */ + JPanel panel = new JPanel(new MigLayout("fill")); + JLabel filterLabel = new JLabel(trans.get("ComponentPresetChooserDialog.filter.label")); + panel.add(filterLabel); + filterText = new JTextField(15); + panel.add(filterText,"growx, growy 0, wrap"); + filterText.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void changedUpdate(DocumentEvent e) { + updateFilters(); + } + @Override + public void insertUpdate(DocumentEvent e) { + updateFilters(); + } + @Override + public void removeUpdate(DocumentEvent e) { + updateFilters(); + } + }); + + /* + * Add filter by fore diameter + */ + foreDiameterFilterCheckBox = new JCheckBox(); + foreDiameterFilterCheckBox.setText(trans.get("ComponentPresetChooserDialog.checkbox.filterForeDiameter")); + panel.add(foreDiameterFilterCheckBox, "skip, span 2"); + foreDiameterFilterCheckBox.addItemListener( new ItemListener () { + @Override + public void itemStateChanged(ItemEvent e) { + updateFilters(); + } + }); + + /* hide the fore diameter filter if it is not applicable */ + if ( foreDiameterColumnIndex < 0 || component.getPreviousComponent() == null ) { + foreDiameterFilterCheckBox.setVisible(false); + } + + /* + * Add filter by aft diameter + */ + aftDiameterFilterCheckBox = new JCheckBox(); + aftDiameterFilterCheckBox.setText(trans.get("ComponentPresetChooserDialog.checkbox.filterAftDiameter")); + panel.add(aftDiameterFilterCheckBox, "skip, span 2, wrap"); + aftDiameterFilterCheckBox.addItemListener( new ItemListener () { + @Override + public void itemStateChanged(ItemEvent e) { + updateFilters(); + } + }); + + /* hide the aft diameter filter if it is not applicable */ + if ( aftDiameterColumnIndex < 0 || component.getNextComponent() == null ) { + aftDiameterFilterCheckBox.setVisible(false); + } + componentSelectionTable = new JTable( tableModel ); componentSelectionTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -189,15 +271,54 @@ public class ComponentPresetChooserDialog extends JDialog { this.setVisible(false); } - private void newFilter(String regex) { - RowFilter filter = null; - try { - // The "(?iu)" magic turns on case insensitivity with unicode chars - filter = RowFilter.regexFilter("(?iu)"+regex); - } catch ( java.util.regex.PatternSyntaxException e ) { - // FIXME - do we want to remove the filter? - return; + private void updateFilters() { + List> filters = new ArrayList> (2); + String filterTextRegex = filterText.getText(); + if ( filterTextRegex != null ) { + try { + // The "(?iu)" magic turns on case insensitivity with unicode chars + RowFilter regexFilter = RowFilter.regexFilter("(?iu)"+filterTextRegex); + filters.add(regexFilter); + } catch ( java.util.regex.PatternSyntaxException e ) { + } + } + if ( aftDiameterFilterCheckBox.isSelected() ) { + // FIXME - please verify this logic looks correct. + // Grab the next component. + // If this.component is an InternalComponent, then we want to filter the outer diameter field + // against the next component's inner diameter. + RocketComponent nextComponent = component.getNextComponent(); + if ( nextComponent != null && nextComponent instanceof SymmetricComponent ) { + SymmetricComponent parent = (SymmetricComponent) nextComponent; + double nextDiameter; + if ( this.component instanceof InternalComponent ) { + nextDiameter = parent.getInnerRadius(0) * 2.0; + } else { + nextDiameter = parent.getForeRadius() * 2.0; + } + RowFilter outerDiameterFilter = new ComponentPresetRowFilter( nextDiameter, aftDiameterColumnIndex); + filters.add(outerDiameterFilter); + } } - sorter.setRowFilter(filter); + if ( foreDiameterFilterCheckBox.isSelected() ) { + // FIXME - please verify this logic looks correct. + // Grab the previous component. + // If this.component is an InternalComponent, then we want to filter the outer diameter field + // against the previous component's inner diameter. + RocketComponent previousComponent = component.getPreviousComponent(); + if ( previousComponent != null && previousComponent instanceof SymmetricComponent ) { + SymmetricComponent parent = (SymmetricComponent) previousComponent; + double previousDaimeter; + if ( this.component instanceof InternalComponent ) { + previousDaimeter = parent.getInnerRadius(parent.getLength()) * 2.0; + } else { + previousDaimeter = parent.getAftRadius() * 2.0; + } + RowFilter outerDiameterFilter = new ComponentPresetRowFilter( previousDaimeter, foreDiameterColumnIndex); + filters.add(outerDiameterFilter); + } + } + + sorter.setRowFilter( RowFilter.andFilter(filters) ); } } diff --git a/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetRowFilter.java b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetRowFilter.java new file mode 100644 index 00000000..78eadda8 --- /dev/null +++ b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetRowFilter.java @@ -0,0 +1,34 @@ +package net.sf.openrocket.gui.dialogs.preset; + +import javax.swing.RowFilter; +import javax.swing.table.TableModel; + +import net.sf.openrocket.unit.Value; + +public class ComponentPresetRowFilter extends RowFilter { + + private final double value; + private final int column; + // FIXME - what should epsilon be? + private final double epsilon = .0002; + + ComponentPresetRowFilter( double value, int column ) { + this.value = value; + this.column = column; + } + + @Override + public boolean include( RowFilter.Entry entry) { + Object o = entry.getValue(column); + if ( o instanceof Value ) { + Value v = (Value)o; + return Math.abs( value - v.getValue() ) < epsilon; + } + if ( o instanceof Double ) { + Double d = (Double) o; + return Math.abs( value - d ) < epsilon; + } + return true; + } + +} -- 2.30.2