JAL-1264 javadoc update
[jalview.git] / src / jalview / gui / PopupMenu.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 package jalview.gui;
22
23 import jalview.analysis.AAFrequency;
24 import jalview.analysis.Conservation;
25 import jalview.commands.ChangeCaseCommand;
26 import jalview.commands.EditCommand;
27 import jalview.datamodel.AlignmentAnnotation;
28 import jalview.datamodel.Annotation;
29 import jalview.datamodel.DBRefEntry;
30 import jalview.datamodel.PDBEntry;
31 import jalview.datamodel.Sequence;
32 import jalview.datamodel.SequenceFeature;
33 import jalview.datamodel.SequenceGroup;
34 import jalview.datamodel.SequenceI;
35 import jalview.io.FormatAdapter;
36 import jalview.io.SequenceAnnotationReport;
37 import jalview.renderer.AnnotationRenderer;
38 import jalview.schemes.AnnotationColourGradient;
39 import jalview.schemes.Blosum62ColourScheme;
40 import jalview.schemes.BuriedColourScheme;
41 import jalview.schemes.ClustalxColourScheme;
42 import jalview.schemes.HelixColourScheme;
43 import jalview.schemes.HydrophobicColourScheme;
44 import jalview.schemes.NucleotideColourScheme;
45 import jalview.schemes.PIDColourScheme;
46 import jalview.schemes.PurinePyrimidineColourScheme;
47 import jalview.schemes.ResidueProperties;
48 import jalview.schemes.StrandColourScheme;
49 import jalview.schemes.TaylorColourScheme;
50 import jalview.schemes.TurnColourScheme;
51 import jalview.schemes.UserColourScheme;
52 import jalview.schemes.ZappoColourScheme;
53 import jalview.util.GroupUrlLink;
54 import jalview.util.GroupUrlLink.UrlStringTooLongException;
55 import jalview.util.MessageManager;
56 import jalview.util.UrlLink;
57
58 import java.awt.Color;
59 import java.awt.event.ActionEvent;
60 import java.awt.event.ActionListener;
61 import java.util.ArrayList;
62 import java.util.Arrays;
63 import java.util.BitSet;
64 import java.util.Collection;
65 import java.util.Hashtable;
66 import java.util.LinkedHashMap;
67 import java.util.List;
68 import java.util.Map;
69 import java.util.Vector;
70
71 import javax.swing.ButtonGroup;
72 import javax.swing.JCheckBoxMenuItem;
73 import javax.swing.JColorChooser;
74 import javax.swing.JMenu;
75 import javax.swing.JMenuItem;
76 import javax.swing.JOptionPane;
77 import javax.swing.JPopupMenu;
78 import javax.swing.JRadioButtonMenuItem;
79
80 /**
81  * DOCUMENT ME!
82  * 
83  * @author $author$
84  * @version $Revision: 1.118 $
85  */
86 public class PopupMenu extends JPopupMenu
87 {
88   private static final String ALL_ANNOTATIONS = "All";
89
90   private static final String COMMA = ",";
91
92   JMenu groupMenu = new JMenu();
93
94   JMenuItem groupName = new JMenuItem();
95
96   protected JRadioButtonMenuItem clustalColour = new JRadioButtonMenuItem();
97
98   protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();
99
100   protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();
101
102   protected JRadioButtonMenuItem hydrophobicityColour = new JRadioButtonMenuItem();
103
104   protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();
105
106   protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();
107
108   protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();
109
110   protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();
111
112   protected JCheckBoxMenuItem abovePIDColour = new JCheckBoxMenuItem();
113
114   protected JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem();
115
116   protected JRadioButtonMenuItem PIDColour = new JRadioButtonMenuItem();
117
118   protected JRadioButtonMenuItem BLOSUM62Colour = new JRadioButtonMenuItem();
119
120   protected JRadioButtonMenuItem purinePyrimidineColour = new JRadioButtonMenuItem();
121
122   protected JRadioButtonMenuItem RNAInteractionColour = new JRadioButtonMenuItem();
123
124   // protected JRadioButtonMenuItem covariationColour = new
125   // JRadioButtonMenuItem();
126
127   JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem();
128
129   protected JCheckBoxMenuItem conservationMenuItem = new JCheckBoxMenuItem();
130
131   AlignmentPanel ap;
132
133   JMenu sequenceMenu = new JMenu();
134
135   JMenuItem sequenceName = new JMenuItem();
136
137   JMenuItem sequenceDetails = new JMenuItem();
138
139   JMenuItem sequenceSelDetails = new JMenuItem();
140
141   JMenuItem chooseAnnotations = new JMenuItem();
142
143   SequenceI sequence;
144
145   JMenuItem createGroupMenuItem = new JMenuItem();
146
147   JMenuItem unGroupMenuItem = new JMenuItem();
148
149   JMenuItem outline = new JMenuItem();
150
151   JRadioButtonMenuItem nucleotideMenuItem = new JRadioButtonMenuItem();
152
153   JMenu colourMenu = new JMenu();
154
155   JCheckBoxMenuItem showBoxes = new JCheckBoxMenuItem();
156
157   JCheckBoxMenuItem showText = new JCheckBoxMenuItem();
158
159   JCheckBoxMenuItem showColourText = new JCheckBoxMenuItem();
160
161   JCheckBoxMenuItem displayNonconserved = new JCheckBoxMenuItem();
162
163   JMenu editMenu = new JMenu();
164
165   JMenuItem cut = new JMenuItem();
166
167   JMenuItem copy = new JMenuItem();
168
169   JMenuItem upperCase = new JMenuItem();
170
171   JMenuItem lowerCase = new JMenuItem();
172
173   JMenuItem toggle = new JMenuItem();
174
175   JMenu pdbMenu = new JMenu();
176
177   JMenuItem pdbFromFile = new JMenuItem();
178
179   // JBPNote: Commented these out - Should add these services via the web
180   // services menu system.
181   // JMenuItem ContraFold = new JMenuItem();
182
183   // JMenuItem RNAFold = new JMenuItem();
184
185   JMenuItem enterPDB = new JMenuItem();
186
187   JMenuItem discoverPDB = new JMenuItem();
188
189   JMenu outputMenu = new JMenu();
190
191   JMenu showAnnotationsMenu = new JMenu();
192
193   JMenu hideAnnotationsMenu = new JMenu();
194
195   JMenuItem sequenceFeature = new JMenuItem();
196
197   JMenuItem textColour = new JMenuItem();
198
199   JMenu jMenu1 = new JMenu();
200
201   JMenu structureMenu = new JMenu();
202
203   JMenu viewStructureMenu = new JMenu();
204
205   // JMenu colStructureMenu = new JMenu();
206   JMenuItem editSequence = new JMenuItem();
207
208   // JMenuItem annotationMenuItem = new JMenuItem();
209
210   JMenu groupLinksMenu;
211
212   /**
213    * Creates a new PopupMenu object.
214    * 
215    * @param ap
216    *          DOCUMENT ME!
217    * @param seq
218    *          DOCUMENT ME!
219    */
220   public PopupMenu(final AlignmentPanel ap, Sequence seq, Vector links)
221   {
222     this(ap, seq, links, null);
223   }
224
225   /**
226    * 
227    * @param ap
228    * @param seq
229    * @param links
230    * @param groupLinks
231    */
232   public PopupMenu(final AlignmentPanel ap, final SequenceI seq,
233           Vector links, Vector groupLinks)
234   {
235     // /////////////////////////////////////////////////////////
236     // If this is activated from the sequence panel, the user may want to
237     // edit or annotate a particular residue. Therefore display the residue menu
238     //
239     // If from the IDPanel, we must display the sequence menu
240     // ////////////////////////////////////////////////////////
241     this.ap = ap;
242     sequence = seq;
243
244     ButtonGroup colours = new ButtonGroup();
245     colours.add(noColourmenuItem);
246     colours.add(clustalColour);
247     colours.add(zappoColour);
248     colours.add(taylorColour);
249     colours.add(hydrophobicityColour);
250     colours.add(helixColour);
251     colours.add(strandColour);
252     colours.add(turnColour);
253     colours.add(buriedColour);
254     colours.add(abovePIDColour);
255     colours.add(userDefinedColour);
256     colours.add(PIDColour);
257     colours.add(BLOSUM62Colour);
258     colours.add(purinePyrimidineColour);
259     colours.add(RNAInteractionColour);
260     // colours.add(covariationColour);
261
262     for (int i = 0; i < jalview.io.FormatAdapter.WRITEABLE_FORMATS.length; i++)
263     {
264       JMenuItem item = new JMenuItem(
265               jalview.io.FormatAdapter.WRITEABLE_FORMATS[i]);
266
267       item.addActionListener(new java.awt.event.ActionListener()
268       {
269         @Override
270         public void actionPerformed(ActionEvent e)
271         {
272           outputText_actionPerformed(e);
273         }
274       });
275
276       outputMenu.add(item);
277     }
278
279     /*
280      * Build menus for annotation types that may be shown or hidden.
281      */
282     buildAnnotationTypesMenus();
283
284     try
285     {
286       jbInit();
287     } catch (Exception e)
288     {
289       e.printStackTrace();
290     }
291
292     JMenuItem menuItem;
293     if (seq != null)
294     {
295       sequenceMenu.setText(sequence.getName());
296
297       if (seq.getDatasetSequence().getPDBId() != null
298               && seq.getDatasetSequence().getPDBId().size() > 0)
299       {
300         java.util.Enumeration e = seq.getDatasetSequence().getPDBId()
301                 .elements();
302
303         while (e.hasMoreElements())
304         {
305           final PDBEntry pdb = (PDBEntry) e.nextElement();
306
307           menuItem = new JMenuItem();
308           menuItem.setText(pdb.getId());
309           menuItem.addActionListener(new java.awt.event.ActionListener()
310           {
311             public void actionPerformed(ActionEvent e)
312             {
313               // TODO re JAL-860: optionally open dialog or provide a menu entry
314               // allowing user to open just one structure per sequence
315               // new AppJmol(pdb, ap.av.collateForPDB(new PDBEntry[]
316               // { pdb })[0], null, ap);
317               new StructureViewer(ap.getStructureSelectionManager())
318                       .viewStructures(pdb,
319                               ap.av.collateForPDB(new PDBEntry[]
320                               { pdb })[0], null, ap);
321             }
322           });
323           viewStructureMenu.add(menuItem);
324
325           /*
326            * menuItem = new JMenuItem(); menuItem.setText(pdb.getId());
327            * menuItem.addActionListener(new java.awt.event.ActionListener() {
328            * public void actionPerformed(ActionEvent e) {
329            * colourByStructure(pdb.getId()); } });
330            * colStructureMenu.add(menuItem);
331            */
332         }
333       }
334       else
335       {
336         if (ap.av.getAlignment().isNucleotide() == false)
337         {
338           structureMenu.remove(viewStructureMenu);
339         }
340         // structureMenu.remove(colStructureMenu);
341       }
342
343       if (ap.av.getAlignment().isNucleotide() == true)
344       {
345         AlignmentAnnotation[] aa = ap.av.getAlignment()
346                 .getAlignmentAnnotation();
347         for (int i = 0; i < aa.length; i++)
348         {
349           if (aa[i].getRNAStruc() != null)
350           {
351             final String rnastruc = aa[i].getRNAStruc();
352             final String structureLine = aa[i].label;
353             menuItem = new JMenuItem();
354             menuItem.setText(MessageManager.formatMessage(
355                     "label.2d_rna_structure_line", new String[]
356                     { structureLine }));
357             menuItem.addActionListener(new java.awt.event.ActionListener()
358
359             {
360               @Override
361               public void actionPerformed(ActionEvent e)
362               {
363                 // System.out.println("1:"+structureLine);
364                 System.out.println("1:sname" + seq.getName());
365                 System.out.println("2:seq" + seq);
366
367                 // System.out.println("3:"+seq.getSequenceAsString());
368                 System.out.println("3:strucseq" + rnastruc);
369                 // System.out.println("4:struc"+seq.getRNA());
370                 System.out.println("5:name" + seq.getName());
371                 System.out.println("6:ap" + ap);
372                 new AppVarna(structureLine, seq, seq.getSequenceAsString(),
373                         rnastruc, seq.getName(), ap);
374                 // new AppVarna(seq.getName(),seq,rnastruc,seq.getRNA(),
375                 // seq.getName(), ap);
376                 System.out.println("end");
377               }
378             });
379             viewStructureMenu.add(menuItem);
380           }
381         }
382
383         // SequenceFeatures[] test = seq.getSequenceFeatures();
384
385         if (seq.getAnnotation() != null)
386         {
387           AlignmentAnnotation seqAnno[] = seq.getAnnotation();
388           for (int i = 0; i < seqAnno.length; i++)
389           {
390             if (seqAnno[i].getRNAStruc() != null)
391             {
392               final String rnastruc = seqAnno[i].getRNAStruc();
393
394               // TODO: make rnastrucF a bit more nice
395               menuItem = new JMenuItem();
396               menuItem.setText(MessageManager.formatMessage(
397                       "label.2d_rna_sequence_name", new String[]
398                       { seq.getName() }));
399               menuItem.addActionListener(new java.awt.event.ActionListener()
400               {
401                 @Override
402                 public void actionPerformed(ActionEvent e)
403                 {
404                   // TODO: VARNA does'nt print gaps in the sequence
405
406                   new AppVarna(seq.getName() + " structure", seq, seq
407                           .getSequenceAsString(), rnastruc, seq.getName(),
408                           ap);
409                 }
410               });
411               viewStructureMenu.add(menuItem);
412             }
413           }
414         }
415
416       }
417
418       menuItem = new JMenuItem(
419               MessageManager.getString("action.hide_sequences"));
420       menuItem.addActionListener(new java.awt.event.ActionListener()
421       {
422         @Override
423         public void actionPerformed(ActionEvent e)
424         {
425           hideSequences(false);
426         }
427       });
428       add(menuItem);
429
430       if (ap.av.getSelectionGroup() != null
431               && ap.av.getSelectionGroup().getSize() > 1)
432       {
433         menuItem = new JMenuItem(MessageManager.formatMessage(
434                 "label.represent_group_with", new String[]
435                 { seq.getName() }));
436         menuItem.addActionListener(new java.awt.event.ActionListener()
437         {
438           @Override
439           public void actionPerformed(ActionEvent e)
440           {
441             hideSequences(true);
442           }
443         });
444         sequenceMenu.add(menuItem);
445       }
446
447       if (ap.av.hasHiddenRows())
448       {
449         final int index = ap.av.getAlignment().findIndex(seq);
450
451         if (ap.av.adjustForHiddenSeqs(index)
452                 - ap.av.adjustForHiddenSeqs(index - 1) > 1)
453         {
454           menuItem = new JMenuItem(
455                   MessageManager.getString("action.reveal_sequences"));
456           menuItem.addActionListener(new ActionListener()
457           {
458             @Override
459             public void actionPerformed(ActionEvent e)
460             {
461               ap.av.showSequence(index);
462               if (ap.overviewPanel != null)
463               {
464                 ap.overviewPanel.updateOverviewImage();
465               }
466             }
467           });
468           add(menuItem);
469         }
470       }
471     }
472     // for the case when no sequences are even visible
473     if (ap.av.hasHiddenRows())
474     {
475       {
476         menuItem = new JMenuItem(
477                 MessageManager.getString("action.reveal_all"));
478         menuItem.addActionListener(new ActionListener()
479         {
480           @Override
481           public void actionPerformed(ActionEvent e)
482           {
483             ap.av.showAllHiddenSeqs();
484             if (ap.overviewPanel != null)
485             {
486               ap.overviewPanel.updateOverviewImage();
487             }
488           }
489         });
490
491         add(menuItem);
492       }
493
494     }
495
496     SequenceGroup sg = ap.av.getSelectionGroup();
497     boolean isDefinedGroup = (sg != null) ? ap.av.getAlignment()
498             .getGroups().contains(sg) : false;
499
500     if (sg != null && sg.getSize() > 0)
501     {
502       groupName.setText(MessageManager.formatMessage("label.name_param",
503               new String[]
504               { sg.getName() }));
505       groupName.setText(MessageManager
506               .getString("label.edit_name_and_description_current_group"));
507
508       if (sg.cs instanceof ZappoColourScheme)
509       {
510         zappoColour.setSelected(true);
511       }
512       else if (sg.cs instanceof TaylorColourScheme)
513       {
514         taylorColour.setSelected(true);
515       }
516       else if (sg.cs instanceof PIDColourScheme)
517       {
518         PIDColour.setSelected(true);
519       }
520       else if (sg.cs instanceof Blosum62ColourScheme)
521       {
522         BLOSUM62Colour.setSelected(true);
523       }
524       else if (sg.cs instanceof UserColourScheme)
525       {
526         userDefinedColour.setSelected(true);
527       }
528       else if (sg.cs instanceof HydrophobicColourScheme)
529       {
530         hydrophobicityColour.setSelected(true);
531       }
532       else if (sg.cs instanceof HelixColourScheme)
533       {
534         helixColour.setSelected(true);
535       }
536       else if (sg.cs instanceof StrandColourScheme)
537       {
538         strandColour.setSelected(true);
539       }
540       else if (sg.cs instanceof TurnColourScheme)
541       {
542         turnColour.setSelected(true);
543       }
544       else if (sg.cs instanceof BuriedColourScheme)
545       {
546         buriedColour.setSelected(true);
547       }
548       else if (sg.cs instanceof ClustalxColourScheme)
549       {
550         clustalColour.setSelected(true);
551       }
552       else if (sg.cs instanceof PurinePyrimidineColourScheme)
553       {
554         purinePyrimidineColour.setSelected(true);
555       }
556
557       /*
558        * else if (sg.cs instanceof CovariationColourScheme) {
559        * covariationColour.setSelected(true); }
560        */
561       else
562       {
563         noColourmenuItem.setSelected(true);
564       }
565
566       if (sg.cs != null && sg.cs.conservationApplied())
567       {
568         conservationMenuItem.setSelected(true);
569       }
570       displayNonconserved.setSelected(sg.getShowNonconserved());
571       showText.setSelected(sg.getDisplayText());
572       showColourText.setSelected(sg.getColourText());
573       showBoxes.setSelected(sg.getDisplayBoxes());
574       // add any groupURLs to the groupURL submenu and make it visible
575       if (groupLinks != null && groupLinks.size() > 0)
576       {
577         buildGroupURLMenu(sg, groupLinks);
578       }
579       // Add a 'show all structures' for the current selection
580       Hashtable<String, PDBEntry> pdbe = new Hashtable<String, PDBEntry>(), reppdb = new Hashtable<String, PDBEntry>();
581       SequenceI sqass = null;
582       for (SequenceI sq : ap.av.getSequenceSelection())
583       {
584         Vector<PDBEntry> pes = sq.getDatasetSequence().getPDBId();
585         if (pes != null && pes.size() > 0)
586         {
587           reppdb.put(pes.get(0).getId(), pes.get(0));
588           for (PDBEntry pe : pes)
589           {
590             pdbe.put(pe.getId(), pe);
591             if (sqass == null)
592             {
593               sqass = sq;
594             }
595           }
596         }
597       }
598       if (pdbe.size() > 0)
599       {
600         final PDBEntry[] pe = pdbe.values().toArray(
601                 new PDBEntry[pdbe.size()]), pr = reppdb.values().toArray(
602                 new PDBEntry[reppdb.size()]);
603         final JMenuItem gpdbview, rpdbview;
604         if (pdbe.size() == 1)
605         {
606           structureMenu.add(gpdbview = new JMenuItem(MessageManager
607                   .formatMessage("label.view_structure_for", new String[]
608                   { sqass.getDisplayId(false) })));
609         }
610         else
611         {
612           structureMenu.add(gpdbview = new JMenuItem(MessageManager
613                   .formatMessage("label.view_all_structures", new String[]
614                   { new Integer(pdbe.size()).toString() })));
615         }
616         gpdbview.setToolTipText(MessageManager
617                 .getString("label.open_new_jmol_view_with_all_structures_associated_current_selection_superimpose_using_alignment"));
618         gpdbview.addActionListener(new ActionListener()
619         {
620
621           @Override
622           public void actionPerformed(ActionEvent e)
623           {
624             new StructureViewer(ap.getStructureSelectionManager())
625                     .viewStructures(ap, pe, ap.av.collateForPDB(pe));
626           }
627         });
628         if (reppdb.size() > 1 && reppdb.size() < pdbe.size())
629         {
630           structureMenu.add(rpdbview = new JMenuItem(MessageManager
631                   .formatMessage(
632                           "label.view_all_representative_structures",
633                           new String[]
634                           { new Integer(reppdb.size()).toString() })));
635           rpdbview.setToolTipText(MessageManager
636                   .getString("label.open_new_jmol_view_with_all_representative_structures_associated_current_selection_superimpose_using_alignment"));
637           rpdbview.addActionListener(new ActionListener()
638           {
639
640             @Override
641             public void actionPerformed(ActionEvent e)
642             {
643               new StructureViewer(ap.getStructureSelectionManager())
644                       .viewStructures(ap, pr, ap.av.collateForPDB(pr));
645             }
646           });
647         }
648       }
649     }
650     else
651     {
652       groupMenu.setVisible(false);
653       editMenu.setVisible(false);
654     }
655
656     if (!isDefinedGroup)
657     {
658       createGroupMenuItem.setVisible(true);
659       unGroupMenuItem.setVisible(false);
660       jMenu1.setText(MessageManager.getString("action.edit_new_group"));
661     }
662     else
663     {
664       createGroupMenuItem.setVisible(false);
665       unGroupMenuItem.setVisible(true);
666       jMenu1.setText(MessageManager.getString("action.edit_group"));
667     }
668
669     if (seq == null)
670     {
671       sequenceMenu.setVisible(false);
672       structureMenu.setVisible(false);
673     }
674
675     if (links != null && links.size() > 0)
676     {
677
678       JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
679       Vector linkset = new Vector();
680       for (int i = 0; i < links.size(); i++)
681       {
682         String link = links.elementAt(i).toString();
683         UrlLink urlLink = null;
684         try
685         {
686           urlLink = new UrlLink(link);
687         } catch (Exception foo)
688         {
689           jalview.bin.Cache.log.error("Exception for URLLink '" + link
690                   + "'", foo);
691           continue;
692         }
693         ;
694         if (!urlLink.isValid())
695         {
696           jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
697           continue;
698         }
699         final String label = urlLink.getLabel();
700         if (seq != null && urlLink.isDynamic())
701         {
702
703           // collect matching db-refs
704           DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(
705                   seq.getDBRef(), new String[]
706                   { urlLink.getTarget() });
707           // collect id string too
708           String id = seq.getName();
709           String descr = seq.getDescription();
710           if (descr != null && descr.length() < 1)
711           {
712             descr = null;
713           }
714
715           if (dbr != null)
716           {
717             for (int r = 0; r < dbr.length; r++)
718             {
719               if (id != null && dbr[r].getAccessionId().equals(id))
720               {
721                 // suppress duplicate link creation for the bare sequence ID
722                 // string with this link
723                 id = null;
724               }
725               // create Bare ID link for this RUL
726               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
727                       true);
728               if (urls != null)
729               {
730                 for (int u = 0; u < urls.length; u += 2)
731                 {
732                   if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
733                   {
734                     linkset.addElement(urls[u] + "|" + urls[u + 1]);
735                     addshowLink(linkMenu, label + "|" + urls[u],
736                             urls[u + 1]);
737                   }
738                 }
739               }
740             }
741           }
742           if (id != null)
743           {
744             // create Bare ID link for this RUL
745             String[] urls = urlLink.makeUrls(id, true);
746             if (urls != null)
747             {
748               for (int u = 0; u < urls.length; u += 2)
749               {
750                 if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
751                 {
752                   linkset.addElement(urls[u] + "|" + urls[u + 1]);
753                   addshowLink(linkMenu, label, urls[u + 1]);
754                 }
755               }
756             }
757           }
758           // Create urls from description but only for URL links which are regex
759           // links
760           if (descr != null && urlLink.getRegexReplace() != null)
761           {
762             // create link for this URL from description where regex matches
763             String[] urls = urlLink.makeUrls(descr, true);
764             if (urls != null)
765             {
766               for (int u = 0; u < urls.length; u += 2)
767               {
768                 if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
769                 {
770                   linkset.addElement(urls[u] + "|" + urls[u + 1]);
771                   addshowLink(linkMenu, label, urls[u + 1]);
772                 }
773               }
774             }
775           }
776         }
777         else
778         {
779           if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
780           {
781             linkset.addElement(label + "|" + urlLink.getUrl_prefix());
782             // Add a non-dynamic link
783             addshowLink(linkMenu, label, urlLink.getUrl_prefix());
784           }
785         }
786       }
787       if (sequence != null)
788       {
789         sequenceMenu.add(linkMenu);
790       }
791       else
792       {
793         add(linkMenu);
794       }
795     }
796   }
797
798   /**
799    * Add annotation types to a 'Show annotations' or 'Hide annotations' menu.
800    * "All" is added first, followed by a separator. Then add any annotation
801    * types associated with the current selection.
802    * <p>
803    * Some annotation rows are always rendered together - these can be identified
804    * by a common graphGroup property > -1. Only one of each group will be marked
805    * as visible (to avoid duplication of the display). For such groups we add a
806    * composite type name, e.g.
807    * <p>
808    * IUPredWS (Long), IUPredWS (Short)
809    */
810   protected void buildAnnotationTypesMenus()
811   {
812     showAnnotationsMenu.removeAll();
813     hideAnnotationsMenu.removeAll();
814     final List<String> all = Arrays.asList(ALL_ANNOTATIONS);
815     addAnnotationTypeToShowHide(showAnnotationsMenu,
816             all, true,
817  true);
818     addAnnotationTypeToShowHide(hideAnnotationsMenu, all, true,
819             false);
820     showAnnotationsMenu.addSeparator();
821     hideAnnotationsMenu.addSeparator();
822
823     final AlignmentAnnotation[] annotations = ap.getAlignment()
824             .getAlignmentAnnotation();
825     BitSet visibleGraphGroups = PopupMenu
826             .getVisibleLineGraphGroups(annotations);
827
828     List<List<String>> shownTypes = new ArrayList<List<String>>();
829     List<List<String>> hiddenTypes = new ArrayList<List<String>>();
830     PopupMenu.getAnnotationTypesForShowHide(shownTypes, hiddenTypes,
831             visibleGraphGroups, annotations, ap.av.getSelectionGroup());
832
833     for (List<String> types : hiddenTypes)
834     {
835       addAnnotationTypeToShowHide(showAnnotationsMenu, types, false, true);
836     }
837
838     for (List<String> types : shownTypes)
839     {
840       addAnnotationTypeToShowHide(hideAnnotationsMenu, types, false, false);
841     }
842   }
843
844   /**
845    * Helper method to populate lists of annotation types for the Show/Hide
846    * Annotations menus. If sequenceGroup is not null, this is restricted to
847    * annotations which are associated with sequences in the selection group.
848    * <p/>
849    * If an annotation row is currently visible, its type (label) is added (once
850    * only per type), to the shownTypes list. If it is currently hidden, it is
851    * added to the hiddenTypesList.
852    * <p/>
853    * For rows that belong to a line graph group, so are always rendered
854    * together:
855    * <ul>
856    * <li>Treat all rows in the group as visible, if at least one of them is</li>
857    * <li>Build a comma-separated label with all the types that belong to the
858    * group</li>
859    * </ul>
860    * 
861    * @param shownTypes
862    * @param hiddenTypes
863    * @param visibleGraphGroups
864    * @param annotations
865    * @param sequenceGroup
866    */
867   public static void getAnnotationTypesForShowHide(
868           List<List<String>> shownTypes, List<List<String>> hiddenTypes,
869           BitSet visibleGraphGroups,
870           AlignmentAnnotation[] annotations, SequenceGroup sequenceGroup)
871   {
872     // lookup table, key = graph group, value = list of types in the group
873     Map<Integer, List<String>> groupLabels = new LinkedHashMap<Integer, List<String>>();
874
875     List<String> addedToShown = new ArrayList<String>();
876     List<String> addedToHidden = new ArrayList<String>();
877
878     for (AlignmentAnnotation aa : annotations)
879     {
880
881       if (sequenceGroup == null
882               || (aa.sequenceRef != null && sequenceGroup.getSequences()
883                       .contains(aa.sequenceRef)))
884       {
885         /*
886          * Build a 'composite label' for types in line graph groups.
887          */
888         final List<String> labelAsList = new ArrayList<String>();
889         labelAsList.add(aa.label);
890         if (aa.graph == AlignmentAnnotation.LINE_GRAPH
891                 && aa.graphGroup > -1)
892         {
893           if (groupLabels.containsKey(aa.graphGroup))
894           {
895             if (!groupLabels.get(aa.graphGroup).contains(aa.label))
896             {
897               groupLabels.get(aa.graphGroup).add(aa.label);
898             }
899           }
900           else
901           {
902             groupLabels.put(aa.graphGroup, labelAsList);
903           }
904         }
905         else if (aa.visible && !addedToShown.contains(aa.label))
906         {
907           shownTypes.add(labelAsList);
908           addedToShown.add(aa.label);
909         }
910         else
911         {
912           if (!aa.visible && !addedToHidden.contains(aa.label))
913           {
914             hiddenTypes.add(labelAsList);
915             addedToHidden.add(aa.label);
916           }
917         }
918       }
919     }
920     /*
921      * finally add the 'composite group labels' to the appropriate lists,
922      * depending on whether the group is identified as visible or hidden
923      */
924     for (int group : groupLabels.keySet())
925     {
926       final List<String> groupLabel = groupLabels.get(group);
927       if (visibleGraphGroups.get(group))
928       {
929         if (!shownTypes.contains(groupLabel))
930         {
931           shownTypes.add(groupLabel);
932         }
933       }
934       else if (!hiddenTypes.contains(groupLabel))
935       {
936         hiddenTypes.add(groupLabel);
937       }
938     }
939   }
940
941   /**
942    * Returns a BitSet (possibly empty) of those graphGroups for line graph
943    * annotations, which have at least one member annotation row marked visible.
944    * The logic is that only one row in the group is marked visible, but when it
945    * is drawn, so are all the other rows in the same group.
946    * <p/>
947    * This lookup set allows us to check whether rows marked not visible are in
948    * fact shown.
949    * 
950    * @see AnnotationRenderer#drawComponent
951    * @param annotations
952    * @return
953    */
954   public static BitSet getVisibleLineGraphGroups(
955           AlignmentAnnotation[] annotations)
956   {
957     // todo move to a utility class
958     BitSet result = new BitSet();
959     for (AlignmentAnnotation ann : annotations)
960     {
961       if (ann.graph == AlignmentAnnotation.LINE_GRAPH && ann.visible)
962       {
963         int gg = ann.graphGroup;
964         if (gg > -1)
965         {
966           result.set(gg);
967         }
968       }
969     }
970     return result;
971   }
972
973   /**
974    * Add one annotation type to the 'Show Annotations' or 'Hide Annotations'
975    * menus.
976    * 
977    * @param showOrHideMenu
978    *          the menu to add to
979    * @param types
980    *          the label to add
981    * @param allTypes
982    *          if true this is a special label meaning 'All'
983    * @param actionIsShow
984    *          if true, the select menu item action is to show the annotation
985    *          type, else hide
986    */
987   protected void addAnnotationTypeToShowHide(JMenu showOrHideMenu,
988           final Collection<String> types, final boolean allTypes,
989           final boolean actionIsShow)
990   {
991     String label = types.toString(); // [a, b, c]
992     label = label.substring(1, label.length() - 1);
993     final JMenuItem item = new JMenuItem(label);
994     item.addActionListener(new java.awt.event.ActionListener()
995     {
996       @Override
997       public void actionPerformed(ActionEvent e)
998       {
999         showHideAnnotation_actionPerformed(types, allTypes, actionIsShow);
1000       }
1001     });
1002     showOrHideMenu.add(item);
1003   }
1004
1005   /**
1006    * Action on selecting a list of annotation type (or the 'all types' values)
1007    * to show or hide for the selection.
1008    * 
1009    * @param types
1010    * @param anyType
1011    * @param doShow
1012    */
1013   protected void showHideAnnotation_actionPerformed(
1014           Collection<String> types,
1015           boolean anyType, boolean doShow)
1016   {
1017     for (AlignmentAnnotation aa : ap.getAlignment()
1018             .getAlignmentAnnotation())
1019     {
1020       if (anyType || types.contains(aa.label))
1021       {
1022         if ((aa.sequenceRef != null)
1023                 && ap.av.getSelectionGroup().getSequences()
1024                         .contains(aa.sequenceRef))
1025         {
1026           aa.visible = doShow;
1027         }
1028       }
1029     }
1030     refresh();
1031   }
1032
1033   private void buildGroupURLMenu(SequenceGroup sg, Vector groupLinks)
1034   {
1035
1036     // TODO: usability: thread off the generation of group url content so root
1037     // menu appears asap
1038     // sequence only URLs
1039     // ID/regex match URLs
1040     groupLinksMenu = new JMenu(
1041             MessageManager.getString("action.group_link"));
1042     JMenu[] linkMenus = new JMenu[]
1043     { null, new JMenu(MessageManager.getString("action.ids")),
1044         new JMenu(MessageManager.getString("action.sequences")),
1045         new JMenu(MessageManager.getString("action.ids_sequences")) }; // three
1046                                                                        // types
1047                                                                        // of url
1048                                                                        // that
1049                                                                        // might
1050                                                                        // be
1051     // created.
1052     SequenceI[] seqs = ap.av.getSelectionAsNewSequence();
1053     String[][] idandseqs = GroupUrlLink.formStrings(seqs);
1054     Hashtable commonDbrefs = new Hashtable();
1055     for (int sq = 0; sq < seqs.length; sq++)
1056     {
1057
1058       int start = seqs[sq].findPosition(sg.getStartRes()), end = seqs[sq]
1059               .findPosition(sg.getEndRes());
1060       // just collect ids from dataset sequence
1061       // TODO: check if IDs collected from selecton group intersects with the
1062       // current selection, too
1063       SequenceI sqi = seqs[sq];
1064       while (sqi.getDatasetSequence() != null)
1065       {
1066         sqi = sqi.getDatasetSequence();
1067       }
1068       DBRefEntry[] dbr = sqi.getDBRef();
1069       if (dbr != null && dbr.length > 0)
1070       {
1071         for (int d = 0; d < dbr.length; d++)
1072         {
1073           String src = dbr[d].getSource(); // jalview.util.DBRefUtils.getCanonicalName(dbr[d].getSource()).toUpperCase();
1074           Object[] sarray = (Object[]) commonDbrefs.get(src);
1075           if (sarray == null)
1076           {
1077             sarray = new Object[2];
1078             sarray[0] = new int[]
1079             { 0 };
1080             sarray[1] = new String[seqs.length];
1081
1082             commonDbrefs.put(src, sarray);
1083           }
1084
1085           if (((String[]) sarray[1])[sq] == null)
1086           {
1087             if (!dbr[d].hasMap()
1088                     || (dbr[d].getMap().locateMappedRange(start, end) != null))
1089             {
1090               ((String[]) sarray[1])[sq] = dbr[d].getAccessionId();
1091               ((int[]) sarray[0])[0]++;
1092             }
1093           }
1094         }
1095       }
1096     }
1097     // now create group links for all distinct ID/sequence sets.
1098     boolean addMenu = false; // indicates if there are any group links to give
1099                              // to user
1100     for (int i = 0; i < groupLinks.size(); i++)
1101     {
1102       String link = groupLinks.elementAt(i).toString();
1103       GroupUrlLink urlLink = null;
1104       try
1105       {
1106         urlLink = new GroupUrlLink(link);
1107       } catch (Exception foo)
1108       {
1109         jalview.bin.Cache.log.error("Exception for GroupURLLink '" + link
1110                 + "'", foo);
1111         continue;
1112       }
1113       ;
1114       if (!urlLink.isValid())
1115       {
1116         jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
1117         continue;
1118       }
1119       final String label = urlLink.getLabel();
1120       boolean usingNames = false;
1121       // Now see which parts of the group apply for this URL
1122       String ltarget = urlLink.getTarget(); // jalview.util.DBRefUtils.getCanonicalName(urlLink.getTarget());
1123       Object[] idset = (Object[]) commonDbrefs.get(ltarget.toUpperCase());
1124       String[] seqstr, ids; // input to makeUrl
1125       if (idset != null)
1126       {
1127         int numinput = ((int[]) idset[0])[0];
1128         String[] allids = ((String[]) idset[1]);
1129         seqstr = new String[numinput];
1130         ids = new String[numinput];
1131         for (int sq = 0, idcount = 0; sq < seqs.length; sq++)
1132         {
1133           if (allids[sq] != null)
1134           {
1135             ids[idcount] = allids[sq];
1136             seqstr[idcount++] = idandseqs[1][sq];
1137           }
1138         }
1139       }
1140       else
1141       {
1142         // just use the id/seq set
1143         seqstr = idandseqs[1];
1144         ids = idandseqs[0];
1145         usingNames = true;
1146       }
1147       // and try and make the groupURL!
1148
1149       Object[] urlset = null;
1150       try
1151       {
1152         urlset = urlLink.makeUrlStubs(ids, seqstr,
1153                 "FromJalview" + System.currentTimeMillis(), false);
1154       } catch (UrlStringTooLongException e)
1155       {
1156       }
1157       if (urlset != null)
1158       {
1159         int type = urlLink.getGroupURLType() & 3;
1160         // System.out.println(urlLink.getGroupURLType()
1161         // +" "+((String[])urlset[3])[0]);
1162         // first two bits ofurlLink type bitfield are sequenceids and sequences
1163         // TODO: FUTURE: ensure the groupURL menu structure can be generalised
1164         addshowLink(linkMenus[type], label
1165                 + (((type & 1) == 1) ? ("("
1166                         + (usingNames ? "Names" : ltarget) + ")") : ""),
1167                 urlLink, urlset);
1168         addMenu = true;
1169       }
1170     }
1171     if (addMenu)
1172     {
1173       groupLinksMenu = new JMenu(
1174               MessageManager.getString("action.group_link"));
1175       for (int m = 0; m < linkMenus.length; m++)
1176       {
1177         if (linkMenus[m] != null
1178                 && linkMenus[m].getMenuComponentCount() > 0)
1179         {
1180           groupLinksMenu.add(linkMenus[m]);
1181         }
1182       }
1183
1184       groupMenu.add(groupLinksMenu);
1185     }
1186   }
1187
1188   /**
1189    * add a show URL menu item to the given linkMenu
1190    * 
1191    * @param linkMenu
1192    * @param label
1193    *          - menu label string
1194    * @param url
1195    *          - url to open
1196    */
1197   private void addshowLink(JMenu linkMenu, String label, final String url)
1198   {
1199     JMenuItem item = new JMenuItem(label);
1200     item.setToolTipText(MessageManager.formatMessage(
1201             "label.open_url_param", new String[]
1202             { url }));
1203     item.addActionListener(new java.awt.event.ActionListener()
1204     {
1205       @Override
1206       public void actionPerformed(ActionEvent e)
1207       {
1208         new Thread(new Runnable()
1209         {
1210
1211           @Override
1212           public void run()
1213           {
1214             showLink(url);
1215           }
1216
1217         }).start();
1218       }
1219     });
1220
1221     linkMenu.add(item);
1222   }
1223
1224   /**
1225    * add a late bound groupURL item to the given linkMenu
1226    * 
1227    * @param linkMenu
1228    * @param label
1229    *          - menu label string
1230    * @param urlgenerator
1231    *          GroupURLLink used to generate URL
1232    * @param urlstub
1233    *          Object array returned from the makeUrlStubs function.
1234    */
1235   private void addshowLink(JMenu linkMenu, String label,
1236           final GroupUrlLink urlgenerator, final Object[] urlstub)
1237   {
1238     JMenuItem item = new JMenuItem(label);
1239     item.setToolTipText(MessageManager.formatMessage(
1240             "label.open_url_seqs_param",
1241             new Object[]
1242             { urlgenerator.getUrl_prefix(),
1243                 urlgenerator.getNumberInvolved(urlstub) }));
1244     // TODO: put in info about what is being sent.
1245     item.addActionListener(new java.awt.event.ActionListener()
1246     {
1247       @Override
1248       public void actionPerformed(ActionEvent e)
1249       {
1250         new Thread(new Runnable()
1251         {
1252
1253           @Override
1254           public void run()
1255           {
1256             try
1257             {
1258               showLink(urlgenerator.constructFrom(urlstub));
1259             } catch (UrlStringTooLongException e)
1260             {
1261             }
1262           }
1263
1264         }).start();
1265       }
1266     });
1267
1268     linkMenu.add(item);
1269   }
1270
1271   /**
1272    * DOCUMENT ME!
1273    * 
1274    * @throws Exception
1275    *           DOCUMENT ME!
1276    */
1277   private void jbInit() throws Exception
1278   {
1279     groupMenu.setText(MessageManager.getString("label.group"));
1280     groupMenu.setText(MessageManager.getString("label.selection"));
1281     groupName.setText(MessageManager.getString("label.name"));
1282     groupName.addActionListener(new java.awt.event.ActionListener()
1283     {
1284       @Override
1285       public void actionPerformed(ActionEvent e)
1286       {
1287         groupName_actionPerformed();
1288       }
1289     });
1290     sequenceMenu.setText(MessageManager.getString("label.sequence"));
1291     sequenceName.setText(MessageManager
1292             .getString("label.edit_name_description"));
1293     sequenceName.addActionListener(new java.awt.event.ActionListener()
1294     {
1295       @Override
1296       public void actionPerformed(ActionEvent e)
1297       {
1298         sequenceName_actionPerformed();
1299       }
1300     });
1301     chooseAnnotations.setText(MessageManager
1302             .getString("label.choose_annotations") + "...");
1303     chooseAnnotations.addActionListener(new java.awt.event.ActionListener()
1304     {
1305       @Override
1306       public void actionPerformed(ActionEvent e)
1307       {
1308         chooseAnnotations_actionPerformed(e);
1309       }
1310     });
1311     sequenceDetails.setText(MessageManager
1312             .getString("label.sequence_details") + "...");
1313     sequenceDetails.addActionListener(new java.awt.event.ActionListener()
1314     {
1315       @Override
1316       public void actionPerformed(ActionEvent e)
1317       {
1318         sequenceDetails_actionPerformed();
1319       }
1320     });
1321     sequenceSelDetails.setText(MessageManager
1322             .getString("label.sequence_details") + "...");
1323     sequenceSelDetails
1324             .addActionListener(new java.awt.event.ActionListener()
1325             {
1326               @Override
1327               public void actionPerformed(ActionEvent e)
1328               {
1329                 sequenceSelectionDetails_actionPerformed();
1330               }
1331             });
1332     PIDColour.setFocusPainted(false);
1333     unGroupMenuItem
1334             .setText(MessageManager.getString("action.remove_group"));
1335     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
1336     {
1337       @Override
1338       public void actionPerformed(ActionEvent e)
1339       {
1340         unGroupMenuItem_actionPerformed();
1341       }
1342     });
1343     createGroupMenuItem.setText(MessageManager
1344             .getString("action.create_group"));
1345     createGroupMenuItem
1346             .addActionListener(new java.awt.event.ActionListener()
1347             {
1348               @Override
1349               public void actionPerformed(ActionEvent e)
1350               {
1351                 createGroupMenuItem_actionPerformed();
1352               }
1353             });
1354
1355     outline.setText(MessageManager.getString("action.border_colour"));
1356     outline.addActionListener(new java.awt.event.ActionListener()
1357     {
1358       @Override
1359       public void actionPerformed(ActionEvent e)
1360       {
1361         outline_actionPerformed();
1362       }
1363     });
1364     nucleotideMenuItem
1365             .setText(MessageManager.getString("label.nucleotide"));
1366     nucleotideMenuItem.addActionListener(new ActionListener()
1367     {
1368       @Override
1369       public void actionPerformed(ActionEvent e)
1370       {
1371         nucleotideMenuItem_actionPerformed();
1372       }
1373     });
1374     colourMenu.setText(MessageManager.getString("label.group_colour"));
1375     showBoxes.setText(MessageManager.getString("action.boxes"));
1376     showBoxes.setState(true);
1377     showBoxes.addActionListener(new ActionListener()
1378     {
1379       @Override
1380       public void actionPerformed(ActionEvent e)
1381       {
1382         showBoxes_actionPerformed();
1383       }
1384     });
1385     showText.setText(MessageManager.getString("action.text"));
1386     showText.setState(true);
1387     showText.addActionListener(new ActionListener()
1388     {
1389       @Override
1390       public void actionPerformed(ActionEvent e)
1391       {
1392         showText_actionPerformed();
1393       }
1394     });
1395     showColourText.setText(MessageManager.getString("label.colour_text"));
1396     showColourText.addActionListener(new ActionListener()
1397     {
1398       @Override
1399       public void actionPerformed(ActionEvent e)
1400       {
1401         showColourText_actionPerformed();
1402       }
1403     });
1404     displayNonconserved.setText(MessageManager
1405             .getString("label.show_non_conversed"));
1406     displayNonconserved.setState(true);
1407     displayNonconserved.addActionListener(new ActionListener()
1408     {
1409       @Override
1410       public void actionPerformed(ActionEvent e)
1411       {
1412         showNonconserved_actionPerformed();
1413       }
1414     });
1415     editMenu.setText(MessageManager.getString("action.edit"));
1416     cut.setText(MessageManager.getString("action.cut"));
1417     cut.addActionListener(new ActionListener()
1418     {
1419       @Override
1420       public void actionPerformed(ActionEvent e)
1421       {
1422         cut_actionPerformed();
1423       }
1424     });
1425     upperCase.setText(MessageManager.getString("label.to_upper_case"));
1426     upperCase.addActionListener(new ActionListener()
1427     {
1428       @Override
1429       public void actionPerformed(ActionEvent e)
1430       {
1431         changeCase(e);
1432       }
1433     });
1434     copy.setText(MessageManager.getString("action.copy"));
1435     copy.addActionListener(new ActionListener()
1436     {
1437       @Override
1438       public void actionPerformed(ActionEvent e)
1439       {
1440         copy_actionPerformed();
1441       }
1442     });
1443     lowerCase.setText(MessageManager.getString("label.to_lower_case"));
1444     lowerCase.addActionListener(new ActionListener()
1445     {
1446       @Override
1447       public void actionPerformed(ActionEvent e)
1448       {
1449         changeCase(e);
1450       }
1451     });
1452     toggle.setText(MessageManager.getString("label.toggle_case"));
1453     toggle.addActionListener(new ActionListener()
1454     {
1455       @Override
1456       public void actionPerformed(ActionEvent e)
1457       {
1458         changeCase(e);
1459       }
1460     });
1461     pdbMenu.setText(MessageManager
1462             .getString("label.associate_structure_with_sequence"));
1463     pdbFromFile.setText(MessageManager.getString("label.from_file"));
1464     pdbFromFile.addActionListener(new ActionListener()
1465     {
1466       @Override
1467       public void actionPerformed(ActionEvent e)
1468       {
1469         pdbFromFile_actionPerformed();
1470       }
1471     });
1472     // RNAFold.setText("From RNA Fold with predict2D");
1473     // RNAFold.addActionListener(new ActionListener()
1474     // {
1475     // public void actionPerformed(ActionEvent e)
1476     // {
1477     // try {
1478     // RNAFold_actionPerformed();
1479     // } catch (Exception e1) {
1480     // // TODO Auto-generated catch block
1481     // e1.printStackTrace();
1482     // }
1483     // }
1484     // });
1485     // ContraFold.setText("From Contra Fold with predict2D");
1486     // ContraFold.addActionListener(new ActionListener()
1487     // {
1488     // public void actionPerformed(ActionEvent e)
1489     // {
1490     // try {
1491     // ContraFold_actionPerformed();
1492     // } catch (Exception e1) {
1493     // // TODO Auto-generated catch block
1494     // e1.printStackTrace();
1495     // }
1496     // }
1497     // });
1498     enterPDB.setText(MessageManager.getString("label.enter_pdb_id"));
1499     enterPDB.addActionListener(new ActionListener()
1500     {
1501       @Override
1502       public void actionPerformed(ActionEvent e)
1503       {
1504         enterPDB_actionPerformed();
1505       }
1506     });
1507     discoverPDB.setText(MessageManager.getString("label.discover_pdb_ids"));
1508     discoverPDB.addActionListener(new ActionListener()
1509     {
1510       @Override
1511       public void actionPerformed(ActionEvent e)
1512       {
1513         discoverPDB_actionPerformed();
1514       }
1515     });
1516     outputMenu.setText(MessageManager.getString("label.out_to_textbox")
1517             + "...");
1518     showAnnotationsMenu.setText(MessageManager
1519             .getString("label.show_annotations"));
1520     hideAnnotationsMenu.setText(MessageManager
1521             .getString("label.hide_annotations"));
1522     sequenceFeature.setText(MessageManager
1523             .getString("label.create_sequence_feature"));
1524     sequenceFeature.addActionListener(new ActionListener()
1525     {
1526       @Override
1527       public void actionPerformed(ActionEvent e)
1528       {
1529         sequenceFeature_actionPerformed();
1530       }
1531     });
1532     textColour.setText(MessageManager.getString("label.text_colour"));
1533     textColour.addActionListener(new ActionListener()
1534     {
1535       @Override
1536       public void actionPerformed(ActionEvent e)
1537       {
1538         textColour_actionPerformed();
1539       }
1540     });
1541     jMenu1.setText(MessageManager.getString("label.group"));
1542     structureMenu.setText(MessageManager.getString("label.structure"));
1543     viewStructureMenu.setText(MessageManager
1544             .getString("label.view_structure"));
1545     // colStructureMenu.setText("Colour By Structure");
1546     editSequence.setText(MessageManager.getString("label.edit_sequence")
1547             + "...");
1548     editSequence.addActionListener(new ActionListener()
1549     {
1550       @Override
1551       public void actionPerformed(ActionEvent actionEvent)
1552       {
1553         editSequence_actionPerformed(actionEvent);
1554       }
1555     });
1556
1557     /*
1558      * annotationMenuItem.setText("By Annotation");
1559      * annotationMenuItem.addActionListener(new ActionListener() { public void
1560      * actionPerformed(ActionEvent actionEvent) {
1561      * annotationMenuItem_actionPerformed(actionEvent); } });
1562      */
1563     groupMenu.add(sequenceSelDetails);
1564     add(groupMenu);
1565     add(sequenceMenu);
1566     this.add(structureMenu);
1567     // groupMenu.add(chooseAnnotations);
1568     groupMenu.add(showAnnotationsMenu);
1569     groupMenu.add(hideAnnotationsMenu);
1570     groupMenu.add(editMenu);
1571     groupMenu.add(outputMenu);
1572     groupMenu.add(sequenceFeature);
1573     groupMenu.add(createGroupMenuItem);
1574     groupMenu.add(unGroupMenuItem);
1575     groupMenu.add(jMenu1);
1576     sequenceMenu.add(sequenceName);
1577     sequenceMenu.add(sequenceDetails);
1578     colourMenu.add(textColour);
1579     colourMenu.add(noColourmenuItem);
1580     colourMenu.add(clustalColour);
1581     colourMenu.add(BLOSUM62Colour);
1582     colourMenu.add(PIDColour);
1583     colourMenu.add(zappoColour);
1584     colourMenu.add(taylorColour);
1585     colourMenu.add(hydrophobicityColour);
1586     colourMenu.add(helixColour);
1587     colourMenu.add(strandColour);
1588     colourMenu.add(turnColour);
1589     colourMenu.add(buriedColour);
1590     colourMenu.add(nucleotideMenuItem);
1591     if (ap.getAlignment().isNucleotide())
1592     {
1593       // JBPNote - commented since the colourscheme isn't functional
1594       // colourMenu.add(RNAInteractionColour);
1595       colourMenu.add(purinePyrimidineColour);
1596     }
1597     // colourMenu.add(covariationColour);
1598     colourMenu.add(userDefinedColour);
1599
1600     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
1601     {
1602       java.util.Enumeration userColours = jalview.gui.UserDefinedColours
1603               .getUserColourSchemes().keys();
1604
1605       while (userColours.hasMoreElements())
1606       {
1607         JMenuItem item = new JMenuItem(userColours.nextElement().toString());
1608         item.addActionListener(new ActionListener()
1609         {
1610           @Override
1611           public void actionPerformed(ActionEvent evt)
1612           {
1613             userDefinedColour_actionPerformed(evt);
1614           }
1615         });
1616         colourMenu.add(item);
1617       }
1618     }
1619
1620     colourMenu.addSeparator();
1621     colourMenu.add(abovePIDColour);
1622     colourMenu.add(conservationMenuItem);
1623     // colourMenu.add(annotationMenuItem);
1624     editMenu.add(copy);
1625     editMenu.add(cut);
1626     editMenu.add(editSequence);
1627     editMenu.add(upperCase);
1628     editMenu.add(lowerCase);
1629     editMenu.add(toggle);
1630     pdbMenu.add(pdbFromFile);
1631     // JBPNote: These shouldn't be added here - should appear in a generic
1632     // 'apply web service to this sequence menu'
1633     // pdbMenu.add(RNAFold);
1634     // pdbMenu.add(ContraFold);
1635     pdbMenu.add(enterPDB);
1636     pdbMenu.add(discoverPDB);
1637     jMenu1.add(groupName);
1638     jMenu1.add(colourMenu);
1639     jMenu1.add(showBoxes);
1640     jMenu1.add(showText);
1641     jMenu1.add(showColourText);
1642     jMenu1.add(outline);
1643     jMenu1.add(displayNonconserved);
1644     structureMenu.add(pdbMenu);
1645     structureMenu.add(viewStructureMenu);
1646     // structureMenu.add(colStructureMenu);
1647     noColourmenuItem.setText(MessageManager.getString("label.none"));
1648     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
1649     {
1650       @Override
1651       public void actionPerformed(ActionEvent e)
1652       {
1653         noColourmenuItem_actionPerformed();
1654       }
1655     });
1656
1657     clustalColour.setText(MessageManager
1658             .getString("label.clustalx_colours"));
1659     clustalColour.addActionListener(new java.awt.event.ActionListener()
1660     {
1661       @Override
1662       public void actionPerformed(ActionEvent e)
1663       {
1664         clustalColour_actionPerformed();
1665       }
1666     });
1667     zappoColour.setText(MessageManager.getString("label.zappo"));
1668     zappoColour.addActionListener(new java.awt.event.ActionListener()
1669     {
1670       @Override
1671       public void actionPerformed(ActionEvent e)
1672       {
1673         zappoColour_actionPerformed();
1674       }
1675     });
1676     taylorColour.setText(MessageManager.getString("label.taylor"));
1677     taylorColour.addActionListener(new java.awt.event.ActionListener()
1678     {
1679       @Override
1680       public void actionPerformed(ActionEvent e)
1681       {
1682         taylorColour_actionPerformed();
1683       }
1684     });
1685     hydrophobicityColour.setText(MessageManager
1686             .getString("label.hydrophobicity"));
1687     hydrophobicityColour
1688             .addActionListener(new java.awt.event.ActionListener()
1689             {
1690               @Override
1691               public void actionPerformed(ActionEvent e)
1692               {
1693                 hydrophobicityColour_actionPerformed();
1694               }
1695             });
1696     helixColour.setText(MessageManager.getString("label.helix_propensity"));
1697     helixColour.addActionListener(new java.awt.event.ActionListener()
1698     {
1699       @Override
1700       public void actionPerformed(ActionEvent e)
1701       {
1702         helixColour_actionPerformed();
1703       }
1704     });
1705     strandColour.setText(MessageManager
1706             .getString("label.strand_propensity"));
1707     strandColour.addActionListener(new java.awt.event.ActionListener()
1708     {
1709       @Override
1710       public void actionPerformed(ActionEvent e)
1711       {
1712         strandColour_actionPerformed();
1713       }
1714     });
1715     turnColour.setText(MessageManager.getString("label.turn_propensity"));
1716     turnColour.addActionListener(new java.awt.event.ActionListener()
1717     {
1718       @Override
1719       public void actionPerformed(ActionEvent e)
1720       {
1721         turnColour_actionPerformed();
1722       }
1723     });
1724     buriedColour.setText(MessageManager.getString("label.buried_index"));
1725     buriedColour.addActionListener(new java.awt.event.ActionListener()
1726     {
1727       @Override
1728       public void actionPerformed(ActionEvent e)
1729       {
1730         buriedColour_actionPerformed();
1731       }
1732     });
1733     abovePIDColour.setText(MessageManager
1734             .getString("label.above_identity_percentage"));
1735     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
1736     {
1737       @Override
1738       public void actionPerformed(ActionEvent e)
1739       {
1740         abovePIDColour_actionPerformed();
1741       }
1742     });
1743     userDefinedColour.setText(MessageManager
1744             .getString("action.user_defined"));
1745     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
1746     {
1747       @Override
1748       public void actionPerformed(ActionEvent e)
1749       {
1750         userDefinedColour_actionPerformed(e);
1751       }
1752     });
1753     PIDColour
1754             .setText(MessageManager.getString("label.percentage_identity"));
1755     PIDColour.addActionListener(new java.awt.event.ActionListener()
1756     {
1757       @Override
1758       public void actionPerformed(ActionEvent e)
1759       {
1760         PIDColour_actionPerformed();
1761       }
1762     });
1763     BLOSUM62Colour.setText(MessageManager.getString("label.blosum62"));
1764     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
1765     {
1766       @Override
1767       public void actionPerformed(ActionEvent e)
1768       {
1769         BLOSUM62Colour_actionPerformed();
1770       }
1771     });
1772     purinePyrimidineColour.setText(MessageManager
1773             .getString("label.purine_pyrimidine"));
1774     purinePyrimidineColour
1775             .addActionListener(new java.awt.event.ActionListener()
1776             {
1777               @Override
1778               public void actionPerformed(ActionEvent e)
1779               {
1780                 purinePyrimidineColour_actionPerformed();
1781               }
1782             });
1783
1784     /*
1785      * covariationColour.addActionListener(new java.awt.event.ActionListener() {
1786      * public void actionPerformed(ActionEvent e) {
1787      * covariationColour_actionPerformed(); } });
1788      */
1789
1790     conservationMenuItem.setText(MessageManager
1791             .getString("label.conservation"));
1792     conservationMenuItem
1793             .addActionListener(new java.awt.event.ActionListener()
1794             {
1795               @Override
1796               public void actionPerformed(ActionEvent e)
1797               {
1798                 conservationMenuItem_actionPerformed();
1799               }
1800             });
1801   }
1802
1803   protected void sequenceSelectionDetails_actionPerformed()
1804   {
1805     createSequenceDetailsReport(ap.av.getSequenceSelection());
1806   }
1807
1808   protected void sequenceDetails_actionPerformed()
1809   {
1810     createSequenceDetailsReport(new SequenceI[]
1811     { sequence });
1812   }
1813
1814   public void createSequenceDetailsReport(SequenceI[] sequences)
1815   {
1816     CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
1817     StringBuffer contents = new StringBuffer();
1818     for (SequenceI seq : sequences)
1819     {
1820       contents.append("<p><h2>"
1821               + MessageManager
1822                       .formatMessage(
1823                               "label.create_sequence_details_report_annotation_for",
1824                               new String[]
1825                               { seq.getDisplayId(true) }) + "</h2></p><p>");
1826       new SequenceAnnotationReport(null)
1827               .createSequenceAnnotationReport(
1828                       contents,
1829                       seq,
1830                       true,
1831                       true,
1832                       false,
1833                       (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
1834                               : null);
1835       contents.append("</p>");
1836     }
1837     cap.setText("<html>" + contents.toString() + "</html>");
1838
1839     Desktop.instance.addInternalFrame(cap, MessageManager.formatMessage(
1840             "label.sequece_details_for",
1841             (sequences.length == 1 ? new String[]
1842             { sequences[0].getDisplayId(true) } : new String[]
1843             { MessageManager.getString("label.selection") })), 500, 400);
1844
1845   }
1846
1847   protected void showNonconserved_actionPerformed()
1848   {
1849     getGroup().setShowNonconserved(displayNonconserved.isSelected());
1850     refresh();
1851   }
1852
1853   /**
1854    * call to refresh view after settings change
1855    */
1856   void refresh()
1857   {
1858     ap.updateAnnotation();
1859     ap.paintAlignment(true);
1860
1861     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
1862   }
1863
1864   /**
1865    * DOCUMENT ME!
1866    * 
1867    * @param e
1868    *          DOCUMENT ME!
1869    */
1870   protected void clustalColour_actionPerformed()
1871   {
1872     SequenceGroup sg = getGroup();
1873     sg.cs = new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences());
1874     refresh();
1875   }
1876
1877   /**
1878    * DOCUMENT ME!
1879    * 
1880    * @param e
1881    *          DOCUMENT ME!
1882    */
1883   protected void zappoColour_actionPerformed()
1884   {
1885     getGroup().cs = new ZappoColourScheme();
1886     refresh();
1887   }
1888
1889   /**
1890    * DOCUMENT ME!
1891    * 
1892    * @param e
1893    *          DOCUMENT ME!
1894    */
1895   protected void taylorColour_actionPerformed()
1896   {
1897     getGroup().cs = new TaylorColourScheme();
1898     refresh();
1899   }
1900
1901   /**
1902    * DOCUMENT ME!
1903    * 
1904    * @param e
1905    *          DOCUMENT ME!
1906    */
1907   protected void hydrophobicityColour_actionPerformed()
1908   {
1909     getGroup().cs = new HydrophobicColourScheme();
1910     refresh();
1911   }
1912
1913   /**
1914    * DOCUMENT ME!
1915    * 
1916    * @param e
1917    *          DOCUMENT ME!
1918    */
1919   protected void helixColour_actionPerformed()
1920   {
1921     getGroup().cs = new HelixColourScheme();
1922     refresh();
1923   }
1924
1925   /**
1926    * DOCUMENT ME!
1927    * 
1928    * @param e
1929    *          DOCUMENT ME!
1930    */
1931   protected void strandColour_actionPerformed()
1932   {
1933     getGroup().cs = new StrandColourScheme();
1934     refresh();
1935   }
1936
1937   /**
1938    * DOCUMENT ME!
1939    * 
1940    * @param e
1941    *          DOCUMENT ME!
1942    */
1943   protected void turnColour_actionPerformed()
1944   {
1945     getGroup().cs = new TurnColourScheme();
1946     refresh();
1947   }
1948
1949   /**
1950    * DOCUMENT ME!
1951    * 
1952    * @param e
1953    *          DOCUMENT ME!
1954    */
1955   protected void buriedColour_actionPerformed()
1956   {
1957     getGroup().cs = new BuriedColourScheme();
1958     refresh();
1959   }
1960
1961   /**
1962    * DOCUMENT ME!
1963    * 
1964    * @param e
1965    *          DOCUMENT ME!
1966    */
1967   public void nucleotideMenuItem_actionPerformed()
1968   {
1969     getGroup().cs = new NucleotideColourScheme();
1970     refresh();
1971   }
1972
1973   protected void purinePyrimidineColour_actionPerformed()
1974   {
1975     getGroup().cs = new PurinePyrimidineColourScheme();
1976     refresh();
1977   }
1978
1979   /*
1980    * protected void covariationColour_actionPerformed() { getGroup().cs = new
1981    * CovariationColourScheme(sequence.getAnnotation()[0]); refresh(); }
1982    */
1983   /**
1984    * DOCUMENT ME!
1985    * 
1986    * @param e
1987    *          DOCUMENT ME!
1988    */
1989   protected void abovePIDColour_actionPerformed()
1990   {
1991     SequenceGroup sg = getGroup();
1992     if (sg.cs == null)
1993     {
1994       return;
1995     }
1996
1997     if (abovePIDColour.isSelected())
1998     {
1999       sg.cs.setConsensus(AAFrequency.calculate(
2000               sg.getSequences(ap.av.getHiddenRepSequences()),
2001               sg.getStartRes(), sg.getEndRes() + 1));
2002
2003       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
2004               .getName());
2005
2006       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
2007
2008       SliderPanel.showPIDSlider();
2009     }
2010     else
2011     // remove PIDColouring
2012     {
2013       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
2014     }
2015
2016     refresh();
2017   }
2018
2019   /**
2020    * DOCUMENT ME!
2021    * 
2022    * @param e
2023    *          DOCUMENT ME!
2024    */
2025   protected void userDefinedColour_actionPerformed(ActionEvent e)
2026   {
2027     SequenceGroup sg = getGroup();
2028
2029     if (e.getSource().equals(userDefinedColour))
2030     {
2031       new UserDefinedColours(ap, sg);
2032     }
2033     else
2034     {
2035       UserColourScheme udc = (UserColourScheme) UserDefinedColours
2036               .getUserColourSchemes().get(e.getActionCommand());
2037
2038       sg.cs = udc;
2039     }
2040     refresh();
2041   }
2042
2043   /**
2044    * Open a panel where the user can choose which types of sequence annotation
2045    * to show or hide.
2046    * 
2047    * @param e
2048    */
2049   protected void chooseAnnotations_actionPerformed(ActionEvent e)
2050   {
2051     // todo correct way to guard against opening a duplicate panel?
2052     new AnnotationChooser(ap);
2053   }
2054
2055   /**
2056    * DOCUMENT ME!
2057    * 
2058    * @param e
2059    *          DOCUMENT ME!
2060    */
2061   protected void PIDColour_actionPerformed()
2062   {
2063     SequenceGroup sg = getGroup();
2064     sg.cs = new PIDColourScheme();
2065     sg.cs.setConsensus(AAFrequency.calculate(
2066             sg.getSequences(ap.av.getHiddenRepSequences()),
2067             sg.getStartRes(), sg.getEndRes() + 1));
2068     refresh();
2069   }
2070
2071   /**
2072    * DOCUMENT ME!
2073    * 
2074    * @param e
2075    *          DOCUMENT ME!
2076    */
2077   protected void BLOSUM62Colour_actionPerformed()
2078   {
2079     SequenceGroup sg = getGroup();
2080
2081     sg.cs = new Blosum62ColourScheme();
2082
2083     sg.cs.setConsensus(AAFrequency.calculate(
2084             sg.getSequences(ap.av.getHiddenRepSequences()),
2085             sg.getStartRes(), sg.getEndRes() + 1));
2086
2087     refresh();
2088   }
2089
2090   /**
2091    * DOCUMENT ME!
2092    * 
2093    * @param e
2094    *          DOCUMENT ME!
2095    */
2096   protected void noColourmenuItem_actionPerformed()
2097   {
2098     getGroup().cs = null;
2099     refresh();
2100   }
2101
2102   /**
2103    * DOCUMENT ME!
2104    * 
2105    * @param e
2106    *          DOCUMENT ME!
2107    */
2108   protected void conservationMenuItem_actionPerformed()
2109   {
2110     SequenceGroup sg = getGroup();
2111     if (sg.cs == null)
2112     {
2113       return;
2114     }
2115
2116     if (conservationMenuItem.isSelected())
2117     {
2118       // JBPNote: Conservation name shouldn't be i18n translated
2119       Conservation c = new Conservation("Group",
2120               ResidueProperties.propHash, 3, sg.getSequences(ap.av
2121                       .getHiddenRepSequences()), sg.getStartRes(),
2122               sg.getEndRes() + 1);
2123
2124       c.calculate();
2125       c.verdict(false, ap.av.getConsPercGaps());
2126
2127       sg.cs.setConservation(c);
2128
2129       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
2130       SliderPanel.showConservationSlider();
2131     }
2132     else
2133     // remove ConservationColouring
2134     {
2135       sg.cs.setConservation(null);
2136     }
2137
2138     refresh();
2139   }
2140
2141   public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
2142   {
2143     SequenceGroup sg = getGroup();
2144     if (sg == null)
2145     {
2146       return;
2147     }
2148
2149     AnnotationColourGradient acg = new AnnotationColourGradient(
2150             sequence.getAnnotation()[0], null,
2151             AnnotationColourGradient.NO_THRESHOLD);
2152
2153     acg.setPredefinedColours(true);
2154     sg.cs = acg;
2155
2156     refresh();
2157   }
2158
2159   /**
2160    * DOCUMENT ME!
2161    * 
2162    * @param e
2163    *          DOCUMENT ME!
2164    */
2165   protected void groupName_actionPerformed()
2166   {
2167
2168     SequenceGroup sg = getGroup();
2169     EditNameDialog dialog = new EditNameDialog(sg.getName(),
2170             sg.getDescription(), "       "
2171                     + MessageManager.getString("label.group_name") + " ",
2172             MessageManager.getString("label.group_description") + " ",
2173             MessageManager.getString("label.edit_group_name_description"),
2174             ap.alignFrame);
2175
2176     if (!dialog.accept)
2177     {
2178       return;
2179     }
2180
2181     sg.setName(dialog.getName());
2182     sg.setDescription(dialog.getDescription());
2183     refresh();
2184   }
2185
2186   /**
2187    * Get selection group - adding it to the alignment if necessary.
2188    * 
2189    * @return sequence group to operate on
2190    */
2191   SequenceGroup getGroup()
2192   {
2193     SequenceGroup sg = ap.av.getSelectionGroup();
2194     // this method won't add a new group if it already exists
2195     if (sg != null)
2196     {
2197       ap.av.getAlignment().addGroup(sg);
2198     }
2199
2200     return sg;
2201   }
2202
2203   /**
2204    * DOCUMENT ME!
2205    * 
2206    * @param e
2207    *          DOCUMENT ME!
2208    */
2209   void sequenceName_actionPerformed()
2210   {
2211     EditNameDialog dialog = new EditNameDialog(sequence.getName(),
2212             sequence.getDescription(),
2213             "       " + MessageManager.getString("label.sequence_name")
2214                     + " ",
2215             MessageManager.getString("label.sequence_description") + " ",
2216             MessageManager
2217                     .getString("label.edit_sequence_name_description"),
2218             ap.alignFrame);
2219
2220     if (!dialog.accept)
2221     {
2222       return;
2223     }
2224
2225     if (dialog.getName() != null)
2226     {
2227       if (dialog.getName().indexOf(" ") > -1)
2228       {
2229         JOptionPane
2230                 .showMessageDialog(
2231                         ap,
2232                         MessageManager
2233                                 .getString("label.spaces_converted_to_backslashes"),
2234                         MessageManager
2235                                 .getString("label.no_spaces_allowed_sequence_name"),
2236                         JOptionPane.WARNING_MESSAGE);
2237       }
2238
2239       sequence.setName(dialog.getName().replace(' ', '_'));
2240       ap.paintAlignment(false);
2241     }
2242
2243     sequence.setDescription(dialog.getDescription());
2244
2245     ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
2246             .getSequences());
2247
2248   }
2249
2250   /**
2251    * DOCUMENT ME!
2252    * 
2253    * @param e
2254    *          DOCUMENT ME!
2255    */
2256   void unGroupMenuItem_actionPerformed()
2257   {
2258     SequenceGroup sg = ap.av.getSelectionGroup();
2259     ap.av.getAlignment().deleteGroup(sg);
2260     ap.av.setSelectionGroup(null);
2261     refresh();
2262   }
2263
2264   void createGroupMenuItem_actionPerformed()
2265   {
2266     getGroup(); // implicitly creates group - note - should apply defaults / use
2267                 // standard alignment window logic for this
2268     refresh();
2269   }
2270
2271   /**
2272    * DOCUMENT ME!
2273    * 
2274    * @param e
2275    *          DOCUMENT ME!
2276    */
2277   protected void outline_actionPerformed()
2278   {
2279     SequenceGroup sg = getGroup();
2280     Color col = JColorChooser.showDialog(this,
2281             MessageManager.getString("label.select_outline_colour"),
2282             Color.BLUE);
2283
2284     if (col != null)
2285     {
2286       sg.setOutlineColour(col);
2287     }
2288
2289     refresh();
2290   }
2291
2292   /**
2293    * DOCUMENT ME!
2294    * 
2295    * @param e
2296    *          DOCUMENT ME!
2297    */
2298   public void showBoxes_actionPerformed()
2299   {
2300     getGroup().setDisplayBoxes(showBoxes.isSelected());
2301     refresh();
2302   }
2303
2304   /**
2305    * DOCUMENT ME!
2306    * 
2307    * @param e
2308    *          DOCUMENT ME!
2309    */
2310   public void showText_actionPerformed()
2311   {
2312     getGroup().setDisplayText(showText.isSelected());
2313     refresh();
2314   }
2315
2316   /**
2317    * DOCUMENT ME!
2318    * 
2319    * @param e
2320    *          DOCUMENT ME!
2321    */
2322   public void showColourText_actionPerformed()
2323   {
2324     getGroup().setColourText(showColourText.isSelected());
2325     refresh();
2326   }
2327
2328   public void showLink(String url)
2329   {
2330     try
2331     {
2332       jalview.util.BrowserLauncher.openURL(url);
2333     } catch (Exception ex)
2334     {
2335       JOptionPane.showInternalMessageDialog(Desktop.desktop,
2336               MessageManager.getString("label.web_browser_not_found_unix"),
2337               MessageManager.getString("label.web_browser_not_found"),
2338               JOptionPane.WARNING_MESSAGE);
2339
2340       ex.printStackTrace();
2341     }
2342   }
2343
2344   void hideSequences(boolean representGroup)
2345   {
2346     SequenceGroup sg = ap.av.getSelectionGroup();
2347     if (sg == null || sg.getSize() < 1)
2348     {
2349       ap.av.hideSequence(new SequenceI[]
2350       { sequence });
2351       return;
2352     }
2353
2354     ap.av.setSelectionGroup(null);
2355
2356     if (representGroup)
2357     {
2358       ap.av.hideRepSequences(sequence, sg);
2359
2360       return;
2361     }
2362
2363     int gsize = sg.getSize();
2364     SequenceI[] hseqs;
2365
2366     hseqs = new SequenceI[gsize];
2367
2368     int index = 0;
2369     for (int i = 0; i < gsize; i++)
2370     {
2371       hseqs[index++] = sg.getSequenceAt(i);
2372     }
2373
2374     ap.av.hideSequence(hseqs);
2375     // refresh(); TODO: ? needed ?
2376     ap.av.sendSelection();
2377   }
2378
2379   public void copy_actionPerformed()
2380   {
2381     ap.alignFrame.copy_actionPerformed(null);
2382   }
2383
2384   public void cut_actionPerformed()
2385   {
2386     ap.alignFrame.cut_actionPerformed(null);
2387   }
2388
2389   void changeCase(ActionEvent e)
2390   {
2391     Object source = e.getSource();
2392     SequenceGroup sg = ap.av.getSelectionGroup();
2393
2394     if (sg != null)
2395     {
2396       int[][] startEnd = ap.av.getVisibleRegionBoundaries(sg.getStartRes(),
2397               sg.getEndRes() + 1);
2398
2399       String description;
2400       int caseChange;
2401
2402       if (source == toggle)
2403       {
2404         description = MessageManager.getString("label.toggle_case");
2405         caseChange = ChangeCaseCommand.TOGGLE_CASE;
2406       }
2407       else if (source == upperCase)
2408       {
2409         description = MessageManager.getString("label.to_upper_case");
2410         caseChange = ChangeCaseCommand.TO_UPPER;
2411       }
2412       else
2413       {
2414         description = MessageManager.getString("label.to_lower_case");
2415         caseChange = ChangeCaseCommand.TO_LOWER;
2416       }
2417
2418       ChangeCaseCommand caseCommand = new ChangeCaseCommand(description,
2419               sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
2420               startEnd, caseChange);
2421
2422       ap.alignFrame.addHistoryItem(caseCommand);
2423
2424       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
2425               .getSequences());
2426
2427     }
2428   }
2429
2430   public void outputText_actionPerformed(ActionEvent e)
2431   {
2432     CutAndPasteTransfer cap = new CutAndPasteTransfer();
2433     cap.setForInput(null);
2434     Desktop.addInternalFrame(cap, MessageManager.formatMessage(
2435             "label.alignment_output_command", new String[]
2436             { e.getActionCommand() }), 600, 500);
2437
2438     String[] omitHidden = null;
2439
2440     System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens
2441     // or we simply trust the user wants
2442     // wysiwig behaviour
2443
2444     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
2445             ap.av, true));
2446   }
2447
2448   public void pdbFromFile_actionPerformed()
2449   {
2450     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
2451             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
2452     chooser.setFileView(new jalview.io.JalviewFileView());
2453     chooser.setDialogTitle(MessageManager.formatMessage(
2454             "label.select_pdb_file_for", new String[]
2455             { sequence.getDisplayId(false) }));
2456     chooser.setToolTipText(MessageManager.formatMessage(
2457             "label.load_pdb_file_associate_with_sequence", new String[]
2458             { sequence.getDisplayId(false) }));
2459
2460     int value = chooser.showOpenDialog(null);
2461
2462     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
2463     {
2464       String choice = chooser.getSelectedFile().getPath();
2465       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
2466       new AssociatePdbFileWithSeq().associatePdbWithSeq(choice,
2467               jalview.io.AppletFormatAdapter.FILE, sequence, true);
2468     }
2469
2470   }
2471
2472   // JBNote: commented out - these won't be instantiated here...!
2473   // public void RNAFold_actionPerformed() throws Exception
2474   // {
2475   // Predict2D P2D = new Predict2D();
2476   // P2D.getStructure2DFromRNAFold("toto");
2477   // }
2478   //
2479   // public void ContraFold_actionPerformed() throws Exception
2480   // {
2481   // Predict2D P2D = new Predict2D();
2482   // P2D.getStructure2DFromContraFold("toto");
2483   // }
2484   public void enterPDB_actionPerformed()
2485   {
2486     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
2487             MessageManager.getString("label.enter_pdb_id"),
2488             MessageManager.getString("label.enter_pdb_id"),
2489             JOptionPane.QUESTION_MESSAGE);
2490
2491     if (id != null && id.length() > 0)
2492     {
2493       PDBEntry entry = new PDBEntry();
2494       entry.setId(id.toUpperCase());
2495       sequence.getDatasetSequence().addPDBId(entry);
2496     }
2497   }
2498
2499   public void discoverPDB_actionPerformed()
2500   {
2501
2502     final SequenceI[] sequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
2503     { sequence }
2504             : ap.av.getSequenceSelection());
2505     Thread discpdb = new Thread(new Runnable()
2506     {
2507       @Override
2508       public void run()
2509       {
2510
2511         new jalview.ws.DBRefFetcher(sequences, ap.alignFrame)
2512                 .fetchDBRefs(false);
2513       }
2514
2515     });
2516     discpdb.start();
2517   }
2518
2519   public void sequenceFeature_actionPerformed()
2520   {
2521     SequenceGroup sg = ap.av.getSelectionGroup();
2522     if (sg == null)
2523     {
2524       return;
2525     }
2526
2527     int rsize = 0, gSize = sg.getSize();
2528     SequenceI[] rseqs, seqs = new SequenceI[gSize];
2529     SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
2530
2531     for (int i = 0; i < gSize; i++)
2532     {
2533       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
2534       int end = sg.findEndRes(sg.getSequenceAt(i));
2535       if (start <= end)
2536       {
2537         seqs[rsize] = sg.getSequenceAt(i).getDatasetSequence();
2538         features[rsize] = new SequenceFeature(null, null, null, start, end,
2539                 "Jalview");
2540         rsize++;
2541       }
2542     }
2543     rseqs = new SequenceI[rsize];
2544     tfeatures = new SequenceFeature[rsize];
2545     System.arraycopy(seqs, 0, rseqs, 0, rsize);
2546     System.arraycopy(features, 0, tfeatures, 0, rsize);
2547     features = tfeatures;
2548     seqs = rseqs;
2549     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
2550             features, true, ap))
2551     {
2552       ap.alignFrame.setShowSeqFeatures(true);
2553       ap.highlightSearchResults(null);
2554     }
2555   }
2556
2557   public void textColour_actionPerformed()
2558   {
2559     SequenceGroup sg = getGroup();
2560     if (sg != null)
2561     {
2562       new TextColourChooser().chooseColour(ap, sg);
2563     }
2564   }
2565
2566   public void colourByStructure(String pdbid)
2567   {
2568     Annotation[] anots = ap.av.getStructureSelectionManager()
2569             .colourSequenceFromStructure(sequence, pdbid);
2570
2571     AlignmentAnnotation an = new AlignmentAnnotation("Structure",
2572             "Coloured by " + pdbid, anots);
2573
2574     ap.av.getAlignment().addAnnotation(an);
2575     an.createSequenceMapping(sequence, 0, true);
2576     // an.adjustForAlignment();
2577     ap.av.getAlignment().setAnnotationIndex(an, 0);
2578
2579     ap.adjustAnnotationHeight();
2580
2581     sequence.addAlignmentAnnotation(an);
2582
2583   }
2584
2585   public void editSequence_actionPerformed(ActionEvent actionEvent)
2586   {
2587     SequenceGroup sg = ap.av.getSelectionGroup();
2588
2589     if (sg != null)
2590     {
2591       if (sequence == null)
2592         sequence = sg.getSequenceAt(0);
2593
2594       EditNameDialog dialog = new EditNameDialog(
2595               sequence.getSequenceAsString(sg.getStartRes(),
2596                       sg.getEndRes() + 1), null,
2597               MessageManager.getString("label.edit_sequence"), null,
2598               MessageManager.getString("label.edit_sequence"),
2599               ap.alignFrame);
2600
2601       if (dialog.accept)
2602       {
2603         EditCommand editCommand = new EditCommand(
2604                 MessageManager.getString("label.edit_sequences"),
2605                 EditCommand.REPLACE, dialog.getName().replace(' ',
2606                         ap.av.getGapCharacter()),
2607                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
2608                 sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());
2609
2610         ap.alignFrame.addHistoryItem(editCommand);
2611
2612         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
2613                 .getSequences());
2614       }
2615     }
2616   }
2617
2618 }