JAL-2028 added improvement for preconfigured ordering of custom display options
[jalview.git] / src / jalview / jbgui / PDBDocFieldPreferences.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.jbgui;
22
23 import jalview.ws.dbsources.PDBRestClient.PDBDocField;
24 import jalview.ws.dbsources.PDBRestClient.PDBDocField.Group;
25
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Comparator;
29 import java.util.HashMap;
30 import java.util.LinkedHashSet;
31 import java.util.List;
32
33 import javax.swing.JScrollPane;
34 import javax.swing.JTable;
35 import javax.swing.RowSorter;
36 import javax.swing.SortOrder;
37 import javax.swing.table.AbstractTableModel;
38 import javax.swing.table.TableModel;
39 import javax.swing.table.TableRowSorter;
40
41
42 @SuppressWarnings("serial")
43 public class PDBDocFieldPreferences extends JScrollPane
44 {
45   protected JTable tbl_pdbDocFieldConfig = new JTable();
46
47   protected JScrollPane scrl_pdbDocFieldConfig = new JScrollPane(
48           tbl_pdbDocFieldConfig);
49
50   private HashMap<String, PDBDocField> map = new HashMap<String, PDBDocField>();
51
52   private static Collection<PDBDocField> searchSummaryFields = new LinkedHashSet<PDBDocField>();
53
54   private static Collection<PDBDocField> structureSummaryFields = new LinkedHashSet<PDBDocField>();
55
56   public enum PreferenceSource
57   {
58     SEARCH_SUMMARY, STRUCTURE_CHOOSER, PREFERENCES;
59   }
60
61   private PreferenceSource currentSource;
62
63   static
64   {
65     searchSummaryFields.add(PDBDocField.PDB_ID);
66     searchSummaryFields.add(PDBDocField.TITLE);
67
68     structureSummaryFields.add(PDBDocField.PDB_ID);
69     structureSummaryFields.add(PDBDocField.TITLE);
70   }
71
72   public PDBDocFieldPreferences(PreferenceSource source)
73   {
74     tbl_pdbDocFieldConfig.setAutoCreateRowSorter(true);
75
76
77
78     this.getViewport().add(tbl_pdbDocFieldConfig);
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[PDBDocField.values().length - 1][3];
99     int x = 0;
100     for (PDBDocField field : PDBDocField.values())
101     {
102       if (field.getName().equalsIgnoreCase("all"))
103       {
104         continue;
105       }
106
107       switch (source)
108       {
109       case SEARCH_SUMMARY:
110         data[x++] = new Object[] { searchSummaryFields.contains(field),
111             field.getName(), field.getGroup() };
112         break;
113       case STRUCTURE_CHOOSER:
114         data[x++] = new Object[] { structureSummaryFields.contains(field),
115             field.getName(), field.getGroup() };
116         break;
117       case PREFERENCES:
118         data[x++] = new Object[] { field.getName(),
119             searchSummaryFields.contains(field),
120             structureSummaryFields.contains(field) };
121         break;
122       default:
123         break;
124       }
125       map.put(field.getName(), field);
126     }
127
128     PDBFieldTableModel model = new PDBFieldTableModel(columnNames, data);
129     tbl_pdbDocFieldConfig.setModel(model);
130
131     // DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer();
132     // rightRenderer.setHorizontalAlignment(SwingConstants.LEFT);
133     // tbl_pdbDocFieldConfig.getColumn("Show in structure summary")
134     // .setCellRenderer(rightRenderer);
135     switch (source)
136     {
137     case SEARCH_SUMMARY:
138     case STRUCTURE_CHOOSER:
139       tbl_pdbDocFieldConfig.getColumnModel().getColumn(0)
140               .setPreferredWidth(5);
141       tbl_pdbDocFieldConfig.getColumnModel().getColumn(1)
142               .setPreferredWidth(195);
143       tbl_pdbDocFieldConfig.getColumnModel().getColumn(2)
144               .setPreferredWidth(200);
145
146       TableRowSorter<TableModel> sorter = new TableRowSorter<>(
147               tbl_pdbDocFieldConfig.getModel());
148       tbl_pdbDocFieldConfig.setRowSorter(sorter);
149       List<RowSorter.SortKey> sortKeys = new ArrayList<>();
150       int columnIndexToSort = 2;
151       sortKeys.add(new RowSorter.SortKey(columnIndexToSort,
152               SortOrder.ASCENDING));
153       sorter.setSortKeys(sortKeys);
154       sorter.setComparator(
155               columnIndexToSort,
156               new Comparator<jalview.ws.dbsources.PDBRestClient.PDBDocField.Group>()
157               {
158                 @Override
159                 public int compare(Group o1, Group o2)
160                 {
161                   return o1.getSortOrder() - o2.getSortOrder();
162                 }
163               });
164       sorter.sort();
165       break;
166     case PREFERENCES:
167     default:
168       break;
169     }
170
171
172   }
173
174   public static Collection<PDBDocField> getSearchSummaryFields()
175   {
176     return searchSummaryFields;
177   }
178
179   public static void setSearchSummaryFields(
180           Collection<PDBDocField> searchSummaryFields)
181   {
182     PDBDocFieldPreferences.searchSummaryFields = searchSummaryFields;
183   }
184
185   public static Collection<PDBDocField> getStructureSummaryFields()
186   {
187     return structureSummaryFields;
188   }
189
190   public static void setStructureSummaryFields(
191           Collection<PDBDocField> structureSummaryFields)
192   {
193     PDBDocFieldPreferences.structureSummaryFields = structureSummaryFields;
194   }
195
196   class PDBFieldTableModel extends AbstractTableModel
197   {
198
199     public PDBFieldTableModel(String[] columnNames, Object[][] data)
200     {
201       this.data = data;
202       this.columnNames = columnNames;
203     }
204
205     private Object[][] data;
206
207     private String[] columnNames;
208
209     @Override
210     public int getColumnCount()
211     {
212       return columnNames.length;
213     }
214
215     @Override
216     public int getRowCount()
217     {
218       return data.length;
219     }
220
221     @Override
222     public String getColumnName(int col)
223     {
224       return columnNames[col];
225     }
226
227     @Override
228     public Object getValueAt(int row, int col)
229     {
230       return data[row][col];
231     }
232
233     /*
234      * JTable uses this method to determine the default renderer/ editor for
235      * each cell. If we didn't implement this method, then the last column would
236      * contain text ("true"/"false"), rather than a check box.
237      */
238     @Override
239     public Class getColumnClass(int c)
240     {
241       return getValueAt(0, c).getClass();
242     }
243
244     /*
245      * Don't need to implement this method unless your table's editable.
246      */
247     @Override
248     public boolean isCellEditable(int row, int col)
249     {
250       // Note that the data/cell address is constant,
251       // no matter where the cell appears onscreen.
252       // !isPDBID(row, col) ensures the PDB_Id cell is never editable as it
253       // serves as a unique id for each row.
254       // return (col == 1 || col == 2) && !isPDBID(row, col);
255       switch (currentSource)
256       {
257       case SEARCH_SUMMARY:
258       case STRUCTURE_CHOOSER:
259         return (col == 0) && !isPDBID(row, 1);
260       case PREFERENCES:
261         return (col == 1 || col == 2) && !isPDBID(row, 0);
262       default:
263         return false;
264       }
265
266     }
267
268     /**
269      * Determines whether the data in a given cell is a PDB ID.
270      * 
271      * @param row
272      * @param col
273      * @return
274      */
275
276     public boolean isPDBID(int row, int col)
277     {
278       boolean matched = false;
279       String name = getValueAt(row, col).toString();
280       PDBDocField pdbField = map.get(name);
281       if (pdbField == PDBDocField.PDB_ID)
282       {
283         matched = true;
284       }
285       return matched;
286     }
287
288     /*
289      * Don't need to implement this method unless your table's data can change.
290      */
291     @Override
292     public void setValueAt(Object value, int row, int col)
293     {
294       data[row][col] = value;
295       fireTableCellUpdated(row, col);
296
297       String name = null;
298       switch (currentSource)
299       {
300       case SEARCH_SUMMARY:
301       case STRUCTURE_CHOOSER:
302         name = getValueAt(row, 1).toString();
303         break;
304       case PREFERENCES:
305         name = getValueAt(row, 0).toString();
306         break;
307       default:
308         break;
309       }
310       boolean selected = ((Boolean) value).booleanValue();
311
312       PDBDocField pdbField = map.get(name);
313
314       if (currentSource == PreferenceSource.SEARCH_SUMMARY)
315       {
316         updatePrefs(searchSummaryFields, pdbField, selected);
317       }
318       else if (currentSource == PreferenceSource.STRUCTURE_CHOOSER)
319       {
320         updatePrefs(structureSummaryFields, pdbField, selected);
321       }
322       else if (currentSource == PreferenceSource.PREFERENCES)
323       {
324         if (col == 1)
325         {
326           updatePrefs(searchSummaryFields, pdbField, selected);
327         }
328         else if (col == 2)
329         {
330           updatePrefs(structureSummaryFields, pdbField, selected);
331         }
332       }
333     }
334
335     private void updatePrefs(Collection<PDBDocField> prefConfig,
336             PDBDocField pdbField, boolean selected)
337     {
338       if (prefConfig.contains(pdbField) && !selected)
339       {
340         prefConfig.remove(pdbField);
341       }
342
343       if (!prefConfig.contains(pdbField) && selected)
344       {
345         prefConfig.add(pdbField);
346       }
347     }
348
349   }
350 }