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