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