proxy commit for Anne Menard <menard.annec@gmail.com> throw generic exceptions (just...
[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
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("2D RNA " + 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("2D RNA - " + 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("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("Represent Group with " + 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("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("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
419     if (sg != null && sg.getSize() > 0)
420     {
421       groupName.setText("Name: " + sg.getName());
422       groupName.setText("Edit name and description of current group.");
423
424       if (sg.cs instanceof ZappoColourScheme)
425       {
426         zappoColour.setSelected(true);
427       }
428       else if (sg.cs instanceof TaylorColourScheme)
429       {
430         taylorColour.setSelected(true);
431       }
432       else if (sg.cs instanceof PIDColourScheme)
433       {
434         PIDColour.setSelected(true);
435       }
436       else if (sg.cs instanceof Blosum62ColourScheme)
437       {
438         BLOSUM62Colour.setSelected(true);
439       }
440       else if (sg.cs instanceof UserColourScheme)
441       {
442         userDefinedColour.setSelected(true);
443       }
444       else if (sg.cs instanceof HydrophobicColourScheme)
445       {
446         hydrophobicityColour.setSelected(true);
447       }
448       else if (sg.cs instanceof HelixColourScheme)
449       {
450         helixColour.setSelected(true);
451       }
452       else if (sg.cs instanceof StrandColourScheme)
453       {
454         strandColour.setSelected(true);
455       }
456       else if (sg.cs instanceof TurnColourScheme)
457       {
458         turnColour.setSelected(true);
459       }
460       else if (sg.cs instanceof BuriedColourScheme)
461       {
462         buriedColour.setSelected(true);
463       }
464       else if (sg.cs instanceof ClustalxColourScheme)
465       {
466         clustalColour.setSelected(true);
467       }
468       else if (sg.cs instanceof PurinePyrimidineColourScheme)
469       {
470         purinePyrimidineColour.setSelected(true);
471       }
472       
473       else if (sg.cs instanceof RNAInteractionColourScheme)
474       {
475         RNAInteractionColour.setSelected(true);
476       }
477       /*
478        * else if (sg.cs instanceof CovariationColourScheme) {
479        * covariationColour.setSelected(true); }
480        */
481       else
482       {
483         noColourmenuItem.setSelected(true);
484       }
485
486       if (sg.cs != null && sg.cs.conservationApplied())
487       {
488         conservationMenuItem.setSelected(true);
489       }
490       displayNonconserved.setSelected(sg.getShowNonconserved());
491       showText.setSelected(sg.getDisplayText());
492       showColourText.setSelected(sg.getColourText());
493       showBoxes.setSelected(sg.getDisplayBoxes());
494       // add any groupURLs to the groupURL submenu and make it visible
495       if (groupLinks != null && groupLinks.size() > 0)
496       {
497         buildGroupURLMenu(sg, groupLinks);
498       }
499       // Add a 'show all structures' for the current selection
500       Hashtable<String, PDBEntry> pdbe = new Hashtable<String, PDBEntry>();
501       SequenceI sqass = null;
502       for (SequenceI sq : ap.av.getSequenceSelection())
503       {
504         Vector<PDBEntry> pes = (Vector<PDBEntry>) sq.getDatasetSequence()
505                 .getPDBId();
506         if (pes != null)
507         {
508           for (PDBEntry pe : pes)
509           {
510             pdbe.put(pe.getId(), pe);
511             if (sqass == null)
512             {
513               sqass = sq;
514             }
515           }
516         }
517       }
518       if (pdbe.size() > 0)
519       {
520         final PDBEntry[] pe = pdbe.values().toArray(
521                 new PDBEntry[pdbe.size()]);
522         final JMenuItem gpdbview;
523         if (pdbe.size() == 1)
524         {
525           structureMenu.add(gpdbview = new JMenuItem("View structure for "
526                   + sqass.getDisplayId(false)));
527         }
528         else
529         {
530           structureMenu.add(gpdbview = new JMenuItem("View all "
531                   + pdbe.size() + " structures."));
532         }
533         gpdbview.setToolTipText("Open a new Jmol view with all structures associated with the current selection and superimpose them using the alignment.");
534         gpdbview.addActionListener(new ActionListener()
535         {
536
537           @Override
538           public void actionPerformed(ActionEvent e)
539           {
540             new AppJmol(ap, pe, ap.av.collateForPDB(pe));
541           }
542         });
543       }
544     }
545     else
546     {
547       groupMenu.setVisible(false);
548       editMenu.setVisible(false);
549     }
550
551     if (!ap.av.getAlignment().getGroups().contains(sg))
552     {
553       unGroupMenuItem.setVisible(false);
554     }
555
556     if (seq == null)
557     {
558       sequenceMenu.setVisible(false);
559       structureMenu.setVisible(false);
560     }
561
562     if (links != null && links.size() > 0)
563     {
564
565       JMenu linkMenu = new JMenu("Link");
566       Vector linkset = new Vector();
567       for (int i = 0; i < links.size(); i++)
568       {
569         String link = links.elementAt(i).toString();
570         UrlLink urlLink = null;
571         try
572         {
573           urlLink = new UrlLink(link);
574         } catch (Exception foo)
575         {
576           jalview.bin.Cache.log.error("Exception for URLLink '" + link
577                   + "'", foo);
578           continue;
579         }
580         ;
581         if (!urlLink.isValid())
582         {
583           jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
584           continue;
585         }
586         final String label = urlLink.getLabel();
587         if (seq != null && urlLink.isDynamic())
588         {
589
590           // collect matching db-refs
591           DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(
592                   seq.getDBRef(), new String[]
593                   { urlLink.getTarget() });
594           // collect id string too
595           String id = seq.getName();
596           String descr = seq.getDescription();
597           if (descr != null && descr.length() < 1)
598           {
599             descr = null;
600           }
601
602           if (dbr != null)
603           {
604             for (int r = 0; r < dbr.length; r++)
605             {
606               if (id != null && dbr[r].getAccessionId().equals(id))
607               {
608                 // suppress duplicate link creation for the bare sequence ID
609                 // string with this link
610                 id = null;
611               }
612               // create Bare ID link for this RUL
613               String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
614                       true);
615               if (urls != null)
616               {
617                 for (int u = 0; u < urls.length; u += 2)
618                 {
619                   if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
620                   {
621                     linkset.addElement(urls[u] + "|" + urls[u + 1]);
622                     addshowLink(linkMenu, label + "|" + urls[u],
623                             urls[u + 1]);
624                   }
625                 }
626               }
627             }
628           }
629           if (id != null)
630           {
631             // create Bare ID link for this RUL
632             String[] urls = urlLink.makeUrls(id, 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 + 1]);
641                 }
642               }
643             }
644           }
645           // Create urls from description but only for URL links which are regex
646           // links
647           if (descr != null && urlLink.getRegexReplace() != null)
648           {
649             // create link for this URL from description where regex matches
650             String[] urls = urlLink.makeUrls(descr, 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         }
664         else
665         {
666           if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
667           {
668             linkset.addElement(label + "|" + urlLink.getUrl_prefix());
669             // Add a non-dynamic link
670             addshowLink(linkMenu, label, urlLink.getUrl_prefix());
671           }
672         }
673       }
674       if (sequence != null)
675       {
676         sequenceMenu.add(linkMenu);
677       }
678       else
679       {
680         add(linkMenu);
681       }
682     }
683   }
684
685   private void buildGroupURLMenu(SequenceGroup sg, Vector groupLinks)
686   {
687
688     // TODO: usability: thread off the generation of group url content so root
689     // menu appears asap
690     // sequence only URLs
691     // ID/regex match URLs
692     groupLinksMenu = new JMenu("Group Link");
693     JMenu[] linkMenus = new JMenu[]
694     { null, new JMenu("IDS"), new JMenu("Sequences"),
695         new JMenu("IDS and Sequences") }; // three types of url that might be
696                                           // created.
697     SequenceI[] seqs = ap.av.getSelectionAsNewSequence();
698     String[][] idandseqs = GroupUrlLink.formStrings(seqs);
699     Hashtable commonDbrefs = new Hashtable();
700     for (int sq = 0; sq < seqs.length; sq++)
701     {
702
703       int start = seqs[sq].findPosition(sg.getStartRes()), end = seqs[sq]
704               .findPosition(sg.getEndRes());
705       // just collect ids from dataset sequence
706       // TODO: check if IDs collected from selecton group intersects with the
707       // current selection, too
708       SequenceI sqi = seqs[sq];
709       while (sqi.getDatasetSequence() != null)
710       {
711         sqi = sqi.getDatasetSequence();
712       }
713       DBRefEntry[] dbr = sqi.getDBRef();
714       if (dbr != null && dbr.length > 0)
715       {
716         for (int d = 0; d < dbr.length; d++)
717         {
718           String src = dbr[d].getSource(); // jalview.util.DBRefUtils.getCanonicalName(dbr[d].getSource()).toUpperCase();
719           Object[] sarray = (Object[]) commonDbrefs.get(src);
720           if (sarray == null)
721           {
722             sarray = new Object[2];
723             sarray[0] = new int[]
724             { 0 };
725             sarray[1] = new String[seqs.length];
726
727             commonDbrefs.put(src, sarray);
728           }
729
730           if (((String[]) sarray[1])[sq] == null)
731           {
732             if (!dbr[d].hasMap()
733                     || (dbr[d].getMap().locateMappedRange(start, end) != null))
734             {
735               ((String[]) sarray[1])[sq] = dbr[d].getAccessionId();
736               ((int[]) sarray[0])[0]++;
737             }
738           }
739         }
740       }
741     }
742     // now create group links for all distinct ID/sequence sets.
743     boolean addMenu = false; // indicates if there are any group links to give
744                              // to user
745     for (int i = 0; i < groupLinks.size(); i++)
746     {
747       String link = groupLinks.elementAt(i).toString();
748       GroupUrlLink urlLink = null;
749       try
750       {
751         urlLink = new GroupUrlLink(link);
752       } catch (Exception foo)
753       {
754         jalview.bin.Cache.log.error("Exception for GroupURLLink '" + link
755                 + "'", foo);
756         continue;
757       }
758       ;
759       if (!urlLink.isValid())
760       {
761         jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
762         continue;
763       }
764       final String label = urlLink.getLabel();
765       boolean usingNames = false;
766       // Now see which parts of the group apply for this URL
767       String ltarget = urlLink.getTarget(); // jalview.util.DBRefUtils.getCanonicalName(urlLink.getTarget());
768       Object[] idset = (Object[]) commonDbrefs.get(ltarget.toUpperCase());
769       String[] seqstr, ids; // input to makeUrl
770       if (idset != null)
771       {
772         int numinput = ((int[]) idset[0])[0];
773         String[] allids = ((String[]) idset[1]);
774         seqstr = new String[numinput];
775         ids = new String[numinput];
776         for (int sq = 0, idcount = 0; sq < seqs.length; sq++)
777         {
778           if (allids[sq] != null)
779           {
780             ids[idcount] = allids[sq];
781             seqstr[idcount++] = idandseqs[1][sq];
782           }
783         }
784       }
785       else
786       {
787         // just use the id/seq set
788         seqstr = idandseqs[1];
789         ids = idandseqs[0];
790         usingNames = true;
791       }
792       // and try and make the groupURL!
793
794       Object[] urlset = null;
795       try
796       {
797         urlset = urlLink.makeUrlStubs(ids, seqstr,
798                 "FromJalview" + System.currentTimeMillis(), false);
799       } catch (UrlStringTooLongException e)
800       {
801       }
802       if (urlset != null)
803       {
804         int type = urlLink.getGroupURLType() & 3;
805         // System.out.println(urlLink.getGroupURLType()
806         // +" "+((String[])urlset[3])[0]);
807         // first two bits ofurlLink type bitfield are sequenceids and sequences
808         // TODO: FUTURE: ensure the groupURL menu structure can be generalised
809         addshowLink(linkMenus[type], label
810                 + (((type & 1) == 1) ? ("("
811                         + (usingNames ? "Names" : ltarget) + ")") : ""),
812                 urlLink, urlset);
813         addMenu = true;
814       }
815     }
816     if (addMenu)
817     {
818       groupLinksMenu = new JMenu("Group Links");
819       for (int m = 0; m < linkMenus.length; m++)
820       {
821         if (linkMenus[m] != null
822                 && linkMenus[m].getMenuComponentCount() > 0)
823         {
824           groupLinksMenu.add(linkMenus[m]);
825         }
826       }
827
828       groupMenu.add(groupLinksMenu);
829     }
830   }
831
832   /**
833    * add a show URL menu item to the given linkMenu
834    * 
835    * @param linkMenu
836    * @param label
837    *          - menu label string
838    * @param url
839    *          - url to open
840    */
841   private void addshowLink(JMenu linkMenu, String label, final String url)
842   {
843     JMenuItem item = new JMenuItem(label);
844     item.setToolTipText("open URL: " + url);
845     item.addActionListener(new java.awt.event.ActionListener()
846     {
847       public void actionPerformed(ActionEvent e)
848       {
849         new Thread(new Runnable()
850         {
851
852           public void run()
853           {
854             showLink(url);
855           }
856
857         }).start();
858       }
859     });
860
861     linkMenu.add(item);
862   }
863
864   /**
865    * add a late bound groupURL item to the given linkMenu
866    * 
867    * @param linkMenu
868    * @param label
869    *          - menu label string
870    * @param urlgenerator
871    *          GroupURLLink used to generate URL
872    * @param urlstub
873    *          Object array returned from the makeUrlStubs function.
874    */
875   private void addshowLink(JMenu linkMenu, String label,
876           final GroupUrlLink urlgenerator, final Object[] urlstub)
877   {
878     JMenuItem item = new JMenuItem(label);
879     item.setToolTipText("open URL (" + urlgenerator.getUrl_prefix()
880             + "..) (" + urlgenerator.getNumberInvolved(urlstub) + " seqs)"); // TODO:
881                                                                              // put
882                                                                              // in
883                                                                              // info
884                                                                              // about
885                                                                              // what
886                                                                              // is
887                                                                              // being
888                                                                              // sent.
889     item.addActionListener(new java.awt.event.ActionListener()
890     {
891       public void actionPerformed(ActionEvent e)
892       {
893         new Thread(new Runnable()
894         {
895
896           public void run()
897           {
898             try
899             {
900               showLink(urlgenerator.constructFrom(urlstub));
901             } catch (UrlStringTooLongException e)
902             {
903             }
904           }
905
906         }).start();
907       }
908     });
909
910     linkMenu.add(item);
911   }
912
913   /**
914    * DOCUMENT ME!
915    * 
916    * @throws Exception
917    *           DOCUMENT ME!
918    */
919   private void jbInit() throws Exception
920   {
921     groupMenu.setText("Group");
922     groupMenu.setText("Selection");
923     groupName.setText("Name");
924     groupName.addActionListener(new java.awt.event.ActionListener()
925     {
926       public void actionPerformed(ActionEvent e)
927       {
928         groupName_actionPerformed();
929       }
930     });
931     sequenceMenu.setText("Sequence");
932     sequenceName.setText("Edit Name/Description");
933     sequenceName.addActionListener(new java.awt.event.ActionListener()
934     {
935       public void actionPerformed(ActionEvent e)
936       {
937         sequenceName_actionPerformed();
938       }
939     });
940     sequenceDetails.setText("Sequence Details ...");
941     sequenceDetails.addActionListener(new java.awt.event.ActionListener()
942     {
943       public void actionPerformed(ActionEvent e)
944       {
945         sequenceDetails_actionPerformed();
946       }
947     });
948     sequenceSelDetails.setText("Sequence Details ...");
949     sequenceSelDetails
950             .addActionListener(new java.awt.event.ActionListener()
951             {
952               public void actionPerformed(ActionEvent e)
953               {
954                 sequenceSelectionDetails_actionPerformed();
955               }
956             });
957     PIDColour.setFocusPainted(false);
958     unGroupMenuItem.setText("Remove Group");
959     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
960     {
961       public void actionPerformed(ActionEvent e)
962       {
963         unGroupMenuItem_actionPerformed();
964       }
965     });
966
967     outline.setText("Border colour");
968     outline.addActionListener(new java.awt.event.ActionListener()
969     {
970       public void actionPerformed(ActionEvent e)
971       {
972         outline_actionPerformed();
973       }
974     });
975     nucleotideMenuItem.setText("Nucleotide");
976     nucleotideMenuItem.addActionListener(new ActionListener()
977     {
978       public void actionPerformed(ActionEvent e)
979       {
980         nucleotideMenuItem_actionPerformed();
981       }
982     });
983     colourMenu.setText("Group Colour");
984     showBoxes.setText("Boxes");
985     showBoxes.setState(true);
986     showBoxes.addActionListener(new ActionListener()
987     {
988       public void actionPerformed(ActionEvent e)
989       {
990         showBoxes_actionPerformed();
991       }
992     });
993     showText.setText("Text");
994     showText.setState(true);
995     showText.addActionListener(new ActionListener()
996     {
997       public void actionPerformed(ActionEvent e)
998       {
999         showText_actionPerformed();
1000       }
1001     });
1002     showColourText.setText("Colour Text");
1003     showColourText.addActionListener(new ActionListener()
1004     {
1005       public void actionPerformed(ActionEvent e)
1006       {
1007         showColourText_actionPerformed();
1008       }
1009     });
1010     displayNonconserved.setText("Show Nonconserved");
1011     displayNonconserved.setState(true);
1012     displayNonconserved.addActionListener(new ActionListener()
1013     {
1014       public void actionPerformed(ActionEvent e)
1015       {
1016         showNonconserved_actionPerformed();
1017       }
1018     });
1019     editMenu.setText("Edit");
1020     cut.setText("Cut");
1021     cut.addActionListener(new ActionListener()
1022     {
1023       public void actionPerformed(ActionEvent e)
1024       {
1025         cut_actionPerformed();
1026       }
1027     });
1028     upperCase.setText("To Upper Case");
1029     upperCase.addActionListener(new ActionListener()
1030     {
1031       public void actionPerformed(ActionEvent e)
1032       {
1033         changeCase(e);
1034       }
1035     });
1036     copy.setText("Copy");
1037     copy.addActionListener(new ActionListener()
1038     {
1039       public void actionPerformed(ActionEvent e)
1040       {
1041         copy_actionPerformed();
1042       }
1043     });
1044     lowerCase.setText("To Lower Case");
1045     lowerCase.addActionListener(new ActionListener()
1046     {
1047       public void actionPerformed(ActionEvent e)
1048       {
1049         changeCase(e);
1050       }
1051     });
1052     toggle.setText("Toggle Case");
1053     toggle.addActionListener(new ActionListener()
1054     {
1055       public void actionPerformed(ActionEvent e)
1056       {
1057         changeCase(e);
1058       }
1059     });
1060     pdbMenu.setText("Associate Structure with Sequence");
1061     pdbFromFile.setText("From File");
1062     pdbFromFile.addActionListener(new ActionListener()
1063     {
1064       public void actionPerformed(ActionEvent e)
1065       {
1066         try {
1067                         pdbFromFile_actionPerformed();
1068                 } catch (ExceptionFileFormatOrSyntax e1) {
1069                         // TODO Auto-generated catch block
1070                         e1.printStackTrace();
1071                 } catch (ParserConfigurationException e1) {
1072                         // TODO Auto-generated catch block
1073                         e1.printStackTrace();
1074                 } catch (SAXException e1) {
1075                         // TODO Auto-generated catch block
1076                         e1.printStackTrace();
1077                 } catch (ExceptionPermissionDenied e1) {
1078                         // TODO Auto-generated catch block
1079                         e1.printStackTrace();
1080                 } catch (ExceptionLoadingFailed e1) {
1081                         // TODO Auto-generated catch block
1082                         e1.printStackTrace();
1083                 } catch (InterruptedException e1) {
1084                         // TODO Auto-generated catch block
1085                         e1.printStackTrace();
1086                 } catch (ExceptionUnmatchedClosingParentheses e1) {
1087                         // TODO Auto-generated catch block
1088                         e1.printStackTrace();
1089                 }
1090       }
1091     });
1092     enterPDB.setText("Enter PDB Id");
1093     enterPDB.addActionListener(new ActionListener()
1094     {
1095       public void actionPerformed(ActionEvent e)
1096       {
1097         enterPDB_actionPerformed();
1098       }
1099     });
1100     discoverPDB.setText("Discover PDB ids");
1101     discoverPDB.addActionListener(new ActionListener()
1102     {
1103       public void actionPerformed(ActionEvent e)
1104       {
1105         discoverPDB_actionPerformed();
1106       }
1107     });
1108     outputMenu.setText("Output to Textbox...");
1109     sequenceFeature.setText("Create Sequence Feature");
1110     sequenceFeature.addActionListener(new ActionListener()
1111     {
1112       public void actionPerformed(ActionEvent e)
1113       {
1114         sequenceFeature_actionPerformed();
1115       }
1116     });
1117     textColour.setText("Text Colour");
1118     textColour.addActionListener(new ActionListener()
1119     {
1120       public void actionPerformed(ActionEvent e)
1121       {
1122         textColour_actionPerformed();
1123       }
1124     });
1125     jMenu1.setText("Group");
1126     structureMenu.setText("Structure");
1127     viewStructureMenu.setText("View Structure");
1128     // colStructureMenu.setText("Colour By Structure");
1129     editSequence.setText("Edit Sequence...");
1130     editSequence.addActionListener(new ActionListener()
1131     {
1132       public void actionPerformed(ActionEvent actionEvent)
1133       {
1134         editSequence_actionPerformed(actionEvent);
1135       }
1136     });
1137
1138     /*
1139      * annotationMenuItem.setText("By Annotation");
1140      * annotationMenuItem.addActionListener(new ActionListener() { public void
1141      * actionPerformed(ActionEvent actionEvent) {
1142      * annotationMenuItem_actionPerformed(actionEvent); } });
1143      */
1144     groupMenu.add(sequenceSelDetails);
1145     add(groupMenu);
1146     add(sequenceMenu);
1147     this.add(structureMenu);
1148     groupMenu.add(editMenu);
1149     groupMenu.add(outputMenu);
1150     groupMenu.add(sequenceFeature);
1151     groupMenu.add(jMenu1);
1152     sequenceMenu.add(sequenceName);
1153     sequenceMenu.add(sequenceDetails);
1154     colourMenu.add(textColour);
1155     colourMenu.add(noColourmenuItem);
1156     colourMenu.add(clustalColour);
1157     colourMenu.add(BLOSUM62Colour);
1158     colourMenu.add(PIDColour);
1159     colourMenu.add(zappoColour);
1160     colourMenu.add(taylorColour);
1161     colourMenu.add(hydrophobicityColour);
1162     colourMenu.add(helixColour);
1163     colourMenu.add(strandColour);
1164     colourMenu.add(turnColour);
1165     colourMenu.add(buriedColour);
1166     colourMenu.add(nucleotideMenuItem);
1167     if (ap.getAlignment().isNucleotide()) {
1168       colourMenu.add(RNAInteractionColour);
1169         colourMenu.add(purinePyrimidineColour);
1170     }
1171     // colourMenu.add(covariationColour);
1172     colourMenu.add(userDefinedColour);
1173
1174     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
1175     {
1176       java.util.Enumeration userColours = jalview.gui.UserDefinedColours
1177               .getUserColourSchemes().keys();
1178
1179       while (userColours.hasMoreElements())
1180       {
1181         JMenuItem item = new JMenuItem(userColours.nextElement().toString());
1182         item.addActionListener(new ActionListener()
1183         {
1184           public void actionPerformed(ActionEvent evt)
1185           {
1186             userDefinedColour_actionPerformed(evt);
1187           }
1188         });
1189         colourMenu.add(item);
1190       }
1191     }
1192
1193     colourMenu.addSeparator();
1194     colourMenu.add(abovePIDColour);
1195     colourMenu.add(conservationMenuItem);
1196     // colourMenu.add(annotationMenuItem);
1197     editMenu.add(copy);
1198     editMenu.add(cut);
1199     editMenu.add(editSequence);
1200     editMenu.add(upperCase);
1201     editMenu.add(lowerCase);
1202     editMenu.add(toggle);
1203     pdbMenu.add(pdbFromFile);
1204     pdbMenu.add(enterPDB);
1205     pdbMenu.add(discoverPDB);
1206     jMenu1.add(groupName);
1207     jMenu1.add(unGroupMenuItem);
1208     jMenu1.add(colourMenu);
1209     jMenu1.add(showBoxes);
1210     jMenu1.add(showText);
1211     jMenu1.add(showColourText);
1212     jMenu1.add(outline);
1213     jMenu1.add(displayNonconserved);
1214     structureMenu.add(pdbMenu);
1215     structureMenu.add(viewStructureMenu);
1216     // structureMenu.add(colStructureMenu);
1217     noColourmenuItem.setText("None");
1218     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
1219     {
1220       public void actionPerformed(ActionEvent e)
1221       {
1222         noColourmenuItem_actionPerformed();
1223       }
1224     });
1225
1226     clustalColour.setText("Clustalx colours");
1227     clustalColour.addActionListener(new java.awt.event.ActionListener()
1228     {
1229       public void actionPerformed(ActionEvent e)
1230       {
1231         clustalColour_actionPerformed();
1232       }
1233     });
1234     zappoColour.setText("Zappo");
1235     zappoColour.addActionListener(new java.awt.event.ActionListener()
1236     {
1237       public void actionPerformed(ActionEvent e)
1238       {
1239         zappoColour_actionPerformed();
1240       }
1241     });
1242     taylorColour.setText("Taylor");
1243     taylorColour.addActionListener(new java.awt.event.ActionListener()
1244     {
1245       public void actionPerformed(ActionEvent e)
1246       {
1247         taylorColour_actionPerformed();
1248       }
1249     });
1250     hydrophobicityColour.setText("Hydrophobicity");
1251     hydrophobicityColour
1252             .addActionListener(new java.awt.event.ActionListener()
1253             {
1254               public void actionPerformed(ActionEvent e)
1255               {
1256                 hydrophobicityColour_actionPerformed();
1257               }
1258             });
1259     helixColour.setText("Helix propensity");
1260     helixColour.addActionListener(new java.awt.event.ActionListener()
1261     {
1262       public void actionPerformed(ActionEvent e)
1263       {
1264         helixColour_actionPerformed();
1265       }
1266     });
1267     strandColour.setText("Strand propensity");
1268     strandColour.addActionListener(new java.awt.event.ActionListener()
1269     {
1270       public void actionPerformed(ActionEvent e)
1271       {
1272         strandColour_actionPerformed();
1273       }
1274     });
1275     turnColour.setText("Turn propensity");
1276     turnColour.addActionListener(new java.awt.event.ActionListener()
1277     {
1278       public void actionPerformed(ActionEvent e)
1279       {
1280         turnColour_actionPerformed();
1281       }
1282     });
1283     buriedColour.setText("Buried Index");
1284     buriedColour.addActionListener(new java.awt.event.ActionListener()
1285     {
1286       public void actionPerformed(ActionEvent e)
1287       {
1288         buriedColour_actionPerformed();
1289       }
1290     });
1291     abovePIDColour.setText("Above % Identity");
1292     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
1293     {
1294       public void actionPerformed(ActionEvent e)
1295       {
1296         abovePIDColour_actionPerformed();
1297       }
1298     });
1299     userDefinedColour.setText("User Defined...");
1300     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
1301     {
1302       public void actionPerformed(ActionEvent e)
1303       {
1304         userDefinedColour_actionPerformed(e);
1305       }
1306     });
1307     PIDColour.setText("Percentage Identity");
1308     PIDColour.addActionListener(new java.awt.event.ActionListener()
1309     {
1310       public void actionPerformed(ActionEvent e)
1311       {
1312         PIDColour_actionPerformed();
1313       }
1314     });
1315     BLOSUM62Colour.setText("BLOSUM62");
1316     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
1317     {
1318       public void actionPerformed(ActionEvent e)
1319       {
1320         BLOSUM62Colour_actionPerformed();
1321       }
1322     });
1323     purinePyrimidineColour.setText("Purine/Pyrimidine");
1324     purinePyrimidineColour
1325             .addActionListener(new java.awt.event.ActionListener()
1326             {
1327               public void actionPerformed(ActionEvent e)
1328               {
1329                 purinePyrimidineColour_actionPerformed();
1330               }
1331             });
1332     
1333     RNAInteractionColour.setText("RNA Interaction type");
1334     RNAInteractionColour
1335             .addActionListener(new java.awt.event.ActionListener()
1336             {
1337               public void actionPerformed(ActionEvent e)
1338               {
1339                 RNAInteractionColour_actionPerformed();
1340               }
1341             });
1342     /*
1343      * covariationColour.addActionListener(new java.awt.event.ActionListener() {
1344      * public void actionPerformed(ActionEvent e) {
1345      * covariationColour_actionPerformed(); } });
1346      */
1347
1348     conservationMenuItem.setText("Conservation");
1349     conservationMenuItem
1350             .addActionListener(new java.awt.event.ActionListener()
1351             {
1352               public void actionPerformed(ActionEvent e)
1353               {
1354                 conservationMenuItem_actionPerformed();
1355               }
1356             });
1357   }
1358
1359   protected void sequenceSelectionDetails_actionPerformed()
1360   {
1361     createSequenceDetailsReport(ap.av.getSequenceSelection());
1362   }
1363
1364   protected void sequenceDetails_actionPerformed()
1365   {
1366     createSequenceDetailsReport(new SequenceI[]
1367     { sequence });
1368   }
1369
1370   public void createSequenceDetailsReport(SequenceI[] sequences)
1371   {
1372     CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
1373     StringBuffer contents = new StringBuffer();
1374     for (SequenceI seq : sequences)
1375     {
1376       contents.append("<p><h2>Annotation for " + seq.getDisplayId(true)
1377               + "</h2></p><p>");
1378       new SequenceAnnotationReport(null)
1379               .createSequenceAnnotationReport(
1380                       contents,
1381                       seq,
1382                       true,
1383                       true,
1384                       false,
1385                       (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
1386                               : null);
1387       contents.append("</p>");
1388     }
1389     cap.setText("<html>" + contents.toString() + "</html>");
1390
1391     Desktop.instance.addInternalFrame(cap, "Sequence Details for "
1392             + (sequences.length == 1 ? sequences[0].getDisplayId(true)
1393                     : "Selection"), 500, 400);
1394
1395   }
1396
1397   protected void showNonconserved_actionPerformed()
1398   {
1399     getGroup().setShowNonconserved(displayNonconserved.isSelected());
1400     refresh();
1401   }
1402
1403   /**
1404    * call to refresh view after settings change
1405    */
1406   void refresh()
1407   {
1408     ap.updateAnnotation();
1409     ap.paintAlignment(true);
1410
1411     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
1412   }
1413
1414   /**
1415    * DOCUMENT ME!
1416    * 
1417    * @param e
1418    *          DOCUMENT ME!
1419    */
1420   protected void clustalColour_actionPerformed()
1421   {
1422     SequenceGroup sg = getGroup();
1423     sg.cs = new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences());
1424     refresh();
1425   }
1426
1427   /**
1428    * DOCUMENT ME!
1429    * 
1430    * @param e
1431    *          DOCUMENT ME!
1432    */
1433   protected void zappoColour_actionPerformed()
1434   {
1435     getGroup().cs = new ZappoColourScheme();
1436     refresh();
1437   }
1438
1439   /**
1440    * DOCUMENT ME!
1441    * 
1442    * @param e
1443    *          DOCUMENT ME!
1444    */
1445   protected void taylorColour_actionPerformed()
1446   {
1447     getGroup().cs = new TaylorColourScheme();
1448     refresh();
1449   }
1450
1451   /**
1452    * DOCUMENT ME!
1453    * 
1454    * @param e
1455    *          DOCUMENT ME!
1456    */
1457   protected void hydrophobicityColour_actionPerformed()
1458   {
1459     getGroup().cs = new HydrophobicColourScheme();
1460     refresh();
1461   }
1462
1463   /**
1464    * DOCUMENT ME!
1465    * 
1466    * @param e
1467    *          DOCUMENT ME!
1468    */
1469   protected void helixColour_actionPerformed()
1470   {
1471     getGroup().cs = new HelixColourScheme();
1472     refresh();
1473   }
1474
1475   /**
1476    * DOCUMENT ME!
1477    * 
1478    * @param e
1479    *          DOCUMENT ME!
1480    */
1481   protected void strandColour_actionPerformed()
1482   {
1483     getGroup().cs = new StrandColourScheme();
1484     refresh();
1485   }
1486
1487   /**
1488    * DOCUMENT ME!
1489    * 
1490    * @param e
1491    *          DOCUMENT ME!
1492    */
1493   protected void turnColour_actionPerformed()
1494   {
1495     getGroup().cs = new TurnColourScheme();
1496     refresh();
1497   }
1498
1499   /**
1500    * DOCUMENT ME!
1501    * 
1502    * @param e
1503    *          DOCUMENT ME!
1504    */
1505   protected void buriedColour_actionPerformed()
1506   {
1507     getGroup().cs = new BuriedColourScheme();
1508     refresh();
1509   }
1510
1511   /**
1512    * DOCUMENT ME!
1513    * 
1514    * @param e
1515    *          DOCUMENT ME!
1516    */
1517   public void nucleotideMenuItem_actionPerformed()
1518   {
1519     getGroup().cs = new NucleotideColourScheme();
1520     refresh();
1521   }
1522
1523   protected void purinePyrimidineColour_actionPerformed()
1524   {
1525     getGroup().cs = new PurinePyrimidineColourScheme();
1526     refresh();
1527   }
1528
1529   protected void RNAInteractionColour_actionPerformed()
1530   {
1531     getGroup().cs = new RNAInteractionColourScheme();
1532     refresh();
1533   }
1534   /*
1535    * protected void covariationColour_actionPerformed() { getGroup().cs = new
1536    * CovariationColourScheme(sequence.getAnnotation()[0]); refresh(); }
1537    */
1538   /**
1539    * DOCUMENT ME!
1540    * 
1541    * @param e
1542    *          DOCUMENT ME!
1543    */
1544   protected void abovePIDColour_actionPerformed()
1545   {
1546     SequenceGroup sg = getGroup();
1547     if (sg.cs == null)
1548     {
1549       return;
1550     }
1551
1552     if (abovePIDColour.isSelected())
1553     {
1554       sg.cs.setConsensus(AAFrequency.calculate(
1555               sg.getSequences(ap.av.getHiddenRepSequences()),
1556               sg.getStartRes(), sg.getEndRes() + 1));
1557
1558       int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
1559               .getName());
1560
1561       sg.cs.setThreshold(threshold, ap.av.getIgnoreGapsConsensus());
1562
1563       SliderPanel.showPIDSlider();
1564     }
1565     else
1566     // remove PIDColouring
1567     {
1568       sg.cs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
1569     }
1570
1571     refresh();
1572   }
1573
1574   /**
1575    * DOCUMENT ME!
1576    * 
1577    * @param e
1578    *          DOCUMENT ME!
1579    */
1580   protected void userDefinedColour_actionPerformed(ActionEvent e)
1581   {
1582     SequenceGroup sg = getGroup();
1583
1584     if (e.getActionCommand().equals("User Defined..."))
1585     {
1586       new UserDefinedColours(ap, sg);
1587     }
1588     else
1589     {
1590       UserColourScheme udc = (UserColourScheme) UserDefinedColours
1591               .getUserColourSchemes().get(e.getActionCommand());
1592
1593       sg.cs = udc;
1594     }
1595     refresh();
1596   }
1597
1598   /**
1599    * DOCUMENT ME!
1600    * 
1601    * @param e
1602    *          DOCUMENT ME!
1603    */
1604   protected void PIDColour_actionPerformed()
1605   {
1606     SequenceGroup sg = getGroup();
1607     sg.cs = new PIDColourScheme();
1608     sg.cs.setConsensus(AAFrequency.calculate(
1609             sg.getSequences(ap.av.getHiddenRepSequences()),
1610             sg.getStartRes(), sg.getEndRes() + 1));
1611     refresh();
1612   }
1613
1614   /**
1615    * DOCUMENT ME!
1616    * 
1617    * @param e
1618    *          DOCUMENT ME!
1619    */
1620   protected void BLOSUM62Colour_actionPerformed()
1621   {
1622     SequenceGroup sg = getGroup();
1623
1624     sg.cs = new Blosum62ColourScheme();
1625
1626     sg.cs.setConsensus(AAFrequency.calculate(
1627             sg.getSequences(ap.av.getHiddenRepSequences()),
1628             sg.getStartRes(), sg.getEndRes() + 1));
1629
1630     refresh();
1631   }
1632
1633   /**
1634    * DOCUMENT ME!
1635    * 
1636    * @param e
1637    *          DOCUMENT ME!
1638    */
1639   protected void noColourmenuItem_actionPerformed()
1640   {
1641     getGroup().cs = null;
1642     refresh();
1643   }
1644
1645   /**
1646    * DOCUMENT ME!
1647    * 
1648    * @param e
1649    *          DOCUMENT ME!
1650    */
1651   protected void conservationMenuItem_actionPerformed()
1652   {
1653     SequenceGroup sg = getGroup();
1654     if (sg.cs == null)
1655     {
1656       return;
1657     }
1658
1659     if (conservationMenuItem.isSelected())
1660     {
1661       Conservation c = new Conservation("Group",
1662               ResidueProperties.propHash, 3, sg.getSequences(ap.av
1663                       .getHiddenRepSequences()), sg.getStartRes(),
1664               sg.getEndRes() + 1);
1665
1666       c.calculate();
1667       c.verdict(false, ap.av.getConsPercGaps());
1668
1669       sg.cs.setConservation(c);
1670
1671       SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
1672       SliderPanel.showConservationSlider();
1673     }
1674     else
1675     // remove ConservationColouring
1676     {
1677       sg.cs.setConservation(null);
1678     }
1679
1680     refresh();
1681   }
1682
1683   public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
1684   {
1685     SequenceGroup sg = getGroup();
1686     if (sg == null)
1687     {
1688       return;
1689     }
1690
1691     AnnotationColourGradient acg = new AnnotationColourGradient(
1692             sequence.getAnnotation()[0], null,
1693             AnnotationColourGradient.NO_THRESHOLD);
1694
1695     acg.predefinedColours = true;
1696     sg.cs = acg;
1697
1698     refresh();
1699   }
1700
1701   /**
1702    * DOCUMENT ME!
1703    * 
1704    * @param e
1705    *          DOCUMENT ME!
1706    */
1707   protected void groupName_actionPerformed()
1708   {
1709
1710     SequenceGroup sg = getGroup();
1711     EditNameDialog dialog = new EditNameDialog(sg.getName(),
1712             sg.getDescription(), "       Group Name ",
1713             "Group Description ", "Edit Group Name/Description",
1714             ap.alignFrame);
1715
1716     if (!dialog.accept)
1717     {
1718       return;
1719     }
1720
1721     sg.setName(dialog.getName());
1722     sg.setDescription(dialog.getDescription());
1723     refresh();
1724   }
1725
1726   /**
1727    * Get selection group - adding it to the alignment if necessary.
1728    * 
1729    * @return sequence group to operate on
1730    */
1731   SequenceGroup getGroup()
1732   {
1733     SequenceGroup sg = ap.av.getSelectionGroup();
1734     // this method won't add a new group if it already exists
1735     if (sg != null)
1736     {
1737       ap.av.getAlignment().addGroup(sg);
1738     }
1739
1740     return sg;
1741   }
1742
1743   /**
1744    * DOCUMENT ME!
1745    * 
1746    * @param e
1747    *          DOCUMENT ME!
1748    */
1749   void sequenceName_actionPerformed()
1750   {
1751     EditNameDialog dialog = new EditNameDialog(sequence.getName(),
1752             sequence.getDescription(), "       Sequence Name ",
1753             "Sequence Description ", "Edit Sequence Name/Description",
1754             ap.alignFrame);
1755
1756     if (!dialog.accept)
1757     {
1758       return;
1759     }
1760
1761     if (dialog.getName() != null)
1762     {
1763       if (dialog.getName().indexOf(" ") > -1)
1764       {
1765         JOptionPane.showMessageDialog(ap,
1766                 "Spaces have been converted to \"_\"",
1767                 "No spaces allowed in Sequence Name",
1768                 JOptionPane.WARNING_MESSAGE);
1769       }
1770
1771       sequence.setName(dialog.getName().replace(' ', '_'));
1772       ap.paintAlignment(false);
1773     }
1774
1775     sequence.setDescription(dialog.getDescription());
1776
1777     ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1778             .getSequences());
1779
1780   }
1781
1782   /**
1783    * DOCUMENT ME!
1784    * 
1785    * @param e
1786    *          DOCUMENT ME!
1787    */
1788   void unGroupMenuItem_actionPerformed()
1789   {
1790     SequenceGroup sg = ap.av.getSelectionGroup();
1791     ap.av.getAlignment().deleteGroup(sg);
1792     ap.av.setSelectionGroup(null);
1793     refresh();
1794   }
1795
1796   /**
1797    * DOCUMENT ME!
1798    * 
1799    * @param e
1800    *          DOCUMENT ME!
1801    */
1802   protected void outline_actionPerformed()
1803   {
1804     SequenceGroup sg = getGroup();
1805     Color col = JColorChooser.showDialog(this, "Select Outline Colour",
1806             Color.BLUE);
1807
1808     if (col != null)
1809     {
1810       sg.setOutlineColour(col);
1811     }
1812
1813     refresh();
1814   }
1815
1816   /**
1817    * DOCUMENT ME!
1818    * 
1819    * @param e
1820    *          DOCUMENT ME!
1821    */
1822   public void showBoxes_actionPerformed()
1823   {
1824     getGroup().setDisplayBoxes(showBoxes.isSelected());
1825     refresh();
1826   }
1827
1828   /**
1829    * DOCUMENT ME!
1830    * 
1831    * @param e
1832    *          DOCUMENT ME!
1833    */
1834   public void showText_actionPerformed()
1835   {
1836     getGroup().setDisplayText(showText.isSelected());
1837     refresh();
1838   }
1839
1840   /**
1841    * DOCUMENT ME!
1842    * 
1843    * @param e
1844    *          DOCUMENT ME!
1845    */
1846   public void showColourText_actionPerformed()
1847   {
1848     getGroup().setColourText(showColourText.isSelected());
1849     refresh();
1850   }
1851
1852   public void showLink(String url)
1853   {
1854     try
1855     {
1856       jalview.util.BrowserLauncher.openURL(url);
1857     } catch (Exception ex)
1858     {
1859       JOptionPane
1860               .showInternalMessageDialog(
1861                       Desktop.desktop,
1862                       "Unixers: Couldn't find default web browser."
1863                               + "\nAdd the full path to your browser in Preferences.",
1864                       "Web browser not found", JOptionPane.WARNING_MESSAGE);
1865
1866       ex.printStackTrace();
1867     }
1868   }
1869
1870   void hideSequences(boolean representGroup)
1871   {
1872     SequenceGroup sg = ap.av.getSelectionGroup();
1873     if (sg == null || sg.getSize() < 1)
1874     {
1875       ap.av.hideSequence(new SequenceI[]
1876       { sequence });
1877       return;
1878     }
1879
1880     ap.av.setSelectionGroup(null);
1881
1882     if (representGroup)
1883     {
1884       ap.av.hideRepSequences(sequence, sg);
1885
1886       return;
1887     }
1888
1889     int gsize = sg.getSize();
1890     SequenceI[] hseqs;
1891
1892     hseqs = new SequenceI[gsize];
1893
1894     int index = 0;
1895     for (int i = 0; i < gsize; i++)
1896     {
1897       hseqs[index++] = sg.getSequenceAt(i);
1898     }
1899
1900     ap.av.hideSequence(hseqs);
1901     // refresh(); TODO: ? needed ?
1902     ap.av.sendSelection();
1903   }
1904
1905   public void copy_actionPerformed()
1906   {
1907     ap.alignFrame.copy_actionPerformed(null);
1908   }
1909
1910   public void cut_actionPerformed()
1911   {
1912     ap.alignFrame.cut_actionPerformed(null);
1913   }
1914
1915   void changeCase(ActionEvent e)
1916   {
1917     Object source = e.getSource();
1918     SequenceGroup sg = ap.av.getSelectionGroup();
1919
1920     if (sg != null)
1921     {
1922       int[][] startEnd = ap.av.getVisibleRegionBoundaries(sg.getStartRes(),
1923               sg.getEndRes() + 1);
1924
1925       String description;
1926       int caseChange;
1927
1928       if (source == toggle)
1929       {
1930         description = "Toggle Case";
1931         caseChange = ChangeCaseCommand.TOGGLE_CASE;
1932       }
1933       else if (source == upperCase)
1934       {
1935         description = "To Upper Case";
1936         caseChange = ChangeCaseCommand.TO_UPPER;
1937       }
1938       else
1939       {
1940         description = "To Lower Case";
1941         caseChange = ChangeCaseCommand.TO_LOWER;
1942       }
1943
1944       ChangeCaseCommand caseCommand = new ChangeCaseCommand(description,
1945               sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
1946               startEnd, caseChange);
1947
1948       ap.alignFrame.addHistoryItem(caseCommand);
1949
1950       ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
1951               .getSequences());
1952
1953     }
1954   }
1955
1956   public void outputText_actionPerformed(ActionEvent e)
1957   {
1958     CutAndPasteTransfer cap = new CutAndPasteTransfer();
1959     cap.setForInput(null);
1960     Desktop.addInternalFrame(cap,
1961             "Alignment output - " + e.getActionCommand(), 600, 500);
1962
1963     String[] omitHidden = null;
1964
1965     System.out.println("PROMPT USER HERE"); // TODO: decide if a prompt happens
1966     // or we simply trust the user wants
1967     // wysiwig behaviour
1968     SequenceGroup sg = ap.av.getSelectionGroup();
1969     ColumnSelection csel = new ColumnSelection(ap.av.getColumnSelection());
1970     omitHidden = ap.av.getViewAsString(true);
1971     Alignment oal = new Alignment(ap.av.getSequenceSelection());
1972     AlignmentAnnotation[] nala = ap.av.getAlignment()
1973             .getAlignmentAnnotation();
1974     if (nala != null)
1975     {
1976       for (int i = 0; i < nala.length; i++)
1977       {
1978         AlignmentAnnotation na = nala[i];
1979         oal.addAnnotation(na);
1980       }
1981     }
1982     cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
1983             oal, omitHidden, csel, sg));
1984     oal = null;
1985   }
1986
1987   public void pdbFromFile_actionPerformed() throws IOException
1988   {
1989     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
1990             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
1991     chooser.setFileView(new jalview.io.JalviewFileView());
1992     chooser.setDialogTitle("Select a PDB file for "
1993             + sequence.getDisplayId(false));
1994     chooser.setToolTipText("Load a PDB file and associate it with sequence '"
1995             + sequence.getDisplayId(false) + "'");
1996
1997     int value = chooser.showOpenDialog(null);
1998
1999     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
2000     {
2001       String choice = chooser.getSelectedFile().getPath();
2002       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
2003       new AssociatePdbFileWithSeq().associatePdbWithSeq(choice,
2004               jalview.io.AppletFormatAdapter.FILE, sequence, true);
2005     }
2006
2007   }
2008
2009   public void enterPDB_actionPerformed()
2010   {
2011     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
2012             "Enter PDB Id", "Enter PDB Id", JOptionPane.QUESTION_MESSAGE);
2013
2014     if (id != null && id.length() > 0)
2015     {
2016       PDBEntry entry = new PDBEntry();
2017       entry.setId(id.toUpperCase());
2018       sequence.getDatasetSequence().addPDBId(entry);
2019     }
2020   }
2021
2022   public void discoverPDB_actionPerformed()
2023   {
2024
2025     final SequenceI[] sequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
2026     { sequence }
2027             : ap.av.getSequenceSelection());
2028     Thread discpdb = new Thread(new Runnable()
2029     {
2030       public void run()
2031       {
2032
2033         new jalview.ws.DBRefFetcher(sequences, ap.alignFrame)
2034                 .fetchDBRefs(false);
2035       }
2036
2037     });
2038     discpdb.start();
2039   }
2040
2041   public void sequenceFeature_actionPerformed()
2042   {
2043     SequenceGroup sg = ap.av.getSelectionGroup();
2044     if (sg == null)
2045     {
2046       return;
2047     }
2048
2049     int rsize = 0, gSize = sg.getSize();
2050     SequenceI[] rseqs, seqs = new SequenceI[gSize];
2051     SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
2052
2053     for (int i = 0; i < gSize; i++)
2054     {
2055       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
2056       int end = sg.findEndRes(sg.getSequenceAt(i));
2057       if (start <= end)
2058       {
2059         seqs[rsize] = sg.getSequenceAt(i).getDatasetSequence();
2060         features[rsize] = new SequenceFeature(null, null, null, start, end,
2061                 "Jalview");
2062         rsize++;
2063       }
2064     }
2065     rseqs = new SequenceI[rsize];
2066     tfeatures = new SequenceFeature[rsize];
2067     System.arraycopy(seqs, 0, rseqs, 0, rsize);
2068     System.arraycopy(features, 0, tfeatures, 0, rsize);
2069     features = tfeatures;
2070     seqs = rseqs;
2071     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
2072             features, true, ap))
2073     {
2074       ap.alignFrame.setShowSeqFeatures(true);
2075       ap.highlightSearchResults(null);
2076     }
2077   }
2078
2079   public void textColour_actionPerformed()
2080   {
2081     SequenceGroup sg = getGroup();
2082     if (sg != null)
2083     {
2084       new TextColourChooser().chooseColour(ap, sg);
2085     }
2086   }
2087
2088   public void colourByStructure(String pdbid)
2089   {
2090     Annotation[] anots = ap.av.getStructureSelectionManager()
2091             .colourSequenceFromStructure(sequence, pdbid);
2092
2093     AlignmentAnnotation an = new AlignmentAnnotation("Structure",
2094             "Coloured by " + pdbid, anots);
2095
2096     ap.av.getAlignment().addAnnotation(an);
2097     an.createSequenceMapping(sequence, 0, true);
2098     // an.adjustForAlignment();
2099     ap.av.getAlignment().setAnnotationIndex(an, 0);
2100
2101     ap.adjustAnnotationHeight();
2102
2103     sequence.addAlignmentAnnotation(an);
2104
2105   }
2106
2107   public void editSequence_actionPerformed(ActionEvent actionEvent)
2108   {
2109     SequenceGroup sg = ap.av.getSelectionGroup();
2110
2111     if (sg != null)
2112     {
2113       if (sequence == null)
2114         sequence = (Sequence) sg.getSequenceAt(0);
2115
2116       EditNameDialog dialog = new EditNameDialog(
2117               sequence.getSequenceAsString(sg.getStartRes(),
2118                       sg.getEndRes() + 1), null, "Edit Sequence ", null,
2119               "Edit Sequence", ap.alignFrame);
2120
2121       if (dialog.accept)
2122       {
2123         EditCommand editCommand = new EditCommand("Edit Sequences",
2124                 EditCommand.REPLACE, dialog.getName().replace(' ',
2125                         ap.av.getGapCharacter()),
2126                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
2127                 sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());
2128
2129         ap.alignFrame.addHistoryItem(editCommand);
2130
2131         ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
2132                 .getSequences());
2133       }
2134     }
2135   }
2136
2137 }