create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / gui / dialogs / preset / ComponentPresetTable.java
1 package net.sf.openrocket.gui.dialogs.preset;
2
3 import java.awt.event.ItemEvent;
4 import java.awt.event.ItemListener;
5 import java.awt.event.MouseAdapter;
6 import java.awt.event.MouseEvent;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.Comparator;
10 import java.util.List;
11 import java.util.Set;
12
13 import javax.swing.JCheckBoxMenuItem;
14 import javax.swing.JMenu;
15 import javax.swing.JPopupMenu;
16 import javax.swing.JTable;
17 import javax.swing.ListSelectionModel;
18 import javax.swing.RowFilter;
19 import javax.swing.RowSorter.SortKey;
20 import javax.swing.SortOrder;
21 import javax.swing.table.AbstractTableModel;
22 import javax.swing.table.JTableHeader;
23 import javax.swing.table.TableColumn;
24 import javax.swing.table.TableModel;
25 import javax.swing.table.TableRowSorter;
26
27 import net.sf.openrocket.l10n.Translator;
28 import net.sf.openrocket.preset.ComponentPreset;
29 import net.sf.openrocket.preset.TypedKey;
30 import net.sf.openrocket.startup.Application;
31 import net.sf.openrocket.unit.Unit;
32 import net.sf.openrocket.unit.UnitGroup;
33 import net.sf.openrocket.unit.Value;
34 import net.sf.openrocket.util.AlphanumComparator;
35
36 public class ComponentPresetTable extends JTable {
37
38         private static final Translator trans = Application.getTranslator();
39
40         private final TableRowSorter<TableModel> sorter;
41         private List<ComponentPreset> presets;
42         private final ComponentPreset.Type presetType;
43         private Set<String> favorites;
44         private final AbstractTableModel tableModel;
45         private final XTableColumnModel tableColumnModel;
46         private final ComponentPresetTableColumn[] columns;
47
48         public ComponentPresetTable(final ComponentPreset.Type presetType, List<ComponentPreset> presets, List<TypedKey<?>> visibleColumnKeys) {
49                 super();
50                 this.presets = presets;
51                 this.presetType = presetType;
52                 this.favorites = Application.getPreferences().getComponentFavorites(presetType);
53                 this.columns = new ComponentPresetTableColumn[ComponentPreset.ORDERED_KEY_LIST.size()+1];
54
55
56                 tableModel = new AbstractTableModel() {
57                         final ComponentPresetTableColumn[] myColumns = columns;
58                         @Override
59                         public int getRowCount() {
60                                 return ComponentPresetTable.this.presets.size();
61                         }
62
63                         @Override
64                         public int getColumnCount() {
65                                 return myColumns.length;
66                         }
67
68                         @Override
69                         public Object getValueAt(int rowIndex, int columnIndex) {
70                                 return myColumns[columnIndex].getValueFromPreset(favorites,ComponentPresetTable.this.presets.get(rowIndex));
71                         }
72
73                         @Override
74                         public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
75                                 // Only support favorite
76                                 if ( columnIndex != 0 ) {
77                                         return;
78                                 }
79                                 ComponentPreset preset = ComponentPresetTable.this.presets.get(rowIndex);
80                                 Application.getComponentPresetDao().setFavorite(preset, presetType, (Boolean) aValue);
81                                 ComponentPresetTable.this.updateFavorites();
82                         }
83
84                         @Override
85                         public boolean isCellEditable(int rowIndex, int columnIndex) {
86                                 return columnIndex == 0;
87                         }
88
89                         @Override
90                         public Class<?> getColumnClass(int columnIndex) {
91                                 return columnIndex == 0 ? Boolean.class : Object.class;
92                         }
93
94                 };
95
96
97                 sorter = new TableRowSorter<TableModel>(tableModel);
98
99                 tableColumnModel = new XTableColumnModel();
100
101                 /*
102                  * Set up the Column Table model, and customize the sorting.
103                  */
104                 columns[0] = new ComponentPresetTableColumn.Favorite(0);
105                 tableColumnModel.addColumn(columns[0]);
106
107                 List<TableColumn> hiddenColumns = new ArrayList<TableColumn>();
108                 {
109                         int index = 1;
110                         for (final TypedKey<?> key: ComponentPreset.ORDERED_KEY_LIST ) {
111                                 if ( key.getType() == Double.class && key.getUnitGroup() != null ) {
112                                         columns[index] = new ComponentPresetTableColumn.DoubleWithUnit((TypedKey<Double>)key,index);
113                                 } else {
114                                         columns[index] = new ComponentPresetTableColumn.Parameter(key,index);
115                                 }
116                                 tableColumnModel.addColumn(columns[index]);
117                                 if ( key == ComponentPreset.MANUFACTURER || key == ComponentPreset.PARTNO ) {
118                                         sorter.setComparator(index, new AlphanumComparator());
119                                 } else if ( key.getType() == Double.class ) {
120                                         sorter.setComparator(index,  new Comparator<Value>() {
121
122                                                 @Override
123                                                 public int compare(Value o1, Value o2) {
124                                                         return Double.compare(o1.getValue(), o2.getValue());
125                                                 }
126                                                 
127                                         });
128                                 }
129                                 if ( visibleColumnKeys.indexOf(key) < 0 ) {
130                                         hiddenColumns.add(columns[index]);
131                                 }
132                                 index ++;
133                         }
134                 }
135
136                 this.setAutoCreateColumnsFromModel(false);
137                 this.setColumnModel( tableColumnModel );
138                 this.setModel(tableModel);
139                 this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
140                 this.setRowSorter(sorter);
141
142                 for ( TableColumn hiddenColumn : hiddenColumns ) {
143                         tableColumnModel.setColumnVisible(hiddenColumn, false);
144                 }
145
146                 JTableHeader header = this.getTableHeader();
147                 
148                 header.setReorderingAllowed(true);
149
150                 header.addMouseListener( new MouseAdapter() {
151
152                         @Override
153                         public void mousePressed(MouseEvent e) {
154                                 if ( e.isPopupTrigger() ) {
155                                         doPopup(e);
156                                 }
157                         }
158                         @Override
159                         public void mouseReleased(MouseEvent e) {
160                                 if ( e.isPopupTrigger() ) {
161                                         doPopup(e);
162                                 }
163                         }
164                 });
165         }
166
167         public void setRowFilter( RowFilter<? super TableModel ,? super Integer> filter ) {
168                 sorter.setRowFilter( filter );
169         }
170
171         public void updateData( List<ComponentPreset> presets ) {
172                 this.presets = presets;
173                 this.favorites = Application.getPreferences().getComponentFavorites(presetType);
174                 this.tableModel.fireTableDataChanged();
175         }
176         
177         public void updateFavorites() {
178                 this.favorites = Application.getPreferences().getComponentFavorites(presetType);
179                 this.tableModel.fireTableDataChanged();
180         }
181
182         private void doPopup(MouseEvent evt ) {
183                 
184                 // Figure out what column header was clicked on.
185                 int colIndex = tableColumnModel.getColumnIndexAtX( evt.getX() );
186                 ComponentPresetTableColumn colClicked = null;
187                 if ( colIndex >=0 ) {
188                         colClicked = (ComponentPresetTableColumn) tableColumnModel.getColumn(colIndex);
189                 }
190                 
191                 JPopupMenu columnMenu = new ColumnPopupMenu(colClicked, colIndex);
192                 columnMenu.show(evt.getComponent(),evt.getX(),evt.getY());
193         }
194
195         private class ColumnPopupMenu extends JPopupMenu {
196
197                 ColumnPopupMenu(ComponentPresetTableColumn colClicked, int colClickedIndex) {
198                         if ( colClickedIndex >= 0 ) {
199                                 JCheckBoxMenuItem item = new SortAscColumnMenuItem(colClickedIndex);
200                                 this.add(item);
201                                 item = new SortDescColumnMenuItem(colClickedIndex);
202                                 this.add(item);
203                                 this.addSeparator();
204                                 if ( colClicked instanceof ComponentPresetTableColumn.DoubleWithUnit ) {
205                                         this.add( new UnitSelectorMenuItem( (ComponentPresetTableColumn.DoubleWithUnit) colClicked ));
206                                         this.addSeparator();
207                                 }
208                         }
209                         for( TableColumn c: columns ) {
210                                 JCheckBoxMenuItem item = new ToggleColumnMenuItem(c);
211                                 this.add(item);
212                         }
213                 }
214
215
216                 private class SortAscColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
217                         private int columnClicked;
218                         SortAscColumnMenuItem(int columnClicked) {
219                                 super( trans.get("ComponentPresetChooserDialog.menu.sortAsc") );
220                                 this.addItemListener(this);
221                                 this.columnClicked = columnClicked;
222                         }
223                         @Override
224                         public void itemStateChanged(ItemEvent e) {
225                                 sorter.setSortKeys( Collections.singletonList( new SortKey(columnClicked, SortOrder.ASCENDING)));
226                         }
227                 }
228                 
229                 private class SortDescColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
230                         private int columnClicked;
231                         SortDescColumnMenuItem(int columnClicked) {
232                                 super( trans.get("ComponentPresetChooserDialog.menu.sortDesc") );
233                                 this.addItemListener(this);
234                                 this.columnClicked = columnClicked;
235                         }
236                         @Override
237                         public void itemStateChanged(ItemEvent e) {
238                                 sorter.setSortKeys( Collections.singletonList( new SortKey(columnClicked, SortOrder.DESCENDING)));
239                         }
240                 }
241                 
242                 private class ToggleColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
243                         TableColumn col;
244                         ToggleColumnMenuItem( TableColumn col ) {
245                                 super( String.valueOf(col.getHeaderValue()), tableColumnModel.isColumnVisible(col));
246                                 this.addItemListener(this);
247                                 this.col = col;
248                         }
249                         @Override
250                         public void itemStateChanged(ItemEvent e) {
251                                 tableColumnModel.setColumnVisible(col, !tableColumnModel.isColumnVisible(col));
252                         }
253                 }
254                 
255                 private class UnitSelectorMenuItem extends JMenu implements ItemListener {
256                         ComponentPresetTableColumn.DoubleWithUnit col;
257                         UnitSelectorMenuItem( ComponentPresetTableColumn.DoubleWithUnit col ) {
258                                 super(trans.get("ComponentPresetChooserDialog.menu.units"));
259                                 this.col = col;
260                                 UnitGroup group = col.unitGroup;
261                                 Unit selectedUnit = col.selectedUnit;
262                                 for( Unit u : group.getUnits() ) {
263                                         JCheckBoxMenuItem item = new JCheckBoxMenuItem( u.toString() );
264                                         if ( u == selectedUnit ) {
265                                                 item.setSelected(true);
266                                         }
267                                         item.addItemListener(this);
268                                         this.add(item);
269                                 }
270                                 
271                         }
272                         @Override
273                         public void itemStateChanged(ItemEvent e) {
274                                 JCheckBoxMenuItem item = (JCheckBoxMenuItem) e.getItem();
275                                 String val = item.getText();
276                                 col.selectedUnit = col.unitGroup.findApproximate(val);
277                                 ComponentPresetTable.this.tableModel.fireTableDataChanged();
278                                 return;
279                         }
280
281                 }
282         }
283 }