gt: 				return (SymmetricComponent) c;
context: package net.sf.openrocket.gui.dialogs.preset;
  
  
  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.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 net.miginfocom.swing.MigLayout;
  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.util.Chars;
  
  /**
   * Dialog shown for selecting a preset component.
   */
  public class ComponentPresetChooserDialog extends JDialog {
  	
  	private static final Translator trans = Application.getTranslator();
  	
  	private final RocketComponent component;
  	
  	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) {
  		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());
  		
  		{
  			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, ins para"));
  		
  		/*
  		 * 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 void changedUpdate(DocumentEvent e) {
  				updateFilters();
  			}
  			
  			@Override
  			public void insertUpdate(DocumentEvent e) {
  				updateFilters();
  			}
  			
  			@Override
  			public void removeUpdate(DocumentEvent e) {
  				updateFilters();
  			}
  		});
  		
  		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);
  		
  		JScrollPane scrollpane = new JScrollPane();
  		scrollpane.setViewportView(componentSelectionTable);
  		panel.add(scrollpane, "grow, width 700lp, height 300lp, spanx, wrap rel");
  		
  		panel.add(new JLabel(Chars.UP_ARROW + " " + trans.get("lbl.favorites")), "spanx, gapleft 5px, wrap para");
  		
  		
  		// OK / Cancel buttons
  		JButton okButton = new JButton(trans.get("dlg.but.ok"));
  		okButton.addActionListener(new ActionListener() {
  			@Override
  			public void actionPerformed(ActionEvent e) {
  				close(true);
  			}
  		});
  		panel.add(okButton, "tag ok, spanx, split");
  		
  		//// Cancel button
  		JButton cancelButton = new JButton(trans.get("dlg.but.cancel"));
  		cancelButton.addActionListener(new ActionListener() {
  			@Override
  			public void actionPerformed(ActionEvent e) {
  				close(false);
  			}
  		});
  		panel.add(cancelButton, "tag cancel");
  		
  		this.add(panel);
  		
  		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);
  				}
  			});
  		}
  		
  		/*
  		 * 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();
  				}
  			});
  		}
  		
  		/*
  		 * 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;
  	}
  	
  	/**
  	 * Return the motor selected by this chooser dialog, or <code>null</code> if the selection has been aborted.
  	 * 
  	 * @return	the selected motor, or <code>null</code> if no motor has been selected or the selection was canceled.
  	 */
  	public ComponentPreset getSelectedComponentPreset() {
  		if (!okClicked)
  			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);
  		}
  		
  		componentSelectionTable.setRowFilter(RowFilter.andFilter(filters));
  	}
  	
  	
  	private SymmetricComponent getPreviousSymmetricComponent() {
  		RocketComponent c = component;
  		while (c != null) {
  			c = c.getPreviousComponent();
  			if (c instanceof SymmetricComponent) {
  