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