JAL-1668 added validation for manual entry of pdb structures
[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.util.MessageManager;
28
29 import java.awt.BorderLayout;
30 import java.awt.CardLayout;
31 import java.awt.Dimension;
32 import java.awt.FlowLayout;
33 import java.awt.event.ActionEvent;
34 import java.awt.event.ItemEvent;
35 import java.awt.event.ItemListener;
36
37 import javax.swing.ImageIcon;
38 import javax.swing.JButton;
39 import javax.swing.JCheckBox;
40 import javax.swing.JComboBox;
41 import javax.swing.JFrame;
42 import javax.swing.JInternalFrame;
43 import javax.swing.JLabel;
44 import javax.swing.JPanel;
45 import javax.swing.JScrollPane;
46 import javax.swing.JTable;
47 import javax.swing.JTextField;
48 import javax.swing.event.DocumentEvent;
49 import javax.swing.event.DocumentListener;
50
51 @SuppressWarnings("serial")
52 /**
53  * GUI layout for structure chooser 
54  * @author tcnofoegbu
55  *
56  */
57 public abstract class GStructureChooser extends JPanel implements
58         ItemListener
59 {
60   protected String frameTitle = MessageManager
61           .getString("label.structure_chooser");
62
63   protected JInternalFrame mainFrame = new JInternalFrame(frameTitle);
64
65   protected JComboBox<FilterOption> cmb_filterOption = new JComboBox<FilterOption>();
66
67
68   protected AlignmentPanel ap;
69
70   protected JLabel lbl_result = new JLabel(
71           MessageManager.getString("label.select"));
72
73   protected JButton btn_view = new JButton();
74
75   protected JButton btn_cancel = new JButton();
76
77   protected JButton btn_pdbFromFile = new JButton();
78
79   protected JTextField txt_search = new JTextField(14);
80
81   private JPanel pnl_actions = new JPanel();
82
83   private JPanel pnl_filter = new JPanel();
84
85   private JPanel pnl_idInput = new JPanel(new FlowLayout());
86
87   private JPanel pnl_fileChooser = new JPanel(new FlowLayout());
88
89   private JPanel pnl_idInputBL = new JPanel(new BorderLayout());
90
91   private JPanel pnl_fileChooserBL = new JPanel(new BorderLayout());
92
93   protected JPanel pnl_switchableViews = new JPanel(new CardLayout());
94
95   protected CardLayout layout_switchableViews = (CardLayout) (pnl_switchableViews
96           .getLayout());
97
98   private BorderLayout mainLayout = new BorderLayout();
99
100   protected JCheckBox chk_rememberSettings = new JCheckBox(
101           MessageManager.getString("label.dont_ask_me_again"));
102
103   protected JCheckBox chk_invertFilter = new JCheckBox(
104           MessageManager.getString("label.invert"));
105
106   protected ImageIcon loadingImage = new ImageIcon(getClass().getResource(
107           "/images/loading.gif"));
108
109   protected ImageIcon goodImage = new ImageIcon(getClass().getResource(
110           "/images/good.png"));
111
112   protected ImageIcon errorImage = new ImageIcon(getClass().getResource(
113           "/images/error.png"));
114
115   protected JLabel lbl_loading = new JLabel(loadingImage);
116
117   protected JLabel lbl_pdbManualFetchStatus = new JLabel(errorImage);
118
119   protected JLabel lbl_fromFileStatus = new JLabel(errorImage);
120
121   protected AssciateSeqPanel idInputAssSeqPanel = new AssciateSeqPanel();
122
123   protected AssciateSeqPanel fileChooserAssSeqPanel = new AssciateSeqPanel();
124
125   protected static final String VIEWS_FILTER = "VIEWS_FILTER";
126
127   protected static final String VIEWS_FROM_FILE = "VIEWS_FROM_FILE";
128
129   protected static final String VIEWS_ENTER_ID = "VIEWS_ENTER_ID";
130
131   // protected JList<PDBResponseSummary> jList_FoundStructures = new
132   // JList<PDBResponseSummary>();
133
134   protected JTable tbl_summary = new JTable();
135
136   protected JScrollPane scrl_foundStructures = new JScrollPane(
137           tbl_summary);
138
139   public GStructureChooser()
140   {
141     try
142     {
143       jbInit();
144       mainFrame.setVisible(false);
145       mainFrame.invalidate();
146       mainFrame.pack();
147     } catch (Exception e)
148     {
149       e.printStackTrace();
150     }
151   }
152
153   /**
154    * Initializes the GUI default properties
155    * 
156    * @throws Exception
157    */
158   private void jbInit() throws Exception
159   {
160     btn_view.setFont(new java.awt.Font("Verdana", 0, 12));
161     btn_view.setText(MessageManager.getString("action.view"));
162     btn_view.addActionListener(new java.awt.event.ActionListener()
163     {
164       public void actionPerformed(ActionEvent e)
165       {
166         ok_ActionPerformed();
167       }
168     });
169     btn_cancel.setFont(new java.awt.Font("Verdana", 0, 12));
170     btn_cancel.setText(MessageManager.getString("action.cancel"));
171     btn_cancel.addActionListener(new java.awt.event.ActionListener()
172     {
173       public void actionPerformed(ActionEvent e)
174       {
175         mainFrame.dispose();
176       }
177     });
178
179     btn_pdbFromFile.setFont(new java.awt.Font("Verdana", 0, 12));
180     String btn_title = MessageManager.getString("label.select_pdb_file");
181     btn_pdbFromFile.setText(btn_title + "              ");
182     btn_pdbFromFile.addActionListener(new java.awt.event.ActionListener()
183     {
184       public void actionPerformed(ActionEvent e)
185       {
186         pdbFromFile_actionPerformed();
187       }
188     });
189
190     scrl_foundStructures.setPreferredSize(new Dimension(500, 300));
191     scrl_foundStructures
192             .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
193
194     cmb_filterOption.setFont(new java.awt.Font("Verdana", 0, 12));
195     chk_invertFilter.setFont(new java.awt.Font("Verdana", 0, 12));
196     chk_rememberSettings.setFont(new java.awt.Font("Verdana", 0, 12));
197
198     cmb_filterOption.addItemListener(this);
199     chk_invertFilter.addItemListener(this);
200
201     pnl_actions.add(chk_rememberSettings);
202     pnl_actions.add(btn_view);
203     pnl_actions.add(btn_cancel);
204
205     // pnl_filter.add(lbl_result);
206     pnl_filter.add(cmb_filterOption);
207     pnl_filter.add(lbl_loading);
208     pnl_filter.add(chk_invertFilter);
209     lbl_loading.setVisible(false);
210
211     txt_search.setToolTipText(MessageManager
212             .getString("label.enter_pdb_id"));
213     cmb_filterOption.setToolTipText(MessageManager
214             .getString("info.select_filter_option"));
215     txt_search.getDocument().addDocumentListener(new DocumentListener()
216     {
217       @Override
218       public void insertUpdate(DocumentEvent e)
219       {
220         txt_search_ActionPerformed();
221       }
222
223       @Override
224       public void removeUpdate(DocumentEvent e)
225       {
226         txt_search_ActionPerformed();
227       }
228
229       @Override
230       public void changedUpdate(DocumentEvent e)
231       {
232         txt_search_ActionPerformed();
233       }
234     });
235     pnl_idInput.add(txt_search);
236     pnl_idInput.add(lbl_pdbManualFetchStatus);
237
238     pnl_fileChooser.add(btn_pdbFromFile);
239     pnl_fileChooser.add(lbl_fromFileStatus);
240
241     pnl_fileChooserBL.add(fileChooserAssSeqPanel, BorderLayout.NORTH);
242     pnl_fileChooserBL.add(pnl_fileChooser, BorderLayout.CENTER);
243
244     pnl_idInputBL.add(idInputAssSeqPanel, BorderLayout.NORTH);
245     pnl_idInputBL.add(pnl_idInput, BorderLayout.CENTER);
246
247     pnl_switchableViews.add(pnl_fileChooserBL, VIEWS_FROM_FILE);
248     pnl_switchableViews.add(pnl_idInputBL, VIEWS_ENTER_ID);
249     pnl_switchableViews.add(scrl_foundStructures, VIEWS_FILTER);
250     
251     this.setLayout(mainLayout);
252     this.add(pnl_filter, java.awt.BorderLayout.NORTH);
253     this.add(pnl_switchableViews, java.awt.BorderLayout.CENTER);
254     this.add(pnl_actions, java.awt.BorderLayout.SOUTH);
255
256     mainFrame.setVisible(true);
257     mainFrame.setContentPane(this);
258     mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
259     Desktop.addInternalFrame(mainFrame, frameTitle, 800, 400);
260   }
261
262   
263   @Override
264   /**
265    * Event listener for the 'filter' combo-box and 'invert' check-box
266    */
267   public void itemStateChanged(ItemEvent e)
268   {
269     stateChanged(e);
270   }
271
272   /**
273    * This inner class provides the data model for the structure filter combo-box
274    * 
275    * @author tcnofoegbu
276    *
277    */
278   public class FilterOption
279   {
280     private String name;
281
282     private String value;
283
284     private String view;
285
286     public FilterOption(String name, String value, String view)
287     {
288       this.name = name;
289       this.value = value;
290       this.view = view;
291     }
292
293     public String getName()
294     {
295       return name;
296     }
297
298     public void setName(String name)
299     {
300       this.name = name;
301     }
302
303     public String getValue()
304     {
305       return value;
306     }
307
308     public void setValue(String value)
309     {
310       this.value = value;
311     }
312
313     public String getView()
314     {
315       return view;
316     }
317
318     public void setView(String view)
319     {
320       this.view = view;
321     }
322
323     public String toString()
324     {
325       return this.name;
326     }
327   }
328
329   /**
330    * This inner class provides the provides the data model for associate
331    * sequence combo-box - cmb_assSeq
332    * 
333    * @author tcnofoegbu
334    *
335    */
336   public class AssociateSeqOptions
337   {
338     private SequenceI sequence;
339     private String name;
340
341     public AssociateSeqOptions(SequenceI seq)
342     {
343       this.sequence = seq;
344       this.name = (seq.getName().length() >= 23) ? seq.getName().substring(
345               0, 23) : seq.getName();
346     }
347
348     public AssociateSeqOptions(String name, SequenceI seq)
349     {
350       this.name = name;
351       this.sequence = seq;
352     }
353
354     public String toString()
355     {
356       return name;
357     }
358
359     public String getName()
360     {
361       return name;
362     }
363
364     public void setName(String name)
365     {
366       this.name = name;
367     }
368
369     public SequenceI getSequence()
370     {
371       return sequence;
372     }
373
374     public void setSequence(SequenceI sequence)
375     {
376       this.sequence = sequence;
377     }
378
379   }
380
381   /**
382    * This inner class holds the Layout and configuration of the panel which
383    * handles association of manually fetched structures to a unique sequence
384    * when more than one sequence selection is made
385    * 
386    * @author tcnofoegbu
387    *
388    */
389   public class AssciateSeqPanel extends JPanel implements ItemListener
390   {
391     private JComboBox<AssociateSeqOptions> cmb_assSeq = new JComboBox<AssociateSeqOptions>();
392     public AssciateSeqPanel()
393     {
394       this.setLayout(new FlowLayout());
395       this.add(cmb_assSeq);
396       cmb_assSeq.setToolTipText(MessageManager
397               .getString("info.associate_wit_sequence"));
398       cmb_assSeq.addItemListener(this);
399     }
400
401     public void loadCmbAssSeq()
402     {
403       populateCmbAssociateSeqOptions(cmb_assSeq);
404     }
405
406     public JComboBox<AssociateSeqOptions> getCmb_assSeq()
407     {
408       return cmb_assSeq;
409     }
410
411     public void setCmb_assSeq(JComboBox<AssociateSeqOptions> cmb_assSeq)
412     {
413       this.cmb_assSeq = cmb_assSeq;
414     }
415
416     @Override
417     public void itemStateChanged(ItemEvent e)
418     {
419       if (e.getStateChange() == ItemEvent.SELECTED)
420       {
421         cmbAssSeqStateChanged();
422       }
423     }
424   }
425
426   public JComboBox<FilterOption> getCmbFilterOption()
427   {
428     return cmb_filterOption;
429   }
430
431   protected abstract void stateChanged(ItemEvent e);
432
433   protected abstract void updateCurrentView();
434
435   protected abstract void populateFilterComboBox();
436
437   protected abstract void ok_ActionPerformed();
438
439   protected abstract void pdbFromFile_actionPerformed();
440
441   protected abstract void txt_search_ActionPerformed();
442
443   public abstract void populateCmbAssociateSeqOptions(
444           JComboBox<AssociateSeqOptions> cmb_assSeq);
445
446   public abstract void cmbAssSeqStateChanged();
447 }