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