Added filter check boxes to limit the displayed components based on fitting with the previous or next component.
This commit is contained in:
parent
6891566799
commit
f69ed1ea2f
@ -1591,6 +1591,8 @@ PresetModel.lbl.database = From database...
|
|||||||
! Component Preset Chooser Dialog
|
! Component Preset Chooser Dialog
|
||||||
ComponentPresetChooserDialog.title = Choose component preset
|
ComponentPresetChooserDialog.title = Choose component preset
|
||||||
ComponentPresetChooserDialog.filter.label = Filter:
|
ComponentPresetChooserDialog.filter.label = Filter:
|
||||||
|
ComponentPresetChooserDialog.checkbox.filterAftDiameter = Match aft diameter
|
||||||
|
ComponentPresetChooserDialog.checkbox.filterForeDiameter = Match fore diameter
|
||||||
table.column.Favorite = Favorite
|
table.column.Favorite = Favorite
|
||||||
table.column.Manufacturer = Manufacturer
|
table.column.Manufacturer = Manufacturer
|
||||||
table.column.PartNo = Part Number
|
table.column.PartNo = Part Number
|
||||||
|
@ -5,9 +5,13 @@ import java.awt.Dialog;
|
|||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.awt.event.ItemListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
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.l10n.Translator;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.preset.TypedKey;
|
import net.sf.openrocket.preset.TypedKey;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InternalComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.unit.Value;
|
import net.sf.openrocket.unit.Value;
|
||||||
|
|
||||||
@ -36,9 +42,20 @@ public class ComponentPresetChooserDialog extends JDialog {
|
|||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
|
private final RocketComponent component;
|
||||||
|
|
||||||
private final JTable componentSelectionTable;
|
private final JTable componentSelectionTable;
|
||||||
private final TableRowSorter<TableModel> sorter;
|
private final TableRowSorter<TableModel> sorter;
|
||||||
private final JTextField filterText;
|
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<ComponentPreset> presets;
|
private final List<ComponentPreset> presets;
|
||||||
|
|
||||||
@ -47,31 +64,15 @@ public class ComponentPresetChooserDialog extends JDialog {
|
|||||||
|
|
||||||
public ComponentPresetChooserDialog(Window owner, RocketComponent component) {
|
public ComponentPresetChooserDialog(Window owner, RocketComponent component) {
|
||||||
super(owner, trans.get("title"), Dialog.ModalityType.APPLICATION_MODAL);
|
super(owner, trans.get("title"), Dialog.ModalityType.APPLICATION_MODAL);
|
||||||
|
this.component = component;
|
||||||
|
|
||||||
final TypedKey<?>[] columnKeys = component.getPresetType().getDisplayedColumns();
|
final TypedKey<?>[] columnKeys = component.getPresetType().getDisplayedColumns();
|
||||||
|
|
||||||
presets = Application.getComponentPresetDao().listForType(component.getPresetType());
|
presets = Application.getComponentPresetDao().listForType(component.getPresetType());
|
||||||
|
|
||||||
JPanel panel = new JPanel(new MigLayout("fill"));
|
/*
|
||||||
JLabel filterLabel = new JLabel(trans.get("ComponentPresetChooserDialog.filter.label"));
|
* Set up the Column Table model
|
||||||
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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final Column[] columns = new Column[columnKeys.length+1];
|
final Column[] columns = new Column[columnKeys.length+1];
|
||||||
|
|
||||||
columns[0] = new Column(trans.get("table.column.Favorite") ) {
|
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++) {
|
for (int i = 0; i < columnKeys.length; i++) {
|
||||||
final TypedKey<?> key = columnKeys[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
|
@Override
|
||||||
public Object getValueAt(int row) {
|
public Object getValueAt(int row) {
|
||||||
ComponentPreset preset = ComponentPresetChooserDialog.this.presets.get(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) {
|
ColumnTableModel tableModel = new ColumnTableModel(columns) {
|
||||||
@Override
|
@Override
|
||||||
public int getRowCount() {
|
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 = new JTable( tableModel );
|
||||||
|
|
||||||
componentSelectionTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
componentSelectionTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
@ -189,15 +271,54 @@ public class ComponentPresetChooserDialog extends JDialog {
|
|||||||
this.setVisible(false);
|
this.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void newFilter(String regex) {
|
private void updateFilters() {
|
||||||
RowFilter<TableModel,Object> filter = null;
|
List<RowFilter<TableModel,Object>> filters = new ArrayList<RowFilter<TableModel,Object>> (2);
|
||||||
|
String filterTextRegex = filterText.getText();
|
||||||
|
if ( filterTextRegex != null ) {
|
||||||
try {
|
try {
|
||||||
// The "(?iu)" magic turns on case insensitivity with unicode chars
|
// The "(?iu)" magic turns on case insensitivity with unicode chars
|
||||||
filter = RowFilter.regexFilter("(?iu)"+regex);
|
RowFilter<TableModel,Object> regexFilter = RowFilter.regexFilter("(?iu)"+filterTextRegex);
|
||||||
|
filters.add(regexFilter);
|
||||||
} catch ( java.util.regex.PatternSyntaxException e ) {
|
} catch ( java.util.regex.PatternSyntaxException e ) {
|
||||||
// FIXME - do we want to remove the filter?
|
}
|
||||||
return;
|
}
|
||||||
}
|
if ( aftDiameterFilterCheckBox.isSelected() ) {
|
||||||
sorter.setRowFilter(filter);
|
// 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<TableModel,Object> outerDiameterFilter = new ComponentPresetRowFilter( nextDiameter, aftDiameterColumnIndex);
|
||||||
|
filters.add(outerDiameterFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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<TableModel,Object> outerDiameterFilter = new ComponentPresetRowFilter( previousDaimeter, foreDiameterColumnIndex);
|
||||||
|
filters.add(outerDiameterFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sorter.setRowFilter( RowFilter.andFilter(filters) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<TableModel, Object> {
|
||||||
|
|
||||||
|
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<? extends TableModel, ? extends Object> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user