f865ac3339165346da103f09261f5b5685d1bf2e
[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()][3];
100
101     int x = 0;
102     for (FTSDataColumnI field : allFTSDataColumns)
103     {   
104       //System.out.println("allFTSDataColumns==" + allFTSDataColumns);
105       if (field.getName().equalsIgnoreCase("all"))
106       {
107         continue;
108       }
109
110       switch (source)
111       {
112       case SEARCH_SUMMARY:
113         data[x++] = new Object[] { ftsRestClient
114                 .getAllDefaultDisplayedFTSDataColumns().contains(field),
115             field.getName(), field.getGroup() };
116         //System.out.println(" PUIS " + field.getName() + " ET AUSSI " + field.getGroup() + "X = " + x);
117         break;
118       case STRUCTURE_CHOOSER:
119         data[x++] = new Object[] { structSummaryColumns.contains(field),
120             field.getName(), field.getGroup() };
121         break;
122       case PREFERENCES:
123         data[x++] = new Object[] {
124             field.getName(), ftsRestClient
125                     .getAllDefaultDisplayedFTSDataColumns().contains(field),
126             structSummaryColumns.contains(field) };
127         break;
128       default:
129         break;
130       }
131       map.put(field.getName(), field);
132     }
133
134     FTSDataColumnPrefsTableModel model = new FTSDataColumnPrefsTableModel(
135             columnNames, data);
136     tbl_FTSDataColumnPrefs.setModel(model);
137
138     switch (source)
139     {
140     case SEARCH_SUMMARY:
141     case STRUCTURE_CHOOSER:
142       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0)
143               .setPreferredWidth(30);
144       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0).setMinWidth(20);
145       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0).setMaxWidth(40);
146       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(1)
147               .setPreferredWidth(150);
148       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(1).setMinWidth(150);
149       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(2)
150               .setPreferredWidth(150);
151       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(2).setMinWidth(150);
152
153       TableRowSorter<TableModel> sorter = new TableRowSorter<>(
154               tbl_FTSDataColumnPrefs.getModel());
155       tbl_FTSDataColumnPrefs.setRowSorter(sorter);
156       List<RowSorter.SortKey> sortKeys = new ArrayList<>();
157       int columnIndexToSort = 2;
158       sortKeys.add(new RowSorter.SortKey(columnIndexToSort,
159               SortOrder.ASCENDING));
160       sorter.setComparator(columnIndexToSort,
161               new Comparator<FTSDataColumnGroupI>()
162               {
163                 @Override
164                 public int compare(FTSDataColumnGroupI o1,
165                         FTSDataColumnGroupI o2)
166                 {
167                   return o1.getSortOrder() - o2.getSortOrder();
168                 }
169               });
170       sorter.setSortKeys(sortKeys);
171       // BH 2018 setSortKeys does a sort      sorter.sort();
172
173       tbl_FTSDataColumnPrefs
174               .setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
175       break;
176     case PREFERENCES:
177     default:
178       break;
179     }
180
181   }
182
183   public Collection<FTSDataColumnI> getStructureSummaryFields()
184   {
185     return structSummaryColumns;
186   }
187
188   class FTSDataColumnPrefsTableModel extends AbstractTableModel
189   {
190
191     public FTSDataColumnPrefsTableModel(String[] columnNames,
192             Object[][] data)
193     {
194       this.data = data;
195       this.columnNames = columnNames;
196     }
197
198     private Object[][] data;
199
200     private String[] columnNames;
201
202     @Override
203     public int getColumnCount()
204     {
205       return columnNames.length;
206     }
207
208     @Override
209     public int getRowCount()
210     {
211       return data.length;
212     }
213
214     @Override
215     public String getColumnName(int col)
216     {
217       return columnNames[col];
218     }
219
220     @Override
221     public Object getValueAt(int row, int col)
222     {
223       return data[row][col];
224     }
225
226     /*
227      * JTable uses this method to determine the default renderer/ editor for
228      * each cell. If we didn't implement this method, then the last column would
229      * contain text ("true"/"false"), rather than a check box.
230      */
231     @Override
232     public Class getColumnClass(int c)
233     {
234       return getValueAt(0, c).getClass();
235     }
236
237     /*
238      * Don't need to implement this method unless your table's editable.
239      */
240     @Override
241     public boolean isCellEditable(int row, int col)
242     {
243       // Note that the data/cell address is constant,
244       // no matter where the cell appears onscreen.
245       // !isPDBID(row, col) ensures the PDB_Id cell is never editable as it
246       // serves as a unique id for each row.
247       // return (col == 1 || col == 2) && !isPDBID(row, col);
248       switch (currentSource)
249       {
250       case SEARCH_SUMMARY:
251       case STRUCTURE_CHOOSER:
252         return (col == 0) && !isPrimaryKeyCell(row, 1);
253       case PREFERENCES:
254         return (col == 1 || col == 2) && !isPrimaryKeyCell(row, 0);
255       default:
256         return false;
257       }
258
259     }
260
261     /**
262      * Determines whether the data in a given cell is a PDB ID.
263      * 
264      * @param row
265      * @param col
266      * @return
267      */
268
269     public boolean isPrimaryKeyCell(int row, int col)
270     {
271       String name = getValueAt(row, col).toString();
272       FTSDataColumnI pdbField = map.get(name);
273       return pdbField.isPrimaryKeyColumn();
274     }
275
276     /*
277      * Don't need to implement this method unless your table's data can change.
278      */
279     @Override
280     public void setValueAt(Object value, int row, int col)
281     {
282       data[row][col] = value;
283       fireTableCellUpdated(row, col);
284
285       String name = null;
286       switch (currentSource)
287       {
288       case SEARCH_SUMMARY:
289       case STRUCTURE_CHOOSER:
290         name = getValueAt(row, 1).toString();
291         break;
292       case PREFERENCES:
293         name = getValueAt(row, 0).toString();
294         break;
295       default:
296         break;
297       }
298       boolean selected = ((Boolean) value).booleanValue();
299
300       FTSDataColumnI ftsDataColumn = map.get(name);
301
302       if (currentSource == PreferenceSource.SEARCH_SUMMARY)
303       {
304         updatePrefs(ftsRestClient.getAllDefaultDisplayedFTSDataColumns(),
305                 ftsDataColumn, selected);
306       }
307       else if (currentSource == PreferenceSource.STRUCTURE_CHOOSER)
308       {
309         updatePrefs(structSummaryColumns, ftsDataColumn, selected);
310       }
311       else if (currentSource == PreferenceSource.PREFERENCES)
312       {
313         if (col == 1)
314         {
315           updatePrefs(ftsRestClient.getAllDefaultDisplayedFTSDataColumns(),
316                   ftsDataColumn, selected);
317         }
318         else if (col == 2)
319         {
320           updatePrefs(structSummaryColumns, ftsDataColumn, selected);
321         }
322       }
323     }
324
325     private void updatePrefs(Collection<FTSDataColumnI> prefConfig,
326             FTSDataColumnI dataColumn, boolean selected)
327     {
328       if (prefConfig.contains(dataColumn) && !selected)
329       {
330         prefConfig.remove(dataColumn);
331       }
332
333       if (!prefConfig.contains(dataColumn) && selected)
334       {
335         prefConfig.add(dataColumn);
336       }
337     }
338
339   }
340 }