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