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