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