JAL-3829 Javadoc for FTSColumnPreferences
[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  * Helps render GUI allowing control of which columns to show for entries returned from an FTS query.
44  * TODO: push down FTSClient specific code
45  * 
46  * @author tcofoegbu
47  *
48  */
49 @SuppressWarnings("serial")
50 public class FTSDataColumnPreferences extends JScrollPane
51 {
52   protected JTable tbl_FTSDataColumnPrefs = new JTable();
53
54   protected JScrollPane scrl_pdbDocFieldConfig = new JScrollPane(
55           tbl_FTSDataColumnPrefs);
56
57   private HashMap<String, FTSDataColumnI> map = new HashMap<String, FTSDataColumnI>();
58
59   private Collection<FTSDataColumnI> structSummaryColumns = new LinkedHashSet<FTSDataColumnI>();
60
61   private Collection<FTSDataColumnI> allFTSDataColumns = new LinkedHashSet<FTSDataColumnI>();
62
63   public enum PreferenceSource
64   {
65     SEARCH_SUMMARY, STRUCTURE_CHOOSER, PREFERENCES;
66   }
67
68   private PreferenceSource currentSource;
69
70   private FTSRestClientI ftsRestClient;
71
72   public FTSDataColumnPreferences(PreferenceSource source,
73           FTSRestClientI ftsRestClient)
74   {
75     this.ftsRestClient = ftsRestClient;
76     if (source.equals(PreferenceSource.STRUCTURE_CHOOSER)
77             || source.equals(PreferenceSource.PREFERENCES))
78     {
79       structSummaryColumns = ((PDBFTSRestClient) ftsRestClient)
80               .getAllDefaultDisplayedStructureDataColumns();
81     }
82     allFTSDataColumns.addAll(ftsRestClient.getAllFTSDataColumns());
83
84     tbl_FTSDataColumnPrefs.setAutoCreateRowSorter(true);
85     this.getViewport().add(tbl_FTSDataColumnPrefs);
86     this.currentSource = source;
87
88     String[] columnNames = null;
89     switch (source)
90     {
91     case SEARCH_SUMMARY:
92       columnNames = new String[] { "", "Display", "Group" };
93       break;
94     case STRUCTURE_CHOOSER:
95       columnNames = new String[] { "", "Display", "Group" };
96       break;
97     case PREFERENCES:
98       columnNames = new String[] { "PDB Field", "Show in search summary",
99           "Show in structure summary" };
100       break;
101     default:
102       break;
103     }
104
105     Object[][] data = new Object[allFTSDataColumns.size()][3];
106
107     int x = 0;
108     for (FTSDataColumnI field : allFTSDataColumns)
109     {   
110       //System.out.println("allFTSDataColumns==" + allFTSDataColumns);
111       if (field.getName().equalsIgnoreCase("all"))
112       {
113         continue;
114       }
115
116       switch (source)
117       {
118       case SEARCH_SUMMARY:
119         data[x++] = new Object[] { ftsRestClient
120                 .getAllDefaultDisplayedFTSDataColumns().contains(field),
121             field.getName(), field.getGroup() };
122         //System.out.println(" PUIS " + field.getName() + " ET AUSSI " + field.getGroup() + "X = " + x);
123         break;
124       case STRUCTURE_CHOOSER:
125         data[x++] = new Object[] { structSummaryColumns.contains(field),
126             field.getName(), field.getGroup() };
127         break;
128       case PREFERENCES:
129         data[x++] = new Object[] {
130             field.getName(), ftsRestClient
131                     .getAllDefaultDisplayedFTSDataColumns().contains(field),
132             structSummaryColumns.contains(field) };
133         break;
134       default:
135         break;
136       }
137       map.put(field.getName(), field);
138     }
139
140     FTSDataColumnPrefsTableModel model = new FTSDataColumnPrefsTableModel(
141             columnNames, data);
142     tbl_FTSDataColumnPrefs.setModel(model);
143
144     switch (source)
145     {
146     case SEARCH_SUMMARY:
147     case STRUCTURE_CHOOSER:
148       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0)
149               .setPreferredWidth(30);
150       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0).setMinWidth(20);
151       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0).setMaxWidth(40);
152       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(1)
153               .setPreferredWidth(150);
154       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(1).setMinWidth(150);
155       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(2)
156               .setPreferredWidth(150);
157       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(2).setMinWidth(150);
158
159       TableRowSorter<TableModel> sorter = new TableRowSorter<>(
160               tbl_FTSDataColumnPrefs.getModel());
161       tbl_FTSDataColumnPrefs.setRowSorter(sorter);
162       List<RowSorter.SortKey> sortKeys = new ArrayList<>();
163       int columnIndexToSort = 2;
164       sortKeys.add(new RowSorter.SortKey(columnIndexToSort,
165               SortOrder.ASCENDING));
166       sorter.setComparator(columnIndexToSort,
167               new Comparator<FTSDataColumnGroupI>()
168               {
169                 @Override
170                 public int compare(FTSDataColumnGroupI o1,
171                         FTSDataColumnGroupI o2)
172                 {
173                   return o1.getSortOrder() - o2.getSortOrder();
174                 }
175               });
176       sorter.setSortKeys(sortKeys);
177       // BH 2018 setSortKeys does a sort      sorter.sort();
178
179       tbl_FTSDataColumnPrefs
180               .setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
181       break;
182     case PREFERENCES:
183     default:
184       break;
185     }
186
187   }
188
189   public Collection<FTSDataColumnI> getStructureSummaryFields()
190   {
191     return structSummaryColumns;
192   }
193
194   class FTSDataColumnPrefsTableModel extends AbstractTableModel
195   {
196
197     public FTSDataColumnPrefsTableModel(String[] columnNames,
198             Object[][] data)
199     {
200       this.data = data;
201       this.columnNames = columnNames;
202     }
203
204     private Object[][] data;
205
206     private String[] columnNames;
207
208     @Override
209     public int getColumnCount()
210     {
211       return columnNames.length;
212     }
213
214     @Override
215     public int getRowCount()
216     {
217       return data.length;
218     }
219
220     @Override
221     public String getColumnName(int col)
222     {
223       return columnNames[col];
224     }
225
226     @Override
227     public Object getValueAt(int row, int col)
228     {
229       return data[row][col];
230     }
231
232     /*
233      * JTable uses this method to determine the default renderer/ editor for
234      * each cell. If we didn't implement this method, then the last column would
235      * contain text ("true"/"false"), rather than a check box.
236      */
237     @Override
238     public Class getColumnClass(int c)
239     {
240       return getValueAt(0, c).getClass();
241     }
242
243     /*
244      * Don't need to implement this method unless your table's editable.
245      */
246     @Override
247     public boolean isCellEditable(int row, int col)
248     {
249       // Note that the data/cell address is constant,
250       // no matter where the cell appears onscreen.
251       // !isPDBID(row, col) ensures the PDB_Id cell is never editable as it
252       // serves as a unique id for each row.
253       // return (col == 1 || col == 2) && !isPDBID(row, col);
254       switch (currentSource)
255       {
256       case SEARCH_SUMMARY:
257       case STRUCTURE_CHOOSER:
258         return (col == 0) && !isPrimaryKeyCell(row, 1);
259       case PREFERENCES:
260         return (col == 1 || col == 2) && !isPrimaryKeyCell(row, 0);
261       default:
262         return false;
263       }
264
265     }
266
267     /**
268      * Determines whether the data in a given cell is a PDB ID.
269      * 
270      * @param row
271      * @param col
272      * @return
273      */
274
275     public boolean isPrimaryKeyCell(int row, int col)
276     {
277       String name = getValueAt(row, col).toString();
278       FTSDataColumnI pdbField = map.get(name);
279       return pdbField.isPrimaryKeyColumn();
280     }
281
282     /*
283      * Don't need to implement this method unless your table's data can change.
284      */
285     @Override
286     public void setValueAt(Object value, int row, int col)
287     {
288       data[row][col] = value;
289       fireTableCellUpdated(row, col);
290
291       String name = null;
292       switch (currentSource)
293       {
294       case SEARCH_SUMMARY:
295       case STRUCTURE_CHOOSER:
296         name = getValueAt(row, 1).toString();
297         break;
298       case PREFERENCES:
299         name = getValueAt(row, 0).toString();
300         break;
301       default:
302         break;
303       }
304       boolean selected = ((Boolean) value).booleanValue();
305
306       FTSDataColumnI ftsDataColumn = map.get(name);
307
308       if (currentSource == PreferenceSource.SEARCH_SUMMARY)
309       {
310         updatePrefs(ftsRestClient.getAllDefaultDisplayedFTSDataColumns(),
311                 ftsDataColumn, selected);
312       }
313       else if (currentSource == PreferenceSource.STRUCTURE_CHOOSER)
314       {
315         updatePrefs(structSummaryColumns, ftsDataColumn, selected);
316       }
317       else if (currentSource == PreferenceSource.PREFERENCES)
318       {
319         if (col == 1)
320         {
321           updatePrefs(ftsRestClient.getAllDefaultDisplayedFTSDataColumns(),
322                   ftsDataColumn, selected);
323         }
324         else if (col == 2)
325         {
326           updatePrefs(structSummaryColumns, ftsDataColumn, selected);
327         }
328       }
329     }
330
331     private void updatePrefs(Collection<FTSDataColumnI> prefConfig,
332             FTSDataColumnI dataColumn, boolean selected)
333     {
334       if (prefConfig.contains(dataColumn) && !selected)
335       {
336         prefConfig.remove(dataColumn);
337       }
338
339       if (!prefConfig.contains(dataColumn) && selected)
340       {
341         prefConfig.add(dataColumn);
342       }
343     }
344
345   }
346 }