JAL-1645 source formatting and organise imports
[jalview.git] / src / jalview / jbgui / GStructureChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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
22 package jalview.jbgui;
23
24 import jalview.datamodel.SequenceI;
25 import jalview.gui.AlignmentPanel;
26 import jalview.gui.Desktop;
27 import jalview.gui.JvSwingUtils;
28 import jalview.jbgui.PDBDocFieldPreferences.PreferenceSource;
29 import jalview.util.MessageManager;
30 import jalview.ws.dbsources.PDBRestClient;
31 import jalview.ws.dbsources.PDBRestClient.PDBDocField;
32
33 import java.awt.BorderLayout;
34 import java.awt.CardLayout;
35 import java.awt.Dimension;
36 import java.awt.FlowLayout;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ItemEvent;
39 import java.awt.event.ItemListener;
40 import java.awt.event.MouseAdapter;
41 import java.awt.event.MouseEvent;
42 import java.util.Arrays;
43
44 import javax.swing.ImageIcon;
45 import javax.swing.JButton;
46 import javax.swing.JCheckBox;
47 import javax.swing.JComboBox;
48 import javax.swing.JFrame;
49 import javax.swing.JInternalFrame;
50 import javax.swing.JLabel;
51 import javax.swing.JPanel;
52 import javax.swing.JScrollPane;
53 import javax.swing.JTabbedPane;
54 import javax.swing.JTable;
55 import javax.swing.JTextField;
56 import javax.swing.event.ChangeEvent;
57 import javax.swing.event.ChangeListener;
58 import javax.swing.event.DocumentEvent;
59 import javax.swing.event.DocumentListener;
60
61 @SuppressWarnings("serial")
62 /**
63  * GUI layout for structure chooser 
64  * @author tcnofoegbu
65  *
66  */
67 public abstract class GStructureChooser extends JPanel implements
68         ItemListener
69 {
70   protected String frameTitle = MessageManager
71           .getString("label.structure_chooser");
72
73   protected JInternalFrame mainFrame = new JInternalFrame(frameTitle);
74
75   protected JComboBox<FilterOption> cmb_filterOption = new JComboBox<FilterOption>();
76
77   protected AlignmentPanel ap;
78
79   protected StringBuilder errorWarning = new StringBuilder();
80
81   protected JLabel lbl_result = new JLabel(
82           MessageManager.getString("label.select"));
83
84   protected JButton btn_view = new JButton();
85
86   protected JButton btn_cancel = new JButton();
87
88   protected JButton btn_pdbFromFile = new JButton();
89
90   protected JTextField txt_search = new JTextField(14);
91
92   private JPanel pnl_actions = new JPanel();
93
94   private JPanel pnl_main = new JPanel();
95
96   private JPanel pnl_idInput = new JPanel(new FlowLayout());
97
98   private JPanel pnl_fileChooser = new JPanel(new FlowLayout());
99
100   private JPanel pnl_idInputBL = new JPanel(new BorderLayout());
101
102   private JPanel pnl_fileChooserBL = new JPanel(new BorderLayout());
103
104   private JPanel pnl_locPDB = new JPanel(new BorderLayout());
105
106   protected JPanel pnl_switchableViews = new JPanel(new CardLayout());
107
108   protected CardLayout layout_switchableViews = (CardLayout) (pnl_switchableViews
109           .getLayout());
110
111   private BorderLayout mainLayout = new BorderLayout();
112
113   protected JCheckBox chk_rememberSettings = new JCheckBox(
114           MessageManager.getString("label.dont_ask_me_again"));
115
116   protected JCheckBox chk_invertFilter = new JCheckBox(
117           MessageManager.getString("label.invert"));
118
119   protected ImageIcon loadingImage = new ImageIcon(getClass().getResource(
120           "/images/loading.gif"));
121
122   protected ImageIcon goodImage = new ImageIcon(getClass().getResource(
123           "/images/good.png"));
124
125   protected ImageIcon errorImage = new ImageIcon(getClass().getResource(
126           "/images/error.png"));
127
128   protected ImageIcon warningImage = new ImageIcon(getClass().getResource(
129           "/images/warning.gif"));
130
131   protected JLabel lbl_warning = new JLabel(warningImage);
132
133   protected JLabel lbl_loading = new JLabel(loadingImage);
134
135   protected JLabel lbl_pdbManualFetchStatus = new JLabel(errorImage);
136
137   protected JLabel lbl_fromFileStatus = new JLabel(errorImage);
138
139   protected AssciateSeqPanel idInputAssSeqPanel = new AssciateSeqPanel();
140
141   protected AssciateSeqPanel fileChooserAssSeqPanel = new AssciateSeqPanel();
142
143   protected static final String VIEWS_FILTER = "VIEWS_FILTER";
144
145   protected static final String VIEWS_FROM_FILE = "VIEWS_FROM_FILE";
146
147   protected static final String VIEWS_ENTER_ID = "VIEWS_ENTER_ID";
148
149   protected static final String VIEWS_LOCAL_PDB = "VIEWS_LOCAL_PDB";
150
151   protected JTable tbl_summary = new JTable()
152   {
153     public String getToolTipText(MouseEvent evt)
154     {
155       String toolTipText = null;
156       java.awt.Point pnt = evt.getPoint();
157       int rowIndex = rowAtPoint(pnt);
158       int colIndex = columnAtPoint(pnt);
159
160       try
161       {
162         toolTipText = getValueAt(rowIndex, colIndex).toString();
163       } catch (Exception e)
164       {
165         e.printStackTrace();
166       }
167       toolTipText = (toolTipText == null ? null
168               : (toolTipText.length() > 500 ? JvSwingUtils.wrapTooltip(
169                       true, "\"" + toolTipText.subSequence(0, 500)
170                               + "...\"") : JvSwingUtils.wrapTooltip(true,
171                       toolTipText)));
172       return toolTipText;
173     }
174   };
175
176   protected JScrollPane scrl_foundStructures = new JScrollPane(tbl_summary);
177
178   protected JTable tbl_local_pdb = new JTable();
179
180   protected JScrollPane scrl_localPDB = new JScrollPane(tbl_local_pdb);
181
182   private JTabbedPane pnl_filter = new JTabbedPane();
183
184   private PDBDocFieldPreferences pdbDocFieldPrefs = new PDBDocFieldPreferences(
185           PreferenceSource.STRUCTURE_CHOOSER);
186
187   protected PDBDocField[] previousWantedFields;
188
189   public GStructureChooser()
190   {
191     try
192     {
193       jbInit();
194       mainFrame.setVisible(false);
195       mainFrame.invalidate();
196       mainFrame.pack();
197     } catch (Exception e)
198     {
199       e.printStackTrace();
200     }
201   }
202
203   /**
204    * Initializes the GUI default properties
205    * 
206    * @throws Exception
207    */
208   private void jbInit() throws Exception
209   {
210     tbl_summary.setAutoCreateRowSorter(true);
211     tbl_summary.getTableHeader().setReorderingAllowed(false);
212     tbl_local_pdb.setAutoCreateRowSorter(true);
213     tbl_local_pdb.getTableHeader().setReorderingAllowed(false);
214     tbl_local_pdb.addMouseListener(new MouseAdapter()
215     {
216       public void mouseClicked(MouseEvent e)
217       {
218         updateCurrentView();
219       }
220
221       public void mouseReleased(MouseEvent e)
222       {
223         updateCurrentView();
224       }
225     });
226
227     btn_view.setFont(new java.awt.Font("Verdana", 0, 12));
228     btn_view.setText(MessageManager.getString("action.view"));
229     btn_view.addActionListener(new java.awt.event.ActionListener()
230     {
231       public void actionPerformed(ActionEvent e)
232       {
233         ok_ActionPerformed();
234       }
235     });
236     btn_cancel.setFont(new java.awt.Font("Verdana", 0, 12));
237     btn_cancel.setText(MessageManager.getString("action.cancel"));
238     btn_cancel.addActionListener(new java.awt.event.ActionListener()
239     {
240       public void actionPerformed(ActionEvent e)
241       {
242         mainFrame.dispose();
243       }
244     });
245
246     btn_pdbFromFile.setFont(new java.awt.Font("Verdana", 0, 12));
247     String btn_title = MessageManager.getString("label.select_pdb_file");
248     btn_pdbFromFile.setText(btn_title + "              ");
249     btn_pdbFromFile.addActionListener(new java.awt.event.ActionListener()
250     {
251       public void actionPerformed(ActionEvent e)
252       {
253         pdbFromFile_actionPerformed();
254       }
255     });
256
257     scrl_foundStructures.setPreferredSize(new Dimension(500, 300));
258     scrl_foundStructures
259             .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
260
261     scrl_localPDB.setPreferredSize(new Dimension(500, 300));
262     scrl_localPDB
263             .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
264
265     cmb_filterOption.setFont(new java.awt.Font("Verdana", 0, 12));
266     chk_invertFilter.setFont(new java.awt.Font("Verdana", 0, 12));
267     chk_rememberSettings.setFont(new java.awt.Font("Verdana", 0, 12));
268     chk_rememberSettings.setVisible(false);
269
270     txt_search.setToolTipText(MessageManager
271             .getString("label.enter_pdb_id"));
272     cmb_filterOption.setToolTipText(MessageManager
273             .getString("info.select_filter_option"));
274     txt_search.getDocument().addDocumentListener(new DocumentListener()
275     {
276       @Override
277       public void insertUpdate(DocumentEvent e)
278       {
279         txt_search_ActionPerformed();
280       }
281
282       @Override
283       public void removeUpdate(DocumentEvent e)
284       {
285         txt_search_ActionPerformed();
286       }
287
288       @Override
289       public void changedUpdate(DocumentEvent e)
290       {
291         txt_search_ActionPerformed();
292       }
293     });
294
295     cmb_filterOption.addItemListener(this);
296     chk_invertFilter.addItemListener(this);
297
298     pnl_actions.add(chk_rememberSettings);
299     pnl_actions.add(btn_view);
300     pnl_actions.add(btn_cancel);
301
302     // pnl_filter.add(lbl_result);
303     pnl_main.add(cmb_filterOption);
304     pnl_main.add(lbl_loading);
305     pnl_main.add(chk_invertFilter);
306     lbl_loading.setVisible(false);
307
308     pnl_fileChooser.add(btn_pdbFromFile);
309     pnl_fileChooser.add(lbl_fromFileStatus);
310     pnl_fileChooserBL.add(fileChooserAssSeqPanel, BorderLayout.NORTH);
311     pnl_fileChooserBL.add(pnl_fileChooser, BorderLayout.CENTER);
312
313     pnl_idInput.add(txt_search);
314     pnl_idInput.add(lbl_pdbManualFetchStatus);
315     pnl_idInputBL.add(idInputAssSeqPanel, BorderLayout.NORTH);
316     pnl_idInputBL.add(pnl_idInput, BorderLayout.CENTER);
317
318     final String foundStructureSummary = MessageManager
319             .getString("label.found_structures_summary");
320     final String configureCols = MessageManager
321             .getString("label.configure_displayed_columns");
322     ChangeListener changeListener = new ChangeListener()
323     {
324       public void stateChanged(ChangeEvent changeEvent)
325       {
326         JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent
327                 .getSource();
328         int index = sourceTabbedPane.getSelectedIndex();
329         if (sourceTabbedPane.getTitleAt(index).equals(configureCols))
330         {
331           btn_view.setEnabled(false);
332           btn_cancel.setEnabled(false);
333           previousWantedFields = PDBDocFieldPreferences
334                   .getStructureSummaryFields().toArray(
335                           new PDBRestClient.PDBDocField[0]);
336         }
337         if (sourceTabbedPane.getTitleAt(index)
338                 .equals(foundStructureSummary))
339         {
340           btn_cancel.setEnabled(true);
341           if (wantedFieldsUpdated())
342           {
343             tabRefresh();
344           }
345           else
346           {
347             validateSelections();
348           }
349         }
350       }
351     };
352     pnl_filter.addChangeListener(changeListener);
353     pnl_filter.setPreferredSize(new Dimension(500, 300));
354     pnl_filter.add(foundStructureSummary, scrl_foundStructures);
355     pnl_filter.add(configureCols, pdbDocFieldPrefs);
356
357     pnl_locPDB.add(scrl_localPDB);
358
359     pnl_switchableViews.add(pnl_fileChooserBL, VIEWS_FROM_FILE);
360     pnl_switchableViews.add(pnl_idInputBL, VIEWS_ENTER_ID);
361     pnl_switchableViews.add(pnl_filter, VIEWS_FILTER);
362     pnl_switchableViews.add(pnl_locPDB, VIEWS_LOCAL_PDB);
363
364     this.setLayout(mainLayout);
365     this.add(pnl_main, java.awt.BorderLayout.NORTH);
366     this.add(pnl_switchableViews, java.awt.BorderLayout.CENTER);
367     this.add(pnl_actions, java.awt.BorderLayout.SOUTH);
368
369     mainFrame.setVisible(true);
370     mainFrame.setContentPane(this);
371     mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
372     Desktop.addInternalFrame(mainFrame, frameTitle, 800, 400);
373   }
374
375   public boolean wantedFieldsUpdated()
376   {
377     if (previousWantedFields == null)
378     {
379       return true;
380     }
381
382     return Arrays.equals(PDBDocFieldPreferences.getStructureSummaryFields()
383             .toArray(new PDBRestClient.PDBDocField[0]),
384             previousWantedFields) ? false : true;
385
386   }
387
388   @Override
389   /**
390    * Event listener for the 'filter' combo-box and 'invert' check-box
391    */
392   public void itemStateChanged(ItemEvent e)
393   {
394     stateChanged(e);
395   }
396
397   /**
398    * This inner class provides the data model for the structure filter combo-box
399    * 
400    * @author tcnofoegbu
401    *
402    */
403   public class FilterOption
404   {
405     private String name;
406
407     private String value;
408
409     private String view;
410
411     public FilterOption(String name, String value, String view)
412     {
413       this.name = name;
414       this.value = value;
415       this.view = view;
416     }
417
418     public String getName()
419     {
420       return name;
421     }
422
423     public void setName(String name)
424     {
425       this.name = name;
426     }
427
428     public String getValue()
429     {
430       return value;
431     }
432
433     public void setValue(String value)
434     {
435       this.value = value;
436     }
437
438     public String getView()
439     {
440       return view;
441     }
442
443     public void setView(String view)
444     {
445       this.view = view;
446     }
447
448     public String toString()
449     {
450       return this.name;
451     }
452   }
453
454   /**
455    * This inner class provides the provides the data model for associate
456    * sequence combo-box - cmb_assSeq
457    * 
458    * @author tcnofoegbu
459    *
460    */
461   public class AssociateSeqOptions
462   {
463     private SequenceI sequence;
464
465     private String name;
466
467     public AssociateSeqOptions(SequenceI seq)
468     {
469       this.sequence = seq;
470       this.name = (seq.getName().length() >= 23) ? seq.getName().substring(
471               0, 23) : seq.getName();
472     }
473
474     public AssociateSeqOptions(String name, SequenceI seq)
475     {
476       this.name = name;
477       this.sequence = seq;
478     }
479
480     public String toString()
481     {
482       return name;
483     }
484
485     public String getName()
486     {
487       return name;
488     }
489
490     public void setName(String name)
491     {
492       this.name = name;
493     }
494
495     public SequenceI getSequence()
496     {
497       return sequence;
498     }
499
500     public void setSequence(SequenceI sequence)
501     {
502       this.sequence = sequence;
503     }
504
505   }
506
507   /**
508    * This inner class holds the Layout and configuration of the panel which
509    * handles association of manually fetched structures to a unique sequence
510    * when more than one sequence selection is made
511    * 
512    * @author tcnofoegbu
513    *
514    */
515   public class AssciateSeqPanel extends JPanel implements ItemListener
516   {
517     private JComboBox<AssociateSeqOptions> cmb_assSeq = new JComboBox<AssociateSeqOptions>();
518
519     private JLabel lbl_associateSeq = new JLabel();
520
521     public AssciateSeqPanel()
522     {
523       this.setLayout(new FlowLayout());
524       this.add(cmb_assSeq);
525       this.add(lbl_associateSeq);
526       cmb_assSeq.setToolTipText(MessageManager
527               .getString("info.associate_wit_sequence"));
528       cmb_assSeq.addItemListener(this);
529     }
530
531     public void loadCmbAssSeq()
532     {
533       populateCmbAssociateSeqOptions(cmb_assSeq, lbl_associateSeq);
534     }
535
536     public JComboBox<AssociateSeqOptions> getCmb_assSeq()
537     {
538       return cmb_assSeq;
539     }
540
541     public void setCmb_assSeq(JComboBox<AssociateSeqOptions> cmb_assSeq)
542     {
543       this.cmb_assSeq = cmb_assSeq;
544     }
545
546     @Override
547     public void itemStateChanged(ItemEvent e)
548     {
549       if (e.getStateChange() == ItemEvent.SELECTED)
550       {
551         cmbAssSeqStateChanged();
552       }
553     }
554   }
555
556   public JComboBox<FilterOption> getCmbFilterOption()
557   {
558     return cmb_filterOption;
559   }
560
561   protected abstract void stateChanged(ItemEvent e);
562
563   protected abstract void updateCurrentView();
564
565   protected abstract void populateFilterComboBox();
566
567   protected abstract void ok_ActionPerformed();
568
569   protected abstract void pdbFromFile_actionPerformed();
570
571   protected abstract void txt_search_ActionPerformed();
572
573   public abstract void populateCmbAssociateSeqOptions(
574           JComboBox<AssociateSeqOptions> cmb_assSeq, JLabel lbl_associateSeq);
575
576   public abstract void cmbAssSeqStateChanged();
577
578   public abstract void tabRefresh();
579
580   public abstract void validateSelections();
581 }