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