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