create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / gui / dialogs / preset / ComponentPresetChooserDialog.java
index fef3a26a3759776aaabc4a31f1f30c174e032be5..9efa3675e7a789c022b9ccfc809516ba02b46d41 100644 (file)
@@ -5,112 +5,140 @@ 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.Arrays;
 import java.util.List;
 
 import javax.swing.JButton;
+import javax.swing.JCheckBox;
 import javax.swing.JDialog;
+import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
+import javax.swing.JTextField;
+import javax.swing.RowFilter;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.table.TableColumn;
 import javax.swing.table.TableModel;
-import javax.swing.table.TableRowSorter;
 
 import net.miginfocom.swing.MigLayout;
-import net.sf.openrocket.gui.adaptors.Column;
-import net.sf.openrocket.gui.adaptors.ColumnTableModel;
 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.RocketComponent;
+import net.sf.openrocket.rocketcomponent.SymmetricComponent;
 import net.sf.openrocket.startup.Application;
-import net.sf.openrocket.unit.Value;
 
+/**
+ * Dialog shown for selecting a preset component.
+ */
 public class ComponentPresetChooserDialog extends JDialog {
        
        private static final Translator trans = Application.getTranslator();
        
-       //      private final ThrustCurveMotorSelectionPanel selectionPanel;
-       
        private final RocketComponent component;
-       private final List<ComponentPreset> presets;
+       
+       private ComponentPresetTable componentSelectionTable;
+       private JTextField filterText;
+       private JCheckBox foreDiameterFilterCheckBox;
+       private JCheckBox aftDiameterFilterCheckBox;
+       
+       private ComponentPresetRowFilter foreDiameterFilter;
+       private ComponentPresetRowFilter aftDiameterFilter;
+       
+       
+       /*
+        * 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 List<ComponentPreset> presets;
+       private ComponentPreset.Type presetType;
        
        private boolean okClicked = false;
        
        
-       public ComponentPresetChooserDialog(Window owner, RocketComponent component, final TypedKey<?>... columnKeys) {
+       public ComponentPresetChooserDialog(Window owner, RocketComponent component) {
                super(owner, trans.get("title"), Dialog.ModalityType.APPLICATION_MODAL);
-               
                this.component = component;
+               this.presetType = component.getPresetType();
+               this.presets = Application.getComponentPresetDao().listForType(component.getPresetType());
+               
+               List<TypedKey<?>> displayedColumnKeys = Arrays.asList(component.getPresetType().getDisplayedColumns());
                
-               presets = Application.getComponentPresetDao().listAll();
+               {
+                       final List<TypedKey<?>> columnKeys = ComponentPreset.ORDERED_KEY_LIST;
+                       int i = 0; // We start at 0 but use preincrement because the first column is favorite.
+                       for (final TypedKey<?> key : columnKeys) {
+                               // Note the increment early in the loop.  This really means that initial loop i=1
+                               // we do it here so the continue below doesn't mess up the counting.
+                               i++;
+                               // Don't allow the matching filters if the column is not part of the default set for
+                               // this kind of preset.
+                               if (!displayedColumnKeys.contains(key)) {
+                                       continue;
+                               }
+                               if (key == ComponentPreset.OUTER_DIAMETER || key == ComponentPreset.AFT_OUTER_DIAMETER) {
+                                       aftDiameterColumnIndex = i;
+                               }
+                               if (key == ComponentPreset.OUTER_DIAMETER || key == ComponentPreset.FORE_OUTER_DIAMETER) {
+                                       foreDiameterColumnIndex = i;
+                               }
+                       }
+               }
                
-               JPanel panel = new JPanel(new MigLayout("fill"));
                
-               final Column[] columns = new Column[columnKeys.length+1];
+               JPanel panel = new JPanel(new MigLayout("fill, ins para"));
                
-               columns[0] = new Column(trans.get("table.column.Favorite") ) {
+               /*
+                * Add filter by text.
+                */
+               JPanel sub = new JPanel(new MigLayout("fill, ins 0"));
+               JLabel filterLabel = new JLabel(trans.get("ComponentPresetChooserDialog.filter.label"));
+               sub.add(filterLabel, "gapright para");
+               
+               filterText = new JTextField();
+               sub.add(filterText, "growx");
+               filterText.getDocument().addDocumentListener(new DocumentListener() {
                        @Override
-                       public Object getValueAt(int row) {
-                               return Boolean.valueOf(ComponentPresetChooserDialog.this.presets.get(row).isFavorite());
+                       public void changedUpdate(DocumentEvent e) {
+                               updateFilters();
                        }
                        
                        @Override
-                       public void setValueAt(int row, Object value) {
-                               Application.getComponentPresetDao().setFavorite(ComponentPresetChooserDialog.this.presets.get(row), (Boolean) value);
-                       }
-
-                       @Override
-                       public Class<?> getColumnClass() {
-                               return Boolean.class;
+                       public void insertUpdate(DocumentEvent e) {
+                               updateFilters();
                        }
                        
-               };
-               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())) {
-                               @Override
-                               public Object getValueAt(int row) {
-                                       if (key.getType() == Double.class && key.getUnitGroup() != null) {
-                                               double v = (Double) ComponentPresetChooserDialog.this.presets.get(row).get(key);
-                                               return new Value( v, key.getUnitGroup() );
-                                       } else {
-                                               return ComponentPresetChooserDialog.this.presets.get(row).get(key);
-                                       }
-                               }
-                       };
-               }
-               
-               ColumnTableModel tableModel = new ColumnTableModel(columns) {
-                       @Override
-                       public int getRowCount() {
-                               return ComponentPresetChooserDialog.this.presets.size();
-                       }
-
                        @Override
-                       public boolean isCellEditable(int rowIndex, int columnIndex) {
-                               return columnIndex == 0;
+                       public void removeUpdate(DocumentEvent e) {
+                               updateFilters();
                        }
-                       
-               };
+               });
                
-               final JTable table = new JTable( tableModel );
+               panel.add(sub, "growx, ay 0, gapright para");
+               
+               
+               panel.add(getFilterCheckboxes(), "wrap para");
+               
+               componentSelectionTable = new ComponentPresetTable(presetType, presets, displayedColumnKeys);
+               //              GUIUtil.setAutomaticColumnTableWidths(componentSelectionTable, 20);
+               int w = componentSelectionTable.getRowHeight() + 4;
+               TableColumn tc = componentSelectionTable.getColumnModel().getColumn(0);
+               tc.setPreferredWidth(w);
+               tc.setMaxWidth(w);
+               tc.setMinWidth(w);
                
-               table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-
-               final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel);
-               // FIXME we might need some custom sorters.
-               /*for (int i = 0; i < columnKeys.length; i++) {
-                       TypedKey<?> column = columnKeys[i];
-                       sorter.setComparator(i, column.getComparator());
-               }*/
-               table.setRowSorter(sorter);
-
                JScrollPane scrollpane = new JScrollPane();
-               scrollpane.setViewportView(table);
-               panel.add(scrollpane, "grow, width :500:, height :300:, spanx, wrap para");
-
+               scrollpane.setViewportView(componentSelectionTable);
+               panel.add(scrollpane, "grow, width 700lp, height 300lp, spanx, wrap para");
+               
                
                // OK / Cancel buttons
                JButton okButton = new JButton(trans.get("dlg.but.ok"));
@@ -134,18 +162,71 @@ public class ComponentPresetChooserDialog extends JDialog {
                
                this.add(panel);
                
-               this.setModal(true);
-               this.pack();
-               this.setLocationByPlatform(true);
+               GUIUtil.rememberWindowSize(this);
                GUIUtil.setDisposableDialogOptions(this, okButton);
+       }
+       
+       
+       private JPanel getFilterCheckboxes() {
+               SymmetricComponent sc;
+               
+               JPanel panel = new JPanel(new MigLayout("fill, ins 0"));
+               
+               /*
+                * Add show all compatible check box.
+                */
+               final List<ComponentPreset.Type> compatibleTypes = component.getPresetType().getCompatibleTypes();
+               final ComponentPreset.Type nativeType = component.getPresetType();
+               if (compatibleTypes != null && compatibleTypes.size() > 0) {
+                       JCheckBox showAll = new JCheckBox();
+                       showAll.setText(trans.get("ComponentPresetChooserDialog.checkbox.showAllCompatible"));
+                       panel.add(showAll, "wrap");
+                       showAll.addItemListener(new ItemListener() {
+                               @Override
+                               public void itemStateChanged(ItemEvent e) {
+                                       if (((JCheckBox) e.getItem()).isSelected()) {
+                                               presets = Application.getComponentPresetDao().listForTypes(compatibleTypes);
+                                       } else {
+                                               presets = Application.getComponentPresetDao().listForType(nativeType);
+                                       }
+                                       componentSelectionTable.updateData(presets);
+                               }
+                       });
+               }
                
-               //JComponent focus = selectionPanel.getDefaultFocus();
-               //if (focus != null) {
-               //      focus.grabFocus();
-               //}
+               /*
+                * Add filter by fore diameter
+                */
+               foreDiameterFilterCheckBox = new JCheckBox(trans.get("ComponentPresetChooserDialog.checkbox.filterForeDiameter"));
+               sc = getPreviousSymmetricComponent();
+               if (sc != null && foreDiameterColumnIndex >= 0) {
+                       foreDiameterFilter = new ComponentPresetRowFilter(sc.getAftRadius() * 2.0, foreDiameterColumnIndex);
+                       panel.add(foreDiameterFilterCheckBox, "wrap");
+                       foreDiameterFilterCheckBox.addItemListener(new ItemListener() {
+                               @Override
+                               public void itemStateChanged(ItemEvent e) {
+                                       updateFilters();
+                               }
+                       });
+               }
                
-               // Set the closeable dialog after all initialization
-               //selectionPanel.setCloseableDialog(this);
+               /*
+                * Add filter by aft diameter
+                */
+               aftDiameterFilterCheckBox = new JCheckBox(trans.get("ComponentPresetChooserDialog.checkbox.filterAftDiameter"));
+               sc = getNextSymmetricComponent();
+               if (sc != null && aftDiameterColumnIndex >= 0) {
+                       aftDiameterFilter = new ComponentPresetRowFilter(sc.getForeRadius() * 2.0, aftDiameterColumnIndex);
+                       panel.add(aftDiameterFilterCheckBox, "wrap");
+                       aftDiameterFilterCheckBox.addItemListener(new ItemListener() {
+                               @Override
+                               public void itemStateChanged(ItemEvent e) {
+                                       updateFilters();
+                               }
+                       });
+               }
+               
+               return panel;
        }
        
        /**
@@ -156,18 +237,62 @@ public class ComponentPresetChooserDialog extends JDialog {
        public ComponentPreset getSelectedComponentPreset() {
                if (!okClicked)
                        return null;
-               //return selectionPanel.getSelectedMotor();
-               return null;
+               int row = componentSelectionTable.getSelectedRow();
+               if ( row < 0 ) {
+                       // Nothing selected.
+                       return null;
+               }
+               row = componentSelectionTable.convertRowIndexToModel(row);
+               return presets.get(row);
        }
        
        public void close(boolean ok) {
                okClicked = ok;
                this.setVisible(false);
+       }
+       
+       private void updateFilters() {
+               List<RowFilter<TableModel, Object>> filters = new ArrayList<RowFilter<TableModel, Object>>(2);
+               String filterTextRegex = filterText.getText();
+               if (filterTextRegex != null) {
+                       try {
+                               // The "(?iu)" magic turns on case insensitivity with unicode chars
+                               RowFilter<TableModel, Object> regexFilter = RowFilter.regexFilter("(?iu)" + filterTextRegex);
+                               filters.add(regexFilter);
+                       } catch (java.util.regex.PatternSyntaxException e) {
+                       }
+               }
+               if (aftDiameterFilterCheckBox.isSelected()) {
+                       filters.add(aftDiameterFilter);
+               }
+               if (foreDiameterFilterCheckBox.isSelected()) {
+                       filters.add(foreDiameterFilter);
+               }
                
-               ComponentPreset preset = getSelectedComponentPreset();
-               if (okClicked && preset != null) {
-                       //selectionPanel.selectedMotor(selected);
+               componentSelectionTable.setRowFilter(RowFilter.andFilter(filters));
+       }
+       
+       
+       private SymmetricComponent getPreviousSymmetricComponent() {
+               RocketComponent c = component;
+               while (c != null) {
+                       c = c.getPreviousComponent();
+                       if (c instanceof SymmetricComponent) {
+                               return (SymmetricComponent) c;
+                       }
                }
+               return null;
        }
        
+       
+       private SymmetricComponent getNextSymmetricComponent() {
+               RocketComponent c = component;
+               while (c != null) {
+                       c = c.getNextComponent();
+                       if (c instanceof SymmetricComponent) {
+                               return (SymmetricComponent) c;
+                       }
+               }
+               return null;
+       }
 }