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