JAL-2738 copy to spikes/mungo
[jalview.git] / src / jalview / fts / core / FTSDataColumnPreferences.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.fts.core;
22
23 import jalview.fts.api.FTSDataColumnI;
24 import jalview.fts.api.FTSDataColumnI.FTSDataColumnGroupI;
25 import jalview.fts.api.FTSRestClientI;
26 import jalview.fts.service.pdb.PDBFTSRestClient;
27
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Comparator;
31 import java.util.HashMap;
32 import java.util.LinkedHashSet;
33 import java.util.List;
34
35 import javax.swing.JScrollPane;
36 import javax.swing.JTable;
37 import javax.swing.RowSorter;
38 import javax.swing.SortOrder;
39 import javax.swing.table.AbstractTableModel;
40 import javax.swing.table.TableModel;
41 import javax.swing.table.TableRowSorter;
42
43 @SuppressWarnings("serial")
44 public class FTSDataColumnPreferences extends JScrollPane
45 {
46   protected JTable tbl_FTSDataColumnPrefs = new JTable();
47
48   protected JScrollPane scrl_pdbDocFieldConfig = new JScrollPane(
49           tbl_FTSDataColumnPrefs);
50
51   private HashMap<String, FTSDataColumnI> map = new HashMap<String, FTSDataColumnI>();
52
53   private Collection<FTSDataColumnI> structSummaryColumns = new LinkedHashSet<FTSDataColumnI>();
54
55   private Collection<FTSDataColumnI> allFTSDataColumns = new LinkedHashSet<FTSDataColumnI>();
56
57   public enum PreferenceSource
58   {
59     SEARCH_SUMMARY, STRUCTURE_CHOOSER, PREFERENCES;
60   }
61
62   private PreferenceSource currentSource;
63
64   private FTSRestClientI ftsRestClient;
65
66   public FTSDataColumnPreferences(PreferenceSource source,
67           FTSRestClientI ftsRestClient)
68   {
69     this.ftsRestClient = ftsRestClient;
70     if (source.equals(PreferenceSource.STRUCTURE_CHOOSER)
71             || source.equals(PreferenceSource.PREFERENCES))
72     {
73       structSummaryColumns = ((PDBFTSRestClient) ftsRestClient)
74               .getAllDefaultDisplayedStructureDataColumns();
75     }
76     allFTSDataColumns.addAll(ftsRestClient.getAllFTSDataColumns());
77
78     tbl_FTSDataColumnPrefs.setAutoCreateRowSorter(true);
79     this.getViewport().add(tbl_FTSDataColumnPrefs);
80     this.currentSource = source;
81
82     String[] columnNames = null;
83     switch (source)
84     {
85     case SEARCH_SUMMARY:
86       columnNames = new String[] { "", "Display", "Group" };
87       break;
88     case STRUCTURE_CHOOSER:
89       columnNames = new String[] { "", "Display", "Group" };
90       break;
91     case PREFERENCES:
92       columnNames = new String[] { "PDB Field", "Show in search summary",
93           "Show in structure summary" };
94       break;
95     default:
96       break;
97     }
98
99     Object[][] data = new Object[allFTSDataColumns.size() - 1][3];
100
101     int x = 0;
102     for (FTSDataColumnI field : allFTSDataColumns)
103     {
104       if (field.getName().equalsIgnoreCase("all"))
105       {
106         continue;
107       }
108
109       switch (source)
110       {
111       case SEARCH_SUMMARY:
112         data[x++] = new Object[] { ftsRestClient
113                 .getAllDefaultDisplayedFTSDataColumns().contains(field),
114             field.getName(), field.getGroup() };
115         break;
116       case STRUCTURE_CHOOSER:
117         data[x++] = new Object[] { structSummaryColumns.contains(field),
118             field.getName(), field.getGroup() };
119         break;
120       case PREFERENCES:
121         data[x++] = new Object[] {
122             field.getName(), ftsRestClient
123                     .getAllDefaultDisplayedFTSDataColumns().contains(field),
124             structSummaryColumns.contains(field) };
125         break;
126       default:
127         break;
128       }
129       map.put(field.getName(), field);
130     }
131
132     FTSDataColumnPrefsTableModel model = new FTSDataColumnPrefsTableModel(
133             columnNames, data);
134     tbl_FTSDataColumnPrefs.setModel(model);
135
136     switch (source)
137     {
138     case SEARCH_SUMMARY:
139     case STRUCTURE_CHOOSER:
140       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0)
141               .setPreferredWidth(30);
142       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0).setMinWidth(20);
143       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0).setMaxWidth(40);
144       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(1)
145               .setPreferredWidth(150);
146       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(1).setMinWidth(150);
147       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(2)
148               .setPreferredWidth(150);
149       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(2).setMinWidth(150);
150
151       TableRowSorter<TableModel> sorter = new TableRowSorter<>(
152               tbl_FTSDataColumnPrefs.getModel());
153       tbl_FTSDataColumnPrefs.setRowSorter(sorter);
154       List<RowSorter.SortKey> sortKeys = new ArrayList<>();
155       int columnIndexToSort = 2;
156       sortKeys.add(new RowSorter.SortKey(columnIndexToSort,
157               SortOrder.ASCENDING));
158       sorter.setSortKeys(sortKeys);
159       sorter.setComparator(columnIndexToSort,
160               new Comparator<FTSDataColumnGroupI>()
161               {
162                 @Override
163                 public int compare(FTSDataColumnGroupI o1,
164                         FTSDataColumnGroupI o2)
165                 {
166                   return o1.getSortOrder() - o2.getSortOrder();
167                 }
168               });
169       sorter.sort();
170
171       tbl_FTSDataColumnPrefs
172               .setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
173       break;
174     case PREFERENCES:
175     default:
176       break;
177     }
178
179   }
180
181   public Collection<FTSDataColumnI> getStructureSummaryFields()
182   {
183     return structSummaryColumns;
184   }
185
186   class FTSDataColumnPrefsTableModel extends AbstractTableModel
187   {
188
189     public FTSDataColumnPrefsTableModel(String[] columnNames,
190             Object[][] data)
191     {
192       this.data = data;
193       this.columnNames = columnNames;
194     }
195
196     private Object[][] data;
197
198     private String[] columnNames;
199
200     @Override
201     public int getColumnCount()
202     {
203       return columnNames.length;
204     }
205
206     @Override
207     public int getRowCount()
208     {
209       return data.length;
210     }
211
212     @Override
213     public String getColumnName(int col)
214     {
215       return columnNames[col];
216     }
217
218     @Override
219     public Object getValueAt(int row, int col)
220     {
221       return data[row][col];
222     }
223
224     /*
225      * JTable uses this method to determine the default renderer/ editor for
226      * each cell. If we didn't implement this method, then the last column would
227      * contain text ("true"/"false"), rather than a check box.
228      */
229     @Override
230     public Class getColumnClass(int c)
231     {
232       return getValueAt(0, c).getClass();
233     }
234
235     /*
236      * Don't need to implement this method unless your table's editable.
237      */
238     @Override
239     public boolean isCellEditable(int row, int col)
240     {
241       // Note that the data/cell address is constant,
242       // no matter where the cell appears onscreen.
243       // !isPDBID(row, col) ensures the PDB_Id cell is never editable as it
244       // serves as a unique id for each row.
245       // return (col == 1 || col == 2) && !isPDBID(row, col);
246       switch (currentSource)
247       {
248       case SEARCH_SUMMARY:
249       case STRUCTURE_CHOOSER:
250         return (col == 0) && !isPrimaryKeyCell(row, 1);
251       case PREFERENCES:
252         return (col == 1 || col == 2) && !isPrimaryKeyCell(row, 0);
253       default:
254         return false;
255       }
256
257     }
258
259     /**
260      * Determines whether the data in a given cell is a PDB ID.
261      * 
262      * @param row
263      * @param col
264      * @return
265      */
266
267     public boolean isPrimaryKeyCell(int row, int col)
268     {
269       String name = getValueAt(row, col).toString();
270       FTSDataColumnI pdbField = map.get(name);
271       return pdbField.isPrimaryKeyColumn();
272     }
273
274     /*
275      * Don't need to implement this method unless your table's data can change.
276      */
277     @Override
278     public void setValueAt(Object value, int row, int col)
279     {
280       data[row][col] = value;
281       fireTableCellUpdated(row, col);
282
283       String name = null;
284       switch (currentSource)
285       {
286       case SEARCH_SUMMARY:
287       case STRUCTURE_CHOOSER:
288         name = getValueAt(row, 1).toString();
289         break;
290       case PREFERENCES:
291         name = getValueAt(row, 0).toString();
292         break;
293       default:
294         break;
295       }
296       boolean selected = ((Boolean) value).booleanValue();
297
298       FTSDataColumnI ftsDataColumn = map.get(name);
299
300       if (currentSource == PreferenceSource.SEARCH_SUMMARY)
301       {
302         updatePrefs(ftsRestClient.getAllDefaultDisplayedFTSDataColumns(),
303                 ftsDataColumn, selected);
304       }
305       else if (currentSource == PreferenceSource.STRUCTURE_CHOOSER)
306       {
307         updatePrefs(structSummaryColumns, ftsDataColumn, selected);
308       }
309       else if (currentSource == PreferenceSource.PREFERENCES)
310       {
311         if (col == 1)
312         {
313           updatePrefs(ftsRestClient.getAllDefaultDisplayedFTSDataColumns(),
314                   ftsDataColumn, selected);
315         }
316         else if (col == 2)
317         {
318           updatePrefs(structSummaryColumns, ftsDataColumn, selected);
319         }
320       }
321     }
322
323     private void updatePrefs(Collection<FTSDataColumnI> prefConfig,
324             FTSDataColumnI dataColumn, boolean selected)
325     {
326       if (prefConfig.contains(dataColumn) && !selected)
327       {
328         prefConfig.remove(dataColumn);
329       }
330
331       if (!prefConfig.contains(dataColumn) && selected)
332       {
333         prefConfig.add(dataColumn);
334       }
335     }
336
337   }
338 }