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