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