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