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