JAL-1834 added tooltip to the PDB sequence fetcher and structure chooser summary...
[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
140   protected AssciateSeqPanel idInputAssSeqPanel = new AssciateSeqPanel();
141
142   protected AssciateSeqPanel fileChooserAssSeqPanel = new AssciateSeqPanel();
143
144   protected static final String VIEWS_FILTER = "VIEWS_FILTER";
145
146   protected static final String VIEWS_FROM_FILE = "VIEWS_FROM_FILE";
147
148   protected static final String VIEWS_ENTER_ID = "VIEWS_ENTER_ID";
149
150   protected static final String VIEWS_LOCAL_PDB = "VIEWS_LOCAL_PDB";
151
152   protected JTable tbl_summary = new JTable()
153   {
154     public String getToolTipText(MouseEvent evt)
155     {
156       String toolTipText = null;
157       java.awt.Point pnt = evt.getPoint();
158       int rowIndex = rowAtPoint(pnt);
159       int colIndex = columnAtPoint(pnt);
160
161       try
162       {
163         toolTipText = getValueAt(rowIndex, colIndex).toString();
164       } catch (Exception e)
165       {
166         e.printStackTrace();
167       }
168       toolTipText = (toolTipText == null ? null : JvSwingUtils.wrapTooltip(
169               true, toolTipText));
170       return toolTipText;
171     }
172   };
173
174   protected JScrollPane scrl_foundStructures = new JScrollPane(
175           tbl_summary);
176
177   protected JTable tbl_local_pdb = new JTable();
178
179   protected JScrollPane scrl_localPDB = new JScrollPane(tbl_local_pdb);
180
181   private JTabbedPane pnl_filter = new JTabbedPane();
182
183   private PDBDocFieldPreferences pdbDocFieldPrefs = new PDBDocFieldPreferences(
184           PreferenceSource.STRUCTURE_CHOOSER);
185
186   protected PDBDocField[] previousWantedFields;
187   public GStructureChooser()
188   {
189     try
190     {
191       jbInit();
192       mainFrame.setVisible(false);
193       mainFrame.invalidate();
194       mainFrame.pack();
195     } catch (Exception e)
196     {
197       e.printStackTrace();
198     }
199   }
200
201   /**
202    * Initializes the GUI default properties
203    * 
204    * @throws Exception
205    */
206   private void jbInit() throws Exception
207   {
208     tbl_summary.setAutoCreateRowSorter(true);
209     tbl_summary.getTableHeader().setReorderingAllowed(false);
210     tbl_local_pdb.setAutoCreateRowSorter(true);
211     tbl_local_pdb.getTableHeader().setReorderingAllowed(false);
212     tbl_local_pdb.addMouseListener(new MouseAdapter()
213     {
214       public void mouseClicked(MouseEvent e)
215       {
216         updateCurrentView();
217       }
218
219       public void mouseReleased(MouseEvent e)
220       {
221         updateCurrentView();
222       }
223     });
224
225     btn_view.setFont(new java.awt.Font("Verdana", 0, 12));
226     btn_view.setText(MessageManager.getString("action.view"));
227     btn_view.addActionListener(new java.awt.event.ActionListener()
228     {
229       public void actionPerformed(ActionEvent e)
230       {
231         ok_ActionPerformed();
232       }
233     });
234     btn_cancel.setFont(new java.awt.Font("Verdana", 0, 12));
235     btn_cancel.setText(MessageManager.getString("action.cancel"));
236     btn_cancel.addActionListener(new java.awt.event.ActionListener()
237     {
238       public void actionPerformed(ActionEvent e)
239       {
240         mainFrame.dispose();
241       }
242     });
243
244     btn_pdbFromFile.setFont(new java.awt.Font("Verdana", 0, 12));
245     String btn_title = MessageManager.getString("label.select_pdb_file");
246     btn_pdbFromFile.setText(btn_title + "              ");
247     btn_pdbFromFile.addActionListener(new java.awt.event.ActionListener()
248     {
249       public void actionPerformed(ActionEvent e)
250       {
251         pdbFromFile_actionPerformed();
252       }
253     });
254
255     scrl_foundStructures.setPreferredSize(new Dimension(500, 300));
256     scrl_foundStructures
257             .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
258
259     scrl_localPDB.setPreferredSize(new Dimension(500, 300));
260     scrl_localPDB
261             .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
262
263     cmb_filterOption.setFont(new java.awt.Font("Verdana", 0, 12));
264     chk_invertFilter.setFont(new java.awt.Font("Verdana", 0, 12));
265     chk_rememberSettings.setFont(new java.awt.Font("Verdana", 0, 12));
266     chk_rememberSettings.setVisible(false);
267
268     txt_search.setToolTipText(MessageManager
269             .getString("label.enter_pdb_id"));
270     cmb_filterOption.setToolTipText(MessageManager
271             .getString("info.select_filter_option"));
272     txt_search.getDocument().addDocumentListener(new DocumentListener()
273     {
274       @Override
275       public void insertUpdate(DocumentEvent e)
276       {
277         txt_search_ActionPerformed();
278       }
279
280       @Override
281       public void removeUpdate(DocumentEvent e)
282       {
283         txt_search_ActionPerformed();
284       }
285
286       @Override
287       public void changedUpdate(DocumentEvent e)
288       {
289         txt_search_ActionPerformed();
290       }
291     });
292
293     cmb_filterOption.addItemListener(this);
294     chk_invertFilter.addItemListener(this);
295
296     pnl_actions.add(chk_rememberSettings);
297     pnl_actions.add(btn_view);
298     pnl_actions.add(btn_cancel);
299
300     // pnl_filter.add(lbl_result);
301     pnl_main.add(cmb_filterOption);
302     pnl_main.add(lbl_loading);
303     pnl_main.add(chk_invertFilter);
304     lbl_loading.setVisible(false);
305
306
307     pnl_fileChooser.add(btn_pdbFromFile);
308     pnl_fileChooser.add(lbl_fromFileStatus);
309     pnl_fileChooserBL.add(fileChooserAssSeqPanel, BorderLayout.NORTH);
310     pnl_fileChooserBL.add(pnl_fileChooser, BorderLayout.CENTER);
311
312     pnl_idInput.add(txt_search);
313     pnl_idInput.add(lbl_pdbManualFetchStatus);
314     pnl_idInputBL.add(idInputAssSeqPanel, BorderLayout.NORTH);
315     pnl_idInputBL.add(pnl_idInput, BorderLayout.CENTER);
316     
317     final String foundStructureSummary = MessageManager
318             .getString("label.found_structures_summary");
319     final String configureCols = MessageManager
320             .getString("label.configure_displayed_columns");
321     ChangeListener changeListener = new ChangeListener()
322     {
323       public void stateChanged(ChangeEvent changeEvent)
324       {
325         JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent
326                 .getSource();
327         btn_view.setEnabled(false);
328         int index = sourceTabbedPane.getSelectedIndex();
329         if (sourceTabbedPane.getTitleAt(index)
330 .equals(configureCols))
331         {
332           previousWantedFields = PDBDocFieldPreferences
333                   .getStructureSummaryFields().toArray(
334                           new PDBRestClient.PDBDocField[0]);
335         }
336         if (sourceTabbedPane.getTitleAt(index)
337                 .equals(foundStructureSummary))
338         {
339           if (wantedFieldsUpdated())
340           {
341             tabRefresh();
342           }
343           else
344           {
345             validateSelections();
346           }
347         }
348       }
349     };
350     pnl_filter.addChangeListener(changeListener);
351     pnl_filter.setPreferredSize(new Dimension(500, 300));
352     pnl_filter.add(foundStructureSummary, scrl_foundStructures);
353     pnl_filter.add(configureCols, pdbDocFieldPrefs);
354     
355     pnl_locPDB.add(scrl_localPDB);
356
357     pnl_switchableViews.add(pnl_fileChooserBL, VIEWS_FROM_FILE);
358     pnl_switchableViews.add(pnl_idInputBL, VIEWS_ENTER_ID);
359     pnl_switchableViews.add(pnl_filter, VIEWS_FILTER);
360     pnl_switchableViews.add(pnl_locPDB, VIEWS_LOCAL_PDB);
361     
362     this.setLayout(mainLayout);
363     this.add(pnl_main, java.awt.BorderLayout.NORTH);
364     this.add(pnl_switchableViews, java.awt.BorderLayout.CENTER);
365     this.add(pnl_actions, java.awt.BorderLayout.SOUTH);
366
367     mainFrame.setVisible(true);
368     mainFrame.setContentPane(this);
369     mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
370     Desktop.addInternalFrame(mainFrame, frameTitle, 800, 400);
371   }
372
373   public boolean wantedFieldsUpdated()
374   {
375     if (previousWantedFields == null)
376     {
377       return true;
378     }
379
380     return Arrays.equals(PDBDocFieldPreferences.getStructureSummaryFields()
381             .toArray(new PDBRestClient.PDBDocField[0]),
382             previousWantedFields) ? false : true;
383
384   }
385   
386   @Override
387   /**
388    * Event listener for the 'filter' combo-box and 'invert' check-box
389    */
390   public void itemStateChanged(ItemEvent e)
391   {
392     stateChanged(e);
393   }
394
395   /**
396    * This inner class provides the data model for the structure filter combo-box
397    * 
398    * @author tcnofoegbu
399    *
400    */
401   public class FilterOption
402   {
403     private String name;
404
405     private String value;
406
407     private String view;
408
409     public FilterOption(String name, String value, String view)
410     {
411       this.name = name;
412       this.value = value;
413       this.view = view;
414     }
415
416     public String getName()
417     {
418       return name;
419     }
420
421     public void setName(String name)
422     {
423       this.name = name;
424     }
425
426     public String getValue()
427     {
428       return value;
429     }
430
431     public void setValue(String value)
432     {
433       this.value = value;
434     }
435
436     public String getView()
437     {
438       return view;
439     }
440
441     public void setView(String view)
442     {
443       this.view = view;
444     }
445
446     public String toString()
447     {
448       return this.name;
449     }
450   }
451
452   /**
453    * This inner class provides the provides the data model for associate
454    * sequence combo-box - cmb_assSeq
455    * 
456    * @author tcnofoegbu
457    *
458    */
459   public class AssociateSeqOptions
460   {
461     private SequenceI sequence;
462     private String name;
463
464     public AssociateSeqOptions(SequenceI seq)
465     {
466       this.sequence = seq;
467       this.name = (seq.getName().length() >= 23) ? seq.getName().substring(
468               0, 23) : seq.getName();
469     }
470
471     public AssociateSeqOptions(String name, SequenceI seq)
472     {
473       this.name = name;
474       this.sequence = seq;
475     }
476
477     public String toString()
478     {
479       return name;
480     }
481
482     public String getName()
483     {
484       return name;
485     }
486
487     public void setName(String name)
488     {
489       this.name = name;
490     }
491
492     public SequenceI getSequence()
493     {
494       return sequence;
495     }
496
497     public void setSequence(SequenceI sequence)
498     {
499       this.sequence = sequence;
500     }
501
502   }
503
504   /**
505    * This inner class holds the Layout and configuration of the panel which
506    * handles association of manually fetched structures to a unique sequence
507    * when more than one sequence selection is made
508    * 
509    * @author tcnofoegbu
510    *
511    */
512   public class AssciateSeqPanel extends JPanel implements ItemListener
513   {
514     private JComboBox<AssociateSeqOptions> cmb_assSeq = new JComboBox<AssociateSeqOptions>();
515
516     private JLabel lbl_associateSeq = new JLabel();
517
518     public AssciateSeqPanel()
519     {
520       this.setLayout(new FlowLayout());
521       this.add(cmb_assSeq);
522       this.add(lbl_associateSeq);
523       cmb_assSeq.setToolTipText(MessageManager
524               .getString("info.associate_wit_sequence"));
525       cmb_assSeq.addItemListener(this);
526     }
527
528     public void loadCmbAssSeq()
529     {
530       populateCmbAssociateSeqOptions(cmb_assSeq, lbl_associateSeq);
531     }
532
533     public JComboBox<AssociateSeqOptions> getCmb_assSeq()
534     {
535       return cmb_assSeq;
536     }
537
538     public void setCmb_assSeq(JComboBox<AssociateSeqOptions> cmb_assSeq)
539     {
540       this.cmb_assSeq = cmb_assSeq;
541     }
542
543     @Override
544     public void itemStateChanged(ItemEvent e)
545     {
546       if (e.getStateChange() == ItemEvent.SELECTED)
547       {
548         cmbAssSeqStateChanged();
549       }
550     }
551   }
552
553   public JComboBox<FilterOption> getCmbFilterOption()
554   {
555     return cmb_filterOption;
556   }
557
558   protected abstract void stateChanged(ItemEvent e);
559
560   protected abstract void updateCurrentView();
561
562   protected abstract void populateFilterComboBox();
563
564   protected abstract void ok_ActionPerformed();
565
566   protected abstract void pdbFromFile_actionPerformed();
567
568   protected abstract void txt_search_ActionPerformed();
569
570   public abstract void populateCmbAssociateSeqOptions(
571           JComboBox<AssociateSeqOptions> cmb_assSeq, JLabel lbl_associateSeq);
572
573   public abstract void cmbAssSeqStateChanged();
574
575   public abstract void tabRefresh();
576
577   public abstract void validateSelections();
578 }