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