cddcc8e8e29dbcaecb2b1a228da7445254bace91
[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
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Comparator;
30 import java.util.HashMap;
31 import java.util.LinkedHashSet;
32 import java.util.List;
33
34 import javax.swing.JScrollPane;
35 import javax.swing.JTable;
36 import javax.swing.RowSorter;
37 import javax.swing.SortOrder;
38 import javax.swing.table.AbstractTableModel;
39 import javax.swing.table.TableModel;
40 import javax.swing.table.TableRowSorter;
41
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     Collection<FTSDataColumnI> defaultCols = ftsRestClient
71             .getAllDefaulDisplayedDataColumns();
72
73     structSummaryColumns.addAll(defaultCols);
74
75     allFTSDataColumns.addAll(ftsRestClient.getAllFTSDataColumns());
76
77     tbl_FTSDataColumnPrefs.setAutoCreateRowSorter(true);
78     this.getViewport().add(tbl_FTSDataColumnPrefs);
79     this.currentSource = source;
80
81     String[] columnNames = null;
82     switch (source)
83     {
84     case SEARCH_SUMMARY:
85       columnNames = new String[] { "", "Display", "Group" };
86       break;
87     case STRUCTURE_CHOOSER:
88       columnNames = new String[] { "", "Display", "Group" };
89       break;
90     case PREFERENCES:
91       columnNames = new String[] { "PDB Field", "Show in search summary",
92           "Show in structure summary" };
93       break;
94     default:
95       break;
96     }
97
98     Object[][] data = new Object[allFTSDataColumns.size() - 1][3];
99
100     int x = 0;
101     for (FTSDataColumnI field : allFTSDataColumns)
102     {
103       if (field.getName().equalsIgnoreCase("all"))
104       {
105         continue;
106       }
107
108       switch (source)
109       {
110       case SEARCH_SUMMARY:
111         data[x++] = new Object[] {
112             ftsRestClient.getAllDefaulDisplayedDataColumns()
113                     .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[] { field.getName(),
122             ftsRestClient.getAllDefaulDisplayedDataColumns()
123                     .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(columnNames, data);
133     tbl_FTSDataColumnPrefs.setModel(model);
134
135     switch (source)
136     {
137     case SEARCH_SUMMARY:
138     case STRUCTURE_CHOOSER:
139       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0)
140               .setPreferredWidth(30);
141       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0).setMinWidth(20);
142       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(0).setMaxWidth(40);
143       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(1)
144               .setPreferredWidth(150);
145       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(1).setMinWidth(150);
146       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(2)
147               .setPreferredWidth(150);
148       tbl_FTSDataColumnPrefs.getColumnModel().getColumn(2)
149 .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(
160               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.sort();
171
172       tbl_FTSDataColumnPrefs
173               .setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
174       break;
175     case PREFERENCES:
176     default:
177       break;
178     }
179
180   }
181
182   public Collection<FTSDataColumnI> getStructureSummaryFields()
183   {
184     return structSummaryColumns;
185   }
186
187   class FTSDataColumnPrefsTableModel extends AbstractTableModel
188   {
189
190     public FTSDataColumnPrefsTableModel(String[] columnNames, 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
303                 .getAllDefaulDisplayedDataColumns(), ftsDataColumn,
304                 selected);
305       }
306       else if (currentSource == PreferenceSource.STRUCTURE_CHOOSER)
307       {
308         updatePrefs(structSummaryColumns, ftsDataColumn, selected);
309       }
310       else if (currentSource == PreferenceSource.PREFERENCES)
311       {
312         if (col == 1)
313         {
314           updatePrefs(ftsRestClient
315                   .getAllDefaulDisplayedDataColumns(), ftsDataColumn,
316                   selected);
317         }
318         else if (col == 2)
319         {
320           updatePrefs(structSummaryColumns, ftsDataColumn, selected);
321         }
322       }
323     }
324
325     private void updatePrefs(
326             Collection<FTSDataColumnI> prefConfig,
327             FTSDataColumnI dataColumn, boolean selected)
328     {
329       if (prefConfig.contains(dataColumn) && !selected)
330       {
331         prefConfig.remove(dataColumn);
332       }
333
334       if (!prefConfig.contains(dataColumn) && selected)
335       {
336         prefConfig.add(dataColumn);
337       }
338     }
339
340   }
341 }