JAL-2376 copied out patch from Phyre branch
[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.fts.api.FTSDataColumnI;
26 import jalview.fts.core.FTSDataColumnPreferences;
27 import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
28 import jalview.fts.service.pdb.PDBFTSRestClient;
29 import jalview.gui.AlignmentPanel;
30 import jalview.gui.Desktop;
31 import jalview.gui.JvSwingUtils;
32 import jalview.util.MessageManager;
33
34 import java.awt.BorderLayout;
35 import java.awt.CardLayout;
36 import java.awt.Component;
37 import java.awt.Dimension;
38 import java.awt.FlowLayout;
39 import java.awt.GridLayout;
40 import java.awt.event.ActionEvent;
41 import java.awt.event.ItemEvent;
42 import java.awt.event.ItemListener;
43 import java.awt.event.KeyAdapter;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.MouseAdapter;
46 import java.awt.event.MouseEvent;
47 import java.util.Arrays;
48 import java.util.HashMap;
49 import java.util.Map;
50
51 import javax.swing.ImageIcon;
52 import javax.swing.JButton;
53 import javax.swing.JCheckBox;
54 import javax.swing.JComboBox;
55 import javax.swing.JFrame;
56 import javax.swing.JInternalFrame;
57 import javax.swing.JLabel;
58 import javax.swing.JList;
59 import javax.swing.JPanel;
60 import javax.swing.JScrollPane;
61 import javax.swing.JSeparator;
62 import javax.swing.JTabbedPane;
63 import javax.swing.JTable;
64 import javax.swing.JTextField;
65 import javax.swing.ListCellRenderer;
66 import javax.swing.event.ChangeEvent;
67 import javax.swing.event.ChangeListener;
68 import javax.swing.event.DocumentEvent;
69 import javax.swing.event.DocumentListener;
70 import javax.swing.event.InternalFrameEvent;
71 import javax.swing.table.TableColumn;
72
73 @SuppressWarnings("serial")
74 /**
75  * GUI layout for structure chooser 
76  * @author tcnofoegbu
77  *
78  */
79 public abstract class GStructureChooser extends JPanel implements
80         ItemListener
81 {
82   protected JPanel statusPanel = new JPanel();
83
84   public JLabel statusBar = new JLabel();
85
86   private JPanel pnl_actionsAndStatus = new JPanel(new BorderLayout());
87
88   protected String frameTitle = MessageManager
89           .getString("label.structure_chooser");
90
91   protected JInternalFrame mainFrame = new JInternalFrame(frameTitle);
92
93   protected JComboBox<FilterOption> cmb_filterOption = new JComboBox<FilterOption>();
94
95   protected AlignmentPanel ap;
96
97   protected StringBuilder errorWarning = new StringBuilder();
98
99   protected JLabel lbl_result = new JLabel(
100           MessageManager.getString("label.select"));
101
102   protected JButton btn_view = new JButton();
103
104   protected JButton btn_cancel = new JButton();
105
106   protected JButton btn_pdbFromFile = new JButton();
107
108   protected JTextField txt_search = new JTextField(14);
109
110   private JPanel pnl_actions = new JPanel();
111
112   private JPanel pnl_main = new JPanel();
113
114   private JPanel pnl_idInput = new JPanel(new FlowLayout());
115
116   private JPanel pnl_fileChooser = new JPanel(new FlowLayout());
117
118   private JPanel pnl_idInputBL = new JPanel(new BorderLayout());
119
120   private JPanel pnl_fileChooserBL = new JPanel(new BorderLayout());
121
122   private JPanel pnl_locPDB = new JPanel(new BorderLayout());
123
124   protected JPanel pnl_switchableViews = new JPanel(new CardLayout());
125
126   protected CardLayout layout_switchableViews = (CardLayout) (pnl_switchableViews
127           .getLayout());
128
129   private BorderLayout mainLayout = new BorderLayout();
130
131   protected JCheckBox chk_rememberSettings = new JCheckBox(
132           MessageManager.getString("label.dont_ask_me_again"));
133
134   protected JCheckBox chk_invertFilter = new JCheckBox(
135           MessageManager.getString("label.invert"));
136
137   protected ImageIcon loadingImage = new ImageIcon(getClass().getResource(
138           "/images/loading.gif"));
139
140   protected ImageIcon goodImage = new ImageIcon(getClass().getResource(
141           "/images/good.png"));
142
143   protected ImageIcon errorImage = new ImageIcon(getClass().getResource(
144           "/images/error.png"));
145
146   protected ImageIcon warningImage = new ImageIcon(getClass().getResource(
147           "/images/warning.gif"));
148
149   protected JLabel lbl_warning = new JLabel(warningImage);
150
151   protected JLabel lbl_loading = new JLabel(loadingImage);
152
153   protected JLabel lbl_pdbManualFetchStatus = new JLabel(errorImage);
154
155   protected JLabel lbl_fromFileStatus = new JLabel(errorImage);
156
157   protected AssciateSeqPanel idInputAssSeqPanel = new AssciateSeqPanel();
158
159   protected AssciateSeqPanel fileChooserAssSeqPanel = new AssciateSeqPanel();
160
161   protected static final String VIEWS_FILTER = "VIEWS_FILTER";
162
163   protected static final String VIEWS_FROM_FILE = "VIEWS_FROM_FILE";
164
165   protected static final String VIEWS_ENTER_ID = "VIEWS_ENTER_ID";
166
167   protected static final String VIEWS_LOCAL_PDB = "VIEWS_LOCAL_PDB";
168
169   protected JTable tbl_local_pdb = new JTable();
170
171   protected JScrollPane scrl_localPDB = new JScrollPane(tbl_local_pdb);
172
173   protected JTabbedPane pnl_filter = new JTabbedPane();
174
175   protected FTSDataColumnPreferences pdbDocFieldPrefs = new FTSDataColumnPreferences(
176           PreferenceSource.STRUCTURE_CHOOSER,
177           PDBFTSRestClient.getInstance());
178
179   protected FTSDataColumnI[] previousWantedFields;
180
181   protected static Map<String, Integer> tempUserPrefs = new HashMap<String, Integer>();
182
183   private JTable tbl_summary = new JTable()
184   {
185     private boolean inLayout;
186
187     @Override
188     public boolean getScrollableTracksViewportWidth()
189     {
190       return hasExcessWidth();
191
192     }
193
194     @Override
195     public void doLayout()
196     {
197       if (hasExcessWidth())
198       {
199         autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS;
200       }
201       inLayout = true;
202       super.doLayout();
203       inLayout = false;
204       autoResizeMode = AUTO_RESIZE_OFF;
205     }
206
207     protected boolean hasExcessWidth()
208     {
209       return getPreferredSize().width < getParent().getWidth();
210     }
211
212     @Override
213     public void columnMarginChanged(ChangeEvent e)
214     {
215       if (isEditing())
216       {
217         removeEditor();
218       }
219       TableColumn resizingColumn = getTableHeader().getResizingColumn();
220       // Need to do this here, before the parent's
221       // layout manager calls getPreferredSize().
222       if (resizingColumn != null && autoResizeMode == AUTO_RESIZE_OFF
223               && !inLayout)
224       {
225         resizingColumn.setPreferredWidth(resizingColumn.getWidth());
226         String colHeader = resizingColumn.getHeaderValue().toString();
227         tempUserPrefs.put(colHeader, resizingColumn.getWidth());
228       }
229       resizeAndRepaint();
230     }
231
232     @Override
233     public String getToolTipText(MouseEvent evt)
234     {
235       String toolTipText = null;
236       java.awt.Point pnt = evt.getPoint();
237       int rowIndex = rowAtPoint(pnt);
238       int colIndex = columnAtPoint(pnt);
239
240       try
241       {
242         if (getValueAt(rowIndex, colIndex) == null)
243         {
244           return null;
245         }
246         toolTipText = getValueAt(rowIndex, colIndex).toString();
247       } catch (Exception e)
248       {
249         // e.printStackTrace();
250       }
251       toolTipText = (toolTipText == null ? null
252               : (toolTipText.length() > 500 ? JvSwingUtils.wrapTooltip(
253                       true, "\"" + toolTipText.subSequence(0, 500)
254                               + "...\"") : JvSwingUtils.wrapTooltip(true,
255                       toolTipText)));
256       return toolTipText;
257     }
258   };
259
260   protected JScrollPane scrl_foundStructures = new JScrollPane(tbl_summary);
261
262   public GStructureChooser()
263   {
264     try
265     {
266       jbInit();
267       mainFrame.setVisible(false);
268       mainFrame.invalidate();
269       mainFrame.pack();
270     } catch (Exception e)
271     {
272       e.printStackTrace();
273     }
274   }
275
276   /**
277    * Initializes the GUI default properties
278    * 
279    * @throws Exception
280    */
281   private void jbInit() throws Exception
282   {
283     Integer width = tempUserPrefs.get("structureChooser.width") == null ? 800
284             : tempUserPrefs.get("structureChooser.width");
285     Integer height = tempUserPrefs.get("structureChooser.height") == null ? 400
286             : tempUserPrefs.get("structureChooser.height");
287     tbl_summary.setAutoCreateRowSorter(true);
288     tbl_summary.getTableHeader().setReorderingAllowed(false);
289     tbl_summary.addMouseListener(new MouseAdapter()
290     {
291       @Override
292       public void mouseClicked(MouseEvent e)
293       {
294         validateSelections();
295       }
296
297       @Override
298       public void mouseReleased(MouseEvent e)
299       {
300         validateSelections();
301       }
302     });
303     tbl_summary.addKeyListener(new KeyAdapter()
304     {
305       @Override
306       public void keyPressed(KeyEvent evt)
307       {
308         validateSelections();
309         switch (evt.getKeyCode())
310         {
311         case KeyEvent.VK_ESCAPE: // escape key
312           mainFrame.dispose();
313           break;
314         case KeyEvent.VK_ENTER: // enter key
315           if (btn_view.isEnabled())
316           {
317             ok_ActionPerformed();
318           }
319           break;
320         case KeyEvent.VK_TAB: // tab key
321           if (evt.isShiftDown())
322           {
323             pnl_filter.requestFocus();
324           }
325           else
326           {
327             btn_view.requestFocus();
328           }
329           evt.consume();
330           break;
331         default:
332           return;
333         }
334       }
335     });
336     tbl_local_pdb.setAutoCreateRowSorter(true);
337     tbl_local_pdb.getTableHeader().setReorderingAllowed(false);
338     tbl_local_pdb.addMouseListener(new MouseAdapter()
339     {
340       @Override
341       public void mouseClicked(MouseEvent e)
342       {
343         validateSelections();
344       }
345
346       @Override
347       public void mouseReleased(MouseEvent e)
348       {
349         validateSelections();
350       }
351     });
352     tbl_local_pdb.addKeyListener(new KeyAdapter()
353     {
354       @Override
355       public void keyPressed(KeyEvent evt)
356       {
357         validateSelections();
358         switch (evt.getKeyCode())
359         {
360         case KeyEvent.VK_ESCAPE: // escape key
361           mainFrame.dispose();
362           break;
363         case KeyEvent.VK_ENTER: // enter key
364           if (btn_view.isEnabled())
365           {
366             ok_ActionPerformed();
367           }
368           break;
369         case KeyEvent.VK_TAB: // tab key
370           if (evt.isShiftDown())
371           {
372             cmb_filterOption.requestFocus();
373           }
374           else
375           {
376             if (btn_view.isEnabled())
377             {
378               btn_view.requestFocus();
379             }
380             else
381             {
382               btn_cancel.requestFocus();
383             }
384           }
385           evt.consume();
386           break;
387         default:
388           return;
389         }
390       }
391     });
392     btn_view.setFont(new java.awt.Font("Verdana", 0, 12));
393     btn_view.setText(MessageManager.getString("action.view"));
394     btn_view.addActionListener(new java.awt.event.ActionListener()
395     {
396       @Override
397       public void actionPerformed(ActionEvent e)
398       {
399         ok_ActionPerformed();
400       }
401     });
402     btn_view.addKeyListener(new KeyAdapter()
403     {
404       @Override
405       public void keyPressed(KeyEvent evt)
406       {
407         if (evt.getKeyCode() == KeyEvent.VK_ENTER)
408         {
409           ok_ActionPerformed();
410         }
411       }
412     });
413
414     btn_cancel.setFont(new java.awt.Font("Verdana", 0, 12));
415     btn_cancel.setText(MessageManager.getString("action.cancel"));
416     btn_cancel.addActionListener(new java.awt.event.ActionListener()
417     {
418       @Override
419       public void actionPerformed(ActionEvent e)
420       {
421         closeAction(pnl_filter.getHeight());
422       }
423     });
424     btn_cancel.addKeyListener(new KeyAdapter()
425     {
426       @Override
427       public void keyPressed(KeyEvent evt)
428       {
429         if (evt.getKeyCode() == KeyEvent.VK_ENTER)
430         {
431           closeAction(pnl_filter.getHeight());
432         }
433       }
434     });
435
436     btn_pdbFromFile.setFont(new java.awt.Font("Verdana", 0, 12));
437     String btn_title = MessageManager.getString("label.select_pdb_file");
438     btn_pdbFromFile.setText(btn_title + "              ");
439     btn_pdbFromFile.addActionListener(new java.awt.event.ActionListener()
440     {
441       @Override
442       public void actionPerformed(ActionEvent e)
443       {
444         pdbFromFile_actionPerformed();
445       }
446     });
447     btn_pdbFromFile.addKeyListener(new KeyAdapter()
448     {
449       @Override
450       public void keyPressed(KeyEvent evt)
451       {
452         if (evt.getKeyCode() == KeyEvent.VK_ENTER)
453         {
454           pdbFromFile_actionPerformed();
455         }
456       }
457     });
458
459     scrl_foundStructures.setPreferredSize(new Dimension(width, height));
460
461     scrl_localPDB.setPreferredSize(new Dimension(width, height));
462     scrl_localPDB
463             .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
464
465     cmb_filterOption.setFont(new java.awt.Font("Verdana", 0, 12));
466     chk_invertFilter.setFont(new java.awt.Font("Verdana", 0, 12));
467     chk_rememberSettings.setFont(new java.awt.Font("Verdana", 0, 12));
468     chk_rememberSettings.setVisible(false);
469     txt_search.setToolTipText(JvSwingUtils.wrapTooltip(true,
470             MessageManager.getString("label.enter_pdb_id")));
471     cmb_filterOption.setToolTipText(MessageManager
472             .getString("info.select_filter_option"));
473     txt_search.getDocument().addDocumentListener(new DocumentListener()
474     {
475       @Override
476       public void insertUpdate(DocumentEvent e)
477       {
478         txt_search_ActionPerformed();
479       }
480
481       @Override
482       public void removeUpdate(DocumentEvent e)
483       {
484         txt_search_ActionPerformed();
485       }
486
487       @Override
488       public void changedUpdate(DocumentEvent e)
489       {
490         txt_search_ActionPerformed();
491       }
492     });
493
494     cmb_filterOption.addItemListener(this);
495
496     // add CustomComboSeparatorsRenderer to filter option combo-box
497     cmb_filterOption.setRenderer(new CustomComboSeparatorsRenderer(
498             (ListCellRenderer<Object>) cmb_filterOption.getRenderer())
499     {
500       @Override
501       protected boolean addSeparatorAfter(JList list, FilterOption value,
502               int index)
503       {
504         return value.isAddSeparatorAfter();
505       }
506     });
507
508     chk_invertFilter.addItemListener(this);
509
510     pnl_actions.add(chk_rememberSettings);
511     pnl_actions.add(btn_view);
512     pnl_actions.add(btn_cancel);
513
514     // pnl_filter.add(lbl_result);
515     pnl_main.add(cmb_filterOption);
516     pnl_main.add(lbl_loading);
517     pnl_main.add(chk_invertFilter);
518     lbl_loading.setVisible(false);
519
520     pnl_fileChooser.add(btn_pdbFromFile);
521     pnl_fileChooser.add(lbl_fromFileStatus);
522     pnl_fileChooserBL.add(fileChooserAssSeqPanel, BorderLayout.NORTH);
523     pnl_fileChooserBL.add(pnl_fileChooser, BorderLayout.CENTER);
524
525     pnl_idInput.add(txt_search);
526     pnl_idInput.add(lbl_pdbManualFetchStatus);
527     pnl_idInputBL.add(idInputAssSeqPanel, BorderLayout.NORTH);
528     pnl_idInputBL.add(pnl_idInput, BorderLayout.CENTER);
529
530     final String foundStructureSummary = MessageManager
531             .getString("label.found_structures_summary");
532     final String configureCols = MessageManager
533             .getString("label.configure_displayed_columns");
534     ChangeListener changeListener = new ChangeListener()
535     {
536       @Override
537       public void stateChanged(ChangeEvent changeEvent)
538       {
539         JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent
540                 .getSource();
541         int index = sourceTabbedPane.getSelectedIndex();
542         btn_view.setVisible(true);
543         btn_cancel.setVisible(true);
544         if (sourceTabbedPane.getTitleAt(index).equals(configureCols))
545         {
546           btn_view.setEnabled(false);
547           btn_cancel.setEnabled(false);
548           btn_view.setVisible(false);
549           btn_cancel.setVisible(false);
550           previousWantedFields = pdbDocFieldPrefs
551                   .getStructureSummaryFields().toArray(
552                           new FTSDataColumnI[0]);
553         }
554         if (sourceTabbedPane.getTitleAt(index)
555                 .equals(foundStructureSummary))
556         {
557           btn_cancel.setEnabled(true);
558           if (wantedFieldsUpdated())
559           {
560             tabRefresh();
561           }
562           else
563           {
564             validateSelections();
565           }
566         }
567       }
568     };
569     pnl_filter.addChangeListener(changeListener);
570     pnl_filter.setPreferredSize(new Dimension(width, height));
571     pnl_filter.add(foundStructureSummary, scrl_foundStructures);
572     pnl_filter.add(configureCols, pdbDocFieldPrefs);
573
574     pnl_locPDB.add(scrl_localPDB);
575
576     pnl_switchableViews.add(pnl_fileChooserBL, VIEWS_FROM_FILE);
577     pnl_switchableViews.add(pnl_idInputBL, VIEWS_ENTER_ID);
578     pnl_switchableViews.add(pnl_filter, VIEWS_FILTER);
579     pnl_switchableViews.add(pnl_locPDB, VIEWS_LOCAL_PDB);
580
581     this.setLayout(mainLayout);
582     this.add(pnl_main, java.awt.BorderLayout.NORTH);
583     this.add(pnl_switchableViews, java.awt.BorderLayout.CENTER);
584     // this.add(pnl_actions, java.awt.BorderLayout.SOUTH);
585     statusPanel.setLayout(new GridLayout());
586     pnl_actionsAndStatus.add(pnl_actions, BorderLayout.CENTER);
587     pnl_actionsAndStatus.add(statusPanel, BorderLayout.SOUTH);
588     statusPanel.add(statusBar, null);
589     this.add(pnl_actionsAndStatus, java.awt.BorderLayout.SOUTH);
590
591     mainFrame
592             .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
593             {
594               @Override
595               public void internalFrameClosing(InternalFrameEvent e)
596               {
597                 closeAction(pnl_filter.getHeight());
598               }
599             });
600     mainFrame.setVisible(true);
601     mainFrame.setContentPane(this);
602     mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
603     Integer x = tempUserPrefs.get("structureChooser.x");
604     Integer y = tempUserPrefs.get("structureChooser.y");
605     if (x != null && y != null)
606     {
607       mainFrame.setLocation(x, y);
608     }
609     Desktop.addInternalFrame(mainFrame, frameTitle, width, height);
610   }
611
612   protected void closeAction(int preferredHeight)
613   {
614     // System.out.println(">>>>>>>>>> closing internal frame!!!");
615     // System.out.println("width : " + mainFrame.getWidth());
616     // System.out.println("heigh : " + mainFrame.getHeight());
617     // System.out.println("x : " + mainFrame.getX());
618     // System.out.println("y : " + mainFrame.getY());
619     tempUserPrefs.put("structureChooser.width", pnl_filter.getWidth());
620     tempUserPrefs.put("structureChooser.height", preferredHeight);
621     tempUserPrefs.put("structureChooser.x", mainFrame.getX());
622     tempUserPrefs.put("structureChooser.y", mainFrame.getY());
623     mainFrame.dispose();
624   }
625
626   public boolean wantedFieldsUpdated()
627   {
628     if (previousWantedFields == null)
629     {
630       return true;
631     }
632
633     FTSDataColumnI[] currentWantedFields = pdbDocFieldPrefs
634             .getStructureSummaryFields().toArray(new FTSDataColumnI[0]);
635     return Arrays.equals(currentWantedFields, previousWantedFields) ? false
636             : true;
637
638   }
639
640   @Override
641   /**
642    * Event listener for the 'filter' combo-box and 'invert' check-box
643    */
644   public void itemStateChanged(ItemEvent e)
645   {
646     stateChanged(e);
647   }
648
649   /**
650    * This inner class provides the data model for the structure filter combo-box
651    * 
652    * @author tcnofoegbu
653    *
654    */
655   public class FilterOption
656   {
657     private String name;
658
659     private String value;
660
661     private String view;
662
663     private boolean addSeparatorAfter;
664
665     /**
666      * Model for structure filter option
667      * 
668      * @param name
669      *          - the name of the Option
670      * @param value
671      *          - the value of the option
672      * @param view
673      *          - the category of the filter option
674      * @param addSeparatorAfter
675      *          - if true, a horizontal separator is rendered immediately after
676      *          this filter option, otherwise
677      */
678     public FilterOption(String name, String value, String view,
679             boolean addSeparatorAfter)
680     {
681       this.name = name;
682       this.value = value;
683       this.view = view;
684       this.addSeparatorAfter = addSeparatorAfter;
685     }
686
687     public String getName()
688     {
689       return name;
690     }
691
692     public void setName(String name)
693     {
694       this.name = name;
695     }
696
697     public String getValue()
698     {
699       return value;
700     }
701
702     public void setValue(String value)
703     {
704       this.value = value;
705     }
706
707     public String getView()
708     {
709       return view;
710     }
711
712     public void setView(String view)
713     {
714       this.view = view;
715     }
716
717     @Override
718     public String toString()
719     {
720       return this.name;
721     }
722
723     public boolean isAddSeparatorAfter()
724     {
725       return addSeparatorAfter;
726     }
727
728     public void setAddSeparatorAfter(boolean addSeparatorAfter)
729     {
730       this.addSeparatorAfter = addSeparatorAfter;
731     }
732   }
733
734   /**
735    * This inner class provides the provides the data model for associate
736    * sequence combo-box - cmb_assSeq
737    * 
738    * @author tcnofoegbu
739    *
740    */
741   public class AssociateSeqOptions
742   {
743     private SequenceI sequence;
744
745     private String name;
746
747     public AssociateSeqOptions(SequenceI seq)
748     {
749       this.sequence = seq;
750       this.name = (seq.getName().length() >= 23) ? seq.getName().substring(
751               0, 23) : seq.getName();
752     }
753
754     public AssociateSeqOptions(String name, SequenceI seq)
755     {
756       this.name = name;
757       this.sequence = seq;
758     }
759
760     @Override
761     public String toString()
762     {
763       return name;
764     }
765
766     public String getName()
767     {
768       return name;
769     }
770
771     public void setName(String name)
772     {
773       this.name = name;
774     }
775
776     public SequenceI getSequence()
777     {
778       return sequence;
779     }
780
781     public void setSequence(SequenceI sequence)
782     {
783       this.sequence = sequence;
784     }
785
786   }
787
788   /**
789    * This inner class holds the Layout and configuration of the panel which
790    * handles association of manually fetched structures to a unique sequence
791    * when more than one sequence selection is made
792    * 
793    * @author tcnofoegbu
794    *
795    */
796   public class AssciateSeqPanel extends JPanel implements ItemListener
797   {
798     private JComboBox<AssociateSeqOptions> cmb_assSeq = new JComboBox<AssociateSeqOptions>();
799
800     private JLabel lbl_associateSeq = new JLabel();
801
802     public AssciateSeqPanel()
803     {
804       this.setLayout(new FlowLayout());
805       this.add(cmb_assSeq);
806       this.add(lbl_associateSeq);
807       cmb_assSeq.setToolTipText(MessageManager
808               .getString("info.associate_wit_sequence"));
809       cmb_assSeq.addItemListener(this);
810     }
811
812     public void loadCmbAssSeq()
813     {
814       populateCmbAssociateSeqOptions(cmb_assSeq, lbl_associateSeq);
815     }
816
817     public JComboBox<AssociateSeqOptions> getCmb_assSeq()
818     {
819       return cmb_assSeq;
820     }
821
822     public void setCmb_assSeq(JComboBox<AssociateSeqOptions> cmb_assSeq)
823     {
824       this.cmb_assSeq = cmb_assSeq;
825     }
826
827     @Override
828     public void itemStateChanged(ItemEvent e)
829     {
830       if (e.getStateChange() == ItemEvent.SELECTED)
831       {
832         cmbAssSeqStateChanged();
833       }
834     }
835   }
836
837   public JTable getResultTable()
838   {
839     return tbl_summary;
840   }
841
842   public JComboBox<FilterOption> getCmbFilterOption()
843   {
844     return cmb_filterOption;
845   }
846
847   /**
848    * Custom ListCellRenderer for adding a separator between different categories
849    * of structure chooser filter option drop-down.
850    * 
851    * @author tcnofoegbu
852    *
853    */
854   public abstract class CustomComboSeparatorsRenderer implements
855           ListCellRenderer<Object>
856   {
857     private ListCellRenderer<Object> regent;
858
859     private JPanel separatorPanel = new JPanel(new BorderLayout());
860
861     private JSeparator jSeparator = new JSeparator();
862
863     public CustomComboSeparatorsRenderer(ListCellRenderer<Object> listCellRenderer)
864     {
865       this.regent = listCellRenderer;
866     }
867
868     @Override
869     public Component getListCellRendererComponent(JList list,
870             Object value,
871             int index, boolean isSelected, boolean cellHasFocus)
872     {
873
874       Component comp = regent.getListCellRendererComponent(list, value,
875               index, isSelected, cellHasFocus);
876       if (index != -1
877               && addSeparatorAfter(list, (FilterOption) value, index))
878       { 
879         separatorPanel.removeAll();
880         separatorPanel.add(comp, BorderLayout.CENTER);
881         separatorPanel.add(jSeparator, BorderLayout.SOUTH);
882         return separatorPanel;
883       }
884       else
885       {
886         return comp;
887       }
888     }
889
890     protected abstract boolean addSeparatorAfter(JList list,
891             FilterOption value,
892             int index);
893   }
894
895   protected abstract void stateChanged(ItemEvent e);
896
897   protected abstract void ok_ActionPerformed();
898
899   protected abstract void pdbFromFile_actionPerformed();
900
901   protected abstract void txt_search_ActionPerformed();
902
903   public abstract void populateCmbAssociateSeqOptions(
904           JComboBox<AssociateSeqOptions> cmb_assSeq, JLabel lbl_associateSeq);
905
906   public abstract void cmbAssSeqStateChanged();
907
908   public abstract void tabRefresh();
909
910   public abstract void validateSelections();
911 }