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