--- /dev/null
+package net.sf.openrocket.gui.dialogs.preset;
+
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JMenu;
+import javax.swing.JPopupMenu;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.RowFilter;
+import javax.swing.RowSorter.SortKey;
+import javax.swing.SortOrder;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableModel;
+import javax.swing.table.TableRowSorter;
+
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.preset.TypedKey;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.Unit;
+import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.unit.Value;
+import net.sf.openrocket.util.AlphanumComparator;
+
+public class ComponentPresetTable extends JTable {
+
+ private static final Translator trans = Application.getTranslator();
+
+ private final TableRowSorter<TableModel> sorter;
+ private List<ComponentPreset> presets;
+ private final ComponentPreset.Type presetType;
+ private Set<String> favorites;
+ private final AbstractTableModel tableModel;
+ private final XTableColumnModel tableColumnModel;
+ private final ComponentPresetTableColumn[] columns;
+
+ public ComponentPresetTable(final ComponentPreset.Type presetType, List<ComponentPreset> presets, List<TypedKey<?>> visibleColumnKeys) {
+ super();
+ this.presets = presets;
+ this.presetType = presetType;
+ this.favorites = Application.getPreferences().getComponentFavorites(presetType);
+ this.columns = new ComponentPresetTableColumn[ComponentPreset.ORDERED_KEY_LIST.size()+1];
+
+
+ tableModel = new AbstractTableModel() {
+ final ComponentPresetTableColumn[] myColumns = columns;
+ @Override
+ public int getRowCount() {
+ return ComponentPresetTable.this.presets.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return myColumns.length;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return myColumns[columnIndex].getValueFromPreset(favorites,ComponentPresetTable.this.presets.get(rowIndex));
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ // Only support favorite
+ if ( columnIndex != 0 ) {
+ return;
+ }
+ ComponentPreset preset = ComponentPresetTable.this.presets.get(rowIndex);
+ Application.getComponentPresetDao().setFavorite(preset, presetType, (Boolean) aValue);
+ ComponentPresetTable.this.updateFavorites();
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return columnIndex == 0;
+ }
+
+ @Override
+ public Class<?> getColumnClass(int columnIndex) {
+ return columnIndex == 0 ? Boolean.class : Object.class;
+ }
+
+ };
+
+
+ sorter = new TableRowSorter<TableModel>(tableModel);
+
+ tableColumnModel = new XTableColumnModel();
+
+ /*
+ * Set up the Column Table model, and customize the sorting.
+ */
+ columns[0] = new ComponentPresetTableColumn.Favorite(0);
+ tableColumnModel.addColumn(columns[0]);
+
+ List<TableColumn> hiddenColumns = new ArrayList<TableColumn>();
+ {
+ int index = 1;
+ for (final TypedKey<?> key: ComponentPreset.ORDERED_KEY_LIST ) {
+ if ( key.getType() == Double.class && key.getUnitGroup() != null ) {
+ columns[index] = new ComponentPresetTableColumn.DoubleWithUnit((TypedKey<Double>)key,index);
+ } else {
+ columns[index] = new ComponentPresetTableColumn.Parameter(key,index);
+ }
+ tableColumnModel.addColumn(columns[index]);
+ if ( key == ComponentPreset.MANUFACTURER || key == ComponentPreset.PARTNO ) {
+ sorter.setComparator(index, new AlphanumComparator());
+ } else if ( key.getType() == Double.class ) {
+ sorter.setComparator(index, new Comparator<Value>() {
+
+ @Override
+ public int compare(Value o1, Value o2) {
+ return Double.compare(o1.getValue(), o2.getValue());
+ }
+
+ });
+ }
+ if ( visibleColumnKeys.indexOf(key) < 0 ) {
+ hiddenColumns.add(columns[index]);
+ }
+ index ++;
+ }
+ }
+
+ this.setAutoCreateColumnsFromModel(false);
+ this.setColumnModel( tableColumnModel );
+ this.setModel(tableModel);
+ this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ this.setRowSorter(sorter);
+
+ for ( TableColumn hiddenColumn : hiddenColumns ) {
+ tableColumnModel.setColumnVisible(hiddenColumn, false);
+ }
+
+ JTableHeader header = this.getTableHeader();
+
+ header.setReorderingAllowed(true);
+
+ header.addMouseListener( new MouseAdapter() {
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ if ( e.isPopupTrigger() ) {
+ doPopup(e);
+ }
+ }
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ if ( e.isPopupTrigger() ) {
+ doPopup(e);
+ }
+ }
+ });
+ }
+
+ public void setRowFilter( RowFilter<? super TableModel ,? super Integer> filter ) {
+ sorter.setRowFilter( filter );
+ }
+
+ public void updateData( List<ComponentPreset> presets ) {
+ this.presets = presets;
+ this.favorites = Application.getPreferences().getComponentFavorites(presetType);
+ this.tableModel.fireTableDataChanged();
+ }
+
+ public void updateFavorites() {
+ this.favorites = Application.getPreferences().getComponentFavorites(presetType);
+ this.tableModel.fireTableDataChanged();
+ }
+
+ private void doPopup(MouseEvent evt ) {
+
+ // Figure out what column header was clicked on.
+ int colIndex = tableColumnModel.getColumnIndexAtX( evt.getX() );
+ ComponentPresetTableColumn colClicked = null;
+ if ( colIndex >=0 ) {
+ colClicked = (ComponentPresetTableColumn) tableColumnModel.getColumn(colIndex);
+ }
+
+ JPopupMenu columnMenu = new ColumnPopupMenu(colClicked, colIndex);
+ columnMenu.show(evt.getComponent(),evt.getX(),evt.getY());
+ }
+
+ private class ColumnPopupMenu extends JPopupMenu {
+
+ ColumnPopupMenu(ComponentPresetTableColumn colClicked, int colClickedIndex) {
+ if ( colClickedIndex >= 0 ) {
+ JCheckBoxMenuItem item = new SortAscColumnMenuItem(colClickedIndex);
+ this.add(item);
+ item = new SortDescColumnMenuItem(colClickedIndex);
+ this.add(item);
+ this.addSeparator();
+ if ( colClicked instanceof ComponentPresetTableColumn.DoubleWithUnit ) {
+ this.add( new UnitSelectorMenuItem( (ComponentPresetTableColumn.DoubleWithUnit) colClicked ));
+ this.addSeparator();
+ }
+ }
+ for( TableColumn c: columns ) {
+ JCheckBoxMenuItem item = new ToggleColumnMenuItem(c);
+ this.add(item);
+ }
+ }
+
+
+ private class SortAscColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
+ private int columnClicked;
+ SortAscColumnMenuItem(int columnClicked) {
+ super( trans.get("ComponentPresetChooserDialog.menu.sortAsc") );
+ this.addItemListener(this);
+ this.columnClicked = columnClicked;
+ }
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ sorter.setSortKeys( Collections.singletonList( new SortKey(columnClicked, SortOrder.ASCENDING)));
+ }
+ }
+
+ private class SortDescColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
+ private int columnClicked;
+ SortDescColumnMenuItem(int columnClicked) {
+ super( trans.get("ComponentPresetChooserDialog.menu.sortDesc") );
+ this.addItemListener(this);
+ this.columnClicked = columnClicked;
+ }
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ sorter.setSortKeys( Collections.singletonList( new SortKey(columnClicked, SortOrder.DESCENDING)));
+ }
+ }
+
+ private class ToggleColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
+ TableColumn col;
+ ToggleColumnMenuItem( TableColumn col ) {
+ super( String.valueOf(col.getHeaderValue()), tableColumnModel.isColumnVisible(col));
+ this.addItemListener(this);
+ this.col = col;
+ }
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ tableColumnModel.setColumnVisible(col, !tableColumnModel.isColumnVisible(col));
+ }
+ }
+
+ private class UnitSelectorMenuItem extends JMenu implements ItemListener {
+ ComponentPresetTableColumn.DoubleWithUnit col;
+ UnitSelectorMenuItem( ComponentPresetTableColumn.DoubleWithUnit col ) {
+ super(trans.get("ComponentPresetChooserDialog.menu.units"));
+ this.col = col;
+ UnitGroup group = col.unitGroup;
+ Unit selectedUnit = col.selectedUnit;
+ for( Unit u : group.getUnits() ) {
+ JCheckBoxMenuItem item = new JCheckBoxMenuItem( u.toString() );
+ if ( u == selectedUnit ) {
+ item.setSelected(true);
+ }
+ item.addItemListener(this);
+ this.add(item);
+ }
+
+ }
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ JCheckBoxMenuItem item = (JCheckBoxMenuItem) e.getItem();
+ String val = item.getText();
+ col.selectedUnit = col.unitGroup.findApproximate(val);
+ ComponentPresetTable.this.tableModel.fireTableDataChanged();
+ return;
+ }
+
+ }
+ }
+}