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